diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-01-03 00:52:30 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-01-03 00:52:30 -0500 |
commit | 8840ebcb00f3988c781063e572b6df5742968f95 (patch) | |
tree | e9711f561dff45b31489a7fb539ed98660e26d0e /src/arch/sparc | |
parent | a0e8aa6737f534a8e51d866728dd6dc59bef263d (diff) | |
parent | 7d7f3d0e99eca98a5659e73bce56d615f0ed4fc3 (diff) | |
download | gem5-8840ebcb00f3988c781063e572b6df5742968f95.tar.xz |
Merge zizzer:/bk/newmem
into zower.eecs.umich.edu:/eecshome/m5/newmem
--HG--
extra : convert_revision : f4a05accb8fa24d425dd818b1b7f268378180e99
Diffstat (limited to 'src/arch/sparc')
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 44 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/mem/blockmem.isa | 4 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/mem/util.isa | 6 | ||||
-rw-r--r-- | src/arch/sparc/tlb.cc | 205 | ||||
-rw-r--r-- | src/arch/sparc/tlb.hh | 10 |
5 files changed, 214 insertions, 55 deletions
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index e8578291c..8abaf1007 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -1039,11 +1039,31 @@ decode OP default Unknown::unknown() 0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}}); 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}}); 0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}}); - 0x13: ldtwa({{ - uint64_t val = Mem.udw; - RdLow = val<31:0>; - RdHigh = val<63:32>; - }}, {{EXT_ASI}}); + 0x13: decode EXT_ASI { + //ASI_QUAD_LDD + 0x24: TwinLoad::ldtx_quad_ldd( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_REAL + 0x26: TwinLoad::ldtx_real( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_N + 0x27: TwinLoad::ldtx_n( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_L + 0x2C: TwinLoad::ldtx_l( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_REAL_L + 0x2E: TwinLoad::ldtx_real_l( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_N_L + 0x2F: TwinLoad::ldtx_n_l( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + default: ldtwa({{ + uint64_t val = Mem.udw; + RdLow = val<31:0>; + RdHigh = val<63:32>; + }}, {{EXT_ASI}}); + } } format StoreAlt { 0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}}); @@ -1105,18 +1125,6 @@ decode OP default Unknown::unknown() 0x15: FailUnimpl::lddfa_real_io(); //ASI_REAL_IO_LITTLE 0x1D: FailUnimpl::lddfa_real_io_l(); - //ASI_LDTX_REAL - 0x26: TwinLoad::ldtx_real( - {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); - //ASI_LDTX_N - 0x27: TwinLoad::ldtx_n( - {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); - //ASI_LDTX_REAL_L - 0x2E: TwinLoad::ldtx_real_l( - {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); - //ASI_LDTX_N_L - 0x2F: TwinLoad::ldtx_n_l( - {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); //ASI_PRIMARY 0x80: FailUnimpl::lddfa_p(); //ASI_PRIMARY_LITTLE diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index c4f052f98..62ac4b43a 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -101,7 +101,7 @@ output header {{ // We make the assumption that all block memory operations // Will take 8 instructions to execute TwinMem(const char *mnem, ExtMachInst _machInst) : - SparcMacroInst(mnem, _machInst, No_OpClass, 8) + SparcMacroInst(mnem, _machInst, No_OpClass, 2) {} }; diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index c56821c4f..5bb4e1fe6 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -295,9 +295,9 @@ let {{ fault = new MemAddressNotAligned; ''' TwinAlignmentFaultCheck = ''' - if(RD & 0xe) + if(RD & 0x1) fault = new IllegalInstruction; - else if(EA & 0x1f) + else if(EA & 0xf) fault = new MemAddressNotAligned; ''' # XXX Need to take care of pstate.hpriv as well. The lower ASIs diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 675287d18..40542a9a6 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -45,7 +45,8 @@ namespace SparcISA { TLB::TLB(const std::string &name, int s) - : SimObject(name), size(s), usedEntries(0), cacheValid(false) + : SimObject(name), size(s), usedEntries(0), lastReplaced(0), + cacheValid(false) { // To make this work you'll have to change the hypervisor and OS if (size > 64) @@ -53,13 +54,16 @@ TLB::TLB(const std::string &name, int s) tlb = new TlbEntry[size]; memset(tlb, 0, sizeof(TlbEntry) * size); + + for (int x = 0; x < size; x++) + freeList.push_back(&tlb[x]); } void TLB::clearUsedBits() { MapIter i; - for (i = lookupTable.begin(); i != lookupTable.end();) { + for (i = lookupTable.begin(); i != lookupTable.end(); i++) { TlbEntry *t = i->second; if (!t->pte.locked()) { t->used = false; @@ -77,32 +81,76 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, MapIter i; TlbEntry *new_entry = NULL; + TlbRange tr; int x; cacheValid = false; + tr.va = va; + tr.size = PTE.size() - 1; + tr.contextId = context_id; + tr.partitionId = partition_id; + tr.real = real; + + + DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", + va, PTE.paddr(), partition_id, context_id, (int)real, entry); + + // Demap any entry that conflicts + i = lookupTable.find(tr); + if (i != lookupTable.end()) { + i->second->valid = false; + if (i->second->used) { + i->second->used = false; + usedEntries--; + } + freeList.push_front(i->second); + DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n", + i->second); + lookupTable.erase(i); + } - DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n", - va, PTE.paddr(), partition_id, context_id, (int)real); if (entry != -1) { assert(entry < size && entry >= 0); new_entry = &tlb[entry]; } else { + if (!freeList.empty()) { + new_entry = freeList.front(); + } else { + x = lastReplaced; + do { + ++x; + if (x == size) + x = 0; + if (x == lastReplaced) + goto insertAllLocked; + } while (tlb[x].pte.locked()); + lastReplaced = x; + new_entry = &tlb[x]; + lookupTable.erase(new_entry->range); + } + /* for (x = 0; x < size; x++) { if (!tlb[x].valid || !tlb[x].used) { new_entry = &tlb[x]; break; } - } + }*/ } +insertAllLocked: // Update the last ently if their all locked - if (!new_entry) + if (!new_entry) { new_entry = &tlb[size-1]; + lookupTable.erase(new_entry->range); + } + + freeList.remove(new_entry); + DPRINTF(TLB, "Using entry: %#X\n", new_entry); assert(PTE.valid()); new_entry->range.va = va; - new_entry->range.size = PTE.size(); + new_entry->range.size = PTE.size() - 1; new_entry->range.partitionId = partition_id; new_entry->range.contextId = context_id; new_entry->range.real = real; @@ -112,19 +160,9 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, usedEntries++; - // Demap any entry that conflicts - i = lookupTable.find(new_entry->range); - if (i != lookupTable.end()) { - i->second->valid = false; - if (i->second->used) { - i->second->used = false; - usedEntries--; - } - DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); - lookupTable.erase(i); - } - lookupTable.insert(new_entry->range, new_entry);; + i = lookupTable.insert(new_entry->range, new_entry); + assert(i != lookupTable.end()); // If all entries have there used bit set, clear it on them all, but the // one we just inserted @@ -148,7 +186,7 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id) va, partition_id, context_id, real); // Assemble full address structure tr.va = va; - tr.size = va + MachineBytes; + tr.size = MachineBytes; tr.contextId = context_id; tr.partitionId = partition_id; tr.real = real; @@ -180,6 +218,7 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id) void TLB::dumpAll() { + MapIter i; for (int x = 0; x < size; x++) { if (tlb[x].valid) { DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n", @@ -196,11 +235,14 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) TlbRange tr; MapIter i; + DPRINTF(IPR, "TLB: Demapping Page va=%#x pid=%#d cid=%d r=%d\n", + va, partition_id, context_id, real); + cacheValid = false; // Assemble full address structure tr.va = va; - tr.size = va + MachineBytes; + tr.size = MachineBytes; tr.contextId = context_id; tr.partitionId = partition_id; tr.real = real; @@ -208,11 +250,14 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) // Demap any entry that conflicts i = lookupTable.find(tr); if (i != lookupTable.end()) { + DPRINTF(IPR, "TLB: Demapped page\n"); i->second->valid = false; if (i->second->used) { i->second->used = false; usedEntries--; } + freeList.push_front(i->second); + DPRINTF(TLB, "Freeing TLB entry : %#X\n", i->second); lookupTable.erase(i); } } @@ -221,10 +266,16 @@ void TLB::demapContext(int partition_id, int context_id) { int x; + DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", + partition_id, context_id); cacheValid = false; for (x = 0; x < size; x++) { if (tlb[x].range.contextId == context_id && tlb[x].range.partitionId == partition_id) { + if (tlb[x].valid == true) { + freeList.push_front(&tlb[x]); + DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); + } tlb[x].valid = false; if (tlb[x].used) { tlb[x].used = false; @@ -239,9 +290,14 @@ void TLB::demapAll(int partition_id) { int x; + DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); cacheValid = false; for (x = 0; x < size; x++) { if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { + if (tlb[x].valid == true){ + freeList.push_front(&tlb[x]); + DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); + } tlb[x].valid = false; if (tlb[x].used) { tlb[x].used = false; @@ -258,7 +314,10 @@ TLB::invalidateAll() int x; cacheValid = false; + freeList.clear(); for (x = 0; x < size; x++) { + if (tlb[x].valid == true) + freeList.push_back(&tlb[x]); tlb[x].valid = false; } usedEntries = 0; @@ -266,17 +325,26 @@ TLB::invalidateAll() uint64_t TLB::TteRead(int entry) { + if (entry >= size) + panic("entry: %d\n", entry); + assert(entry < size); - return tlb[entry].pte(); + if (tlb[entry].valid) + return tlb[entry].pte(); + else + return (uint64_t)-1ll; } uint64_t TLB::TagRead(int entry) { assert(entry < size); uint64_t tag; + if (!tlb[entry].valid) + return (uint64_t)-1ll; - tag = tlb[entry].range.contextId | tlb[entry].range.va | - (uint64_t)tlb[entry].range.partitionId << 61; + tag = tlb[entry].range.contextId; + tag |= tlb[entry].range.va; + tag |= (uint64_t)tlb[entry].range.partitionId << 61; tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; tag |= (uint64_t)~tlb[entry].pte._size() << 56; return tag; @@ -492,13 +560,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) // Be fast if we can! if (cacheValid && cacheState == tlbdata) { if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && - cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) { + cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr) { req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | vaddr & cacheEntry[0]->pte.size()-1 ); return NoFault; } if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && - cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) { + cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr) { req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | vaddr & cacheEntry[1]->pte.size()-1 ); return NoFault; @@ -575,6 +643,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (write && asi == ASI_LDTX_P) // block init store (like write hint64) goto continueDtbFlow; + if (!write && asi == ASI_QUAD_LDD) + goto continueDtbFlow; + if (AsiIsTwin(asi)) panic("Twin ASIs not supported\n"); if (AsiIsPartialStore(asi)) @@ -655,8 +726,12 @@ continueDtbFlow: } // cache translation date for next translation - cacheValid = true; cacheState = tlbdata; + if (!cacheValid) { + cacheEntry[1] = NULL; + cacheEntry[0] = NULL; + } + if (cacheEntry[0] != e && cacheEntry[1] != e) { cacheEntry[1] = cacheEntry[0]; cacheEntry[0] = e; @@ -665,7 +740,7 @@ continueDtbFlow: if (implicit) cacheAsi[0] = (ASI)0; } - + cacheValid = true; req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | vaddr & e->pte.size()-1); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); @@ -684,7 +759,7 @@ handleQueueRegAccess: writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); return new PrivilegedAction; } - if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { + if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } @@ -881,6 +956,9 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) int part_insert; int entry_insert = -1; bool real_insert; + bool ignore; + int part_id; + int ctx_id; PageTableEntry pte; DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", @@ -1000,6 +1078,41 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) PageTableEntry::sun4u); insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); break; + case ASI_IMMU_DEMAP: + ignore = false; + ctx_id = -1; + part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + switch (bits(va,5,4)) { + case 0: + ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + break; + case 1: + ignore = true; + break; + case 3: + ctx_id = 0; + break; + default: + ignore = true; + } + + switch(bits(va,7,6)) { + case 0: // demap page + if (!ignore) + tc->getITBPtr()->demapPage(mbits(va,63,13), part_id, + bits(va,9,9), ctx_id); + break; + case 1: //demap context + if (!ignore) + tc->getITBPtr()->demapContext(part_id, ctx_id); + break; + case 2: + tc->getITBPtr()->demapAll(part_id); + break; + default: + panic("Invalid type for IMMU demap\n"); + } + break; case ASI_DMMU: switch (va) { case 0x30: @@ -1012,6 +1125,40 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) goto doMmuWriteError; } break; + case ASI_DMMU_DEMAP: + ignore = false; + ctx_id = -1; + part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + switch (bits(va,5,4)) { + case 0: + ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + break; + case 1: + ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT); + break; + case 3: + ctx_id = 0; + break; + default: + ignore = true; + } + + switch(bits(va,7,6)) { + case 0: // demap page + if (!ignore) + demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id); + break; + case 1: //demap context + if (!ignore) + demapContext(part_id, ctx_id); + break; + case 2: + demapAll(part_id); + break; + default: + panic("Invalid type for IMMU demap\n"); + } + break; default: doMmuWriteError: panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index a6e6a8bd3..34e5f5feb 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -54,10 +54,13 @@ class TLB : public SimObject int size; int usedEntries; + int lastReplaced; uint64_t cacheState; bool cacheValid; + std::list<TlbEntry*> freeList; + enum FaultTypes { OtherFault = 0, PrivViolation = 0x1, @@ -93,9 +96,6 @@ class TLB : public SimObject /** Given an entry id, read that tlb entries' tag. */ uint64_t TagRead(int entry); - /** Give an entry id, read that tlb entries' tte */ - uint64_t TteRead(int entry); - /** Remove all entries from the TLB */ void invalidateAll(); @@ -128,6 +128,10 @@ class TLB : public SimObject // Checkpointing virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); + + /** Give an entry id, read that tlb entries' tte */ + uint64_t TteRead(int entry); + }; class ITB : public TLB |