diff options
-rw-r--r-- | kernel/cpu/cpu.c | 62 | ||||
-rw-r--r-- | kernel/cpu/idt.S | 107 | ||||
-rw-r--r-- | kernel/cpu/idt.c | 40 | ||||
-rw-r--r-- | kernel/cpu/tss.c | 7 | ||||
-rw-r--r-- | kernel/include/comus/cpu.h | 7 | ||||
-rw-r--r-- | kernel/include/comus/memory.h | 5 | ||||
-rw-r--r-- | kernel/include/comus/procs.h | 11 | ||||
-rw-r--r-- | kernel/memory/memory.c | 21 | ||||
-rw-r--r-- | kernel/memory/physalloc.c | 1 | ||||
-rw-r--r-- | kernel/procs.c | 83 | ||||
-rw-r--r-- | kernel/syscall.c | 22 | ||||
-rw-r--r-- | kernel/user.c | 40 |
12 files changed, 272 insertions, 134 deletions
diff --git a/kernel/cpu/cpu.c b/kernel/cpu/cpu.c index 6ef5ef5..f607b36 100644 --- a/kernel/cpu/cpu.c +++ b/kernel/cpu/cpu.c @@ -1,5 +1,6 @@ #include <lib.h> #include <comus/cpu.h> +#include <comus/asm.h> #include "pic.h" #include "idt.h" @@ -61,8 +62,10 @@ void cpu_init(void) struct cpu_feat feats; cpu_feats(&feats); - pic_remap(); + cli(); idt_init(); + tss_init(); + pic_remap(); if (feats.fpu) fpu_init(); if (feats.sse) { @@ -74,8 +77,6 @@ void cpu_init(void) if (feats.avx) avx_init(); } - - tss_init(); } void cpu_report(void) @@ -181,25 +182,26 @@ void cpu_feats(struct cpu_feat *feats) void cpu_print_regs(struct cpu_regs *regs) { - kprintf("rax: %#016lx (%lu)\n", regs->rax, regs->rax); - kprintf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx); - kprintf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx); - kprintf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx); - kprintf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi); - kprintf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi); - kprintf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp); - kprintf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp); - kprintf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8); - kprintf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9); - kprintf("r10: %#016lx (%lu)\n", regs->r10, regs->r10); - kprintf("r11: %#016lx (%lu)\n", regs->r11, regs->r11); - kprintf("r12: %#016lx (%lu)\n", regs->r12, regs->r12); - kprintf("r13: %#016lx (%lu)\n", regs->r13, regs->r13); - kprintf("r14: %#016lx (%lu)\n", regs->r14, regs->r14); - kprintf("r15: %#016lx (%lu)\n", regs->r15, regs->r15); - kprintf("rip: %#016lx (%lu)\n", regs->rip, regs->rip); - kprintf("rflags: %#016lx (%lu)\n", regs->rflags, regs->rflags); - kputs("rflags: "); + kprintf("rax:\t%#016lx (%lu)\n", regs->rax, regs->rax); + kprintf("rbx:\t%#016lx (%lu)\n", regs->rbx, regs->rbx); + kprintf("rcx:\t%#016lx (%lu)\n", regs->rcx, regs->rcx); + kprintf("rdx:\t%#016lx (%lu)\n", regs->rdx, regs->rdx); + kprintf("rsi:\t%#016lx (%lu)\n", regs->rsi, regs->rsi); + kprintf("rdi:\t%#016lx (%lu)\n", regs->rdi, regs->rdi); + kprintf("rsp:\t%#016lx (%lu)\n", regs->rsp, regs->rsp); + kprintf("rbp:\t%#016lx (%lu)\n", regs->rbp, regs->rbp); + kprintf("r8:\t%#016lx (%lu)\n", regs->r8, regs->r8); + kprintf("r9:\t%#016lx (%lu)\n", regs->r9, regs->r9); + kprintf("r10:\t%#016lx (%lu)\n", regs->r10, regs->r10); + kprintf("r11:\t%#016lx (%lu)\n", regs->r11, regs->r11); + kprintf("r12:\t%#016lx (%lu)\n", regs->r12, regs->r12); + kprintf("r13:\t%#016lx (%lu)\n", regs->r13, regs->r13); + kprintf("r14:\t%#016lx (%lu)\n", regs->r14, regs->r14); + kprintf("r15:\t%#016lx (%lu)\n", regs->r15, regs->r15); + kprintf("rip:\t%#016lx (%lu)\n", regs->rip, regs->rip); + kprintf("rflags: %#016lx (%lu) [ ", regs->rflags, regs->rflags); + if (regs->rflags & (3 << 12)) + kprintf("IOPL=%lu ", (regs->rflags >> 12) & 0x3); if (regs->rflags & (1 << 0)) kputs("CF "); if (regs->rflags & (1 << 2)) @@ -218,8 +220,6 @@ void cpu_print_regs(struct cpu_regs *regs) kputs("DF "); if (regs->rflags & (1 << 11)) kputs("OF "); - if (regs->rflags & (3 << 12)) - kputs("IOPL "); if (regs->rflags & (1 << 14)) kputs("NT "); if (regs->rflags & (1 << 15)) @@ -236,5 +236,19 @@ void cpu_print_regs(struct cpu_regs *regs) kputs("VIP "); if (regs->rflags & (1 << 21)) kputs("ID "); + kputs("]\n"); + kprintf("cs:\t%#04lx (%lu) [ DPL=%lu ]\n", regs->cs, regs->cs, + regs->cs & 0x3); + kprintf("ss:\t%#04lx (%lu) [ DPL=%lu ]\n", regs->ss, regs->ss, + regs->ss & 0x3); + kprintf("ds:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->ds, regs->ds, + regs->ds & 0x3); + kprintf("es:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->es, regs->es, + regs->es & 0x3); + kprintf("fs:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->fs, regs->fs, + regs->fs & 0x3); + kprintf("gs:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->gs, regs->gs, + regs->gs & 0x3); + kprintf("cr3:\t%#016lx (%lu)\n", regs->cr3, regs->cr3); kputs("\n"); } diff --git a/kernel/cpu/idt.S b/kernel/cpu/idt.S index 06c70a0..05c34f5 100644 --- a/kernel/cpu/idt.S +++ b/kernel/cpu/idt.S @@ -1,6 +1,5 @@ .global isr_stub_table .global syscall_return - .global awd .extern idt_exception_handler .extern idt_pic_timer @@ -9,8 +8,10 @@ .extern idt_pic_eoi .extern syscall_handler .extern current_pcb + .extern isr_save .macro PUSHALL + # regs pushq %rax pushq %rbx pushq %rcx @@ -26,9 +27,38 @@ pushq %r13 pushq %r14 pushq %r15 + + # segments + movw %ds, %ax + pushw %ax + movw %es, %ax + pushw %ax + movw %fs, %ax + pushw %ax + movw %gs, %ax + pushw %ax + + # pgdir + movq %cr3, %rax + pushq %rax .endm .macro POPALL + # pgdir + popq %rax + movq %rax, %cr3 + + # segments + popw %ax + movw %ax, %gs + movw %ax, %fs + popw %ax + movw %ax, %es + popw %ax + movw %ax, %ds + popw %ax + + # regs popq %r15 popq %r14 popq %r13 @@ -46,19 +76,28 @@ popq %rax .endm +.macro ISRSave + PUSHALL + cld + movq %rsp, %rdi + callq isr_save +.endm + +.macro ISRRestore + POPALL + iretq +.endm + # call the exception handler with the interrupt number # args: interrupt number .macro ISRException num .align 8 isr_stub_\num: - PUSHALL - cld - movq $\num, %rdi # exception number + ISRSave + movq $\num, %rdi # exception number movq $0, %rsi # placeholder error code - movq %rsp, %rdx # top of stack callq idt_exception_handler - POPALL - iretq + ISRRestore .endm # call the exception handler with the interrupt number @@ -68,26 +107,21 @@ isr_stub_\num: .align 8 isr_stub_\num: # retrieve the error code without corrupting registers - mov %eax, isr_tmp + movq %rax, isr_tmp popq %rax - mov %eax, isr_err_code + movq %rax, isr_err_code movq isr_tmp, %rax - PUSHALL - cld + ISRSave movq $\num, %rdi # exception number movq isr_err_code, %rsi # error code - movq %rsp, %rdx # top of stack callq idt_exception_handler - POPALL - iretq + ISRRestore .endm .macro SYSCALL num .align 8 isr_stub_\num: - PUSHALL - cld - movq %rsp, %rdi # top of stack + ISRSave callq syscall_handler jmp syscall_return .endm @@ -95,48 +129,40 @@ isr_stub_\num: .macro PICGeneric num .align 8 isr_stub_\num: - PUSHALL - cld + ISRSave movq $\num, %rdi callq idt_pic_eoi - POPALL - iretq + ISRRestore .endm .macro PICTimer num .align 8 isr_stub_\num: - PUSHALL - cld + ISRSave callq idt_pic_timer movq $\num, %rdi callq idt_pic_eoi - POPALL - iretq + ISRRestore .endm .macro PICKeyboard num .align 8 isr_stub_\num: - PUSHALL - cld + ISRSave callq idt_pic_keyboard movq $\num, %rdi callq idt_pic_eoi - POPALL - iretq + ISRRestore .endm .macro PICMouse num .align 8 isr_stub_\num: - PUSHALL - cld + ISRSave callq idt_pic_mouse movq $\num, %rdi callq idt_pic_eoi - POPALL - iretq + ISRRestore .endm # do nothing @@ -421,18 +447,13 @@ isr_stub_table: # isr restore syscall_return: - movq current_pcb, %rbx // return user stack - movq 0(%rbx), %rsp // esp - movq 8(%rbx), %rcx // pml4 - movq (%rcx), %rcx - movq %rcx, %cr3 + // get current pcb address + movq current_pcb, %rbx - movw $(0x20 | 3), %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs + // load user stack + leaq 8(%rbx), %rsp + // return POPALL iretq diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c index 8bddc21..d071d29 100644 --- a/kernel/cpu/idt.c +++ b/kernel/cpu/idt.c @@ -3,6 +3,7 @@ #include <comus/asm.h> #include <comus/cpu.h> #include <comus/drivers/pit.h> +#include <comus/procs.h> #include <comus/memory.h> #include "idt.h" @@ -42,8 +43,12 @@ struct idtr { __attribute__((aligned(0x10))) static struct idt_entry idt[256]; static struct idtr idtr; -// from idt.S extern void *isr_stub_table[]; +extern char kern_stack_start[]; +extern char kern_stack_end[]; + +// current register state on interrupt +static struct cpu_regs *state; // initialize and load the IDT void idt_init(void) @@ -58,11 +63,10 @@ void idt_init(void) uint64_t isr = (uint64_t)isr_stub_table[vector]; // interrupts before 0x20 are for cpu exceptions - uint8_t gate_type = (vector < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT; entry->kernel_cs = 0x08; // offset of 1 into GDT entry->ist = 0; - entry->flags = PRESENT | RING0 | gate_type; + entry->flags = PRESENT | RING0 | GATE_64BIT_INT; entry->isr_low = isr & 0xffff; entry->isr_mid = (isr >> 16) & 0xffff; entry->isr_high = (isr >> 32) & 0xffffffff; @@ -115,14 +119,11 @@ char *EXCEPTIONS[] = { "Reserved", }; -void idt_exception_handler(uint64_t exception, uint64_t code, - struct cpu_regs *state) +__attribute__((noreturn)) void idt_exception_handler(uint64_t exception, + uint64_t code) { uint64_t cr2; - // make sure were in the kernel memory context - mem_ctx_switch(kernel_mem_ctx); - switch (exception) { case EX_PAGE_FAULT: // page faults store the offending address in cr2 @@ -151,16 +152,35 @@ void idt_exception_handler(uint64_t exception, uint64_t code, } } +void isr_save(struct cpu_regs *regs) +{ + // make sure were in the kernel memory context + mem_ctx_switch(kernel_mem_ctx); + + // save pointer to registers + state = regs; + + // if we have a kernel stack pointer + // we should return to not save kernel context + // data to userspace + if (regs->rsp >= (size_t)kern_stack_start && + regs->rsp <= (size_t)kern_stack_end) + return; + + // save registers in current_pcb + if (current_pcb != NULL) + current_pcb->regs = *regs; +} + void idt_pic_eoi(uint8_t exception) { pic_eoi(exception - PIC_REMAP_OFFSET); } -int counter = 0; - void idt_pic_timer(void) { ticks++; + pcb_on_tick(); } void idt_pic_keyboard(void) diff --git a/kernel/cpu/tss.c b/kernel/cpu/tss.c index 184b884..bca979d 100644 --- a/kernel/cpu/tss.c +++ b/kernel/cpu/tss.c @@ -1,6 +1,5 @@ -#include "comus/memory.h" -#include "lib/kstring.h" -#include <stdint.h> +#include <comus/memory.h> +#include <lib.h> #include "tss.h" @@ -48,7 +47,7 @@ extern volatile uint8_t GDT[]; static volatile struct sys_seg_descriptor *GDT_TSS; // kernel stack pointer -static char interrupt_stack[PAGE_SIZE*2]; +static char interrupt_stack[PAGE_SIZE * 2]; void tss_init(void) { diff --git a/kernel/include/comus/cpu.h b/kernel/include/comus/cpu.h index 3669000..df8f44e 100644 --- a/kernel/include/comus/cpu.h +++ b/kernel/include/comus/cpu.h @@ -31,6 +31,13 @@ struct cpu_feat { }; struct cpu_regs { + // pgdir + uint64_t cr3; + // segments + uint16_t gs; + uint16_t fs; + uint16_t es; + uint16_t ds; // registers uint64_t r15; uint64_t r14; diff --git a/kernel/include/comus/memory.h b/kernel/include/comus/memory.h index 408521b..47ea103 100644 --- a/kernel/include/comus/memory.h +++ b/kernel/include/comus/memory.h @@ -104,6 +104,11 @@ void mem_ctx_free(mem_ctx_t ctx); void mem_ctx_switch(mem_ctx_t ctx); /** + * @returns the pgdir pointer in the memory ctx + */ +volatile void *mem_ctx_pgdir(mem_ctx_t ctx); + +/** * Allocates at least len bytes of memory starting at * physical address addr. Returned address can be * any virtural address. diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h index 0150975..eb6c54f 100644 --- a/kernel/include/comus/procs.h +++ b/kernel/include/comus/procs.h @@ -15,8 +15,8 @@ #include <lib.h> #include <elf.h> -#define PCB_REG(pcb, x) ((pcb)->regs->x) -#define PCB_RET(pcb) ((pcb)->regs->rax) +#define PCB_REG(pcb, x) ((pcb)->regs.x) +#define PCB_RET(pcb) ((pcb)->regs.rax) #define PCB_ARG1(pcb) PCB_REG((pcb), rdi) #define PCB_ARG2(pcb) PCB_REG((pcb), rsi) #define PCB_ARG3(pcb) PCB_REG((pcb), rdx) @@ -47,8 +47,8 @@ enum proc_state { /// process control block struct pcb { // context - struct cpu_regs *regs; mem_ctx_t memctx; + struct cpu_regs regs; // metadata pid_t pid; @@ -224,4 +224,9 @@ void schedule(struct pcb *pcb); */ __attribute__((noreturn)) void dispatch(void); +/** + * Scheduler function called on every system tick + */ +void pcb_on_tick(void); + #endif /* procs.h */ diff --git a/kernel/memory/memory.c b/kernel/memory/memory.c index bd3e06b..ecfd639 100644 --- a/kernel/memory/memory.c +++ b/kernel/memory/memory.c @@ -71,7 +71,12 @@ mem_ctx_t mem_ctx_alloc(void) mem_ctx_t mem_ctx_clone(const mem_ctx_t old, bool cow) { - mem_ctx_t new = user_mem_ctx_next; + mem_ctx_t new; + + assert(old != NULL, "memory context is null"); + assert(old->pml4 != NULL, "pgdir is null"); + + new = user_mem_ctx_next; if (new == NULL) return NULL; @@ -93,6 +98,9 @@ mem_ctx_t mem_ctx_clone(const mem_ctx_t old, bool cow) void mem_ctx_free(mem_ctx_t ctx) { + assert(ctx != NULL, "memory context is null"); + assert(ctx->pml4 != NULL, "pgdir is null"); + pgdir_free(ctx->pml4); virtaddr_cleanup(&ctx->virtctx); @@ -107,9 +115,20 @@ void mem_ctx_free(mem_ctx_t ctx) void mem_ctx_switch(mem_ctx_t ctx) { + assert(ctx != NULL, "memory context is null"); + assert(ctx->pml4 != NULL, "pgdir is null"); + __asm__ volatile("mov %0, %%cr3" ::"r"(ctx->pml4) : "memory"); } +volatile void *mem_ctx_pgdir(mem_ctx_t ctx) +{ + assert(ctx != NULL, "memory context is null"); + assert(ctx->pml4 != NULL, "pgdir is null"); + + return ctx->pml4; +} + void memory_init(void) { struct memory_map mmap; diff --git a/kernel/memory/physalloc.c b/kernel/memory/physalloc.c index 55ece02..c5a74b7 100644 --- a/kernel/memory/physalloc.c +++ b/kernel/memory/physalloc.c @@ -1,4 +1,3 @@ -#include "lib/kio.h" #include <lib.h> #include <comus/memory.h> #include <comus/asm.h> diff --git a/kernel/procs.c b/kernel/procs.c index c1bcc4f..f3d855c 100644 --- a/kernel/procs.c +++ b/kernel/procs.c @@ -1,3 +1,4 @@ +#include <comus/drivers/pit.h> #include <comus/procs.h> #include <comus/error.h> #include <comus/cpu.h> @@ -179,45 +180,47 @@ void pcb_zombify(struct pcb *victim) // schedule init if zombie child found if (zchild != NULL && init_pcb->state == PROC_STATE_WAITING) { + pid_t pid; + int *status; + assert(pcb_queue_remove(zombie, zchild) == SUCCESS, "pcb_zombify: cannot remove zombie process from queue"); assert(pcb_queue_remove(waiting, init_pcb) == SUCCESS, "pcb_zombify: cannot remove waiting process from queue"); - // send exited pid to init - PCB_RET(init_pcb) = zchild->pid; - // set &status in init's waitpid call - int *ptr = (int *)PCB_ARG2(init_pcb); - if (ptr != NULL) { - mem_ctx_switch(init_pcb->memctx); - *ptr = zchild->exit_status; - mem_ctx_switch(kernel_mem_ctx); + pid = (pid_t)PCB_ARG1(init_pcb); + status = (int *)PCB_ARG2(init_pcb); + + // set exited pid and exist status in init's waitpid call + if (pid == 0 || pid == zchild->pid) { + PCB_RET(init_pcb) = zchild->pid; + if (status != NULL) { + mem_ctx_switch(init_pcb->memctx); + *status = zchild->exit_status; + mem_ctx_switch(kernel_mem_ctx); + } + schedule(init_pcb); } - // schedule init and cleanup child - schedule(init_pcb); pcb_cleanup(zchild); } // if the parent is waiting, wake it up and clean the victim, // otherwise the victim will become a zombie if (parent->state == PROC_STATE_WAITING) { - // verify that the parent is either waiting for this process - // or is waiting for any of its children - uint64_t target = PCB_ARG1(parent); + pid_t pid; + int *status; + + pid = (pid_t)PCB_ARG1(parent); + status = (int *)PCB_ARG2(parent); - if (target != 0 || target == victim->pid) { - // send exited pid to parent - PCB_RET(parent) = victim->pid; - // send &status to parent - int *ptr = (int *)PCB_ARG2(parent); - if (ptr != NULL) { + if (pid == 0 || pid == victim->pid) { + PCB_RET(parent) = zchild->pid; + if (status != NULL) { mem_ctx_switch(parent->memctx); - *ptr = victim->exit_status; + *status = victim->exit_status; mem_ctx_switch(kernel_mem_ctx); } - - // schedule the parent, and clean up the zombie schedule(parent); pcb_cleanup(victim); return; @@ -476,3 +479,39 @@ __attribute__((noreturn)) void dispatch(void) syscall_return(); } + +void pcb_on_tick(void) +{ + // procs not initalized yet + if (init_pcb == NULL) + return; + + // update on sleeping + do { + struct pcb *pcb; + + if (pcb_queue_empty(sleeping)) + break; + + pcb = pcb_queue_peek(sleeping); + assert(pcb != NULL, "sleeping queue should not be empty"); + + if (pcb->wakeup >= ticks) + break; + + if (pcb_queue_remove(sleeping, pcb)) + panic("failed to wake sleeping process: %d", pcb->pid); + + schedule(pcb); + } while (1); + + if (current_pcb) { + current_pcb->ticks--; + if (current_pcb->ticks < 1) { + // schedule another process + schedule(current_pcb); + current_pcb = NULL; + dispatch(); + } + } +} diff --git a/kernel/syscall.c b/kernel/syscall.c index b595b6a..44bfe5f 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -10,11 +10,11 @@ static struct pcb *pcb; -#define RET(type, name) type *name = (type *)(&pcb->regs->rax) -#define ARG1(type, name) type name = (type)(pcb->regs->rdi) -#define ARG2(type, name) type name = (type)(pcb->regs->rsi) -#define ARG3(type, name) type name = (type)(pcb->regs->rdx) -#define ARG4(type, name) type name = (type)(pcb->regs->rcx) +#define RET(type, name) type *name = (type *)(&pcb->regs.rax) +#define ARG1(type, name) type name = (type)(pcb->regs.rdi) +#define ARG2(type, name) type name = (type)(pcb->regs.rsi) +#define ARG3(type, name) type name = (type)(pcb->regs.rdx) +#define ARG4(type, name) type name = (type)(pcb->regs.rcx) __attribute__((noreturn)) static int sys_exit(void) { @@ -255,20 +255,16 @@ static int (*syscall_tbl[N_SYSCALLS])(void) = { [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks, }; -void syscall_handler(struct cpu_regs *regs) +void syscall_handler(void) { uint64_t num; int (*handler)(void); int ret = 1; - // make sure were in the kernel memory context - mem_ctx_switch(kernel_mem_ctx); - // update data pcb = current_pcb; - pcb->regs = regs; - num = pcb->regs->rax; - pcb->regs->rax = 0; + num = pcb->regs.rax; + pcb->regs.rax = 0; current_pcb = NULL; // check for invalid syscall @@ -287,7 +283,7 @@ void syscall_handler(struct cpu_regs *regs) // on failure, set rax if (ret) - pcb->regs->rax = ret; + pcb->regs.rax = ret; // return to current pcb current_pcb = pcb; diff --git a/kernel/user.c b/kernel/user.c index 9d933e5..ce24b3e 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -16,6 +16,10 @@ #define BLOCK_SIZE (PAGE_SIZE * 1000) static uint8_t *load_buffer = NULL; +#define USER_CODE 0x18 +#define USER_DATA 0x20 +#define RING3 3 + static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx) { Elf64_Phdr hdr; @@ -63,7 +67,7 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx) kunmapaddr(mapADDR); return 1; } - memcpyv(mapADDR + total_read, load_buffer, read); + memcpy(mapADDR + total_read, load_buffer, read); total_read += read; } @@ -156,16 +160,28 @@ static int user_setup_stack(struct pcb *pcb) F_WRITEABLE | F_UNPRIVILEGED) == NULL) return 1; - // setup initial context save area - pcb->regs = (struct cpu_regs *)(USER_STACK_TOP - sizeof(struct cpu_regs)); - mem_ctx_switch(pcb->memctx); - memset(pcb->regs, 0, sizeof(struct cpu_regs)); - pcb->regs->rip = pcb->elf_header.e_entry; - pcb->regs->cs = 0x18 | 3; - pcb->regs->rflags = (1 << 9); - pcb->regs->rsp = USER_STACK_TOP; - pcb->regs->ss = 0x20 | 3; - mem_ctx_switch(kernel_mem_ctx); + memset(&pcb->regs, 0, sizeof(struct cpu_regs)); + + // pgdir + pcb->regs.cr3 = (uint64_t)mem_ctx_pgdir(pcb->memctx); + // segments + pcb->regs.gs = USER_DATA | RING3; + pcb->regs.fs = USER_DATA | RING3; + pcb->regs.es = USER_DATA | RING3; + pcb->regs.ds = USER_DATA | RING3; + // registers + pcb->regs.rdi = 0; // argc + pcb->regs.rsi = 0; // argv + // intruction pointer + pcb->regs.rip = pcb->elf_header.e_entry; + // code segment + pcb->regs.cs = 0x18 | 3; + // rflags + pcb->regs.rflags = (1 << 9); + // stack pointer + pcb->regs.rsp = USER_STACK_TOP; + // stack segment + pcb->regs.ss = 0x20 | 3; return 0; } @@ -176,8 +192,6 @@ int user_load(struct pcb *pcb, struct disk *disk) if (pcb == NULL || disk == NULL) return 1; - pcb->regs = NULL; - // allocate memory context pcb->memctx = mem_ctx_alloc(); if (pcb->memctx == NULL) |