int page_insert(Pde *pgdir, struct Page *pp, u_long va, u_int perm) { // Fill this function in u_int PERM; Pte *pgtable_entry; PERM = perm | PTE_V; pgdir_walk(pgdir, va, 0, &pgtable_entry); if (pgtable_entry != 0 && (*pgtable_entry & PTE_V) != 0) { if (pa2page(*pgtable_entry) != pp) { page_remove(pgdir, va); } else { tlb_invalidate(pgdir, va); *pgtable_entry = (page2pa(pp) | PERM); return 0; } } tlb_invalidate(pgdir, va); if (pgdir_walk(pgdir, va, 1, &pgtable_entry) != 0) { return -E_NO_MEM; // panic("page insert wrong.\n"); } *pgtable_entry = (page2pa(pp) | PERM); //printf("page_insert:PTE:\tcon:%x\t@:%x\n",(int)*pgtable_entry,(int)pgtable_entry); pp->pp_ref++; return 0; }
// swap_out_vma - try unmap pte & move pages into swap active list. static int swap_out_vma(struct mm_struct *mm, struct vma_struct *vma, uintptr_t addr, size_t require) { if (require == 0 || !(addr >= vma->vm_start && addr < vma->vm_end)) { return 0; } uintptr_t end; size_t free_count = 0; addr = ROUNDDOWN(addr, PGSIZE), end = ROUNDUP(vma->vm_end, PGSIZE); while (addr < end && require != 0) { pte_t *ptep = get_pte(mm->pgdir, addr, 0); if (ptep == NULL) { if (get_pud(mm->pgdir, addr, 0) == NULL) { addr = ROUNDDOWN(addr + PUSIZE, PUSIZE); } else if (get_pmd(mm->pgdir, addr, 0) == NULL) { addr = ROUNDDOWN(addr + PMSIZE, PMSIZE); } else { addr = ROUNDDOWN(addr + PTSIZE, PTSIZE); } continue ; } if (*ptep & PTE_P) { struct Page *page = pte2page(*ptep); assert(!PageReserved(page)); if (*ptep & PTE_A) { *ptep &= ~PTE_A; tlb_invalidate(mm->pgdir, addr); goto try_next_entry; } if (!PageSwap(page)) { if (!swap_page_add(page, 0)) { goto try_next_entry; } swap_active_list_add(page); } else if (*ptep & PTE_D) { SetPageDirty(page); } swap_entry_t entry = page->index; swap_duplicate(entry); page_ref_dec(page); *ptep = entry; tlb_invalidate(mm->pgdir, addr); mm->swap_address = addr + PGSIZE; free_count ++, require --; if ((vma->vm_flags & VM_SHARE) && page_ref(page) == 1) { uintptr_t shmem_addr = addr - vma->vm_start + vma->shmem_off; pte_t *sh_ptep = shmem_get_entry(vma->shmem, shmem_addr, 0); assert(sh_ptep != NULL && *sh_ptep != 0); if (*sh_ptep & PTE_P) { shmem_insert_entry(vma->shmem, shmem_addr, entry); } } } try_next_entry: addr += PGSIZE; } return free_count; }
// // 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'. // // Requirements // - If there is already a page mapped at 'va', it should be page_remove()d. // - If necessary, on demand, a page table should be allocated and inserted // 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'. // // Corner-case hint: Make sure to consider what happens when the same // pp is re-inserted at the same virtual address in the same pgdir. // However, try not to distinguish this case in your code, as this // frequently leads to subtle bugs; there's an elegant way to handle // everything in one code path. // // 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. // int page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm) { // Fill this function in pte_t* ptep = pgdir_walk(pgdir, va, true); if(!ptep) { return -E_NO_MEM; } if( pa2page(*ptep) != pp ){ page_remove(pgdir, va); assert( *ptep == 0 ); assert(pp->pp_ref >= 0); pp->pp_ref++; } else { tlb_invalidate(pgdir, va); } *ptep = page2pa(pp) | perm | PTE_P; /* we should also change pde's perm*/ pde_t *pde = pgdir + PDX(va); *pde = *pde | perm; return 0; }
void call_linux(long a0, long a1, long a2) { local_irq_disable(); cache_clean_invalidate(); tlb_invalidate(); __asm__( "mov r0, %0\n" "mov r1, %1\n" "mov r2, %2\n" "mov ip, #0\n" "mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */ "mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */ "mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */ "mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */ "mrc p15, 0, ip, c1, c0, 0\n" /* get control register */ "bic ip, ip, #0x0001\n" /* disable MMU */ "mcr p15, 0, ip, c1, c0, 0\n" /* write control register */ "mov pc, r2\n" "nop\n" "nop\n" : /* no outpus */ : "r" (a0), "r" (a1), "r" (a2) : "r0","r1","r2","ip" ); }
// // 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'. // // Requirements // - If there is already a page mapped at 'va', it should be page_remove()d. // - If necessary, on demand, a page table should be allocated and inserted // 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'. // // Corner-case hint: Make sure to consider what happens when the same // pp is re-inserted at the same virtual address in the same pgdir. // // RETURNS: // 0 on success // -E_NO_MEM, if page table couldn't be allocated // // Hint: Check out pgdir_walk, page_remove, page2pa, and similar functions. // int page_insert(pde_t *pgdir, struct Page *pp, uintptr_t va, pte_t perm) { // Make sure the page table exists. If it doesn't, try and create one. // If that fails, exit with status -E_NO_MEM. pte_t *pte = pgdir_walk(pgdir, va, true); if (pte == NULL) return -E_NO_MEM; physaddr_t pa = page2pa(pp); Page *virtpage = page_lookup(pgdir, va, &pte); // See if there was an existing entry for va if (virtpage && (*pte & PTE_P)) { // Is it the same as the one we're entering? if (PTE_ADDR(*pte) == pa) { // Then just change the permissions and return *pte = PTE_ADDR(*pte) | perm | PTE_P; // Don't forget to invalidate the tlb! tlb_invalidate(pgdir, va); // cprintf("Found existing entry... changing permissions.\n"); return 0; } // Remove the old entry // cprintf("Found an existing entry... removing\n"); page_remove(pgdir, va); } // Either there was no entry for va, or there was an old entry and we removed it // cprintf("Adding entry...\n"); *pte = pa | perm | PTE_P; pp->pp_ref++; assert(page_lookup(pgdir, va, &pte)); assert(PTE_ADDR(*pte) == pa); return 0; }
void page_remove(Pde *pgdir, u_long va) { // Fill this function in Pte *pagetable_entry; struct Page *ppage; // pgdir_walk(pgdir, va, 0, &pagetable_entry); // if(pagetable_entry==0) return; // if((*pagetable_entry & PTE_P)==0) return; //the page is not in memory. // ppage = pa2page(*pagetable_entry); ppage = page_lookup(pgdir, va, &pagetable_entry); if (ppage == 0) { return; } ppage->pp_ref--; if (ppage->pp_ref == 0) { page_free(ppage); } *pagetable_entry = 0; //printf(" in page_remove pagetalbe_entry=%x\n",pagetable_entry); tlb_invalidate(pgdir, va); return; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in struct PageInfo *pg; pte_t *pte; pte_t **pte_store=&pte; pg=page_lookup(pgdir,va,pte_store); // If there is no physical page at that address, silently does nothing. if (!pg) {cprintf("page not found \n"); return;} // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. page_decref(pg); //cprintf("page ref after decrement : %d \n",pg->pp_ref); //- The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) if(pte_store){ **pte_store=0; // - The TLB must be invalidated if you remove an entry from // the page table. tlb_invalidate(pgdir,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'. // // Requirements // - If there is already a page mapped at 'va', it should be page_remove()d. // - If necessary, on demand, a page table should be allocated and inserted // 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'. // // Corner-case hint: Make sure to consider what happens when the same // pp is re-inserted at the same virtual address in the same pgdir. // However, try not to distinguish this case in your code, as this // frequently leads to subtle bugs; there's an elegant way to handle // everything in one code path. // // 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. // int page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm) { // Fill this function in if(!pgdir) return -E_NO_MEM; if(!pp) return -E_NO_MEM; pte_t *pt = pgdir_walk(pgdir, va, 1); if(!pt) return -E_NO_MEM; if(pt[0] & PTE_P){ //Already exsists if(PTE_ADDR(pt[0]) != page2pa(pp)) { page_remove(pgdir, va); } else { pt[0] = PTE_ADDR(pt[0]) | perm | PTE_P; return 0; } } pp->pp_ref++; tlb_invalidate(pgdir, va); pt[0] = page2pa(pp) | perm | PTE_P; return 0; }
// // 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'. // // Requirements // - If there is already a page mapped at 'va', it should be page_remove()d. // - If necessary, on demand, a page table should be allocated and inserted // 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'. // // Corner-case hint: Make sure to consider what happens when the same // pp is re-inserted at the same virtual address in the same pgdir. // Don't be tempted to write special-case code to handle this // situation, though; there's an elegant way to address it. // // 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. // int page_insert(pde_t *pgdir, struct Page *pp, void *va, int perm) { // cprintf("page_insert: pp:0x%x va:0x%x perm:0x%x\n",pp,va,perm); bool exist = 0; pte_t *pte = pgdir_walk(pgdir,va,1); // cprintf("page_insert: pte:0x%x *pte:0x%x\n",pte,*pte); if (pte == NULL) return -E_NO_MEM; if (*pte & PTE_P) { struct Page *nowpp = page_lookup(pgdir,va,0); if (nowpp!=pp) page_remove(pgdir,va); else{ tlb_invalidate(pgdir, va); exist = 1; } } // cprintf("page_insert: do not exist\n"); *pte = page2pa(pp) | perm | PTE_P; if (exist == 0) { pp->pp_ref++; } return 0; }
void tlb_flush(void) { vmstats_inc(3); int i; for (i = 0 ; i < NUM_TLB; ++i){ tlb_invalidate(i); } }
// // 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'. // // Requirements // - If there is already a page mapped at 'va', it should be page_remove()d. // - If necessary, on demand, a page table should be allocated and inserted // 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'. // // Corner-case hint: Make sure to consider what happens when the same // pp is re-inserted at the same virtual address in the same pgdir. // However, try not to distinguish this case in your code, as this // frequently leads to subtle bugs; there's an elegant way to handle // everything in one code path. // // 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. // int page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm) {/* // Fill this function in pte_t *pte; physaddr_t pa=page2pa(pp); pte=pgdir_walk(pgdir,va,1); if (pte==NULL){ cprintf("return error\n"); return -E_NO_MEM;} //Check If there is already a page mapped at 'va', if(*pte & PTE_P){ // check if same page is reinserted at the same virtual addr in same pgdir if(PTE_ADDR(*pte)==pa){ *pte=pa|perm|PTE_P; return 0; } //page should be page_remove()d and tlb invalidated. page_remove(pgdir,va); tlb_invalidate(pgdir,va); } //set permission of page_table_entry and increment pp->ref count *pte=pa |perm| PTE_P ; pp->pp_ref++; return 0; */ pte_t *pte = pgdir_walk(pgdir, va, 0); physaddr_t ppa = page2pa(pp); if (pte != NULL) { // for page alreay mapped if (*pte & PTE_P){ if(PTE_ADDR(*pte)==ppa){ *pte=ppa|perm|PTE_P; return 0; } page_remove(pgdir, va); // also invalidates tlb } if (page_free_list == pp) page_free_list = page_free_list->pp_link; } else { pte = pgdir_walk(pgdir, va, 1); if (!pte) return -E_NO_MEM; } *pte = page2pa(pp) | perm | PTE_P; pp->pp_ref++; //cprintf("ref variable count: %d \n",pp->pp_ref); tlb_invalidate(pgdir, va); return 0; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, uintptr_t va) { pte_t *pte; Page *pp = page_lookup(pgdir, va, &pte); if (pp != NULL) { page_decref(pp); *pte = *pte & ~0x1; tlb_invalidate(pgdir, va); } }
static inline void page_remove_pte(pgd_t *pgdir, uintptr_t la, pte_t *ptep) { if (*ptep & PTE_P) { struct Page *page = pte2page(*ptep); if (page_ref_dec(page) == 0) { free_page(page); } *ptep = 0; tlb_invalidate(pgdir, la); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *pte; struct PageInfo *pp = page_lookup(pgdir, va, &pte); if (!pp || !(*pte & PTE_P)) return; page_decref(pp); *pte = 0; tlb_invalidate(pgdir, va); }
/** * Check whether page directory for boot lives well. * NOTE: we don't have mm_struct at present. * as write to a clean page also raises SIGSEGV, we're not able to deal with it now. * so just mark all page inserted to be accessed and dirty. */ void check_boot_pgdir(void) { pte_t *ptep; int i; for (i = 0; i < npage; i += PGSIZE) { assert((ptep = get_pte(boot_pgdir, (uintptr_t)KADDR(i), 0)) != NULL); assert(PTE_ADDR(*ptep) == i); } //assert(PDE_ADDR(boot_pgdir[PDX(VPT)]) == PADDR(boot_pgdir)); assert(boot_pgdir[PDX(TEST_PAGE)] == 0); struct Page *p; p = alloc_page(); assert(page_insert(boot_pgdir, p, TEST_PAGE, PTE_W | PTE_D | PTE_A) == 0); assert(page_ref(p) == 1); assert(page_insert(boot_pgdir, p, TEST_PAGE + PGSIZE, PTE_W | PTE_D | PTE_A) == 0); assert(page_ref(p) == 2); const char *str = "ucore: Hello world!!"; strcpy((void *)TEST_PAGE, str); assert(strcmp((void *)TEST_PAGE, (void *)(TEST_PAGE + PGSIZE)) == 0); *(char *)(page2kva(p)) = '\0'; assert(strlen((const char *)TEST_PAGE) == 0); /* * in um architecture clear page table doesn't mean * the linear address is invalid * so remove them by hand */ tlb_invalidate (boot_pgdir, TEST_PAGE); tlb_invalidate (boot_pgdir, TEST_PAGE + PGSIZE); free_page(p); free_page(pa2page(PDE_ADDR(boot_pgdir[PDX(TEST_PAGE)]))); boot_pgdir[PDX(TEST_PAGE)] = 0; kprintf("check_boot_pgdir() succeeded.\n"); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *table_entry; struct PageInfo *page = page_lookup(pgdir, va, &table_entry); if (page) { // Decrement/free page, reset table entry, and invalidate TLB entry. page_decref(page); *table_entry = 0x0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *tmppte; struct PageInfo *tmp = page_lookup(pgdir, va, &tmppte); if( tmp != NULL && (*tmppte & PTE_P)) { page_decref(tmp); *tmppte = 0; } tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp) { page_decref(pp); *pte = 0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t* pte_store = NULL; struct PageInfo* pg = page_lookup(pgdir, va, &pte_store); if (!pg) return; page_decref(pg); tlb_invalidate(pgdir, va); *pte_store = 0; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pml4e_t *pml4e, void *va) { // Fill this function in pte_t* pte = NULL; struct Page *page = page_lookup(pml4e, va, &pte); if(page != 0){ page_decref(page); *pte = 0; tlb_invalidate(pml4e, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t * pte_page; struct Page * page = page_lookup(pgdir, va, &pte_page); if(page) { page_decref(page); (* pte_page) = 0; tlb_invalidate(pgdir, va); } }
/* * tlb_clear: flushes the TLB by loading it with invalid entries. * * Synchronization: assumes we hold coremap_spinlock. Does not block. */ static void tlb_clear(void) { int i; KASSERT(spinlock_do_i_hold(&coremap_spinlock)); for (i=0; i<NUM_TLB; i++) { tlb_invalidate(i); } curcpu->c_vm.cvm_nexttlb = 0; }
void * nw_mmio_map_region(physaddr_t pa, size_t size) { static uintptr_t base = NW_MMIOBASE; uintptr_t ret_base = base; boot_map_region(kern_pgdir, base, ROUNDUP(size, PGSIZE) , pa , PTE_P | PTE_W | PTE_PCD | PTE_PWT); base = (uintptr_t)((char *)base + ROUNDUP(size, PGSIZE)); // Fo now, there is only one address space, so always invalidate. tlb_invalidate(kern_pgdir, (void *)base); return (void *)ret_base; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t* pte; struct Page* res; res=page_lookup(pgdir,va,&pte); if(res!=NULL) { page_decref(res); *pte=0; tlb_invalidate(pgdir,va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in //bluesea struct PageInfo *page = NULL; pte_t *ptep = NULL; if ((page = page_lookup(pgdir, va, &ptep)) != NULL){ page_decref(page); *ptep = *ptep & (0xfff & ~PTE_P); tlb_invalidate(pgdir, va); } }
void tlb_init(reconos_tlb_t * tlb) { fprintf(stderr, "tlb_init called\n"); if(dcrraw_fd = -1) open_dcrraw(); tlb->page_faults = 0; tlb->invalidate_dcrn = 11; tlb->id_dcrn = 10; tlb->status1_dcrn = 5; tlb->status2_dcrn = 4; tlb_invalidate(tlb); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t* pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp != NULL) { *pte = 0; page_decref(pp); tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in /*stone's solution for lab2*/ pte_t* pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp != NULL){ *pte = 0; page_decref(pp); tlb_invalidate(pgdir, va); } return; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *pte_store; struct PageInfo *pp = page_lookup(pgdir, va, &pte_store); if(!pte_store || !(pte_store[0] & PTE_P)){ return ; } page_decref(pp); *pte_store = 0; tlb_invalidate(pgdir, va); }
void mmu_early_disable(void) { unsigned int cr; cr = get_cr(); cr &= ~(CR_M | CR_C); set_cr(cr); v8_flush_dcache_all(); tlb_invalidate(); dsb(); isb(); }