summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2010-06-02 12:58:16 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2010-06-02 12:58:16 -0500
commitc1e1de8d69624b1cf18a13a46e624ad5827954b7 (patch)
tree60f11a14eafcc03715c283270edb336e0a44bccc
parent7de7ea3b22e16a6d489a71dc5c54ddba5a5b5a0e (diff)
downloadgem5-c1e1de8d69624b1cf18a13a46e624ad5827954b7.tar.xz
ARM: Some TLB bug fixes.
-rw-r--r--src/arch/arm/isa.cc1
-rw-r--r--src/arch/arm/isa.hh2
-rw-r--r--src/arch/arm/miscregs.cc4
-rw-r--r--src/arch/arm/miscregs.hh18
-rw-r--r--src/arch/arm/table_walker.cc27
-rw-r--r--src/arch/arm/table_walker.hh8
-rw-r--r--src/arch/arm/tlb.cc55
-rw-r--r--src/arch/arm/tlb.hh7
8 files changed, 82 insertions, 40 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 3fcd25fe5..8446962a2 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -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;
diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh
index ec6479f50..5952dc11f 100644
--- a/src/arch/arm/isa.hh
+++ b/src/arch/arm/isa.hh
@@ -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;
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index a6311e179..776ed94c3 100644
--- a/src/arch/arm/miscregs.cc
+++ b/src/arch/arm/miscregs.cc
@@ -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:
diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh
index 42431e777..ddb4ea934 100644
--- a/src/arch/arm/miscregs.hh
+++ b/src/arch/arm/miscregs.hh
@@ -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
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 313b23316..e3ecb7ddd 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -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;
}
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index d18b7c489..8e851acd7 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -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 */
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 362020a91..05d65457c 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -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,
@@ -340,6 +332,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;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 7193ac0e8..c2894e5cd 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -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();