Merge zizzer:/bk/sparcfs

into  zower.eecs.umich.edu:/eecshome/m5/newmemmid

src/arch/sparc/isa_traits.hh:
src/arch/sparc/miscregfile.hh:
    hand merge

--HG--
extra : convert_revision : 34f50dc5e6e22096cb2c08b5888f2b0fcd418f3e
This commit is contained in:
Gabe Black 2006-11-29 17:34:20 -05:00
commit 5bdf4400b2
34 changed files with 1986 additions and 238 deletions

View file

@ -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,

View file

@ -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),

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View 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)
{
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);
}
}

View 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__
@ -34,6 +35,7 @@
namespace SparcISA
{
enum ASI {
ASI_IMPLICIT = 0x00,
/* Priveleged ASIs */
//0x00-0x03 implementation dependent
ASI_NUCLEUS = 0x4,
@ -53,64 +55,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,
@ -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);
};

View 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__
@ -39,10 +40,6 @@ class StaticInstPtr;
namespace BigEndianGuest {}
#if FULL_SYSTEM
#include "arch/sparc/isa_fullsys_traits.hh"
#endif
namespace SparcISA
{
class RegFile;
@ -94,6 +91,30 @@ namespace SparcISA
const int BranchPredAddrShiftAmt = 2;
StaticInstPtr decodeInst(ExtMachInst);
#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__

View file

@ -102,8 +102,32 @@ void MiscRegFile::clear()
//This is set this way in Legion for some reason
strandStatusReg = 0x50000;
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)
@ -187,6 +211,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);
}
@ -333,35 +420,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)
{
@ -383,11 +530,9 @@ void MiscRegFile::setRegWithEffect(int miscReg,
break;
case MISCREG_PSTATE:
pstate = val & PSTATE_MASK;
setImplicitAsis();
return;
case MISCREG_TL:
tl = val;
setImplicitAsis();
return;
case MISCREG_CWP:
tc->changeRegFileContext(CONTEXT_CWP, val);
@ -490,8 +635,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)
@ -521,12 +686,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

View file

@ -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"
@ -93,6 +92,40 @@ namespace SparcISA
/** Floating Point Status Register */
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
MISCREG_NUMMISCREGS
};
@ -150,8 +183,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
@ -192,14 +249,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);
@ -213,7 +270,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();
};
}

View file

@ -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

View file

@ -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};
}

194
src/arch/sparc/pagetable.hh Normal file
View file

@ -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__

View 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();
}

View file

@ -25,55 +25,566 @@
* (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<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)
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;
/** Normal flow ends here. */
handleScratchRegAccess:
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)
{
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)
}

View file

@ -31,57 +31,127 @@
#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"
#include "sim/sim_object.hh"
class ThreadContext;
class Packet;
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 &section);
};
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);
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
private:
void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
};
}
#endif // __ARCH_SPARC_TLB_HH__

135
src/arch/sparc/tlb_map.hh Normal file
View file

@ -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__

View 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;

129
src/base/range_map.hh Normal file
View file

@ -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__

View file

@ -497,8 +497,6 @@ FullO3CPU<Impl>::init()
}
#if FULL_SYSTEM
src_tc->init();
TheISA::initCPU(src_tc, src_tc->readCpuId());
#endif
}
@ -554,6 +552,12 @@ template <class Impl>
void
FullO3CPU<Impl>::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 "

View file

@ -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(); }

View file

@ -101,8 +101,10 @@ template <class Impl>
void
O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp)
{
delete vp->getPeer();
delete vp;
if (vp != thread->getVirtPort()) {
delete vp->getPeer();
delete vp;
}
}
#endif

View file

@ -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"
@ -77,9 +78,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 +238,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;
@ -285,7 +290,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 +380,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);

View file

@ -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<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);

View file

@ -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(); }

View file

@ -113,23 +113,29 @@ ThreadState::unserialize(Checkpoint *cp, const std::string &section)
#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);

View file

@ -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();

View file

@ -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) {

View file

@ -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,6 +97,10 @@ class Request
/** The address space ID. */
int asid;
/** This request is to a memory mapped register. */
bool mmapedIpr;
/** The virtual address of the request. */
Addr vaddr;
@ -164,6 +170,7 @@ class Request
validAsidVaddr = false;
validPC = false;
validScResult = false;
mmapedIpr = false;
}
/**
@ -181,6 +188,7 @@ class Request
validAsidVaddr = true;
validPC = true;
validScResult = false;
mmapedIpr = false;
}
/** Set just the physical address. This should only be used to
@ -215,6 +223,19 @@ class Request
/** Accessor function for asid.*/
int getAsid() { assert(validAsidVaddr); return asid; }
/** Accessor function for asi.*/
uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; }
/** Accessor function for asi.*/
void setAsi(uint8_t a)
{ assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; }
/** Accessor function for asi.*/
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; }
/** Accessor function for store conditional return value.*/

View 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

View file

@ -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());
}