nuclear@52: #include nuclear@47: #include nuclear@52: #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@51: #include "syscall.h" nuclear@51: #include "sched.h" nuclear@47: nuclear@52: #define FLAGS_INTR_BIT 9 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@51: cur_pid = 0; nuclear@51: nuclear@51: init_syscall(); nuclear@42: nuclear@42: /* prepare the first process */ nuclear@51: proc[1].id = 1; nuclear@51: proc[1].parent = 0; 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@51: 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@51: memcpy(img_start, test_proc, proc_size_pg * PGSIZE); nuclear@45: nuclear@52: printf("copied init process at: %x\n", (unsigned int)img_start); nuclear@52: nuclear@47: /* instruction pointer at the beginning of the process image */ nuclear@51: proc[1].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@51: proc[1].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE; nuclear@47: nuclear@52: proc[1].stack_end = KMEM_START; nuclear@52: proc[1].stack_start = KMEM_START - PGSIZE; nuclear@52: nuclear@45: /* create the virtual address space for this process */ nuclear@51: proc[1].ctx.pgtbl_paddr = clone_vm(); nuclear@45: nuclear@47: /* we don't need the image and the stack in this address space */ nuclear@51: unmap_page_range(img_start_pg, proc_size_pg); nuclear@51: pgfree(img_start_pg, proc_size_pg); nuclear@45: nuclear@47: unmap_page(stack_pg); nuclear@47: pgfree(stack_pg, 1); nuclear@42: nuclear@51: /* add it to the scheduler queues */ nuclear@52: add_proc(1, STATE_RUNNING); nuclear@42: nuclear@51: /* switch to the initial process, this never returns */ nuclear@51: context_switch(1); nuclear@42: } nuclear@42: nuclear@47: nuclear@47: void context_switch(int pid) nuclear@42: { nuclear@52: struct context *ctx; nuclear@47: struct intr_frame ifrm; nuclear@52: struct intr_frame *cur_frame = get_intr_frame(); nuclear@47: nuclear@52: assert(0); nuclear@49: nuclear@52: if(cur_pid == pid) { nuclear@52: assert(cur_frame); nuclear@52: intr_ret(*cur_frame); nuclear@52: } nuclear@52: nuclear@52: ctx = &proc[pid].ctx; nuclear@47: cur_pid = pid; nuclear@47: nuclear@47: ifrm.inum = ifrm.err = 0; nuclear@47: nuclear@47: ifrm.regs = ctx->regs; nuclear@52: ifrm.eflags = ctx->flags | (1 << FLAGS_INTR_BIT); 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@52: /*ifrm.regs.esp = ctx->stack_ptr;*/ /* ... until then... */ nuclear@52: ifrm.esp = ctx->stack_ptr; /* this will only be used when we switch to userspace */ nuclear@52: ifrm.ss = selector(SEGM_KDATA, 0); nuclear@47: nuclear@47: /* switch to the vm of the process */ nuclear@47: set_pgdir_addr(ctx->pgtbl_paddr); nuclear@47: intr_ret(ifrm); nuclear@47: } nuclear@51: nuclear@51: int get_current_pid(void) nuclear@51: { nuclear@51: return cur_pid; nuclear@51: } nuclear@51: nuclear@51: struct process *get_current_proc(void) nuclear@51: { nuclear@51: return cur_pid ? &proc[cur_pid] : 0; nuclear@51: } nuclear@51: nuclear@51: struct process *get_process(int pid) nuclear@51: { nuclear@51: return &proc[pid]; nuclear@51: }