[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC] arm64: 32-bit tolerant sync bitops



Xen assumes that bit operations are able to operate on 32-bit size and
alignment [1]. For arm64 bitops are based on atomic exclusive load/store
instructions to guarantee that changes are made atomically. However, these
instructions require that address to be aligned to the data size. Because, by
default, bitops operates on 64-bit size it implies that address should be
aligned appropriately. All these lead to breakage of Xen assumption for bitops
properties.

With this patch 32-bit sized/aligned bitops is implemented. 

[1] http://www.gossamer-threads.com/lists/xen/devel/325613

Signed-off-by: Vladimir Murzin <murzin.v@xxxxxxxxx>
---
 Apart this patch other approaches were implemented:
 1. turn bitops to be 32-bit size/align tolerant.
    the changes are minimal, but I'm not sure how broad side effect might be
 2. separate 32-bit size/aligned operations.
    it exports new API, which might not be good

 All implementations based on arm64 version of bitops and were boot tested
 only. Hope, I didn't miss something ;) 

 arch/arm64/include/asm/sync_bitops.h | 60 ++++++++++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/sync_bitops.h 
b/arch/arm64/include/asm/sync_bitops.h
index 8da0bf4..809926f 100644
--- a/arch/arm64/include/asm/sync_bitops.h
+++ b/arch/arm64/include/asm/sync_bitops.h
@@ -3,6 +3,7 @@
 
 #include <asm/bitops.h>
 #include <asm/cmpxchg.h>
+#include <linux/stringify.h>
 
 /* sync_bitops functions are equivalent to the SMP implementation of the
  * original functions, independently from CONFIG_SMP being defined.
@@ -12,14 +13,61 @@
  * who might be on another CPU (e.g. two uniprocessor guests communicating
  * via event channels and grant tables). So we need a variant of the bit
  * ops which are SMP safe even on a UP kernel.
+ *
+ * Xen assumes that bitops are 32-bit sized/aligned
  */
 
-#define sync_set_bit(nr, p)            set_bit(nr, p)
-#define sync_clear_bit(nr, p)          clear_bit(nr, p)
-#define sync_change_bit(nr, p)         change_bit(nr, p)
-#define sync_test_and_set_bit(nr, p)   test_and_set_bit(nr, p)
-#define sync_test_and_clear_bit(nr, p) test_and_clear_bit(nr, p)
-#define sync_test_and_change_bit(nr, p)        test_and_change_bit(nr, p)
+#define sync_bitop32(name, instr)                                      \
+static inline void sync_##name(int nr, volatile unsigned long *addr)   \
+{                                                                      \
+       unsigned tmp1, tmp2;                                            \
+       asm volatile(                                                   \
+       "       and     %w1, %w2, #31\n"                                \
+       "       eor     %w2, %w2, %w1\n"                                \
+       "       mov     %w0, #1\n"                                      \
+       "       add     %3, %3, %2, lsr #2\n"                           \
+       "       lsl     %w1, %w0, %w1\n"                                \
+       "1:     ldxr    %w0, [%3]\n"                                    \
+       __stringify(instr)" %w0, %w0, %w1\n"                            \
+       "       stxr    %w2, %w0, [%3]\n"                               \
+       "       cbnz    %w2, 1b\n"                                      \
+       : "=&r"(tmp1), "=&r"(tmp2)                                      \
+       : "r"(nr), "r"(addr)                                            \
+       : "memory");                                                    \
+}
+
+#define sync_testop32(name, instr)                                     \
+static inline int sync_##name(int nr, volatile unsigned long *addr)    \
+{                                                                      \
+       int oldbit;                                                     \
+       unsigned tmp1, tmp2, tmp3;                                      \
+       asm volatile(                                                   \
+       "       and     %w1, %w4, #31\n"                                \
+       "       eor     %w4, %w4, %w1\n"                                \
+       "       mov     %w0, #1\n"                                      \
+       "       add     %5, %5, %4, lsr #2\n"                           \
+       "       lsl     %w2, %w0, %w1\n"                                \
+       "1:     ldxr    %w0, [%5]\n"                                    \
+       "       lsr     %w3, %w0, %w1\n"                                \
+       __stringify(instr)" %w0, %w0, %w2\n"                            \
+       "       stlxr   %w4, %w0, [%5]\n"                               \
+       "       cbnz    %w4, 1b\n"                                      \
+       "       dmb     ish\n"                                          \
+       "       and     %w3, %w3, #1\n"                                 \
+       : "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(oldbit)          \
+       : "r"(nr), "r"(addr)                                            \
+       : "memory");                                                    \
+       return oldbit;                                                  \
+}
+
+sync_bitop32(set_bit, orr)
+sync_bitop32(clear_bit, bic)
+sync_bitop32(change_bit, eor)
+
+sync_testop32(test_and_set_bit, orr)
+sync_testop32(test_and_clear_bit, bic)
+sync_testop32(test_and_change_bit, eor)
+
 #define sync_test_bit(nr, addr)                test_bit(nr, addr)
 #define sync_cmpxchg                   cmpxchg
 
-- 
1.8.3.2


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.