OBJECT * vmm_vaddr_to_memobj(PROCESS *prp, void *addr, unsigned *offset, int mark_page) { pte_t *ptep; uint32_t pte_lo; unsigned pgsize; paddr_t paddr; uintptr_t vaddr = (uintptr_t)addr; ADDRESS *adp; if((vaddr >= MIPS_R4K_K0BASE) && (vaddr < (MIPS_R4K_K1BASE+MIPS_R4K_K1SIZE))) { // Assuming kseg0 & kseg1 are the same size paddr = vaddr & (MIPS_R4K_K0SIZE - 1); *offset = PADDR_TO_SYNC_OFF(paddr); return PADDR_TO_SYNC_OBJ(paddr); } CRASHCHECK(prp == NULL); adp = prp->memory; CRASHCHECK(adp == NULL); ptep = adp->cpu.pgdir[L1IDX(vaddr)]; if(ptep != NULL) { ptep += L2IDX(vaddr); pte_lo = ptep->lo; if(PTE_PRESENT(pte_lo)) { pgsize = PGMASK_TO_PGSIZE(ptep->pm); if(pgsize > __PAGESIZE) { // Because we scramble the PTE's up when dealing with // big pages so that the TLB miss handler can be quick, // the ptep that we got up above might not have the correct // paddr information in it for this address. Because of the // way cpu_pte_merge() works, we can get the PTE for the // start of big page and artificially multiply the page // size by 2. Then when we pull the paddr out of the PTE // everything works out. uintptr_t check = vaddr & ~(pgsize*2 - 1); pte_lo = adp->cpu.pgdir[L1IDX(check)][L2IDX(check)].lo; pgsize *= 2; } paddr = PTE_PADDR(pte_lo) + (vaddr & (pgsize - 1)); if(mark_page) { struct pa_quantum *pq; pq = pa_paddr_to_quantum(paddr); if(pq != NULL) { pq->flags |= PAQ_FLAG_HAS_SYNC; } } *offset = PADDR_TO_SYNC_OFF(paddr); return PADDR_TO_SYNC_OBJ(paddr); } } CRASHCHECK(1); return (OBJECT *)-1; }
static hwpte_t *lookup_va(MMU_st *st, word_t va) { hwpte_t *l1, *l2, *lpte; word_t lpte_va, offset; lpte = &(st->lptbr[VPN(va)]); if(!st->enabled) { /* Need to 'translate' lpte internally via system ptab */ lpte_va = (word_t)lpte - PTAB_BASE; /* Get its L1 idx & its L2 one */ l1 = &(st->l1tab[L1IDX(lpte_va)]); if(!l1->ctl.flags.c_valid) { /* L1 not valid => TNV! */ eprintf("lookup_va (va=%p): L1 lpte entry [%lx] not valid!\n", va, *((word_t *)l1)); return NULL; } l2 = ((hwpte_t *)((word_t)l1->pfn << FRAME_WIDTH)) + L2IDX(lpte_va); if(!l2->ctl.flags.c_valid) { eprintf("lookup_va (va=%p): L2 lpte entry [%lx] not valid!\n", va, *((word_t *)l2)); /* L2 not valid => TNV! */ return NULL; } offset = (lpte_va & 0x1FFF) >> 3; lpte = &((hwpte_t *)((word_t)l2->pfn << FRAME_WIDTH))[offset]; }