]> xenbits.xensource.com Git - xen.git/commitdiff
arm64: fix fls()
authorJan Beulich <jbeulich@suse.com>
Fri, 23 Jan 2015 14:02:39 +0000 (15:02 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Thu, 2 Apr 2015 10:45:19 +0000 (11:45 +0100)
It using CLZ on a 64-bit register while specifying the input operand as
only 32 bits wide is wrong: An operand intentionally shrunk down to 32
bits at the source level doesn't imply respective zero extension also
happens at the machine instruction level, and hence the wrong result
could get returned.

Add suitable inline assembly abstraction so that the function can
remain shared between arm32 and arm64. The need to include asm_defns.h
in bitops.h makes it necessary to adjust processor.h though - it is
generally wrong to include public headers without making sure that
integer types are properly defined. (I didn't innvestigate or try
whether the possible alternative of moving the public/arch-arm.h
inclusion down in the file would also work.)

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
(cherry picked from commit e9c1747a25763c66de4a06923946c59a9f043069)

xen/include/asm-arm/asm_defns.h
xen/include/asm-arm/bitops.h
xen/include/asm-arm/processor.h

index 36e72ffe3f50e608ab02a351dc1c202b2d5167e4..02be83e2b395dd6363ecab0a60823251b3c1cade 100644 (file)
@@ -7,6 +7,15 @@
 #endif
 #include <asm/processor.h>
 
+/* For generic assembly code: use macros to define operand sizes. */
+#if defined(CONFIG_ARM_32)
+# define __OP32
+#elif defined(CONFIG_ARM_64)
+# define __OP32 "w"
+#else
+# error "unknown ARM variant"
+#endif
+
 #endif /* __ARM_ASM_DEFNS_H__ */
 /*
  * Local variables:
index 25f96c89cbd4bad589edc4063a09cc7b28d0052b..d69a7c32a670a2a589c467149ceeb823a789647a 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _ARM_BITOPS_H
 #define _ARM_BITOPS_H
 
+#include <asm/asm_defns.h>
+
 /*
  * Non-atomic bit manipulation.
  *
@@ -140,9 +142,8 @@ static inline int fls(int x)
         if (__builtin_constant_p(x))
                return constant_fls(x);
 
-        asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
-        ret = BITS_PER_LONG - ret;
-        return ret;
+        asm("clz\t%"__OP32"0, %"__OP32"1" : "=r" (ret) : "r" (x));
+        return 32 - ret;
 }
 
 
index b7ef817fd2ab5217e66e76c2a4420e8f5ef3b810..fcd26fb4098f2fb1e9cd09fbc102b9bca276f135 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <asm/cpregs.h>
 #include <asm/sysregs.h>
+#ifndef __ASSEMBLY__
+#include <xen/types.h>
+#endif
 #include <public/arch-arm.h>
 
 /* MIDR Main ID Register */
 
 #ifndef __ASSEMBLY__
 
-#include <xen/types.h>
-
 struct cpuinfo_arm {
     union {
         uint32_t bits;