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>
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
---------------------------------------------------------------------
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
--- /dev/null
+/*
+ * 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:
+ */
+++ /dev/null
-#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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
#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