Skip to content

Commit 59bec00

Browse files
ubizjakIngo Molnar
authored andcommitted
x86/percpu: Introduce %rip-relative addressing to PER_CPU_VAR()
Introduce x86_64 %rip-relative addressing to the PER_CPU_VAR() macro. Instructions using %rip-relative address operand are one byte shorter than their absolute address counterparts and are also compatible with position independent executable (-fpie) builds. The patch reduces code size of a test kernel build by 150 bytes. The PER_CPU_VAR() macro is intended to be applied to a symbol and should not be used with register operands. Introduce the new __percpu macro and use it in cmpxchg{8,16}b_emu.S instead. Also add a missing function comment to this_cpu_cmpxchg8b_emu(). No functional changes intended. Signed-off-by: Uros Bizjak <ubizjak@gmail.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: Brian Gerst <brgerst@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Sean Christopherson <seanjc@google.com>
1 parent aa47f90 commit 59bec00

File tree

3 files changed

+35
-19
lines changed

3 files changed

+35
-19
lines changed

arch/x86/include/asm/percpu.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@
44

55
#ifdef CONFIG_X86_64
66
#define __percpu_seg gs
7+
#define __percpu_rel (%rip)
78
#else
89
#define __percpu_seg fs
10+
#define __percpu_rel
911
#endif
1012

1113
#ifdef __ASSEMBLY__
1214

1315
#ifdef CONFIG_SMP
14-
#define PER_CPU_VAR(var) %__percpu_seg:var
15-
#else /* ! SMP */
16-
#define PER_CPU_VAR(var) var
17-
#endif /* SMP */
16+
#define __percpu %__percpu_seg:
17+
#else
18+
#define __percpu
19+
#endif
20+
21+
#define PER_CPU_VAR(var) __percpu(var)__percpu_rel
1822

1923
#ifdef CONFIG_X86_64_SMP
2024
#define INIT_PER_CPU_VAR(var) init_per_cpu__##var

arch/x86/lib/cmpxchg16b_emu.S

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ SYM_FUNC_START(this_cpu_cmpxchg16b_emu)
2323
cli
2424

2525
/* if (*ptr == old) */
26-
cmpq PER_CPU_VAR(0(%rsi)), %rax
26+
cmpq __percpu (%rsi), %rax
2727
jne .Lnot_same
28-
cmpq PER_CPU_VAR(8(%rsi)), %rdx
28+
cmpq __percpu 8(%rsi), %rdx
2929
jne .Lnot_same
3030

3131
/* *ptr = new */
32-
movq %rbx, PER_CPU_VAR(0(%rsi))
33-
movq %rcx, PER_CPU_VAR(8(%rsi))
32+
movq %rbx, __percpu (%rsi)
33+
movq %rcx, __percpu 8(%rsi)
3434

3535
/* set ZF in EFLAGS to indicate success */
3636
orl $X86_EFLAGS_ZF, (%rsp)
@@ -42,8 +42,8 @@ SYM_FUNC_START(this_cpu_cmpxchg16b_emu)
4242
/* *ptr != old */
4343

4444
/* old = *ptr */
45-
movq PER_CPU_VAR(0(%rsi)), %rax
46-
movq PER_CPU_VAR(8(%rsi)), %rdx
45+
movq __percpu (%rsi), %rax
46+
movq __percpu 8(%rsi), %rdx
4747

4848
/* clear ZF in EFLAGS to indicate failure */
4949
andl $(~X86_EFLAGS_ZF), (%rsp)

arch/x86/lib/cmpxchg8b_emu.S

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ SYM_FUNC_START(cmpxchg8b_emu)
2424
pushfl
2525
cli
2626

27-
cmpl 0(%esi), %eax
27+
cmpl (%esi), %eax
2828
jne .Lnot_same
2929
cmpl 4(%esi), %edx
3030
jne .Lnot_same
3131

32-
movl %ebx, 0(%esi)
32+
movl %ebx, (%esi)
3333
movl %ecx, 4(%esi)
3434

3535
orl $X86_EFLAGS_ZF, (%esp)
@@ -38,7 +38,7 @@ SYM_FUNC_START(cmpxchg8b_emu)
3838
RET
3939

4040
.Lnot_same:
41-
movl 0(%esi), %eax
41+
movl (%esi), %eax
4242
movl 4(%esi), %edx
4343

4444
andl $(~X86_EFLAGS_ZF), (%esp)
@@ -53,27 +53,39 @@ EXPORT_SYMBOL(cmpxchg8b_emu)
5353

5454
#ifndef CONFIG_UML
5555

56+
/*
57+
* Emulate 'cmpxchg8b %fs:(%rsi)'
58+
*
59+
* Inputs:
60+
* %esi : memory location to compare
61+
* %eax : low 32 bits of old value
62+
* %edx : high 32 bits of old value
63+
* %ebx : low 32 bits of new value
64+
* %ecx : high 32 bits of new value
65+
*
66+
* Notably this is not LOCK prefixed and is not safe against NMIs
67+
*/
5668
SYM_FUNC_START(this_cpu_cmpxchg8b_emu)
5769

5870
pushfl
5971
cli
6072

61-
cmpl PER_CPU_VAR(0(%esi)), %eax
73+
cmpl __percpu (%esi), %eax
6274
jne .Lnot_same2
63-
cmpl PER_CPU_VAR(4(%esi)), %edx
75+
cmpl __percpu 4(%esi), %edx
6476
jne .Lnot_same2
6577

66-
movl %ebx, PER_CPU_VAR(0(%esi))
67-
movl %ecx, PER_CPU_VAR(4(%esi))
78+
movl %ebx, __percpu (%esi)
79+
movl %ecx, __percpu 4(%esi)
6880

6981
orl $X86_EFLAGS_ZF, (%esp)
7082

7183
popfl
7284
RET
7385

7486
.Lnot_same2:
75-
movl PER_CPU_VAR(0(%esi)), %eax
76-
movl PER_CPU_VAR(4(%esi)), %edx
87+
movl __percpu (%esi), %eax
88+
movl __percpu 4(%esi), %edx
7789

7890
andl $(~X86_EFLAGS_ZF), (%esp)
7991

0 commit comments

Comments
 (0)