diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-27 06:51:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-27 06:51:42 -0400 |
commit | 162e6df47c4f80c87cb617ec473eca015df454ca (patch) | |
tree | 3b0a445994d3fad35ebed41d10316d6d5bdef941 | |
parent | 5a6bdf06bbd022db25d9935273b409c337c48a6b (diff) | |
parent | 83c133cf11fb0e68a51681447e372489f052d40e (diff) |
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
-rw-r--r-- | arch/x86/entry/entry_64.S | 16 | ||||
-rw-r--r-- | arch/x86/kernel/paravirt.c | 16 |
2 files changed, 27 insertions, 5 deletions
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index d3033183ed70..055a01de7c8d 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S | |||
@@ -1128,7 +1128,18 @@ END(error_exit) | |||
1128 | 1128 | ||
1129 | /* Runs on exception stack */ | 1129 | /* Runs on exception stack */ |
1130 | ENTRY(nmi) | 1130 | 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 | */ | ||
1131 | PARAVIRT_ADJUST_EXCEPTION_FRAME | 1141 | PARAVIRT_ADJUST_EXCEPTION_FRAME |
1142 | |||
1132 | /* | 1143 | /* |
1133 | * We allow breakpoints in NMIs. If a breakpoint occurs, then | 1144 | * We allow breakpoints in NMIs. If a breakpoint occurs, then |
1134 | * the iretq it performs will take us out of NMI context. | 1145 | * the iretq it performs will take us out of NMI context. |
@@ -1179,9 +1190,12 @@ ENTRY(nmi) | |||
1179 | * we don't want to enable interrupts, because then we'll end | 1190 | * we don't want to enable interrupts, because then we'll end |
1180 | * up in an awkward situation in which IRQs are on but NMIs | 1191 | * up in an awkward situation in which IRQs are on but NMIs |
1181 | * are off. | 1192 | * are off. |
1193 | * | ||
1194 | * We also must not push anything to the stack before switching | ||
1195 | * stacks lest we corrupt the "NMI executing" variable. | ||
1182 | */ | 1196 | */ |
1183 | 1197 | ||
1184 | SWAPGS | 1198 | SWAPGS_UNSAFE_STACK |
1185 | cld | 1199 | cld |
1186 | movq %rsp, %rdx | 1200 | movq %rsp, %rdx |
1187 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp | 1201 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index f68e48f5f6c2..c2130aef3f9d 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
@@ -41,10 +41,18 @@ | |||
41 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
42 | #include <asm/special_insns.h> | 42 | #include <asm/special_insns.h> |
43 | 43 | ||
44 | /* nop stub */ | 44 | /* |
45 | void _paravirt_nop(void) | 45 | * nop stub, which must not clobber anything *including the stack* to |
46 | { | 46 | * avoid confusing the entry prologues. |
47 | } | 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"); | ||
48 | 56 | ||
49 | /* identity function, which can be inlined */ | 57 | /* identity function, which can be inlined */ |
50 | u32 _paravirt_ident_32(u32 x) | 58 | u32 _paravirt_ident_32(u32 x) |