ARM: Some TLB bug fixes.

This commit is contained in:
Ali Saidi 2010-06-02 12:58:16 -05:00
parent 7de7ea3b22
commit c1e1de8d69
8 changed files with 82 additions and 40 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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:

View file

@ -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

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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;

View file

@ -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();