Skip to content

Commit c8366ba

Browse files
committed
arm64: xchg: 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 xchg primitives so that the LSE swp instruction (yes, you read right!) is used instead. Reviewed-by: Steve Capper <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 084f903 commit c8366ba

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

arch/arm64/include/asm/cmpxchg.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,73 @@
2222
#include <linux/mmdebug.h>
2323

2424
#include <asm/barrier.h>
25+
#include <asm/lse.h>
2526

2627
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
2728
{
2829
unsigned long ret, tmp;
2930

3031
switch (size) {
3132
case 1:
32-
asm volatile("// __xchg1\n"
33+
asm volatile(ARM64_LSE_ATOMIC_INSN(
34+
/* LL/SC */
3335
"1: ldxrb %w0, %2\n"
3436
" stlxrb %w1, %w3, %2\n"
3537
" cbnz %w1, 1b\n"
38+
" dmb ish",
39+
/* LSE atomics */
40+
" nop\n"
41+
" swpalb %w3, %w0, %2\n"
42+
" nop\n"
43+
" nop")
3644
: "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
3745
: "r" (x)
3846
: "memory");
3947
break;
4048
case 2:
41-
asm volatile("// __xchg2\n"
49+
asm volatile(ARM64_LSE_ATOMIC_INSN(
50+
/* LL/SC */
4251
"1: ldxrh %w0, %2\n"
4352
" stlxrh %w1, %w3, %2\n"
4453
" cbnz %w1, 1b\n"
54+
" dmb ish",
55+
/* LSE atomics */
56+
" nop\n"
57+
" swpalh %w3, %w0, %2\n"
58+
" nop\n"
59+
" nop")
4560
: "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
4661
: "r" (x)
4762
: "memory");
4863
break;
4964
case 4:
50-
asm volatile("// __xchg4\n"
65+
asm volatile(ARM64_LSE_ATOMIC_INSN(
66+
/* LL/SC */
5167
"1: ldxr %w0, %2\n"
5268
" stlxr %w1, %w3, %2\n"
5369
" cbnz %w1, 1b\n"
70+
" dmb ish",
71+
/* LSE atomics */
72+
" nop\n"
73+
" swpal %w3, %w0, %2\n"
74+
" nop\n"
75+
" nop")
5476
: "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
5577
: "r" (x)
5678
: "memory");
5779
break;
5880
case 8:
59-
asm volatile("// __xchg8\n"
81+
asm volatile(ARM64_LSE_ATOMIC_INSN(
82+
/* LL/SC */
6083
"1: ldxr %0, %2\n"
6184
" stlxr %w1, %3, %2\n"
6285
" cbnz %w1, 1b\n"
86+
" dmb ish",
87+
/* LSE atomics */
88+
" nop\n"
89+
" swpal %3, %0, %2\n"
90+
" nop\n"
91+
" nop")
6392
: "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
6493
: "r" (x)
6594
: "memory");
@@ -68,7 +97,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
6897
BUILD_BUG();
6998
}
7099

71-
smp_mb();
72100
return ret;
73101
}
74102

0 commit comments

Comments
 (0)