first cut at a sparc tlb
authorAli Saidi <saidi@eecs.umich.edu>
Thu, 23 Nov 2006 06:42:57 +0000 (01:42 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Thu, 23 Nov 2006 06:42:57 +0000 (01:42 -0500)
src/arch/sparc/SConscript:
    Add code to serialize/unserialze tlb entries
src/arch/sparc/asi.cc:
src/arch/sparc/asi.hh:
    update asi names for how they're listed in the supplement
    add asis
    add more asi functions
src/arch/sparc/isa_traits.hh:
    move the interrupt stuff and some basic address space stuff into isa traits
src/arch/sparc/miscregfile.cc:
src/arch/sparc/miscregfile.hh:
    add mmu registers to tlb
    get rid of implicit asi stuff... the tlb will handle it
src/arch/sparc/regfile.hh:
    make isnt/dataAsid return ints not asis
src/arch/sparc/tlb.cc:
src/arch/sparc/tlb.hh:
    first cut at sparc tlb
src/arch/sparc/vtophys.hh:
    pagatable nedes to be included here
src/mem/request.hh:
    add asi and if the request is a memory mapped register to the requset object
src/sim/host.hh:
    fix incorrect definition of LL

--HG--
extra : convert_revision : 6c85cd1681c62c8cd8eab04f70b1f15a034b0aa3

17 files changed:
src/arch/sparc/SConscript
src/arch/sparc/asi.cc
src/arch/sparc/asi.hh
src/arch/sparc/isa_traits.hh
src/arch/sparc/miscregfile.cc
src/arch/sparc/miscregfile.hh
src/arch/sparc/pagetable.cc [new file with mode: 0644]
src/arch/sparc/pagetable.hh [new file with mode: 0644]
src/arch/sparc/regfile.hh
src/arch/sparc/tlb.cc
src/arch/sparc/tlb.hh
src/arch/sparc/tlb_map.hh [new file with mode: 0644]
src/arch/sparc/vtophys.hh
src/base/range_map.hh [new file with mode: 0644]
src/mem/request.hh
src/sim/host.hh
src/unittest/rangemaptest.cc [new file with mode: 0644]

index 281c166c09b33513d3eee285d4aab87aafe86d9d..a0a6112de02016a4fd732f287e4fb6998e0dd721 100644 (file)
@@ -56,6 +56,7 @@ base_sources = Split('''
 full_system_sources = Split('''
        arguments.cc
        remote_gdb.cc
+        pagetable.cc
        stacktrace.cc
        system.cc
        tlb.cc
index 00c9e041e35a38aacca040b0c23718e02b9eb5f7..14e581e433d3e6905ecec0198c3be7d96040ea1a 100644 (file)
@@ -26,6 +26,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Ali Saidi
  */
 
 #include "arch/sparc/asi.hh"
@@ -37,8 +38,8 @@ namespace SparcISA
         return
             (asi == ASI_BLK_AIUP) ||
             (asi == ASI_BLK_AIUS) ||
-            (asi == ASI_BLK_AIUPL) ||
-            (asi == ASI_BLK_AIUSL) ||
+            (asi == ASI_BLK_AIUP_L) ||
+            (asi == ASI_BLK_AIUS_L) ||
             (asi == ASI_BLK_P) ||
             (asi == ASI_BLK_S) ||
             (asi == ASI_BLK_PL) ||
@@ -50,10 +51,10 @@ namespace SparcISA
         return
             (asi == ASI_AIUP) ||
             (asi == ASI_BLK_AIUP) ||
-            (asi == ASI_AIUPL) ||
-            (asi == ASI_BLK_AIUPL) ||
+            (asi == ASI_AIUP_L) ||
+            (asi == ASI_BLK_AIUP_L) ||
             (asi == ASI_LDTX_AIUP) ||
-            (asi == ASI_LDTX_AIUPL) ||
+            (asi == ASI_LDTX_AIUP_L) ||
             (asi == ASI_P) ||
             (asi == ASI_PNF) ||
             (asi == ASI_PL) ||
@@ -79,10 +80,10 @@ namespace SparcISA
         return
             (asi == ASI_AIUS) ||
             (asi == ASI_BLK_AIUS) ||
-            (asi == ASI_AIUSL) ||
-            (asi == ASI_BLK_AIUSL) ||
+            (asi == ASI_AIUS_L) ||
+            (asi == ASI_BLK_AIUS_L) ||
             (asi == ASI_LDTX_AIUS) ||
-            (asi == ASI_LDTX_AIUSL) ||
+            (asi == ASI_LDTX_AIUS_L) ||
             (asi == ASI_S) ||
             (asi == ASI_SNF) ||
             (asi == ASI_SL) ||
@@ -119,14 +120,14 @@ namespace SparcISA
             (asi == ASI_AIUS) ||
             (asi == ASI_BLK_AIUP) ||
             (asi == ASI_BLK_AIUS) ||
-            (asi == ASI_AIUPL) ||
-            (asi == ASI_AIUSL) ||
-            (asi == ASI_BLK_AIUPL) ||
-            (asi == ASI_BLK_AIUSL) ||
+            (asi == ASI_AIUP_L) ||
+            (asi == ASI_AIUS_L) ||
+            (asi == ASI_BLK_AIUP_L) ||
+            (asi == ASI_BLK_AIUS_L) ||
             (asi == ASI_LDTX_AIUP) ||
             (asi == ASI_LDTX_AIUS) ||
-            (asi == ASI_LDTX_AIUPL) ||
-            (asi == ASI_LDTX_AIUSL);
+            (asi == ASI_LDTX_AIUP_L) ||
+            (asi == ASI_LDTX_AIUS_L);
     }
 
     bool AsiIsIO(ASI asi)
@@ -144,22 +145,21 @@ namespace SparcISA
             (asi == ASI_REAL_L) ||
             (asi == ASI_REAL_IO_L) ||
             (asi == ASI_LDTX_REAL) ||
-            (asi == ASI_LDTX_REAL_L) ||
-            (asi == ASI_MMU_REAL);
+            (asi == ASI_LDTX_REAL_L);
     }
 
     bool AsiIsLittle(ASI asi)
     {
         return
             (asi == ASI_NL) ||
-            (asi == ASI_AIUPL) ||
-            (asi == ASI_AIUSL) ||
+            (asi == ASI_AIUP_L) ||
+            (asi == ASI_AIUS_L) ||
             (asi == ASI_REAL_L) ||
             (asi == ASI_REAL_IO_L) ||
-            (asi == ASI_BLK_AIUPL) ||
-            (asi == ASI_BLK_AIUSL) ||
-            (asi == ASI_LDTX_AIUPL) ||
-            (asi == ASI_LDTX_AIUSL) ||
+            (asi == ASI_BLK_AIUP_L) ||
+            (asi == ASI_BLK_AIUS_L) ||
+            (asi == ASI_LDTX_AIUP_L) ||
+            (asi == ASI_LDTX_AIUS_L) ||
             (asi == ASI_LDTX_REAL_L) ||
             (asi == ASI_LDTX_NL) ||
             (asi == ASI_PL) ||
@@ -189,8 +189,8 @@ namespace SparcISA
             (asi == ASI_LDTX_AIUS) ||
             (asi == ASI_LDTX_REAL) ||
             (asi == ASI_LDTX_N) ||
-            (asi == ASI_LDTX_AIUPL) ||
-            (asi == ASI_LDTX_AIUSL) ||
+            (asi == ASI_LDTX_AIUP_L) ||
+            (asi == ASI_LDTX_AIUS_L) ||
             (asi == ASI_LDTX_REAL_L) ||
             (asi == ASI_LDTX_NL) ||
             (asi == ASI_LDTX_P) ||
@@ -248,8 +248,7 @@ namespace SparcISA
     bool AsiIsCmt(ASI asi)
     {
         return
-            (asi == ASI_CMT_PER_STRAND) ||
-            (asi == ASI_CMT_SHARED);
+            (asi == ASI_CMT_PER_STRAND);
     }
 
     bool AsiIsQueue(ASI asi)
@@ -257,23 +256,38 @@ namespace SparcISA
         return asi == ASI_QUEUE;
     }
 
-    bool AsiIsDtlb(ASI asi)
+    bool AsiIsMmu(ASI asi)
     {
-        return
-            (asi == ASI_DTLB_DATA_IN_REG) ||
-            (asi == ASI_DTLB_DATA_ACCESS_REG) ||
-            (asi == ASI_DTLB_TAG_READ_REG);
+        return  asi == ASI_MMU ||
+               (asi >= ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0 &&
+                asi <= ASI_IMMU_CTXT_ZERO_CONFIG) ||
+               (asi >= ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0 &&
+                asi <= ASI_IMMU_CTXT_NONZERO_CONFIG) ||
+               (asi >= ASI_IMMU &&
+                asi <= ASI_IMMU_TSB_PS1_PTR_REG) ||
+               (asi >= ASI_ITLB_DATA_IN_REG  &&
+                asi <= ASI_TLB_INVALIDATE_ALL);
     }
 
