x86: Use a separate stack and handler for NMIs
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 25 Jul 2016 16:23:50 +0000 (12:23 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 27 Jul 2016 16:52:43 +0000 (12:52 -0400)
commit2d495bb5618abb468c54d95a7947b855c3074e84
treeb0aa015d24eb7ab3f00cc895b6ef0c40e068ec25
parentf15da24e4d8dc51ad02f8b508842661dbe0a9bfc
x86: Use a separate stack and handler for NMIs

It turns out that on x86_64, you *must* use a separate stack for
NMIs.  On i386, this was an option.  Why, you ask?  Because SYSCALL (64
bit) differs from SYSENTER (32 bit) in that SYSCALL does *not* set the
stack pointer for the kernel on entry.  It's up to the SYSCALL/SYSENTER
entry point software to figure out and set the stack pointer.

The problem is that if you receive an NMI before the kernel can set the
stack pointer.  If your NMI handler doesn't use a separate, pre-determined
stack, the interrupt hardware pushes the basic interrupt info onto the
*current* stack, which happens to be a user-controlled pointer at this
point.  Good times.

For more fun times, we also need to return to user TFs directly, and not
call proc_restartcore().  See the notes on handle_nmi() for more info.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/smp_boot.c
kern/arch/x86/trap.c
kern/arch/x86/trapentry64.S