summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDam Sunwoo <dam.sunwoo@arm.com>2010-06-02 12:58:18 -0500
committerDam Sunwoo <dam.sunwoo@arm.com>2010-06-02 12:58:18 -0500
commit6c8dd32fa4f21771a2c83886b08c3d68be516044 (patch)
tree35a88b63e76ee57ffe73a1a2b118d2b2e676800c /src
parent85ba2a32436aa7dde2319f213b5f410a80c6453a (diff)
downloadgem5-6c8dd32fa4f21771a2c83886b08c3d68be516044.tar.xz
ARM: Added support for Access Flag and some CP15 regs (V2PCWPR, V2PCWPW, V2PCWUR, V2PCWUW,...)
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/isa.cc89
-rw-r--r--src/arch/arm/miscregs.hh28
-rw-r--r--src/arch/arm/pagetable.hh8
-rw-r--r--src/arch/arm/table_walker.cc247
-rw-r--r--src/arch/arm/table_walker.hh59
-rw-r--r--src/arch/arm/tlb.cc17
-rw-r--r--src/arch/arm/tlb.hh15
7 files changed, 414 insertions, 49 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 25e616e8e..60f00e438 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -117,6 +117,38 @@ ISA::clear()
miscRegs[MISCREG_MPIDR] = 0;
+ // Reset values of PRRR and NMRR are implementation dependent
+
+ miscRegs[MISCREG_PRRR] =
+ (1 << 19) | // 19
+ (0 << 18) | // 18
+ (0 << 17) | // 17
+ (1 << 16) | // 16
+ (2 << 14) | // 15:14
+ (0 << 12) | // 13:12
+ (2 << 10) | // 11:10
+ (2 << 8) | // 9:8
+ (2 << 6) | // 7:6
+ (2 << 4) | // 5:4
+ (1 << 2) | // 3:2
+ 0; // 1:0
+ miscRegs[MISCREG_NMRR] =
+ (1 << 30) | // 31:30
+ (0 << 26) | // 27:26
+ (0 << 24) | // 25:24
+ (3 << 22) | // 23:22
+ (2 << 20) | // 21:20
+ (0 << 18) | // 19:18
+ (0 << 16) | // 17:16
+ (1 << 14) | // 15:14
+ (0 << 12) | // 13:12
+ (2 << 10) | // 11:10
+ (0 << 8) | // 9:8
+ (3 << 6) | // 7:6
+ (2 << 4) | // 5:4
+ (0 << 2) | // 3:2
+ 0; // 1:0
+
//XXX We need to initialize the rest of the state.
}
@@ -362,6 +394,63 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
case MISCREG_DTLBIASID:
tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
return;
+ case MISCREG_V2PCWPR:
+ case MISCREG_V2PCWPW:
+ case MISCREG_V2PCWUR:
+ case MISCREG_V2PCWUW:
+ case MISCREG_V2POWPR:
+ case MISCREG_V2POWPW:
+ case MISCREG_V2POWUR:
+ case MISCREG_V2POWUW:
+ {
+ RequestPtr req = new Request;
+ unsigned flags;
+ BaseTLB::Mode mode;
+ Fault fault;
+ switch(misc_reg) {
+ case MISCREG_V2PCWPR:
+ flags = TLB::MustBeOne;
+ mode = BaseTLB::Read;
+ break;
+ case MISCREG_V2PCWPW:
+ flags = TLB::MustBeOne;
+ mode = BaseTLB::Write;
+ break;
+ case MISCREG_V2PCWUR:
+ flags = TLB::MustBeOne | TLB::UserMode;
+ mode = BaseTLB::Read;
+ break;
+ case MISCREG_V2PCWUW:
+ flags = TLB::MustBeOne | TLB::UserMode;
+ mode = BaseTLB::Write;
+ break;
+ case MISCREG_V2POWPR:
+ case MISCREG_V2POWPW:
+ case MISCREG_V2POWUR:
+ case MISCREG_V2POWUW:
+ panic("Security Extensions not implemented!");
+ }
+ req->setVirt(0, val, 1, flags, tc->readPC());
+ fault = tc->getDTBPtr()->translateAtomic(req, tc, mode);
+ if (fault == NoFault) {
+ miscRegs[MISCREG_PAR] =
+ (req->getPaddr() & 0xfffff000) |
+ (tc->getDTBPtr()->getAttr() );
+ DPRINTF(MiscRegs,
+ "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n",
+ val, miscRegs[MISCREG_PAR]);
+ }
+ else {
+ // Set fault bit and FSR
+ FSR fsr = miscRegs[MISCREG_DFSR];
+ miscRegs[MISCREG_PAR] =
+ (fsr.ext << 6) |
+ (fsr.fsHigh << 5) |
+ (fsr.fsLow << 1) |
+ 0x1; // F bit
+ }
+ return;
+ }
}
}
setMiscRegNoEffect(misc_reg, newVal);
diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh
index ad8f01dd0..267626e74 100644
--- a/src/arch/arm/miscregs.hh
+++ b/src/arch/arm/miscregs.hh
@@ -138,6 +138,15 @@ namespace ArmISA
MISCREG_CTR,
MISCREG_SCR,
MISCREG_SDER,
+ MISCREG_PAR,
+ MISCREG_V2PCWPR,
+ MISCREG_V2PCWPW,
+ MISCREG_V2PCWUR,
+ MISCREG_V2PCWUW,
+ MISCREG_V2POWPR,
+ MISCREG_V2POWPW,
+ MISCREG_V2POWUR,
+ MISCREG_V2POWUW,
MISCREG_CP15_UNIMP_START,
MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
MISCREG_ID_PFR1,
@@ -153,7 +162,6 @@ namespace ArmISA
MISCREG_ID_ISAR3,
MISCREG_ID_ISAR4,
MISCREG_ID_ISAR5,
- MISCREG_PAR,
MISCREG_AIDR,
MISCREG_ACTLR,
MISCREG_ADFSR,
@@ -163,14 +171,6 @@ namespace ArmISA
MISCREG_MCCSW,
MISCREG_DCCMVAU,
MISCREG_NSACR,
- MISCREG_V2PCWPR,
- MISCREG_V2PCWPW,
- MISCREG_V2PCWUR,
- MISCREG_V2PCWUW,
- MISCREG_V2POWPR,
- MISCREG_V2POWPW,
- MISCREG_V2POWUR,
- MISCREG_V2POWUW,
MISCREG_VBAR,
MISCREG_MVBAR,
MISCREG_ISR,
@@ -206,20 +206,20 @@ namespace ArmISA
"dtlbiall", "dtlbimva", "dtlbiasid",
"tlbiall", "tlbimva", "tlbiasid", "tlbimvaa",
"dfsr", "ifsr", "dfar", "ifar", "mpidr",
- "prrr", "nmrr", "ttbcr", "id_pfr0", "ctr"
- "scr", "sder"
+ "prrr", "nmrr", "ttbcr", "id_pfr0", "ctr",
+ "scr", "sder", "par",
+ "v2pcwpr", "v2pcwpw", "v2pcwur", "v2pcwuw",
+ "v2powpr", "v2powpw", "v2powur", "v2powuw",
// Unimplemented below
"tcmtr",
"id_pfr1", "id_dfr0", "id_afr0",
"id_mmfr0", "id_mmfr1", "id_mmfr2", "id_mmfr3",
"id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
- "par", "aidr", "actlr",
+ "aidr", "actlr",
"adfsr", "aifsr",
"dcimvac", "dcisw", "mccsw",
"dccmvau",
"nsacr",
- "v2pcwpr", "v2pcwpw", "v2pcwur", "v2pcwuw",
- "v2powpr", "v2powpw", "v2powur", "v2powuw",
"vbar", "mvbar", "isr", "fceidr",
"nop", "raz"
};
diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh
index f1e86f0cc..76b0e3bb8 100644
--- a/src/arch/arm/pagetable.hh
+++ b/src/arch/arm/pagetable.hh
@@ -133,6 +133,14 @@ struct TlbEntry
bool nonCacheable; // Can we wrap this in mtype?
bool sNp; // Section descriptor
+ // Memory Attributes
+ MemoryType mtype;
+ uint8_t innerAttrs;
+ uint8_t outerAttrs;
+ bool shareable;
+ uint32_t attributes; // Memory attributes formatted for PAR
+
+
// Access permissions
bool xn; // Execute Never
uint8_t ap:3; // Access permissions bits
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index e3ecb7ddd..85d5b00cf 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -96,8 +96,8 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode m
contextId = _cid;
timing = _timing;
- // XXX These should be cached or grabbed from cached copies in
- // the TLB, all these miscreg reads are expensive
+ /** @todo These should be cached or grabbed from cached copies in
+ the TLB, all these miscreg reads are expensive */
vaddr = req->getVaddr() & ~PcModeMask;
sctlr = tc->readMiscReg(MISCREG_SCTLR);
cpsr = tc->readMiscReg(MISCREG_CPSR);
@@ -149,58 +149,224 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode m
}
void
-TableWalker::memAttrs(TlbEntry &te, uint8_t texcb)
+TableWalker::memAttrs(TlbEntry &te, uint8_t texcb, bool s)
{
-
+ DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
+ te.shareable = false; // default value
+ bool outer_shareable = false;
if (sctlr.tre == 0) {
switch(texcb) {
- case 0:
- case 1:
- case 4:
- case 8:
+ case 0: // Stongly-ordered
+ te.nonCacheable = true;
+ te.mtype = TlbEntry::StronglyOrdered;
+ te.shareable = true;
+ te.innerAttrs = 1;
+ te.outerAttrs = 0;
+ break;
+ case 1: // Shareable Device
te.nonCacheable = true;
+ te.mtype = TlbEntry::Device;
+ te.shareable = true;
+ te.innerAttrs = 3;
+ te.outerAttrs = 0;
+ break;
+ case 2: // Outer and Inner Write-Through, no Write-Allocate
+ te.mtype = TlbEntry::Normal;
+ te.shareable = s;
+ te.innerAttrs = 6;
+ te.outerAttrs = bits(texcb, 1, 0);
+ break;
+ case 3: // Outer and Inner Write-Back, no Write-Allocate
+ te.mtype = TlbEntry::Normal;
+ te.shareable = s;
+ te.innerAttrs = 7;
+ te.outerAttrs = bits(texcb, 1, 0);
+ break;
+ case 4: // Outer and Inner Non-cacheable
+ te.nonCacheable = true;
+ te.mtype = TlbEntry::Normal;
+ te.shareable = s;
+ te.innerAttrs = 0;
+ te.outerAttrs = bits(texcb, 1, 0);
+ break;
+ case 5: // Reserved
+ break;
+ case 6: // Implementation Defined
break;
- case 16:
+ case 7: // Outer and Inner Write-Back, Write-Allocate
+ te.mtype = TlbEntry::Normal;
+ te.shareable = s;
+ te.innerAttrs = 5;
+ te.outerAttrs = 1;
+ break;
+ case 8: // Non-shareable Device
+ te.nonCacheable = true;
+ te.mtype = TlbEntry::Device;
+ te.shareable = false;
+ te.innerAttrs = 3;
+ te.outerAttrs = 0;
+ break;
+ case 9 ... 15: // Reserved
+ break;
+ case 16 ... 31: // Cacheable Memory
+ te.mtype = TlbEntry::Normal;
+ te.shareable = s;
if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
te.nonCacheable = true;
+ te.innerAttrs = bits(texcb, 1, 0);
+ te.outerAttrs = bits(texcb, 3, 2);
break;
+ default:
+ panic("More than 32 states for 5 bits?\n");
}
} else {
PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
+ DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
+ uint8_t curr_tr, curr_ir, curr_or;
switch(bits(texcb, 2,0)) {
case 0:
- if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr0;
+ curr_ir = nmrr.ir0;
+ curr_or = nmrr.or0;
+ outer_shareable = (prrr.nos0 == 0);
break;
case 1:
- if (nmrr.ir1 == 0 || nmrr.or1 == 0 || prrr.tr1 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr1;
+ curr_ir = nmrr.ir1;
+ curr_or = nmrr.or1;
+ outer_shareable = (prrr.nos1 == 0);
break;
case 2:
- if (nmrr.ir2 == 0 || nmrr.or2 == 0 || prrr.tr2 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr2;
+ curr_ir = nmrr.ir2;
+ curr_or = nmrr.or2;
+ outer_shareable = (prrr.nos2 == 0);
break;
case 3:
- if (nmrr.ir3 == 0 || nmrr.or3 == 0 || prrr.tr3 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr3;
+ curr_ir = nmrr.ir3;
+ curr_or = nmrr.or3;
+ outer_shareable = (prrr.nos3 == 0);
break;
case 4:
- if (nmrr.ir4 == 0 || nmrr.or4 == 0 || prrr.tr4 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr4;
+ curr_ir = nmrr.ir4;
+ curr_or = nmrr.or4;
+ outer_shareable = (prrr.nos4 == 0);
break;
case 5:
- if (nmrr.ir5 == 0 || nmrr.or5 == 0 || prrr.tr5 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr5;
+ curr_ir = nmrr.ir5;
+ curr_or = nmrr.or5;
+ outer_shareable = (prrr.nos5 == 0);
break;
case 6:
panic("Imp defined type\n");
case 7:
- if (nmrr.ir7 == 0 || nmrr.or7 == 0 || prrr.tr7 != 0x2)
- te.nonCacheable = true;
+ curr_tr = prrr.tr7;
+ curr_ir = nmrr.ir7;
+ curr_or = nmrr.or7;
+ outer_shareable = (prrr.nos7 == 0);
break;
}
+
+ switch(curr_tr) {
+ case 0:
+ DPRINTF(TLBVerbose, "StronglyOrdered\n");
+ te.mtype = TlbEntry::StronglyOrdered;
+ te.nonCacheable = true;
+ te.innerAttrs = 1;
+ te.outerAttrs = 0;
+ te.shareable = true;
+ break;
+ case 1:
+ DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
+ prrr.ds1, prrr.ds0, s);
+ te.mtype = TlbEntry::Device;
+ te.nonCacheable = true;
+ te.innerAttrs = 3;
+ te.outerAttrs = 0;
+ if (prrr.ds1 && s)
+ te.shareable = true;
+ if (prrr.ds0 && !s)
+ te.shareable = true;
+ break;
+ case 2:
+ DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
+ prrr.ns1, prrr.ns0, s);
+ te.mtype = TlbEntry::Normal;
+ if (prrr.ns1 && s)
+ te.shareable = true;
+ if (prrr.ns0 && !s)
+ te.shareable = true;
+ //te.shareable = outer_shareable;
+ break;
+ case 3:
+ panic("Reserved type");
+ }
+
+ if (te.mtype == TlbEntry::Normal){
+ switch(curr_ir) {
+ case 0:
+ te.nonCacheable = true;
+ te.innerAttrs = 0;
+ break;
+ case 1:
+ te.innerAttrs = 5;
+ break;
+ case 2:
+ te.innerAttrs = 6;
+ break;
+ case 3:
+ te.innerAttrs = 7;
+ break;
+ }
+
+ switch(curr_or) {
+ case 0:
+ te.nonCacheable = true;
+ te.outerAttrs = 0;
+ break;
+ case 1:
+ te.outerAttrs = 1;
+ break;
+ case 2:
+ te.outerAttrs = 2;
+ break;
+ case 3:
+ te.outerAttrs = 3;
+ break;
+ }
+ }
}
+
+ /** Formatting for Physical Address Register (PAR)
+ * Only including lower bits (TLB info here)
+ * PAR:
+ * PA [31:12]
+ * Reserved [11]
+ * TLB info [10:1]
+ * NOS [10] (Not Outer Sharable)
+ * NS [9] (Non-Secure)
+ * -- [8] (Implementation Defined)
+ * SH [7] (Sharable)
+ * Inner[6:4](Inner memory attributes)
+ * Outer[3:2](Outer memory attributes)
+ * SS [1] (SuperSection)
+ * F [0] (Fault, Fault Status in [6:1] if faulted)
+ */
+ te.attributes = (
+ ((outer_shareable ? 0:1) << 10) |
+ // TODO: NS Bit
+ ((te.shareable ? 1:0) << 7) |
+ (te.innerAttrs << 4) |
+ (te.outerAttrs << 2)
+ // TODO: Supersection bit
+ // TODO: Fault bit
+ );
+
+
}
void
@@ -218,11 +384,19 @@ TableWalker::doL1Descriptor()
if (isFetch)
fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
else
- fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
+ fault = new DataAbort(vaddr, NULL, isWrite,
+ ArmFault::Translation0);
return;
case L1Descriptor::Section:
- if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
- panic("Haven't implemented AFE\n");
+ if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) {
+ /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
+ * enabled if set, do l1.Desc.setAp0() instead of generating
+ * AccessFlag0
+ */
+
+ fault = new DataAbort(vaddr, NULL, isWrite,
+ ArmFault::AccessFlag0);
+ }
if (l1Desc.supersection()) {
panic("Haven't implemented supersections\n");
@@ -238,7 +412,7 @@ TableWalker::doL1Descriptor()
te.ap = l1Desc.ap();
te.domain = l1Desc.domain();
te.asid = contextId;
- memAttrs(te, l1Desc.texcb());
+ memAttrs(te, l1Desc.texcb(), l1Desc.shareable());
DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n",
@@ -256,7 +430,8 @@ TableWalker::doL1Descriptor()
case L1Descriptor::PageTable:
Addr l2desc_addr;
l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2);
- DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", l2desc_addr);
+ DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
+ l2desc_addr);
// Trickbox address check
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
@@ -288,9 +463,6 @@ TableWalker::doL2Descriptor()
DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data);
TlbEntry te;
- if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
- panic("Haven't implemented AFE\n");
-
if (l2Desc.invalid()) {
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
tc = NULL;
@@ -298,10 +470,19 @@ TableWalker::doL2Descriptor()
if (isFetch)
fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
else
- fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
+ fault = new DataAbort(vaddr, l1Desc.domain(), isWrite,
+ ArmFault::Translation1);
return;
}
+ if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) {
+ /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
+ * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
+ */
+
+ fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1);
+ }
+
if (l2Desc.large()) {
te.N = 16;
te.pfn = l2Desc.pfn();
@@ -319,7 +500,7 @@ TableWalker::doL2Descriptor()
te.xn = l2Desc.xn();
te.ap = l2Desc.ap();
te.domain = l1Desc.domain();
- memAttrs(te, l2Desc.texcb());
+ memAttrs(te, l2Desc.texcb(), l2Desc.shareable());
tc = NULL;
req = NULL;
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index 8e851acd7..f6d3bee06 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -68,8 +68,13 @@ class TableWalker : public MemObject
Reserved
};
+ /** The raw bits of the entry */
uint32_t data;
+ /** This entry has been modified (access flag set) and needs to be
+ * written back to memory */
+ bool _dirty;
+
EntryType type() const
{
return (EntryType)(data & 0x3);
@@ -127,19 +132,48 @@ class TableWalker : public MemObject
return mbits(data, 31,10);
}
- /** Memory region attributes: ARM DDI 0406B: B3-32 */
+ /** Memory region attributes: ARM DDI 0406B: B3-32.
+ * These bits are largly ignored by M5 and only used to
+ * provide the illusion that the memory system cares about
+ * anything but cachable vs. uncachable.
+ */
uint8_t texcb() const
{
return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2;
}
+ /** If the section is shareable. See texcb() comment. */
+ bool shareable() const
+ {
+ return bits(data, 16);
+ }
+
+ /** Set access flag that this entry has been touched. Mark
+ * the entry as requiring a writeback, in the future.
+ */
+ void setAp0()
+ {
+ data |= 1 << 10;
+ _dirty = true;
+ }
+
+ /** This entry needs to be written back to memory */
+ bool dirty() const
+ {
+ return _dirty;
+ }
};
/** Level 2 page table descriptor */
struct L2Descriptor {
+ /** The raw bits of the entry. */
uint32_t data;
+ /** This entry has been modified (access flag set) and needs to be
+ * written back to memory */
+ bool _dirty;
+
/** Is the entry invalid */
bool invalid() const
{
@@ -184,6 +218,27 @@ class TableWalker : public MemObject
return large() ? bits(data, 31, 16) : bits(data, 31, 12);
}
+ /** If the section is shareable. See texcb() comment. */
+ bool shareable() const
+ {
+ return bits(data, 10);
+ }
+
+ /** Set access flag that this entry has been touched. Mark
+ * the entry as requiring a writeback, in the future.
+ */
+ void setAp0()
+ {
+ data |= 1 << 4;
+ _dirty = true;
+ }
+
+ /** This entry needs to be written back to memory */
+ bool dirty() const
+ {
+ return _dirty;
+ }
+
};
/** Port to issue translation requests from */
@@ -252,9 +307,9 @@ class TableWalker : public MemObject
TLB::Translation *_trans, bool timing);
void setTlb(TLB *_tlb) { tlb = _tlb; }
+ void memAttrs(TlbEntry &te, uint8_t texcb, bool s);
private:
- void memAttrs(TlbEntry &te, uint8_t texcb);
void doL1Descriptor();
EventWrapper<TableWalker, &TableWalker::doL1Descriptor> doL1DescEvent;
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 05d65457c..7f02061b0 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -384,6 +384,16 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2)
req->setFlags(Request::UNCACHEABLE);
}
+
+ // Set memory attributes
+ TlbEntry temp_te;
+ tableWalker->memAttrs(temp_te, 0, 1);
+ temp_te.shareable = true;
+ DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable:\
+ %d, innerAttrs: %d, outerAttrs: %d\n", temp_te.shareable,
+ temp_te.innerAttrs, temp_te.outerAttrs);
+ setAttr(temp_te.attributes);
+
return trickBoxCheck(req, mode, 0, false);
}
@@ -409,6 +419,13 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
assert(te);
}
+ // Set memory attributes
+ DPRINTF(TLBVerbose,
+ "Setting memory attributes: shareable: %d, innerAttrs: %d, \
+ outerAttrs: %d\n",
+ te->shareable, te->innerAttrs, te->outerAttrs);
+ setAttr(te->attributes);
+
uint32_t dacr = tc->readMiscReg(MISCREG_DACR);
switch ( (dacr >> (te->domain * 2)) & 0x3) {
case 0:
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index c2894e5cd..a779a492d 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -88,6 +88,8 @@ class TLB : public BaseTLB
int size; // TLB Size
int nlu; // not last used entry (for replacement)
+ uint32_t _attr; // Memory attributes for last accessed TLB entry
+
#if FULL_SYSTEM
TableWalker *tableWalker;
#endif
@@ -151,6 +153,19 @@ class TLB : public BaseTLB
static bool validVirtualAddress(Addr vaddr);
+ /** Accessor functions for memory attributes for last accessed TLB entry
+ */
+ void
+ setAttr(uint32_t attr)
+ {
+ _attr = attr;
+ }
+ uint32_t
+ getAttr() const
+ {
+ return _attr;
+ }
+
#if FULL_SYSTEM
Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing);