JOS2-3
我们来琢磨下,下面这个函数应该怎么实现:
// Given 'pgdir', a pointer to a page directory, pgdir_walk returns // a pointer to the page table entry (PTE) for linear address 'va'. // This requires walking the two-level page table structure. // // The relevant page table page might not exist yet. // If this is true, and create == false, then pgdir_walk returns NULL. // Otherwise, pgdir_walk allocates a new page table page with page_alloc. // - If the allocation fails, pgdir_walk returns NULL. // - Otherwise, the new page's reference count is incremented, // the page is cleared, // and pgdir_walk returns a pointer into the new page table page. // // Hint 1: you can turn a Page * into the physical address of the // page it refers to with page2pa() from kern/pmap.h. // // Hint 2: the x86 MMU checks permission bits in both the page directory // and the page table, so it's safe to leave permissions in the page // more permissive than strictly necessary. // // Hint 3: look at inc/mmu.h for useful macros that mainipulate page // table and page directory entries. // #返回值带属性 pte_t * pgdir_walk(pde_t *pgdir, const void *va, int create) { // Fill this function in }
要求:
返回值为指向PTE的指针
pte_t * pgdir_walk(pde_t *pgdir, const void *va, int create) { pde_t pt_base_attr; pte_t pt_base; struct PageInfo *pp; pde_t new_pt_base; // #首先从页目录中取PDE pt_base_attr = pgdir[PDX(va)]; // #PDE实质就是 PT的基址|属性 // #去掉属性 获取基址 pt_base = (pte_t)(pt_base_attr & 0xfffff000) if(pt_base){ // #如果为真 返回PTE的地址 return &pt_base[PTX(va)]; } else{ if(create == false){ return NULL; } // #如果PDE为0 那么申请一个PT pp = page_alloc(1); if(!pp){ return NULL; } new_pt_base = (pde_t)page2pa(pp); // #填上就不为空了 pgdir[PDX(va)] = new_pt_base|PTE_W|PTE_P; // #返回PTE pt_base = (pte_t)(new_pt_base); return &(pt_base[PTX(va)]); } }
上面编译时出现一处错误:subscripted value is neither array nor pointer nor vector
也就是想对一个变量名使用下标,它必须是数组或者指针。
然后我们琢磨一下这个函数:
// Map [va, va+size) of virtual address space to physical [pa, pa+size) // in the page table rooted at pgdir. Size is a multiple of PGSIZE. // Use permission bits perm|PTE_P for the entries. // // This function is only intended to set up the ``static'' mappings // above UTOP. As such, it should *not* change the pp_ref field on the // mapped pages. // // Hint: the TA solution uses pgdir_walk static void boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
实现的是虚拟地址[va,va+size]到物理地址[pa,pa+size]的映射
注意的问题是:
不论物理地址还是虚拟地址要PGSIZE对齐
那么应该映射多少页?
左往左延伸,右往右延伸,PGSIZE大小对齐,然后除以PGSIZE。

浙公网安备 33010602011771号