diff options
Diffstat (limited to 'src/kernel/arch/amd64/sysenter.s')
-rw-r--r-- | src/kernel/arch/amd64/sysenter.s | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s index 4dfe19d..74db018 100644 --- a/src/kernel/arch/amd64/sysenter.s +++ b/src/kernel/arch/amd64/sysenter.s @@ -3,9 +3,10 @@ .set SEG_r3code, 3 .set SEG_r3data, 4 -.set IA32_SYSENTER_CS, 0x174 -.set IA32_SYSENTER_ESP, 0x175 -.set IA32_SYSENTER_EIP, 0x176 +.set IA32_STAR, 0xC0000081 +.set IA32_LSTAR, 0xC0000082 +.set IA32_CSTAR, 0xC0000083 +.set IA32_FMASK, 0xC0000084 .section .text .global sysenter_setup @@ -13,81 +14,101 @@ sysenter_setup: xor %rdx, %rdx - mov $(SEG_r0code << 3), %rax - mov $IA32_SYSENTER_CS, %rcx + // the intel docs don't mention the lower 32 bits + mov $( ((SEG_r3code << 3 | 3) << 48) | ((SEG_r0code << 3) << 32) ), %rax + mov $IA32_STAR, %rcx wrmsr - mov $IA32_SYSENTER_ESP, %rcx - mov $0, %rax // unused - wrmsr - - mov $IA32_SYSENTER_EIP, %rcx + mov $IA32_LSTAR, %rcx mov $sysenter_stage1, %rax wrmsr + // hoping that the default RFLAGS mask is fine... + ret .section .shared -.global stored_eax -stored_eax: -.long 0 +.global stored_rsp +stored_rsp: + .skip 8 .global pagedir_current // a hack to maintain compat with the old arch api, TODO pagedir_current: -.long 0 + .skip 8 .global _sysexit_real .type _sysexit_real, @function _sysexit_real: - xchgw %bx, %bx + /* mov $(SEG_r3data << 3 | 3), %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs + */ + + xchgw %bx, %bx - // restore the registers 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 - add $8, %rsp + pop (stored_rsp) + pop %rbx pop %rdx pop %rcx pop %rax // enable paging - // %rsp used as a scratch register mov (pagedir_current), %rsp mov %rsp, %cr3 - sysexit + mov (stored_rsp), %rsp + nop + sysretq sysenter_stage1: - cli /* prevent random IRQs in the middle of kernel code */ + cli xchgw %bx, %bx - // disable paging - // I don't want to damage any of the registers passed in by the user, - // so i'm using ESP as a temporary register. At this point there's nothing - // useful in it, it's == _bss_end. - mov %cr0, %rsp - and $0x7FFFFFFF, %rsp // disable paging - mov %rsp, %cr0 + mov %rsp, (stored_rsp) + + mov $pml4_identity, %rsp + mov %rsp, %cr3 - // save the registers - mov $(_sysexit_regs + 64), %rsp + mov $(_sysexit_regs + 128), %rsp push %rax push %rcx push %rdx push %rbx - push $0x0 // pushal pushes %rsp here, but that's worthless + + 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 jmp sysenter_stage2 |