]> xenbits.xensource.com Git - xen.git/commitdiff
xen/arm32: bitops: Rewrite bitop helpers in C
authorJulien Grall <julien.grall@arm.com>
Mon, 29 Apr 2019 14:05:19 +0000 (15:05 +0100)
committerJulien Grall <julien.grall@arm.com>
Fri, 14 Jun 2019 14:46:00 +0000 (15:46 +0100)
This is part of XSA-295.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
xen/arch/arm/README.LinuxPrimitives
xen/arch/arm/arm32/lib/Makefile
xen/arch/arm/arm32/lib/bitops.c [new file with mode: 0644]
xen/arch/arm/arm32/lib/bitops.h [deleted file]
xen/arch/arm/arm32/lib/changebit.S [deleted file]
xen/arch/arm/arm32/lib/clearbit.S [deleted file]
xen/arch/arm/arm32/lib/setbit.S [deleted file]
xen/arch/arm/arm32/lib/testchangebit.S [deleted file]
xen/arch/arm/arm32/lib/testclearbit.S [deleted file]
xen/arch/arm/arm32/lib/testsetbit.S [deleted file]
xen/include/asm-arm/arm32/bitops.h

index 891667a5da10964998fb22d428cb412508d67ece..664a9f89ed27ffd42771f979b0204559e761f3a5 100644 (file)
@@ -68,19 +68,9 @@ arm32
 
 bitops: last sync @ v3.16-rc6 (last commit: c32ffce0f66e)
 
-linux/arch/arm/lib/bitops.h             xen/arch/arm/arm32/lib/bitops.h
-linux/arch/arm/lib/changebit.S          xen/arch/arm/arm32/lib/changebit.S
-linux/arch/arm/lib/clearbit.S           xen/arch/arm/arm32/lib/clearbit.S
 linux/arch/arm/lib/findbit.S            xen/arch/arm/arm32/lib/findbit.S
-linux/arch/arm/lib/setbit.S             xen/arch/arm/arm32/lib/setbit.S
-linux/arch/arm/lib/testchangebit.S      xen/arch/arm/arm32/lib/testchangebit.S
-linux/arch/arm/lib/testclearbit.S       xen/arch/arm/arm32/lib/testclearbit.S
-linux/arch/arm/lib/testsetbit.S         xen/arch/arm/arm32/lib/testsetbit.S
-
-for i in bitops.h changebit.S clearbit.S findbit.S setbit.S testchangebit.S \
-         testclearbit.S testsetbit.S; do
-    diff -u ../linux/arch/arm/lib/$i xen/arch/arm/arm32/lib/$i;
-done
+
+diff -u ../linux/arch/arm/lib/findbit.S xen/arch/arm/arm32/lib/findbit.S
 
 ---------------------------------------------------------------------
 
index e9fbc595b9cf37543a0b23926ad3f9a15c151a74..b1457c89dc660b1b00dbd206e0ee715e558c392a 100644 (file)
@@ -1,6 +1,5 @@
 obj-y += memcpy.o memmove.o memset.o memchr.o memzero.o
-obj-y += findbit.o setbit.o
-obj-y += setbit.o clearbit.o changebit.o
-obj-y += testsetbit.o testclearbit.o testchangebit.o
+obj-y += findbit.o
+obj-y += bitops.o
 obj-y += strchr.o strrchr.o
 obj-y += lib1funcs.o lshrdi3.o div64.o