-    bool AsiIsMmu(ASI asi)
+    bool AsiIsUnPriv(ASI asi)
     {
-        return
-            (asi == ASI_MMU_CONTEXTID) ||
-            (asi == ASI_IMMU) ||
-            (asi == ASI_MMU_REAL) ||
-            (asi == ASI_MMU) ||
-            (asi == ASI_DMMU) ||
-            (asi == ASI_UMMU) ||
-            (asi == ASI_DMMU_DEMAP);
+        return asi >= 0x80;
+    }
+
+    bool AsiIsPriv(ASI asi)
+    {
+        return asi <= 0x2f;
     }
+
+
+    bool AsiIsHPriv(ASI asi)
+    {
+        return asi >= 0x30 && asi <= 0x7f;
+    }
+
+    bool AsiIsReg(ASI asi)
+    {
+        return AsiIsMmu(asi) || AsiIsScratchPad(asi);
+    }
+
 }
index 6677b23dffde675f67a03c171fe2f0332da8c0fd..bd1696c78fd0356bf05319c2d38622e6b49dcd68 100644 (file)
@@ -26,6 +26,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Ali Saidi
  */
 
 #ifndef __ARCH_SPARC_ASI_HH__
@@ -53,64 +54,110 @@ namespace SparcISA
         ASI_BLOCK_AS_IF_USER_PRIMARY = ASI_BLK_AIUP,
         ASI_BLK_AIUS = 0x17,
         ASI_BLOCK_AS_IF_USER_SECONDARY = ASI_BLK_AIUS,
-        ASI_AIUPL = 0x18,
-        ASI_AS_IF_USER_PRIMARY_LITTLE = ASI_AIUPL,
-        ASI_AIUSL = 0x19,
-        ASI_AS_IF_USER_SECONDARY_LITTLE = ASI_AIUSL,
+        ASI_AIUP_L = 0x18,
+        ASI_AS_IF_USER_PRIMARY_LITTLE = ASI_AIUP_L,
+        ASI_AIUS_L = 0x19,
+        ASI_AS_IF_USER_SECONDARY_LITTLE = ASI_AIUS_L,
         //0x1A-0x1B implementation dependent
         ASI_REAL_L = 0x1C,
         ASI_REAL_LITTLE = ASI_REAL_L,
         ASI_REAL_IO_L = 0x1D,
         ASI_REAL_IO_LITTLE = ASI_REAL_IO_L,
-        ASI_BLK_AIUPL = 0x1E,
-        ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE = ASI_BLK_AIUPL,
-        ASI_BLK_AIUSL = 0x1F,
-        ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE = ASI_BLK_AIUSL,
+        ASI_BLK_AIUP_L = 0x1E,
+        ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE = ASI_BLK_AIUP_L,
+        ASI_BLK_AIUS_L = 0x1F,
+        ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE = ASI_BLK_AIUS_L,
         ASI_SCRATCHPAD = 0x20,
-        ASI_MMU_CONTEXTID = 0x21,
+        ASI_MMU = 0x21,
         ASI_LDTX_AIUP = 0x22,
         ASI_LD_TWINX_AS_IF_USER_PRIMARY = ASI_LDTX_AIUP,
         ASI_LDTX_AIUS = 0x23,
         ASI_LD_TWINX_AS_IF_USER_SECONDARY = ASI_LDTX_AIUS,
-        //0x24 implementation dependent
+        ASI_QUAD_LDD = 0x24,
         ASI_QUEUE = 0x25,
-        ASI_LDTX_REAL = 0x26,
-        ASI_LD_TWINX_REAL = ASI_LDTX_REAL,
+        ASI_QUAD_LDD_REAL = 0x26,
+        ASI_LDTX_REAL = ASI_QUAD_LDD_REAL,
         ASI_LDTX_N = 0x27,
         ASI_LD_TWINX_NUCLEUS = ASI_LDTX_N,
+        ASI_ST_BLKINIT_NUCLEUS = ASI_LDTX_N,
+        ASI_STBI_N = ASI_LDTX_N,
         //0x28-0x29 implementation dependent
-        ASI_LDTX_AIUPL = 0x2A,
-        ASI_LD_TWINX_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUPL,
-        ASI_LDTX_AIUSL = 0x2B,
-        ASI_LD_TWINX_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUSL,
-        //0x2C-0x2D implementation dependent
+        ASI_LDTX_AIUP_L = 0x2A,
+        ASI_TWINX_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUP_L,
+        ASI_ST_BLKINIT_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUP_L,
+        ASI_STBI_AIUP_L = ASI_LDTX_AIUP_L,
+        ASI_LDTX_AIUS_L = 0x2B,
+        ASI_LD_TWINX_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUS_L,
+        ASI_ST_BLKINIT_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUS_L,
+        ASI_STBI_AIUS_L = ASI_LDTX_AIUS_L,
+        ASI_LTX_L = 0x2C,
+        ASI_TWINX_LITTLE = ASI_LTX_L,
+        //0x2D implementation dependent
         ASI_LDTX_REAL_L = 0x2E,
         ASI_LD_TWINX_REAL_LITTLE = ASI_LDTX_REAL_L,
         ASI_LDTX_NL = 0x2F,
         ASI_LD_TWINX_NUCLEUS_LITTLE = ASI_LDTX_NL,
-        //0x30-0x40 implementation dependent
-        ASI_CMT_SHARED = 0x41,
-        //0x42-0x4F implementation dependent
+        //0x20 implementation dependent
+        ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0 = 0x31,
+        ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1 = 0x32,
+        ASI_DMMU_CTXT_ZERO_CONFIG = 0x33,
+        //0x34 implementation dependent
+        ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0 = 0x35,
+        ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1 = 0x36,
+        ASI_IMMU_CTXT_ZERO_CONFIG = 0x37,
+        //0x38 implementation dependent
+        ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0 = 0x39,
+        ASI_DMMU_CTXT_NONZERO_USB_BASE_PS1 = 0x3A,
+        ASI_DMMU_CTXT_NONZERO_CONFIG = 0x3B,
+        //0x3C implementation dependent
+        ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0 = 0x3D,
+        ASI_IMMU_CTXT_NONZERO_USB_BASE_PS1 = 0x3E,
+        ASI_IMMU_CTXT_NONZERO_CONFIG = 0x3F,
+        ASI_STREAM_MA = 0x40,
+        //0x41 implementation dependent
+        ASI_SPARC_BIST_CONTROL = 0x42,
+        ASI_INST_MASK_REG = 0x42,
+        ASI_LSU_DIAG_REG = 0x42,
+        //0x43 implementation dependent
+        ASI_STM_CTL_REG = 0x44,
+        ASI_LSU_CONTROL_REG = 0x45,
+        ASI_DCACHE_DATA = 0x46,
+        ASI_DCACHE_TAG = 0x47,
+        ASI_INTR_DISPATCH_STATUS = 0x48,
+        ASI_INTR_RECEIVE = 0x49,
+        ASI_UPA_CONFIG_REGISTER = 0x4A,
+        ASI_SPARC_ERROR_EN_REG = 0x4B,
+        ASI_SPARC_ERROR_STATUS_REG = 0x4C,
+        ASI_SPARC_ERROR_ADDRESS_REG = 0x4D,
+        ASI_ECACHE_TAG_DATA = 0x4E,
         ASI_HYP_SCRATCHPAD = 0x4F,
         ASI_IMMU = 0x50,
-        ASI_MMU_REAL = 0x52,
+        ASI_IMMU_TSB_PS0_PTR_REG = 0x51,
+        ASI_IMMU_TSB_PS1_PTR_REG = 0x52,
         //0x53 implementation dependent
-        ASI_MMU = 0x54,
+        ASI_ITLB_DATA_IN_REG = 0x54,
         ASI_ITLB_DATA_ACCESS_REG = 0x55,
         ASI_ITLB_TAG_READ_REG = 0x56,
         ASI_IMMU_DEMAP = 0x57,
         ASI_DMMU = 0x58,
-        ASI_UMMU = 0x58,
-        //0x59-0x5B reserved
+        ASI_DMMU_TSB_PS0_PTR_REG = 0x59,
+        ASI_DMMU_TSB_PS1_PTR_REG = 0x5A,
+        ASI_DMMU_TSB_DIRECT_PTR_REG = 0x5B,
         ASI_DTLB_DATA_IN_REG = 0x5C,
         ASI_DTLB_DATA_ACCESS_REG = 0x5D,
         ASI_DTLB_TAG_READ_REG = 0x5E,
         ASI_DMMU_DEMAP = 0x5F,
-        //0x60-62 implementation dependent
+        ASI_TLB_INVALIDATE_ALL = 0x60,
+        //0x61-0x62 implementation dependent
         ASI_CMT_PER_STRAND = 0x63,
-        //0x64-0x67 implementation dependent
-        //0x68-0x7F reserved
-
+        //0x64-0x65 implementation dependent
+        ASI_ICACHE_INSTR = 0x66,
+        ASI_ICACHE_TAG = 0x67,
+        //0x68-0x71 implementation dependent
+        ASI_SWVR_INTR_RECEIVE = 0x72,
+        ASI_SWVR_UDB_INTR_W = 0x73,
+        ASI_SWVR_UDB_INTR_R = 0x74,
+        //0x74-0x7F reserved
         /* Unpriveleged ASIs */
         ASI_P = 0x80,
         ASI_PRIMARY = ASI_P,
