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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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