ARM: Some TLB bug fixes.
authorAli Saidi <Ali.Saidi@ARM.com>
Wed, 2 Jun 2010 17:58:16 +0000 (12:58 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Wed, 2 Jun 2010 17:58:16 +0000 (12:58 -0500)
src/arch/arm/isa.cc
src/arch/arm/isa.hh
src/arch/arm/miscregs.cc
src/arch/arm/miscregs.hh
src/arch/arm/table_walker.cc
src/arch/arm/table_walker.hh
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh

index 3fcd25fe5b2341ff1de9f777d1790b1333a5c3bd..8446962a26f4129977db1832b4f862a7e1e3e0ff 100644 (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;
index ec6479f5008753e5654c2d8f42e5699c8b0282f0..5952dc11f5a69170a2cbb515ad24c34d3eb4ac30 100644 (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;
index a6311e179872246bcdb60747f7c9af7aababf789..776ed94c363dffa7b78a0dbc0ba87c22c8e41fc9 100644 (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:
index 42431e777be37a442b60dda9feaed0d1dada4c53..ddb4ea9343004f1e6cde0a4419bef10002079700 100644 (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
index 313b233165f72e0c085e71f182f2a87f31f3a597..e3ecb7ddd6d95ea0a25f506fa848b0928c5a949c 100644 (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;
     }
 
index d18b7c4899a516cbaab4d3e89c0525dbaf69bd41..8e851acd7976008553296ff92b1bb0f1daa8b915 100644 (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 */
index 362020a9195496059eee377cf5f9397e03bff400..05d65457ce47e8d5ee2ded2aa46972838987c59b 100644 (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"
 #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;
index 7193ac0e83cf77ddecbc73ebb5d34be09490f801..c2894e5cdfdc363a29bf6ee59a1300f5bf112855 100644 (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();