@@ -195,6 +242,7 @@ namespace SparcISA
         ASI_BLK_SL = 0xF9,
         ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL,
         //0xFA-0xFF implementation dependent
+        ASI_IMPLICIT = 0xFF,
         MAX_ASI = 0xFF
     };
 
@@ -216,6 +264,10 @@ namespace SparcISA
     bool AsiIsQueue(ASI);
     bool AsiIsDtlb(ASI);
     bool AsiIsMmu(ASI);
+    bool AsiIsUnPriv(ASI);
+    bool AsiIsPriv(ASI);
+    bool AsiIsHPriv(ASI);
+    bool AsiIsReg(ASI);
 
 };
 
index 1433ba3f8ce56b63c0b379e109e6922fe2b16b6c..109fdfae7d0fa067223d4e299014df53c95a9780 100644 (file)
@@ -26,6 +26,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Ali Saidi
  */
 
 #ifndef __ARCH_SPARC_ISA_TRAITS_HH__
@@ -46,10 +47,6 @@ class StaticInstPtr;
 
 namespace BigEndianGuest {}
 
-#if FULL_SYSTEM
-#include "arch/sparc/isa_fullsys_traits.hh"
-#endif
-
 namespace SparcISA
 {
     class RegFile;
@@ -133,6 +130,30 @@ namespace SparcISA
 
     // return a no-op instruction... used for instruction fetch faults
     extern const MachInst NoopMachInst;
+
+#if FULL_SYSTEM
+    ////////// Interrupt Stuff ///////////
+    enum InterruptLevels
+    {
+       INTLEVEL_MIN = 1,
+       INTLEVEL_MAX = 15,
+
+       NumInterruptLevels = INTLEVEL_MAX - INTLEVEL_MIN
+    };
+
+    // I don't know what it's for, so I don't
+    // know what SPARC's value should be
+    // For loading... XXX This maybe could be USegEnd?? --ali
+    const Addr LoadAddrMask = ULL(0xffffffffff);
+
+    /////////// TLB Stuff ////////////
+    const Addr StartVAddrHole = ULL(0x0000800000000000);
+    const Addr EndVAddrHole = ULL(0xFFFF7FFFFFFFFFFF);
+    const Addr VAddrAMask = ULL(0xFFFFFFFF);
+    const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF);
+    const Addr BytesInPageMask = ULL(0x1FFF);
+
+#endif
 }
 
 #endif // __ARCH_SPARC_ISA_TRAITS_HH__
index d52e3983fe2f041a70bd1c13c9b64fd39daed48e..93737ad013b066308868903470039c53640b7d08 100644 (file)
@@ -95,8 +95,32 @@ void MiscRegFile::reset()
     hstick_cmpr = 0;
     strandStatusReg = 0;
     fsr = 0;
-    implicitInstAsi = ASI_PRIMARY;
-    implicitDataAsi = ASI_PRIMARY;
+
+    priContext = 0;
+    secContext = 0;
+    partId = 0;
+    lsuCtrlReg = 0;
+
+    iTlbC0TsbPs0 = 0;
+    iTlbC0TsbPs1 = 0;
+    iTlbC0Config = 0;
+    iTlbCXTsbPs0 = 0;
+    iTlbCXTsbPs1 = 0;
+    iTlbCXConfig = 0;
+    iTlbSfsr = 0;
+    iTlbTagAccess = 0;
+
+    dTlbC0TsbPs0 = 0;
+    dTlbC0TsbPs1 = 0;
+    dTlbC0Config = 0;
+    dTlbCXTsbPs0 = 0;
+    dTlbCXTsbPs1 = 0;
+    dTlbCXConfig = 0;
+    dTlbSfsr = 0;
+    dTlbSfar = 0;
+    dTlbTagAccess = 0;
+
+    memset(scratchPad, 0, sizeof(scratchPad));
 }
 
 MiscReg MiscRegFile::readReg(int miscReg)
@@ -180,6 +204,69 @@ MiscReg MiscRegFile::readReg(int miscReg)
         /** Floating Point Status Register */
         case MISCREG_FSR:
           return fsr;
+
+        case MISCREG_MMU_P_CONTEXT:
+          return priContext;
+        case MISCREG_MMU_S_CONTEXT:
+          return secContext;
+        case MISCREG_MMU_PART_ID:
+          return partId;
+        case MISCREG_MMU_LSU_CTRL:
+          return lsuCtrlReg;
+
+        case MISCREG_MMU_ITLB_C0_TSB_PS0:
+          return iTlbC0TsbPs0;
+        case MISCREG_MMU_ITLB_C0_TSB_PS1:
+          return iTlbC0TsbPs1;
+        case MISCREG_MMU_ITLB_C0_CONFIG:
+          return iTlbC0Config;
+        case MISCREG_MMU_ITLB_CX_TSB_PS0:
+          return iTlbCXTsbPs0;
+        case MISCREG_MMU_ITLB_CX_TSB_PS1:
+          return iTlbCXTsbPs1;
+        case MISCREG_MMU_ITLB_CX_CONFIG:
+          return iTlbCXConfig;
+        case MISCREG_MMU_ITLB_SFSR:
+          return iTlbSfsr;
+        case MISCREG_MMU_ITLB_TAG_ACCESS:
+          return iTlbTagAccess;
+
+        case MISCREG_MMU_DTLB_C0_TSB_PS0:
+          return dTlbC0TsbPs0;
+        case MISCREG_MMU_DTLB_C0_TSB_PS1:
+          return dTlbC0TsbPs1;
+        case MISCREG_MMU_DTLB_C0_CONFIG:
+          return dTlbC0Config;
+        case MISCREG_MMU_DTLB_CX_TSB_PS0:
+          return dTlbCXTsbPs0;
+        case MISCREG_MMU_DTLB_CX_TSB_PS1:
+          return dTlbCXTsbPs1;
+        case MISCREG_MMU_DTLB_CX_CONFIG:
+          return dTlbCXConfig;
+        case MISCREG_MMU_DTLB_SFSR:
+          return dTlbSfsr;
+        case MISCREG_MMU_DTLB_SFAR:
+          return dTlbSfar;
+        case MISCREG_MMU_DTLB_TAG_ACCESS:
+          return dTlbTagAccess;
+
+        case MISCREG_SCRATCHPAD_R0:
+          return scratchPad[0];
+        case MISCREG_SCRATCHPAD_R1:
+          return scratchPad[1];
+        case MISCREG_SCRATCHPAD_R2:
+          return scratchPad[2];
+        case MISCREG_SCRATCHPAD_R3:
+          return scratchPad[3];
+        case MISCREG_SCRATCHPAD_R4:
+          return scratchPad[4];
+        case MISCREG_SCRATCHPAD_R5:
+          return scratchPad[5];
+        case MISCREG_SCRATCHPAD_R6:
+          return scratchPad[6];
+        case MISCREG_SCRATCHPAD_R7:
+          return scratchPad[7];
+
         default:
           panic("Miscellaneous register %d not implemented\n", miscReg);
     }
@@ -326,35 +413,95 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
         case MISCREG_FSR:
           fsr = val;
           break;
+
+        case MISCREG_MMU_P_CONTEXT:
+          priContext = val;
+          break;
+        case MISCREG_MMU_S_CONTEXT:
+          secContext = val;
+          break;
+        case MISCREG_MMU_PART_ID:
+          partId = val;
+          break;
+        case MISCREG_MMU_LSU_CTRL:
+          lsuCtrlReg = val;
+          break;
+
+        case MISCREG_MMU_ITLB_C0_TSB_PS0:
+          iTlbC0TsbPs0 = val;
+          break;
+        case MISCREG_MMU_ITLB_C0_TSB_PS1:
+          iTlbC0TsbPs1 = val;
+          break;
+        case MISCREG_MMU_ITLB_C0_CONFIG:
+          iTlbC0Config = val;
+          break;
+        case MISCREG_MMU_ITLB_CX_TSB_PS0:
+          iTlbCXTsbPs0 = val;
+          break;
+        case MISCREG_MMU_ITLB_CX_TSB_PS1:
+          iTlbCXTsbPs1 = val;
+          break;
+        case MISCREG_MMU_ITLB_CX_CONFIG:
+          iTlbCXConfig = val;
+          break;
+        case MISCREG_MMU_ITLB_SFSR:
+          iTlbSfsr = val;
+          break;
+        case MISCREG_MMU_ITLB_TAG_ACCESS:
+          iTlbTagAccess = val;
+          break;
+
+        case MISCREG_MMU_DTLB_C0_TSB_PS0:
+          dTlbC0TsbPs0 = val;
+          break;
+        case MISCREG_MMU_DTLB_C0_TSB_PS1:
+          dTlbC0TsbPs1 = val;
+          break;
+        case MISCREG_MMU_DTLB_C0_CONFIG:
+          dTlbC0Config = val;
+          break;
+        case MISCREG_MMU_DTLB_CX_TSB_PS0:
+          dTlbCXTsbPs0 = val;
+          break;
+        case MISCREG_MMU_DTLB_CX_TSB_PS1:
+          dTlbCXTsbPs1 = val;
+          break;
+        case MISCREG_MMU_DTLB_CX_CONFIG:
+          dTlbCXConfig = val;
+          break;
+        case MISCREG_MMU_DTLB_SFSR:
+          dTlbSfsr = val;
+          break;
+        case MISCREG_MMU_DTLB_SFAR:
+          dTlbSfar = val;
+          break;
+        case MISCREG_MMU_DTLB_TAG_ACCESS:
+          dTlbTagAccess = val;
+          break;
+
+        case MISCREG_SCRATCHPAD_R0:
+           scratchPad[0] = val;
+        case MISCREG_SCRATCHPAD_R1:
+           scratchPad[1] = val;
+        case MISCREG_SCRATCHPAD_R2:
+           scratchPad[2] = val;
+        case MISCREG_SCRATCHPAD_R3:
+           scratchPad[3] = val;
+        case MISCREG_SCRATCHPAD_R4:
+           scratchPad[4] = val;
+        case MISCREG_SCRATCHPAD_R5:
+           scratchPad[5] = val;
+        case MISCREG_SCRATCHPAD_R6:
+           scratchPad[6] = val;
+        case MISCREG_SCRATCHPAD_R7:
+           scratchPad[7] = val;
+
         default:
           panic("Miscellaneous register %d not implemented\n", miscReg);
     }
 }
 
