void i386_init(void) { extern char edata[], end[]; // Before doing anything else, complete the ELF loading process. // Clear the uninitialized global data (BSS) section of our program. // This ensures that all static/global variables start out zero. memset(edata, 0, end - edata); // Initialize the console. // Can't call cprintf until after we do this! cons_init(); cprintf("6828 decimal is %o octal!\n", 6828); // Lab 2 memory management initialization functions i386_detect_memory(); i386_vm_init(); page_init(); page_check(); // Drop into the kernel monitor. while (1) monitor(NULL); }
void i386_init(void) { extern char edata[], end[]; // Before doing anything else, complete the ELF loading process. // Clear the uninitialized global data (BSS) section of our program. // This ensures that all static/global variables start out zero. memset(edata, 0, end - edata); // Initialize the console. // Can't call cprintf until after we do this! cons_init(); cprintf("6828 decimal is %o octal!\n", 6828); // Lab 2 memory management initialization functions i386_detect_memory(); i386_vm_init(); page_init(); page_check(); // Lab 3 user environment initialization functions env_init(); idt_init(); // Lab 4 multitasking initialization functions pic_init(); kclock_init(); // Should always have an idle process as first one. ENV_CREATE(user_idle); // Start fs. ENV_CREATE(fs_fs); ENV_CREATE(user_icode); #if defined(TEST) // Don't touch -- used by grading script! ENV_CREATE2(TEST, TESTSIZE) #else // Touch all you want. // ENV_CREATE(user_icode); // ENV_CREATE(user_pipereadeof); // ENV_CREATE(user_pipewriteeof); // ENV_CREATE(user_testpipe); // ENV_CREATE(user_primespipe); // ENV_CREATE(user_testpiperace); // ENV_CREATE(user_testpiperace2); // ENV_CREATE(user_testfdsharing); #endif // TEST* // Should not be necessary - drain keyboard because interrupt has given up. kbd_intr(); // Schedule and run the first user environment! sched_yield(); }
void i386_init(void) { extern char edata[], end[]; uint32_t *ctorva; // Initialize the console. // Can't call cprintf until after we do this! cons_init(); cprintf("6828 decimal is %o octal!\n", 6828); // Lab 2 memory management initialization functions boot_mem_init(); page_init(); page_check(); // Lab 2 interrupt and gate descriptor initialization functions idt_init(); // Test IDT (lab 2 only) __asm__ __volatile__("int3"); cprintf("Breakpoint succeeded!\n"); // Test the stack backtrace function (lab 1 only) //test_backtrace(5); // Lab 3 user environment initialization functions env_init(); #if JOS_MULTIENV // Should always have an idle process as first one. ENV_CREATE(user_idle); #endif #ifdef TEST // Don't touch -- used by grading script! ENV_CREATE2(TEST, TESTSIZE); #else // Touch all you want. ENV_CREATE(user_hello); #endif // TEST* // We only have one user environment for now, so just run it. env_run(&envs[0]); // Drop into the kernel monitor. while (1) monitor(NULL); }
/* * Walk the vp->v_pages list, for every page call the callback function * pointed by *page_check. If page_check returns non-zero, then mark the * page as modified and if VMODSORT is set, move it to the end of v_pages * list. Moving makes sense only if we have at least two pages - this also * avoids having v_pages temporarily being NULL after calling page_vpsub() * if there was just one page. */ void pvn_vplist_setdirty(vnode_t *vp, int (*page_check)(page_t *)) { page_t *pp, *next, *end; kmutex_t *vphm; int shuffle; vphm = page_vnode_mutex(vp); mutex_enter(vphm); if (vp->v_pages == NULL) { mutex_exit(vphm); return; } end = vp->v_pages->p_vpprev; shuffle = IS_VMODSORT(vp) && (vp->v_pages != end); pp = vp->v_pages; for (;;) { next = pp->p_vpnext; if (pp->p_hash != PVN_VPLIST_HASH_TAG && page_check(pp)) { /* * hat_setmod_only() in contrast to hat_setmod() does * not shuffle the pages and does not grab the mutex * page_vnode_mutex. Exactly what we need. */ hat_setmod_only(pp); if (shuffle) { page_vpsub(&vp->v_pages, pp); ASSERT(vp->v_pages != NULL); page_vpadd(&vp->v_pages->p_vpprev->p_vpnext, pp); } } /* Stop if we have just processed the last page. */ if (pp == end) break; pp = next; } mutex_exit(vphm); }
// Set up a four-level page table: // boot_pml4e is its linear (virtual) address of the root // // This function only sets up the kernel part of the address space // (ie. addresses >= UTOP). The user part of the address space // will be setup later. // // From UTOP to ULIM, the user is allowed to read but not write. // Above ULIM the user cannot read or write. void x64_vm_init(void) { pml4e_t* pml4e; uint32_t cr0; int i; size_t n; int r; struct Env *env; i386_detect_memory(); //panic("i386_vm_init: This function is not finished\n"); ////////////////////////////////////////////////////////////////////// // create initial page directory. ///panic("x64_vm_init: this function is not finished\n"); pml4e = boot_alloc(PGSIZE); memset(pml4e, 0, PGSIZE); boot_pml4e = pml4e; boot_cr3 = PADDR(pml4e); ////////////////////////////////////////////////////////////////////// // Allocate an array of npage 'struct Page's and store it in 'pages'. // The kernel uses this array to keep track of physical pages: for // each physical page, there is a corresponding struct Page in this // array. 'npage' is the number of physical pages in memory. // User-level programs will get read-only access to the array as well. // Your code goes here: pages = boot_alloc(npages * sizeof(struct Page)); ////////////////////////////////////////////////////////////////////// // Make 'envs' point to an array of size 'NENV' of 'struct Env'. // LAB 3: Your code here. envs = boot_alloc(NENV * sizeof(struct Env)); ////////////////////////////////////////////////////////////////////// // Now that we've allocated the initial kernel data structures, we set // up the list of free physical pages. Once we've done so, all further // memory management will go through the page_* functions. In // particular, we can now map memory using boot_map_segment or page_insert page_init(); check_page_free_list(1); check_page_alloc(); page_check(); ////////////////////////////////////////////////////////////////////// // Now we set up virtual memory ////////////////////////////////////////////////////////////////////// // Map 'pages' read-only by the user at linear address UPAGES // Permissions: // - the new image at UPAGES -- kernel R, user R // (ie. perm = PTE_U | PTE_P) // - pages itself -- kernel RW, user NONE // Your code goes here: ////////////////////////////////////////////////////////////////////// // Map the 'envs' array read-only by the user at linear address UENVS // (ie. perm = PTE_U | PTE_P). // Permissions: // - the new image at UENVS -- kernel R, user R // - envs itself -- kernel RW, user NONE // LAB 3: Your code here. boot_map_segment(boot_pml4e, UPAGES, ROUNDUP(npages*sizeof(struct Page), PGSIZE), PADDR(pages), PTE_U | PTE_P); boot_map_segment(boot_pml4e, (uintptr_t)pages, ROUNDUP(npages *sizeof(struct Page), PGSIZE), PADDR(pages), PTE_P | PTE_W); boot_map_segment(boot_pml4e, UENVS, ROUNDUP(NENV*sizeof(struct Env), PGSIZE), PADDR(envs), PTE_U | PTE_P); boot_map_segment(boot_pml4e, (uintptr_t)envs, ROUNDUP(NENV *sizeof(struct Env), PGSIZE), PADDR(envs), PTE_P | PTE_W); ////////////////////////////////////////////////////////////////////// // Use the physical memory that 'bootstack' refers to as the kernel // stack. The kernel stack grows down from virtual address KSTACKTOP. // We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP) // to be the kernel stack, but break this into two pieces: // * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory // * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if // the kernel overflows its stack, it will fault rather than // overwrite memory. Known as a "guard page". // Permissions: kernel RW, user NONE // Your code goes here: boot_map_segment(boot_pml4e, KSTACKTOP-KSTKSIZE, KSTKSIZE, PADDR(bootstack), PTE_P | PTE_W); /////////////////////////////////////////////////////////////////////// // Map all of physical memory at KERNBASE. // Ie. the VA range [KERNBASE, 2^32) should map to // the PA range [0, 2^32 - KERNBASE) // We might not have 2^32 - KERNBASE bytes of physical memory, but // we just set up the mapping anyway. // Permissions: kernel RW, user NONE // Your code goes here: boot_map_segment(boot_pml4e, KERNBASE, ~(uint32_t)0 - KERNBASE + 1, 0, PTE_P | PTE_W); // Check that the initial page directory has been set up correctly. // Initialize the SMP-related parts of the memory map mem_init_mp(); check_boot_pml4e(boot_pml4e); ////////////////////////////////////////////////////////////////////// // Permissions: kernel RW, user NONE pdpe_t *pdpe = KADDR(PTE_ADDR(pml4e[0])); pde_t *pgdir = KADDR(PTE_ADDR(pdpe[3])); lcr3(boot_cr3); check_page_free_list(0); }
void kernel_init(multiboot_info_t *mboot_info) { extern char __start_bss[], __stop_bss[]; memset(__start_bss, 0, __stop_bss - __start_bss); /* mboot_info is a physical address. while some arches currently have the * lower memory mapped, everyone should have it mapped at kernbase by now. * also, it might be in 'free' memory, so once we start dynamically using * memory, we may clobber it. */ multiboot_kaddr = (struct multiboot_info*)((physaddr_t)mboot_info + KERNBASE); extract_multiboot_cmdline(multiboot_kaddr); cons_init(); print_cpuinfo(); printk("Boot Command Line: '%s'\n", boot_cmdline); exception_table_init(); cache_init(); // Determine systems's cache properties pmem_init(multiboot_kaddr); kmem_cache_init(); // Sets up slab allocator kmalloc_init(); hashtable_init(); radix_init(); cache_color_alloc_init(); // Inits data structs colored_page_alloc_init(); // Allocates colors for agnostic processes acpiinit(); topology_init(); kthread_init(); /* might need to tweak when this happens */ vmr_init(); file_init(); page_check(); idt_init(); kernel_msg_init(); timer_init(); vfs_init(); devfs_init(); train_timing(); kb_buf_init(&cons_buf); arch_init(); block_init(); enable_irq(); run_linker_funcs(); /* reset/init devtab after linker funcs 3 and 4. these run NIC and medium * pre-inits, which need to happen before devether. */ devtabreset(); devtabinit(); #ifdef CONFIG_EXT2FS mount_fs(&ext2_fs_type, "/dev/ramdisk", "/mnt", 0); #endif /* CONFIG_EXT2FS */ #ifdef CONFIG_ETH_AUDIO eth_audio_init(); #endif /* CONFIG_ETH_AUDIO */ get_coreboot_info(&sysinfo); booting = 0; #ifdef CONFIG_RUN_INIT_SCRIPT if (run_init_script()) { printk("Configured to run init script, but no script specified!\n"); manager(); } #else manager(); #endif }