diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/arch/amd64/registers.h | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.s | 46 | ||||
-rw-r--r-- | src/kernel/execbuf.c | 2 | ||||
-rw-r--r-- | src/kernel/proc.c | 6 |
4 files changed, 31 insertions, 25 deletions
diff --git a/src/kernel/arch/amd64/registers.h b/src/kernel/arch/amd64/registers.h index 5fd09c9..cfbfa54 100644 --- a/src/kernel/arch/amd64/registers.h +++ b/src/kernel/arch/amd64/registers.h @@ -7,7 +7,7 @@ struct CpuRegs { uint64_t r15, r14, r13, r12, r11, r10, r9, r8; uint64_t rdi, rsi; userptr_t rbp, rsp; - uint64_t rbx, rdx, rcx, rax; + uint64_t rbx, rdx, rcx, rax, rip, flags; uint8_t _sse[512]; } __attribute__((__packed__)); diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s index 8d91c4a..8e07dbb 100644 --- a/src/kernel/arch/amd64/sysenter.s +++ b/src/kernel/arch/amd64/sysenter.s @@ -41,13 +41,19 @@ stored_rsp: pagedir_current: .skip 8 -// temporarily used for IRET +/* 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 - .skip 8 - .skip 8 -dumb_stack: +iret_ss: + .quad SEG_r3data << 3 | 3 .global _sysexit_real .type _sysexit_real, @function @@ -58,12 +64,6 @@ _sysexit_real: mov %ax, %fs mov %ax, %gs - /* 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. */ - // TODO will probably end up fucking something up in a hard to debug way - // sorry, future me. hopefully you have learned something from this - fxrstor (_sysexit_regs + 128) mov $_sysexit_regs, %rsp pop %r15 pop %r14 @@ -78,23 +78,25 @@ _sysexit_real: pop %rdi pop %rsi pop %rbp - pop (stored_rsp) + pop (iret_sp) pop %rbx pop %rdx pop %rcx pop %rax - // enable paging + 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 $dumb_stack, %rsp - push $(SEG_r3data << 3 | 3) /* SS */ - push (stored_rsp) /* SP */ - push %r11 /* FLAGS */ - push $(SEG_r3code << 3 | 3) /* CS */ - push %rcx /* IP */ + mov $iret_stack, %rsp iretq sysenter_stage1: @@ -105,8 +107,12 @@ sysenter_stage1: mov $pml4_identity, %rsp mov %rsp, %cr3 - fxsave (_sysexit_regs + 128) - mov $(_sysexit_regs + 128), %rsp + mov $(_sysexit_regs + 144), %rsp + fxsave (%rsp) + + push %r11 /* flags */ + push %rcx /* ip */ + push %rax push %rcx push %rdx diff --git a/src/kernel/execbuf.c b/src/kernel/execbuf.c index fe9e159..71fc662 100644 --- a/src/kernel/execbuf.c +++ b/src/kernel/execbuf.c @@ -36,7 +36,7 @@ _Noreturn void execbuf_run(Proc *proc) { case EXECBUF_JMP: try_fetch(proc, buf, 1); - proc->regs.rcx = buf[0]; + proc->regs.rip = buf[0]; break; default: diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 6cc1679..a22f632 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -40,7 +40,7 @@ Proc *proc_seed(void *data, size_t datalen) { for (uintptr_t off = 0; off < datalen; off += PAGE_SIZE) pagedir_map(proc_first->pages, init_base + off, data + off, true, true); - proc_first->regs.rcx = (uintptr_t)init_base; // SYSRET jumps to %rcx + proc_first->regs.rip = (uintptr_t)init_base; // proc_first->regs.r11 |= 1<<9; /* enable interrupts */ return proc_first; @@ -372,12 +372,12 @@ void proc_intr(Proc *p, const char *buf, size_t len) { /* save old rsp,rip */ struct intr_data d; void __user *sp = p->regs.rsp - 128 - sizeof(d); - d.ip = (void __user *)p->regs.rcx; + d.ip = (void __user *)p->regs.rip; d.sp = p->regs.rsp; pcpy_to(p, sp, &d, sizeof(d)); /* switch to intr handler */ - p->regs.rcx = (uint64_t)p->intr_fn; + p->regs.rip = (uint64_t)p->intr_fn; p->regs.rsp = sp; } |