// 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" #include "functions.h" //halt() extern u32_t idle_loop; u32_t cur_task = 0; u32_t n_processes = 0; process_t *processes[3]; tss_t tss0; u32_t proc_new_esp; u32_t proc_new_ss; int proc_init() { /* initialize tss0 */ memset(&tss0, 0, sizeof(tss_t)); tss0.ss0 = SEG_KERNEL_DATA; tss0.esp0 = VIRT_STACK_TOP; /* tss0.pdbr = read_cr3(); tss0.eip = &idle_loop; tss0.eflags = 0x0202; tss0.esp = VIRT_STACK_TOP-32; // idle_loop won't use -- a good thing tss0.es = tss0.ds = tss0.fs = tss0.gs = tss0.ss = SEG_KERNEL_DATA; tss0.cs = SEG_KERNEL_CODE; */ processes[0] = New(process_t); processes[0]->p_page_dir = read_cr3(); processes[0]->page_dir = (void *)0xFFFFF000; return 0; } void proc_sched(int_stack_t *int_stack) { memcpy(&processes[cur_task]->int_stack, int_stack, sizeof(int_stack_t)); cur_task++; if (cur_task == 3) cur_task = 0; memcpy(int_stack, &processes[cur_task]->int_stack, sizeof(int_stack_t)); write_cr3(processes[cur_task]->p_page_dir); } u32_t create_task(void *base, u32_t image_size, u32_t bss_size, void *entry) { processes[++n_processes] = create_process(base, image_size, bss_size, entry); return n_processes; } /* Create process_t struct for a new process * image_size should be a multiple of 4096 */ process_t *create_process(void *base, u32_t image_size, u32_t bss_size, void *entry) { if (mm_freepages < ((image_size + bss_size) >> 12) + 25) return 0; process_t *process = New(process_t); /* Allocate process_t struct */ create_address_space(process); create_process_stack(process, entry); 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 + 4095) >> 12; u32_t bss_pages = (bss_size + 4095) >> 12; /* 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((void *)*ptr32); vmm_unmapp(process->v_page_dir); process->v_page_dir = 0; process->size = image_size + bss_size; 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 *)0xFFFFFC00, 256); /* 1 gig kernel mem */ } void create_process_stack(process_t *p, void *entry) { u32_t p_stack_table, p_stack; u32_t *v_stack_table = vmm_palloc_addr(&p_stack_table); u32_t *v_stack = vmm_palloc_addr(&p_stack); int i; u32_t *ptr32 = v_stack_table; for (i = 0; i < 1023; i++) *ptr32++ = 0; v_stack_table[1023] = p_stack | 0x7; /* user permissions */ p->page_dir[511] = p_stack_table | 0x7; /* stack at 2GB */ vmm_unmapp(v_stack_table); vmm_unmapp(v_stack); p->int_stack.ds = SEG_USER_DATA | 0x3; p->int_stack.es = SEG_USER_DATA | 0x3; p->int_stack.fs = SEG_USER_DATA | 0x3; p->int_stack.gs = SEG_USER_DATA | 0x3; p->int_stack.ss = SEG_USER_DATA | 0x3; p->int_stack.esp = 0x20000000; p->int_stack.eflags = 0x0202; p->int_stack.cs = SEG_USER_CODE | 0x3; p->int_stack.eip = (u32_t)entry; } /* 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] = (u32_t)vmm_palloc_addr(&p_page_addr); p->page_dir[pde] = p_page_addr | 0x7; // vmm_unmapp((void *)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] = (u32_t)vmm_palloc_addr(&p_page_addr); p->page_dir[pde] = p_page_addr | 0x7; vmm_unmapp((void *)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; }