Skip to content

Commit 98f05b5

Browse files
amlutoKAGA-KOKO
authored andcommitted
x86/entry/64: Use the TSS sp2 slot for SYSCALL/SYSRET scratch space
In the non-trampoline SYSCALL64 path, a percpu variable is used to temporarily store the user RSP value. Instead of a separate variable, use the otherwise unused sp2 slot in the TSS. This will improve cache locality, as the sp1 slot is already used in the same code to find the kernel stack. It will also simplify a future change to make the non-trampoline path work in PTI mode. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lkml.kernel.org/r/08e769a0023dbad4bac6f34f3631dbaf8ad59f4f.1536015544.git.luto@kernel.org
1 parent bd7b1f7 commit 98f05b5

File tree

5 files changed

+22
-13
lines changed

5 files changed

+22
-13
lines changed

arch/x86/entry/entry_64.S

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,20 @@ ENTRY(entry_SYSCALL_64)
215215
/*
216216
* This path is only taken when PAGE_TABLE_ISOLATION is disabled so it
217217
* is not required to switch CR3.
218+
*
219+
* tss.sp2 is scratch space.
218220
*/
219-
movq %rsp, PER_CPU_VAR(rsp_scratch)
221+
movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
220222
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
221223

222224
/* Construct struct pt_regs on stack */
223-
pushq $__USER_DS /* pt_regs->ss */
224-
pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */
225-
pushq %r11 /* pt_regs->flags */
226-
pushq $__USER_CS /* pt_regs->cs */
227-
pushq %rcx /* pt_regs->ip */
225+
pushq $__USER_DS /* pt_regs->ss */
226+
pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2) /* pt_regs->sp */
227+
pushq %r11 /* pt_regs->flags */
228+
pushq $__USER_CS /* pt_regs->cs */
229+
pushq %rcx /* pt_regs->ip */
228230
GLOBAL(entry_SYSCALL_64_after_hwframe)
229-
pushq %rax /* pt_regs->orig_ax */
231+
pushq %rax /* pt_regs->orig_ax */
230232

231233
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
232234

arch/x86/include/asm/processor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,13 @@ struct x86_hw_tss {
315315
*/
316316
u64 sp1;
317317

318+
/*
319+
* Since Linux does not use ring 2, the 'sp2' slot is unused by
320+
* hardware. entry_SYSCALL_64 uses it as scratch space to stash
321+
* the user RSP value.
322+
*/
318323
u64 sp2;
324+
319325
u64 reserved2;
320326
u64 ist[7];
321327
u32 reserved3;

arch/x86/kernel/asm-offsets.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ void common(void) {
105105
DEFINE(SIZEOF_entry_stack, sizeof(struct entry_stack));
106106
DEFINE(MASK_entry_stack, (~(sizeof(struct entry_stack) - 1)));
107107

108-
/* Offset for sp0 and sp1 into the tss_struct */
108+
/* Offset for fields in tss_struct */
109109
OFFSET(TSS_sp0, tss_struct, x86_tss.sp0);
110110
OFFSET(TSS_sp1, tss_struct, x86_tss.sp1);
111+
OFFSET(TSS_sp2, tss_struct, x86_tss.sp2);
111112
}

arch/x86/kernel/process_64.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@
5959
#include <asm/unistd_32_ia32.h>
6060
#endif
6161

62-
__visible DEFINE_PER_CPU(unsigned long, rsp_scratch);
63-
6462
/* Prints also some state that isn't saved in the pt_regs */
6563
void __show_regs(struct pt_regs *regs, int all)
6664
{

arch/x86/xen/xen-asm_64.S

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ ENTRY(xen_iret)
9191
ENTRY(xen_sysret64)
9292
/*
9393
* We're already on the usermode stack at this point, but
94-
* still with the kernel gs, so we can easily switch back
94+
* still with the kernel gs, so we can easily switch back.
95+
*
96+
* tss.sp2 is scratch space.
9597
*/
96-
movq %rsp, PER_CPU_VAR(rsp_scratch)
98+
movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
9799
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
98100

99101
pushq $__USER_DS
100-
pushq PER_CPU_VAR(rsp_scratch)
102+
pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
101103
pushq %r11
102104
pushq $__USER_CS
103105
pushq %rcx

0 commit comments

Comments
 (0)