# HG changeset patch # User John Tsiombikas # Date 1311820984 -10800 # Node ID f65b348780e34b60d01a5e9524d98468d1b175ac # Parent b793b8fcba7d6ef6f2c2c15f2d71360948971449 continuing with the process implementation. not done yet, panics. diff -r b793b8fcba7d -r f65b348780e3 src/intr-asm.S --- a/src/intr-asm.S Thu Jul 28 05:33:59 2011 +0300 +++ b/src/intr-asm.S Thu Jul 28 05:43:04 2011 +0300 @@ -70,6 +70,9 @@ intr_entry_common: pusha call dispatch_intr + + .globl intr_ret +intr_ret: popa /* remove error code and intr num from stack */ add $8, %esp diff -r b793b8fcba7d -r f65b348780e3 src/intr.c --- a/src/intr.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/intr.c Thu Jul 28 05:43:04 2011 +0300 @@ -35,21 +35,6 @@ #define OCW2_EOI (1 << 5) -/* structure used to pass the interrupt stack frame from the - * entry points to the C dispatch function. - */ -struct intr_frame { - /* registers pushed by pusha in intr_entry_* */ - struct registers regs; - /* interrupt number and error code pushed in intr_entry_* */ - uint32_t inum, err; - /* pushed by CPU during interrupt entry */ - uint32_t eip, cs, eflags; - /* pushed by CPU during interrupt entry from user space */ - uint32_t esp, ss; -}; - - static void init_pic(int offset); static void gate_desc(desc_t *desc, uint16_t sel, uint32_t addr, int dpl, int type); static void set_intr_entry(int num, void (*handler)(void)); diff -r b793b8fcba7d -r f65b348780e3 src/intr.h --- a/src/intr.h Thu Jul 28 05:33:59 2011 +0300 +++ b/src/intr.h Thu Jul 28 05:43:04 2011 +0300 @@ -12,6 +12,21 @@ /* checks whether a particular interrupt is an remapped IRQ */ #define IS_IRQ(n) ((n) >= IRQ_OFFSET && (n) < IRQ_OFFSET + 16) +/* structure used to pass the interrupt stack frame from the + * entry points to the C dispatch function. + */ +struct intr_frame { + /* registers pushed by pusha in intr_entry_* */ + struct registers regs; + /* interrupt number and error code pushed in intr_entry_* */ + uint32_t inum, err; + /* pushed by CPU during interrupt entry */ + uint32_t eip, cs, eflags; + /* pushed by CPU during interrupt entry from user space */ + uint32_t esp, ss; +}; + + typedef void (*intr_func_t)(int, uint32_t); @@ -24,4 +39,6 @@ int get_intr_state(void); void set_intr_state(int s); +void intr_ret(struct intr_frame ifrm); + #endif /* INTR_H_ */ diff -r b793b8fcba7d -r f65b348780e3 src/main.c --- a/src/main.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/main.c Thu Jul 28 05:43:04 2011 +0300 @@ -9,6 +9,7 @@ #include "timer.h" #include "mem.h" #include "vm.h" +#include "proc.h" void kmain(struct mboot_info *mbinf) @@ -41,6 +42,8 @@ /* initialization complete, enable interrupts */ enable_intr(); + init_proc(); + for(;;) { halt_cpu(); diff -r b793b8fcba7d -r f65b348780e3 src/proc.c --- a/src/proc.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/proc.c Thu Jul 28 05:43:04 2011 +0300 @@ -1,13 +1,22 @@ +#include #include "proc.h" #include "tss.h" #include "vm.h" +#include "segm.h" +#include "intr.h" +#include "panic.h" + + +/* defined in test_proc.S */ +void test_proc(void); +void test_proc_end(void); static struct process proc[MAX_PROC]; static int cur_pid; void init_proc(void) { - int proc_size_pg, img_start_pg; + int proc_size_pg, img_start_pg, stack_pg; void *img_start; cur_pid = -1; @@ -24,30 +33,56 @@ img_start = (void*)PAGE_TO_ADDR(img_start_pg); memcpy(img_start, test_proc, proc_size_pg * PGSIZE); + /* instruction pointer at the beginning of the process image */ + proc[0].ctx.instr_ptr = (uint32_t)img_start; + + /* allocate the first page of the process stack */ + stack_pg = ADDR_TO_PAGE(KMEM_START) - 1; + if(pgalloc_vrange(stack_pg, 1) == -1) { + panic("failed to allocate user stack page\n"); + } + proc[0].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE; + /* create the virtual address space for this process */ - proc[0].ctx.pgtbl_paddr = clone_vmem(); + proc[0].ctx.pgtbl_paddr = clone_vm(); - /* we don't need the image in this address space */ - unmap_pa + /* we don't need the image and the stack in this address space */ + unmap_page_range(img_start_pg, proc_size_pg); pgfree(img_start_pg, proc_size_pg); + unmap_page(stack_pg); + pgfree(stack_pg, 1); - /* fill in the proc[0].ctx with the appropriate process stack - * and instruction pointers - */ /* switch to it by calling a function that takes the context * of the current process, plugs the values into the interrupt * stack, and calls iret. * (should also set ss0/sp0 in TSS before returning) */ + context_switch(0); + /* XXX this will never return */ } -/* -void save_context(struct intr_frame *ifrm) + +void context_switch(int pid) { - proc[cur_pid].ctx->regs = ifrm->regs; - proc[cur_pid].ctx->instr_ptr = ifrm->eip; - proc[cur_pid].ctx->stack_ptr = ifrm->esp; - proc[cur_pid].ctx->flags = ifrm->eflags; -}*/ + struct intr_frame ifrm; + struct context *ctx = &proc[pid].ctx; + + cur_pid = pid; + + ifrm.inum = ifrm.err = 0; + + ifrm.regs = ctx->regs; + ifrm.eflags = ctx->flags; + + ifrm.eip = ctx->instr_ptr; + ifrm.cs = SEGM_KCODE; /* XXX change this when we setup the TSS */ + ifrm.esp = ctx->stack_ptr; + ifrm.ss = SEGM_KDATA; /* XXX */ + + /* switch to the vm of the process */ + set_pgdir_addr(ctx->pgtbl_paddr); + + intr_ret(ifrm); +} diff -r b793b8fcba7d -r f65b348780e3 src/proc.h --- a/src/proc.h Thu Jul 28 05:33:59 2011 +0300 +++ b/src/proc.h Thu Jul 28 05:43:04 2011 +0300 @@ -7,17 +7,22 @@ #define MAX_PROC 128 struct context { - struct registers regs; - uint32_t instr_ptr; - uint32_t stack_ptr; - uint32_t flags; - uint32_t pgtbl_paddr; + struct registers regs; /* saved general purpose registers */ + uint32_t instr_ptr; /* saved eip */ + uint32_t stack_ptr; /* saved esp */ + uint32_t flags; /* saved eflags */ + uint32_t pgtbl_paddr; /* physical address of the page table */ /* TODO add FPU state */ }; struct process { + int parent; struct context ctx; }; +void init_proc(void); + +void context_switch(int pid); + #endif /* PROC_H_ */ diff -r b793b8fcba7d -r f65b348780e3 src/segm.c --- a/src/segm.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/segm.c Thu Jul 28 05:43:04 2011 +0300 @@ -43,7 +43,7 @@ segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA); segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE); segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA); - /*task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY);*/ + task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY); set_gdt((uint32_t)gdt, sizeof gdt - 1); diff -r b793b8fcba7d -r f65b348780e3 src/timer.c --- a/src/timer.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/timer.c Thu Jul 28 05:43:04 2011 +0300 @@ -69,9 +69,4 @@ static void intr_handler() { nticks++; - - if(nticks % TICK_FREQ_HZ == 0) { - time_t t = time(0); - printf("%s", asctime(gmtime(&t))); - } } diff -r b793b8fcba7d -r f65b348780e3 src/vm.c --- a/src/vm.c Thu Jul 28 05:33:59 2011 +0300 +++ b/src/vm.c Thu Jul 28 05:43:04 2011 +0300 @@ -8,7 +8,6 @@ #include "panic.h" -#define KMEM_START 0xc0000000 #define IDMAP_START 0xa0000 #define PGDIR_ADDR 0xfffff000 @@ -56,6 +55,7 @@ void init_vm(void) { uint32_t idmap_end; + int i, kmem_start_pg, pgtbl_base_pg; /* setup the page tables */ pgdir = (uint32_t*)alloc_phys_page(); @@ -79,15 +79,29 @@ /* initialize the virtual page allocator */ node_pool = 0; - first_node.start = ADDR_TO_PAGE(KMEM_START); - first_node.end = ADDR_TO_PAGE(PGTBL_BASE); + kmem_start_pg = ADDR_TO_PAGE(KMEM_START); + pgtbl_base_pg = ADDR_TO_PAGE(PGTBL_BASE); + + first_node.start = kmem_start_pg; + first_node.end = pgtbl_base_pg; first_node.next = 0; pglist[MEM_KERNEL] = &first_node; pglist[MEM_USER] = alloc_node(); pglist[MEM_USER]->start = ADDR_TO_PAGE(idmap_end); - pglist[MEM_USER]->end = ADDR_TO_PAGE(KMEM_START); + pglist[MEM_USER]->end = kmem_start_pg; pglist[MEM_USER]->next = 0; + + /* temporaroly map something into every 1024th page of the kernel address + * space to force pre-allocation of all the kernel page-tables + */ + for(i=kmem_start_pg; i= ADDR_TO_PAGE(KMEM_START)) ? MEM_KERNEL : MEM_USER; - if(area == KMEM_USER && start + num > ADDR_TO_PAGE(KMEM_START)) { + if(area == MEM_USER && start + num > ADDR_TO_PAGE(KMEM_START)) { printf("pgalloc_vrange: invalid range request crossing user/kernel split\n"); return -1; } @@ -447,7 +461,7 @@ if(node_pool) { node = node_pool; node_pool = node_pool->next; - printf("alloc_node -> %x\n", (unsigned int)node); + /*printf("alloc_node -> %x\n", (unsigned int)node);*/ return node; } @@ -468,7 +482,7 @@ /* grab the first and return it */ node = node_pool++; - printf("alloc_node -> %x\n", (unsigned int)node); + /*printf("alloc_node -> %x\n", (unsigned int)node);*/ return node; } @@ -476,26 +490,34 @@ { node->next = node_pool; node_pool = node; - printf("free_node\n"); + /*printf("free_node\n");*/ } -/* clone_vmem makes a copy of the current page tables, thus duplicating - * the virtual address space. +/* clone_vm makes a copy of the current page tables, thus duplicating the + * virtual address space. + * + * For the kernel part of the address space (last 256 page directory entries) + * we don't want to diplicate the page tables, just point all page directory + * entries to the same set of page tables. * * Returns the physical address of the new page directory. */ -uint32_t clone_vmem(void) +uint32_t clone_vm(void) { - int i, dirpg, tblpg; + int i, dirpg, tblpg, kmem_start_pg; uint32_t paddr; uint32_t *ndir, *ntbl; + /* allocate the new page directory */ if((dirpg = pgalloc(1, MEM_KERNEL)) == -1) { panic("clone_vmem: failed to allocate page directory page\n"); } ndir = (uint32_t*)PAGE_TO_ADDR(dirpg); + /* allocate a virtual page for temporarily mapping all new + * page tables while we populate them. + */ if((tblpg = pgalloc(1, MEM_KERNEL)) == -1) { panic("clone_vmem: failed to allocate page table page\n"); } @@ -506,7 +528,10 @@ */ free_phys_page(virt_to_phys(tblpg)); - for(i=0; i<1024; i++) { + kmem_start_pg = ADDR_TO_PAGE(KMEM_START); + + /* user space */ + for(i=0; i #include "mboot.h" +#define KMEM_START 0xc0000000 + /* page mapping flags */ #define PG_PRESENT (1 << 0) #define PG_WRITABLE (1 << 1) @@ -52,10 +54,14 @@ }; int pgalloc(int num, int area); +int pgalloc_vrange(int start, int num); void pgfree(int start, int num); -uint32_t clone_vmem(void); +uint32_t clone_vm(void); void dbg_print_vm(int area); +/* defined in vm-asm.S */ +void set_pgdir_addr(uint32_t addr); + #endif /* VM_H_ */