All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] math.h: Account for 64-bit division on i386
@ 2025-04-19 11:51 cem
  2025-04-19 18:28 ` kernel test robot
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: cem @ 2025-04-19 11:51 UTC (permalink / raw)
  To: linux-kernel
  Cc: Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

From: Carlos Maiolino <cem@kernel.org>

Building linux on i386 might fail if a 64bit type is passed to
mult_fract(). To prevent the failure, use do_div() for the division
calculation instead of hardcoding a / b.

Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
---

I'm sending it as a RFC because I didn't to extensive testing on this
patch, also I'm not sure if mult_frac() was intended to work on 32-bit
only types. If that's the case, perhaps, a new mult_frac64() might be a
better idea?!

 include/linux/math.h | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/include/linux/math.h b/include/linux/math.h
index 0198c92cbe3e..05ea853b75b4 100644
--- a/include/linux/math.h
+++ b/include/linux/math.h
@@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
 #undef __STRUCT_FRACT
 
 /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
-#define mult_frac(x, n, d)	\
-({				\
-	typeof(x) x_ = (x);	\
-	typeof(n) n_ = (n);	\
-	typeof(d) d_ = (d);	\
-				\
-	typeof(x_) q = x_ / d_;	\
-	typeof(x_) r = x_ % d_;	\
-	q * n_ + r * n_ / d_;	\
+#define mult_frac(x, n, d)		\
+({					\
+	typeof(x) x_ = (x);		\
+	typeof(n) n_ = (n);		\
+	typeof(d) d_ = (d);		\
+					\
+	typeof(x_) r = do_div(x_, d_);	\
+	r *= n_;			\
+	do_div(r, d_);			\
+	x_ * n_ + r;			\
 })
 
 #define sector_div(a, b) do_div(a, b)
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-19 11:51 [RFC PATCH] math.h: Account for 64-bit division on i386 cem
@ 2025-04-19 18:28 ` kernel test robot
  2025-04-19 18:59 ` kernel test robot
  2025-04-20 15:40 ` Guenter Roeck
  2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-04-19 18:28 UTC (permalink / raw)
  To: cem; +Cc: oe-kbuild-all

Hi,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on hch-configfs/for-next v6.15-rc2 next-20250417]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/cem-kernel-org/math-h-Account-for-64-bit-division-on-i386/20250419-195242
base:   linus/master
patch link:    https://lore.kernel.org/r/20250419115157.567249-1-cem%40kernel.org
patch subject: [RFC PATCH] math.h: Account for 64-bit division on i386
config: csky-randconfig-002-20250420 (https://download.01.org/0day-ci/archive/20250420/202504200218.98vwdj3m-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250420/202504200218.98vwdj3m-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504200218.98vwdj3m-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   In file included from ./arch/csky/include/generated/asm/div64.h:1,
                    from include/linux/math.h:6,
                    from include/linux/math64.h:6,
                    from include/linux/time.h:6,
                    from include/linux/stat.h:19,
                    from include/linux/module.h:13,
                    from drivers/power/supply/ltc4162-l-charger.c:12:
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4162l_get_ibat':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
   In file included from include/linux/build_bug.h:5,
                    from include/linux/bitfield.h:10,
                    from drivers/power/supply/ltc4162-l-charger.c:11:
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:360:23: note: in expansion of macro 'mult_frac'
     360 |         val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb);
         |                       ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4162l_get_icharge':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:417:32: note: in expansion of macro 'mult_frac'
     417 |         val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
         |                                ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4162l_set_icharge':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:426:17: note: in expansion of macro 'mult_frac'
     426 |         value = mult_frac(value, info->rsnsb, 100000u);
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4015_get_vcharge':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:528:37: note: in expansion of macro 'mult_frac'
     528 |                 voltage = 2000000 + mult_frac(regval, 1000000, 105);
         |                                     ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4162l_set_iin_limit':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:655:18: note: in expansion of macro 'mult_frac'
     655 |         regval = mult_frac(value, info->rsnsi, 50000u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/power/supply/ltc4162-l-charger.c: In function 'ltc4162l_set_term_current':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types]
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Wincompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/power/supply/ltc4162-l-charger.c:746:18: note: in expansion of macro 'mult_frac'
     746 |         regval = mult_frac(value, info->rsnsb, 14660u);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~


vim +/__div64_32 +199 include/asm-generic/div64.h

