From 6841f863c5dee6ce2028ba647254ec9ad27a57fd Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 18 Dec 2006 03:37:52 -0500 Subject: move the twinx loads to the correct opcode and add asis 0x24 and 0x27 Make the TLB ok to translate QUAD_LDD src/arch/sparc/isa/decoder.isa: move the twinx loads to the correct opcode. src/arch/sparc/tlb.cc: Make QUAD_LDD asi ok to execute --HG-- extra : convert_revision : 2a44d1c9e4edb627079fc05776c28d918c8508ce --- src/arch/sparc/isa/decoder.isa | 42 +++++++++++++++++++++++++----------------- src/arch/sparc/tlb.cc | 3 +++ 2 files changed, 28 insertions(+), 17 deletions(-) (limited to 'src/arch') diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index bbc6a8c4b..e2bebd987 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -1060,11 +1060,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}}); @@ -1126,18 +1146,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/tlb.cc b/src/arch/sparc/tlb.cc index 675287d18..1eb3aa53b 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -575,6 +575,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)) -- cgit v1.2.3 From 5e9d8795f2a2642843cbb73b2637adb97935521d Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 19 Dec 2006 02:11:33 -0500 Subject: fix twinx loads a little bit bugfixes and demap implementation in tlb ignore some more differencs for one cycle src/arch/sparc/isa/formats/mem/blockmem.isa: twinx has 2 micro-ops src/arch/sparc/isa/formats/mem/util.isa: fix the fault check for twinx src/arch/sparc/tlb.cc: tlb bugfixes and write demapping code src/cpu/exetrace.cc: don't halt on a couple more instruction (ldx, stx) when things differ beacuse of the way tlb faults are handled in legion. --HG-- extra : convert_revision : 1e156dead6ebd58b257213625ed63c3793ef4b71 --- src/arch/sparc/isa/formats/mem/blockmem.isa | 2 +- src/arch/sparc/isa/formats/mem/util.isa | 4 +- src/arch/sparc/tlb.cc | 87 ++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 6 deletions(-) (limited to 'src/arch') diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 8bbbdc1da..5d05dad03 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -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 3f9146c21..b6e0945b7 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -285,9 +285,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 1eb3aa53b..327ab659b 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -124,7 +124,8 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, 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 +149,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 +181,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 +198,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,6 +213,7 @@ 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; @@ -221,6 +227,8 @@ 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 && @@ -239,6 +247,7 @@ 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) { @@ -884,6 +893,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", @@ -1003,6 +1015,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: @@ -1015,6 +1062,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", -- cgit v1.2.3 From ba14d6d0e1debea686681e5738bcdb041522dca0 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 27 Dec 2006 14:38:07 -0500 Subject: Bug fixes in the TLB Make our replacement algorithm same as legion (although not same as the spec) itb should be 64 entries not 48 src/arch/sparc/tlb.cc: Bug fixes in the TLB Make our replacement algorithm same as legion (although not same as the spec) src/arch/sparc/tlb.hh: Make our replacement algorithm same as legion (although not same as the spec) src/python/m5/objects/SparcTLB.py: itb should be 64 entries too --HG-- extra : convert_revision : 1b5cb3597091e3cfe293e94f6f2219b1e621c35f --- src/arch/sparc/tlb.cc | 115 ++++++++++++++++++++++++++++++++++++++------------ src/arch/sparc/tlb.hh | 10 +++-- 2 files changed, 96 insertions(+), 29 deletions(-) (limited to 'src/arch') diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 327ab659b..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,17 +160,6 @@ 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); - } i = lookupTable.insert(new_entry->range, new_entry); assert(i != lookupTable.end()); @@ -219,6 +256,8 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) i->second->used = false; usedEntries--; } + freeList.push_front(i->second); + DPRINTF(TLB, "Freeing TLB entry : %#X\n", i->second); lookupTable.erase(i); } } @@ -233,6 +272,10 @@ TLB::demapContext(int partition_id, int context_id) 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; @@ -251,6 +294,10 @@ TLB::demapAll(int 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; @@ -267,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; @@ -275,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; @@ -501,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; @@ -667,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; @@ -677,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()); @@ -696,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; } 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 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 -- cgit v1.2.3