"cli\n\t" \
"/* Switch to the per-CPU auxiliary stack */\n\t" \
"/* AMD64 SysV ABI: r11 is scratch register */\n\t" \
+ "/* Our stack top now contains a return address\n\t" \
+ " * pushed by call; this must be ignored when\n\t" \
+ " * saving the stack pointer to the interrupt\n\t" \
+ " * return structure, but taken into account when\n\t" \
+ " * we actually return execution\n\t" \
+ " */\n\t" \
"movq %rsp, %r11\n\t" \
"movq %gs:(" STRINGIFY(LCPU_AUXSP_OFFSET) "), %rsp\n\t"\
"/* Auxiliary stack is already ECTX aligned */\n\t" \
" * [ 1: 0]: Requestor Privilege Level - ring 0\n\t" \
" */\n\t" \
"pushq $(0x10)\n\t" \
- "/* Push saving original rsp stored in r11 */\n\t" \
+ "/* Push saving original rsp - 8 stored in r11 */\n\t" \
"pushq %r11\n\t" \
+ "/* Above pushed rsp is actually the caller's\n\t" \
+ " * rsp minus 8, because the call instruction\n\t" \
+ " * pushes the address the ret instruction is\n\t" \
+ " * supposed to return to. This means that to truly\n\t"\
+ " * mimic a trap/syscall we must store/restore\n\t" \
+ " * the rsp we were given, plus 8.\n\t" \
+ " */\n\t" \
+ "addq $8, (%rsp)\n\t" \
"/* Push EFLAGS register. Additionally, since we\n\t" \
" * pushed it with IRQs disabled, it won't have\n\t" \
" * the corresponding bit flag set, making it look\n\t" \
"popq %rbx\n\t" \
"/* Restore rsp from where it was stored */\n\t" \
"movq 104(%rsp), %rsp\n\t" \
+ "/* Adjust saved stack to original value; ret\n\t" \
+ " * expects return address on top of stack\n\t" \
+ " */\n\t" \
+ "subq $8, %rsp\n\t" \
"ret\n\t" \
);