From 7a459b8df79bff067b1f89fae0b28105ba578b28 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 29 Dec 2025 11:41:34 +0000 Subject: [PATCH] xen: Split muldiv64() out of lib.h muldiv64() has 7 users across all architectures, and is limited to time handling functions. Therefore, move it's declaration out of lib.h into a dedicated header. Rename the library function to generic_muldiv64(), as x86 is going to provide an arch_muldiv64() in a subsequent change. Explain what the function does, including the limitations; x86's version will suffer a divide error rather than truncate the result to 64 bits. Annotate it with attr_const, not that this allows the optimiser to improve any of Xen's current users. Add one selftest to check the internal precision, putting it in bitops.c for want of any better place to put it. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich Acked-by: Michal Orzel --- xen/arch/arm/time.c | 2 +- xen/arch/riscv/include/asm/time.h | 4 ++-- xen/arch/x86/emul-i8254.c | 2 +- xen/arch/x86/time.c | 2 +- xen/common/bitops.c | 12 ++++++++++++ xen/include/xen/lib.h | 2 -- xen/include/xen/muldiv64.h | 18 ++++++++++++++++++ xen/lib/muldiv64.c | 5 ++--- 8 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 xen/include/xen/muldiv64.h diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 03dc5b51a8..cc3fcf47b6 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -16,8 +16,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/xen/arch/riscv/include/asm/time.h b/xen/arch/riscv/include/asm/time.h index 63bdd471cc..1e7801e2ea 100644 --- a/xen/arch/riscv/include/asm/time.h +++ b/xen/arch/riscv/include/asm/time.h @@ -3,8 +3,8 @@ #define ASM__RISCV__TIME_H #include -#include -#include +#include + #include /* Clock cycles count at Xen startup */ diff --git a/xen/arch/x86/emul-i8254.c b/xen/arch/x86/emul-i8254.c index c16ed0bead..ceb0ef721e 100644 --- a/xen/arch/x86/emul-i8254.c +++ b/xen/arch/x86/emul-i8254.c @@ -25,8 +25,8 @@ */ #include -#include #include +#include #include #include #include diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 1aeb144c83..36d990f7f4 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/common/bitops.c b/xen/common/bitops.c index 14e6265037..e46ea1d3ec 100644 --- a/xen/common/bitops.c +++ b/xen/common/bitops.c @@ -247,3 +247,15 @@ static void __init __constructor test_bitops(void) test_multiple_bits_set(); test_hweight(); } + +#include + +/* Not a bitop, but here in lieu of any any better location */ +static void __init __constructor test_muldiv64(void) +{ + uint64_t res = muldiv64(0xffffffffffffffffULL, + HIDE(0xffffffffU), + HIDE(0xffffffffU)); + if ( res != 0xffffffffffffffffULL ) + panic("muldiv64(), expecting -1ULL, got %#"PRIx64"\n", res); +} diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 559e87636c..bb0fd446b4 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -136,8 +136,6 @@ unsigned long long simple_strtoull( unsigned long long parse_size_and_unit(const char *s, const char **ps); -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c); - /* * A slightly more typesafe variant of cmpxchg() when the entities dealt with * are pointers. diff --git a/xen/include/xen/muldiv64.h b/xen/include/xen/muldiv64.h new file mode 100644 index 0000000000..6141f5c401 --- /dev/null +++ b/xen/include/xen/muldiv64.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef XEN_MULDIV64_H +#define XEN_MULDIV64_H + +#include + +uint64_t attr_const generic_muldiv64(uint64_t a, uint32_t b, uint32_t c); + +/* + * Calculate a * b / c using at least 96-bit internal precision. The + * behaviour is undefined if the end result does not fit in a uint64_t. + */ +static inline uint64_t attr_const muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ + return generic_muldiv64(a, b, c); +} + +#endif /* XEN_MULDIV64_H */ diff --git a/xen/lib/muldiv64.c b/xen/lib/muldiv64.c index f281578c09..545a9bad19 100644 --- a/xen/lib/muldiv64.c +++ b/xen/lib/muldiv64.c @@ -1,7 +1,6 @@ -#include +#include -/* Compute with 96 bit intermediate result: (a*b)/c */ -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) +uint64_t generic_muldiv64(uint64_t a, uint32_t b, uint32_t c) { #ifdef CONFIG_X86 asm ( "mulq %1; divq %2" : "+a" (a)