^1da177e4c3f41 Linus Torvalds     2005-04-16  176  
^1da177e4c3f41 Linus Torvalds     2005-04-16  177  /* The unnecessary pointer compare is there
^1da177e4c3f41 Linus Torvalds     2005-04-16  178   * to check for type safety (n must be 64bit)
^1da177e4c3f41 Linus Torvalds     2005-04-16  179   */
^1da177e4c3f41 Linus Torvalds     2005-04-16  180  # define do_div(n,base) ({				\
^1da177e4c3f41 Linus Torvalds     2005-04-16  181  	uint32_t __base = (base);			\
^1da177e4c3f41 Linus Torvalds     2005-04-16  182  	uint32_t __rem;					\
^1da177e4c3f41 Linus Torvalds     2005-04-16  183  	(void)(((typeof((n)) *)0) == ((uint64_t *)0));	\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  184  	if (__builtin_constant_p(__base) &&		\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  185  	    is_power_of_2(__base)) {			\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  186  		__rem = (n) & (__base - 1);		\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  187  		(n) >>= ilog2(__base);			\
c747ce4706190e Geert Uytterhoeven 2021-08-11  188  	} else if (__builtin_constant_p(__base) &&	\
461a5e51060c93 Nicolas Pitre      2015-10-30  189  		   __base != 0) {			\
461a5e51060c93 Nicolas Pitre      2015-10-30  190  		uint32_t __res_lo, __n_lo = (n);	\
461a5e51060c93 Nicolas Pitre      2015-10-30  191  		(n) = __div64_const32(n, __base);	\
461a5e51060c93 Nicolas Pitre      2015-10-30  192  		/* the remainder can be computed with 32-bit regs */ \
461a5e51060c93 Nicolas Pitre      2015-10-30  193  		__res_lo = (n);				\
461a5e51060c93 Nicolas Pitre      2015-10-30  194  		__rem = __n_lo - __res_lo * __base;	\
911918aa7ef6f8 Nicolas Pitre      2015-11-02 @195  	} else if (likely(((n) >> 32) == 0)) {		\
^1da177e4c3f41 Linus Torvalds     2005-04-16  196  		__rem = (uint32_t)(n) % __base;		\
^1da177e4c3f41 Linus Torvalds     2005-04-16  197  		(n) = (uint32_t)(n) / __base;		\
c747ce4706190e Geert Uytterhoeven 2021-08-11  198  	} else {					\
^1da177e4c3f41 Linus Torvalds     2005-04-16 @199  		__rem = __div64_32(&(n), __base);	\
c747ce4706190e Geert Uytterhoeven 2021-08-11  200  	}						\
^1da177e4c3f41 Linus Torvalds     2005-04-16  201  	__rem;						\
^1da177e4c3f41 Linus Torvalds     2005-04-16  202   })
^1da177e4c3f41 Linus Torvalds     2005-04-16  203  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-19 11:51 [RFC PATCH] math.h: Account for 64-bit division on i386 cem
  2025-04-19 18:28 ` kernel test robot
@ 2025-04-19 18:59 ` kernel test robot
  2025-04-20 15:40 ` Guenter Roeck
  2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-04-19 18:59 UTC (permalink / raw)
  To: cem; +Cc: oe-kbuild-all

Hi,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.15-rc2 next-20250417]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/cem-kernel-org/math-h-Account-for-64-bit-division-on-i386/20250419-195242
base:   linus/master
patch link:    https://lore.kernel.org/r/20250419115157.567249-1-cem%40kernel.org
patch subject: [RFC PATCH] math.h: Account for 64-bit division on i386
config: arc-randconfig-001-20250420 (https://download.01.org/0day-ci/archive/20250420/202504200217.lAUS8TXX-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 12.4.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250420/202504200217.lAUS8TXX-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504200217.lAUS8TXX-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from ./arch/arc/include/generated/asm/div64.h:1,
                    from include/linux/math.h:6,
                    from include/linux/kernel.h:27,
                    from include/linux/cpumask.h:11,
                    from include/linux/smp.h:13,
                    from include/linux/lockdep.h:14,
                    from include/linux/mutex.h:17,
                    from include/linux/interconnect.h:10,
                    from drivers/soc/qcom/icc-bwmon.c:10:
   drivers/soc/qcom/icc-bwmon.c: In function 'bwmon_set_threshold':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   In file included from include/linux/err.h:5,
                    from drivers/soc/qcom/icc-bwmon.c:9:
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Werror=incompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Werror=incompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:558:17: note: in expansion of macro 'mult_frac'
     558 |         thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
         |                 ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/soc/qcom/icc-bwmon.c: In function 'bwmon_start':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:187:21: error: assignment of read-only variable 'x_'
     187 |                 (n) >>= ilog2(__base);                  \
         |                     ^~~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:191:21: error: assignment of read-only variable 'x_'
     191 |                 (n) = __div64_const32(n, __base);       \
         |                     ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:197:21: error: assignment of read-only variable 'x_'
     197 |                 (n) = (uint32_t)(n) / __base;           \
         |                     ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Werror=incompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    const unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'const unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
>> include/linux/math.h:143:11: error: assignment of read-only variable 'r'
     143 |         r *= n_;                        \
         |           ^~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
>> include/asm-generic/div64.h:187:21: error: assignment of read-only variable 'r'
     187 |                 (n) >>= ilog2(__base);                  \
         |                     ^~~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:191:21: error: assignment of read-only variable 'r'
     191 |                 (n) = __div64_const32(n, __base);       \
         |                     ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:197:21: error: assignment of read-only variable 'r'
     197 |                 (n) = (uint32_t)(n) / __base;           \
         |                     ^
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Werror=incompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    const unsigned int *
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:574:18: note: in expansion of macro 'mult_frac'
     574 |         window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
         |                  ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'const unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   drivers/soc/qcom/icc-bwmon.c: In function 'bwmon_intr':
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:640:30: note: in expansion of macro 'mult_frac'
     640 |         bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
         |                              ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~
   include/linux/compiler.h:76:45: note: in definition of macro 'likely'
      76 | # define likely(x)      __builtin_expect(!!(x), 1)
         |                                             ^
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:640:30: note: in expansion of macro 'mult_frac'
     640 |         bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
         |                              ^~~~~~~~~
   include/asm-generic/div64.h:199:36: error: passing argument 1 of '__div64_32' from incompatible pointer type [-Werror=incompatible-pointer-types]
     199 |                 __rem = __div64_32(&(n), __base);       \
         |                                    ^~~~
         |                                    |
         |                                    unsigned int *
   include/linux/math.h:142:24: note: in expansion of macro 'do_div'
     142 |         typeof(x_) r = do_div(x_, d_);  \
         |                        ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:640:30: note: in expansion of macro 'mult_frac'
     640 |         bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
         |                              ^~~~~~~~~
   include/asm-generic/div64.h:174:38: note: expected 'uint64_t *' {aka 'long long unsigned int *'} but argument is of type 'unsigned int *'
     174 | extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
         |                            ~~~~~~~~~~^~~~~~~~
   include/asm-generic/div64.h:183:35: warning: comparison of distinct pointer types lacks a cast
     183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
         |                                   ^~
   include/linux/math.h:144:9: note: in expansion of macro 'do_div'
     144 |         do_div(r, d_);                  \
         |         ^~~~~~
   drivers/soc/qcom/icc-bwmon.c:640:30: note: in expansion of macro 'mult_frac'
     640 |         bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
         |                              ^~~~~~~~~
   include/asm-generic/div64.h:195:32: warning: right shift count >= width of type [-Wshift-count-overflow]
     195 |         } else if (likely(((n) >> 32) == 0)) {          \
         |                                ^~


vim +/x_ +187 include/asm-generic/div64.h

^1da177e4c3f41 Linus Torvalds     2005-04-16  176  
^1da177e4c3f41 Linus Torvalds     2005-04-16  177  /* The unnecessary pointer compare is there
^1da177e4c3f41 Linus Torvalds     2005-04-16  178   * to check for type safety (n must be 64bit)
^1da177e4c3f41 Linus Torvalds     2005-04-16  179   */
^1da177e4c3f41 Linus Torvalds     2005-04-16  180  # define do_div(n,base) ({				\
^1da177e4c3f41 Linus Torvalds     2005-04-16  181  	uint32_t __base = (base);			\
^1da177e4c3f41 Linus Torvalds     2005-04-16  182  	uint32_t __rem;					\
^1da177e4c3f41 Linus Torvalds     2005-04-16 @183  	(void)(((typeof((n)) *)0) == ((uint64_t *)0));	\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  184  	if (__builtin_constant_p(__base) &&		\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  185  	    is_power_of_2(__base)) {			\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  186  		__rem = (n) & (__base - 1);		\
911918aa7ef6f8 Nicolas Pitre      2015-11-02 @187  		(n) >>= ilog2(__base);			\
c747ce4706190e Geert Uytterhoeven 2021-08-11  188  	} else if (__builtin_constant_p(__base) &&	\
461a5e51060c93 Nicolas Pitre      2015-10-30  189  		   __base != 0) {			\
461a5e51060c93 Nicolas Pitre      2015-10-30  190  		uint32_t __res_lo, __n_lo = (n);	\
461a5e51060c93 Nicolas Pitre      2015-10-30  191  		(n) = __div64_const32(n, __base);	\
461a5e51060c93 Nicolas Pitre      2015-10-30  192  		/* the remainder can be computed with 32-bit regs */ \
461a5e51060c93 Nicolas Pitre      2015-10-30  193  		__res_lo = (n);				\
461a5e51060c93 Nicolas Pitre      2015-10-30  194  		__rem = __n_lo - __res_lo * __base;	\
911918aa7ef6f8 Nicolas Pitre      2015-11-02  195  	} else if (likely(((n) >> 32) == 0)) {		\
^1da177e4c3f41 Linus Torvalds     2005-04-16  196  		__rem = (uint32_t)(n) % __base;		\
^1da177e4c3f41 Linus Torvalds     2005-04-16  197  		(n) = (uint32_t)(n) / __base;		\
c747ce4706190e Geert Uytterhoeven 2021-08-11  198  	} else {					\
^1da177e4c3f41 Linus Torvalds     2005-04-16  199  		__rem = __div64_32(&(n), __base);	\
c747ce4706190e Geert Uytterhoeven 2021-08-11  200  	}						\
^1da177e4c3f41 Linus Torvalds     2005-04-16  201  	__rem;						\
^1da177e4c3f41 Linus Torvalds     2005-04-16  202   })
^1da177e4c3f41 Linus Torvalds     2005-04-16  203  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-19 11:51 [RFC PATCH] math.h: Account for 64-bit division on i386 cem
  2025-04-19 18:28 ` kernel test robot
  2025-04-19 18:59 ` kernel test robot
@ 2025-04-20 15:40 ` Guenter Roeck
  2025-04-20 17:42   ` Guenter Roeck
  2025-04-20 18:01   ` Carlos Maiolino
  2 siblings, 2 replies; 8+ messages in thread
