On Mon, May 06, 2019 at 10:19:51AM +0200, Peter Zijlstra wrote:
+.Lfrom_usermode_no_fixup_@: +.endm
+.macro IRET_FRAME
- /* orig_eax is already POP'ed when we're here */
- testl $CS_FROM_KERNEL, 1*4(%esp)
- jz .Lfinished_frame_@
- pushl %eax
From there..
- lea 10*4(%esp), %eax # address of <previous context>
- cmpl %eax, 4*4(%esp) # if ->sp is unmodified
- jnz .Lmodified_sp_do_fixup_@
- /*
* Fast path; regs->sp wasn't modified, reuse the original IRET frame.
*/
- pop %eax
- add $6*4, %esp
- jmp .Lfinished_frame_@;
+.Lmodified_sp_do_fixup_@:
... until here, needs to go, it is buggy. While a clever idea, it looses updates to regs->ip and ->flags.
- /*
* Reconstruct the 3 entry IRET frame right after the (modified)
* regs->sp without lowering %esp in between, such that an NMI in the
* middle doesn't scribble our stack.
*/
- pushl %ecx
- movl 5*4(%esp), %eax # (modified) regs->sp
- movl 4*4(%esp), %ecx # flags
- movl %ecx, -4(%eax)
- movl 3*4(%esp), %ecx # cs
- andl $0x0000ffff, %ecx
- movl %ecx, -8(%eax)
- movl 2*4(%esp), %ecx # ip
- movl %ecx, -12(%eax)
- movl 1*4(%esp), %ecx # eax
- movl %ecx, -16(%eax)
- popl %ecx
- lea -16(%eax), %esp
- popl %eax
+.Lfinished_frame_@: +.endm