-inline void MiscRegFile::setImplicitAsis()
-{
-    //The spec seems to use trap level to indicate the privilege level of the
-    //processor. It's unclear whether the implicit ASIs should directly depend
-    //on the trap level, or if they should really be based on the privelege
-    //bits
-    if(tl == 0)
-    {
-        implicitInstAsi = implicitDataAsi =
-            (pstate & (1 << 9)) ? ASI_PRIMARY_LITTLE : ASI_PRIMARY;
-    }
-    else if(tl <= MaxPTL)
-    {
-        implicitInstAsi = ASI_NUCLEUS;
-        implicitDataAsi = (pstate & (1 << 9)) ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS;
-    }
-    else
-    {
-        //This is supposed to force physical addresses to match the spec.
-        //It might not because of context values and partition values.
-        implicitInstAsi = implicitDataAsi = ASI_REAL;
-    }
-}
-
 void MiscRegFile::setRegWithEffect(int miscReg,
         const MiscReg &val, ThreadContext * tc)
 {
@@ -376,11 +523,9 @@ void MiscRegFile::setRegWithEffect(int miscReg,
           break;
         case MISCREG_PSTATE:
           pstate = val;
-          setImplicitAsis();
           return;
         case MISCREG_TL:
           tl = val;
-          setImplicitAsis();
           return;
         case MISCREG_CWP:
           tc->changeRegFileContext(CONTEXT_CWP, val);
@@ -483,8 +628,28 @@ void MiscRegFile::serialize(std::ostream & os)
     SERIALIZE_ARRAY(htstate, MaxTL);
     SERIALIZE_SCALAR(htba);
     SERIALIZE_SCALAR(hstick_cmpr);
-    SERIALIZE_SCALAR((int)implicitInstAsi);
-    SERIALIZE_SCALAR((int)implicitDataAsi);
+    SERIALIZE_SCALAR(strandStatusReg);
+    SERIALIZE_SCALAR(priContext);
+    SERIALIZE_SCALAR(secContext);
+    SERIALIZE_SCALAR(partId);
+    SERIALIZE_SCALAR(lsuCtrlReg);
+    SERIALIZE_SCALAR(iTlbC0TsbPs0);
+    SERIALIZE_SCALAR(iTlbC0TsbPs1);
+    SERIALIZE_SCALAR(iTlbC0Config);
+    SERIALIZE_SCALAR(iTlbCXTsbPs0);
+    SERIALIZE_SCALAR(iTlbCXTsbPs1);
+    SERIALIZE_SCALAR(iTlbCXConfig);
+    SERIALIZE_SCALAR(iTlbSfsr);
+    SERIALIZE_SCALAR(iTlbTagAccess);
+    SERIALIZE_SCALAR(dTlbC0TsbPs0);
+    SERIALIZE_SCALAR(dTlbC0TsbPs1);
+    SERIALIZE_SCALAR(dTlbC0Config);
+    SERIALIZE_SCALAR(dTlbCXTsbPs0);
+    SERIALIZE_SCALAR(dTlbCXTsbPs1);
+    SERIALIZE_SCALAR(dTlbSfsr);
+    SERIALIZE_SCALAR(dTlbSfar);
+    SERIALIZE_SCALAR(dTlbTagAccess);
+    SERIALIZE_ARRAY(scratchPad,8);
 }
 
 void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
@@ -514,12 +679,28 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
     UNSERIALIZE_ARRAY(htstate, MaxTL);
     UNSERIALIZE_SCALAR(htba);
     UNSERIALIZE_SCALAR(hstick_cmpr);
-    int temp;
-    UNSERIALIZE_SCALAR(temp);
-    implicitInstAsi = (ASI)temp;
-    UNSERIALIZE_SCALAR(temp);
-    implicitDataAsi = (ASI)temp;
-}
+    UNSERIALIZE_SCALAR(strandStatusReg);
+    UNSERIALIZE_SCALAR(priContext);
+    UNSERIALIZE_SCALAR(secContext);
+    UNSERIALIZE_SCALAR(partId);
+    UNSERIALIZE_SCALAR(lsuCtrlReg);
+    UNSERIALIZE_SCALAR(iTlbC0TsbPs0);
+    UNSERIALIZE_SCALAR(iTlbC0TsbPs1);
+    UNSERIALIZE_SCALAR(iTlbC0Config);
+    UNSERIALIZE_SCALAR(iTlbCXTsbPs0);
+    UNSERIALIZE_SCALAR(iTlbCXTsbPs1);
+    UNSERIALIZE_SCALAR(iTlbCXConfig);
+    UNSERIALIZE_SCALAR(iTlbSfsr);
+    UNSERIALIZE_SCALAR(iTlbTagAccess);
+    UNSERIALIZE_SCALAR(dTlbC0TsbPs0);
+    UNSERIALIZE_SCALAR(dTlbC0TsbPs1);
+    UNSERIALIZE_SCALAR(dTlbC0Config);
+    UNSERIALIZE_SCALAR(dTlbCXTsbPs0);
+    UNSERIALIZE_SCALAR(dTlbCXTsbPs1);
+    UNSERIALIZE_SCALAR(dTlbSfsr);
+    UNSERIALIZE_SCALAR(dTlbSfar);
+    UNSERIALIZE_SCALAR(dTlbTagAccess);
+    UNSERIALIZE_ARRAY(scratchPad,8);}
 
 #if FULL_SYSTEM
 void
index f74943256ad074a3b55f39c4185f24b23b2e22f8..a4ce6ca5c78cbf2c48b7755c9d7ba9f1f41fce19 100644 (file)
@@ -92,7 +92,42 @@ namespace SparcISA
         MISCREG_HSTICK_CMPR,
 
         /** Floating Point Status Register */
-        MISCREG_FSR
+        MISCREG_FSR,
+
+        /** MMU Internal Registers */
+        MISCREG_MMU_P_CONTEXT,
+        MISCREG_MMU_S_CONTEXT,
+        MISCREG_MMU_PART_ID,
+        MISCREG_MMU_LSU_CTRL,
+
+        MISCREG_MMU_ITLB_C0_TSB_PS0,
+        MISCREG_MMU_ITLB_C0_TSB_PS1,
+        MISCREG_MMU_ITLB_C0_CONFIG,
+        MISCREG_MMU_ITLB_CX_TSB_PS0,
+        MISCREG_MMU_ITLB_CX_TSB_PS1,
+        MISCREG_MMU_ITLB_CX_CONFIG,
+        MISCREG_MMU_ITLB_SFSR,
+        MISCREG_MMU_ITLB_TAG_ACCESS,
+
+        MISCREG_MMU_DTLB_C0_TSB_PS0,
+        MISCREG_MMU_DTLB_C0_TSB_PS1,
+        MISCREG_MMU_DTLB_C0_CONFIG,
+        MISCREG_MMU_DTLB_CX_TSB_PS0,
+        MISCREG_MMU_DTLB_CX_TSB_PS1,
+        MISCREG_MMU_DTLB_CX_CONFIG,
+        MISCREG_MMU_DTLB_SFSR,
+        MISCREG_MMU_DTLB_SFAR,
+        MISCREG_MMU_DTLB_TAG_ACCESS,
+
+        /** Scratchpad regiscers **/
+        MISCREG_SCRATCHPAD_R0,
+        MISCREG_SCRATCHPAD_R1,
+        MISCREG_SCRATCHPAD_R2,
+        MISCREG_SCRATCHPAD_R3,
+        MISCREG_SCRATCHPAD_R4,
+        MISCREG_SCRATCHPAD_R5,
+        MISCREG_SCRATCHPAD_R6,
+        MISCREG_SCRATCHPAD_R7
     };
 
     // The control registers, broken out into fields
