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