ARM: Added support for Access Flag and some CP15 regs (V2PCWPR, V2PCWPW, V2PCWUR, V2PCWUW,...)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 16:
|
||||
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 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user