diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2010-06-02 12:58:16 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2010-06-02 12:58:16 -0500 |
commit | c1e1de8d69624b1cf18a13a46e624ad5827954b7 (patch) | |
tree | 60f11a14eafcc03715c283270edb336e0a44bccc | |
parent | 7de7ea3b22e16a6d489a71dc5c54ddba5a5b5a0e (diff) | |
download | gem5-c1e1de8d69624b1cf18a13a46e624ad5827954b7.tar.xz |
ARM: Some TLB bug fixes.
-rw-r--r-- | src/arch/arm/isa.cc | 1 | ||||
-rw-r--r-- | src/arch/arm/isa.hh | 2 | ||||
-rw-r--r-- | src/arch/arm/miscregs.cc | 4 | ||||
-rw-r--r-- | src/arch/arm/miscregs.hh | 18 | ||||
-rw-r--r-- | src/arch/arm/table_walker.cc | 27 | ||||
-rw-r--r-- | src/arch/arm/table_walker.hh | 8 | ||||
-rw-r--r-- | src/arch/arm/tlb.cc | 55 | ||||
-rw-r--r-- | src/arch/arm/tlb.hh | 7 |
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(); |