aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2018-07-18 05:40:50 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-07-19 19:11:39 -0400
commitb65bef400689ceee7108c2d47fb97ae91f4d1440 (patch)
tree80d94285df956ffc7372e20cc13a1a91c6fcb954
parente464fb9f241ddf46815b31ca594af96f2699a78e (diff)
x86/entry/32: Add PTI CR3 switches to NMI handler code
The NMI handler is special, as it needs to leave with the same CR3 as it was entered with. This is required because the NMI can happen within kernel context but with user CR3 already loaded, i.e. after switching to user CR3 but before returning to user space. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Pavel Machek <pavel@ucw.cz> Cc: "H . Peter Anvin" <hpa@zytor.com> Cc: linux-mm@kvack.org Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Brian Gerst <brgerst@gmail.com> Cc: David Laight <David.Laight@aculab.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Eduardo Valentin <eduval@amazon.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Will Deacon <will.deacon@arm.com> Cc: aliguori@amazon.com Cc: daniel.gruss@iaik.tugraz.at Cc: hughd@google.com Cc: keescook@google.com Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Waiman Long <llong@redhat.com> Cc: "David H . Gutteridge" <dhgutteridge@sympatico.ca> Cc: joro@8bytes.org Link: https://lkml.kernel.org/r/1531906876-13451-14-git-send-email-joro@8bytes.org
-rw-r--r--arch/x86/entry/entry_32.S39
1 files changed, 33 insertions, 6 deletions
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 60b28dfa00dc..b1541c74c71a 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -210,8 +210,19 @@
210 210
211.endm 211.endm
212 212
213.macro SAVE_ALL_NMI 213.macro SAVE_ALL_NMI cr3_reg:req
214 SAVE_ALL 214 SAVE_ALL
215
216 /*
217 * Now switch the CR3 when PTI is enabled.
218 *
219 * We can enter with either user or kernel cr3, the code will
220 * store the old cr3 in \cr3_reg and switches to the kernel cr3
221 * if necessary.
222 */
223 SWITCH_TO_KERNEL_CR3 scratch_reg=\cr3_reg
224
225.Lend_\@:
215.endm 226.endm
216/* 227/*
217 * This is a sneaky trick to help the unwinder find pt_regs on the stack. The 228 * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
@@ -259,7 +270,23 @@
259 POP_GS_EX 270 POP_GS_EX
260.endm 271.endm
261 272
262.macro RESTORE_ALL_NMI pop=0 273.macro RESTORE_ALL_NMI cr3_reg:req pop=0
274 /*
275 * Now switch the CR3 when PTI is enabled.
276 *
277 * We enter with kernel cr3 and switch the cr3 to the value
278 * stored on \cr3_reg, which is either a user or a kernel cr3.
279 */
280 ALTERNATIVE "jmp .Lswitched_\@", "", X86_FEATURE_PTI
281
282 testl $PTI_SWITCH_MASK, \cr3_reg
283 jz .Lswitched_\@
284
285 /* User cr3 in \cr3_reg - write it to hardware cr3 */
286 movl \cr3_reg, %cr3
287
288.Lswitched_\@:
289
263 RESTORE_REGS pop=\pop 290 RESTORE_REGS pop=\pop
264.endm 291.endm
265 292
@@ -1331,7 +1358,7 @@ ENTRY(nmi)
1331#endif 1358#endif
1332 1359
1333 pushl %eax # pt_regs->orig_ax 1360 pushl %eax # pt_regs->orig_ax
1334 SAVE_ALL_NMI 1361 SAVE_ALL_NMI cr3_reg=%edi
1335 ENCODE_FRAME_POINTER 1362 ENCODE_FRAME_POINTER
1336 xorl %edx, %edx # zero error code 1363 xorl %edx, %edx # zero error code
1337 movl %esp, %eax # pt_regs pointer 1364 movl %esp, %eax # pt_regs pointer
@@ -1359,7 +1386,7 @@ ENTRY(nmi)
1359 1386
1360.Lnmi_return: 1387.Lnmi_return:
1361 CHECK_AND_APPLY_ESPFIX 1388 CHECK_AND_APPLY_ESPFIX
1362 RESTORE_ALL_NMI pop=4 1389 RESTORE_ALL_NMI cr3_reg=%edi pop=4
1363 jmp .Lirq_return 1390 jmp .Lirq_return
1364 1391
1365#ifdef CONFIG_X86_ESPFIX32 1392#ifdef CONFIG_X86_ESPFIX32
@@ -1375,12 +1402,12 @@ ENTRY(nmi)
1375 pushl 16(%esp) 1402 pushl 16(%esp)
1376 .endr 1403 .endr
1377 pushl %eax 1404 pushl %eax
1378 SAVE_ALL_NMI 1405 SAVE_ALL_NMI cr3_reg=%edi
1379 ENCODE_FRAME_POINTER 1406 ENCODE_FRAME_POINTER
1380 FIXUP_ESPFIX_STACK # %eax == %esp 1407 FIXUP_ESPFIX_STACK # %eax == %esp
1381 xorl %edx, %edx # zero error code 1408 xorl %edx, %edx # zero error code
1382 call do_nmi 1409 call do_nmi
1383 RESTORE_ALL_NMI 1410 RESTORE_ALL_NMI cr3_reg=%edi
1384 lss 12+4(%esp), %esp # back to espfix stack 1411 lss 12+4(%esp), %esp # back to espfix stack
1385 jmp .Lirq_return 1412 jmp .Lirq_return
1386#endif 1413#endif