summaryrefslogtreecommitdiff
path: root/src/arch/sparc
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-01-03 00:52:30 -0500
committerGabe Black <gblack@eecs.umich.edu>2007-01-03 00:52:30 -0500
commit8840ebcb00f3988c781063e572b6df5742968f95 (patch)
treee9711f561dff45b31489a7fb539ed98660e26d0e /src/arch/sparc
parenta0e8aa6737f534a8e51d866728dd6dc59bef263d (diff)
parent7d7f3d0e99eca98a5659e73bce56d615f0ed4fc3 (diff)
downloadgem5-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.isa44
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa4
-rw-r--r--src/arch/sparc/isa/formats/mem/util.isa6
-rw-r--r--src/arch/sparc/tlb.cc205
-rw-r--r--src/arch/sparc/tlb.hh10
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 &section);
+
+ /** Give an entry id, read that tlb entries' tte */
+ uint64_t TteRead(int entry);
+
};
class ITB : public TLB