Push the current stack pointer (SP) to the IRET frame in do_iret() to ensure a valid stack after IRET execution, particularly in 64-bit mode. Currently, do_iret() crafts an IRET frame with a zeroed SP. For 32-bit guests, SP is not popped during IRET due to no privilege change. so, the stack after IRET is still valid. But for 64-bit guests, IRET unconditionally pops RSP, restoring it to zero. This can cause a nested NMI to push its interrupt frame to the topmost page (0xffffffff_fffff000), which may be not mapped and cause triple fault [1]. To fix this issue, push the current SP to the IRET frame, ensuring RSP is restored to a valid stack in 64-bit mode. Reported-by: Sean Christopherson Signed-off-by: Chao Gao Link: https://lore.kernel.org/kvm/aMahfvF1r39Xq6zK@intel.com/ --- x86/eventinj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/x86/eventinj.c b/x86/eventinj.c index ec8a5ef1..63ebbaab 100644 --- a/x86/eventinj.c +++ b/x86/eventinj.c @@ -153,6 +153,7 @@ asm("do_iret:" "mov 8(%esp), %edx \n\t" // virt_stack #endif "xchg %"R "dx, %"R "sp \n\t" // point to new stack + "push"W" %"R "sp \n\t" "pushf"W" \n\t" "mov %cs, %ecx \n\t" "push"W" %"R "cx \n\t" -- 2.47.3