// proc.c // Author: Josh Holtrop // Date; 08/18/05 // Modified: 08/18/05 extern int mm_freepages; #include "hos_defines.h" #include "proc.h" #include "mm/mm.h" #include "mm/vmm.h" #include "lang/lang.h" #include "kernel.h" u32_t cur_task = 0; u32_t n_processes = 0; process_t *processes[3]; int proc_init() { return 0; } void proc_sched(int_stack_t *stack_frame) { cur_task = (cur_task + 1) & 1; write_cr3(processes[cur_task] } u32_t create_task(void *base, u32_t image_size, u32_t bss_size, void *entry); { process_t *proc = create_process(vase, image_size, bss_size, entry); processes[n_processes] = proc; return n_processes++; } process_t *create_process(void *base, u32_t image_size, u32_t bss_size, void *entry); { if (mm_freepages < pages + bsspages + 25) return 0; process_t *process = New(process_t); /* Allocate process_t struct */ create_address_space(process); create_process_stack(process); int i; u32_t *ptr32 = process->v_page_dir = vmm_palloc(); for (i = 0; i < 1024; i++) *ptr32++ = 0; u32_t code_data_pages = (image_size >> 12) + ((image_size & 0x3FF) ? 1 : 0); u32_t bss_pages = (bss_size >> 12) + ((bss_size & 0x3FF) ? 1 : 0); /* Load program at address 0 */ copy_into_address_space(0, base, code_data_pages, process); zero_address_space(code_data_pages << 12, bss_pages, process); ptr32 = process->v_page_dir; for (i = 0; i < 1024; i++) if (*ptr32) vmm_unmapp(*ptr32); vmm_unmapp(process->v_page_dir); process->v_page_dir = 0; return process; } void create_address_space(process_t *p) { /* Allocate a new page directory */ p->page_dir = vmm_palloc_addr(&p->p_page_dir); int i; u32_t *ptr32 = p->page_dir; for (i = 0; i < 768; i++) /* zero 3 gigs */ *ptr32++ = 0; memcpyd(ptr32, (void *)0xFFFFF000, 256); /* 1 gig kernel mem */ } void create_process_stack(process_t *p) { u32_t p_stack_table, p_stack; u32_t *v_stack_table = vmm_palloc_addr(&p_stack_table); void *v_stack = vmm_palloc_addr(&p_stack); int i; u32_t *ptr32 = v_stack_table; for (int i = 0; i < 1023; i++) *ptr32++ = 0; v_stack_table[1032] = p_stack | 0x7; /* user permissions */ p->page_dir[511] = p_stack_table | 0x7; vmm_unmapp(v_stack_table); vmm_unmapp(v_stack); p->esp = 0x80000000; /* Stack at 2GB */ } /* Copy pages into new address space (v_page_dir must be set up) */ void copy_into_address_space(u32_t dest_addr, void *src_addr, u32_t pages, process_t *p) { u32_t pde, pte; void *page; while (pages) { pde = dest_addr >> 22; pte = (dest_addr >> 12) & 0x3FF; u32_t p_page_addr; if (!p->v_page_dir[pde]) { /* Time for a new page table & page directory entry! */ p->v_page_dir[pde] = vmm_palloc_addr(&p_page_addr); p->page_dir[pde] = p_page_addr | 0x7; vmm_unmapp(p->v_page_dir[pde]); } page = vmm_palloc_addr(&p_page_addr); ((u32_t *)(p->v_page_dir[pde]))[pte] = p_page_addr | 0x7; memcpyd(page, src_addr, 1024); vmm_unmapp(page); dest_addr += 4096; src_addr += 4096; pages--; } } /* Zeros pages into new address space (v_page_dir must be set up) */ void zero_address_space(u32_t dest_addr, u32_t pages, process_t *p) { u32_t pde, pte; void *page; while (pages) { pde = dest_addr >> 22; pte = (dest_addr >> 12) & 0x3FF; u32_t p_page_addr; if (!p->v_page_dir[pde]) { /* Time for a new page table & page directory entry! */ p->v_page_dir[pde] = vmm_palloc_addr(&p_page_addr); p->page_dir[pde] = p_page_addr | 0x7; vmm_unmapp(p->v_page_dir[pde]); } page = vmm_palloc_addr(&p_page_addr); ((u32_t *)(p->v_page_dir[pde]))[pte] = p_page_addr | 0x7; memsetd(page, 0, 1024); vmm_unmapp(page); dest_addr += 4096; pages--; } } u32_t fork(process_t *p) { return 0; }