Skip to content

Commit 084f903

Browse files
committed
arm64: bitops: patch in lse instructions when supported by the CPU
On CPUs which support the LSE atomic instructions introduced in ARMv8.1, it makes sense to use them in preference to ll/sc sequences. This patch introduces runtime patching of our bitops functions so that LSE atomic instructions are used instead. Reviewed-by: Steve Capper <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 81bb5c6 commit 084f903

File tree

2 files changed

+45
-21
lines changed

2 files changed

+45
-21
lines changed

arch/arm64/include/asm/lse.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@
44
#if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
55

66
#include <linux/stringify.h>
7-
87
#include <asm/alternative.h>
98
#include <asm/cpufeature.h>
109

10+
#ifdef __ASSEMBLER__
11+
12+
.arch_extension lse
13+
14+
.macro alt_lse, llsc, lse
15+
alternative_insn "\llsc", "\lse", ARM64_CPU_FEAT_LSE_ATOMICS
16+
.endm
17+
18+
#else /* __ASSEMBLER__ */
19+
1120
__asm__(".arch_extension lse");
1221

1322
/* Move the ll/sc atomics out-of-line */
@@ -22,13 +31,23 @@ __asm__(".arch_extension lse");
2231
#define ARM64_LSE_ATOMIC_INSN(llsc, lse) \
2332
ALTERNATIVE(llsc, lse, ARM64_CPU_FEAT_LSE_ATOMICS)
2433

25-
#else
34+
#endif /* __ASSEMBLER__ */
35+
#else /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
36+
37+
#ifdef __ASSEMBLER__
38+
39+
.macro alt_lse, llsc, lse
40+
\llsc
41+
.endm
42+
43+
#else /* __ASSEMBLER__ */
2644

2745
#define __LL_SC_INLINE static inline
2846
#define __LL_SC_PREFIX(x) x
2947
#define __LL_SC_EXPORT(x)
3048

3149
#define ARM64_LSE_ATOMIC_INSN(llsc, lse) llsc
3250

51+
#endif /* __ASSEMBLER__ */
3352
#endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
3453
#endif /* __ASM_LSE_H */

arch/arm64/lib/bitops.S

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,52 +18,57 @@
1818

1919
#include <linux/linkage.h>
2020
#include <asm/assembler.h>
21+
#include <asm/lse.h>
2122

2223
/*
2324
* x0: bits 5:0 bit offset
2425
* bits 31:6 word offset
2526
* x1: address
2627
*/
27-
.macro bitop, name, instr
28+
.macro bitop, name, llsc, lse
2829
ENTRY( \name )
2930
and w3, w0, #63 // Get bit offset
3031
eor w0, w0, w3 // Clear low bits
3132
mov x2, #1
3233
add x1, x1, x0, lsr #3 // Get word offset
3334
lsl x3, x2, x3 // Create mask
34-
1: ldxr x2, [x1]
35-
\instr x2, x2, x3
36-
stxr w0, x2, [x1]
37-
cbnz w0, 1b
35+
36+
alt_lse "1: ldxr x2, [x1]", "\lse x3, [x1]"
37+
alt_lse " \llsc x2, x2, x3", "nop"
38+
alt_lse " stxr w0, x2, [x1]", "nop"
39+
alt_lse " cbnz w0, 1b", "nop"
40+
3841
ret
3942
ENDPROC(\name )
4043
.endm
4144

42-
.macro testop, name, instr
45+
.macro testop, name, llsc, lse
4346
ENTRY( \name )
4447
and w3, w0, #63 // Get bit offset
4548
eor w0, w0, w3 // Clear low bits
4649
mov x2, #1
4750
add x1, x1, x0, lsr #3 // Get word offset
4851
lsl x4, x2, x3 // Create mask
49-
1: ldxr x2, [x1]
50-
lsr x0, x2, x3 // Save old value of bit
51-
\instr x2, x2, x4 // toggle bit
52-
stlxr w5, x2, [x1]
53-
cbnz w5, 1b
54-
dmb ish
52+
53+
alt_lse "1: ldxr x2, [x1]", "\lse x4, x2, [x1]"
54+
lsr x0, x2, x3
55+
alt_lse " \llsc x2, x2, x4", "nop"
56+
alt_lse " stlxr w5, x2, [x1]", "nop"
57+
alt_lse " cbnz w5, 1b", "nop"
58+
alt_lse " dmb ish", "nop"
59+
5560
and x0, x0, #1
56-
3: ret
61+
ret
5762
ENDPROC(\name )
5863
.endm
5964

6065
/*
6166
* Atomic bit operations.
6267
*/
63-
bitop change_bit, eor
64-
bitop clear_bit, bic
65-
bitop set_bit, orr
68+
bitop change_bit, eor, steor
69+
bitop clear_bit, bic, stclr
70+
bitop set_bit, orr, stset
6671

67-
testop test_and_change_bit, eor
68-
testop test_and_clear_bit, bic
69-
testop test_and_set_bit, orr
72+
testop test_and_change_bit, eor, ldeoral
73+
testop test_and_clear_bit, bic, ldclral
74+
testop test_and_set_bit, orr, ldsetal

0 commit comments

Comments
 (0)