// gdt.h .set SEG_r0code, 1 .set SEG_r3code32, 3 .set SEG_r3data, 4 .set SEG_r3code, 5 .set IA32_STAR, 0xC0000081 .set IA32_LSTAR, 0xC0000082 .set IA32_CSTAR, 0xC0000083 .set IA32_FMASK, 0xC0000084 .section .text .global sysenter_setup .type sysenter_setup, @function sysenter_setup: // the intel docs don't mention the lower 32 bits mov $0, %eax mov $( ((SEG_r3code32 << 3 | 3) << 16) | (SEG_r0code << 3) ), %edx mov $IA32_STAR, %rcx wrmsr mov $sysenter_stage1, %eax mov $0, %edx mov $IA32_LSTAR, %rcx wrmsr // hoping that the default RFLAGS mask is fine... ret .section .shared .global stored_rsp stored_rsp: .skip 8 .global pagedir_current // TODO make into an argument of sysexit pagedir_current: .skip 8 /* fake stack used for IRET */ .align 8 iret_stack: iret_ip: .skip 8 iret_cs: .quad SEG_r3code << 3 | 3 iret_flags: .skip 8 iret_sp: .skip 8 iret_ss: .quad SEG_r3data << 3 | 3 .global _sysexit_real .type _sysexit_real, @function _sysexit_real: mov $(SEG_r3data << 3 | 3), %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs mov $_sysexit_regs, %rsp pop %r15 pop %r14 pop %r13 pop %r12 pop %r11 pop %r10 pop %r9 pop %r8 pop %rdi pop %rsi pop %rbp pop (iret_sp) pop %rbx pop %rdx pop %rcx pop %rax pop (iret_ip) pop (iret_flags) /* The state image referenced with an FXRSTOR instruction must have * been saved using an FXSAVE instruction or be in the same format * as required [...] will result in an incorrect state restoration. */ fxrstor (%rsp) mov (pagedir_current), %rsp mov %rsp, %cr3 mov $iret_stack, %rsp iretq sysenter_stage1: cli mov %rsp, (stored_rsp) mov $pml4_identity, %rsp mov %rsp, %cr3 mov $(_sysexit_regs + 144), %rsp fxsave (%rsp) push %r11 /* flags */ push %rcx /* ip */ push %rax push %rcx push %rdx push %rbx push (stored_rsp) push %rbp push %rsi push %rdi push %r8 push %r9 push %r10 push %r11 push %r12 push %r13 push %r14 push %r15 mov $_bss_end, %rsp push $0 // for stacktraces jmp sysenter_stage2