nuclear@47: #include nuclear@42: #include "proc.h" nuclear@42: #include "tss.h" nuclear@45: #include "vm.h" nuclear@47: #include "segm.h" nuclear@47: #include "intr.h" nuclear@47: #include "panic.h" nuclear@47: nuclear@47: nuclear@47: /* defined in test_proc.S */ nuclear@47: void test_proc(void); nuclear@47: void test_proc_end(void); nuclear@42: nuclear@42: static struct process proc[MAX_PROC]; nuclear@42: static int cur_pid; nuclear@42: nuclear@42: void init_proc(void) nuclear@42: { nuclear@47: int proc_size_pg, img_start_pg, stack_pg; nuclear@45: void *img_start; nuclear@42: cur_pid = -1; nuclear@42: nuclear@42: /* prepare the first process */ nuclear@42: nuclear@42: /* allocate a chunk of memory for the process image nuclear@42: * and copy the code of test_proc there. nuclear@42: * (should be mapped at a fixed address) nuclear@42: */ nuclear@49: /*proc_size_pg = (test_proc_end - test_proc) / PGSIZE + 1; nuclear@45: if((img_start_pg = pgalloc(proc_size_pg, MEM_USER)) == -1) { nuclear@45: panic("failed to allocate space for the init process image\n"); nuclear@45: } nuclear@45: img_start = (void*)PAGE_TO_ADDR(img_start_pg); nuclear@49: memcpy(img_start, test_proc, proc_size_pg * PGSIZE);*/ nuclear@49: img_start = test_proc; nuclear@45: nuclear@47: /* instruction pointer at the beginning of the process image */ nuclear@47: proc[0].ctx.instr_ptr = (uint32_t)img_start; nuclear@47: nuclear@47: /* allocate the first page of the process stack */ nuclear@47: stack_pg = ADDR_TO_PAGE(KMEM_START) - 1; nuclear@47: if(pgalloc_vrange(stack_pg, 1) == -1) { nuclear@47: panic("failed to allocate user stack page\n"); nuclear@47: } nuclear@47: proc[0].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE; nuclear@47: nuclear@45: /* create the virtual address space for this process */ nuclear@47: proc[0].ctx.pgtbl_paddr = clone_vm(); nuclear@45: nuclear@47: /* we don't need the image and the stack in this address space */ nuclear@49: /*unmap_page_range(img_start_pg, proc_size_pg); nuclear@49: pgfree(img_start_pg, proc_size_pg);*/ nuclear@45: nuclear@47: unmap_page(stack_pg); nuclear@47: pgfree(stack_pg, 1); nuclear@42: nuclear@42: nuclear@42: /* switch to it by calling a function that takes the context nuclear@42: * of the current process, plugs the values into the interrupt nuclear@42: * stack, and calls iret. nuclear@42: * (should also set ss0/sp0 in TSS before returning) nuclear@42: */ nuclear@47: context_switch(0); nuclear@47: /* XXX this will never return */ nuclear@42: } nuclear@42: nuclear@47: nuclear@47: void context_switch(int pid) nuclear@42: { nuclear@47: struct intr_frame ifrm; nuclear@47: struct context *ctx = &proc[pid].ctx; nuclear@47: nuclear@49: nuclear@47: cur_pid = pid; nuclear@47: nuclear@47: ifrm.inum = ifrm.err = 0; nuclear@47: nuclear@47: ifrm.regs = ctx->regs; nuclear@47: ifrm.eflags = ctx->flags; nuclear@47: nuclear@47: ifrm.eip = ctx->instr_ptr; nuclear@49: ifrm.cs = selector(SEGM_KCODE, 0); /* XXX change this when we setup the TSS */ nuclear@49: ifrm.esp = 0;/*ctx->stack_ptr; /* this will only be used when we switch to userspace */ nuclear@49: ifrm.regs.esp = ctx->stack_ptr; /* ... until then... */ nuclear@49: ifrm.ss = 0;/*selector(SEGM_KDATA, 0); /* XXX */ nuclear@47: nuclear@47: /* switch to the vm of the process */ nuclear@47: set_pgdir_addr(ctx->pgtbl_paddr); nuclear@47: nuclear@47: intr_ret(ifrm); nuclear@47: }