diff --git a/xen/arch/arm/arm32/lib/bitops.c b/xen/arch/arm/arm32/lib/bitops.c
new file mode 100644 (file)
index 0000000..c69bb53
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/bitops.h>
+#include <xen/prefetch.h>
+#include <asm/system.h>
+
+/*
+ * The atomic bit operations pass the number of bit in a signed number
+ * (not sure why). This has the drawback to increase the complexity of
+ * the resulting assembly.
+ *
+ * To generate simpler code, the number of bit (nr) will be cast to
+ * unsigned int.
+ *
+ * XXX: Rework the interface to use unsigned int.
+ */
+
+#define bitop(name, instr)                                                  \
+void name(int nr, volatile void *p)                                         \
+{                                                                           \
+    volatile uint32_t *ptr = (uint32_t *)p + BIT_WORD((unsigned int)nr);    \
+    const uint32_t mask = BIT_MASK((unsigned int)nr);                       \
+    unsigned long res, tmp;                                                 \
+                                                                            \
+    ASSERT(((vaddr_t)p & 0x3) == 0);                                        \
+    prefetchw((const void *)ptr);                                           \
+                                                                            \
+    do                                                                      \
+    {                                                                       \
+        asm volatile ("// " __stringify(name) "\n"                          \
+        "   ldrex   %2, %1\n"                                               \
+        "   " __stringify(instr) "     %2, %2, %3\n"                        \
+        "   strex   %0, %2, %1\n"                                           \
+        : "=&r" (res), "+Qo" (*ptr), "=&r" (tmp)                            \
+        : "r" (mask));                                                      \
+    } while ( res );                                                        \
+}
+
+#define testop(name, instr)                                                 \
+int name(int nr, volatile void *p)                                          \
+{                                                                           \
+    volatile uint32_t *ptr = (uint32_t *)p + BIT_WORD((unsigned int)nr);    \
+    unsigned int bit = (unsigned int)nr % BITS_PER_WORD;                    \
+    const uint32_t mask = BIT_MASK(bit);                                    \
+    unsigned long res, tmp;                                                 \
+    int oldbit;                                                             \
+                                                                            \
+    ASSERT(((vaddr_t)p & 0x3) == 0);                                        \
+    smp_mb();                                                               \
+                                                                            \
+    prefetchw((const void *)ptr);                                           \
+                                                                            \
+    do                                                                      \
+    {                                                                       \
+        asm volatile ("// " __stringify(name) "\n"                          \
+        "   ldrex   %3, %2\n"                                               \
+        "   lsr     %1, %3, %5 // Save old value of bit\n"                  \
+        "   " __stringify(instr) "  %3, %3, %4 // Toggle bit\n"             \
+        "   strex  %0, %3, %2\n"                                            \
+        : "=&r" (res), "=&r" (oldbit), "+Qo" (*ptr), "=&r" (tmp)            \
+        : "r" (mask), "r" (bit));                                           \
+    } while ( res );                                                        \
+                                                                            \
+    smp_mb();                                                               \
+                                                                            \
+    return oldbit & 1;                                                      \
+}                                                                           \
+
+bitop(change_bit, eor)
+bitop(clear_bit, bic)
+bitop(set_bit, orr)
+
+testop(test_and_change_bit, eor)
+testop(test_and_clear_bit, bic)
+testop(test_and_set_bit, orr)
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/arm32/lib/bitops.h b/xen/arch/arm/arm32/lib/bitops.h
deleted file mode 100644 (file)
index a167c2d..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <xen/config.h>
-
-#if __LINUX_ARM_ARCH__ >= 6
-       .macro  bitop, name, instr
-ENTRY( \name           )
-UNWIND(        .fnstart        )
-       ands    ip, r1, #3
-       strneb  r1, [ip]                @ assert word-aligned
-       mov     r2, #1
-       and     r3, r0, #31             @ Get bit offset
-       mov     r0, r0, lsr #5
-       add     r1, r1, r0, lsl #2      @ Get word offset
-#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
-       .arch_extension mp
-       ALT_SMP(W(pldw) [r1])
-       ALT_UP(W(nop))
-#endif
-       mov     r3, r2, lsl r3
-1:     ldrex   r2, [r1]
-       \instr  r2, r2, r3
-       strex   r0, r2, [r1]
-       cmp     r0, #0
-       bne     1b
-       bx      lr
-UNWIND(        .fnend          )
-ENDPROC(\name          )
-       .endm
-
-       .macro  testop, name, instr, store
-ENTRY( \name           )
-UNWIND(        .fnstart        )
-       ands    ip, r1, #3
-       strneb  r1, [ip]                @ assert word-aligned
-       mov     r2, #1
-       and     r3, r0, #31             @ Get bit offset
-       mov     r0, r0, lsr #5
-       add     r1, r1, r0, lsl #2      @ Get word offset
-       mov     r3, r2, lsl r3          @ create mask
-       smp_dmb
-#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
-       .arch_extension mp
-       ALT_SMP(W(pldw) [r1])
-       ALT_UP(W(nop))
-#endif
-1:     ldrex   r2, [r1]
-       ands    r0, r2, r3              @ save old value of bit
-       \instr  r2, r2, r3              @ toggle bit
-       strex   ip, r2, [r1]
-       cmp     ip, #0
-       bne     1b
-       smp_dmb
-       cmp     r0, #0
-       movne   r0, #1
-2:     bx      lr
-UNWIND(        .fnend          )
-ENDPROC(\name          )
-       .endm
-#else
-       .macro  bitop, name, instr
-ENTRY( \name           )
-UNWIND(        .fnstart        )
-       ands    ip, r1, #3
-       strneb  r1, [ip]                @ assert word-aligned
-       and     r2, r0, #31
-       mov     r0, r0, lsr #5
-       mov     r3, #1
-       mov     r3, r3, lsl r2
-       save_and_disable_irqs ip
-       ldr     r2, [r1, r0, lsl #2]
-       \instr  r2, r2, r3
-       str     r2, [r1, r0, lsl #2]
-       restore_irqs ip
-       mov     pc, lr
-UNWIND(        .fnend          )
-ENDPROC(\name          )
-       .endm
-
-/**
- * testop - implement a test_and_xxx_bit operation.
- * @instr: operational instruction
- * @store: store instruction
- *
- * Note: we can trivially conditionalise the store instruction
- * to avoid dirtying the data cache.
- */
-       .macro  testop, name, instr, store
-ENTRY( \name           )
-UNWIND(        .fnstart        )
-       ands    ip, r1, #3
-       strneb  r1, [ip]                @ assert word-aligned
-       and     r3, r0, #31
-       mov     r0, r0, lsr #5
-       save_and_disable_irqs ip
-       ldr     r2, [r1, r0, lsl #2]!
-       mov     r0, #1
-       tst     r2, r0, lsl r3
-       \instr  r2, r2, r0, lsl r3
-       \store  r2, [r1]
-       moveq   r0, #0
-       restore_irqs ip
-       mov     pc, lr
-UNWIND(        .fnend          )
-ENDPROC(\name          )
-       .endm
-#endif
diff --git a/xen/arch/arm/arm32/lib/changebit.S b/xen/arch/arm/arm32/lib/changebit.S
deleted file mode 100644 (file)
index 11f41d2..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/lib/changebit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-                .text
-
-bitop  _change_bit, eor
diff --git a/xen/arch/arm/arm32/lib/clearbit.S b/xen/arch/arm/arm32/lib/clearbit.S
deleted file mode 100644 (file)
index 1b6a569..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- *  linux/arch/arm/lib/clearbit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-                .text
-
-bitop  _clear_bit, bic
diff --git a/xen/arch/arm/arm32/lib/setbit.S b/xen/arch/arm/arm32/lib/setbit.S
deleted file mode 100644 (file)
index 1f4ef56..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/lib/setbit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-       .text
-
-bitop  _set_bit, orr
diff --git a/xen/arch/arm/arm32/lib/testchangebit.S b/xen/arch/arm/arm32/lib/testchangebit.S
deleted file mode 100644 (file)
index 7f4635c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/lib/testchangebit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-                .text
-
-testop _test_and_change_bit, eor, str
diff --git a/xen/arch/arm/arm32/lib/testclearbit.S b/xen/arch/arm/arm32/lib/testclearbit.S
deleted file mode 100644 (file)
index 4d4152f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/lib/testclearbit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-                .text
-
-testop _test_and_clear_bit, bicne, strne
diff --git a/xen/arch/arm/arm32/lib/testsetbit.S b/xen/arch/arm/arm32/lib/testsetbit.S
deleted file mode 100644 (file)
index 54f48f9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/lib/testsetbit.S
- *
- *  Copyright (C) 1995-1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <xen/config.h>
-
-#include "assembler.h"
-#include "bitops.h"
-                .text
-
-testop _test_and_set_bit, orreq, streq
index 8be3564540948a4158fded9119313baf03f276e4..67c4c3f55cc7a0d74cc96560c29819dc29c066c1 100644 (file)
@@ -1,19 +1,12 @@
 #ifndef _ARM_ARM32_BITOPS_H
 #define _ARM_ARM32_BITOPS_H
 
-extern void _set_bit(int nr, volatile void * p);
-extern void _clear_bit(int nr, volatile void * p);
-extern void _change_bit(int nr, volatile void * p);
-extern int _test_and_set_bit(int nr, volatile void * p);
-extern int _test_and_clear_bit(int nr, volatile void * p);
-extern int _test_and_change_bit(int nr, volatile void * p);
-
-#define set_bit(n,p)              _set_bit(n,p)
-#define clear_bit(n,p)            _clear_bit(n,p)
-#define change_bit(n,p)           _change_bit(n,p)
-#define test_and_set_bit(n,p)     _test_and_set_bit(n,p)
-#define test_and_clear_bit(n,p)   _test_and_clear_bit(n,p)
-#define test_and_change_bit(n,p)  _test_and_change_bit(n,p)
+extern void set_bit(int nr, volatile void * p);
+extern void clear_bit(int nr, volatile void * p);
+extern void change_bit(int nr, volatile void * p);
+extern int test_and_set_bit(int nr, volatile void * p);
+extern int test_and_clear_bit(int nr, volatile void * p);
+extern int test_and_change_bit(int nr, volatile void * p);
 
 #define flsl fls