Skip to content

Commit c516213

Browse files
Peter Zijlstraingomolnar
authored andcommitted
x86/entry: Optimize common_interrupt_return()
The code in common_interrupt_return() does a bunch of unconditional work that is really only needed on PTI kernels. Specifically it unconditionally copies the IRET frame back onto the entry stack, swizzles onto the entry stack and does IRET from there. However, without PTI we can simply IRET from whatever stack we're on. ivb-ep, mitigations=off, gettid-1m: PRE: 140,118,538 cycles:k ( +- 0.01% ) 236,692,878 instructions:k # 1.69 insn per cycle ( +- 0.00% ) POST: 140,026,608 cycles:k ( +- 0.01% ) 236,696,176 instructions:k # 1.69 insn per cycle ( +- 0.00% ) (this is with --repeat 100 and the run-to-run variance is bigger than the difference shown) Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: https://lore.kernel.org/r/20231120143626.638107480@infradead.org
1 parent 98b1cc8 commit c516213

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

arch/x86/entry/calling.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,7 @@ For 32-bit we have the following conventions - kernel is built with
175175
#define THIS_CPU_user_pcid_flush_mask \
176176
PER_CPU_VAR(cpu_tlbstate) + TLB_STATE_user_pcid_flush_mask
177177

178-
.macro SWITCH_TO_USER_CR3_NOSTACK scratch_reg:req scratch_reg2:req
179-
ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
178+
.macro SWITCH_TO_USER_CR3 scratch_reg:req scratch_reg2:req
180179
mov %cr3, \scratch_reg
181180

182181
ALTERNATIVE "jmp .Lwrcr3_\@", "", X86_FEATURE_PCID
@@ -206,13 +205,20 @@ For 32-bit we have the following conventions - kernel is built with
206205
/* Flip the PGD to the user version */
207206
orq $(PTI_USER_PGTABLE_MASK), \scratch_reg
208207
mov \scratch_reg, %cr3
208+
.endm
209+
210+
.macro SWITCH_TO_USER_CR3_NOSTACK scratch_reg:req scratch_reg2:req
211+
ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
212+
SWITCH_TO_USER_CR3 \scratch_reg \scratch_reg2
209213
.Lend_\@:
210214
.endm
211215

212216
.macro SWITCH_TO_USER_CR3_STACK scratch_reg:req
217+
ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
213218
pushq %rax
214-
SWITCH_TO_USER_CR3_NOSTACK scratch_reg=\scratch_reg scratch_reg2=%rax
219+
SWITCH_TO_USER_CR3 scratch_reg=\scratch_reg scratch_reg2=%rax
215220
popq %rax
221+
.Lend_\@:
216222
.endm
217223

218224
.macro SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg:req save_reg:req

arch/x86/entry/entry_64.S

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,18 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
569569
#ifdef CONFIG_XEN_PV
570570
ALTERNATIVE "", "jmp xenpv_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
571571
#endif
572+
#ifdef CONFIG_PAGE_TABLE_ISOLATION
573+
ALTERNATIVE "", "jmp .Lpti_restore_regs_and_return_to_usermode", X86_FEATURE_PTI
574+
#endif
575+
576+
STACKLEAK_ERASE
577+
POP_REGS
578+
add $8, %rsp /* orig_ax */
579+
swapgs
580+
jmp .Lnative_iret
572581

582+
#ifdef CONFIG_PAGE_TABLE_ISOLATION
583+
.Lpti_restore_regs_and_return_to_usermode:
573584
POP_REGS pop_rdi=0
574585

575586
/*
@@ -596,13 +607,15 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
596607
*/
597608
STACKLEAK_ERASE_NOCLOBBER
598609

599-
SWITCH_TO_USER_CR3_STACK scratch_reg=%rdi
610+
push %rax
611+
SWITCH_TO_USER_CR3 scratch_reg=%rdi scratch_reg2=%rax
612+
pop %rax
600613

601614
/* Restore RDI. */
602615
popq %rdi
603616
swapgs
604617
jmp .Lnative_iret
605-
618+
#endif
606619

607620
SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
608621
#ifdef CONFIG_DEBUG_ENTRY

0 commit comments

Comments
 (0)