Skip to content

Commit 2995590

Browse files
amlutoIngo Molnar
authored andcommitted
x86/entry/64: Initialize the top of the IRQ stack before switching stacks
The OOPS unwinder wants the word at the top of the IRQ stack to point back to the previous stack at all times when the IRQ stack is in use. There's currently a one-instruction window in ENTER_IRQ_STACK during which this isn't the case. Fix it by writing the old RSP to the top of the IRQ stack before jumping. This currently writes the pointer to the stack twice, which is a bit ugly. We could get rid of this by replacing irq_stack_ptr with irq_stack_ptr_minus_eight (better name welcome). OTOH, there may be all kinds of odd microarchitectural considerations in play that affect performance by a few cycles here. Reported-by: Mike Galbraith <efault@gmx.de> Reported-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: live-patching@vger.kernel.org Link: http://lkml.kernel.org/r/aae7e79e49914808440ad5310ace138ced2179ca.1499786555.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 1d3e53e commit 2995590

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

arch/x86/entry/entry_64.S

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ END(irq_entries_start)
469469
DEBUG_ENTRY_ASSERT_IRQS_OFF
470470
movq %rsp, \old_rsp
471471
incl PER_CPU_VAR(irq_count)
472+
jnz .Lirq_stack_push_old_rsp_\@
472473

473474
/*
474475
* Right now, if we just incremented irq_count to zero, we've
@@ -478,9 +479,30 @@ END(irq_entries_start)
478479
* it must be *extremely* careful to limit its stack usage. This
479480
* could include kprobes and a hypothetical future IST-less #DB
480481
* handler.
482+
*
483+
* The OOPS unwinder relies on the word at the top of the IRQ
484+
* stack linking back to the previous RSP for the entire time we're
485+
* on the IRQ stack. For this to work reliably, we need to write
486+
* it before we actually move ourselves to the IRQ stack.
487+
*/
488+
489+
movq \old_rsp, PER_CPU_VAR(irq_stack_union + IRQ_STACK_SIZE - 8)
490+
movq PER_CPU_VAR(irq_stack_ptr), %rsp
491+
492+
#ifdef CONFIG_DEBUG_ENTRY
493+
/*
494+
* If the first movq above becomes wrong due to IRQ stack layout
495+
* changes, the only way we'll notice is if we try to unwind right
496+
* here. Assert that we set up the stack right to catch this type
497+
* of bug quickly.
481498
*/
499+
cmpq -8(%rsp), \old_rsp
500+
je .Lirq_stack_okay\@
501+
ud2
502+
.Lirq_stack_okay\@:
503+
#endif
482504

483-
cmovzq PER_CPU_VAR(irq_stack_ptr), %rsp
505+
.Lirq_stack_push_old_rsp_\@:
484506
pushq \old_rsp
485507
.endm
486508

0 commit comments

Comments
 (0)