Skip to content

Commit f3d415e

Browse files
Dominik BrodowskiIngo Molnar
authored andcommitted
x86/entry/64: Open-code switch_to_thread_stack()
Open-code the two instances which called switch_to_thread_stack(). This allows us to remove the wrapper around DO_SWITCH_TO_THREAD_STACK. While at it, update the UNWIND hint to reflect where the IRET frame is, and update the commentary to reflect what we are actually doing here. Signed-off-by: Dominik Brodowski <[email protected]> Acked-by: Thomas Gleixner <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: David Woodhouse <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent b2855d8 commit f3d415e

File tree

2 files changed

+55
-38
lines changed

2 files changed

+55
-38
lines changed

arch/x86/entry/entry_64.S

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -538,17 +538,48 @@ END(irq_entries_start)
538538
.endm
539539

540540
/*
541-
* Switch to the thread stack. This is called with the IRET frame and
542-
* orig_ax on the stack. (That is, RDI..R12 are not on the stack and
543-
* space has not been allocated for them.)
541+
* Interrupt entry helper function.
542+
*
543+
* Entry runs with interrupts off. Stack layout at entry:
544+
* +----------------------------------------------------+
545+
* | regs->ss |
546+
* | regs->rsp |
547+
* | regs->eflags |
548+
* | regs->cs |
549+
* | regs->ip |
550+
* +----------------------------------------------------+
551+
* | regs->orig_ax = ~(interrupt number) |
552+
* +----------------------------------------------------+
553+
* | return address |
554+
* +----------------------------------------------------+
544555
*/
545-
.macro DO_SWITCH_TO_THREAD_STACK
556+
ENTRY(interrupt_entry)
557+
UNWIND_HINT_FUNC
558+
ASM_CLAC
559+
cld
560+
561+
testb $3, CS-ORIG_RAX+8(%rsp)
562+
jz 1f
563+
SWAPGS
564+
565+
/*
566+
* Switch to the thread stack. The IRET frame and orig_ax are
567+
* on the stack, as well as the return address. RDI..R12 are
568+
* not (yet) on the stack and space has not (yet) been
569+
* allocated for them.
570+
*/
546571
pushq %rdi
572+
547573
/* Need to switch before accessing the thread stack. */
548574
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
549575
movq %rsp, %rdi
550576
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
551-
UNWIND_HINT sp_offset=16 sp_reg=ORC_REG_DI
577+
578+
/*
579+
* We have RDI, return address, and orig_ax on the stack on
580+
* top of the IRET frame. That means offset=24
581+
*/
582+
UNWIND_HINT_IRET_REGS base=%rdi offset=24
552583

553584
pushq 7*8(%rdi) /* regs->ss */
554585
pushq 6*8(%rdi) /* regs->rsp */
@@ -560,25 +591,6 @@ END(irq_entries_start)
560591
UNWIND_HINT_FUNC
561592

562593
movq (%rdi), %rdi
563-
.endm
564-
565-
/*
566-
* Interrupt entry/exit.
567-
*
568-
* Interrupt entry points save only callee clobbered registers in fast path.
569-
*
570-
* Entry runs with interrupts off.
571-
*/
572-
/* 8(%rsp): ~(interrupt number) */
573-
ENTRY(interrupt_entry)
574-
UNWIND_HINT_FUNC
575-
ASM_CLAC
576-
cld
577-
578-
testb $3, CS-ORIG_RAX+8(%rsp)
579-
jz 1f
580-
SWAPGS
581-
DO_SWITCH_TO_THREAD_STACK
582594
1:
583595

584596
PUSH_AND_CLEAR_REGS save_ret=1
@@ -592,7 +604,7 @@ ENTRY(interrupt_entry)
592604
*
593605
* We need to tell lockdep that IRQs are off. We can't do this until
594606
* we fix gsbase, and we should do it before enter_from_user_mode
595-
* (which can take locks). Since TRACE_IRQS_OFF idempotent,
607+
* (which can take locks). Since TRACE_IRQS_OFF is idempotent,
596608
* the simplest way to handle it is to just call it twice if
597609
* we enter from user mode. There's no reason to optimize this since
598610
* TRACE_IRQS_OFF is a no-op if lockdep is off.
@@ -609,6 +621,9 @@ ENTRY(interrupt_entry)
609621
ret
610622
END(interrupt_entry)
611623

624+
625+
/* Interrupt entry/exit. */
626+
612627
/*
613628
* The interrupt stubs push (~vector+0x80) onto the stack and
614629
* then jump to common_interrupt.
@@ -878,17 +893,6 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt
878893
*/
879894
#define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + ((x) - 1) * 8)
880895

881-
#if defined(CONFIG_IA32_EMULATION)
882-
/* entry_64_compat.S::entry_INT80_compat expects this to be an ASM function */
883-
ENTRY(switch_to_thread_stack)
884-
UNWIND_HINT_FUNC
885-
886-
DO_SWITCH_TO_THREAD_STACK
887-
888-
ret
889-
END(switch_to_thread_stack)
890-
#endif
891-
892896
.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1
893897
ENTRY(\sym)
894898
UNWIND_HINT_IRET_REGS offset=\has_error_code*8

arch/x86/entry/entry_64_compat.S

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,23 @@ ENTRY(entry_INT80_compat)
347347
*/
348348
movl %eax, %eax
349349

350+
/* switch to thread stack expects orig_ax and rdi to be pushed */
350351
pushq %rax /* pt_regs->orig_ax */
352+
pushq %rdi /* pt_regs->di */
353+
354+
/* Need to switch before accessing the thread stack. */
355+
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
356+
movq %rsp, %rdi
357+
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
358+
359+
pushq 6*8(%rdi) /* regs->ss */
360+
pushq 5*8(%rdi) /* regs->rsp */
361+
pushq 4*8(%rdi) /* regs->eflags */
362+
pushq 3*8(%rdi) /* regs->cs */
363+
pushq 2*8(%rdi) /* regs->ip */
364+
pushq 1*8(%rdi) /* regs->orig_ax */
351365

352-
/* switch to thread stack expects orig_ax to be pushed */
353-
call switch_to_thread_stack
366+
movq (%rdi), %rdi /* restore %rdi */
354367

355368
pushq %rdi /* pt_regs->di */
356369
pushq %rsi /* pt_regs->si */

0 commit comments

Comments
 (0)