// kern/mm/vmm.h//pre definestruct mm_struct;// the virtual continuous memory area(vma), [vm_start, vm_end),// addr belong to a vma means vma.vm_start<= addr <vma.vm_endstruct vma_struct {struct mm_struct *vm_mm; // the set of vma using the same PDTuintptr_t vm_start; // start addr of vmauintptr_t vm_end; // end addr of vma, not include the vm_end itselfuint_t vm_flags; // flags of vmalist_entry_t list_link; // linear list link which sorted by start addr of vma};#definele2vma(le, member) \to_struct((le),struct vma_struct, member)#defineVM_READ0x00000001#defineVM_WRITE0x00000002#defineVM_EXEC0x00000004// the control struct for a set of vma using the same Page Tablestruct mm_struct {list_entry_t mmap_list; // linear list link which sorted by start addr of vmastruct vma_struct *mmap_cache; // current accessed vma, used for speed purposepde_t*pgdir; // the Page Table of these vmaint map_count; // the count of these vmavoid*sm_priv; // the private data for swap manager};
// kern/mm/vmm.cintdo_pgfault(struct mm_struct *mm,uint_t error_code,uintptr_t addr) {//addr: 访问出错的虚拟地址int ret =-E_INVAL;//try to find a vma which include addrstruct vma_struct *vma =find_vma(mm, addr);//我们首先要做的就是在mm_struct里判断这个虚拟地址是否可用 pgfault_num++;//If the addr is not in the range of a mm's vma?if (vma ==NULL||vma->vm_start > addr) {cprintf("not valid addr %x, and can not find it in vma\n", addr);goto failed; } /* IF (write an existed addr ) OR * (write an non_existed addr && addr is writable) OR * (read an non_existed addr && addr is readable) * THEN * continue process */uint32_t perm = PTE_U;if (vma->vm_flags & VM_WRITE) { perm |= (PTE_R | PTE_W); } addr =ROUNDDOWN(addr, PGSIZE); //按照页面大小把地址对齐 ret =-E_NO_MEM;pte_t*ptep=NULL; ptep =get_pte(mm->pgdir, addr,1); //(1) try to find a pte, if pte's//PT(Page Table) isn't existed, then//create a PT.if (*ptep ==0) {if (pgdir_alloc_page(mm->pgdir, addr, perm)==NULL) {cprintf("pgdir_alloc_page in do_pgfault failed\n");goto failed; } } else { /* * Now we think this pte is a swap entry, we should load data from disk * to a page with phy addr, * and map the phy addr with logical addr, trigger swap manager to record * the access situation of this page. * * swap_in(mm, addr, &page) : alloc a memory page, then according to * the swap entry in PTE for addr, find the addr of disk page, read the * content of disk page into this memroy page * page_insert : build the map of phy addr of an Page with the virtual addr la * swap_map_swappable : set the page swappable */if (swap_init_ok) {struct Page *page =NULL;//在swap_in()函数执行完之后,page保存换入的物理页面。//swap_in()函数里面可能把内存里原有的页面换出去swap_in(mm, addr,&page); //(1)According to the mm AND addr, try//to load the content of right disk page//into the memory which page managed.page_insert(mm->pgdir, page, addr, perm); //更新页表,插入新的页表项//(2) According to the mm, addr AND page, // setup the map of phy addr <---> virtual addrswap_map_swappable(mm, addr, page,1); //(3) make the page swappable.//标记这个页面将来是可以再换出的page->pra_vaddr = addr; } else {cprintf("no swap_init_ok but ptep is %x, failed\n",*ptep);goto failed; } } ret =0;failed:return ret;}