@@ -326,8 +326,24 @@ syscall_return_via_sysret:
326326 popq %rsi /* skip rcx */
327327 popq %rdx
328328 popq %rsi
329+
330+ /*
331+ * Now all regs are restored except RSP and RDI.
332+ * Save old stack pointer and switch to trampoline stack.
333+ */
334+ movq %rsp , %rdi
335+ movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
336+
337+ pushq RSP-RDI(%rdi ) /* RSP */
338+ pushq (%rdi ) /* RDI */
339+
340+ /*
341+ * We are on the trampoline stack. All regs except RDI are live.
342+ * We can do future final exit work right here.
343+ */
344+
329345 popq %rdi
330- movq RSP-ORIG_RAX( %rsp ), %rsp
346+ popq %rsp
331347 USERGS_SYSRET64
332348END(entry_SYSCALL_64)
333349
@@ -630,10 +646,41 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode)
630646 ud2
6316471:
632648#endif
633- SWAPGS
634649 POP_EXTRA_REGS
635- POP_C_REGS
636- addq $8 , %rsp /* skip regs->orig_ax */
650+ popq %r11
651+ popq %r10
652+ popq %r9
653+ popq %r8
654+ popq %rax
655+ popq %rcx
656+ popq %rdx
657+ popq %rsi
658+
659+ /*
660+ * The stack is now user RDI, orig_ax, RIP, CS, EFLAGS, RSP, SS.
661+ * Save old stack pointer and switch to trampoline stack.
662+ */
663+ movq %rsp , %rdi
664+ movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
665+
666+ /* Copy the IRET frame to the trampoline stack. */
667+ pushq 6*8 (%rdi ) /* SS */
668+ pushq 5*8 (%rdi ) /* RSP */
669+ pushq 4*8 (%rdi ) /* EFLAGS */
670+ pushq 3*8 (%rdi ) /* CS */
671+ pushq 2*8 (%rdi ) /* RIP */
672+
673+ /* Push user RDI on the trampoline stack. */
674+ pushq (%rdi )
675+
676+ /*
677+ * We are on the trampoline stack. All regs except RDI are live.
678+ * We can do future final exit work right here.
679+ */
680+
681+ /* Restore RDI. */
682+ popq %rdi
683+ SWAPGS
637684 INTERRUPT_RETURN
638685
639686
0 commit comments