Skip to content

Commit 162e6df

Browse files
committed
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "Two bugfixes from Andy addressing at least some of the subtle NMI related wreckage which has been reported by Sasha Levin" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/nmi/64: Fix a paravirt stack-clobbering bug in the NMI code x86/paravirt: Replace the paravirt nop with a bona fide empty function
2 parents 5a6bdf0 + 83c133c commit 162e6df

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

arch/x86/entry/entry_64.S

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,18 @@ END(error_exit)
11281128

11291129
/* Runs on exception stack */
11301130
ENTRY(nmi)
1131+
/*
1132+
* Fix up the exception frame if we're on Xen.
1133+
* PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
1134+
* one value to the stack on native, so it may clobber the rdx
1135+
* scratch slot, but it won't clobber any of the important
1136+
* slots past it.
1137+
*
1138+
* Xen is a different story, because the Xen frame itself overlaps
1139+
* the "NMI executing" variable.
1140+
*/
11311141
PARAVIRT_ADJUST_EXCEPTION_FRAME
1142+
11321143
/*
11331144
* We allow breakpoints in NMIs. If a breakpoint occurs, then
11341145
* the iretq it performs will take us out of NMI context.
@@ -1179,9 +1190,12 @@ ENTRY(nmi)
11791190
* we don't want to enable interrupts, because then we'll end
11801191
* up in an awkward situation in which IRQs are on but NMIs
11811192
* are off.
1193+
*
1194+
* We also must not push anything to the stack before switching
1195+
* stacks lest we corrupt the "NMI executing" variable.
11821196
*/
11831197

1184-
SWAPGS
1198+
SWAPGS_UNSAFE_STACK
11851199
cld
11861200
movq %rsp, %rdx
11871201
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp

arch/x86/kernel/paravirt.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,18 @@
4141
#include <asm/timer.h>
4242
#include <asm/special_insns.h>
4343

44-
/* nop stub */
45-
void _paravirt_nop(void)
46-
{
47-
}
44+
/*
45+
* nop stub, which must not clobber anything *including the stack* to
46+
* avoid confusing the entry prologues.
47+
*/
48+
extern void _paravirt_nop(void);
49+
asm (".pushsection .entry.text, \"ax\"\n"
50+
".global _paravirt_nop\n"
51+
"_paravirt_nop:\n\t"
52+
"ret\n\t"
53+
".size _paravirt_nop, . - _paravirt_nop\n\t"
54+
".type _paravirt_nop, @function\n\t"
55+
".popsection");
4856

4957
/* identity function, which can be inlined */
5058
u32 _paravirt_ident_32(u32 x)

0 commit comments

Comments
 (0)