📄 foreveryone.c
字号:
boot_alloc{ extern char end[]; void *v; if (boot_freemem == 0) boot_freemem = end;void * a = ROUNDUP(boot_freemem, align); v = a; boot_freemem = v+n; return v;}voidpage_init(void){ // The example code here marks all pages as free. // However this is not truly the case. What memory is free? // 1) Mark page 0 as in use. // This way we preserve the real-mode IDT and BIOS structures // in case we ever need them. (Currently we don't, but...) // 2) Mark the rest of base memory as free. // 3) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM). // Mark it as in use so that it can never be allocated. // 4) Then extended memory [EXTPHYSMEM, ...). // Some of it is in use, some is free. Where is the kernel? // Which pages are used for page tables and other data structures? // // Change the code to reflect this. int i; LIST_INIT(&page_free_list); for (i = 0; i < npage; i++) { pages[i].pp_ref = 0; LIST_INSERT_HEAD(&page_free_list, &pages[i], pp_link); } struct Page *pp; pp=pa2page(0); LIST_REMOVE(pp,pp_link); pp->pp_ref++; physaddr_t pa; for (pa = IOPHYSMEM; pa < EXTPHYSMEM; pa += PGSIZE){ pp=pa2page(pa); LIST_REMOVE(pp, pp_link); pp->pp_ref++; } for (pa = EXTPHYSMEM; pa < (physaddr_t) (boot_freemem-KERNBASE); pa+=PGSIZE){ pp = pa2page(pa); LIST_REMOVE(pp, pp_link); pp->pp_ref++; }}page_alloc(struct Page **pp_store){ struct Page *p = LIST_FIRST(&page_free_list); if(p == NULL) return -E_NO_MEM; *pp_store = p; LIST_REMOVE(p, pp_link); page_initpp(p); return 0;}page_free(struct Page *pp){ // Fill this function in LIST_INSERT_HEAD(&page_free_list, pp, pp_link);}pte_t *pgdir_walk(pde_t *pgdir, const void *va, int create){ pte_t *p; struct Page *pp; physaddr_t pa; pgdir = &pgdir[PDX(va)]; if(!(*pgdir & PTE_P)){ if(!create) { return NULL; } if(page_alloc(&pp) != 0) return NULL; pp->pp_ref++; pa = page2pa(pp); memset(KADDR(PTE_ADDR(pa)), 0 ,PGSIZE); *pgdir = pa | PTE_U | PTE_P | PTE_W; } p = (pte_t*) KADDR(PTE_ADDR((*pgdir))); return &p[PTX(va)];}//// Map the physical page 'pp' at virtual address 'va'.// The permissions (the low 12 bits) of the page table// entry should be set to 'perm|PTE_P'.//// Details// - If there is already a page mapped at 'va', it is page_remove()d.// - If necessary, on demand, allocates a page table and inserts it into// 'pgdir'.// - pp->pp_ref should be incremented if the insertion succeeds.// - The TLB must be invalidated if a page was formerly present at 'va'.//// RETURNS: // 0 on success// -E_NO_MEM, if page table couldn't be allocated//// Hint: The TA solution is implemented using pgdir_walk, page_remove,// and page2pa.//intpage_insert(pde_t *pgdir, struct Page *pp, void *va, int perm) { // Fill this function in pte_t *p=pgdir_walk(pgdir, va, 1); if(p==NULL) return -E_NO_MEM; if(*p & PTE_P){ if(pa2page(PTE_ADDR(*p)) != pp){ page_remove(pgdir, va); pp->pp_ref++; } *p = page2pa(pp) | perm | PTE_P; } else{ *p = page2pa(pp) | perm | PTE_P; pp->pp_ref++; } return 0;}static voidboot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm){ // Fill this function in pte_t *addr, *p; int i; for(i = 0; i < size; i += PGSIZE){ addr = pgdir_walk(pgdir, (void*)(la + i), 1); *addr |= (PTE_ADDR(pa + i) | perm); }}struct Page *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store){ *pte_store=pgdir_walk(pgdir, va, 0); if((*pte_store != 0) && (**pte_store & PTE_P)){ return pa2page(PTE_ADDR(**pte_store)); } return 0;}voidpage_remove(pde_t *pgdir, void *va){ pte_t *p; struct Page *pp; if((pp = page_lookup(pgdir, va, &p)) != 0){ page_decref(pp); *p = 0; tlb_invalidate(pgdir, va); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -