From 271b9a5435ac26c836774b25ad1fa68e2351d25a Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 23 Nov 2006 01:42:57 -0500 Subject: [PATCH 1/8] first cut at a sparc tlb 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 --- src/arch/sparc/SConscript | 1 + src/arch/sparc/asi.cc | 98 +++--- src/arch/sparc/asi.hh | 108 +++++-- src/arch/sparc/isa_traits.hh | 29 +- src/arch/sparc/miscregfile.cc | 253 ++++++++++++--- src/arch/sparc/miscregfile.hh | 74 ++++- src/arch/sparc/pagetable.cc | 69 ++++ src/arch/sparc/pagetable.hh | 194 ++++++++++++ src/arch/sparc/regfile.hh | 4 +- src/arch/sparc/tlb.cc | 577 +++++++++++++++++++++++++++++++--- src/arch/sparc/tlb.hh | 139 +++++--- src/arch/sparc/tlb_map.hh | 135 ++++++++ src/arch/sparc/vtophys.hh | 1 + src/base/range_map.hh | 129 ++++++++ src/mem/request.hh | 15 + src/sim/host.hh | 2 +- src/unittest/rangemaptest.cc | 63 ++++ 17 files changed, 1692 insertions(+), 199 deletions(-) create mode 100644 src/arch/sparc/pagetable.cc create mode 100644 src/arch/sparc/pagetable.hh create mode 100644 src/arch/sparc/tlb_map.hh create mode 100644 src/base/range_map.hh create mode 100644 src/unittest/rangemaptest.cc diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 281c166c09..a0a6112de0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -56,6 +56,7 @@ base_sources = Split(''' full_system_sources = Split(''' arguments.cc remote_gdb.cc + pagetable.cc stacktrace.cc system.cc tlb.cc diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc index 00c9e041e3..14e581e433 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -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) - { - return - (asi == ASI_DTLB_DATA_IN_REG) || - (asi == ASI_DTLB_DATA_ACCESS_REG) || - (asi == ASI_DTLB_TAG_READ_REG); - } - bool AsiIsMmu(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 == 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 AsiIsUnPriv(ASI asi) + { + 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); + } + } diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 6677b23dff..bd1696c78f 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -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); }; diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 1433ba3f8c..109fdfae7d 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -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__ diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index d52e3983fe..93737ad013 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -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 diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index f74943256a..a4ce6ca5c7 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -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 index 0000000000..22130d41c5 --- /dev/null +++ b/src/arch/sparc/pagetable.cc @@ -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 §ion) +{ + 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 index 0000000000..21dbad0a33 --- /dev/null +++ b/src/arch/sparc/pagetable.hh @@ -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 §ion); + +}; + + +}; // namespace SparcISA + +#endif // __ARCH_SPARC_PAGE_TABLE_HH__ + diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 9f33435f69..0a09d0f669 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -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(); } diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 0b1a2ff5f4..9b7943ed9d 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -25,55 +25,548 @@ * (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."); - Param 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 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) + 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); + } + + lookupTable.insert(new_entry->range, new_entry);; + + // 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++; + } + +} + + +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; + + // Try to find the entry + i = lookupTable.find(tr); + if (i == lookupTable.end()) { + return NULL; + } + + // 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++; + } + } + + return t; +} + + +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; + + // 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); + } +} + +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); + } + } +} + +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); + } + + if (e == NULL || !e->valid) { + tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, + vaddr & ~BytesInPageMask | context); + if (real) + return new InstructionRealTranslationMiss; + else + return new FastInstructionAccessMMUMiss; + } + + // 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 §ion) +{ + panic("Need to implement unserialize tlb for SPARC\n"); +} + + +DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) + + Param 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 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) } diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 136103f448..824d6494c7 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -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 - { - 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; - } - }; + /** 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 §ion); +}; + +class ITB : public TLB +{ + public: + ITB(const std::string &name, int size) : TLB(name, size) + { + } + + 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 index 0000000000..226ef23a1b --- /dev/null +++ b/src/arch/sparc/tlb_map.hh @@ -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 + +namespace SparcISA +{ + +class TlbMap +{ + private: + typedef std::map 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(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__ diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh index bf2b757d67..66679a5657 100644 --- a/src/arch/sparc/vtophys.hh +++ b/src/arch/sparc/vtophys.hh @@ -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 index 0000000000..17ecb92900 --- /dev/null +++ b/src/base/range_map.hh @@ -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 + +template +class range_map +{ + private: + typedef std::map,V> RangeMap; + RangeMap tree; + + public: + typedef typename RangeMap::iterator iterator; + + template + const iterator find(const Range &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 + bool intersect(const Range &r) + { + iterator i; + i = find(r); + if (i != tree.end()) + return true; + return false; + } + + + template + iterator insert(const Range &r, const W d) + { + if (intersect(r)) + return tree.end(); + + return tree.insert(std::make_pair,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__ diff --git a/src/mem/request.hh b/src/mem/request.hh index e54984fcde..5817b24e05 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -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.*/ diff --git a/src/sim/host.hh b/src/sim/host.hh index a2faa206bf..8b1ddbfe7f 100644 --- a/src/sim/host.hh +++ b/src/sim/host.hh @@ -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 index 0000000000..6fd99c927b --- /dev/null +++ b/src/unittest/rangemaptest.cc @@ -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 +#include +#include "sim/host.hh" +#include "base/range_map.hh" + +using namespace std; + +int main() +{ + range_map r; + + range_map::iterator i; + + i = r.insert(RangeIn(0,40),5); + assert(i != r.end()); + i = r.insert(RangeIn(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()); +} + + + + + + + + From 07e525e8b78fba0ebaf5c50f32fbf30d17051891 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Sun, 26 Nov 2006 11:46:58 -0500 Subject: [PATCH 2/8] Include check for making sure caches are enabled. --HG-- extra : convert_revision : e3902b065db524ebe5bf762e44a840133ccb8d75 --- configs/common/Simulation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 374ff3fc25..e037d03436 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -39,6 +39,9 @@ def setCPUClass(options): if options.timing: TmpClass = TimingSimpleCPU elif options.detailed: + if not options.caches: + print "O3 CPU must be used with caches" + sys.exit(1) TmpClass = DerivO3CPU else: TmpClass = AtomicSimpleCPU From 6bbb86dfa986d9a52e8b46ef3d3795bc8123331a Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 27 Nov 2006 02:16:24 -0500 Subject: [PATCH 3/8] Add TRACING_ON setting for m5.prof. --HG-- extra : convert_revision : ebda49bff30d76d3209acce55458d3f4e29594d3 --- src/SConscript | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SConscript b/src/SConscript index 9d54174ab9..429e1bee1c 100644 --- a/src/SConscript +++ b/src/SConscript @@ -333,6 +333,7 @@ makeEnv('fast', '.fo', strip = True, # Profiled binary makeEnv('prof', '.po', CCFLAGS = Split('-O3 -g -pg'), + CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], LINKFLAGS = '-pg') Return('envList') From 2b5fdf603399c63a9344206f1593b20fcb834013 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Tue, 28 Nov 2006 11:41:08 -0500 Subject: [PATCH 4/8] Remove assertion. It's not needed and messes up writebacks when a 2 level cache is used in a uniprocessor setting. --HG-- extra : convert_revision : 020a9799cd7177fdb85a767701d6fcb8cf018827 --- src/mem/cache/coherence/uni_coherence.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mem/cache/coherence/uni_coherence.cc b/src/mem/cache/coherence/uni_coherence.cc index 5813a0281b..ea615d70a5 100644 --- a/src/mem/cache/coherence/uni_coherence.cc +++ b/src/mem/cache/coherence/uni_coherence.cc @@ -94,10 +94,6 @@ UniCoherence::handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, bool UniCoherence::propogateInvalidate(PacketPtr pkt, bool isTiming) { - //Make sure we don't snoop a write - //we are expecting writeInvalidates on the snoop port of a uni-coherent cache - assert(!(!pkt->isInvalidate() && pkt->isWrite())); - if (pkt->isInvalidate()) { /* Temp Fix for now, forward all invalidates up as functional accesses */ if (isTiming) { From ed78fc257b7e55a94cae6a54a0eacf7090ed7f26 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 28 Nov 2006 16:02:13 -0500 Subject: [PATCH 5/8] add 2.0b2 release notes --HG-- extra : convert_revision : ce34f8086f682cc732bf868f6b9700e42c604ca3 --- RELEASE_NOTES | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 39086de890..03eec3aabe 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,3 +1,19 @@ +Nov. 28, 2006: m5_2.0_beta2 +-------------------- +Bug fixes since beta 1: +1. Many cache issues resolved +2. Uni-coherence fixes in full-system +3. LL/SC Support +4. Draining/Switchover +5. Functional Accesses +6. Bus now has real timing +7. Single config file fro all SpecCPU2000 benchmarks +8. Several other minor bug fixes and enhancements + +Outstading issues for 2.0 release: +1. Simulator performance fixes for memory system/caches +2. Multiprocessor linux boot using the detailed O3 CPU model + Aug. 25, 2006: m5_2.0_beta patch 1 -------------------- Handful of minor bug fixes for m5_2.0_beta, From 610064c98a16a7c9cdc51e4e4c15cd5c1d2c2e4f Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Wed, 29 Nov 2006 11:50:03 -0500 Subject: [PATCH 6/8] Add in O3CPU to default CPU list. --HG-- extra : convert_revision : 4aaaae058cb763580ea0b9019d4a9346938121d4 --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index d8851f0916..50ca2d6e4a 100644 --- a/SConstruct +++ b/SConstruct @@ -344,7 +344,7 @@ sticky_opts.AddOptions( # values (more than one value) not to be able to be restored from # a saved option file. If this causes trouble then upgrade to # scons 0.96.90 or later. - ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU', + ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU', env['ALL_CPU_LIST']), BoolOption('ALPHA_TLASER', 'Model Alpha TurboLaser platform (vs. Tsunami)', False), From c96160cef541b1b4b3e58bf0c56612ef17250e46 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Wed, 29 Nov 2006 16:07:55 -0500 Subject: [PATCH 7/8] Change the connecting of the physPort and virtPort to the memory object below the CPU to happen every time activateContext is called. The overhead is probably a little higher than necessary, but allows these connections to properly be made when there are CPUs that are inactive until they are switched in. Right now this introduces a minor memory leak as old physPorts and virtPorts are not deleted when new ones are created. A flyspray task has been created for this issue. It can not be resolved until we determine how the bus will handle giving out ID's to functional ports that may be deleted. src/cpu/o3/cpu.cc: src/cpu/simple/atomic.cc: src/cpu/simple/timing.cc: Change the setup of the physPort and virtPort to instead happen every time the CPU has a context activated. This is a little high overhead, but keeps it working correctly when the CPU does not have a physical memory attached to it until it switches in (like the case of switch CPUs). src/cpu/o3/thread_context.hh: Change function from being called at init() to just being called whenever the memory ports need to be connected. src/cpu/o3/thread_context_impl.hh: Update this to not delete the port if it's the same as the virtPort. src/cpu/thread_context.hh: Change function from being called at init() to whenever the memory ports need to be connected. src/cpu/thread_state.cc: Instead of initializing the ports, simply connect them, deleting any old ports that might exist. This allows these functions to be called multiple times. src/cpu/thread_state.hh: Ports are no longer initialized, but rather connected at context activation time. --HG-- extra : convert_revision : e399ce5dfbd6ad658c953a7c9c7b69b89a70219e --- src/cpu/o3/cpu.cc | 8 ++++++-- src/cpu/o3/thread_context.hh | 2 +- src/cpu/o3/thread_context_impl.hh | 6 ++++-- src/cpu/simple/atomic.cc | 10 +++++++--- src/cpu/simple/timing.cc | 10 +++++++--- src/cpu/thread_context.hh | 4 ++-- src/cpu/thread_state.cc | 16 +++++++++++----- src/cpu/thread_state.hh | 6 +++--- 8 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 3dc353a9fb..a5a00015f4 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -497,8 +497,6 @@ FullO3CPU::init() } #if FULL_SYSTEM - src_tc->init(); - TheISA::initCPU(src_tc, src_tc->readCpuId()); #endif } @@ -554,6 +552,12 @@ template void FullO3CPU::activateContext(int tid, int delay) { +#if FULL_SYSTEM + // Connect the ThreadContext's memory ports (Functional/Virtual + // Ports) + threadContexts[tid]->connectMemPorts(); +#endif + // Needs to set each stage to running as well. if (delay){ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 031f36480a..390569c3d0 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -92,7 +92,7 @@ class O3ThreadContext : public ThreadContext void delVirtPort(VirtualPort *vp); - virtual void init() { thread->init(); } + virtual void connectMemPorts() { thread->connectMemPorts(); } #else virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 0180756e38..afebf294f3 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -101,8 +101,10 @@ template void O3ThreadContext::delVirtPort(VirtualPort *vp) { - delete vp->getPeer(); - delete vp; + if (vp != thread->getVirtPort()) { + delete vp->getPeer(); + delete vp; + } } #endif diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index cd335e36da..8cfe2ee83e 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -77,9 +77,6 @@ AtomicSimpleCPU::init() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; - // initialize the mem pointers - tc->init(); - // initialize CPU, including PC TheISA::initCPU(tc, tc->readCpuId()); } @@ -240,6 +237,13 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) assert(!tickEvent.scheduled()); notIdleFraction++; + +#if FULL_SYSTEM + // Connect the ThreadContext's memory ports (Functional/Virtual + // Ports) + tc->connectMemPorts(); +#endif + //Make sure ticks are still on multiples of cycles tickEvent.schedule(nextCycle(curTick + cycles(delay))); _status = Running; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index aa23a00e8a..dfffb0b1fa 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -59,9 +59,6 @@ TimingSimpleCPU::init() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; - // initialize the mem pointers - tc->init(); - // initialize CPU, including PC TheISA::initCPU(tc, tc->readCpuId()); } @@ -241,6 +238,13 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; + +#if FULL_SYSTEM + // Connect the ThreadContext's memory ports (Functional/Virtual + // Ports) + tc->connectMemPorts(); +#endif + // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper(this, false); diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index baeb7a8bed..bb9cc9e16e 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -134,7 +134,7 @@ class ThreadContext virtual void delVirtPort(VirtualPort *vp) = 0; - virtual void init() = 0; + virtual void connectMemPorts() = 0; #else virtual TranslatingPort *getMemPort() = 0; @@ -308,7 +308,7 @@ class ProxyThreadContext : public ThreadContext void delVirtPort(VirtualPort *vp) { return actualTC->delVirtPort(vp); } - void init() {actualTC->init(); } + void connectMemPorts() { actualTC->connectMemPorts(); } #else TranslatingPort *getMemPort() { return actualTC->getMemPort(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 9cac4fd26b..93dd1e2eb0 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -113,23 +113,29 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) #if FULL_SYSTEM void -ThreadState::init() +ThreadState::connectMemPorts() { - initPhysPort(); - initVirtPort(); + connectPhysPort(); + connectVirtPort(); } void -ThreadState::initPhysPort() +ThreadState::connectPhysPort() { + // @todo: For now this disregards any older port that may have + // already existed. Fix this memory leak once the bus port IDs + // for functional ports is resolved. physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); connectToMemFunc(physPort); } void -ThreadState::initVirtPort() +ThreadState::connectVirtPort() { + // @todo: For now this disregards any older port that may have + // already existed. Fix this memory leak once the bus port IDs + // for functional ports is resolved. virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); connectToMemFunc(virtPort); diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 1844be8b72..4f878db1f2 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -91,11 +91,11 @@ struct ThreadState { Tick readLastSuspend() { return lastSuspend; } #if FULL_SYSTEM - void init(); + void connectMemPorts(); - void initPhysPort(); + void connectPhysPort(); - void initVirtPort(); + void connectVirtPort(); void dumpFuncProfile(); From b2eecd643c1706d0d070568d5370aafa3910c104 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 29 Nov 2006 17:11:10 -0500 Subject: [PATCH 8/8] Add support for mmapped iprs to atomic cpu src/arch/SConscript: add mmaped_ipr.hh to switch headers src/arch/sparc/asi.hh: make ASI_IMPLICT=0 so by default nothing needs to be done src/arch/sparc/miscregfile.hh: miscregfile no longer needs to include asi.hh src/arch/sparc/tlb.cc: src/arch/sparc/tlb.hh: implement panic instructions for mmaped ipr reads src/cpu/simple/atomic.cc: add check for mmaped iprs and handle them if it exists src/mem/request.hh: allocate space in the flags for mmaped iprs. Put in in the first 8 bits so that by default its fast. Move the other flags up 8 bits --HG-- extra : convert_revision : 31255b0494588c4d06a727fe35241121d741b115 --- src/arch/SConscript | 1 + src/arch/alpha/mmaped_ipr.hh | 61 +++++++++++++++++++++++++++++++++ src/arch/mips/mmaped_ipr.hh | 61 +++++++++++++++++++++++++++++++++ src/arch/sparc/asi.hh | 2 +- src/arch/sparc/miscregfile.hh | 1 - src/arch/sparc/mmaped_ipr.hh | 63 +++++++++++++++++++++++++++++++++++ src/arch/sparc/tlb.cc | 24 +++++++++++-- src/arch/sparc/tlb.hh | 3 ++ src/cpu/simple/atomic.cc | 14 ++++++-- src/mem/request.hh | 42 +++++++++++++---------- 10 files changed, 246 insertions(+), 26 deletions(-) create mode 100644 src/arch/alpha/mmaped_ipr.hh create mode 100644 src/arch/mips/mmaped_ipr.hh create mode 100644 src/arch/sparc/mmaped_ipr.hh diff --git a/src/arch/SConscript b/src/arch/SConscript index bbe3c4e3ac..74be5f8d1c 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -53,6 +53,7 @@ isa_switch_hdrs = Split(''' isa_traits.hh kernel_stats.hh locked_mem.hh + mmaped_ipr.hh process.hh regfile.hh remote_gdb.hh diff --git a/src/arch/alpha/mmaped_ipr.hh b/src/arch/alpha/mmaped_ipr.hh new file mode 100644 index 0000000000..2b4ba87452 --- /dev/null +++ b/src/arch/alpha/mmaped_ipr.hh @@ -0,0 +1,61 @@ +/* + * 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_ALPHA_MMAPED_IPR_HH__ +#define __ARCH_ALPHA_MMAPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "mem/packet.hh" + + +namespace AlphaISA +{ +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + panic("No handleIprRead implementation in Alpha\n"); +} + + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + panic("No handleIprWrite implementation in Alpha\n"); +} + + +} // namespace AlphaISA + +#endif diff --git a/src/arch/mips/mmaped_ipr.hh b/src/arch/mips/mmaped_ipr.hh new file mode 100644 index 0000000000..041c76fdc5 --- /dev/null +++ b/src/arch/mips/mmaped_ipr.hh @@ -0,0 +1,61 @@ +/* + * 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_MIPS_MMAPED_IPR_HH__ +#define __ARCH_MIPS_MMAPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "mem/packet.hh" + + +namespace MipsISA +{ +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprRead in MIPS\n"); +} + + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprWrite in MIPS\n"); +} + + +} // namespace MipsISA + +#endif diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index bd1696c78f..a0d667cf3b 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -35,6 +35,7 @@ namespace SparcISA { enum ASI { + ASI_IMPLICIT = 0x00, /* Priveleged ASIs */ //0x00-0x03 implementation dependent ASI_NUCLEUS = 0x4, @@ -242,7 +243,6 @@ namespace SparcISA ASI_BLK_SL = 0xF9, ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL, //0xFA-0xFF implementation dependent - ASI_IMPLICIT = 0xFF, MAX_ASI = 0xFF }; diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index a4ce6ca5c7..9cfe3a8cfe 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -32,7 +32,6 @@ #ifndef __ARCH_SPARC_MISCREGFILE_HH__ #define __ARCH_SPARC_MISCREGFILE_HH__ -#include "arch/sparc/asi.hh" #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/types.hh" diff --git a/src/arch/sparc/mmaped_ipr.hh b/src/arch/sparc/mmaped_ipr.hh new file mode 100644 index 0000000000..d87d127b07 --- /dev/null +++ b/src/arch/sparc/mmaped_ipr.hh @@ -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 + */ + +#ifndef __ARCH_SPARC_MMAPED_IPR_HH__ +#define __ARCH_SPARC_MMAPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "cpu/thread_context.hh" +#include "mem/packet.hh" +#include "arch/sparc/tlb.hh" + + +namespace SparcISA +{ +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + return xc->getDTBPtr()->doMmuRegRead(xc, pkt); +} + + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + return xc->getDTBPtr()->doMmuRegWrite(xc, pkt); +} + + +} // namespace SparcISA + +#endif diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 9b7943ed9d..5fde4d36dd 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -508,13 +508,31 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) req->setPaddr(e->pte.paddr() & ~e->pte.size() | req->getVaddr() & e->pte.size()); return NoFault; - /*** End of normal Path ***/ + /** Normal flow ends here. */ -handleMmuRegAccess: handleScratchRegAccess: - panic("How are we ever going to deal with this?\n"); + if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + return new DataAccessException; + } +handleMmuRegAccess: + req->setMmapedIpr(true); + req->setPaddr(req->getVaddr()); + return NoFault; }; +Tick +DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) +{ + panic("need to implement DTB::doMmuRegRead()\n"); +} + +Tick +DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) +{ + panic("need to implement DTB::doMmuRegWrite()\n"); +} + void TLB::serialize(std::ostream &os) { diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 824d6494c7..2df4fe4c89 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -38,6 +38,7 @@ #include "sim/sim_object.hh" class ThreadContext; +class Packet; namespace SparcISA { @@ -142,6 +143,8 @@ class DTB : public TLB } Fault translate(RequestPtr &req, ThreadContext *tc, bool write); + Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); + Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); private: void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index cd335e36da..b7699c4050 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -29,6 +29,7 @@ */ #include "arch/locked_mem.hh" +#include "arch/mmaped_ipr.hh" #include "arch/utility.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" @@ -285,7 +286,10 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) if (fault == NoFault) { pkt->reinitFromRequest(); - dcache_latency = dcachePort.sendAtomic(pkt); + if (req->isMmapedIpr()) + dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt); + else + dcache_latency = dcachePort.sendAtomic(pkt); dcache_access = true; assert(pkt->result == Packet::Success); @@ -372,11 +376,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } if (do_access) { - data = htog(data); pkt->reinitFromRequest(); pkt->dataStatic(&data); - dcache_latency = dcachePort.sendAtomic(pkt); + if (req->isMmapedIpr()) { + dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt); + } else { + data = htog(data); + dcache_latency = dcachePort.sendAtomic(pkt); + } dcache_access = true; assert(pkt->result == Packet::Success); diff --git a/src/mem/request.hh b/src/mem/request.hh index 5817b24e05..b01c024410 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -49,26 +49,28 @@ class Request; typedef Request* RequestPtr; +/** ASI information for this request if it exsits. */ +const uint32_t ASI_BITS = 0x000FF; /** The request is a Load locked/store conditional. */ -const unsigned LOCKED = 0x001; +const uint32_t LOCKED = 0x00100; /** The virtual address is also the physical address. */ -const unsigned PHYSICAL = 0x002; +const uint32_t PHYSICAL = 0x00200; /** The request is an ALPHA VPTE pal access (hw_ld). */ -const unsigned VPTE = 0x004; +const uint32_t VPTE = 0x00400; /** Use the alternate mode bits in ALPHA. */ -const unsigned ALTMODE = 0x008; +const uint32_t ALTMODE = 0x00800; /** The request is to an uncacheable address. */ -const unsigned UNCACHEABLE = 0x010; +const uint32_t UNCACHEABLE = 0x01000; /** The request should not cause a page fault. */ -const unsigned NO_FAULT = 0x020; +const uint32_t NO_FAULT = 0x02000; /** The request should be prefetched into the exclusive state. */ -const unsigned PF_EXCLUSIVE = 0x100; +const uint32_t PF_EXCLUSIVE = 0x10000; /** The request should be marked as LRU. */ -const unsigned EVICT_NEXT = 0x200; +const uint32_t EVICT_NEXT = 0x20000; /** The request should ignore unaligned access faults */ -const unsigned NO_ALIGN_FAULT = 0x400; +const uint32_t NO_ALIGN_FAULT = 0x40000; /** The request was an instruction read. */ -const unsigned INST_READ = 0x800; +const uint32_t INST_READ = 0x80000; class Request { @@ -95,10 +97,9 @@ 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; + bool mmapedIpr; /** The virtual address of the request. */ Addr vaddr; @@ -169,6 +170,7 @@ class Request validAsidVaddr = false; validPC = false; validScResult = false; + mmapedIpr = false; } /** @@ -186,6 +188,7 @@ class Request validAsidVaddr = true; validPC = true; validScResult = false; + mmapedIpr = false; } /** Set just the physical address. This should only be used to @@ -221,14 +224,17 @@ class Request 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; } + uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; } /** Accessor function for asi.*/ - bool getMmapedReg() { assert(validPaddr); return mmapedReg; } + void setAsi(uint8_t a) + { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; } + /** Accessor function for asi.*/ - void setMmapedReg(bool r) { assert(validPaddr); mmapedReg = r; } + bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; } + + /** Accessor function for asi.*/ + void setMmapedIpr(bool r) { assert(validPaddr); mmapedIpr = r; } /** Accessor function to check if sc result is valid. */ bool scResultValid() { return validScResult; }