@@ -146,8 +181,32 @@ namespace SparcISA
         /** Floating point misc registers. */
         uint64_t fsr;          // Floating-Point State Register
 
-        ASI implicitInstAsi;
-        ASI implicitDataAsi;
+        /** MMU Internal Registers */
+        uint16_t priContext;
+        uint16_t secContext;
+        uint16_t partId;
+        uint64_t lsuCtrlReg;
+
+        uint64_t iTlbC0TsbPs0;
+        uint64_t iTlbC0TsbPs1;
+        uint64_t iTlbC0Config;
+        uint64_t iTlbCXTsbPs0;
+        uint64_t iTlbCXTsbPs1;
+        uint64_t iTlbCXConfig;
+        uint64_t iTlbSfsr;
+        uint64_t iTlbTagAccess;
+
+        uint64_t dTlbC0TsbPs0;
+        uint64_t dTlbC0TsbPs1;
+        uint64_t dTlbC0Config;
+        uint64_t dTlbCXTsbPs0;
+        uint64_t dTlbCXTsbPs1;
+        uint64_t dTlbCXConfig;
+        uint64_t dTlbSfsr;
+        uint64_t dTlbSfar;
+        uint64_t dTlbTagAccess;
+
+        uint64_t scratchPad[8];
 
         // These need to check the int_dis field and if 0 then
         // set appropriate bit in softint and checkinterrutps on the cpu
@@ -188,14 +247,14 @@ namespace SparcISA
         void setRegWithEffect(int miscReg,
                 const MiscReg &val, ThreadContext * tc);
 
-        ASI getInstAsid()
+        int getInstAsid()
         {
-            return implicitInstAsi;
+            return priContext | (uint32_t)partId << 13;
         }
 
-        ASI getDataAsid()
+        int getDataAsid()
         {
-            return implicitDataAsi;
+            return priContext | (uint32_t)partId << 13;
         }
 
         void serialize(std::ostream & os);
@@ -209,7 +268,6 @@ namespace SparcISA
         bool isHyperPriv() { return (hpstate & (1 << 2)); }
         bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
         bool isNonPriv() { return !isPriv(); }
-        inline void setImplicitAsis();
     };
 }
 
