Skip to content

Commit eaad981

Browse files
ChangSeokBaeKAGA-KOKO
authored andcommitted
x86/entry/64: Introduce the FIND_PERCPU_BASE macro
GSBASE is used to find per-CPU data in the kernel. But when GSBASE is unknown, the per-CPU base can be found from the per_cpu_offset table with a CPU NR. The CPU NR is extracted from the limit field of the CPUNODE entry in GDT, or by the RDPID instruction. This is a prerequisite for using FSGSBASE in the low level entry code. Also, add the GAS-compatible RDPID macro as binutils 2.23 do not support it. Support is added in version 2.27. [ tglx: Massaged changelog ] Suggested-by: H. Peter Anvin <[email protected]> Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 96b2371 commit eaad981

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

arch/x86/entry/calling.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <asm/percpu.h>
77
#include <asm/asm-offsets.h>
88
#include <asm/processor-flags.h>
9+
#include <asm/inst.h>
910

1011
/*
1112
@@ -351,3 +352,36 @@ For 32-bit we have the following conventions - kernel is built with
351352
call stackleak_erase
352353
#endif
353354
.endm
355+
356+
#ifdef CONFIG_SMP
357+
358+
/*
359+
* CPU/node NR is loaded from the limit (size) field of a special segment
360+
* descriptor entry in GDT.
361+
*/
362+
.macro LOAD_CPU_AND_NODE_SEG_LIMIT reg:req
363+
movq $__CPUNODE_SEG, \reg
364+
lsl \reg, \reg
365+
.endm
366+
367+
/*
368+
* Fetch the per-CPU GSBASE value for this processor and put it in @reg.
369+
* We normally use %gs for accessing per-CPU data, but we are setting up
370+
* %gs here and obviously can not use %gs itself to access per-CPU data.
371+
*/
372+
.macro GET_PERCPU_BASE reg:req
373+
ALTERNATIVE \
374+
"LOAD_CPU_AND_NODE_SEG_LIMIT \reg", \
375+
"RDPID \reg", \
376+
X86_FEATURE_RDPID
377+
andq $VDSO_CPUNODE_MASK, \reg
378+
movq __per_cpu_offset(, \reg, 8), \reg
379+
.endm
380+
381+
#else
382+
383+
.macro GET_PERCPU_BASE reg:req
384+
movq pcpu_unit_offsets(%rip), \reg
385+
.endm
386+
387+
#endif /* CONFIG_SMP */

arch/x86/include/asm/inst.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,21 @@
306306
.endif
307307
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
308308
.endm
309+
310+
.macro RDPID opd
311+
REG_TYPE rdpid_opd_type \opd
312+
.if rdpid_opd_type == REG_TYPE_R64
313+
R64_NUM rdpid_opd \opd
314+
.else
315+
R32_NUM rdpid_opd \opd
316+
.endif
317+
.byte 0xf3
318+
.if rdpid_opd > 7
319+
PFX_REX rdpid_opd 0
320+
.endif
321+
.byte 0x0f, 0xc7
322+
MODRM 0xc0 rdpid_opd 0x7
323+
.endm
309324
#endif
310325

311326
#endif

0 commit comments

Comments
 (0)