void init_paging() { size_t sz; uint32_t i; uint32_t mem_end_page; DPRINTK("paging...\t\t"); mem_end_page = 0x1000000; nframes = mem_end_page / PAGE_SIZ; sz = INDEX_FROM_BIT(nframes); frames = (uint32_t *)kmalloc(sz); memset(frames, 0, sz); kernel_directory = (struct page_directory *) kmalloc_a(sizeof(struct page_directory)); memset(kernel_directory, 0, sizeof(struct page_directory)); // don't do this... current_directory = kernel_directory; // do this instead... kernel_directory->physical_addr = (uint32_t)kernel_directory->tables_physical; for (i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += PAGE_SIZ) get_page(i, 1, kernel_directory); i = 0; while (i < placement_addr + PAGE_SIZ) { alloc_frame(get_page(i, 1, kernel_directory), 0, 0); i += PAGE_SIZ; } for (i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += PAGE_SIZ) alloc_frame(get_page(i, 1, kernel_directory), 0, 0); // register_interrupt_handler(14, page_fault); switch_page_directory(kernel_directory); enable_paging(); kheap = create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0); current_directory = clone_directory(kernel_directory); switch_page_directory(current_directory); DPRINTK("done!\n"); }
int32_t fork() { if (kernel_thread == current_thread) panic("SCHED: no forking from kernel thread."); // TODO: change to kernel locking asm volatile("cli"); // we will fork current thread and clone current task address space thread_t* new_thread = kmalloc(sizeof(thread_t)); new_thread->tid = next_tid++; new_thread->state = THREAD_RUNNING; new_thread->esp0 = current_thread->esp0; new_thread->stack_size = current_thread->stack_size; page_directory_t* page_dir = clone_directory(current_directory); // NOTE: this is allocated in kernel address space so shouldn't be copied, // take care of properly (fully) linking kernel page tables task_t* new_task = create_task(new_thread, page_dir); // NOTE: we copy whole address space -- it means that we copy the // new stack (no in case when forking from kernel) // add to run queue schedule_add_task(new_task); // after this will be entry point save_thread_state(new_thread); // NEW TASK ENTRY POINT // decide if we're in child or parent if (current_thread == new_thread) { // we're in child return 0; } else { // we're in parent // TODO: change to kernel locking asm volatile("sti"); // by convention return child's pid return new_task->pid; } }
int system( char * path, /* Path to the executable to run */ int argc, /* Argument count (ie, /bin/echo hello world = 3) */ char ** argv /* Argument strings (including executable path) */ ) { char ** argv_ = malloc(sizeof(char *) * (argc + 1)); for (int j = 0; j < argc; ++j) { argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char)); memcpy(argv_[j], argv[j], strlen(argv[j]) + 1); } argv_[argc] = 0; char * env[] = {NULL}; set_process_environment((process_t*)current_process, clone_directory(current_directory)); current_directory = current_process->thread.page_directory; switch_page_directory(current_directory); exec(path,argc,argv_,env); debug_print(ERROR, "Failed to execute process!"); kexit(-1); return -1; }
uint32_t exec_elf(const char* name) { fs_node_t* file = finddir(fs_root, name); open(file, 1, 0); // disable interrupts asm volatile("cli"); // save directory and create one for new task page_directory_t* old_dir = current_directory; page_directory_t* new_dir = clone_directory(old_dir); // switch to new directory (this is where we set up process) switch_page_directory(new_dir); // load elf and get entry point uint32_t entry = load_elf_binary(file); // setup stack uint32_t stack = (uint32_t) allocate_stack(THREAD_STACK_SIZE); // create scheduling structures thread_t* new_thread = create_thread((int(*)(void*)) entry, 0, (uint32_t*) stack, THREAD_STACK_SIZE); task_t* new_task = create_task(new_thread, new_dir); schedule_add_task(new_task); // switch back to parents directory switch_page_directory(old_dir); // close executable image close(file); // reenable interrupts asm volatile("sti"); // like in fork return child pid return new_task->pid; }