diff --git a/src/arch/sparc/pagetable.cc b/src/arch/sparc/pagetable.cc
new file mode 100644 (file)
index 0000000..22130d4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "arch/sparc/pagetable.hh"
+#include "sim/serialize.hh"
+
+namespace SparcISA
+{
+void
+TlbEntry::serialize(std::ostream &os)
+{
+    SERIALIZE_SCALAR(range.va);
+    SERIALIZE_SCALAR(range.size);
+    SERIALIZE_SCALAR(range.contextId);
+    SERIALIZE_SCALAR(range.partitionId);
+    SERIALIZE_SCALAR(range.real);
+    uint64_t entry4u = pte();
+    SERIALIZE_SCALAR(entry4u);
+    SERIALIZE_SCALAR(used);
+}
+
+
+void
+TlbEntry::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(range.va);
+    UNSERIALIZE_SCALAR(range.size);
+    UNSERIALIZE_SCALAR(range.contextId);
+    UNSERIALIZE_SCALAR(range.partitionId);
+    UNSERIALIZE_SCALAR(range.real);
+    uint64_t entry4u;
+    UNSERIALIZE_SCALAR(entry4u);
+    pte.populate(entry4u);
+    UNSERIALIZE_SCALAR(used);
+}
+
+
+int PageTableEntry::pageSizes[] = {8*1024, 64*1024, 0, 4*1024*1024, 0,
+            256*1024*1024L};
+
+
+}
diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh
new file mode 100644 (file)
index 0000000..21dbad0
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_PAGETABLE_HH__
+#define __ARCH_SPARC_PAGETABLE_HH__
+
+#include "arch/sparc/isa_traits.hh"
+#include "config/full_system.hh"
+
+namespace SparcISA
+{
+struct VAddr
+{
+    VAddr(Addr a) { panic("not implemented yet."); }
+};
+
+class PageTableEntry
+{
+  public:
+    enum EntryType {
+      sun4v,
+      sun4u,
+      invalid
+    };
+
+  private:
+    uint64_t entry;
+    EntryType type;
+    uint64_t entry4u;
+    bool populated;
+
+
+  public:
+    PageTableEntry() : entry(0), type(invalid), populated(false) {}
+
+    PageTableEntry(uint64_t e, EntryType t = sun4u)
+        : entry(e), type(t), populated(true)
+
+    {
+        populate(entry, type);
+    }
+
+    void populate(uint64_t e, EntryType t = sun4u)
+    {
+        entry = e;
+        type = t;
+        populated = true;
+
+        // If we get a sun4v format TTE, turn it into a sun4u
+        if (type == sun4u)
+            entry4u = entry;
+        else {
+            uint64_t entry4u = 0;
+            entry4u |= entry & ULL(0x8000000000000000);              //valid
+            entry4u |= (entry & 0x3) << 61;                     //size[1:0]
+            entry4u |= (entry & ULL(0x4000000000000000)) >> 2;       //nfo
+            entry4u |= (entry & 0x1000) << 47;                  //ie
+            //entry4u |= (entry & 0x3F00000000000000) >> 7;       //soft2
+            entry4u |= (entry & 0x4) << 48;                     //size[2]
+                                                                //diag?
+            entry4u |= (entry & ULL(0x0000FFFFFFFFE000));            //paddr
+            entry4u |= (entry & 0x400) >> 5;                    //cp
+            entry4u |= (entry & 0x200) >> 5;                    //cv
+            entry4u |= (entry & 0x800) >> 8;                    //e
+            entry4u |= (entry & 0x100) >> 6;                    //p
+            entry4u |= (entry & 0x40) >> 5;                     //w
+        }
+    }
+
+    void clear()
+    {
+        populated = false;
+    }
+
+    static int pageSizes[6];
+
+
+    uint64_t operator()() const { assert(populated); return entry4u; }
+    const PageTableEntry &operator=(uint64_t e) { populated = true;
+                                                  entry4u = e; return *this; }
+
+    const PageTableEntry &operator=(const PageTableEntry &e)
+    { populated = true; entry4u = e.entry4u; return *this; }
+
+    bool    valid()    const { return entry4u & ULL(0x8000000000000000) && populated; }
+    uint8_t _size()     const { assert(populated);
+                               return ((entry4u & 0x6) >> 61) |
+                                      ((entry4u & ULL(0x000080000000000)) >> 46); }
+    Addr    size()     const { return pageSizes[_size()]; }
+    bool    ie()       const { return entry4u >> 59 & 0x1; }
+    Addr    pfn()      const { assert(populated);
+                               return entry4u >> 13 & ULL(0xFFFFFFFFFF); }
+    Addr    paddr()    const { assert(populated);
+                               return entry4u & ULL(0x0000FFFFFFFFE000); }
+    bool    locked()   const { assert(populated);
+                               return entry4u & 0x40; }
+    bool    cv()       const { assert(populated);
+                               return entry4u & 0x10; }
+    bool    cp()       const { assert(populated);
+                               return entry4u & 0x20; }
+    bool    priv()     const { assert(populated);
+                               return entry4u & 0x4; }
+    bool    writable() const { assert(populated);
+                               return entry4u & 0x2; }
+    bool    nofault()  const { assert(populated);
+                               return entry4u & ULL(0x1000000000000000); }
+    bool    sideffect() const { assert(populated);
+                                return entry4u & 0x8; }
+};
+
+struct TlbRange {
+    Addr va;
+    Addr size;
+    int contextId;
+    int partitionId;
+    bool real;
+
+    inline bool operator<(const TlbRange &r2) const
+    {
+        if (real && !r2.real)
+            return true;
+        if (!real && r2.real)
+            return false;
+
+        if (!real && !r2.real) {
+            if (contextId < r2.contextId)
+                return true;
+            else if (contextId > r2.contextId)
+                return false;
+        }
+
+        if (partitionId < r2.partitionId)
+            return true;
+        else if (partitionId > r2.partitionId)
+            return false;
+
+        if (va < r2.va)
+            return true;
+        return false;
+    }
+    inline bool operator==(const TlbRange &r2) const
+    {
+        return va == r2.va &&
+               size == r2.size &&
+               contextId == r2.contextId &&
+               partitionId == r2.partitionId &&
+               real == r2.real;
+    }
+};
+
+
+struct TlbEntry {
+    TlbRange range;
+    PageTableEntry pte;
+    bool used;
+    bool valid;
+
+    void serialize(std::ostream &os);
+    void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+
+}; // namespace SparcISA
+
+#endif // __ARCH_SPARC_PAGE_TABLE_HH__
+
index 9f33435f69e8c30fba71f8259864d18fbfa2adaa..0a09d0f6693849b05e82cd6063f758c755bc1a2c 100644 (file)
@@ -82,12 +82,12 @@ namespace SparcISA
         void setMiscRegWithEffect(int miscReg, const MiscReg &val,
                 ThreadContext * tc);
 
-        ASI instAsid()
+        int instAsid()
         {
             return miscRegFile.getInstAsid();
         }
 
-        ASI dataAsid()
+        int dataAsid()
         {
             return miscRegFile.getDataAsid();
         }
index 0b1a2ff5f4d6774a9f28a0f10f5f6c4c1fa4c9a3..9b7943ed9d9014c5310ca67c7b14ee54843c0441 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Nathan Binkert
- *          Steve Reinhardt
- *          Andrew Schultz
+ * Authors: Ali Saidi
  */
 
+#include "arch/sparc/asi.hh"
 #include "arch/sparc/tlb.hh"
 #include "sim/builder.hh"
+#include "arch/sparc/miscregfile.hh"
+#include "cpu/thread_context.hh"
 
+/* @todo remove some of the magic constants.  -- ali
+ * */
 namespace SparcISA
 {
-    DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
 
-    BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
+TLB::TLB(const std::string &name, int s)
+    : SimObject(name), size(s)
+{
+    // To make this work you'll have to change the hypervisor and OS
+    if (size > 64)
+        fatal("SPARC T1 TLB registers don't support more than 64 TLB entries.");
+
+    tlb = new TlbEntry[size];
+    memset(tlb, 0, sizeof(TlbEntry) * size);
+}
+
+void
+TLB::clearUsedBits()
+{
+    MapIter i;
+    for (i = lookupTable.begin(); i != lookupTable.end();) {
+        TlbEntry *t = i->second;
+        if (!t->pte.locked()) {
+            t->used = false;
+            usedEntries--;
+        }
+    }
+}
+
+
+void
+TLB::insert(Addr va, int partition_id, int context_id, bool real,
+        const PageTableEntry& PTE)
+{
+
+
+    MapIter i;
+    TlbEntry *new_entry;
+    int x = -1;
+    for (x = 0; x < size; x++) {
+        if (!tlb[x].valid || !tlb[x].used)  {
+            new_entry = &tlb[x];
+            break;
+        }
+    }
+
+    // Update the last ently if their all locked
+    if (x == -1)
+       x = size - 1;
+
+    assert(PTE.valid());
+    new_entry->range.va = va;
+    new_entry->range.size = PTE.size();
+    new_entry->range.partitionId = partition_id;
+    new_entry->range.contextId = context_id;
+    new_entry->range.real = real;
+    new_entry->pte = PTE;
+    new_entry->used = true;;
+    new_entry->valid = true;
+    usedEntries++;
+
+
+    // Demap any entry that conflicts
+    i = lookupTable.find(new_entry->range);
+    if (i != lookupTable.end()) {
+        i->second->valid = false;
+        if (i->second->used) {
+            i->second->used = false;
+            usedEntries--;
+        }
+        lookupTable.erase(i);
+    }
 
-        Param<int> size;
+    lookupTable.insert(new_entry->range, new_entry);;
 
-    END_DECLARE_SIM_OBJECT_PARAMS(ITB)
+    // If all entries have there used bit set, clear it on them all, but the
+    // one we just inserted
+    if (usedEntries == size) {
+        clearUsedBits();
+        new_entry->used = true;
+        usedEntries++;
+    }
 
-    BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
+}
 
-        INIT_PARAM_DFLT(size, "TLB size", 48)
 
-    END_INIT_SIM_OBJECT_PARAMS(ITB)
+TlbEntry*
+TLB::lookup(Addr va, int partition_id, bool real, int context_id)
+{
+    MapIter i;
+    TlbRange tr;
+    TlbEntry *t;
 
+    // Assemble full address structure
+    tr.va = va;
+    tr.size = va + MachineBytes;
+    tr.contextId = context_id;
+    tr.partitionId = partition_id;
+    tr.real = real;
 
-    CREATE_SIM_OBJECT(ITB)
-    {
-        return new ITB(getInstanceName(), size);
+    // Try to find the entry
+    i = lookupTable.find(tr);
+    if (i == lookupTable.end()) {
+        return NULL;
     }
 
-    REGISTER_SIM_OBJECT("SparcITB", ITB)
+    // Mark the entries used bit and clear other used bits in needed
+    t = i->second;
+    if (!t->used) {
+        t->used = true;
+        usedEntries++;
+        if (usedEntries == size) {
+            clearUsedBits();
+            t->used = true;
+            usedEntries++;
+        }
+    }
 
-    BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
+    return t;
+}
 
-        Param<int> size;
 
-    END_DECLARE_SIM_OBJECT_PARAMS(DTB)
+void
+TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
+{
+    TlbRange tr;
+    MapIter i;
+
+    // Assemble full address structure
+    tr.va = va;
+    tr.size = va + MachineBytes;
+    tr.contextId = context_id;
+    tr.partitionId = partition_id;
+    tr.real = real;
 
-    BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
+    // Demap any entry that conflicts
+    i = lookupTable.find(tr);
+    if (i != lookupTable.end()) {
+        i->second->valid = false;
+        if (i->second->used) {
+            i->second->used = false;
+            usedEntries--;
+        }
+        lookupTable.erase(i);
+    }
+}
 
-        INIT_PARAM_DFLT(size, "TLB size", 64)
+void
+TLB::demapContext(int partition_id, int context_id)
+{
+    int x;
+    for (x = 0; x < size; x++) {
+        if (tlb[x].range.contextId == context_id &&
+            tlb[x].range.partitionId == partition_id) {
+            tlb[x].valid = false;
+            if (tlb[x].used) {
+                tlb[x].used = false;
+                usedEntries--;
+            }
+            lookupTable.erase(tlb[x].range);
+        }
+    }
+}
 
-    END_INIT_SIM_OBJECT_PARAMS(DTB)
+void
+TLB::demapAll(int partition_id)
+{
+    int x;
+    for (x = 0; x < size; x++) {
+        if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
+            tlb[x].valid = false;
+            if (tlb[x].used) {
+                tlb[x].used = false;
+                usedEntries--;
+            }
+            lookupTable.erase(tlb[x].range);
+        }
+    }
+}
 
+void
+TLB::invalidateAll()
+{
+    int x;
+    for (x = 0; x < size; x++) {
+        tlb[x].valid = false;
+    }
+    usedEntries = 0;
+}
+
+uint64_t
+TLB::TteRead(int entry) {
+    assert(entry < size);
+    return tlb[entry].pte();
+}
+
+uint64_t
+TLB::TagRead(int entry) {
+    assert(entry < size);
+    uint64_t tag;
+
+    tag = tlb[entry].range.contextId | tlb[entry].range.va |
+          (uint64_t)tlb[entry].range.partitionId << 61;
+    tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
+    tag |= (uint64_t)~tlb[entry].pte._size() << 56;
+    return tag;
+}
+
+bool
+TLB::validVirtualAddress(Addr va, bool am)
+{
+    if (am)
+        return true;
+    if (va >= StartVAddrHole && va <= EndVAddrHole)
+        return false;
+    return true;
+}
+
+void
+TLB::writeSfsr(ThreadContext *tc, int reg,  bool write, ContextType ct,
+        bool se, FaultTypes ft, int asi)
+{
+    uint64_t sfsr;
+    sfsr = tc->readMiscReg(reg);
+
+    if (sfsr & 0x1)
+        sfsr = 0x3;
+    else
+        sfsr = 1;
+
+    if (write)
+        sfsr |= 1 << 2;
+    sfsr |= ct << 4;
+    if (se)
+        sfsr |= 1 << 6;
+    sfsr |= ft << 7;
+    sfsr |= asi << 16;
+    tc->setMiscReg(reg, sfsr);
+}
+
+
+void
+ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct,
+        bool se, FaultTypes ft, int asi)
+{
+    TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi);
+}
+
+void
+DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
+        bool se, FaultTypes ft, int asi)
+{
+    TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi);
+    tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
+}
+
+
+Fault
+ITB::translate(RequestPtr &req, ThreadContext *tc)
+{
+    uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
+    uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
+    bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
+    uint64_t tl = tc->readMiscReg(MISCREG_TL);
+    uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
+    bool addr_mask = pstate >> 3 & 0x1;
+    bool priv = pstate >> 2 & 0x1;
+    Addr vaddr = req->getVaddr();
+    int context;
+    ContextType ct;
+    int asi;
+    bool real = false;
+    TlbEntry *e;
+
+    assert(req->getAsi() == ASI_IMPLICIT);
+
+    if (tl > 0) {
+        asi = ASI_N;
+        ct = Nucleus;
+        context = 0;
+    } else {
+        asi = ASI_P;
+        ct = Primary;
+        context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+    }
+
+    if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
+        req->setPaddr(req->getVaddr() & PAddrImplMask);
+        return NoFault;
+    }
+
+    // If the asi is unaligned trap
+    if (vaddr & 0x7) {
+        writeSfsr(tc, false, ct, false, OtherFault, asi);
+        return new MemAddressNotAligned;
+    }
+
+    if (addr_mask)
+        vaddr = vaddr & VAddrAMask;
+
+    if (!validVirtualAddress(vaddr, addr_mask)) {
+        writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
+        return new InstructionAccessException;
+    }
+
+    if (lsuIm) {
+        e = lookup(req->getVaddr(), part_id, true);
+        real = true;
+        context = 0;
+    } else {
+        e = lookup(vaddr, part_id, false, context);
+    }
 