From: Guenter Roeck @ 2025-04-20 15:40 UTC (permalink / raw)
  To: cem
  Cc: linux-kernel, Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

On Sat, Apr 19, 2025 at 01:51:46PM +0200, cem@kernel.org wrote:
> From: Carlos Maiolino <cem@kernel.org>
> 
> Building linux on i386 might fail if a 64bit type is passed to

i386 actually builds. Its compiler is probably able to convert
the offending mult_frac() without helpers since the divisor is
a constant. I see the problem with openrisc and parisc, with
gcc 13.3.0.

> mult_fract(). To prevent the failure, use do_div() for the division
> calculation instead of hardcoding a / b.
> 
> Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
> ---
> 
> I'm sending it as a RFC because I didn't to extensive testing on this
> patch, also I'm not sure if mult_frac() was intended to work on 32-bit
> only types. If that's the case, perhaps, a new mult_frac64() might be a
> better idea?!
> 
>  include/linux/math.h | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/include/linux/math.h b/include/linux/math.h
> index 0198c92cbe3e..05ea853b75b4 100644
> --- a/include/linux/math.h
> +++ b/include/linux/math.h
> @@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
>  #undef __STRUCT_FRACT
>  
>  /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
> -#define mult_frac(x, n, d)	\
> -({				\
> -	typeof(x) x_ = (x);	\
> -	typeof(n) n_ = (n);	\
> -	typeof(d) d_ = (d);	\
> -				\
> -	typeof(x_) q = x_ / d_;	\
> -	typeof(x_) r = x_ % d_;	\
> -	q * n_ + r * n_ / d_;	\
> +#define mult_frac(x, n, d)		\
> +({					\
> +	typeof(x) x_ = (x);		\
> +	typeof(n) n_ = (n);		\
> +	typeof(d) d_ = (d);		\
> +					\
> +	typeof(x_) r = do_div(x_, d_);	\
> +	r *= n_;			\
> +	do_div(r, d_);			\
> +	x_ * n_ + r;			\
>  })
>  

Unfortunately that doesn't work. I get build errors on parisc.

In file included from ./arch/parisc/include/generated/asm/div64.h:1,
                 from ./include/linux/math.h:6,
                 from ./include/linux/kernel.h:27,
                 from ./arch/parisc/include/asm/bug.h:5,
                 from ./include/linux/bug.h:5,
                 from ./include/linux/mmdebug.h:5,
                 from ./include/linux/mm.h:6,
                 from mm/page_alloc.c:19:
mm/page_alloc.c: In function 'boost_watermark':
./include/asm-generic/div64.h:183:35: error: comparison of distinct pointer types lacks a cast [-Werror]
  183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
      |                                   ^~
./include/linux/math.h:142:24: note: in expansion of macro 'do_div'
  142 |         typeof(x_) r = do_div(x_, d_);  \
      |                        ^~~~~~
mm/page_alloc.c:2010:21: note: in expansion of macro 'mult_frac'
 2010 |         max_boost = mult_frac(zone->_watermark[WMARK_HIGH],

That is just one example. It seems to affect all uses of
mult_frac().

Guenter

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-20 15:40 ` Guenter Roeck
@ 2025-04-20 17:42   ` Guenter Roeck
  2025-04-20 18:05     ` Carlos Maiolino
  2025-04-23  7:02     ` Geert Uytterhoeven
  2025-04-20 18:01   ` Carlos Maiolino
  1 sibling, 2 replies; 8+ messages in thread
From: Guenter Roeck @ 2025-04-20 17:42 UTC (permalink / raw)
  To: cem
  Cc: linux-kernel, Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

On Sun, Apr 20, 2025 at 08:40:27AM -0700, Guenter Roeck wrote:
> On Sat, Apr 19, 2025 at 01:51:46PM +0200, cem@kernel.org wrote:
> > From: Carlos Maiolino <cem@kernel.org>
> > 
> > Building linux on i386 might fail if a 64bit type is passed to
> 
> i386 actually builds. Its compiler is probably able to convert
> the offending mult_frac() without helpers since the divisor is
> a constant. I see the problem with openrisc and parisc, with
> gcc 13.3.0.
> 
> > mult_fract(). To prevent the failure, use do_div() for the division
> > calculation instead of hardcoding a / b.
> > 
> > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
> > ---
> > 
> > I'm sending it as a RFC because I didn't to extensive testing on this
> > patch, also I'm not sure if mult_frac() was intended to work on 32-bit
> > only types. If that's the case, perhaps, a new mult_frac64() might be a
> > better idea?!
> > 
> >  include/linux/math.h | 19 ++++++++++---------
> >  1 file changed, 10 insertions(+), 9 deletions(-)
> > 
> > diff --git a/include/linux/math.h b/include/linux/math.h
> > index 0198c92cbe3e..05ea853b75b4 100644
> > --- a/include/linux/math.h
> > +++ b/include/linux/math.h
> > @@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
> >  #undef __STRUCT_FRACT
> >  
> >  /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
> > -#define mult_frac(x, n, d)	\
> > -({				\
> > -	typeof(x) x_ = (x);	\
> > -	typeof(n) n_ = (n);	\
> > -	typeof(d) d_ = (d);	\
> > -				\
> > -	typeof(x_) q = x_ / d_;	\
> > -	typeof(x_) r = x_ % d_;	\
> > -	q * n_ + r * n_ / d_;	\
> > +#define mult_frac(x, n, d)		\
> > +({					\
> > +	typeof(x) x_ = (x);		\
> > +	typeof(n) n_ = (n);		\
> > +	typeof(d) d_ = (d);		\
> > +					\
> > +	typeof(x_) r = do_div(x_, d_);	\
> > +	r *= n_;			\
> > +	do_div(r, d_);			\
> > +	x_ * n_ + r;			\
> >  })
> >  
> 
> Unfortunately that doesn't work. I get build errors on parisc.
> 

Turns out the first parameter of do_div needs to be u64, not s64,
at least on parisc.

Guenter

> In file included from ./arch/parisc/include/generated/asm/div64.h:1,
>                  from ./include/linux/math.h:6,
>                  from ./include/linux/kernel.h:27,
>                  from ./arch/parisc/include/asm/bug.h:5,
>                  from ./include/linux/bug.h:5,
>                  from ./include/linux/mmdebug.h:5,
>                  from ./include/linux/mm.h:6,
>                  from mm/page_alloc.c:19:
> mm/page_alloc.c: In function 'boost_watermark':
> ./include/asm-generic/div64.h:183:35: error: comparison of distinct pointer types lacks a cast [-Werror]
>   183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
>       |                                   ^~
> ./include/linux/math.h:142:24: note: in expansion of macro 'do_div'
>   142 |         typeof(x_) r = do_div(x_, d_);  \
>       |                        ^~~~~~
> mm/page_alloc.c:2010:21: note: in expansion of macro 'mult_frac'
>  2010 |         max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
> 
> That is just one example. It seems to affect all uses of
> mult_frac().
> 
> Guenter

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-20 15:40 ` Guenter Roeck
  2025-04-20 17:42   ` Guenter Roeck
@ 2025-04-20 18:01   ` Carlos Maiolino
  1 sibling, 0 replies; 8+ messages in thread
From: Carlos Maiolino @ 2025-04-20 18:01 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-kernel, Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

On Sun, Apr 20, 2025 at 08:40:25AM -0700, Guenter Roeck wrote:
> On Sat, Apr 19, 2025 at 01:51:46PM +0200, cem@kernel.org wrote:
> > From: Carlos Maiolino <cem@kernel.org>
> >
> > Building linux on i386 might fail if a 64bit type is passed to
> 
> i386 actually builds. Its compiler is probably able to convert
> the offending mult_frac() without helpers since the divisor is
> a constant. I see the problem with openrisc and parisc, with
> gcc 13.3.0.

It does fail to build, that's how it got identified in the first place. I
managed to reproduce here according to the reproducer sent by the test robot.
I think it works if you don't enable build checks (in this case W=1) though.

I didn't try other architectures other than x86 though, thanks for the heads up.


> 
> > mult_fract(). To prevent the failure, use do_div() for the division
> > calculation instead of hardcoding a / b.
> >
> > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
> > ---
> >
> > I'm sending it as a RFC because I didn't to extensive testing on this
> > patch, also I'm not sure if mult_frac() was intended to work on 32-bit
> > only types. If that's the case, perhaps, a new mult_frac64() might be a
> > better idea?!
> >
> >  include/linux/math.h | 19 ++++++++++---------
> >  1 file changed, 10 insertions(+), 9 deletions(-)
> >
> > diff --git a/include/linux/math.h b/include/linux/math.h
> > index 0198c92cbe3e..05ea853b75b4 100644
> > --- a/include/linux/math.h
> > +++ b/include/linux/math.h
> > @@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
> >  #undef __STRUCT_FRACT
> >
> >  /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
> > -#define mult_frac(x, n, d)	\
> > -({				\
> > -	typeof(x) x_ = (x);	\
> > -	typeof(n) n_ = (n);	\
> > -	typeof(d) d_ = (d);	\
> > -				\
> > -	typeof(x_) q = x_ / d_;	\
> > -	typeof(x_) r = x_ % d_;	\
> > -	q * n_ + r * n_ / d_;	\
> > +#define mult_frac(x, n, d)		\
> > +({					\
> > +	typeof(x) x_ = (x);		\
> > +	typeof(n) n_ = (n);		\
> > +	typeof(d) d_ = (d);		\
> > +					\
> > +	typeof(x_) r = do_div(x_, d_);	\
> > +	r *= n_;			\
> > +	do_div(r, d_);			\
> > +	x_ * n_ + r;			\
> >  })
> >
> 
> Unfortunately that doesn't work. I get build errors on parisc.
> 
> In file included from ./arch/parisc/include/generated/asm/div64.h:1,
>                  from ./include/linux/math.h:6,
>                  from ./include/linux/kernel.h:27,
>                  from ./arch/parisc/include/asm/bug.h:5,
>                  from ./include/linux/bug.h:5,
>                  from ./include/linux/mmdebug.h:5,
>                  from ./include/linux/mm.h:6,
>                  from mm/page_alloc.c:19:
> mm/page_alloc.c: In function 'boost_watermark':
> ./include/asm-generic/div64.h:183:35: error: comparison of distinct pointer types lacks a cast [-Werror]
>   183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
>       |                                   ^~
> ./include/linux/math.h:142:24: note: in expansion of macro 'do_div'
>   142 |         typeof(x_) r = do_div(x_, d_);  \
>       |                        ^~~~~~
> mm/page_alloc.c:2010:21: note: in expansion of macro 'mult_frac'
>  2010 |         max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
> 
> That is just one example. It seems to affect all uses of
> mult_frac().
> 
> Guenter

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-20 17:42   ` Guenter Roeck
@ 2025-04-20 18:05     ` Carlos Maiolino
  2025-04-23  7:02     ` Geert Uytterhoeven
  1 sibling, 0 replies; 8+ messages in thread
From: Carlos Maiolino @ 2025-04-20 18:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-kernel, Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

On Sun, Apr 20, 2025 at 10:42:18AM -0700, Guenter Roeck wrote:
> On Sun, Apr 20, 2025 at 08:40:27AM -0700, Guenter Roeck wrote:
> > On Sat, Apr 19, 2025 at 01:51:46PM +0200, cem@kernel.org wrote:
> > > From: Carlos Maiolino <cem@kernel.org>
> > >
> > > Building linux on i386 might fail if a 64bit type is passed to
> >
> > i386 actually builds. Its compiler is probably able to convert
> > the offending mult_frac() without helpers since the divisor is
> > a constant. I see the problem with openrisc and parisc, with
> > gcc 13.3.0.
> >
> > > mult_fract(). To prevent the failure, use do_div() for the division
> > > calculation instead of hardcoding a / b.
> > >
> > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
> > > ---
> > >
> > > I'm sending it as a RFC because I didn't to extensive testing on this
> > > patch, also I'm not sure if mult_frac() was intended to work on 32-bit
> > > only types. If that's the case, perhaps, a new mult_frac64() might be a
> > > better idea?!
> > >
> > >  include/linux/math.h | 19 ++++++++++---------
> > >  1 file changed, 10 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/include/linux/math.h b/include/linux/math.h
> > > index 0198c92cbe3e..05ea853b75b4 100644
> > > --- a/include/linux/math.h
> > > +++ b/include/linux/math.h
> > > @@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
> > >  #undef __STRUCT_FRACT
> > >
> > >  /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
> > > -#define mult_frac(x, n, d)	\
> > > -({				\
> > > -	typeof(x) x_ = (x);	\
> > > -	typeof(n) n_ = (n);	\
> > > -	typeof(d) d_ = (d);	\
> > > -				\
> > > -	typeof(x_) q = x_ / d_;	\
> > > -	typeof(x_) r = x_ % d_;	\
> > > -	q * n_ + r * n_ / d_;	\
> > > +#define mult_frac(x, n, d)		\
> > > +({					\
> > > +	typeof(x) x_ = (x);		\
> > > +	typeof(n) n_ = (n);		\
> > > +	typeof(d) d_ = (d);		\
> > > +					\
> > > +	typeof(x_) r = do_div(x_, d_);	\
> > > +	r *= n_;			\
> > > +	do_div(r, d_);			\
> > > +	x_ * n_ + r;			\
> > >  })
> > >
> >
> > Unfortunately that doesn't work. I get build errors on parisc.
> >
> 
> Turns out the first parameter of do_div needs to be u64, not s64,
> at least on parisc.

Yup, that's true for x86 too, needs to be fixed once we decide which
path to take to fix it.

> 
> Guenter
> 
> > In file included from ./arch/parisc/include/generated/asm/div64.h:1,
> >                  from ./include/linux/math.h:6,
> >                  from ./include/linux/kernel.h:27,
> >                  from ./arch/parisc/include/asm/bug.h:5,
> >                  from ./include/linux/bug.h:5,
> >                  from ./include/linux/mmdebug.h:5,
> >                  from ./include/linux/mm.h:6,
> >                  from mm/page_alloc.c:19:
> > mm/page_alloc.c: In function 'boost_watermark':
> > ./include/asm-generic/div64.h:183:35: error: comparison of distinct pointer types lacks a cast [-Werror]
> >   183 |         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
> >       |                                   ^~
> > ./include/linux/math.h:142:24: note: in expansion of macro 'do_div'
> >   142 |         typeof(x_) r = do_div(x_, d_);  \
> >       |                        ^~~~~~
> > mm/page_alloc.c:2010:21: note: in expansion of macro 'mult_frac'
> >  2010 |         max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
> >
> > That is just one example. It seems to affect all uses of
> > mult_frac().
> >
> > Guenter

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] math.h: Account for 64-bit division on i386
  2025-04-20 17:42   ` Guenter Roeck
  2025-04-20 18:05     ` Carlos Maiolino
@ 2025-04-23  7:02     ` Geert Uytterhoeven
  1 sibling, 0 replies; 8+ messages in thread
From: Geert Uytterhoeven @ 2025-04-23  7:02 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: cem, linux-kernel, Hans.Holmberg, oe-kbuild-all, hch, lukas,
	angelogioacchino.delregno, Jonathan.Cameron

On Sun, 20 Apr 2025 at 19:42, Guenter Roeck <linux@roeck-us.net> wrote:
> On Sun, Apr 20, 2025 at 08:40:27AM -0700, Guenter Roeck wrote:
> > On Sat, Apr 19, 2025 at 01:51:46PM +0200, cem@kernel.org wrote:
> > > From: Carlos Maiolino <cem@kernel.org>
> > >
> > > Building linux on i386 might fail if a 64bit type is passed to
> >
> > i386 actually builds. Its compiler is probably able to convert
> > the offending mult_frac() without helpers since the divisor is
> > a constant. I see the problem with openrisc and parisc, with
> > gcc 13.3.0.
> >
> > > mult_fract(). To prevent the failure, use do_div() for the division
> > > calculation instead of hardcoding a / b.
> > >
> > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Closes: https://lore.kernel.org/oe-kbuild-all/202504181233.F7D9Atra-lkp@intel.com/
> > > ---
> > >
> > > I'm sending it as a RFC because I didn't to extensive testing on this
> > > patch, also I'm not sure if mult_frac() was intended to work on 32-bit
> > > only types. If that's the case, perhaps, a new mult_frac64() might be a
> > > better idea?!
> > >
> > >  include/linux/math.h | 19 ++++++++++---------
> > >  1 file changed, 10 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/include/linux/math.h b/include/linux/math.h
> > > index 0198c92cbe3e..05ea853b75b4 100644
> > > --- a/include/linux/math.h
> > > +++ b/include/linux/math.h
> > > @@ -133,15 +133,16 @@ __STRUCT_FRACT(u32)
> > >  #undef __STRUCT_FRACT
> > >
> > >  /* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
> > > -#define mult_frac(x, n, d) \
> > > -({                         \
> > > -   typeof(x) x_ = (x);     \
> > > -   typeof(n) n_ = (n);     \
> > > -   typeof(d) d_ = (d);     \
> > > -                           \
> > > -   typeof(x_) q = x_ / d_; \
> > > -   typeof(x_) r = x_ % d_; \
> > > -   q * n_ + r * n_ / d_;   \
> > > +#define mult_frac(x, n, d)         \
> > > +({                                 \
> > > +   typeof(x) x_ = (x);             \
> > > +   typeof(n) n_ = (n);             \
> > > +   typeof(d) d_ = (d);             \
> > > +                                   \
> > > +   typeof(x_) r = do_div(x_, d_);  \
> > > +   r *= n_;                        \
> > > +   do_div(r, d_);                  \
> > > +   x_ * n_ + r;                    \
> > >  })
> > >
> >
> > Unfortunately that doesn't work. I get build errors on parisc.
> >
>
> Turns out the first parameter of do_div needs to be u64, not s64,
> at least on parisc.

That is correct: the first parameter must be u64, the second must be u32:
https://elixir.bootlin.com/linux/v6.14.3/source/include/asm-generic/div64.h

As you must never use open-coded 64-bit divisions in the kernel,
simple helpers like mult_frac() can only be used for 32-bit values.
For anything involving 64-bit divisions, you must use the helpers from
<linux/math64.h>, e.g. mul_u64_u32_div().
https://elixir.bootlin.com/linux/v6.14.3/source/include/linux/math64.h#L257

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-04-23  7:02 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-19 11:51 [RFC PATCH] math.h: Account for 64-bit division on i386 cem
2025-04-19 18:28 ` kernel test robot
2025-04-19 18:59 ` kernel test robot
2025-04-20 15:40 ` Guenter Roeck
2025-04-20 17:42   ` Guenter Roeck
2025-04-20 18:05     ` Carlos Maiolino
2025-04-23  7:02     ` Geert Uytterhoeven
2025-04-20 18:01   ` Carlos Maiolino

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.