否则把对应的pte清0,然后调用tlb_invalidate和page_decref
void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t * pte; struct PageInfo *page = page_lookup(pgdir,va,&pte); if (!page) { return; } *pte = 0; tlb_invalidate(pgdir,va); page_decref(page); } 2.5 Page_insert把物理页pp映射在虚拟地址va,页表项权限设置为perm|PTE_P。
如果已经有一个页面在va,它应该先调用page_remove()删除
如有必要,应按需分配页表并将其插入“ pgdir”。插入成功pp->ref应该自增。如果以前有页面位于“ va”,则TLB必须无效。
提示:使用pgdir_walk,page_remove和page2pa。
根据提示我们需要分配页表并将其插入pgdir。这不是就是前面实现的pgir_walk把crate设置成1的功能。
同样如果以前有页面位于va。则让他的tlb无效。。这里听起来很麻烦,但实际上只需要调用page_remove原来va对应的映射移除即可。而且page_remove已经实现了让tlb无效的操作。
int page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm) { // Fill this function in pte_t *pte = pgdir_walk(pgdir,(void *) va, 1); if (!pte) { return -E_NO_MEM; } pp->pp_ref++; if (*pte & PTE_P) { page_remove(pgdir,va); } *pte = page2pa(pp) | perm | PTE_P; return 0; } 3. Part3 : Kernel Address Space第三部分需要我们补齐mem_init函数
只要跟随提示来完成对于内核部分的一些映射。按照下面这样做就好了
boot_map_region(kern_pgdir, UPAGES, PTSIZE, PADDR(pages), PTE_U); boot_map_region(kern_pgdir, KSTACKTOP - KSTKSIZE, KSTKSIZE, PADDR(bootstack), PTE_W); boot_map_region(kern_pgdir, KERNBASE, 0xffffffff - KERNBASE, 0, PTE_W); 3.1 Question补充完第三部分的代码之后,我们来看一下第三部分的问题
What entries (rows) in the page directory have been filled in at this point? What addresses do they map and where do they point? In other words, fill out this table as much as possible:
Entry Base Virtual Address Points to (logically):1023 0xff000000 Page table for top 4MB of phys memory
1022 ? ?
959 0xefc00000 cpu0's kernel stack(0xefff8000),cpu1's kernel stack(0xeffe8000)
956 0xef000000 npages of PageInfo(0xef000000)
952 0xee000000 bootstack
2 0x00800000 Program Data & Heap
1 0x00400000 Empty
0 0x00000000 [see next question]
这个地方要参考一下memlayout.h就可以写出了
其实主要搞清楚几个重要的就可以了
比如0xef000000表示UPAGES
oxefc00000表示内核栈等等
We have placed the kernel and user environment in the same address space. Why will user programs not be able to read or write the kernel's memory? What specific mechanisms protect the kernel memory?
通过把页表项中的 Supervisor/User位置0,那么用户态的代码就不能访问内存中的这个页。
What is the maximum amount of physical memory that this operating system can support? Why?
这个操作系统利用一个大小为4MB的空间也就是UPAGES这一段。来存放所有的页的PageInfo结构体信息,每个结构体的大小为8B,所以一共可以存放512K个PageInfo结构体,所以一共可以出现512K个物理页,每个物理页大小为4KB,自然总的物理内存占2GB。
How much space overhead is there for managing memory, if we actually had the maximum amount of physical memory? How is this overhead broken down?
这个问题是说如果我们现在的物理页达到最大,那么管理这些内存所需要的额外空间开销有多少
首先我们所有的pageinfo需要4mb。然后需要存放页目录表。一共1024个每一个需要4B所以一共4kb
还有存放当前的页表。页表是1024 * 4kb = 4mb
所以一共需要4MB + 4MB + 4KB = 8MB + 4KB
Revisit the page table setup in kern/entry.S and kern/entrypgdir.c. Immediately after we turn on paging, EIP is still a low number (a little over 1MB). At what point do we transition to running at an EIP above KERNBASE? What makes it possible for us to continue executing at a low EIP between when we enable paging and when we begin running at an EIP above KERNBASE? Why is this transition necessary?
是通过下面的代码来跳转到kernbase之上的虚拟地址的
mov $relocated, %eax
jmp *%eax