From 6b8b0136ab3018e4b552b485f808bf66bcf19ead Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 8 Jun 2020 16:55:11 +0000 Subject: softfloat: merge floatx80_mod and floatx80_rem The m68k-specific softfloat code includes a function floatx80_mod that is extremely similar to floatx80_rem, but computing the remainder based on truncating the quotient toward zero rather than rounding it to nearest integer. This is also useful for emulating the x87 fprem and fprem1 instructions. Change the floatx80_rem implementation into floatx80_modrem that can perform either operation, with both floatx80_rem and floatx80_mod as thin wrappers available for all targets. There does not appear to be any use for the _mod operation for other floating-point formats in QEMU (the only other architectures using _rem at all are linux-user/arm/nwfpe, for FPA emulation, and openrisc, for instructions that have been removed in the latest version of the architecture), so no change is made to the code for other formats. Signed-off-by: Joseph Myers Reviewed-by: Richard Henderson Message-Id: Signed-off-by: Paolo Bonzini --- include/fpu/softfloat.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 16ca697a73..bff6934d09 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -687,6 +687,8 @@ floatx80 floatx80_add(floatx80, floatx80, float_status *status); floatx80 floatx80_sub(floatx80, floatx80, float_status *status); floatx80 floatx80_mul(floatx80, floatx80, float_status *status); floatx80 floatx80_div(floatx80, floatx80, float_status *status); +floatx80 floatx80_modrem(floatx80, floatx80, bool, float_status *status); +floatx80 floatx80_mod(floatx80, floatx80, float_status *status); floatx80 floatx80_rem(floatx80, floatx80, float_status *status); floatx80 floatx80_sqrt(floatx80, float_status *status); FloatRelation floatx80_compare(floatx80, floatx80, float_status *status); -- cgit v1.2.3-55-g7522 From 445810ec915687d37b8ae0ef8d7340ab4a153efa Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 8 Jun 2020 16:57:16 +0000 Subject: softfloat: return low bits of quotient from floatx80_modrem Both x87 and m68k need the low parts of the quotient for their remainder operations. Arrange for floatx80_modrem to track those bits and return them via a pointer. The architectures using float32_rem and float64_rem do not appear to need this information, so the *_rem interface is left unchanged and the information returned only from floatx80_modrem. The logic used to determine the low 7 bits of the quotient for m68k (target/m68k/fpu_helper.c:make_quotient) appears completely bogus (it looks at the result of converting the remainder to integer, the quotient having been discarded by that point); this patch does not change that, but the m68k maintainers may wish to do so. Signed-off-by: Joseph Myers Reviewed-by: Richard Henderson Message-Id: Signed-off-by: Paolo Bonzini --- fpu/softfloat.c | 23 ++++++++++++++++++----- include/fpu/softfloat.h | 3 ++- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 1ee3342715..79be4f5840 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -5699,10 +5699,11 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status) | `a' with respect to the corresponding value `b'. The operation is performed | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, | if 'mod' is false; if 'mod' is true, return the remainder based on truncating -| the quotient toward zero instead. +| the quotient toward zero instead. '*quotient' is set to the low 64 bits of +| the absolute value of the integer quotient. *----------------------------------------------------------------------------*/ -floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, +floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, uint64_t *quotient, float_status *status) { bool aSign, zSign; @@ -5710,6 +5711,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, uint64_t aSig0, aSig1, bSig; uint64_t q, term0, term1, alternateASig0, alternateASig1; + *quotient = 0; if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { float_raise(float_flag_invalid, status); return floatx80_default_nan(status); @@ -5768,7 +5770,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); expDiff = 0; } - q = ( bSig <= aSig0 ); + *quotient = q = ( bSig <= aSig0 ); if ( q ) aSig0 -= bSig; expDiff -= 64; while ( 0 < expDiff ) { @@ -5778,6 +5780,8 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); expDiff -= 62; + *quotient <<= 62; + *quotient += q; } expDiff += 64; if ( 0 < expDiff ) { @@ -5791,6 +5795,12 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, ++q; sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); } + if (expDiff < 64) { + *quotient <<= expDiff; + } else { + *quotient = 0; + } + *quotient += q; } else { term1 = 0; @@ -5805,6 +5815,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, aSig0 = alternateASig0; aSig1 = alternateASig1; zSign = ! zSign; + ++*quotient; } } return @@ -5821,7 +5832,8 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) { - return floatx80_modrem(a, b, false, status); + uint64_t quotient; + return floatx80_modrem(a, b, false, "ient, status); } /*---------------------------------------------------------------------------- @@ -5832,7 +5844,8 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) { - return floatx80_modrem(a, b, true, status); + uint64_t quotient; + return floatx80_modrem(a, b, true, "ient, status); } /*---------------------------------------------------------------------------- diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index bff6934d09..ff4e2605b1 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -687,7 +687,8 @@ floatx80 floatx80_add(floatx80, floatx80, float_status *status); floatx80 floatx80_sub(floatx80, floatx80, float_status *status); floatx80 floatx80_mul(floatx80, floatx80, float_status *status); floatx80 floatx80_div(floatx80, floatx80, float_status *status); -floatx80 floatx80_modrem(floatx80, floatx80, bool, float_status *status); +floatx80 floatx80_modrem(floatx80, floatx80, bool, uint64_t *, + float_status *status); floatx80 floatx80_mod(floatx80, floatx80, float_status *status); floatx80 floatx80_rem(floatx80, floatx80, float_status *status); floatx80 floatx80_sqrt(floatx80, float_status *status); -- cgit v1.2.3-55-g7522 From f9919116b8c226428df28bc69ab33480eaa1ee6d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 25 Jun 2020 11:26:02 -0500 Subject: osdep: Make MIN/MAX evaluate arguments only once I'm not aware of any immediate bugs in qemu where a second runtime evaluation of the arguments to MIN() or MAX() causes a problem, but proactively preventing such abuse is easier than falling prey to an unintended case down the road. At any rate, here's the conversation that sparked the current patch: https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg05718.html Update the MIN/MAX macros to only evaluate their argument once at runtime; this uses typeof(1 ? (a) : (b)) to ensure that we are promoting the temporaries to the same type as the final comparison (we have to trigger type promotion, as typeof(bitfield) won't compile; and we can't use typeof((a) + (b)) or even typeof((a) + 0), as some of our uses of MAX are on void* pointers where such addition is undefined). However, we are unable to work around gcc refusing to compile ({}) in a constant context (such as the array length of a static variable), even when only used in the dead branch of a __builtin_choose_expr(), so we have to provide a second macro pair MIN_CONST and MAX_CONST for use when both arguments are known to be compile-time constants and where the result must also be usable as a constant; this second form evaluates arguments multiple times but that doesn't matter for constants. By using a void expression as the expansion if a non-constant is presented to this second form, we can enlist the compiler to ensure the double evaluation is not attempted on non-constants. Alas, as both macros now rely on compiler intrinsics, they are no longer usable in preprocessor #if conditions; those will just have to be open-coded or the logic rewritten into #define or runtime 'if' conditions (but where the compiler dead-code-elimination will probably still apply). I tested that both gcc 10.1.1 and clang 10.0.0 produce errors for all forms of macro mis-use. As the errors can sometimes be cryptic, I'm demonstrating the gcc output: Use of MIN when MIN_CONST is needed: In file included from /home/eblake/qemu/qemu-img.c:25: /home/eblake/qemu/include/qemu/osdep.h:249:5: error: braced-group within expression allowed only inside a function 249 | ({ \ | ^ /home/eblake/qemu/qemu-img.c:92:12: note: in expansion of macro ‘MIN’ 92 | char array[MIN(1, 2)] = ""; | ^~~ Use of MIN_CONST when MIN is needed: /home/eblake/qemu/qemu-img.c: In function ‘is_allocated_sectors’: /home/eblake/qemu/qemu-img.c:1225:15: error: void value not ignored as it ought to be 1225 | i = MIN_CONST(i, n); | ^ Use of MIN in the preprocessor: In file included from /home/eblake/qemu/accel/tcg/translate-all.c:20: /home/eblake/qemu/accel/tcg/translate-all.c: In function ‘page_check_range’: /home/eblake/qemu/include/qemu/osdep.h:249:6: error: token "{" is not valid in preprocessor expressions 249 | ({ \ | ^ Fix the resulting callsites that used #if or computed a compile-time constant min or max to use the new macros. cpu-defs.h is interesting, as CPU_TLB_DYN_MAX_BITS is sometimes used as a constant and sometimes dynamic. It may be worth improving glib's MIN/MAX definitions to be saner, but that is a task for another day. Signed-off-by: Eric Blake Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20200625162602.700741-1-eblake@redhat.com> Signed-off-by: Paolo Bonzini --- accel/tcg/translate-all.c | 6 ++--- hw/usb/hcd-xhci.h | 2 +- include/block/block.h | 4 ++-- include/exec/cpu-all.h | 8 +++---- include/exec/cpu-defs.h | 7 +++++- include/qemu/osdep.h | 57 ++++++++++++++++++++++++++++++++++++++--------- migration/qemu-file.c | 2 +- 7 files changed, 63 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index c3d37058a1..2afa46bd2b 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2582,9 +2582,9 @@ int page_check_range(target_ulong start, target_ulong len, int flags) /* This function should never be called with addresses outside the guest address space. If this assert fires, it probably indicates a missing call to h2g_valid. */ -#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS - assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); -#endif + if (TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS) { + assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); + } if (len == 0) { return 0; diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index 2fad4df2a7..946af51fc2 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -214,7 +214,7 @@ struct XHCIState { uint32_t dcbaap_high; uint32_t config; - USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; + USBPort uports[MAX_CONST(MAXPORTS_2, MAXPORTS_3)]; XHCIPort ports[MAXPORTS]; XHCISlot slots[MAXSLOTS]; uint32_t numports; diff --git a/include/block/block.h b/include/block/block.h index 25e299605e..e8fc814996 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -133,8 +133,8 @@ typedef struct HDGeometry { #define BDRV_SECTOR_BITS 9 #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) -#define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \ - INT_MAX >> BDRV_SECTOR_BITS) +#define BDRV_REQUEST_MAX_SECTORS MIN_CONST(SIZE_MAX >> BDRV_SECTOR_BITS, \ + INT_MAX >> BDRV_SECTOR_BITS) #define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS) /* diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index fb4e8a8e29..fc403d456b 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -176,11 +176,9 @@ extern unsigned long reserved_va; * avoid setting bits at the top of guest addresses that might need * to be used for tags. */ -#if MIN(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32 -# define GUEST_ADDR_MAX_ UINT32_MAX -#else -# define GUEST_ADDR_MAX_ (~0ul) -#endif +#define GUEST_ADDR_MAX_ \ + ((MIN_CONST(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32) ? \ + UINT32_MAX : ~0ul) #define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : GUEST_ADDR_MAX_) #else diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 8c44abefa2..9185632337 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -102,8 +102,13 @@ typedef uint64_t target_ulong; * Skylake's Level-2 STLB has 16 1G entries. * Also, make sure we do not size the TLB past the guest's address space. */ -# define CPU_TLB_DYN_MAX_BITS \ +# ifdef TARGET_PAGE_BITS_VARY +# define CPU_TLB_DYN_MAX_BITS \ MIN(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS) +# else +# define CPU_TLB_DYN_MAX_BITS \ + MIN_CONST(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS) +# endif # endif typedef struct CPUTLBEntry { diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index ff7c17b857..0d26a1b9bd 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -236,18 +236,55 @@ extern int daemon(int, int); #define SIZE_MAX ((size_t)-1) #endif -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif +/* + * Two variations of MIN/MAX macros. The first is for runtime use, and + * evaluates arguments only once (so it is safe even with side + * effects), but will not work in constant contexts (such as array + * size declarations) because of the '{}'. The second is for constant + * expression use, where evaluating arguments twice is safe because + * the result is going to be constant anyway, but will not work in a + * runtime context because of a void expression where a value is + * expected. Thus, both gcc and clang will fail to compile if you use + * the wrong macro (even if the error may seem a bit cryptic). + * + * Note that neither form is usable as an #if condition; if you truly + * need to write conditional code that depends on a minimum or maximum + * determined by the pre-processor instead of the compiler, you'll + * have to open-code it. + */ +#undef MIN +#define MIN(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a < _b ? _a : _b; \ + }) +#define MIN_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) < (b) ? (a) : (b), \ + ((void)0)) +#undef MAX +#define MAX(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a > _b ? _a : _b; \ + }) +#define MAX_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) > (b) ? (a) : (b), \ + ((void)0)) -/* Minimum function that returns zero only iff both values are zero. - * Intended for use with unsigned values only. */ +/* + * Minimum function that returns zero only if both values are zero. + * Intended for use with unsigned values only. + */ #ifndef MIN_NON_ZERO -#define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \ - ((b) == 0 ? (a) : (MIN(a, b)))) +#define MIN_NON_ZERO(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \ + }) #endif /* Round number down to multiple */ diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 1c3a358a14..be21518c57 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -31,7 +31,7 @@ #include "qapi/error.h" #define IO_BUF_SIZE 32768 -#define MAX_IOV_SIZE MIN(IOV_MAX, 64) +#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64) struct QEMUFile { const QEMUFileOps *ops; -- cgit v1.2.3-55-g7522 From 8f06f22f38246ea7a6b0b20013fd9a7a87e23569 Mon Sep 17 00:00:00 2001 From: Jon Doron Date: Wed, 17 Jun 2020 19:09:02 +0300 Subject: hyperv: vmbus: Remove the 2nd IRQ It seems like Windows does not really require 2 IRQs to have a functioning VMBus. Signed-off-by: Jon Doron Message-Id: <20200617160904.681845-2-arilou@gmail.com> Signed-off-by: Paolo Bonzini --- hw/hyperv/vmbus.c | 3 +-- hw/i386/acpi-build.c | 4 +--- include/hw/hyperv/vmbus-bridge.h | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index f371240176..a8bcb41026 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2741,8 +2741,7 @@ static const VMStateDescription vmstate_vmbus_bridge = { }; static Property vmbus_bridge_props[] = { - DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), - DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), + DEFINE_PROP_UINT8("irq", VMBusBridge, irq, 7), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 378515df66..b7bcbbbb2a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -967,9 +967,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); crs = aml_resource_template(); - aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); - /* FIXME: newer HyperV gets by with only one IRQ */ - aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); + aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index c0a06d832c..33f93de64d 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,8 +19,7 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; - uint8_t irq0; - uint8_t irq1; + uint8_t irq; VMBus *bus; } VMBusBridge; -- cgit v1.2.3-55-g7522