//page_remove - free an Page which is related linear address la and has an validated pte void page_remove(pde_t *pgdir, uintptr_t la) { //cprintf("!=%08x\n",(char*)((char*)la+101) ); //cprintf("?=%d\n",*(char *)(0x50000105)); //cprintf("remove addr=%08x\n\n",la); pte_t *ptep = get_pte(pgdir, la, 0); //cprintf("remove *ptep=%08x\n",*ptep); struct Page* page=pte2page(*ptep); //cprintf("pagerefremoveshi %d\n",page->ref); //cprintf("remove page addr=%08x\n",page); //cprintf("ptep=%08x\n",ptep); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); if (ptep != NULL) { //cprintf("pgrmv=%08x\n",ptep); page_remove_pte(pgdir, la, ptep); } }
void page_remove(pgd_t *pgdir, uintptr_t la) { pte_t *ptep = get_pte(pgdir, la, 0); if (ptep != NULL) { page_remove_pte(pgdir, la, ptep); } }
static void unmap_range_pte(pgd_t *pgdir, pte_t *pte, uintptr_t base, uintptr_t start, uintptr_t end) { assert(start >= 0 && start < end && end <= PTSIZE); assert(start % PGSIZE == 0 && end % PGSIZE == 0); do { pte_t *ptep = &pte[PTX(start)]; if (*ptep != 0) { page_remove_pte(pgdir, base + start, ptep); } start += PGSIZE; } while (start != 0 && start < end); }
//page_insert - build the map of phy addr of an Page with the linear addr la // paramemters: // pgdir: the kernel virtual base address of PDT // page: the Page which need to map // la: the linear address need to map // perm: the permission of this Page which is setted in related pte // return value: always 0 //note: PT is changed, so the TLB need to be invalidate int page_insert(pde_t *pgdir, struct Page *page, uintptr_t la, uint32_t perm) { pte_t *ptep = get_pte(pgdir, la, 1); //cprintf("insert ptep=%08x\n",ptep); if (ptep == NULL) { return -E_NO_MEM; } page_ref_inc(page); //cprintf("pageref2 %d\n",page->ref); //cprintf("addr=%08x\n\n",la); if (*ptep & PTE_V) { //cprintf("pageref3 %d\n",page->ref); struct Page *p = pte2page(*ptep); // cprintf("guagua\n"); if (p == page) { page_ref_dec(page); } else { page_remove_pte(pgdir, la, ptep); } } // pte_t* pte = get_pte(mm->pgdir,0x50000000,0); // struct Page* page=pte2page(*pte); //cprintf("insert page addr = %08x\n",page); //cprintf("insert page physical =%08x\n",page2pa(page)); //cprintf(" before *ptep=%08x\n",*ptep); //*ptep = page2pa(page); //cprintf("ptep start=%08x\n",*ptep); //cprintf("perm=%08x\n",perm); *ptep = page2pa(page)| PTE_V | perm | PTE_R; //cprintf("ptep last=%08x\n",*ptep); // cprintf("\ninsert page1 addr=%08x\n",page); // cprintf("insert *ptep=%08x\n",*ptep); // pte_t* pte = get_pte(pgdir,la,0); //cprintf("pgf *pte=%08x\n",*pte); // struct Page* page2=pte2page(*pte); // cprintf("page2 addr = %08x\n",page2); // struct Page* pg=page; // cprintf("%08x\n",pg); // cprintf("%08x\n",page2pa(pg)); //cprintf("%08x\n",pa2page(page2pa(pg))); //tlb_invalidate(pgdir, la); return 0; }
void unmap_range(pde_t *pgdir, uintptr_t start, uintptr_t end) { assert(start % PGSIZE == 0 && end % PGSIZE == 0); //assert(USER_ACCESS(start, end)); do { pte_t *ptep = get_pte(pgdir, start, 0); if (ptep == NULL) { start = ROUNDDOWN(start + PTSIZE, PTSIZE); continue ; } if (*ptep != 0) { page_remove_pte(pgdir, start, ptep); } start += PGSIZE; } while (start != 0 && start < end); }
int page_insert(pgd_t *pgdir, struct Page *page, uintptr_t la, uint32_t perm) { pte_t *ptep = get_pte(pgdir, la, 1); if (ptep == NULL) { return -E_NO_MEM; } page_ref_inc(page); if (*ptep & PTE_P) { struct Page *p = pte2page(*ptep); if (p == page) { page_ref_dec(page); } else { page_remove_pte(pgdir, la, ptep); } } *ptep = page2pa(page) | PTE_P | perm; tlb_invalidate(pgdir, la); return 0; }
/** * page_insert - build the map of phy addr of an Page with the linear addr @la * @param pgdir page directory * @param page the page descriptor of the page to be inserted * @param la logical address of the page * @param perm permission of the page * @return 0 on success and error code when failed */ int page_insert(pgd_t *pgdir, struct Page *page, uintptr_t la, pte_perm_t perm) { pte_t *ptep = get_pte(pgdir, la, 1); if (ptep == NULL) { return -E_NO_MEM; } page_ref_inc(page); if (*ptep != 0) { if (ptep_present(ptep) && pte2page(*ptep) == page) { page_ref_dec(page); goto out; } page_remove_pte(pgdir, la, ptep); } out: ptep_map(ptep, page2pa(page)); ptep_set_perm(ptep, perm); mp_tlb_update(pgdir, la); return 0; }