diff options
Diffstat (limited to 'src/arch/sparc/vtophys.cc')
-rw-r--r-- | src/arch/sparc/vtophys.cc | 162 |
1 files changed, 85 insertions, 77 deletions
diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index 9a93950d2..f23fb8304 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -40,85 +40,93 @@ using namespace std; -namespace SparcISA +namespace SparcISA { + +Addr +vtophys(Addr vaddr) { - Addr vtophys(Addr vaddr) - { - // In SPARC it's almost always impossible to turn a VA->PA w/o a context - // The only times we can kinda do it are if we have a SegKPM mapping - // and can find the real address in the tlb or we have a physical - // adddress already (beacuse we are looking at the hypervisor) - // Either case is rare, so we'll just panic. - - panic("vtophys() without context on SPARC largly worthless\n"); - M5_DUMMY_RETURN - } + // In SPARC it's almost always impossible to turn a VA->PA w/o a + // context The only times we can kinda do it are if we have a + // SegKPM mapping and can find the real address in the tlb or we + // have a physical adddress already (beacuse we are looking at the + // hypervisor) Either case is rare, so we'll just panic. + + panic("vtophys() without context on SPARC largly worthless\n"); + M5_DUMMY_RETURN; +} + +Addr +vtophys(ThreadContext *tc, Addr addr) +{ + // Here we have many options and are really implementing something like + // a fill handler to find the address since there isn't a multilevel + // table for us to walk around. + // + // 1. We are currently hyperpriv, return the address unmodified + // 2. The mmu is off return(ra->pa) + // 3. We are currently priv, use ctx0* tsbs to find the page + // 4. We are not priv, use ctxN0* tsbs to find the page + // For all accesses we check the tlbs first since it's possible that + // long standing pages (e.g. locked kernel mappings) won't be in the tsb + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + + bool hpriv = bits(tlbdata,0,0); + //bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool data_real = !bits(tlbdata,5,5); + bool inst_real = !bits(tlbdata,4,4); + bool ctx_zero = bits(tlbdata,18,16) > 0; + int part_id = bits(tlbdata,15,8); + int pri_context = bits(tlbdata,47,32); + //int sec_context = bits(tlbdata,63,48); - Addr vtophys(ThreadContext *tc, Addr addr) - { - // Here we have many options and are really implementing something like - // a fill handler to find the address since there isn't a multilevel - // table for us to walk around. - // - // 1. We are currently hyperpriv, return the address unmodified - // 2. The mmu is off return(ra->pa) - // 3. We are currently priv, use ctx0* tsbs to find the page - // 4. We are not priv, use ctxN0* tsbs to find the page - // For all accesses we check the tlbs first since it's possible that - // long standing pages (e.g. locked kernel mappings) won't be in the tsb - uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); - - bool hpriv = bits(tlbdata,0,0); - //bool priv = bits(tlbdata,2,2); - bool addr_mask = bits(tlbdata,3,3); - bool data_real = !bits(tlbdata,5,5); - bool inst_real = !bits(tlbdata,4,4); - bool ctx_zero = bits(tlbdata,18,16) > 0; - int part_id = bits(tlbdata,15,8); - int pri_context = bits(tlbdata,47,32); - //int sec_context = bits(tlbdata,63,48); - - FunctionalPort *mem = tc->getPhysPort(); - ITB* itb = tc->getITBPtr(); - DTB* dtb = tc->getDTBPtr(); - TlbEntry* tbe; - PageTableEntry pte; - Addr tsbs[4]; - Addr va_tag; - TteTag ttetag; - - if (hpriv) - return addr; - - if (addr_mask) - addr = addr & VAddrAMask; - - tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false); - if (tbe) goto foundtbe; - - tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false); - if (tbe) goto foundtbe; - - // We didn't find it in the tlbs, so lets look at the TSBs - dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); - va_tag = bits(addr, 63, 22); - for (int x = 0; x < 4; x++) { - ttetag = betoh(mem->read<uint64_t>(tsbs[x])); - if (ttetag.valid() && ttetag.va() == va_tag) { - pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)), - PageTableEntry::sun4v); // I think it's sun4v at least! - DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr, - pte.paddrMask() | addr & pte.sizeMask()); - goto foundpte; - } + FunctionalPort *mem = tc->getPhysPort(); + ITB* itb = tc->getITBPtr(); + DTB* dtb = tc->getDTBPtr(); + TlbEntry* tbe; + PageTableEntry pte; + Addr tsbs[4]; + Addr va_tag; + TteTag ttetag; + + if (hpriv) + return addr; + + if (addr_mask) + addr = addr & VAddrAMask; + + tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , + false); + if (tbe) + goto foundtbe; + + tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, + false); + if (tbe) + goto foundtbe; + + // We didn't find it in the tlbs, so lets look at the TSBs + dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); + va_tag = bits(addr, 63, 22); + for (int x = 0; x < 4; x++) { + ttetag = betoh(mem->read<uint64_t>(tsbs[x])); + if (ttetag.valid() && ttetag.va() == va_tag) { + uint64_t entry = mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t); + // I think it's sun4v at least! + pte.populate(betoh(entry), PageTableEntry::sun4v); + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", + addr, pte.translate(addr)); + goto foundpte; } - panic("couldn't translate %#x\n", addr); - -foundtbe: - pte = tbe->pte; - DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, - pte.paddrMask() | addr & pte.sizeMask()); -foundpte: - return pte.paddrMask() | addr & pte.sizeMask(); } + panic("couldn't translate %#x\n", addr); + + foundtbe: + pte = tbe->pte; + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, + pte.translate(addr)); + foundpte: + return pte.translate(addr); } + +} /* namespace SparcISA */ |