* [RFC+CFT] Use word operations in bitops
@ 2011-01-16 12:19 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-16 12:19 UTC (permalink / raw)
To: linux-arm-kernel, linux-omap
XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
I strongly suggest you ensure you have a copy of your filesystems before
trying this patch.
The patch below switches the bitops to use word loads/stores rather than
byte operations - so that we can avoid using the ldrexb/strexb instructions
which are only supported from ARMv6k and up.
The current bitops prevent a single kernel covering ARMv6 and ARMv7
architectures without the resulting kernel being unsafe on SMP. As
ldrex/strex is supported from ARMv6 upwards, but ldrexb/strexb is not,
switch these functions to use the word-based loads/stores.
As our bitops functions have been tolerant of misaligned pointers, they
now include a check which will do a NULL pointer store in the event that
they're passed a non-aligned pointers: ldrex/strex can't cope with such
things.
I've verified in userspace that these give the same results on LE setups
as our existing implementation - that doesn't mean these aren't buggy, it
just means they appear to behave the same for the testing I've done. BE
is completely untested (I don't have any ARM BE setups.)
Someone who uses BE setups needs to check that filesystem images (for
minix and ext2/ext3) which worked prior to this patch continue to work
after these patches.
This does need a fair amount of testing before it can be merged, so I'd
like to see a number of Tested-by's against this patch. Please also
indicate whether you tested on LE or BE or both, which filesystems, and
whether they were read-only mounted or read-write mounted.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/include/asm/bitops.h | 125 +++++++-------------------
arch/arm/kernel/armksyms.c | 33 ++-----
arch/arm/lib/bitops.h | 43 ++++++----
arch/arm/lib/changebit.S | 10 +--
arch/arm/lib/clearbit.S | 11 +--
arch/arm/lib/findbit.S | 197 ++++++++++++++--------------------------
arch/arm/lib/setbit.S | 11 +--
arch/arm/lib/testchangebit.S | 9 +--
arch/arm/lib/testclearbit.S | 9 +--
arch/arm/lib/testsetbit.S | 9 +--
10 files changed, 155 insertions(+), 302 deletions(-)
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 7b1bb2b..da813b0 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -149,90 +149,47 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
*/
/*
- * Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
+ * Assembly bitops. nr = 0 -> word 0 bit 0.
*/
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(const void * p, unsigned size);
-extern int _find_next_zero_bit_le(const void * p, int size, int offset);
-extern int _find_first_bit_le(const unsigned long *p, unsigned size);
-extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
-
-/*
- * Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
- */
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_be(const void * p, unsigned size);
-extern int _find_next_zero_bit_be(const void * p, int size, int offset);
-extern int _find_first_bit_be(const unsigned long *p, unsigned size);
-extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
+extern void _set_bit(int nr, volatile unsigned long * p);
+extern void _clear_bit(int nr, volatile unsigned long * p);
+extern void _change_bit(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit(int nr, volatile unsigned long * p);
+extern int _find_first_zero_bit(const unsigned long * p, unsigned size);
+extern int _find_next_zero_bit(const unsigned long * p, int size, int offset);
+extern int _find_first_bit(const unsigned long *p, unsigned size);
+extern int _find_next_bit(const unsigned long *p, int size, int offset);
#ifndef CONFIG_SMP
/*
* The __* form of bitops are non-atomic and may be reordered.
*/
-#define ATOMIC_BITOP_LE(name,nr,p) \
+#define ATOMIC_BITOP(name,nr,p) \
(__builtin_constant_p(nr) ? \
____atomic_##name(nr, p) : \
- _##name##_le(nr,p))
-
-#define ATOMIC_BITOP_BE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_be(nr,p))
+ _##name(nr,p))
#else
-#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
#endif
#define NONATOMIC_BITOP(name,nr,p) \
(____nonatomic_##name(nr, p))
-#ifndef __ARMEB__
/*
- * These are the little endian, atomic definitions.
+ * These are the endian-indifferent as they use word loads/stores.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
-#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
-#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
-#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)
-
-#define WORD_BITOFF_TO_LE(x) ((x))
-
-#else
-
-/*
- * These are the big endian, atomic definitions.
- */
-#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
-#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
-#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
-#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
-#define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off)
-
-#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18)
-
-#endif
+#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p)
+#define find_first_zero_bit(p,sz) _find_first_zero_bit(p,sz)
+#define find_next_zero_bit(p,sz,off) _find_next_zero_bit(p,sz,off)
+#define find_first_bit(p,sz) _find_first_bit(p,sz)
+#define find_next_bit(p,sz,off) _find_next_bit(p,sz,off)
#if __LINUX_ARM_ARCH__ < 5
@@ -302,42 +259,28 @@ static inline int fls(int x)
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/minix.h>
/*
* Ext2 is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define ext2_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit(nr, (unsigned long *)(p))
#define ext2_set_bit_atomic(lock,nr,p) \
- test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_set_bit(nr, (unsigned long *)(p))
#define ext2_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit(nr, (unsigned long *)(p))
#define ext2_clear_bit_atomic(lock,nr,p) \
- test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_clear_bit(nr, (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(nr, (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ _find_first_zero_bit((unsigned long *)(p),sz)
#define ext2_find_next_zero_bit(p,sz,off) \
- _find_next_zero_bit_le(p,sz,off)
+ _find_next_zero_bit((unsigned long *)(p),sz,off)
#define ext2_find_next_bit(p, sz, off) \
- _find_next_bit_le(p, sz, off)
-
-/*
- * Minix is defined to use little-endian byte ordering.
- * These do not need to be atomic.
- */
-#define minix_set_bit(nr,p) \
- __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ _find_next_bit((unsigned long *)(p), sz, off)
#endif /* __KERNEL__ */
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9615423..7064ef4 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -140,29 +140,16 @@ EXPORT_SYMBOL(__aeabi_ulcmp);
#endif
/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
-EXPORT_SYMBOL(_find_first_zero_bit_le);
-EXPORT_SYMBOL(_find_next_zero_bit_le);
-EXPORT_SYMBOL(_find_first_bit_le);
-EXPORT_SYMBOL(_find_next_bit_le);
-
-#ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
-EXPORT_SYMBOL(_find_first_zero_bit_be);
-EXPORT_SYMBOL(_find_next_zero_bit_be);
-EXPORT_SYMBOL(_find_first_bit_be);
-EXPORT_SYMBOL(_find_next_bit_be);
-#endif
+EXPORT_SYMBOL(_set_bit);
+EXPORT_SYMBOL(_test_and_set_bit);
+EXPORT_SYMBOL(_clear_bit);
+EXPORT_SYMBOL(_test_and_clear_bit);
+EXPORT_SYMBOL(_change_bit);
+EXPORT_SYMBOL(_test_and_change_bit);
+EXPORT_SYMBOL(_find_first_zero_bit);
+EXPORT_SYMBOL(_find_next_zero_bit);
+EXPORT_SYMBOL(_find_first_bit);
+EXPORT_SYMBOL(_find_next_bit);
#ifdef CONFIG_FUNCTION_TRACER
#ifdef CONFIG_OLD_MCOUNT
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index d422529..2a09e57 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,28 +1,34 @@
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
.macro bitop, instr
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- and r3, r0, #7 @ Get bit offset
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
\instr r2, r2, r3
- strexb r0, r2, [r1]
+ strex r0, r2, [r1]
cmp r0, #0
bne 1b
mov pc, lr
.endm
.macro testop, instr, store
- and r3, r0, #7 @ Get bit offset
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
ands r0, r2, r3 @ save old value of bit
- \instr r2, r2, r3 @ toggle bit
- strexb ip, r2, [r1]
+ \instr r2, r2, r3 @ toggle bit
+ strex ip, r2, [r1]
cmp ip, #0
bne 1b
smp_dmb
@@ -32,13 +38,16 @@
.endm
#else
.macro bitop, instr
- and r2, r0, #7
+ tst r1, #3
+ strne r1, [r1, -r1] @ 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
- ldrb r2, [r1, r0, lsr #3]
+ ldr r2, [r1, r0, lsl #2]
\instr r2, r2, r3
- strb r2, [r1, r0, lsr #3]
+ str r2, [r1, r0, lsl #2]
restore_irqs ip
mov pc, lr
.endm
@@ -52,11 +61,13 @@
* to avoid dirtying the data cache.
*/
.macro testop, instr, store
- add r1, r1, r0, lsr #3
- and r3, r0, #7
- mov r0, #1
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
+ and r3, r0, #31
+ mov r0, r0, lsr #5
save_and_disable_irqs ip
- ldrb r2, [r1]
+ ldr r2, [r1, r0, lsl #2]!
+ mov r0, #1
tst r2, r0, lsl r3
\instr r2, r2, r0, lsl r3
\store r2, [r1]
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 80f3115..68ed5b6 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -12,12 +12,6 @@
#include "bitops.h"
.text
-/* Purpose : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
bitop eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 1a63e43..4c04c3b 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
bitop bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 64f6bc1..223e92a 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -21,173 +21,114 @@
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
*/
-ENTRY(_find_first_zero_bit_le)
+ENTRY(_find_first_zero_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3f
+ beq ffz_none
mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ffz_loop:
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
+ THUMB( ldr r3, [r0, r3] )
+ mvns r3, r3 @ invert bits
+ bne .L_found0 @ any now set - found zero bit
+ffz_next: add r2, r2, #32 @ next bit pointer
+ cmp r2, r1 @ any more?
+ blo ffz_loop
+ffz_none: mov r0, r1 @ no free bits
mov pc, lr
-ENDPROC(_find_first_zero_bit_le)
+ENDPROC(_find_first_zero_bit)
/*
* Purpose : Find next 'zero' bit
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
-ENTRY(_find_next_zero_bit_le)
+ENTRY(_find_next_zero_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ beq ffz_none
+ ands ip, r2, #31
+ beq ffz_loop
+ bic r2, r2, #31
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
+ THUMB( ldr r3, [r0, r3] )
+ mvn r3, r3 @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_le)
+ bne .L_foundoff
+ b ffz_next @ loop for next bit
+ENDPROC(_find_next_zero_bit)
/*
* Purpose : Find a 'one' bit
* Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
*/
-ENTRY(_find_first_bit_le)
+ENTRY(_find_first_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3f
+ beq ffb_none
mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ffb_loop:
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
+ THUMB( ldr r3, [r0, r3] )
movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
+ bne .L_found0 @ any now set - found zero bit
+ffb_next: add r2, r2, #32 @ next bit pointer
+ cmp r2, r1 @ any more?
+ blo ffb_loop
+ffb_none: mov r0, r1 @ no free bits
mov pc, lr
-ENDPROC(_find_first_bit_le)
+ENDPROC(_find_first_bit)
/*
* Purpose : Find next 'one' bit
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
-ENTRY(_find_next_bit_le)
+ENTRY(_find_next_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ beq ffb_none
+ ands ip, r2, #31
+ beq ffb_loop @ If new word, goto old routine
+ bic r2, r2, #31
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
+ THUMB( ldr r3, [r0, r3] )
movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_bit_le)
-
-#ifdef __ARMEB__
-
-ENTRY(_find_first_zero_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- mov pc, lr
-ENDPROC(_find_first_zero_bit_be)
-
-ENTRY(_find_next_zero_bit_be)
- teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_be)
-
-ENTRY(_find_first_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- mov pc, lr
-ENDPROC(_find_first_bit_be)
-
-ENTRY(_find_next_bit_be)
- teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_bit_be)
-
-#endif
+ bne .L_foundoff
+ b ffb_loop @ loop for next bit
+ENDPROC(_find_next_bit)
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
-.L_found:
-#if __LINUX_ARM_ARCH__ >= 5
- rsb r0, r3, #0
+.L_foundoff: add r2, r2, ip @ add bit offset back in
+.L_found0: rsb r0, r3, #0
and r3, r3, r0
+#if __LINUX_ARM_ARCH__ >= 5
clz r3, r3
rsb r3, r3, #31
add r0, r2, r3
#else
- tst r3, #0x0f
- addeq r2, r2, #4
- movne r3, r3, lsl #4
- tst r3, #0x30
- addeq r2, r2, #2
- movne r3, r3, lsl #2
- tst r3, #0x40
- addeq r2, r2, #1
+ movs r0, r3, lsr #16
+ addne r2, r2, #16
+ movne r3, r0
+ movs r0, r3, lsr #8
+ addne r2, r2, #8
+ movne r3, r0
+ movs r0, r3, lsr #4
+ addne r2, r2, #4
+ movne r3, r0
+ movs r0, r3, lsr #2
+ addne r2, r2, #2
+ movne r3, r0
+ tst r3, #2
+ addne r2, r2, #1
mov r0, r2
#endif
cmp r1, r0 @ Clamp to maxbit
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 1dd7176..bbee5c6 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
bitop orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 5c98dc5..15a4d43 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
- testop eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+ testop eor, str
+ENDPROC(_test_and_change_bit)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 543d709..521b66b 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
- testop bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+ testop bicne, strne
+ENDPROC(_test_and_clear_bit)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 0b3f390..1c98cc2 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
- testop orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+ testop orreq, streq
+ENDPROC(_test_and_set_bit)
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-16 12:19 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-16 12:19 UTC (permalink / raw)
To: linux-arm-kernel
XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
I strongly suggest you ensure you have a copy of your filesystems before
trying this patch.
The patch below switches the bitops to use word loads/stores rather than
byte operations - so that we can avoid using the ldrexb/strexb instructions
which are only supported from ARMv6k and up.
The current bitops prevent a single kernel covering ARMv6 and ARMv7
architectures without the resulting kernel being unsafe on SMP. As
ldrex/strex is supported from ARMv6 upwards, but ldrexb/strexb is not,
switch these functions to use the word-based loads/stores.
As our bitops functions have been tolerant of misaligned pointers, they
now include a check which will do a NULL pointer store in the event that
they're passed a non-aligned pointers: ldrex/strex can't cope with such
things.
I've verified in userspace that these give the same results on LE setups
as our existing implementation - that doesn't mean these aren't buggy, it
just means they appear to behave the same for the testing I've done. BE
is completely untested (I don't have any ARM BE setups.)
Someone who uses BE setups needs to check that filesystem images (for
minix and ext2/ext3) which worked prior to this patch continue to work
after these patches.
This does need a fair amount of testing before it can be merged, so I'd
like to see a number of Tested-by's against this patch. Please also
indicate whether you tested on LE or BE or both, which filesystems, and
whether they were read-only mounted or read-write mounted.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/include/asm/bitops.h | 125 +++++++-------------------
arch/arm/kernel/armksyms.c | 33 ++-----
arch/arm/lib/bitops.h | 43 ++++++----
arch/arm/lib/changebit.S | 10 +--
arch/arm/lib/clearbit.S | 11 +--
arch/arm/lib/findbit.S | 197 ++++++++++++++--------------------------
arch/arm/lib/setbit.S | 11 +--
arch/arm/lib/testchangebit.S | 9 +--
arch/arm/lib/testclearbit.S | 9 +--
arch/arm/lib/testsetbit.S | 9 +--
10 files changed, 155 insertions(+), 302 deletions(-)
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 7b1bb2b..da813b0 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -149,90 +149,47 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
*/
/*
- * Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
+ * Assembly bitops. nr = 0 -> word 0 bit 0.
*/
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(const void * p, unsigned size);
-extern int _find_next_zero_bit_le(const void * p, int size, int offset);
-extern int _find_first_bit_le(const unsigned long *p, unsigned size);
-extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
-
-/*
- * Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
- */
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_be(const void * p, unsigned size);
-extern int _find_next_zero_bit_be(const void * p, int size, int offset);
-extern int _find_first_bit_be(const unsigned long *p, unsigned size);
-extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
+extern void _set_bit(int nr, volatile unsigned long * p);
+extern void _clear_bit(int nr, volatile unsigned long * p);
+extern void _change_bit(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit(int nr, volatile unsigned long * p);
+extern int _find_first_zero_bit(const unsigned long * p, unsigned size);
+extern int _find_next_zero_bit(const unsigned long * p, int size, int offset);
+extern int _find_first_bit(const unsigned long *p, unsigned size);
+extern int _find_next_bit(const unsigned long *p, int size, int offset);
#ifndef CONFIG_SMP
/*
* The __* form of bitops are non-atomic and may be reordered.
*/
-#define ATOMIC_BITOP_LE(name,nr,p) \
+#define ATOMIC_BITOP(name,nr,p) \
(__builtin_constant_p(nr) ? \
____atomic_##name(nr, p) : \
- _##name##_le(nr,p))
-
-#define ATOMIC_BITOP_BE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_be(nr,p))
+ _##name(nr,p))
#else
-#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
#endif
#define NONATOMIC_BITOP(name,nr,p) \
(____nonatomic_##name(nr, p))
-#ifndef __ARMEB__
/*
- * These are the little endian, atomic definitions.
+ * These are the endian-indifferent as they use word loads/stores.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
-#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
-#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
-#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)
-
-#define WORD_BITOFF_TO_LE(x) ((x))
-
-#else
-
-/*
- * These are the big endian, atomic definitions.
- */
-#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
-#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
-#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
-#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
-#define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off)
-
-#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18)
-
-#endif
+#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p)
+#define find_first_zero_bit(p,sz) _find_first_zero_bit(p,sz)
+#define find_next_zero_bit(p,sz,off) _find_next_zero_bit(p,sz,off)
+#define find_first_bit(p,sz) _find_first_bit(p,sz)
+#define find_next_bit(p,sz,off) _find_next_bit(p,sz,off)
#if __LINUX_ARM_ARCH__ < 5
@@ -302,42 +259,28 @@ static inline int fls(int x)
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/minix.h>
/*
* Ext2 is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define ext2_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit(nr, (unsigned long *)(p))
#define ext2_set_bit_atomic(lock,nr,p) \
- test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_set_bit(nr, (unsigned long *)(p))
#define ext2_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit(nr, (unsigned long *)(p))
#define ext2_clear_bit_atomic(lock,nr,p) \
- test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_clear_bit(nr, (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(nr, (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ _find_first_zero_bit((unsigned long *)(p),sz)
#define ext2_find_next_zero_bit(p,sz,off) \
- _find_next_zero_bit_le(p,sz,off)
+ _find_next_zero_bit((unsigned long *)(p),sz,off)
#define ext2_find_next_bit(p, sz, off) \
- _find_next_bit_le(p, sz, off)
-
-/*
- * Minix is defined to use little-endian byte ordering.
- * These do not need to be atomic.
- */
-#define minix_set_bit(nr,p) \
- __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ _find_next_bit((unsigned long *)(p), sz, off)
#endif /* __KERNEL__ */
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9615423..7064ef4 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -140,29 +140,16 @@ EXPORT_SYMBOL(__aeabi_ulcmp);
#endif
/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
-EXPORT_SYMBOL(_find_first_zero_bit_le);
-EXPORT_SYMBOL(_find_next_zero_bit_le);
-EXPORT_SYMBOL(_find_first_bit_le);
-EXPORT_SYMBOL(_find_next_bit_le);
-
-#ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
-EXPORT_SYMBOL(_find_first_zero_bit_be);
-EXPORT_SYMBOL(_find_next_zero_bit_be);
-EXPORT_SYMBOL(_find_first_bit_be);
-EXPORT_SYMBOL(_find_next_bit_be);
-#endif
+EXPORT_SYMBOL(_set_bit);
+EXPORT_SYMBOL(_test_and_set_bit);
+EXPORT_SYMBOL(_clear_bit);
+EXPORT_SYMBOL(_test_and_clear_bit);
+EXPORT_SYMBOL(_change_bit);
+EXPORT_SYMBOL(_test_and_change_bit);
+EXPORT_SYMBOL(_find_first_zero_bit);
+EXPORT_SYMBOL(_find_next_zero_bit);
+EXPORT_SYMBOL(_find_first_bit);
+EXPORT_SYMBOL(_find_next_bit);
#ifdef CONFIG_FUNCTION_TRACER
#ifdef CONFIG_OLD_MCOUNT
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index d422529..2a09e57 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,28 +1,34 @@
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
.macro bitop, instr
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- and r3, r0, #7 @ Get bit offset
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
\instr r2, r2, r3
- strexb r0, r2, [r1]
+ strex r0, r2, [r1]
cmp r0, #0
bne 1b
mov pc, lr
.endm
.macro testop, instr, store
- and r3, r0, #7 @ Get bit offset
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
ands r0, r2, r3 @ save old value of bit
- \instr r2, r2, r3 @ toggle bit
- strexb ip, r2, [r1]
+ \instr r2, r2, r3 @ toggle bit
+ strex ip, r2, [r1]
cmp ip, #0
bne 1b
smp_dmb
@@ -32,13 +38,16 @@
.endm
#else
.macro bitop, instr
- and r2, r0, #7
+ tst r1, #3
+ strne r1, [r1, -r1] @ 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
- ldrb r2, [r1, r0, lsr #3]
+ ldr r2, [r1, r0, lsl #2]
\instr r2, r2, r3
- strb r2, [r1, r0, lsr #3]
+ str r2, [r1, r0, lsl #2]
restore_irqs ip
mov pc, lr
.endm
@@ -52,11 +61,13 @@
* to avoid dirtying the data cache.
*/
.macro testop, instr, store
- add r1, r1, r0, lsr #3
- and r3, r0, #7
- mov r0, #1
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
+ and r3, r0, #31
+ mov r0, r0, lsr #5
save_and_disable_irqs ip
- ldrb r2, [r1]
+ ldr r2, [r1, r0, lsl #2]!
+ mov r0, #1
tst r2, r0, lsl r3
\instr r2, r2, r0, lsl r3
\store r2, [r1]
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 80f3115..68ed5b6 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -12,12 +12,6 @@
#include "bitops.h"
.text
-/* Purpose : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
bitop eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 1a63e43..4c04c3b 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
bitop bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 64f6bc1..223e92a 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -21,173 +21,114 @@
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
*/
-ENTRY(_find_first_zero_bit_le)
+ENTRY(_find_first_zero_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3f
+ beq ffz_none
mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ffz_loop:
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
+ THUMB( ldr r3, [r0, r3] )
+ mvns r3, r3 @ invert bits
+ bne .L_found0 @ any now set - found zero bit
+ffz_next: add r2, r2, #32 @ next bit pointer
+ cmp r2, r1 @ any more?
+ blo ffz_loop
+ffz_none: mov r0, r1 @ no free bits
mov pc, lr
-ENDPROC(_find_first_zero_bit_le)
+ENDPROC(_find_first_zero_bit)
/*
* Purpose : Find next 'zero' bit
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
-ENTRY(_find_next_zero_bit_le)
+ENTRY(_find_next_zero_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ beq ffz_none
+ ands ip, r2, #31
+ beq ffz_loop
+ bic r2, r2, #31
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
+ THUMB( ldr r3, [r0, r3] )
+ mvn r3, r3 @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_le)
+ bne .L_foundoff
+ b ffz_next @ loop for next bit
+ENDPROC(_find_next_zero_bit)
/*
* Purpose : Find a 'one' bit
* Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
*/
-ENTRY(_find_first_bit_le)
+ENTRY(_find_first_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3f
+ beq ffb_none
mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ffb_loop:
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
+ THUMB( ldr r3, [r0, r3] )
movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
+ bne .L_found0 @ any now set - found zero bit
+ffb_next: add r2, r2, #32 @ next bit pointer
+ cmp r2, r1 @ any more?
+ blo ffb_loop
+ffb_none: mov r0, r1 @ no free bits
mov pc, lr
-ENDPROC(_find_first_bit_le)
+ENDPROC(_find_first_bit)
/*
* Purpose : Find next 'one' bit
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
-ENTRY(_find_next_bit_le)
+ENTRY(_find_next_bit)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word aligned
teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
+ beq ffb_none
+ ands ip, r2, #31
+ beq ffb_loop @ If new word, goto old routine
+ bic r2, r2, #31
+ ARM( ldr r3, [r0, r2, lsr #3] )
THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
+ THUMB( ldr r3, [r0, r3] )
movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_bit_le)
-
-#ifdef __ARMEB__
-
-ENTRY(_find_first_zero_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- mov pc, lr
-ENDPROC(_find_first_zero_bit_be)
-
-ENTRY(_find_next_zero_bit_be)
- teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_be)
-
-ENTRY(_find_first_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- mov pc, lr
-ENDPROC(_find_first_bit_be)
-
-ENTRY(_find_next_bit_be)
- teq r1, #0
- beq 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_bit_be)
-
-#endif
+ bne .L_foundoff
+ b ffb_loop @ loop for next bit
+ENDPROC(_find_next_bit)
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
-.L_found:
-#if __LINUX_ARM_ARCH__ >= 5
- rsb r0, r3, #0
+.L_foundoff: add r2, r2, ip @ add bit offset back in
+.L_found0: rsb r0, r3, #0
and r3, r3, r0
+#if __LINUX_ARM_ARCH__ >= 5
clz r3, r3
rsb r3, r3, #31
add r0, r2, r3
#else
- tst r3, #0x0f
- addeq r2, r2, #4
- movne r3, r3, lsl #4
- tst r3, #0x30
- addeq r2, r2, #2
- movne r3, r3, lsl #2
- tst r3, #0x40
- addeq r2, r2, #1
+ movs r0, r3, lsr #16
+ addne r2, r2, #16
+ movne r3, r0
+ movs r0, r3, lsr #8
+ addne r2, r2, #8
+ movne r3, r0
+ movs r0, r3, lsr #4
+ addne r2, r2, #4
+ movne r3, r0
+ movs r0, r3, lsr #2
+ addne r2, r2, #2
+ movne r3, r0
+ tst r3, #2
+ addne r2, r2, #1
mov r0, r2
#endif
cmp r1, r0 @ Clamp to maxbit
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 1dd7176..bbee5c6 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
bitop orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 5c98dc5..15a4d43 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
- testop eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+ testop eor, str
+ENDPROC(_test_and_change_bit)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 543d709..521b66b 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
- testop bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+ testop bicne, strne
+ENDPROC(_test_and_clear_bit)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 0b3f390..1c98cc2 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
- testop orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+ testop orreq, streq
+ENDPROC(_test_and_set_bit)
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-16 12:19 ` Russell King - ARM Linux
@ 2011-01-16 18:15 ` Russell King - ARM Linux
-1 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-16 18:15 UTC (permalink / raw)
To: linux-arm-kernel, linux-omap
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
> I strongly suggest you ensure you have a copy of your filesystems before
> trying this patch.
>
> The patch below switches the bitops to use word loads/stores rather than
> byte operations - so that we can avoid using the ldrexb/strexb instructions
> which are only supported from ARMv6k and up.
>
> The current bitops prevent a single kernel covering ARMv6 and ARMv7
> architectures without the resulting kernel being unsafe on SMP. As
> ldrex/strex is supported from ARMv6 upwards, but ldrexb/strexb is not,
> switch these functions to use the word-based loads/stores.
>
> As our bitops functions have been tolerant of misaligned pointers, they
> now include a check which will do a NULL pointer store in the event that
> they're passed a non-aligned pointers: ldrex/strex can't cope with such
> things.
>
> I've verified in userspace that these give the same results on LE setups
> as our existing implementation - that doesn't mean these aren't buggy, it
> just means they appear to behave the same for the testing I've done. BE
> is completely untested (I don't have any ARM BE setups.)
>
> Someone who uses BE setups needs to check that filesystem images (for
> minix and ext2/ext3) which worked prior to this patch continue to work
> after these patches.
>
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Revised patch - the previous one was slightly buggered for BE. We also
don't need to touch the findbit operations at all, so that part has been
dropped.
This includes a patch by Akinobu Mita ("arm: introduce little-endian
bitops", v4).
arch/arm/include/asm/bitops.h | 114 +++++++++++++++++++++--------------------
arch/arm/kernel/armksyms.c | 18 ++----
arch/arm/lib/bitops.h | 46 ++++++++++-------
arch/arm/lib/changebit.S | 10 +---
arch/arm/lib/clearbit.S | 11 +---
arch/arm/lib/findbit.S | 16 ++++++
arch/arm/lib/setbit.S | 11 +---
arch/arm/lib/testchangebit.S | 9 +--
arch/arm/lib/testclearbit.S | 9 +--
arch/arm/lib/testsetbit.S | 9 +--
10 files changed, 124 insertions(+), 129 deletions(-)
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 338ff19..1e8c366 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -149,30 +149,28 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
*/
/*
+ * Native endian assembly bitops. nr = 0 -> word 0 bit 0.
+ */
+extern void _set_bit(int nr, volatile unsigned long * p);
+extern void _clear_bit(int nr, volatile unsigned long * p);
+extern void _change_bit(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit(int nr, volatile unsigned long * p);
+
+/*
* Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
*/
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(const void * p, unsigned size);
-extern int _find_next_zero_bit_le(const void * p, int size, int offset);
+extern int _find_first_zero_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_le(const unsigned long *p, int size, int offset);
extern int _find_first_bit_le(const unsigned long *p, unsigned size);
extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
/*
* Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
*/
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_be(const void * p, unsigned size);
-extern int _find_next_zero_bit_be(const void * p, int size, int offset);
+extern int _find_first_zero_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_be(const unsigned long *p, int size, int offset);
extern int _find_first_bit_be(const unsigned long *p, unsigned size);
extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
@@ -180,33 +178,26 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
/*
* The __* form of bitops are non-atomic and may be reordered.
*/
-#define ATOMIC_BITOP_LE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_le(nr,p))
-
-#define ATOMIC_BITOP_BE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_be(nr,p))
+#define ATOMIC_BITOP(name,nr,p) \
+ (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
#else
-#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
#endif
-#define NONATOMIC_BITOP(name,nr,p) \
- (____nonatomic_##name(nr, p))
+/*
+ * Native endian atomic definitions.
+ */
+#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p)
#ifndef __ARMEB__
/*
* These are the little endian, atomic definitions.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
@@ -215,16 +206,9 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#define WORD_BITOFF_TO_LE(x) ((x))
#else
-
/*
* These are the big endian, atomic definitions.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
@@ -303,41 +287,61 @@ static inline int fls(int x)
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
+#define __set_bit_le(nr, p) \
+ __set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __clear_bit_le(nr, p) \
+ __clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __test_and_set_bit_le(nr, p) \
+ __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_and_set_bit_le(nr, p) \
+ test_and_set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __test_and_clear_bit_le(nr, p) \
+ __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_and_clear_bit_le(nr, p) \
+ test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_bit_le(nr, p) \
+ test_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define find_first_zero_bit_le(p, sz) \
+ _find_first_zero_bit_le(p, sz)
+#define find_next_zero_bit_le(p, sz, off) \
+ _find_next_zero_bit_le(p, sz, off)
+#define find_next_bit_le(p, sz, off) \
+ _find_next_bit_le(p, sz, off)
/*
* Ext2 is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define ext2_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit_le(nr, (unsigned long *)(p))
#define ext2_set_bit_atomic(lock,nr,p) \
- test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_set_bit_le(nr, (unsigned long *)(p))
#define ext2_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit_le(nr, (unsigned long *)(p))
#define ext2_clear_bit_atomic(lock,nr,p) \
- test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_clear_bit_le(nr, (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit_le(nr, (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ find_first_zero_bit_le((unsigned long *)(p), sz)
#define ext2_find_next_zero_bit(p,sz,off) \
- _find_next_zero_bit_le(p,sz,off)
+ find_next_zero_bit_le((unsigned long *)(p), sz, off)
#define ext2_find_next_bit(p, sz, off) \
- _find_next_bit_le(p, sz, off)
+ find_next_bit_le((unsigned long *)(p), sz, off)
/*
* Minix is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define minix_set_bit(nr,p) \
- __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __set_bit_le(nr, (unsigned long *)(p))
#define minix_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit_le(nr, (unsigned long *)(p))
#define minix_test_and_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit_le(nr, (unsigned long *)(p))
#define minix_test_and_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit_le(nr, (unsigned long *)(p))
#define minix_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ find_first_zero_bit_le((unsigned long *)(p), sz)
#endif /* __KERNEL__ */
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index e5e1e53..d5d4185 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -140,24 +140,18 @@ EXPORT_SYMBOL(__aeabi_ulcmp);
#endif
/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
+EXPORT_SYMBOL(_set_bit);
+EXPORT_SYMBOL(_test_and_set_bit);
+EXPORT_SYMBOL(_clear_bit);
+EXPORT_SYMBOL(_test_and_clear_bit);
+EXPORT_SYMBOL(_change_bit);
+EXPORT_SYMBOL(_test_and_change_bit);
EXPORT_SYMBOL(_find_first_zero_bit_le);
EXPORT_SYMBOL(_find_next_zero_bit_le);
EXPORT_SYMBOL(_find_first_bit_le);
EXPORT_SYMBOL(_find_next_bit_le);
#ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
EXPORT_SYMBOL(_find_first_zero_bit_be);
EXPORT_SYMBOL(_find_next_zero_bit_be);
EXPORT_SYMBOL(_find_first_bit_be);
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index d422529..f8a2bd3 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,28 +1,33 @@
-
-#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
+#if __LINUX_ARM_ARCH__ >= 6
.macro bitop, instr
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- and r3, r0, #7 @ Get bit offset
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
\instr r2, r2, r3
- strexb r0, r2, [r1]
+ strex r0, r2, [r1]
cmp r0, #0
bne 1b
mov pc, lr
.endm
.macro testop, instr, store
- and r3, r0, #7 @ Get bit offset
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
ands r0, r2, r3 @ save old value of bit
- \instr r2, r2, r3 @ toggle bit
- strexb ip, r2, [r1]
+ \instr r2, r2, r3 @ toggle bit
+ strex ip, r2, [r1]
cmp ip, #0
bne 1b
smp_dmb
@@ -32,13 +37,16 @@
.endm
#else
.macro bitop, instr
- and r2, r0, #7
+ tst r1, #3
+ strne r1, [r1, -r1] @ 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
- ldrb r2, [r1, r0, lsr #3]
+ ldr r2, [r1, r0, lsl #2]
\instr r2, r2, r3
- strb r2, [r1, r0, lsr #3]
+ str r2, [r1, r0, lsl #2]
restore_irqs ip
mov pc, lr
.endm
@@ -52,11 +60,13 @@
* to avoid dirtying the data cache.
*/
.macro testop, instr, store
- add r1, r1, r0, lsr #3
- and r3, r0, #7
- mov r0, #1
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
+ and r3, r0, #31
+ mov r0, r0, lsr #5
save_and_disable_irqs ip
- ldrb r2, [r1]
+ ldr r2, [r1, r0, lsl #2]!
+ mov r0, #1
tst r2, r0, lsl r3
\instr r2, r2, r0, lsl r3
\store r2, [r1]
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 80f3115..68ed5b6 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -12,12 +12,6 @@
#include "bitops.h"
.text
-/* Purpose : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
bitop eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 1a63e43..4c04c3b 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
bitop bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 64f6bc1..7edd605 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -22,6 +22,8 @@
* Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
*/
ENTRY(_find_first_zero_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -43,6 +45,8 @@ ENDPROC(_find_first_zero_bit_le)
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
ENTRY(_find_next_zero_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -63,6 +67,8 @@ ENDPROC(_find_next_zero_bit_le)
* Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
*/
ENTRY(_find_first_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -84,6 +90,8 @@ ENDPROC(_find_first_bit_le)
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
ENTRY(_find_next_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -101,6 +109,8 @@ ENDPROC(_find_next_bit_le)
#ifdef __ARMEB__
ENTRY(_find_first_zero_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -118,6 +128,8 @@ ENTRY(_find_first_zero_bit_be)
ENDPROC(_find_first_zero_bit_be)
ENTRY(_find_next_zero_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -135,6 +147,8 @@ ENTRY(_find_next_zero_bit_be)
ENDPROC(_find_next_zero_bit_be)
ENTRY(_find_first_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -152,6 +166,8 @@ ENTRY(_find_first_bit_be)
ENDPROC(_find_first_bit_be)
ENTRY(_find_next_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 1dd7176..bbee5c6 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
bitop orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 5c98dc5..15a4d43 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
- testop eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+ testop eor, str
+ENDPROC(_test_and_change_bit)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 543d709..521b66b 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
- testop bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+ testop bicne, strne
+ENDPROC(_test_and_clear_bit)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 0b3f390..1c98cc2 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
- testop orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+ testop orreq, streq
+ENDPROC(_test_and_set_bit)
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-16 18:15 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-16 18:15 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
> I strongly suggest you ensure you have a copy of your filesystems before
> trying this patch.
>
> The patch below switches the bitops to use word loads/stores rather than
> byte operations - so that we can avoid using the ldrexb/strexb instructions
> which are only supported from ARMv6k and up.
>
> The current bitops prevent a single kernel covering ARMv6 and ARMv7
> architectures without the resulting kernel being unsafe on SMP. As
> ldrex/strex is supported from ARMv6 upwards, but ldrexb/strexb is not,
> switch these functions to use the word-based loads/stores.
>
> As our bitops functions have been tolerant of misaligned pointers, they
> now include a check which will do a NULL pointer store in the event that
> they're passed a non-aligned pointers: ldrex/strex can't cope with such
> things.
>
> I've verified in userspace that these give the same results on LE setups
> as our existing implementation - that doesn't mean these aren't buggy, it
> just means they appear to behave the same for the testing I've done. BE
> is completely untested (I don't have any ARM BE setups.)
>
> Someone who uses BE setups needs to check that filesystem images (for
> minix and ext2/ext3) which worked prior to this patch continue to work
> after these patches.
>
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Revised patch - the previous one was slightly buggered for BE. We also
don't need to touch the findbit operations at all, so that part has been
dropped.
This includes a patch by Akinobu Mita ("arm: introduce little-endian
bitops", v4).
arch/arm/include/asm/bitops.h | 114 +++++++++++++++++++++--------------------
arch/arm/kernel/armksyms.c | 18 ++----
arch/arm/lib/bitops.h | 46 ++++++++++-------
arch/arm/lib/changebit.S | 10 +---
arch/arm/lib/clearbit.S | 11 +---
arch/arm/lib/findbit.S | 16 ++++++
arch/arm/lib/setbit.S | 11 +---
arch/arm/lib/testchangebit.S | 9 +--
arch/arm/lib/testclearbit.S | 9 +--
arch/arm/lib/testsetbit.S | 9 +--
10 files changed, 124 insertions(+), 129 deletions(-)
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 338ff19..1e8c366 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -149,30 +149,28 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
*/
/*
+ * Native endian assembly bitops. nr = 0 -> word 0 bit 0.
+ */
+extern void _set_bit(int nr, volatile unsigned long * p);
+extern void _clear_bit(int nr, volatile unsigned long * p);
+extern void _change_bit(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit(int nr, volatile unsigned long * p);
+
+/*
* Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
*/
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(const void * p, unsigned size);
-extern int _find_next_zero_bit_le(const void * p, int size, int offset);
+extern int _find_first_zero_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_le(const unsigned long *p, int size, int offset);
extern int _find_first_bit_le(const unsigned long *p, unsigned size);
extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
/*
* Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
*/
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_be(const void * p, unsigned size);
-extern int _find_next_zero_bit_be(const void * p, int size, int offset);
+extern int _find_first_zero_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_be(const unsigned long *p, int size, int offset);
extern int _find_first_bit_be(const unsigned long *p, unsigned size);
extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
@@ -180,33 +178,26 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
/*
* The __* form of bitops are non-atomic and may be reordered.
*/
-#define ATOMIC_BITOP_LE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_le(nr,p))
-
-#define ATOMIC_BITOP_BE(name,nr,p) \
- (__builtin_constant_p(nr) ? \
- ____atomic_##name(nr, p) : \
- _##name##_be(nr,p))
+#define ATOMIC_BITOP(name,nr,p) \
+ (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
#else
-#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
#endif
-#define NONATOMIC_BITOP(name,nr,p) \
- (____nonatomic_##name(nr, p))
+/*
+ * Native endian atomic definitions.
+ */
+#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p)
#ifndef __ARMEB__
/*
* These are the little endian, atomic definitions.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
@@ -215,16 +206,9 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#define WORD_BITOFF_TO_LE(x) ((x))
#else
-
/*
* These are the big endian, atomic definitions.
*/
-#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
@@ -303,41 +287,61 @@ static inline int fls(int x)
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
+#define __set_bit_le(nr, p) \
+ __set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __clear_bit_le(nr, p) \
+ __clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __test_and_set_bit_le(nr, p) \
+ __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_and_set_bit_le(nr, p) \
+ test_and_set_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define __test_and_clear_bit_le(nr, p) \
+ __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_and_clear_bit_le(nr, p) \
+ test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define test_bit_le(nr, p) \
+ test_bit(WORD_BITOFF_TO_LE(nr), (p))
+#define find_first_zero_bit_le(p, sz) \
+ _find_first_zero_bit_le(p, sz)
+#define find_next_zero_bit_le(p, sz, off) \
+ _find_next_zero_bit_le(p, sz, off)
+#define find_next_bit_le(p, sz, off) \
+ _find_next_bit_le(p, sz, off)
/*
* Ext2 is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define ext2_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit_le(nr, (unsigned long *)(p))
#define ext2_set_bit_atomic(lock,nr,p) \
- test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_set_bit_le(nr, (unsigned long *)(p))
#define ext2_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit_le(nr, (unsigned long *)(p))
#define ext2_clear_bit_atomic(lock,nr,p) \
- test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_and_clear_bit_le(nr, (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit_le(nr, (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ find_first_zero_bit_le((unsigned long *)(p), sz)
#define ext2_find_next_zero_bit(p,sz,off) \
- _find_next_zero_bit_le(p,sz,off)
+ find_next_zero_bit_le((unsigned long *)(p), sz, off)
#define ext2_find_next_bit(p, sz, off) \
- _find_next_bit_le(p, sz, off)
+ find_next_bit_le((unsigned long *)(p), sz, off)
/*
* Minix is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
#define minix_set_bit(nr,p) \
- __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __set_bit_le(nr, (unsigned long *)(p))
#define minix_test_bit(nr,p) \
- test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit_le(nr, (unsigned long *)(p))
#define minix_test_and_set_bit(nr,p) \
- __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_set_bit_le(nr, (unsigned long *)(p))
#define minix_test_and_clear_bit(nr,p) \
- __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ __test_and_clear_bit_le(nr, (unsigned long *)(p))
#define minix_find_first_zero_bit(p,sz) \
- _find_first_zero_bit_le(p,sz)
+ find_first_zero_bit_le((unsigned long *)(p), sz)
#endif /* __KERNEL__ */
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index e5e1e53..d5d4185 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -140,24 +140,18 @@ EXPORT_SYMBOL(__aeabi_ulcmp);
#endif
/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
+EXPORT_SYMBOL(_set_bit);
+EXPORT_SYMBOL(_test_and_set_bit);
+EXPORT_SYMBOL(_clear_bit);
+EXPORT_SYMBOL(_test_and_clear_bit);
+EXPORT_SYMBOL(_change_bit);
+EXPORT_SYMBOL(_test_and_change_bit);
EXPORT_SYMBOL(_find_first_zero_bit_le);
EXPORT_SYMBOL(_find_next_zero_bit_le);
EXPORT_SYMBOL(_find_first_bit_le);
EXPORT_SYMBOL(_find_next_bit_le);
#ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
EXPORT_SYMBOL(_find_first_zero_bit_be);
EXPORT_SYMBOL(_find_next_zero_bit_be);
EXPORT_SYMBOL(_find_first_bit_be);
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index d422529..f8a2bd3 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,28 +1,33 @@
-
-#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
+#if __LINUX_ARM_ARCH__ >= 6
.macro bitop, instr
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- and r3, r0, #7 @ Get bit offset
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
\instr r2, r2, r3
- strexb r0, r2, [r1]
+ strex r0, r2, [r1]
cmp r0, #0
bne 1b
mov pc, lr
.endm
.macro testop, instr, store
- and r3, r0, #7 @ Get bit offset
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
mov r2, #1
- add r1, r1, r0, lsr #3 @ Get byte offset
+ 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
-1: ldrexb r2, [r1]
+1: ldrex r2, [r1]
ands r0, r2, r3 @ save old value of bit
- \instr r2, r2, r3 @ toggle bit
- strexb ip, r2, [r1]
+ \instr r2, r2, r3 @ toggle bit
+ strex ip, r2, [r1]
cmp ip, #0
bne 1b
smp_dmb
@@ -32,13 +37,16 @@
.endm
#else
.macro bitop, instr
- and r2, r0, #7
+ tst r1, #3
+ strne r1, [r1, -r1] @ 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
- ldrb r2, [r1, r0, lsr #3]
+ ldr r2, [r1, r0, lsl #2]
\instr r2, r2, r3
- strb r2, [r1, r0, lsr #3]
+ str r2, [r1, r0, lsl #2]
restore_irqs ip
mov pc, lr
.endm
@@ -52,11 +60,13 @@
* to avoid dirtying the data cache.
*/
.macro testop, instr, store
- add r1, r1, r0, lsr #3
- and r3, r0, #7
- mov r0, #1
+ tst r1, #3
+ strne r1, [r1, -r1] @ assert word-aligned
+ and r3, r0, #31
+ mov r0, r0, lsr #5
save_and_disable_irqs ip
- ldrb r2, [r1]
+ ldr r2, [r1, r0, lsl #2]!
+ mov r0, #1
tst r2, r0, lsl r3
\instr r2, r2, r0, lsl r3
\store r2, [r1]
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 80f3115..68ed5b6 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -12,12 +12,6 @@
#include "bitops.h"
.text
-/* Purpose : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
bitop eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 1a63e43..4c04c3b 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
bitop bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 64f6bc1..7edd605 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -22,6 +22,8 @@
* Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
*/
ENTRY(_find_first_zero_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -43,6 +45,8 @@ ENDPROC(_find_first_zero_bit_le)
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
ENTRY(_find_next_zero_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -63,6 +67,8 @@ ENDPROC(_find_next_zero_bit_le)
* Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
*/
ENTRY(_find_first_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -84,6 +90,8 @@ ENDPROC(_find_first_bit_le)
* Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
ENTRY(_find_next_bit_le)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -101,6 +109,8 @@ ENDPROC(_find_next_bit_le)
#ifdef __ARMEB__
ENTRY(_find_first_zero_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -118,6 +128,8 @@ ENTRY(_find_first_zero_bit_be)
ENDPROC(_find_first_zero_bit_be)
ENTRY(_find_next_zero_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
@@ -135,6 +147,8 @@ ENTRY(_find_next_zero_bit_be)
ENDPROC(_find_next_zero_bit_be)
ENTRY(_find_first_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3f
mov r2, #0
@@ -152,6 +166,8 @@ ENTRY(_find_first_bit_be)
ENDPROC(_find_first_bit_be)
ENTRY(_find_next_bit_be)
+ tst r0, #3
+ strne r0, [r0, -r0] @ assert word-aligned
teq r1, #0
beq 3b
ands ip, r2, #7
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 1dd7176..bbee5c6 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -12,13 +12,6 @@
#include "bitops.h"
.text
-/*
- * Purpose : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
bitop orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 5c98dc5..15a4d43 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_change_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
- testop eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+ testop eor, str
+ENDPROC(_test_and_change_bit)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 543d709..521b66b 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_clear_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
- testop bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+ testop bicne, strne
+ENDPROC(_test_and_clear_bit)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 0b3f390..1c98cc2 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -12,9 +12,6 @@
#include "bitops.h"
.text
-ENTRY(_test_and_set_bit_be)
- eor r0, r0, #0x18 @ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
- testop orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+ testop orreq, streq
+ENDPROC(_test_and_set_bit)
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-16 12:19 ` Russell King - ARM Linux
@ 2011-01-17 9:46 ` Jamie Iles
-1 siblings, 0 replies; 20+ messages in thread
From: Jamie Iles @ 2011-01-17 9:46 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
> I strongly suggest you ensure you have a copy of your filesystems before
> trying this patch.
>
> The patch below switches the bitops to use word loads/stores rather than
> byte operations - so that we can avoid using the ldrexb/strexb instructions
> which are only supported from ARMv6k and up.
[...]
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
Hi Russell,
I've tested these on my picoxcell board (ARMv6K UP LE) with UBIFS, JFFS2
and NFS all mounted rw and haven't seen any problems. Our platforms
aren't particulary FS intensive so I'll keep these patches applied to
give them a bit more time.
Tested-by: Jamie Iles <jamie@jamieiles.com>
Jamie
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-17 9:46 ` Jamie Iles
0 siblings, 0 replies; 20+ messages in thread
From: Jamie Iles @ 2011-01-17 9:46 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> XXX WARNING: bitops are used heavily by filesystem code: there be dragons XXX
> I strongly suggest you ensure you have a copy of your filesystems before
> trying this patch.
>
> The patch below switches the bitops to use word loads/stores rather than
> byte operations - so that we can avoid using the ldrexb/strexb instructions
> which are only supported from ARMv6k and up.
[...]
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
Hi Russell,
I've tested these on my picoxcell board (ARMv6K UP LE) with UBIFS, JFFS2
and NFS all mounted rw and haven't seen any problems. Our platforms
aren't particulary FS intensive so I'll keep these patches applied to
give them a bit more time.
Tested-by: Jamie Iles <jamie@jamieiles.com>
Jamie
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-16 12:19 ` Russell King - ARM Linux
@ 2011-01-17 10:08 ` Uwe Kleine-König
-1 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-17 10:08 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap
Hello Russell,
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
You could make life a bit easier (at least for us at Pengutronix,
probably more) if you had a branch with a defined name for patches like
these. We could add that to our daily test then.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-17 10:08 ` Uwe Kleine-König
0 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-17 10:08 UTC (permalink / raw)
To: linux-arm-kernel
Hello Russell,
On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> This does need a fair amount of testing before it can be merged, so I'd
> like to see a number of Tested-by's against this patch. Please also
> indicate whether you tested on LE or BE or both, which filesystems, and
> whether they were read-only mounted or read-write mounted.
You could make life a bit easier (at least for us at Pengutronix,
probably more) if you had a branch with a defined name for patches like
these. We could add that to our daily test then.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-17 10:08 ` Uwe Kleine-König
@ 2011-01-17 10:46 ` Russell King - ARM Linux
-1 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-17 10:46 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: linux-arm-kernel, linux-omap
On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-König wrote:
> Hello Russell,
>
> On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > This does need a fair amount of testing before it can be merged, so I'd
> > like to see a number of Tested-by's against this patch. Please also
> > indicate whether you tested on LE or BE or both, which filesystems, and
> > whether they were read-only mounted or read-write mounted.
> You could make life a bit easier (at least for us at Pengutronix,
> probably more) if you had a branch with a defined name for patches like
> these. We could add that to our daily test then.
No, because then it's not possible to properly tie down what has been
tested and what hasn't.
The advantage of emailed patches is that when people reply to them, you
have a better idea that the patch to which they're replying to is the
one they tested.
Such as in this case where the follow-up patch hasn't received any
replies, and so I can't add the one received tested-by to the follow-up
patch. With the git approach, I wouldn't know what was tested unless
you included the commit IDs each time.
And let's face it - if it was tested daily, are you going to go through
the hastle of digging out the commit IDs and emailing each day to say
what was tested? That sounds to me like a _lot_ more work than testing
the occasional emailed patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-17 10:46 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-17 10:46 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-K?nig wrote:
> Hello Russell,
>
> On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > This does need a fair amount of testing before it can be merged, so I'd
> > like to see a number of Tested-by's against this patch. Please also
> > indicate whether you tested on LE or BE or both, which filesystems, and
> > whether they were read-only mounted or read-write mounted.
> You could make life a bit easier (at least for us at Pengutronix,
> probably more) if you had a branch with a defined name for patches like
> these. We could add that to our daily test then.
No, because then it's not possible to properly tie down what has been
tested and what hasn't.
The advantage of emailed patches is that when people reply to them, you
have a better idea that the patch to which they're replying to is the
one they tested.
Such as in this case where the follow-up patch hasn't received any
replies, and so I can't add the one received tested-by to the follow-up
patch. With the git approach, I wouldn't know what was tested unless
you included the commit IDs each time.
And let's face it - if it was tested daily, are you going to go through
the hastle of digging out the commit IDs and emailing each day to say
what was tested? That sounds to me like a _lot_ more work than testing
the occasional emailed patch.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-16 18:15 ` Russell King - ARM Linux
@ 2011-01-17 11:03 ` Jamie Iles
-1 siblings, 0 replies; 20+ messages in thread
From: Jamie Iles @ 2011-01-17 11:03 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap
On Sun, Jan 16, 2011 at 06:15:51PM +0000, Russell King - ARM Linux wrote:
> Revised patch - the previous one was slightly buggered for BE. We also
> don't need to touch the findbit operations at all, so that part has been
> dropped.
>
> This includes a patch by Akinobu Mita ("arm: introduce little-endian
> bitops", v4).
Oops, I hit reply to the wrong patch before. Sorry!
Tested-by: Jamie Iles <jamie@jamieiles.com>
Jamie
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-17 11:03 ` Jamie Iles
0 siblings, 0 replies; 20+ messages in thread
From: Jamie Iles @ 2011-01-17 11:03 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Jan 16, 2011 at 06:15:51PM +0000, Russell King - ARM Linux wrote:
> Revised patch - the previous one was slightly buggered for BE. We also
> don't need to touch the findbit operations at all, so that part has been
> dropped.
>
> This includes a patch by Akinobu Mita ("arm: introduce little-endian
> bitops", v4).
Oops, I hit reply to the wrong patch before. Sorry!
Tested-by: Jamie Iles <jamie@jamieiles.com>
Jamie
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-17 10:46 ` Russell King - ARM Linux
@ 2011-01-18 15:32 ` Uwe Kleine-König
-1 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-18 15:32 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap
Hi Russell,
On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-König wrote:
> > On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > > This does need a fair amount of testing before it can be merged, so I'd
> > > like to see a number of Tested-by's against this patch. Please also
> > > indicate whether you tested on LE or BE or both, which filesystems, and
> > > whether they were read-only mounted or read-write mounted.
> > You could make life a bit easier (at least for us at Pengutronix,
> > probably more) if you had a branch with a defined name for patches like
> > these. We could add that to our daily test then.
>
> No, because then it's not possible to properly tie down what has been
> tested and what hasn't.
>
> The advantage of emailed patches is that when people reply to them, you
> have a better idea that the patch to which they're replying to is the
> one they tested.
>
> Such as in this case where the follow-up patch hasn't received any
> replies, and so I can't add the one received tested-by to the follow-up
> patch. With the git approach, I wouldn't know what was tested unless
> you included the commit IDs each time.
>
> And let's face it - if it was tested daily, are you going to go through
> the hastle of digging out the commit IDs and emailing each day to say
> what was tested? That sounds to me like a _lot_ more work than testing
> the occasional emailed patch.
I maybe wouldn't report each success, I would report if my test fails.
You can consider this more or less valuable. Still I think given the
ease this could be done it's worth it.
That's how linux-next works, too.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-18 15:32 ` Uwe Kleine-König
0 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-18 15:32 UTC (permalink / raw)
To: linux-arm-kernel
Hi Russell,
On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-K?nig wrote:
> > On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > > This does need a fair amount of testing before it can be merged, so I'd
> > > like to see a number of Tested-by's against this patch. Please also
> > > indicate whether you tested on LE or BE or both, which filesystems, and
> > > whether they were read-only mounted or read-write mounted.
> > You could make life a bit easier (at least for us at Pengutronix,
> > probably more) if you had a branch with a defined name for patches like
> > these. We could add that to our daily test then.
>
> No, because then it's not possible to properly tie down what has been
> tested and what hasn't.
>
> The advantage of emailed patches is that when people reply to them, you
> have a better idea that the patch to which they're replying to is the
> one they tested.
>
> Such as in this case where the follow-up patch hasn't received any
> replies, and so I can't add the one received tested-by to the follow-up
> patch. With the git approach, I wouldn't know what was tested unless
> you included the commit IDs each time.
>
> And let's face it - if it was tested daily, are you going to go through
> the hastle of digging out the commit IDs and emailing each day to say
> what was tested? That sounds to me like a _lot_ more work than testing
> the occasional emailed patch.
I maybe wouldn't report each success, I would report if my test fails.
You can consider this more or less valuable. Still I think given the
ease this could be done it's worth it.
That's how linux-next works, too.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-18 15:32 ` Uwe Kleine-König
@ 2011-01-18 15:43 ` Russell King - ARM Linux
-1 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-18 15:43 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: linux-arm-kernel, linux-omap
On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-König wrote:
> Hi Russell,
>
> On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> > On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-König wrote:
> > > On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > > > This does need a fair amount of testing before it can be merged, so I'd
> > > > like to see a number of Tested-by's against this patch. Please also
> > > > indicate whether you tested on LE or BE or both, which filesystems, and
> > > > whether they were read-only mounted or read-write mounted.
> > > You could make life a bit easier (at least for us at Pengutronix,
> > > probably more) if you had a branch with a defined name for patches like
> > > these. We could add that to our daily test then.
> >
> > No, because then it's not possible to properly tie down what has been
> > tested and what hasn't.
> >
> > The advantage of emailed patches is that when people reply to them, you
> > have a better idea that the patch to which they're replying to is the
> > one they tested.
> >
> > Such as in this case where the follow-up patch hasn't received any
> > replies, and so I can't add the one received tested-by to the follow-up
> > patch. With the git approach, I wouldn't know what was tested unless
> > you included the commit IDs each time.
> >
> > And let's face it - if it was tested daily, are you going to go through
> > the hastle of digging out the commit IDs and emailing each day to say
> > what was tested? That sounds to me like a _lot_ more work than testing
> > the occasional emailed patch.
> I maybe wouldn't report each success, I would report if my test fails.
> You can consider this more or less valuable. Still I think given the
> ease this could be done it's worth it.
>
> That's how linux-next works, too.
And linux-next is an extremely poor test of whether a patch is correct
or not. It's a good test of whether there's any merge issues between
trees and that's all.
The point of posting patches to mailing lists is to get them:
(a) reviewed, and add Reviewed-by/Acked-by attributes to them
(b) get them tested by other people and successes reported back,
as well as failures.
You don't get (b) from any automated test system, and (b) is what I'm
after. It's completely pointless to throw them into some sort of branch
which gets automatically tested if there's no positive feedback coming
from such a test.
It gives nothing more than just throwing them at linux-next and listening
for the resounding silence. I personally have never had anyone say "I
tested your patch X in linux-next and it really worked for me". It just
doesn't happen. And so it's useless as a system for testing the quality
of patches.
I have had the extremely _rare_ report that something has broken in
linux-next, but on the whole those virtually never happen even when there
has been breakage. See the recent breakage of OMAP with the sched_clock()
fixes, which had been sitting in linux-next for about a week with no one
noticing.
So, no, I give zero value to automatic test systems as a means to ascertain
the quality of patches. Their *only* use is as a tool to check whether
a particular combination of patches builds. Nothing more.
I will continue to mail out patches which I want people to test and give
feedback on, because that is the _only_ way to do it.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-18 15:43 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-18 15:43 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-K?nig wrote:
> Hi Russell,
>
> On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> > On Mon, Jan 17, 2011 at 11:08:57AM +0100, Uwe Kleine-K?nig wrote:
> > > On Sun, Jan 16, 2011 at 12:19:11PM +0000, Russell King - ARM Linux wrote:
> > > > This does need a fair amount of testing before it can be merged, so I'd
> > > > like to see a number of Tested-by's against this patch. Please also
> > > > indicate whether you tested on LE or BE or both, which filesystems, and
> > > > whether they were read-only mounted or read-write mounted.
> > > You could make life a bit easier (at least for us at Pengutronix,
> > > probably more) if you had a branch with a defined name for patches like
> > > these. We could add that to our daily test then.
> >
> > No, because then it's not possible to properly tie down what has been
> > tested and what hasn't.
> >
> > The advantage of emailed patches is that when people reply to them, you
> > have a better idea that the patch to which they're replying to is the
> > one they tested.
> >
> > Such as in this case where the follow-up patch hasn't received any
> > replies, and so I can't add the one received tested-by to the follow-up
> > patch. With the git approach, I wouldn't know what was tested unless
> > you included the commit IDs each time.
> >
> > And let's face it - if it was tested daily, are you going to go through
> > the hastle of digging out the commit IDs and emailing each day to say
> > what was tested? That sounds to me like a _lot_ more work than testing
> > the occasional emailed patch.
> I maybe wouldn't report each success, I would report if my test fails.
> You can consider this more or less valuable. Still I think given the
> ease this could be done it's worth it.
>
> That's how linux-next works, too.
And linux-next is an extremely poor test of whether a patch is correct
or not. It's a good test of whether there's any merge issues between
trees and that's all.
The point of posting patches to mailing lists is to get them:
(a) reviewed, and add Reviewed-by/Acked-by attributes to them
(b) get them tested by other people and successes reported back,
as well as failures.
You don't get (b) from any automated test system, and (b) is what I'm
after. It's completely pointless to throw them into some sort of branch
which gets automatically tested if there's no positive feedback coming
from such a test.
It gives nothing more than just throwing them at linux-next and listening
for the resounding silence. I personally have never had anyone say "I
tested your patch X in linux-next and it really worked for me". It just
doesn't happen. And so it's useless as a system for testing the quality
of patches.
I have had the extremely _rare_ report that something has broken in
linux-next, but on the whole those virtually never happen even when there
has been breakage. See the recent breakage of OMAP with the sched_clock()
fixes, which had been sitting in linux-next for about a week with no one
noticing.
So, no, I give zero value to automatic test systems as a means to ascertain
the quality of patches. Their *only* use is as a tool to check whether
a particular combination of patches builds. Nothing more.
I will continue to mail out patches which I want people to test and give
feedback on, because that is the _only_ way to do it.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-18 15:43 ` Russell King - ARM Linux
@ 2011-01-18 15:58 ` Uwe Kleine-König
-1 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-18 15:58 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap
Hello Russell,
On Tue, Jan 18, 2011 at 03:43:44PM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-König wrote:
> > On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> I will continue to mail out patches which I want people to test and give
> feedback on, because that is the _only_ way to do it.
Note that I didn't suggest to stop sending out patches and collecting
the acks and tested-bys there. The automated tests are just a different
test.
And IMHO it's not harder to reply with a git commit-id, but it makes it
more likely that a reply to a wrong mail is detected.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-18 15:58 ` Uwe Kleine-König
0 siblings, 0 replies; 20+ messages in thread
From: Uwe Kleine-König @ 2011-01-18 15:58 UTC (permalink / raw)
To: linux-arm-kernel
Hello Russell,
On Tue, Jan 18, 2011 at 03:43:44PM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-K?nig wrote:
> > On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> I will continue to mail out patches which I want people to test and give
> feedback on, because that is the _only_ way to do it.
Note that I didn't suggest to stop sending out patches and collecting
the acks and tested-bys there. The automated tests are just a different
test.
And IMHO it's not harder to reply with a git commit-id, but it makes it
more likely that a reply to a wrong mail is detected.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC+CFT] Use word operations in bitops
2011-01-18 15:58 ` Uwe Kleine-König
@ 2011-01-18 16:28 ` Russell King - ARM Linux
-1 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-18 16:28 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: linux-arm-kernel, linux-omap
On Tue, Jan 18, 2011 at 04:58:51PM +0100, Uwe Kleine-König wrote:
> Hello Russell,
>
> On Tue, Jan 18, 2011 at 03:43:44PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-König wrote:
> > > On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> > I will continue to mail out patches which I want people to test and give
> > feedback on, because that is the _only_ way to do it.
> Note that I didn't suggest to stop sending out patches and collecting
> the acks and tested-bys there. The automated tests are just a different
> test.
>
> And IMHO it's not harder to reply with a git commit-id, but it makes it
> more likely that a reply to a wrong mail is detected.
No. Take a moment and think.
Two people pull the commits one evening. One gets in during GMT morning,
checks their tests, and reports "git commit X passed, have this Tested-by".
So, their tested-by is added to the commit, which changes the git ID to
Y.
Second person gets in during GMT afternoon, and reports "git commit X
passed." Now instead of looking in the current branch, I'd have to
cross-reference it back to what was originally there, check that's
what they actually meant, look that up in the new branch, and apply
their tested-by to that instead.
More complicated means more things to go wrong. No thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC+CFT] Use word operations in bitops
@ 2011-01-18 16:28 ` Russell King - ARM Linux
0 siblings, 0 replies; 20+ messages in thread
From: Russell King - ARM Linux @ 2011-01-18 16:28 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 18, 2011 at 04:58:51PM +0100, Uwe Kleine-K?nig wrote:
> Hello Russell,
>
> On Tue, Jan 18, 2011 at 03:43:44PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Jan 18, 2011 at 04:32:57PM +0100, Uwe Kleine-K?nig wrote:
> > > On Mon, Jan 17, 2011 at 10:46:18AM +0000, Russell King - ARM Linux wrote:
> > I will continue to mail out patches which I want people to test and give
> > feedback on, because that is the _only_ way to do it.
> Note that I didn't suggest to stop sending out patches and collecting
> the acks and tested-bys there. The automated tests are just a different
> test.
>
> And IMHO it's not harder to reply with a git commit-id, but it makes it
> more likely that a reply to a wrong mail is detected.
No. Take a moment and think.
Two people pull the commits one evening. One gets in during GMT morning,
checks their tests, and reports "git commit X passed, have this Tested-by".
So, their tested-by is added to the commit, which changes the git ID to
Y.
Second person gets in during GMT afternoon, and reports "git commit X
passed." Now instead of looking in the current branch, I'd have to
cross-reference it back to what was originally there, check that's
what they actually meant, look that up in the new branch, and apply
their tested-by to that instead.
More complicated means more things to go wrong. No thank you.
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2011-01-18 16:30 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-16 12:19 [RFC+CFT] Use word operations in bitops Russell King - ARM Linux
2011-01-16 12:19 ` Russell King - ARM Linux
2011-01-16 18:15 ` Russell King - ARM Linux
2011-01-16 18:15 ` Russell King - ARM Linux
2011-01-17 11:03 ` Jamie Iles
2011-01-17 11:03 ` Jamie Iles
2011-01-17 9:46 ` Jamie Iles
2011-01-17 9:46 ` Jamie Iles
2011-01-17 10:08 ` Uwe Kleine-König
2011-01-17 10:08 ` Uwe Kleine-König
2011-01-17 10:46 ` Russell King - ARM Linux
2011-01-17 10:46 ` Russell King - ARM Linux
2011-01-18 15:32 ` Uwe Kleine-König
2011-01-18 15:32 ` Uwe Kleine-König
2011-01-18 15:43 ` Russell King - ARM Linux
2011-01-18 15:43 ` Russell King - ARM Linux
2011-01-18 15:58 ` Uwe Kleine-König
2011-01-18 15:58 ` Uwe Kleine-König
2011-01-18 16:28 ` Russell King - ARM Linux
2011-01-18 16:28 ` Russell King - ARM Linux
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.