ARM: Some TLB bug fixes.
This commit is contained in:
parent
7de7ea3b22
commit
c1e1de8d69
8 changed files with 82 additions and 40 deletions
|
@ -215,6 +215,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
|||
break;
|
||||
case MISCREG_SCTLR:
|
||||
{
|
||||
DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal);
|
||||
SCTLR sctlr = miscRegs[MISCREG_SCTLR];
|
||||
SCTLR new_sctlr = newVal;
|
||||
new_sctlr.nmfi = (bool)sctlr.nmfi;
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace ArmISA
|
|||
sctlr.nmfi = (bool)sctlr_rst.nmfi;
|
||||
sctlr.v = (bool)sctlr_rst.v;
|
||||
sctlr.u = 1;
|
||||
sctlr.rao1 = 1;
|
||||
sctlr.xp = 1;
|
||||
sctlr.rao2 = 1;
|
||||
sctlr.rao3 = 1;
|
||||
sctlr.rao4 = 1;
|
||||
|
|
|
@ -153,7 +153,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
|
|||
}
|
||||
break;
|
||||
case 2:
|
||||
if (opc2 == 0 && crm == 0) {
|
||||
if (opc1 == 0 && crm == 0) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_TTBR0;
|
||||
|
@ -408,7 +408,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
|
|||
case 13:
|
||||
if (opc1 == 0) {
|
||||
if (crm == 0) {
|
||||
switch (crm) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_FCEIDR;
|
||||
case 1:
|
||||
|
|
|
@ -134,9 +134,11 @@ namespace ArmISA
|
|||
MISCREG_NMRR,
|
||||
MISCREG_TTBCR,
|
||||
MISCREG_ID_PFR0,
|
||||
MISCREG_CTR,
|
||||
MISCREG_SCR,
|
||||
MISCREG_SDER,
|
||||
MISCREG_CP15_UNIMP_START,
|
||||
MISCREG_CTR = MISCREG_CP15_UNIMP_START,
|
||||
MISCREG_TCMTR,
|
||||
MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
|
||||
MISCREG_ID_PFR1,
|
||||
MISCREG_ID_DFR0,
|
||||
MISCREG_ID_AFR0,
|
||||
|
@ -159,8 +161,6 @@ namespace ArmISA
|
|||
MISCREG_DCISW,
|
||||
MISCREG_MCCSW,
|
||||
MISCREG_DCCMVAU,
|
||||
MISCREG_SCR,
|
||||
MISCREG_SDER,
|
||||
MISCREG_NSACR,
|
||||
MISCREG_V2PCWPR,
|
||||
MISCREG_V2PCWPW,
|
||||
|
@ -205,9 +205,10 @@ namespace ArmISA
|
|||
"dtlbiall", "dtlbimva", "dtlbiasid",
|
||||
"tlbiall", "tlbimva", "tlbiasid", "tlbimvaa",
|
||||
"dfsr", "ifsr", "dfar", "ifar", "mpidr",
|
||||
"prrr", "nmrr", "ttbcr", "id_pfr0",
|
||||
"prrr", "nmrr", "ttbcr", "id_pfr0", "ctr"
|
||||
"scr", "sder"
|
||||
// Unimplemented below
|
||||
"ctr", "tcmtr",
|
||||
"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",
|
||||
|
@ -215,7 +216,7 @@ namespace ArmISA
|
|||
"adfsr", "aifsr",
|
||||
"dcimvac", "dcisw", "mccsw",
|
||||
"dccmvau",
|
||||
"scr", "sder", "nsacr",
|
||||
"nsacr",
|
||||
"v2pcwpr", "v2pcwpw", "v2pcwur", "v2pcwuw",
|
||||
"v2powpr", "v2powpw", "v2powur", "v2powuw",
|
||||
"vbar", "mvbar", "isr", "fceidr",
|
||||
|
@ -252,7 +253,7 @@ namespace ArmISA
|
|||
Bitfield<27> nmfi;// Non-maskable fast interrupts enable
|
||||
Bitfield<25> ee; // Exception Endianness bit
|
||||
Bitfield<24> ve; // Interrupt vectors enable
|
||||
Bitfield<23> rao1;// Read as one
|
||||
Bitfield<23> xp; // Extended page table enable bit
|
||||
Bitfield<22> u; // Alignment (now unused)
|
||||
Bitfield<21> fi; // Fast interrupts configuration enable
|
||||
Bitfield<19> dz; // Divide by Zero fault enable bit
|
||||
|
@ -264,6 +265,7 @@ namespace ArmISA
|
|||
Bitfield<12> i; // instruction cache enable
|
||||
Bitfield<11> z; // branch prediction enable bit
|
||||
Bitfield<10> sw; // Enable swp/swpb
|
||||
Bitfield<9,8> rs; // deprecated protection bits
|
||||
Bitfield<6,3> rao4;// Read as one
|
||||
Bitfield<7> b; // Endianness support (unused)
|
||||
Bitfield<2> c; // Cache enable bit
|
||||
|
|
|
@ -111,21 +111,25 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode m
|
|||
// If translation isn't enabled, we shouldn't be here
|
||||
assert(sctlr.m);
|
||||
|
||||
if (N == 0 || mbits(vaddr, 31, 32-N)) {
|
||||
DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
|
||||
vaddr, N, mbits(vaddr, 31, 32-N));
|
||||
|
||||
if (N == 0 || !mbits(vaddr, 31, 32-N)) {
|
||||
DPRINTF(TLB, " - Selecting TTBR0\n");
|
||||
ttbr = tc->readMiscReg(MISCREG_TTBR0);
|
||||
} else {
|
||||
ttbr = tc->readMiscReg(MISCREG_TTBR0);
|
||||
DPRINTF(TLB, " - Selecting TTBR1\n");
|
||||
ttbr = tc->readMiscReg(MISCREG_TTBR1);
|
||||
N = 0;
|
||||
}
|
||||
|
||||
Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2);
|
||||
DPRINTF(TLB, "Begining table walk for address %#x at descriptor %#x\n",
|
||||
vaddr, l1desc_addr);
|
||||
DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
|
||||
|
||||
|
||||
// Trickbox address check
|
||||
fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t),
|
||||
isFetch, 0, true);
|
||||
isFetch, isWrite, 0, true);
|
||||
if (fault) {
|
||||
tc = NULL;
|
||||
req = NULL;
|
||||
|
@ -210,7 +214,11 @@ TableWalker::doL1Descriptor()
|
|||
case L1Descriptor::Reserved:
|
||||
tc = NULL;
|
||||
req = NULL;
|
||||
fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
|
||||
DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
|
||||
if (isFetch)
|
||||
fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
|
||||
else
|
||||
fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
|
||||
return;
|
||||
case L1Descriptor::Section:
|
||||
if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
|
||||
|
@ -252,7 +260,7 @@ TableWalker::doL1Descriptor()
|
|||
|
||||
// Trickbox address check
|
||||
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
|
||||
isFetch, l1Desc.domain(), false);
|
||||
isFetch, isWrite, l1Desc.domain(), false);
|
||||
if (fault) {
|
||||
tc = NULL;
|
||||
req = NULL;
|
||||
|
@ -287,7 +295,10 @@ TableWalker::doL2Descriptor()
|
|||
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
|
||||
tc = NULL;
|
||||
req = NULL;
|
||||
fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
|
||||
if (isFetch)
|
||||
fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
|
||||
else
|
||||
fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ class TableWalker : public MemObject
|
|||
/** Is the translation global (no asid used)? */
|
||||
bool global() const
|
||||
{
|
||||
return bits(data, 17);
|
||||
return bits(data, 4);
|
||||
}
|
||||
|
||||
/** Is the translation not allow execution? */
|
||||
|
@ -130,7 +130,7 @@ class TableWalker : public MemObject
|
|||
/** Memory region attributes: ARM DDI 0406B: B3-32 */
|
||||
uint8_t texcb() const
|
||||
{
|
||||
return bits(data, 2) | bits(data,3) << 1 | bits(data, 12, 14) << 2;
|
||||
return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -174,8 +174,8 @@ class TableWalker : public MemObject
|
|||
uint8_t texcb() const
|
||||
{
|
||||
return large() ?
|
||||
(bits(data, 2) | (bits(data,3) << 1) | (bits(data, 12, 14) << 2)) :
|
||||
(bits(data, 2) | (bits(data,3) << 1) | (bits(data, 6, 8) << 2));
|
||||
(bits(data, 2) | (bits(data,3) << 1) | (bits(data, 14, 12) << 2)) :
|
||||
(bits(data, 2) | (bits(data,3) << 1) | (bits(data, 8, 6) << 2));
|
||||
}
|
||||
|
||||
/** Return the physical frame, bits shifted right */
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/pagetable.hh"
|
||||
#include "arch/arm/table_walker.hh"
|
||||
#include "arch/arm/tlb.hh"
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "base/inifile.hh"
|
||||
|
@ -58,6 +57,10 @@
|
|||
#include "params/ArmTLB.hh"
|
||||
#include "sim/process.hh"
|
||||
|
||||
#if FULL_SYSTEM
|
||||
#include "arch/arm/table_walker.hh"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace ArmISA;
|
||||
|
||||
|
@ -70,7 +73,9 @@ TLB::TLB(const Params *p)
|
|||
table = new TlbEntry[size];
|
||||
memset(table, 0, sizeof(TlbEntry[size]));
|
||||
|
||||
#if FULL_SYSTEM
|
||||
tableWalker->setTlb(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
TLB::~TLB()
|
||||
|
@ -292,19 +297,6 @@ TLB::regStats()
|
|||
accesses = read_accesses + write_accesses;
|
||||
}
|
||||
|
||||
Fault
|
||||
TLB::trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp)
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
|
||||
uint8_t domain, bool sNp)
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
Fault
|
||||
TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||
|
@ -339,6 +331,19 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
|
|||
|
||||
#else // FULL_SYSTEM
|
||||
|
||||
Fault
|
||||
TLB::trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp)
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
|
||||
bool is_write, uint8_t domain, bool sNp)
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||
Translation *translation, bool &delay, bool timing)
|
||||
|
@ -435,9 +440,29 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
|||
|
||||
bool abt;
|
||||
|
||||
/* if (!sctlr.xp)
|
||||
ap &= 0x3;
|
||||
*/
|
||||
switch (ap) {
|
||||
case 0:
|
||||
abt = true;
|
||||
DPRINTF(TLB, "Access permissions 0, checking rs:%#x\n", (int)sctlr.rs);
|
||||
if (!sctlr.xp) {
|
||||
switch ((int)sctlr.rs) {
|
||||
case 2:
|
||||
abt = is_write;
|
||||
break;
|
||||
case 1:
|
||||
abt = is_write || !is_priv;
|
||||
break;
|
||||
case 0:
|
||||
case 3:
|
||||
default:
|
||||
abt = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
abt = true;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
abt = !is_priv;
|
||||
|
|
|
@ -87,7 +87,10 @@ class TLB : public BaseTLB
|
|||
TlbEntry *table; // the Page Table
|
||||
int size; // TLB Size
|
||||
int nlu; // not last used entry (for replacement)
|
||||
|
||||
#if FULL_SYSTEM
|
||||
TableWalker *tableWalker;
|
||||
#endif
|
||||
|
||||
void nextnlu() { if (++nlu >= size) nlu = 0; }
|
||||
TlbEntry *lookup(Addr vpn, uint8_t asn);
|
||||
|
@ -136,8 +139,8 @@ class TLB : public BaseTLB
|
|||
void flushMva(Addr mva);
|
||||
|
||||
Fault trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp);
|
||||
Fault walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec, uint8_t
|
||||
domain, bool sNp);
|
||||
Fault walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
|
||||
bool is_write, uint8_t domain, bool sNp);
|
||||
|
||||
void printTlb();
|
||||
|
||||
|
|
Loading…
Reference in a new issue