diff options
Diffstat (limited to 'src/arch/sparc/vtophys.cc')
-rw-r--r-- | src/arch/sparc/vtophys.cc | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index 429126b70..cb545185a 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -25,14 +25,14 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Nathan Binkert - * Steve Reinhardt - * Ali Saidi + * Authors: Ali Saidi */ #include <string> #include "arch/sparc/vtophys.hh" +#include "arch/sparc/tlb.hh" +#include "base/compiler.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" @@ -42,37 +42,83 @@ using namespace std; namespace SparcISA { - PageTableEntry kernel_pte_lookup(FunctionalPort *mem, - Addr ptbr, VAddr vaddr) - { - PageTableEntry pte(4); - return pte; - } - Addr vtophys(Addr vaddr) { - return 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 } Addr vtophys(ThreadContext *tc, Addr addr) { - return 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->readMiscReg(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); - void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) - { - } + FunctionalPort *mem = tc->getPhysPort(); + ITB* itb = tc->getITBPtr(); + DTB* dtb = tc->getDTBPtr(); + TlbEntry* tbe; + PageTableEntry pte; + Addr tsbs[4]; + Addr va_tag; + TteTag ttetag; - void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) - { - } + if (hpriv) + return addr; - void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) - { - } + if (addr_mask) + addr = addr & VAddrAMask; - void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) - { + 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; + } + } + 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(); } } |