-    CREATE_SIM_OBJECT(DTB)
-    {
-        return new DTB(getInstanceName(), size);
+    if (e == NULL || !e->valid) {
+        tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
+                vaddr & ~BytesInPageMask | context);
+        if (real)
+            return new InstructionRealTranslationMiss;
+        else
+            return new FastInstructionAccessMMUMiss;
     }
 
-    REGISTER_SIM_OBJECT("SparcDTB", DTB)
+    // were not priviledged accesing priv page
+    if (!priv && e->pte.priv()) {
+        writeSfsr(tc, false, ct, false, PrivViolation, asi);
+        return new InstructionAccessException;
+    }
+
+    req->setPaddr(e->pte.paddr() & ~e->pte.size() |
+                  req->getVaddr() & e->pte.size());
+    return NoFault;
+}
+
+
+
+Fault
+DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
+{
+    /* @todo this could really use some profiling and fixing to make it faster! */
+    uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
+    uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
+    bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
+    uint64_t tl = tc->readMiscReg(MISCREG_TL);
+    uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
+    bool hpriv = hpstate >> 2 & 0x1;
+    bool red = hpstate >> 5 >> 0x1;
+    bool addr_mask = pstate >> 3 & 0x1;
+    bool priv = pstate >> 2 & 0x1;
+    bool implicit = false;
+    bool real = false;
+    Addr vaddr = req->getVaddr();
+    ContextType ct;
+    int context;
+    ASI asi;
+
+    TlbEntry *e;
+
+
+    asi = (ASI)req->getAsi();
+    if (asi == ASI_IMPLICIT)
+        implicit = true;
+
+    if (implicit) {
+        if (tl > 0) {
+            asi = ASI_N;
+            ct = Nucleus;
+            context = 0;
+        } else {
+            asi = ASI_P;
+            ct = Primary;
+            context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+        }
+    } else if (!hpriv && !red) {
+        if (tl > 0) {
+            ct = Nucleus;
+            context = 0;
+        } else if (AsiIsSecondary(asi)) {
+            ct = Secondary;
+            context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
+        } else {
+            context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+            ct = Primary; //???
+        }
+
+        // We need to check for priv level/asi priv
+        if (!priv && !AsiIsUnPriv(asi)) {
+            // It appears that context should be Nucleus in these cases?
+            writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
+            return new PrivilegedAction;
+        }
+        if (priv && AsiIsHPriv(asi)) {
+            writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
+            return new DataAccessException;
+        }
+
+    }
+
+    // If the asi is unaligned trap
+    if (AsiIsBlock(asi) && vaddr & 0x3f || vaddr & 0x7) {
+        writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
+        return new MemAddressNotAligned;
+    }
+
+    if (addr_mask)
+        vaddr = vaddr & VAddrAMask;
+
+    if (!validVirtualAddress(vaddr, addr_mask)) {
+        writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
+        return new DataAccessException;
+    }
+
+    if (!implicit) {
+        if (AsiIsLittle(asi))
+            panic("Little Endian ASIs not supported\n");
+        if (AsiIsBlock(asi))
+            panic("Block ASIs not supported\n");
+        if (AsiIsNoFault(asi))
+            panic("No Fault ASIs not supported\n");
+        if (AsiIsTwin(asi))
+            panic("Twin ASIs not supported\n");
+        if (AsiIsPartialStore(asi))
+            panic("Partial Store ASIs not supported\n");
+        if (AsiIsMmu(asi))
+            goto handleMmuRegAccess;
+
+        if (AsiIsScratchPad(asi))
+            goto handleScratchRegAccess;
+    }
+
+    if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
+        real = true;
+        context = 0;
+    };
+
+    if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
+        req->setPaddr(req->getVaddr() & PAddrImplMask);
+        return NoFault;
+    }
+
+    e = lookup(req->getVaddr(), part_id, real, context);
+
+    if (e == NULL || !e->valid) {
+        tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
+                vaddr & ~BytesInPageMask | context);
+        if (real)
+            return new DataRealTranslationMiss;
+        else
+            return new FastDataAccessMMUMiss;
+
+    }
+
+
+    if (write && !e->pte.writable()) {
+        writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
+        return new FastDataAccessProtection;
+    }
+
+    if (e->pte.nofault() && !AsiIsNoFault(asi)) {
+        writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
+        return new DataAccessException;
+    }
+
+    if (e->pte.sideffect())
+        req->setFlags(req->getFlags() | UNCACHEABLE);
+
+
+    if (!priv && e->pte.priv()) {
+        writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
+        return new DataAccessException;
+    }
+
+    req->setPaddr(e->pte.paddr() & ~e->pte.size() |
+                  req->getVaddr() & e->pte.size());
+    return NoFault;
+    /*** End of normal Path ***/
+
+handleMmuRegAccess:
+handleScratchRegAccess:
+    panic("How are we ever going to deal with this?\n");
+};
+
+void
+TLB::serialize(std::ostream &os)
+{
+    panic("Need to implement serialize tlb for SPARC\n");
+}
+
+void
+TLB::unserialize(Checkpoint *cp, const std::string &section)
+{
+    panic("Need to implement unserialize tlb for SPARC\n");
+}
+
+
+DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
+
+    Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(ITB)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
+
+    INIT_PARAM_DFLT(size, "TLB size", 48)
+
+END_INIT_SIM_OBJECT_PARAMS(ITB)
+
+
+CREATE_SIM_OBJECT(ITB)
+{
+    return new ITB(getInstanceName(), size);
+}
+
+REGISTER_SIM_OBJECT("SparcITB", ITB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
+
+    Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(DTB)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
+
+    INIT_PARAM_DFLT(size, "TLB size", 64)
+
+END_INIT_SIM_OBJECT_PARAMS(DTB)
+
+
+CREATE_SIM_OBJECT(DTB)
+{
+    return new DTB(getInstanceName(), size);
+}
+
+REGISTER_SIM_OBJECT("SparcDTB", DTB)
 }
index 136103f448b26a01ae4a520d7850ddb52b4f6068..824d6494c7a3aa5ab8b5629f00b6d84f95d1f9f6 100644 (file)
@@ -31,6 +31,7 @@
 #ifndef __ARCH_SPARC_TLB_HH__
 #define __ARCH_SPARC_TLB_HH__
 
+#include "arch/sparc/tlb_map.hh"
 #include "base/misc.hh"
 #include "mem/request.hh"
 #include "sim/faults.hh"
@@ -40,48 +41,114 @@ class ThreadContext;
 
 namespace SparcISA
 {
-    const int PAddrImplBits = 40;
-    const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1;
 
-    class TLB : public SimObject
-    {
-      public:
-        TLB(const std::string &name, int size) : SimObject(name)
-        {
-        }
+class TLB : public SimObject
+{
+  protected:
+    TlbMap lookupTable;;
+    typedef TlbMap::iterator MapIter;
+
+    TlbEntry *tlb;
+
+    int size;
+    int usedEntries;
+
+    enum FaultTypes {
+        OtherFault = 0,
+        PrivViolation = 0x1,
+        SideEffect = 0x2,
+        AtomicToIo = 0x4,
+        IllegalAsi = 0x8,
+        LoadFromNfo = 0x10,
+        VaOutOfRange = 0x20,
+        VaOutOfRangeJmp = 0x40
     };
 
-    class ITB : public TLB
-    {
-      public:
-        ITB(const std::string &name, int size) : TLB(name, size)
-        {
-        }
-
-        Fault translate(RequestPtr &req, ThreadContext *tc) const
-        {
-            //For now, always assume the address is already physical.
-            //Also assume that there are 40 bits of physical address space.
-            req->setPaddr(req->getVaddr() & PAddrImplMask);
-            return NoFault;
-        }
+    enum ContextType {
+        Primary = 0,
+        Secondary = 1,
+        Nucleus = 2
     };
 
-    class DTB : public TLB
+
+    /** lookup an entry in the TLB based on the partition id, and real bit if
+     * real is true or the partition id, and context id if real is false.
+     * @param va the virtual address not shifted (e.g. bottom 13 bits are 0)
+     * @param paritition_id partition this entry is for
+     * @param real is this a real->phys or virt->phys translation
+     * @param context_id if this is virt->phys what context
+     * @return A pointer to a tlb entry
+     */
+    TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0);
+
+    /** Insert a PTE into the TLB. */
+    void insert(Addr vpn, int partition_id, int context_id, bool real,
+            const PageTableEntry& PTE);
+
+    /** Given an entry id, read that tlb entries' tag. */
+    uint64_t TagRead(int entry);
+
+    /** Give an entry id, read that tlb entries' tte */
+    uint64_t TteRead(int entry);
+
+    /** Remove all entries from the TLB */
+    void invalidateAll();
+
+    /** Remove all non-locked entries from the tlb that match partition id. */
+    void demapAll(int partition_id);
+
+    /** Remove all entries that match a given context/partition id. */
+    void demapContext(int partition_id, int context_id);
+
+    /** Remve all entries that match a certain partition id, (contextid), and
+     * va). */
+    void demapPage(Addr va, int partition_id, bool real, int context_id);
+
+    /** Checks if the virtual address provided is a valid one. */
+    bool validVirtualAddress(Addr va, bool am);
+
+    void writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
+            bool se, FaultTypes ft, int asi);
+
+    void TLB::clearUsedBits();
+
+
+  public:
+    TLB(const std::string &name, int size);
+
+    // Checkpointing
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+class ITB : public TLB
+{
+  public:
+    ITB(const std::string &name, int size) : TLB(name, size)
     {
-      public:
-        DTB(const std::string &name, int size) : TLB(name, size)
-        {
-        }
-
-        Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const
-        {
-            //For now, always assume the address is already physical.
-            //Also assume that there are 40 bits of physical address space.
-            req->setPaddr(req->getVaddr() & ((1ULL << 40) - 1));
-            return NoFault;
-        }
-    };
+    }
+
+    Fault translate(RequestPtr &req, ThreadContext *tc);
+  private:
+    void writeSfsr(ThreadContext *tc, bool write, ContextType ct,
+            bool se, FaultTypes ft, int asi);
+};
+
+class DTB : public TLB
+{
+  public:
+    DTB(const std::string &name, int size) : TLB(name, size)
+    {
+    }
+
+    Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
+
+  private:
+    void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
+            bool se, FaultTypes ft, int asi);
+
+};
+
 }
 
 #endif // __ARCH_SPARC_TLB_HH__
diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh
new file mode 100644 (file)
index 0000000..226ef23
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_TLB_MAP_HH__
+#define __ARCH_SPARC_TLB_MAP_HH__
+
+#include "arch/sparc/pagetable.hh"
+#include <map>
+
+namespace SparcISA
+{
+
+class TlbMap
+{
+  private:
+    typedef std::map<TlbRange, TlbEntry*> RangeMap;
+    RangeMap tree;
+
+  public:
+    typedef RangeMap::iterator iterator;
+
+    iterator find(const TlbRange &r)
+    {
+        iterator i;
+
+        i = tree.upper_bound(r);
+
+        if (i == tree.begin())
+            // Nothing could match, so return end()
+            return tree.end();
+
+        i--;
+
+        if (r.real != i->first.real)
+            return tree.end();
+        if (!r.real && r.contextId != i->first.contextId)
+            return tree.end();
+        if (r.partitionId != i->first.partitionId)
+            return tree.end();
+        if (i->first.va <= r.va+r.size &&
+            i->first.va+i->first.size >= r.va)
+            return i;
+
+        return tree.end();
+    }
+
+    bool intersect(const TlbRange &r)
+    {
+        iterator i;
+        i = find(r);
+        if (i != tree.end())
+            return true;
+        return false;
+    }
+
+
+    iterator insert(TlbRange &r, TlbEntry *d)
+    {
+        if (intersect(r))
+            return tree.end();
+
+        return tree.insert(std::make_pair<TlbRange,TlbEntry*>(r, d)).first;
+    }
+
+    size_t erase(TlbRange k)
+    {
+        return tree.erase(k);
+    }
+
+    void erase(iterator p)
+    {
+        tree.erase(p);
+    }
+
+    void erase(iterator p, iterator q)
+    {
+        tree.erase(p,q);
+    }
+
+    void clear()
+    {
+        tree.erase(tree.begin(), tree.end());
+    }
+
+    iterator begin()
+    {
+        return tree.begin();
+    }
+
+    iterator end()
+    {
+        return tree.end();
+    }
+
+    size_t size()
+    {
+        return tree.size();
+    }
+
+    bool empty()
+    {
+        return tree.empty();
+    }
+};
+
+};
+
+#endif // __ARCH_SPARC_TLB_MAP_HH__
index bf2b757d6787ec1f083d4a4565644932391f4c14..66679a565797d77a822252b78153082bf96b3c0d 100644 (file)
@@ -33,6 +33,7 @@
 #define __ARCH_SPARC_VTOPHYS_H__
 
 #include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/pagetable.hh"
 
 class ThreadContext;
 class FunctionalPort;
diff --git a/src/base/range_map.hh b/src/base/range_map.hh
new file mode 100644 (file)
index 0000000..17ecb92
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __BASE_RANGE_MAP_HH__
+#define __BASE_RANGE_MAP_HH__
+
+#include "base/range.hh"
+
+#include <map>
+
+template <class T,class V>
+class range_map
+{
+  private:
+    typedef std::map<Range<T>,V> RangeMap;
+    RangeMap tree;
+
+  public:
+    typedef typename RangeMap::iterator iterator;
+
+    template <class U>
+    const iterator find(const Range<U> &r)
+    {
+        iterator i;
+
+        i = tree.upper_bound(r);
+
+        if (i == tree.begin())
+            // Nothing could match, so return end()
+            return tree.end();
+
+        i--;
+
+        if (i->first.start <= r.end && i->first.end >= r.start)
+            return i;
+
+        return tree.end();
+    }
+
+    template <class U>
+    bool intersect(const Range<U> &r)
+    {
+        iterator i;
+        i = find(r);
+        if (i != tree.end())
+            return true;
+        return false;
+    }
+
+
+    template <class U,class W>
+    iterator insert(const Range<U> &r, const W d)
+    {
+        if (intersect(r))
+            return tree.end();
+
+        return tree.insert(std::make_pair<Range<T>,V>(r, d)).first;
+    }
+
+    size_t erase(T k)
+    {
+        return tree.erase(k);
+    }
+
+    void erase(iterator p)
+    {
+        tree.erase(p);
+    }
+
+    void erase(iterator p, iterator q)
+    {
+        tree.erase(p,q);
+    }
+
+    void clear()
+    {
+        tree.erase(tree.begin(), tree.end());
+    }
+
+    iterator begin()
+    {
+        return tree.begin();
+    }
+
+    iterator end()
+    {
+        return tree.end();
+    }
+
+    size_t size()
+    {
+        return tree.size();
+    }
+
+    bool empty()
+    {
+        return tree.empty();
+    }
+};
+
+
+#endif //__BASE_RANGE_MAP_HH__
index e54984fcde1f6d372399a68821eef07efbf5b472..5817b24e05468b0c256ff7c39bf16fd3cb003798 100644 (file)
@@ -95,6 +95,11 @@ class Request
 
     /** The address space ID. */
     int asid;
+    /** The ASI is any -- SPARC ONLY */
+    int asi;
+    /** This request is to a memory mapped register. */
+    bool mmapedReg;
+
     /** The virtual address of the request. */
     Addr vaddr;
 
@@ -215,6 +220,16 @@ class Request
     /** Accessor function for asid.*/
     int getAsid() { assert(validAsidVaddr); return asid; }
 
+    /** Accessor function for asi.*/
+    int getAsi() { assert(validAsidVaddr); return asi; }
+    /** Accessor function for asi.*/
+    void setAsi(int a) { assert(validAsidVaddr); asi = a; }
+
+    /** Accessor function for asi.*/
+    bool getMmapedReg() { assert(validPaddr); return mmapedReg; }
+    /** Accessor function for asi.*/
+    void setMmapedReg(bool r) { assert(validPaddr); mmapedReg = r; }
+
     /** Accessor function to check if sc result is valid. */
     bool scResultValid() { return validScResult; }
     /** Accessor function for store conditional return value.*/
index a2faa206bfa060308cdda75e7e35d4766659743e..8b1ddbfe7fb7847aaed89124f0485621bee7016e 100644 (file)
@@ -42,7 +42,7 @@
 /** uint64_t constant */
 #define ULL(N)         ((uint64_t)N##ULL)
 /** int64_t constant */
-#define LL(N)          (((int64_t)N##LL)
+#define LL(N)          ((int64_t)N##LL)
 
 /** Statistics counter type.  Not much excuse for not using a 64-bit
  * integer here, but if you're desperate and only run short
diff --git a/src/unittest/rangemaptest.cc b/src/unittest/rangemaptest.cc
new file mode 100644 (file)
index 0000000..6fd99c9
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include <iostream>
+#include <cassert>
+#include "sim/host.hh"
+#include "base/range_map.hh"
+
+using namespace std;
+
+int main()
+{
+    range_map<Addr,int> r;
+
+    range_map<Addr,int>::iterator i;
+
+    i = r.insert(RangeIn<Addr>(0,40),5);
+    assert(i != r.end());
+    i = r.insert(RangeIn<Addr>(60,90),3);
+    assert(i != r.end());
+
+    i = r.find(RangeIn(20,30));
+    assert(i != r.end());
+    cout << i->first << " " << i->second << endl;
+
+    i = r.find(RangeIn(55,55));
+    assert(i == r.end());
+}
+
+
+
+
+
+
+
+