Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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];
    }