Patch "arm64: percpu: rewrite ll/sc loops in assembly" has been added to the 4.8-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
arm64: percpu: rewrite ll/sc loops in assembly
to the 4.8-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
arm64-percpu-rewrite-ll-sc-loops-in-assembly.patch
and it can be found in the queue-4.8 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
1e6e57d9b34a9075d5f9e2048ea7b09756590d11Mon Sep 17 00:00:00 2001
From: Will Deacon <[email protected]>
Date: Mon, 4 Jul 2016 17:44:48 +0100
Subject: arm64: percpu: rewrite ll/sc loops in assembly
From: Will Deacon <[email protected]>
commit 1e6e57d9b34a9075d5f9e2048ea7b09756590d11 upstream.
Writing the outer loop of an LL/SC sequence using do {...} while constructs potentially allows the compiler to hoist memory accesses between the STXR and the branch back to the LDXR. On CPUs that do not guarantee forward progress of LL/SC loops when faced with memory accesses to the same ERG (up to 2k) between the failed STXR and the branch back, we may end up livelocking.
This patch avoids this issue in our percpu atomics by rewriting the outer loop as part of the LL/SC inline assembly block.
--- arch/arm64/include/asm/percpu.h | 120 ++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 64 deletions(-)
arch/arm64/include/asm/percpu.h +56 -64
@@ -44,48 +44,44 @@ static inline unsigned long __percpu_##o \switch (size) { \case 1 : \ - do { \ - asm ("//__per_cpu_" #op "_1\n" \ - "ldxrb %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_1\n" \ + "1: ldxrb %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrb %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u8 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrb %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u8 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 2: \ - do { \ - asm ("//__per_cpu_" #op "_2\n" \ - "ldxrh %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_2\n" \ + "1: ldxrh %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrh %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u16 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrh %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u16 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 4: \ - do { \ - asm ("//__per_cpu_" #op "_4\n" \ - "ldxr %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_4\n" \ + "1: ldxr %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxr %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u32 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u32 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 8: \ - do { \ - asm ("//__per_cpu_" #op "_8\n" \ - "ldxr %[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_8\n" \ + "1: ldxr %[ret], %[ptr]\n" \ #asm_op " %[ret], %[ret], %[val]\n" \ - "stxr %w[loop], %[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u64 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u64 *)ptr) \ + : [val] "Ir" (val)); \ break; \ default: \ BUILD_BUG(); \
@@ -150,44 +146,40 @@ static inline unsigned long __percpu_xchswitch (size) {case 1 : -do { - asm ("//__percpu_xchg_1\n" -"ldxrb %w[ret], %[ptr]\n" -"stxrb %w[loop], %w[val], %[ptr]\n" - : [loop]"=&r" (loop), [ret]"=&r" (ret), - [ptr]"+Q" (*(u8 *)ptr) - : [val]"r" (val)); - }while (loop); + asm ("//__percpu_xchg_1\n" +"1: ldxrb %w[ret], %[ptr]\n" +" stxrb %w[loop], %w[val], %[ptr]\n" +" cbnz %w[loop], 1b" + : [loop]"=&r" (loop), [ret]"=&r" (ret), + [ptr]"+Q" (*(u8 *)ptr) + : [val]"r" (val));break ;case 2 : -do { - asm ("//__percpu_xchg_2\n" -"ldxrh %w[ret], %[ptr]\n" -"stxrh %w[loop], %w[val], %[ptr]\n" - : [loop]"=&r" (loop), [ret]"=&r" (ret), - [ptr]"+Q" (*(u16 *)ptr) - : [val]"r" (val)); - }while (loop); + asm ("//__percpu_xchg_2\n" +"1: ldxrh %w[ret], %[ptr]\n" +" stxrh %w[loop], %w[val], %[ptr]\n" +" cbnz %w[loop], 1b" + : [loop]"=&r" (loop), [ret]"=&r" (ret), + [ptr]"+Q" (*(u16 *)ptr) + : [val]"r" (val));break ;case 4 : -do { - asm ("//__percpu_xchg_4\n" -"ldxr %w[ret], %[ptr]\n" -"stxr %w[loop], %w[val], %[ptr]\n" - : [loop]"=&r" (loop), [ret]"=&r" (ret), - [ptr]"+Q" (*(u32 *)ptr) - : [val]"r" (val)); - }while (loop); + asm ("//__percpu_xchg_4\n" +"1: ldxr %w[ret], %[ptr]\n" +" stxr %w[loop], %w[val], %[ptr]\n" +" cbnz %w[loop], 1b" + : [loop]"=&r" (loop), [ret]"=&r" (ret), + [ptr]"+Q" (*(u32 *)ptr) + : [val]"r" (val));break ;case 8 : -do { - asm ("//__percpu_xchg_8\n" -"ldxr %[ret], %[ptr]\n" -"stxr %w[loop], %[val], %[ptr]\n" - : [loop]"=&r" (loop), [ret]"=&r" (ret), - [ptr]"+Q" (*(u64 *)ptr) - : [val]"r" (val)); - }while (loop); + asm ("//__percpu_xchg_8\n" +"1: ldxr %[ret], %[ptr]\n" +" stxr %w[loop], %[val], %[ptr]\n" +" cbnz %w[loop], 1b" + : [loop]"=&r" (loop), [ret]"=&r" (ret), + [ptr]"+Q" (*(u64 *)ptr) + : [val]"r" (val));break ;default :BUILD_BUG ();
Patches currently in stable-queue which might be from [email protected] are
queue-4.8/arm64-swp-emulation-bound-ll-sc-retries-before-rescheduling.patch queue-4.8/arm64-kaslr-fix-breakage-with-config_modversions-y.patch queue-4.8/arm64-cortex-a53-errata-workaround-check-for-kernel-addresses.patch queue-4.8/arm64-kernel-init-mdcr_el2-even-in-the-absence-of-a-pmu.patch queue-4.8/arm64-kvm-take-s1-walks-into-account-when-determining-s2-write-faults.patch queue-4.8/arm64-percpu-rewrite-ll-sc-loops-in-assembly.patch