diff options
author | Kevin Lim <ktlim@umich.edu> | 2006-11-10 12:44:15 -0500 |
---|---|---|
committer | Kevin Lim <ktlim@umich.edu> | 2006-11-10 12:44:15 -0500 |
commit | b5e68fb54677f601bb00c23af52db8fd6571301f (patch) | |
tree | dc3c17198ba4010d907ecd8cb7189aa7959948d4 /src/arch/sparc | |
parent | 264f9ce374ff4689fec3c32d8289fe76b0b65078 (diff) | |
parent | 9ef51f2dbaba88c10366d708f0ca872bb39064e4 (diff) | |
download | gem5-b5e68fb54677f601bb00c23af52db8fd6571301f.tar.xz |
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem
--HG--
extra : convert_revision : 0c2db1e1b5fdb91c1ac5705ab872a6bfb575a67a
Diffstat (limited to 'src/arch/sparc')
29 files changed, 2431 insertions, 1297 deletions
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index e317502e0..281c166c0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -54,7 +54,11 @@ base_sources = Split(''' # Full-system sources full_system_sources = Split(''' - ua2005.cc + arguments.cc + remote_gdb.cc + stacktrace.cc + system.cc + tlb.cc vtophys.cc ''') diff --git a/src/arch/sparc/arguments.cc b/src/arch/sparc/arguments.cc new file mode 100644 index 000000000..44adf4a15 --- /dev/null +++ b/src/arch/sparc/arguments.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003-2005 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: Nathan Binkert + */ + +#include "arch/sparc/arguments.hh" +#include "arch/sparc/vtophys.hh" +#include "cpu/thread_context.hh" +#include "mem/vport.hh" + +using namespace SparcISA; + +Arguments::Data::~Data() +{ + while (!data.empty()) { + delete [] data.front(); + data.pop_front(); + } +} + +char * +Arguments::Data::alloc(size_t size) +{ + char *buf = new char[size]; + data.push_back(buf); + return buf; +} + +uint64_t +Arguments::getArg(bool fp) +{ + //The caller uses %o0-%05 for the first 6 arguments even if their floating + //point. Double precision floating point values take two registers/args. + //Quads, structs, and unions are passed as pointers. All arguments beyond + //the sixth are passed on the stack past the 16 word window save area, + //space for the struct/union return pointer, and space reserved for the + //first 6 arguments which the caller may use but doesn't have to. + if (number < 6) { + return tc->readIntReg(8 + number); + } else { + Addr sp = tc->readIntReg(14); + VirtualPort *vp = tc->getVirtPort(tc); + uint64_t arg = vp->read<uint64_t>(sp + 92 + (number-6) * sizeof(uint64_t)); + tc->delVirtPort(vp); + return arg; + } +} + diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh new file mode 100644 index 000000000..8f925dd25 --- /dev/null +++ b/src/arch/sparc/arguments.hh @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2003-2005 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: Nathan Binkert + */ + +#ifndef __ARCH_SPARC_ARGUMENTS_HH__ +#define __ARCH_SPARC_ARGUMENTS_HH__ + +#include <assert.h> + +#include "arch/sparc/vtophys.hh" +#include "base/refcnt.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace SparcISA { + +class Arguments +{ + protected: + ThreadContext *tc; + int number; + uint64_t getArg(bool fp = false); + + protected: + class Data : public RefCounted + { + public: + Data(){} + ~Data(); + + private: + std::list<char *> data; + + public: + char *alloc(size_t size); + }; + + RefCountingPtr<Data> data; + + public: + Arguments(ThreadContext *ctx, int n = 0) + : tc(ctx), number(n), data(NULL) + { assert(number >= 0); data = new Data;} + Arguments(const Arguments &args) + : tc(args.tc), number(args.number), data(args.data) {} + ~Arguments() {} + + ThreadContext *getThreadContext() const { return tc; } + + const Arguments &operator=(const Arguments &args) { + tc = args.tc; + number = args.number; + data = args.data; + return *this; + } + + Arguments &operator++() { + ++number; + assert(number >= 0); + return *this; + } + + Arguments operator++(int) { + Arguments args = *this; + ++number; + assert(number >= 0); + return args; + } + + Arguments &operator--() { + --number; + assert(number >= 0); + return *this; + } + + Arguments operator--(int) { + Arguments args = *this; + --number; + assert(number >= 0); + return args; + } + + const Arguments &operator+=(int index) { + number += index; + assert(number >= 0); + return *this; + } + + const Arguments &operator-=(int index) { + number -= index; + assert(number >= 0); + return *this; + } + + Arguments operator[](int index) { + return Arguments(tc, index); + } + + template <class T> + operator T() { + assert(sizeof(T) <= sizeof(uint64_t)); + T data = static_cast<T>(getArg()); + return data; + } + + template <class T> + operator T *() { + T *buf = (T *)data->alloc(sizeof(T)); + CopyData(tc, buf, getArg(), sizeof(T)); + return buf; + } + + operator char *() { + char *buf = data->alloc(2048); + CopyStringOut(tc, buf, getArg(), 2048); + return buf; + } +}; + +}; // namespace SparcISA + +#endif // __ARCH_SPARC_ARGUMENTS_HH__ diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 876567225..6677b23df 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -219,4 +219,4 @@ namespace SparcISA }; -#endif // __ARCH_SPARC_TLB_HH__ +#endif // __ARCH_SPARC_ASI_HH__ diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 2c8da44c5..57ee040f1 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -33,12 +33,14 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" -#include "arch/sparc/process.hh" +#include "arch/sparc/types.hh" #include "base/bitfield.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #if !FULL_SYSTEM +#include "arch/sparc/process.hh" #include "mem/page_table.hh" #include "sim/process.hh" #endif @@ -48,214 +50,352 @@ using namespace std; namespace SparcISA { -FaultName InternalProcessorError::_name = "intprocerr"; -TrapType InternalProcessorError::_trapType = 0x029; -FaultPriority InternalProcessorError::_priority = 4; -FaultStat InternalProcessorError::_count; - -FaultName MemAddressNotAligned::_name = "unalign"; -TrapType MemAddressNotAligned::_trapType = 0x034; -FaultPriority MemAddressNotAligned::_priority = 10; -FaultStat MemAddressNotAligned::_count; - -FaultName PowerOnReset::_name = "pow_reset"; -TrapType PowerOnReset::_trapType = 0x001; -FaultPriority PowerOnReset::_priority = 0; -FaultStat PowerOnReset::_count; - -FaultName WatchDogReset::_name = "watch_dog_reset"; -TrapType WatchDogReset::_trapType = 0x002; -FaultPriority WatchDogReset::_priority = 1; -FaultStat WatchDogReset::_count; - -FaultName ExternallyInitiatedReset::_name = "extern_reset"; -TrapType ExternallyInitiatedReset::_trapType = 0x003; -FaultPriority ExternallyInitiatedReset::_priority = 1; -FaultStat ExternallyInitiatedReset::_count; - -FaultName SoftwareInitiatedReset::_name = "software_reset"; -TrapType SoftwareInitiatedReset::_trapType = 0x004; -FaultPriority SoftwareInitiatedReset::_priority = 1; -FaultStat SoftwareInitiatedReset::_count; - -FaultName REDStateException::_name = "red_counte"; -TrapType REDStateException::_trapType = 0x005; -FaultPriority REDStateException::_priority = 1; -FaultStat REDStateException::_count; - -FaultName InstructionAccessException::_name = "inst_access"; -TrapType InstructionAccessException::_trapType = 0x008; -FaultPriority InstructionAccessException::_priority = 5; -FaultStat InstructionAccessException::_count; - -FaultName InstructionAccessMMUMiss::_name = "inst_mmu"; -TrapType InstructionAccessMMUMiss::_trapType = 0x009; -FaultPriority InstructionAccessMMUMiss::_priority = 2; -FaultStat InstructionAccessMMUMiss::_count; - -FaultName InstructionAccessError::_name = "inst_error"; -TrapType InstructionAccessError::_trapType = 0x00A; -FaultPriority InstructionAccessError::_priority = 3; -FaultStat InstructionAccessError::_count; - -FaultName IllegalInstruction::_name = "illegal_inst"; -TrapType IllegalInstruction::_trapType = 0x010; -FaultPriority IllegalInstruction::_priority = 7; -FaultStat IllegalInstruction::_count; - -FaultName PrivilegedOpcode::_name = "priv_opcode"; -TrapType PrivilegedOpcode::_trapType = 0x011; -FaultPriority PrivilegedOpcode::_priority = 6; -FaultStat PrivilegedOpcode::_count; - -FaultName UnimplementedLDD::_name = "unimp_ldd"; -TrapType UnimplementedLDD::_trapType = 0x012; -FaultPriority UnimplementedLDD::_priority = 6; -FaultStat UnimplementedLDD::_count; - -FaultName UnimplementedSTD::_name = "unimp_std"; -TrapType UnimplementedSTD::_trapType = 0x013; -FaultPriority UnimplementedSTD::_priority = 6; -FaultStat UnimplementedSTD::_count; - -FaultName FpDisabled::_name = "fp_disabled"; -TrapType FpDisabled::_trapType = 0x020; -FaultPriority FpDisabled::_priority = 8; -FaultStat FpDisabled::_count; - -FaultName FpExceptionIEEE754::_name = "fp_754"; -TrapType FpExceptionIEEE754::_trapType = 0x021; -FaultPriority FpExceptionIEEE754::_priority = 11; -FaultStat FpExceptionIEEE754::_count; - -FaultName FpExceptionOther::_name = "fp_other"; -TrapType FpExceptionOther::_trapType = 0x022; -FaultPriority FpExceptionOther::_priority = 11; -FaultStat FpExceptionOther::_count; - -FaultName TagOverflow::_name = "tag_overflow"; -TrapType TagOverflow::_trapType = 0x023; -FaultPriority TagOverflow::_priority = 14; -FaultStat TagOverflow::_count; - -FaultName DivisionByZero::_name = "div_by_zero"; -TrapType DivisionByZero::_trapType = 0x028; -FaultPriority DivisionByZero::_priority = 15; -FaultStat DivisionByZero::_count; - -FaultName DataAccessException::_name = "data_access"; -TrapType DataAccessException::_trapType = 0x030; -FaultPriority DataAccessException::_priority = 12; -FaultStat DataAccessException::_count; - -FaultName DataAccessMMUMiss::_name = "data_mmu"; -TrapType DataAccessMMUMiss::_trapType = 0x031; -FaultPriority DataAccessMMUMiss::_priority = 12; -FaultStat DataAccessMMUMiss::_count; - -FaultName DataAccessError::_name = "data_error"; -TrapType DataAccessError::_trapType = 0x032; -FaultPriority DataAccessError::_priority = 12; -FaultStat DataAccessError::_count; - -FaultName DataAccessProtection::_name = "data_protection"; -TrapType DataAccessProtection::_trapType = 0x033; -FaultPriority DataAccessProtection::_priority = 12; -FaultStat DataAccessProtection::_count; - -FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf"; -TrapType LDDFMemAddressNotAligned::_trapType = 0x035; -FaultPriority LDDFMemAddressNotAligned::_priority = 10; -FaultStat LDDFMemAddressNotAligned::_count; - -FaultName STDFMemAddressNotAligned::_name = "unalign_stdf"; -TrapType STDFMemAddressNotAligned::_trapType = 0x036; -FaultPriority STDFMemAddressNotAligned::_priority = 10; -FaultStat STDFMemAddressNotAligned::_count; - -FaultName PrivilegedAction::_name = "priv_action"; -TrapType PrivilegedAction::_trapType = 0x037; -FaultPriority PrivilegedAction::_priority = 11; -FaultStat PrivilegedAction::_count; - -FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf"; -TrapType LDQFMemAddressNotAligned::_trapType = 0x038; -FaultPriority LDQFMemAddressNotAligned::_priority = 10; -FaultStat LDQFMemAddressNotAligned::_count; - -FaultName STQFMemAddressNotAligned::_name = "unalign_stqf"; -TrapType STQFMemAddressNotAligned::_trapType = 0x039; -FaultPriority STQFMemAddressNotAligned::_priority = 10; -FaultStat STQFMemAddressNotAligned::_count; - -FaultName AsyncDataError::_name = "async_data"; -TrapType AsyncDataError::_trapType = 0x040; -FaultPriority AsyncDataError::_priority = 2; -FaultStat AsyncDataError::_count; - -FaultName CleanWindow::_name = "clean_win"; -TrapType CleanWindow::_trapType = 0x024; -FaultPriority CleanWindow::_priority = 10; -FaultStat CleanWindow::_count; - -//The enumerated faults - -FaultName InterruptLevelN::_name = "interrupt_n"; -TrapType InterruptLevelN::_baseTrapType = 0x041; -FaultStat InterruptLevelN::_count; - -FaultName SpillNNormal::_name = "spill_n_normal"; -TrapType SpillNNormal::_baseTrapType = 0x080; -FaultPriority SpillNNormal::_priority = 9; -FaultStat SpillNNormal::_count; - -FaultName SpillNOther::_name = "spill_n_other"; -TrapType SpillNOther::_baseTrapType = 0x0A0; -FaultPriority SpillNOther::_priority = 9; -FaultStat SpillNOther::_count; - -FaultName FillNNormal::_name = "fill_n_normal"; -TrapType FillNNormal::_baseTrapType = 0x0C0; -FaultPriority FillNNormal::_priority = 9; -FaultStat FillNNormal::_count; - -FaultName FillNOther::_name = "fill_n_other"; -TrapType FillNOther::_baseTrapType = 0x0E0; -FaultPriority FillNOther::_priority = 9; -FaultStat FillNOther::_count; - -FaultName TrapInstruction::_name = "trap_inst_n"; -TrapType TrapInstruction::_baseTrapType = 0x100; -FaultPriority TrapInstruction::_priority = 16; -FaultStat TrapInstruction::_count; +template<> SparcFaultBase::FaultVals + SparcFault<PowerOnReset>::vals = + {"power_on_reset", 0x001, 0, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<WatchDogReset>::vals = + {"watch_dog_reset", 0x002, 120, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<ExternallyInitiatedReset>::vals = + {"externally_initiated_reset", 0x003, 110, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<SoftwareInitiatedReset>::vals = + {"software_initiated_reset", 0x004, 130, {SH, SH, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<REDStateException>::vals = + {"RED_state_exception", 0x005, 1, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<StoreError>::vals = + {"store_error", 0x007, 201, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<InstructionAccessException>::vals = + {"instruction_access_exception", 0x008, 300, {H, H, H}}; + +//XXX This trap is apparently dropped from ua2005 +/*template<> SparcFaultBase::FaultVals + SparcFault<InstructionAccessMMUMiss>::vals = + {"inst_mmu", 0x009, 2, {H, H, H}};*/ + +template<> SparcFaultBase::FaultVals + SparcFault<InstructionAccessError>::vals = + {"instruction_access_error", 0x00A, 400, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<IllegalInstruction>::vals = + {"illegal_instruction", 0x010, 620, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<PrivilegedOpcode>::vals = + {"privileged_opcode", 0x011, 700, {P, SH, SH}}; + +//XXX This trap is apparently dropped from ua2005 +/*template<> SparcFaultBase::FaultVals + SparcFault<UnimplementedLDD>::vals = + {"unimp_ldd", 0x012, 6, {H, H, H}};*/ + +//XXX This trap is apparently dropped from ua2005 +/*template<> SparcFaultBase::FaultVals + SparcFault<UnimplementedSTD>::vals = + {"unimp_std", 0x013, 6, {H, H, H}};*/ + +template<> SparcFaultBase::FaultVals + SparcFault<FpDisabled>::vals = + {"fp_disabled", 0x020, 800, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FpExceptionIEEE754>::vals = + {"fp_exception_ieee_754", 0x021, 1110, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FpExceptionOther>::vals = + {"fp_exception_other", 0x022, 1110, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<TagOverflow>::vals = + {"tag_overflow", 0x023, 1400, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<CleanWindow>::vals = + {"clean_window", 0x024, 1010, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DivisionByZero>::vals = + {"division_by_zero", 0x028, 1500, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<InternalProcessorError>::vals = + {"internal_processor_error", 0x029, 4, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<InstructionInvalidTSBEntry>::vals = + {"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DataInvalidTSBEntry>::vals = + {"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DataAccessException>::vals = + {"data_access_exception", 0x030, 1201, {H, H, H}}; + +//XXX This trap is apparently dropped from ua2005 +/*template<> SparcFaultBase::FaultVals + SparcFault<DataAccessMMUMiss>::vals = + {"data_mmu", 0x031, 12, {H, H, H}};*/ + +template<> SparcFaultBase::FaultVals + SparcFault<DataAccessError>::vals = + {"data_access_error", 0x032, 1210, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DataAccessProtection>::vals = + {"data_access_protection", 0x033, 1207, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<MemAddressNotAligned>::vals = + {"mem_address_not_aligned", 0x034, 1020, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<LDDFMemAddressNotAligned>::vals = + {"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<STDFMemAddressNotAligned>::vals = + {"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<PrivilegedAction>::vals = + {"privileged_action", 0x037, 1110, {H, H, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<LDQFMemAddressNotAligned>::vals = + {"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<STQFMemAddressNotAligned>::vals = + {"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<InstructionRealTranslationMiss>::vals = + {"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DataRealTranslationMiss>::vals = + {"data_real_translation_miss", 0x03F, 1203, {H, H, H}}; + +//XXX This trap is apparently dropped from ua2005 +/*template<> SparcFaultBase::FaultVals + SparcFault<AsyncDataError>::vals = + {"async_data", 0x040, 2, {H, H, H}};*/ + +template<> SparcFaultBase::FaultVals + SparcFault<InterruptLevelN>::vals = + {"interrupt_level_n", 0x041, 0, {P, P, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<HstickMatch>::vals = + {"hstick_match", 0x05E, 1601, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<TrapLevelZero>::vals = + {"trap_level_zero", 0x05F, 202, {H, H, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<PAWatchpoint>::vals = + {"PA_watchpoint", 0x061, 1209, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<VAWatchpoint>::vals = + {"VA_watchpoint", 0x062, 1120, {P, P, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FastInstructionAccessMMUMiss>::vals = + {"fast_instruction_access_MMU_miss", 0x064, 208, {H, H, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FastDataAccessMMUMiss>::vals = + {"fast_data_access_MMU_miss", 0x068, 1203, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FastDataAccessProtection>::vals = + {"fast_data_access_protection", 0x06C, 1207, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<InstructionBreakpoint>::vals = + {"instruction_break", 0x076, 610, {H, H, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<CpuMondo>::vals = + {"cpu_mondo", 0x07C, 1608, {P, P, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<DevMondo>::vals = + {"dev_mondo", 0x07D, 1611, {P, P, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<ResumeableError>::vals = + {"resume_error", 0x07E, 3330, {P, P, SH}}; + +template<> SparcFaultBase::FaultVals + SparcFault<SpillNNormal>::vals = + {"spill_n_normal", 0x080, 900, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<SpillNOther>::vals = + {"spill_n_other", 0x0A0, 900, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FillNNormal>::vals = + {"fill_n_normal", 0x0C0, 900, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<FillNOther>::vals = + {"fill_n_other", 0x0E0, 900, {P, P, H}}; + +template<> SparcFaultBase::FaultVals + SparcFault<TrapInstruction>::vals = + {"trap_instruction", 0x100, 1602, {P, P, H}}; #if !FULL_SYSTEM -FaultName PageTableFault::_name = "page_table_fault"; -TrapType PageTableFault::_trapType = 0x0000; -FaultPriority PageTableFault::_priority = 0; -FaultStat PageTableFault::_count; +template<> SparcFaultBase::FaultVals + SparcFault<PageTableFault>::vals = + {"page_table_fault", 0x0000, 0, {SH, SH, SH}}; #endif /** + * This causes the thread context to enter RED state. This causes the side + * effects which go with entering RED state because of a trap. + */ + +void enterREDState(ThreadContext *tc) +{ + //@todo Disable the mmu? + //@todo Disable watchpoints? + MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + //HPSTATE.red = 1 + HPSTATE |= (1 << 5); + //HPSTATE.hpriv = 1 + HPSTATE |= (1 << 2); + tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); +} + +/** + * This sets everything up for a RED state trap except for actually jumping to + * the handler. + */ + +void doREDFault(ThreadContext *tc, TrapType tt) +{ + MiscReg TL = tc->readMiscReg(MISCREG_TL); + MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg ASI = tc->readMiscReg(MISCREG_ASI); + MiscReg CWP = tc->readMiscReg(MISCREG_CWP); + MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg PC = tc->readPC(); + MiscReg NPC = tc->readNextPC(); + + TL++; + + //set TSTATE.gl to gl + replaceBits(TSTATE, 42, 40, GL); + //set TSTATE.ccr to ccr + replaceBits(TSTATE, 39, 32, CCR); + //set TSTATE.asi to asi + replaceBits(TSTATE, 31, 24, ASI); + //set TSTATE.pstate to pstate + replaceBits(TSTATE, 20, 8, PSTATE); + //set TSTATE.cwp to cwp + replaceBits(TSTATE, 4, 0, CWP); + + //Write back TSTATE + tc->setMiscReg(MISCREG_TSTATE, TSTATE); + + //set TPC to PC + tc->setMiscReg(MISCREG_TPC, PC); + //set TNPC to NPC + tc->setMiscReg(MISCREG_TNPC, NPC); + + //set HTSTATE.hpstate to hpstate + tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + + //TT = trap type; + tc->setMiscReg(MISCREG_TT, tt); + + //Update GL + tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); + + //set PSTATE.mm to 00 + //set PSTATE.pef to 1 + PSTATE |= (1 << 4); + //set PSTATE.am to 0 + PSTATE &= ~(1 << 3); + //set PSTATE.priv to 0 + PSTATE &= ~(1 << 2); + //set PSTATE.ie to 0 + PSTATE &= ~(1 << 1); + //set PSTATE.cle to 0 + PSTATE &= ~(1 << 9); + //PSTATE.tle is unchanged + //XXX Where is the tct bit? + //set PSTATE.tct to 0 + tc->setMiscReg(MISCREG_PSTATE, PSTATE); + + //set HPSTATE.red to 1 + HPSTATE |= (1 << 5); + //set HPSTATE.hpriv to 1 + HPSTATE |= (1 << 2); + //set HPSTATE.ibe to 0 + HPSTATE &= ~(1 << 10); + //set HPSTATE.tlz to 0 + HPSTATE &= ~(1 << 0); + tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + + bool changedCWP = true; + if(tt == 0x24) + CWP++; + else if(0x80 <= tt && tt <= 0xbf) + CWP += (CANSAVE + 2); + else if(0xc0 <= tt && tt <= 0xff) + CWP--; + else + changedCWP = false; + + if(changedCWP) + { + CWP = (CWP + NWindows) % NWindows; + tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + } +} + +/** * This sets everything up for a normal trap except for actually jumping to - * the handler. It will need to be expanded to include the state machine in - * the manual. Right now it assumes that traps will always be to the - * privileged level. + * the handler. */ -void doNormalFault(ThreadContext *tc, TrapType tt) +void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) { - uint64_t TL = tc->readMiscReg(MISCREG_TL); - uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE); - uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE); - uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - uint64_t CCR = tc->readMiscReg(MISCREG_CCR); - uint64_t ASI = tc->readMiscReg(MISCREG_ASI); - uint64_t CWP = tc->readMiscReg(MISCREG_CWP); - uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); - uint64_t GL = tc->readMiscReg(MISCREG_GL); - uint64_t PC = tc->readPC(); - uint64_t NPC = tc->readNextPC(); + MiscReg TL = tc->readMiscReg(MISCREG_TL); + MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg ASI = tc->readMiscReg(MISCREG_ASI); + MiscReg CWP = tc->readMiscReg(MISCREG_CWP); + MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg PC = tc->readPC(); + MiscReg NPC = tc->readNextPC(); //Increment the trap level TL++; @@ -289,10 +429,10 @@ void doNormalFault(ThreadContext *tc, TrapType tt) tc->setMiscReg(MISCREG_TT, tt); //Update the global register level - if(1/*We're delivering the trap in priveleged mode*/) - tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL)); + if(!gotoHpriv) + tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); else - tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL)); + tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); //PSTATE.mm is unchanged //PSTATE.pef = whether or not an fpu is present @@ -301,7 +441,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt) PSTATE |= (1 << 4); //PSTATE.am = 0 PSTATE &= ~(1 << 3); - if(1/*We're delivering the trap in priveleged mode*/) + if(!gotoHpriv) { //PSTATE.priv = 1 PSTATE |= (1 << 2); @@ -322,7 +462,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt) //XXX Where exactly is this field? tc->setMiscReg(MISCREG_PSTATE, PSTATE); - if(0/*We're delivering the trap in hyperprivileged mode*/) + if(gotoHpriv) { //HPSTATE.red = 0 HPSTATE &= ~(1 << 5); @@ -351,47 +491,135 @@ void doNormalFault(ThreadContext *tc, TrapType tt) } } +void getREDVector(Addr & PC, Addr & NPC) +{ + //XXX The following constant might belong in a header file. + const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL; + PC = RSTVAddr | 0xA0; + NPC = PC + sizeof(MachInst); +} + +void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT) +{ + Addr HTBA = tc->readMiscReg(MISCREG_HTBA); + PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); + NPC = PC + sizeof(MachInst); +} + +void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL) +{ + Addr TBA = tc->readMiscReg(MISCREG_TBA); + PC = (TBA & ~mask(15)) | + (TL > 1 ? (1 << 14) : 0) | + ((TT << 5) & mask(14)); + NPC = PC + sizeof(MachInst); +} + #if FULL_SYSTEM -void SparcFault::invoke(ThreadContext * tc) +void SparcFaultBase::invoke(ThreadContext * tc) { FaultBase::invoke(tc); countStat()++; - //Use the SPARC trap state machine - /*// exception restart address - if (setRestartAddress() || !tc->inPalMode()) - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc); + //We can refer to this to see what the trap level -was-, but something + //in the middle could change it in the regfile out from under us. + MiscReg TL = tc->readMiscReg(MISCREG_TL); + MiscReg TT = tc->readMiscReg(MISCREG_TT); + MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - if (skipFaultingInstruction()) { - // traps... skip faulting instruction. - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, - tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4); - } + Addr PC, NPC; - if (!tc->inPalMode()) - AlphaISA::swap_palshadow(&(tc->regs), true); + PrivilegeLevel current; + if(!(PSTATE & (1 << 2))) + current = User; + else if(!(HPSTATE & (1 << 2))) + current = Privileged; + else + current = Hyperprivileged; - tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect(); - tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/ -} + PrivilegeLevel level = getNextLevel(current); -#endif + if(HPSTATE & (1 << 5) || TL == MaxTL - 1) + { + getREDVector(PC, NPC); + enterREDState(tc); + doREDFault(tc, TT); + } + else if(TL == MaxTL) + { + //Do error_state somehow? + //Probably inject a WDR fault using the interrupt mechanism. + //What should the PC and NPC be set to? + } + else if(TL > MaxPTL && level == Privileged) + { + //guest_watchdog fault + doNormalFault(tc, trapType(), true); + getHyperVector(tc, PC, NPC, 2); + } + else if(level == Hyperprivileged) + { + doNormalFault(tc, trapType(), true); + getHyperVector(tc, PC, NPC, trapType()); + } + else + { + doNormalFault(tc, trapType(), false); + getPrivVector(tc, PC, NPC, trapType(), TL+1); + } -#if !FULL_SYSTEM + tc->setPC(PC); + tc->setNextPC(NPC); + tc->setNextNPC(NPC + sizeof(MachInst)); +} -void TrapInstruction::invoke(ThreadContext * tc) +void PowerOnReset::invoke(ThreadContext * tc) { - // Should be handled in ISA. + //First, enter RED state. + enterREDState(tc); + + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + /* + tl = MaxTL; + gl = MaxGL; + + tickFields.counter = 0; //The TICK register is unreadable bya + tickFields.npt = 1; //The TICK register is unreadable by by !priv + + softint = 0; // Clear all the soft interrupt bits + tick_cmprFields.int_dis = 1; // disable timer compare interrupts + tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + stickFields.npt = 1; //The TICK register is unreadable by by !priv + stick_cmprFields.int_dis = 1; // disable timer compare interrupts + stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + + tt[tl] = _trapType; + pstate = 0; // fields 0 but pef + pstateFields.pef = 1; + + hpstate = 0; + hpstateFields.red = 1; + hpstateFields.hpriv = 1; + hpstateFields.tlz = 0; // this is a guess + hintp = 0; // no interrupts pending + hstick_cmprFields.int_dis = 1; // disable timer compare interrupts + hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + */ } +#else // !FULL_SYSTEM + void SpillNNormal::invoke(ThreadContext *tc) { - doNormalFault(tc, trapType()); + doNormalFault(tc, trapType(), false); Process *p = tc->getProcessPtr(); - //This will only work in faults from a SparcLiveProcess + //XXX This will only work in faults from a SparcLiveProcess SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); assert(lp); @@ -404,15 +632,15 @@ void SpillNNormal::invoke(ThreadContext *tc) void FillNNormal::invoke(ThreadContext *tc) { - doNormalFault(tc, trapType()); + doNormalFault(tc, trapType(), false); Process * p = tc->getProcessPtr(); - //This will only work in faults from a SparcLiveProcess + //XXX This will only work in faults from a SparcLiveProcess SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); assert(lp); - //The adjust the PC and NPC + //Then adjust the PC and NPC Addr fillStart = lp->readFillStart(); tc->setPC(fillStart); tc->setNextPC(fillStart + sizeof(MachInst)); diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 394a06294..e632502aa 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -42,579 +42,240 @@ namespace SparcISA typedef uint32_t TrapType; typedef uint32_t FaultPriority; -class SparcFault : public FaultBase -{ - public: +class SparcFaultBase : public FaultBase +{ + public: + enum PrivilegeLevel + { + U, User = U, + P, Privileged = P, + H, Hyperprivileged = H, + NumLevels, + SH = -1, + ShouldntHappen = SH + }; + struct FaultVals + { + const FaultName name; + const TrapType trapType; + const FaultPriority priority; + const PrivilegeLevel nextPrivilegeLevel[NumLevels]; + FaultStat count; + }; #if FULL_SYSTEM void invoke(ThreadContext * tc); #endif + virtual FaultName name() = 0; virtual TrapType trapType() = 0; virtual FaultPriority priority() = 0; virtual FaultStat & countStat() = 0; + virtual PrivilegeLevel getNextLevel(PrivilegeLevel current) = 0; }; -class InternalProcessorError : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} - bool isMachineCheckFault() {return true;} -}; - -class MemAddressNotAligned : public SparcFault +template<typename T> +class SparcFault : public SparcFaultBase { - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; + protected: + static FaultVals vals; public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} - bool isAlignmentFault() {return true;} + FaultName name() {return vals.name;} + TrapType trapType() {return vals.trapType;} + FaultPriority priority() {return vals.priority;} + FaultStat & countStat() {return vals.count;} + PrivilegeLevel getNextLevel(PrivilegeLevel current) + { + return vals.nextPrivilegeLevel[current]; + } }; -#if !FULL_SYSTEM -class PageTableFault : public SparcFault +class PowerOnReset : public SparcFault<PowerOnReset> { - private: - Addr vaddr; - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - PageTableFault(Addr va) - : vaddr(va) {} - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); }; -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} -#endif +class WatchDogReset : public SparcFault<WatchDogReset> {}; -static inline Fault genMachineCheckFault() -{ - return new InternalProcessorError; -} +class ExternallyInitiatedReset : public SparcFault<ExternallyInitiatedReset> {}; -static inline Fault genAlignmentFault() -{ - return new MemAddressNotAligned; -} +class SoftwareInitiatedReset : public SparcFault<SoftwareInitiatedReset> {}; -class PowerOnReset : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class REDStateException : public SparcFault<REDStateException> {}; -class WatchDogReset : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class StoreError : public SparcFault<StoreError> {}; -class ExternallyInitiatedReset : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class InstructionAccessException : public SparcFault<InstructionAccessException> {}; -class SoftwareInitiatedReset : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +//class InstructionAccessMMUMiss : public SparcFault<InstructionAccessMMUMiss> {}; -class REDStateException : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class InstructionAccessError : public SparcFault<InstructionAccessError> {}; -class InstructionAccessException : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class IllegalInstruction : public SparcFault<IllegalInstruction> {}; -class InstructionAccessMMUMiss : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class PrivilegedOpcode : public SparcFault<PrivilegedOpcode> {}; -class InstructionAccessError : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +//class UnimplementedLDD : public SparcFault<UnimplementedLDD> {}; -class IllegalInstruction : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +//class UnimplementedSTD : public SparcFault<UnimplementedSTD> {}; -class PrivilegedOpcode : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class FpDisabled : public SparcFault<FpDisabled> {}; -class UnimplementedLDD : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class FpExceptionIEEE754 : public SparcFault<FpExceptionIEEE754> {}; -class UnimplementedSTD : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class FpExceptionOther : public SparcFault<FpExceptionOther> {}; -class FpDisabled : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class TagOverflow : public SparcFault<TagOverflow> {}; -class FpExceptionIEEE754 : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class CleanWindow : public SparcFault<CleanWindow> {}; -class FpExceptionOther : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class DivisionByZero : public SparcFault<DivisionByZero> {}; -class TagOverflow : public SparcFault +class InternalProcessorError : + public SparcFault<InternalProcessorError> { - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + bool isMachineCheckFault() {return true;} }; -class DivisionByZero : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class InstructionInvalidTSBEntry : public SparcFault<InstructionInvalidTSBEntry> {}; -class DataAccessException : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class DataInvalidTSBEntry : public SparcFault<DataInvalidTSBEntry> {}; -class DataAccessMMUMiss : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class DataAccessException : public SparcFault<DataAccessException> {}; -class DataAccessError : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +//class DataAccessMMUMiss : public SparcFault<DataAccessMMUMiss> {}; -class DataAccessProtection : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class DataAccessError : public SparcFault<DataAccessError> {}; -class LDDFMemAddressNotAligned : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class DataAccessProtection : public SparcFault<DataAccessProtection> {}; -class STDFMemAddressNotAligned : public SparcFault +class MemAddressNotAligned : + public SparcFault<MemAddressNotAligned> { - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + bool isAlignmentFault() {return true;} }; -class PrivilegedAction : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class LDDFMemAddressNotAligned : public SparcFault<LDDFMemAddressNotAligned> {}; -class LDQFMemAddressNotAligned : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class STDFMemAddressNotAligned : public SparcFault<STDFMemAddressNotAligned> {}; -class STQFMemAddressNotAligned : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -}; +class PrivilegedAction : public SparcFault<PrivilegedAction> {}; + +class LDQFMemAddressNotAligned : public SparcFault<LDQFMemAddressNotAligned> {}; + +class STQFMemAddressNotAligned : public SparcFault<STQFMemAddressNotAligned> {}; + +class InstructionRealTranslationMiss : + public SparcFault<InstructionRealTranslationMiss> {}; + +class DataRealTranslationMiss : public SparcFault<DataRealTranslationMiss> {}; -class AsyncDataError : public SparcFault +//class AsyncDataError : public SparcFault<AsyncDataError> {}; + +template <class T> +class EnumeratedFault : public SparcFault<T> { - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; + protected: + uint32_t _n; public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + EnumeratedFault(uint32_t n) : SparcFault<T>(), _n(n) {} + TrapType trapType() {return SparcFault<T>::trapType() + _n;} }; -class CleanWindow : public SparcFault +class InterruptLevelN : public EnumeratedFault<InterruptLevelN> { - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; public: - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + InterruptLevelN(uint32_t n) : EnumeratedFault<InterruptLevelN>(n) {;} + FaultPriority priority() {return 3200 - _n*100;} }; -class EnumeratedFault : public SparcFault +class HstickMatch : public SparcFault<HstickMatch> {}; + +class TrapLevelZero : public SparcFault<TrapLevelZero> {}; + +class PAWatchpoint : public SparcFault<PAWatchpoint> {}; + +class VAWatchpoint : public SparcFault<VAWatchpoint> {}; + +class FastInstructionAccessMMUMiss : + public SparcFault<FastInstructionAccessMMUMiss> {}; + +class FastDataAccessMMUMiss : public SparcFault<FastDataAccessMMUMiss> {}; + +class FastDataAccessProtection : public SparcFault<FastDataAccessProtection> {}; + +class InstructionBreakpoint : public SparcFault<InstructionBreakpoint> {}; + +class CpuMondo : public SparcFault<CpuMondo> {}; + +class DevMondo : public SparcFault<DevMondo> {}; + +class ResumeableError : public SparcFault<ResumeableError> {}; + +class SpillNNormal : public EnumeratedFault<SpillNNormal> { - protected: - uint32_t _n; - virtual TrapType baseTrapType() = 0; public: - EnumeratedFault(uint32_t n) : SparcFault() {_n = n;} - TrapType trapType() {return baseTrapType() + _n;} + SpillNNormal(uint32_t n) : EnumeratedFault<SpillNNormal>(n) {;} + //These need to be handled specially to enable spill traps in SE +#if !FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif }; -class InterruptLevelN : public EnumeratedFault +class SpillNOther : public EnumeratedFault<SpillNOther> { - private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} public: - InterruptLevelN(uint32_t n) : EnumeratedFault(n) {;} - FaultName name() {return _name;} - FaultPriority priority() {return 32 - _n;} - FaultStat & countStat() {return _count;} + SpillNOther(uint32_t n) : EnumeratedFault<SpillNOther>(n) {;} }; -class SpillNNormal : public EnumeratedFault +class FillNNormal : public EnumeratedFault<FillNNormal> { - private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultPriority _priority; - static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} public: - SpillNNormal(uint32_t n) : EnumeratedFault(n) {;} - FaultName name() {return _name;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + FillNNormal(uint32_t n) : EnumeratedFault<FillNNormal>(n) {;} + //These need to be handled specially to enable fill traps in SE +#if !FULL_SYSTEM void invoke(ThreadContext * tc); +#endif }; -class SpillNOther : public EnumeratedFault +class FillNOther : public EnumeratedFault<FillNOther> { - private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultPriority _priority; - static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} public: - SpillNOther(uint32_t n) : EnumeratedFault(n) {;} - FaultName name() {return _name;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + FillNOther(uint32_t n) : EnumeratedFault<FillNOther>(n) {;} }; -class FillNNormal : public EnumeratedFault +class TrapInstruction : public EnumeratedFault<TrapInstruction> { - private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultPriority _priority; - static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} + public: - FillNNormal(uint32_t n) : EnumeratedFault(n) {;} - FaultName name() {return _name;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); + TrapInstruction(uint32_t n) : EnumeratedFault<TrapInstruction>(n) {;} }; -class FillNOther : public EnumeratedFault +#if !FULL_SYSTEM +class PageTableFault : public SparcFault<PageTableFault> { private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultPriority _priority; - static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} + Addr vaddr; public: - FillNOther(uint32_t n) : EnumeratedFault(n) {;} - FaultName name() {return _name;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} + PageTableFault(Addr va) : vaddr(va) {} + void invoke(ThreadContext * tc); }; -class TrapInstruction : public EnumeratedFault +static inline Fault genPageTableFault(Addr va) { - private: - static FaultName _name; - static TrapType _baseTrapType; - static FaultPriority _priority; - static FaultStat _count; - uint64_t syscall_num; - TrapType baseTrapType() {return _baseTrapType;} - public: - TrapInstruction(uint32_t n, uint64_t syscall) : - EnumeratedFault(n), syscall_num(syscall) {;} - FaultName name() {return _name;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -#if !FULL_SYSTEM - void invoke(ThreadContext * tc); + return new PageTableFault(va); +} #endif -}; + +static inline Fault genMachineCheckFault() +{ + return new InternalProcessorError; +} + +static inline Fault genAlignmentFault() +{ + return new MemAddressNotAligned; +} } // SparcISA namespace diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index 3afe6ef54..7f3d5a758 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -34,6 +34,8 @@ #include "sim/byteswap.hh" #include "sim/serialize.hh" +#include <string.h> + using namespace SparcISA; using namespace std; @@ -55,7 +57,7 @@ string SparcISA::getFloatRegName(RegIndex index) void FloatRegFile::clear() { - bzero(regSpace, sizeof(regSpace)); + memset(regSpace, 0, sizeof(regSpace)); } FloatReg FloatRegFile::readReg(int floatReg, int width) diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh new file mode 100644 index 000000000..0072f4184 --- /dev/null +++ b/src/arch/sparc/interrupts.hh @@ -0,0 +1,92 @@ +/* + * 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: Gabe Black + */ + +#ifndef __ARCH_SPARC_INTERRUPT_HH__ +#define __ARCH_SPARC_INTERRUPT_HH__ + +#include "arch/sparc/faults.hh" + +namespace SparcISA +{ + class Interrupts + { + protected: + Fault interrupts[NumInterruptLevels]; + bool requested[NumInterruptLevels]; + + public: + Interrupts() + { + for(int x = 0; x < NumInterruptLevels; x++) + { + interrupts[x] = new InterruptLevelN(x); + requested[x] = false; + } + } + void post(int int_num, int index) + { + if(int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + requested[int_num] = true; + } + + void clear(int int_num, int index) + { + requested[int_num] = false; + } + + void clear_all() + { + for(int x = 0; x < NumInterruptLevels; x++) + requested[x] = false; + } + + bool check_interrupts(ThreadContext * tc) const + { + return true; + } + + Fault getInterrupt(ThreadContext * tc) + { + return NoFault; + } + + void serialize(std::ostream &os) + { + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + } + }; +} + +#endif // __ARCH_SPARC_INTERRUPT_HH__ diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 164f194dd..0e313dc94 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -33,6 +33,8 @@ #include "base/trace.hh" #include "sim/serialize.hh" +#include <string.h> + using namespace SparcISA; using namespace std; @@ -62,7 +64,7 @@ void IntRegFile::clear() for (x = 0; x < MaxGL; x++) memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); for(int x = 0; x < 2 * NWindows; x++) - bzero(regSegments[x], sizeof(IntReg) * RegsPerFrame); + memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame); } IntRegFile::IntRegFile() diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index a64ff09bb..4f3ea7810 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -346,22 +346,93 @@ decode OP default Unknown::unknown() 0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}}); 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}}); } - // XXX might want a format rdipr thing here 0x28: decode RS1 { - 0xF: decode I { + 0x00: NoPriv::rdy({{Rd = Y;}}); + //1 should cause an illegal instruction exception + 0x02: NoPriv::rdccr({{Rd = Ccr;}}); + 0x03: NoPriv::rdasi({{Rd = Asi;}}); + 0x04: PrivCheck::rdtick({{Rd = Tick;}}, {{Tick<63:>}}); + 0x05: NoPriv::rdpc({{ + if(Pstate<3:>) + Rd = (xc->readPC())<31:0>; + else + Rd = xc->readPC();}}); + 0x06: NoPriv::rdfprs({{ + //Wait for all fpops to finish. + Rd = Fprs; + }}); + //7-14 should cause an illegal instruction exception + 0x0F: decode I { 0x0: Nop::stbar({{/*stuff*/}}); 0x1: Nop::membar({{/*stuff*/}}); } - default: rdasr({{ - Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault); + 0x10: Priv::rdpcr({{Rd = Pcr;}}); + 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}}); + //0x12 should cause an illegal instruction exception + 0x13: NoPriv::rdgsr({{ + if(Fprs<2:> == 0 || Pstate<4:> == 0) + Rd = Gsr; + else + fault = new FpDisabled; }}); + //0x14-0x15 should cause an illegal instruction exception + 0x16: Priv::rdsoftint({{Rd = Softint;}}); + 0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}}); + 0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}}); + 0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}}); + //0x1A-0x1F should cause an illegal instruction exception + } + 0x29: decode RS1 { + 0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}}); + 0x01: HPriv::rdhprhtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Htstate; + }}); + //0x02 should cause an illegal instruction exception + 0x03: HPriv::rdhprhintp({{Rd = Hintp;}}); + //0x04 should cause an illegal instruction exception + 0x05: HPriv::rdhprhtba({{Rd = Htba;}}); + 0x06: HPriv::rdhprhver({{Rd = Hver;}}); + //0x07-0x1E should cause an illegal instruction exception + 0x1F: HPriv::rdhprhstick_cmpr({{Rd = HstickCmpr;}}); + } + 0x2A: decode RS1 { + 0x00: Priv::rdprtpc({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tpc; + }}); + 0x01: Priv::rdprtnpc({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tnpc; + }}); + 0x02: Priv::rdprtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tstate; + }}); + 0x03: Priv::rdprtt({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tt; + }}); + 0x04: Priv::rdprtick({{Rd = Tick;}}); + 0x05: Priv::rdprtba({{Rd = Tba;}}); + 0x06: Priv::rdprpstate({{Rd = Pstate;}}); + 0x07: Priv::rdprtl({{Rd = Tl;}}); + 0x08: Priv::rdprpil({{Rd = Pil;}}); + 0x09: Priv::rdprcwp({{Rd = Cwp;}}); + 0x0A: Priv::rdprcansave({{Rd = Cansave;}}); + 0x0B: Priv::rdprcanrestore({{Rd = Canrestore;}}); + 0x0C: Priv::rdprcleanwin({{Rd = Cleanwin;}}); + 0x0D: Priv::rdprotherwin({{Rd = Otherwin;}}); + 0x0E: Priv::rdprwstate({{Rd = Wstate;}}); + //0x0F should cause an illegal instruction exception + 0x10: Priv::rdprgl({{Rd = Gl;}}); + //0x11-0x1F should cause an illegal instruction exception } - 0x29: HPriv::rdhpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault); - }}); - 0x2A: Priv::rdpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault); - }}); 0x2B: BasicOperate::flushw({{ if(NWindows - 2 - Cansave == 0) { @@ -417,9 +488,35 @@ decode OP default Unknown::unknown() 0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}}); 0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}}); } - 0x30: wrasr({{ - xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13); - }}); + 0x30: decode RD { + 0x00: NoPriv::wry({{Y = Rs1 ^ Rs2_or_imm13;}}); + //0x01 should cause an illegal instruction exception + 0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}}); + 0x03: NoPriv::wrasi({{Ccr = Rs1 ^ Rs2_or_imm13;}}); + //0x04-0x05 should cause an illegal instruction exception + 0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}}); + //0x07-0x0E should cause an illegal instruction exception + 0x0F: Trap::softreset({{fault = new SoftwareInitiatedReset;}}); + 0x10: Priv::wrpcr({{Pcr = Rs1 ^ Rs2_or_imm13;}}); + 0x11: PrivCheck::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}}); + //0x12 should cause an illegal instruction exception + 0x13: NoPriv::wrgsr({{ + if(Fprs<2:> == 0 || Pstate<4:> == 0) + return new FpDisabled; + Gsr = Rs1 ^ Rs2_or_imm13; + }}); + 0x14: Priv::wrsoftint_set({{SoftintSet = Rs1 ^ Rs2_or_imm13;}}); + 0x15: Priv::wrsoftint_clr({{SoftintClr = Rs1 ^ Rs2_or_imm13;}}); + 0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}}); + 0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}}); + 0x18: NoPriv::wrstick({{ + if(!Hpstate<2:>) + return new IllegalInstruction; + Stick = Rs1 ^ Rs2_or_imm13; + }}); + 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); + //0x1A-0x1F should cause an illegal instruction exception + } 0x31: decode FCN { 0x0: Priv::saved({{ assert(Cansave < NWindows - 2); @@ -440,16 +537,70 @@ decode OP default Unknown::unknown() Otherwin = Otherwin - 1; }}); } - 0x32: Priv::wrpr({{ - // XXX Need to protect with format that traps non-priv - // access - xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); - }}); - 0x33: HPriv::wrhpr({{ - // XXX Need to protect with format that traps non-priv/priv - // access - xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); - }}); + 0x32: decode RD { + 0x00: Priv::wrprtpc({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tpc = Rs1 ^ Rs2_or_imm13; + }}); + 0x01: Priv::wrprtnpc({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tnpc = Rs1 ^ Rs2_or_imm13; + }}); + 0x02: Priv::wrprtstate({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tstate = Rs1 ^ Rs2_or_imm13; + }}); + 0x03: Priv::wrprtt({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tt = Rs1 ^ Rs2_or_imm13; + }}); + 0x04: HPriv::wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}}); + 0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}}); + 0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}}); + 0x07: Priv::wrprtl({{ + if(Pstate<2:> && !Hpstate<2:>) + Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL); + else + Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL); + }}); + 0x08: Priv::wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}}); + 0x09: Priv::wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}}); + 0x0A: Priv::wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}}); + 0x0B: Priv::wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}}); + 0x0C: Priv::wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}}); + 0x0D: Priv::wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}}); + 0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}}); + //0x0F should cause an illegal instruction exception + 0x10: Priv::wrprgl({{ + if(Pstate<2:> && !Hpstate<2:>) + Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL); + else + Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL); + }}); + //0x11-0x1F should cause an illegal instruction exception + } + 0x33: decode RD { + 0x00: HPriv::wrhprhpstate({{Hpstate = Rs1 ^ Rs2_or_imm13;}}); + 0x01: HPriv::wrhprhtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Htstate = Rs1 ^ Rs2_or_imm13; + }}); + //0x02 should cause an illegal instruction exception + 0x03: HPriv::wrhprhintp({{Hintp = Rs1 ^ Rs2_or_imm13;}}); + //0x04 should cause an illegal instruction exception + 0x05: HPriv::wrhprhtba({{Htba = Rs1 ^ Rs2_or_imm13;}}); + //0x06-0x01D should cause an illegal instruction exception + 0x1F: HPriv::wrhprhstick_cmpr({{HstickCmpr = Rs1 ^ Rs2_or_imm13;}}); + } 0x34: decode OPF{ format BasicOperate{ 0x01: fmovs({{ diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 04c67d332..55bf968f4 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -119,18 +119,34 @@ let {{ return (header_output, decoder_output, exec_output, decode_block) }}; -// Primary format for integer operate instructions: def format Priv(code, *opt_flags) {{ - checkCode = "!(Pstate<2:2> || Hpstate<2:2>)" + checkCode = "!(Pstate<2:> || Hpstate<2:>)" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags + ('IprAccessOp',)) + checkCode, name, Name, opt_flags) +}}; + +def format NoPriv(code, *opt_flags) {{ + #Instructions which use this format don't really check for + #any particular mode, but the disassembly is performed + #using the control registers actual name + checkCode = "false" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) +}}; + +def format PrivCheck(code, extraCheckCode, *opt_flags) {{ + checkCode = "(%s) && !(Pstate<2:> || Hpstate<2:>)" % extraCheckCode + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) }}; def format HPriv(code, *opt_flags) {{ checkCode = "!Hpstate<2:2>" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags + ('IprAccessOp',)) + checkCode, name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index a324756ec..624afb693 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -54,6 +54,7 @@ output decoder {{ #if defined(linux) #include <fenv.h> #endif +#include <algorithm> using namespace SparcISA; }}; diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 80b499b91..caee20b0c 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -80,8 +80,6 @@ def operands {{ 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), - #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), - #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), 'R0': ('IntReg', 'udw', '0', None, 6), 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), @@ -91,24 +89,42 @@ def operands {{ 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), + 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43), + 'Pcr': ('ControlReg', 'udw', 'MISCREG_PCR', None, 44), + 'Pic': ('ControlReg', 'udw', 'MISCREG_PIC', None, 45), + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 46), + 'Softint': ('ControlReg', 'udw', 'MISCREG_SOFTINT', None, 47), + 'SoftintSet': ('ControlReg', 'udw', 'MISCREG_SOFTINT_SET', None, 48), + 'SoftintClr': ('ControlReg', 'udw', 'MISCREG_SOFTINT_CLR', None, 49), + 'TickCmpr': ('ControlReg', 'udw', 'MISCREG_TICK_CMPR', None, 50), + 'Stick': ('ControlReg', 'udw', 'MISCREG_STICK', None, 51), + 'StickCmpr': ('ControlReg', 'udw', 'MISCREG_STICK_CMPR', None, 52), - 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43), - 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44), - 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45), - 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46), - 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47), - 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48), + 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 53), + 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 54), + 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 55), + 'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56), + 'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57), + 'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 58), + 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), + 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 62), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54), - 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55), + 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69), + 'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70), + 'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71), + 'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72), + 'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73), + 'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74), - 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56), - 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57), + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80), # Mem gets a large number so it's always last 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) diff --git a/src/arch/sparc/kernel_stats.hh b/src/arch/sparc/kernel_stats.hh new file mode 100644 index 000000000..c007c54c2 --- /dev/null +++ b/src/arch/sparc/kernel_stats.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2005 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: Gabe Black + */ + +#ifndef __ARCH_SPARC_KERNEL_STATS_HH__ +#define __ARCH_SPARC_KERNEL_STATS_HH__ + +#include <map> +#include <stack> +#include <string> +#include <vector> + +#include "kern/kernel_stats.hh" + +namespace SparcISA { +namespace Kernel { + +enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; + +class Statistics : public ::Kernel::Statistics +{ + public: + Statistics(System *system) : ::Kernel::Statistics(system) + {} +}; + +} /* end namespace AlphaISA::Kernel */ +} /* end namespace AlphaISA */ + +#endif // __ARCH_SPARC_KERNEL_STATS_HH__ diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index bf4572878..d52e3983f 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -29,11 +29,18 @@ * Ali Saidi */ +#include "arch/sparc/asi.hh" #include "arch/sparc/miscregfile.hh" +#include "base/bitfield.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#if FULL_SYSTEM +#include "arch/sparc/system.hh" +#endif + using namespace SparcISA; using namespace std; @@ -55,66 +62,41 @@ string SparcISA::getMiscRegName(RegIndex index) return miscRegName[index]; } -#if FULL_SYSTEM - -//XXX These need an implementation someplace -/** Fullsystem only register version of ReadRegWithEffect() */ -MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); -/** Fullsystem only register version of SetRegWithEffect() */ -Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); -#endif - void MiscRegFile::reset() { - pstateFields.pef = 0; //No FPU - //pstateFields.pef = 1; //FPU -#if FULL_SYSTEM - //For SPARC, when a system is first started, there is a power - //on reset Trap which sets the processor into the following state. - //Bits that aren't set aren't defined on startup. - tl = MaxTL; - gl = MaxGL; - - tickFields.counter = 0; //The TICK register is unreadable bya - tickFields.npt = 1; //The TICK register is unreadable by by !priv - - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts - tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - stickFields.npt = 1; //The TICK register is unreadable by by !priv - stick_cmprFields.int_dis = 1; // disable timer compare interrupts - stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - - - tt[tl] = power_on_reset; - pstate = 0; // fields 0 but pef - pstateFields.pef = 1; - + y = 0; + ccr = 0; + asi = 0; + tick = 0; + fprs = 0; + gsr = 0; + softint = 0; + tick_cmpr = 0; + stick = 0; + stick_cmpr = 0; + memset(tpc, 0, sizeof(tpc)); + memset(tnpc, 0, sizeof(tnpc)); + memset(tstate, 0, sizeof(tstate)); + memset(tt, 0, sizeof(tt)); + pstate = 0; + tl = 0; + pil = 0; + cwp = 0; + cansave = 0; + canrestore = 0; + cleanwin = 0; + otherwin = 0; + wstate = 0; + gl = 0; hpstate = 0; - hpstateFields.red = 1; - hpstateFields.hpriv = 1; - hpstateFields.tlz = 0; // this is a guess - hintp = 0; // no interrupts pending - hstick_cmprFields.int_dis = 1; // disable timer compare interrupts - hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing -#else -/* //This sets up the initial state of the processor for usermode processes - pstateFields.priv = 0; //Process runs in user mode - pstateFields.ie = 1; //Interrupts are enabled - fsrFields.rd = 0; //Round to nearest - fsrFields.tem = 0; //Floating point traps not enabled - fsrFields.ns = 0; //Non standard mode off - fsrFields.qne = 0; //Floating point queue is empty - fsrFields.aexc = 0; //No accrued exceptions - fsrFields.cexc = 0; //No current exceptions - - //Register window management registers - otherwin = 0; //No windows contain info from other programs - canrestore = 0; //There are no windows to pop - cansave = MaxTL - 2; //All windows are available to save into - cleanwin = MaxTL;*/ -#endif + memset(htstate, 0, sizeof(htstate)); + hintp = 0; + htba = 0; + hstick_cmpr = 0; + strandStatusReg = 0; + fsr = 0; + implicitInstAsi = ASI_PRIMARY; + implicitDataAsi = ASI_PRIMARY; } MiscReg MiscRegFile::readReg(int miscReg) @@ -131,8 +113,9 @@ MiscReg MiscRegFile::readReg(int miscReg) case MISCREG_TICK: return tick; case MISCREG_PCR: + panic("PCR not implemented\n"); case MISCREG_PIC: - panic("ASR number %d not implemented\n", miscReg - AsrStart); + panic("PIC not implemented\n"); case MISCREG_GSR: return gsr; case MISCREG_SOFTINT: @@ -207,17 +190,27 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) switch (miscReg) { case MISCREG_TICK: case MISCREG_PRIVTICK: - return tc->getCpuPtr()->curCycle() - tickFields.counter | - tickFields.npt << 63; + return tc->getCpuPtr()->curCycle() - (tick & mask(63)) | + (tick & ~(mask(63))) << 63; case MISCREG_FPRS: panic("FPU not implemented\n"); case MISCREG_PCR: case MISCREG_PIC: panic("Performance Instrumentation not impl\n"); - /** Floating Point Status Register */ case MISCREG_FSR: panic("Floating Point not implemented\n"); +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + SparcSystem *sys; + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); +#endif + case MISCREG_HVER: + return NWindows | MaxTL << 8 | MaxGL << 16; } return readReg(miscReg); } @@ -241,8 +234,9 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) tick = val; break; case MISCREG_PCR: + panic("PCR not implemented\n"); case MISCREG_PIC: - panic("ASR number %d not implemented\n", miscReg - AsrStart); + panic("PIC not implemented\n"); case MISCREG_GSR: gsr = val; break; @@ -337,14 +331,42 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) } } +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) { const uint64_t Bit64 = (1ULL << 63); +#if FULL_SYSTEM + uint64_t time; + SparcSystem *sys; +#endif switch (miscReg) { case MISCREG_TICK: - tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; - tickFields.npt = val & Bit64 ? 1 : 0; + tick = tc->getCpuPtr()->curCycle() - val & ~Bit64; + tick |= val & Bit64; break; case MISCREG_FPRS: //Configure the fpu based on the fprs @@ -352,12 +374,84 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_PCR: //Set up performance counting based on pcr value break; + case MISCREG_PSTATE: + pstate = val; + setImplicitAsis(); + return; + case MISCREG_TL: + tl = val; + setImplicitAsis(); + return; case MISCREG_CWP: tc->changeRegFileContext(CONTEXT_CWP, val); break; case MISCREG_GL: tc->changeRegFileContext(CONTEXT_GLOBALS, val); break; + case MISCREG_SOFTINT: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; + case MISCREG_SOFTINT_CLR: + //Do whatever this is supposed to do... + break; + case MISCREG_SOFTINT_SET: + //Do whatever this is supposed to do... + break; +#if FULL_SYSTEM + case MISCREG_TICK_CMPR: + if (tickCompare == NULL) + tickCompare = new TickCompareEvent(this, tc); + setReg(miscReg, val); + if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) + tickCompare->deschedule(); + time = (tick_cmpr & mask(63)) - (tick & mask(63)); + if (!(tick_cmpr & ~mask(63)) && time > 0) + tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + break; +#endif + case MISCREG_PIL: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64; + stick |= val & Bit64; + break; + case MISCREG_STICK_CMPR: + if (sTickCompare == NULL) + sTickCompare = new STickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) + sTickCompare->deschedule(); + time = (stick_cmpr & mask(63)) - sys->sysTick; + if (!(stick_cmpr & ~mask(63)) && time > 0) + sTickCompare->schedule(time * Clock::Int::ns); + break; + case MISCREG_HSTICK_CMPR: + if (hSTickCompare == NULL) + hSTickCompare = new HSTickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) + hSTickCompare->deschedule(); + int64_t time = (hstick_cmpr & mask(63)) - sys->sysTick; + if (!(hstick_cmpr & ~mask(63)) && time > 0) + hSTickCompare->schedule(time * Clock::Int::ns); + break; +#endif } setReg(miscReg, val); } @@ -389,6 +483,8 @@ 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); } void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) @@ -418,5 +514,29 @@ 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; } +#if FULL_SYSTEM +void +MiscRegFile::processTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processHSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} +#endif diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 771cb1ed6..f74943256 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -32,9 +32,11 @@ #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" +#include "cpu/cpuevent.hh" #include <string> @@ -44,59 +46,53 @@ namespace SparcISA //These functions map register indices to names std::string getMiscRegName(RegIndex); - const int AsrStart = 0; - const int PrStart = 32; - const int HprStart = 64; - const int MiscStart = 96; - enum MiscRegIndex { /** Ancillary State Registers */ - MISCREG_Y = AsrStart + 0, - MISCREG_CCR = AsrStart + 2, - MISCREG_ASI = AsrStart + 3, - MISCREG_TICK = AsrStart + 4, - MISCREG_FPRS = AsrStart + 6, - MISCREG_PCR = AsrStart + 16, - MISCREG_PIC = AsrStart + 17, - MISCREG_GSR = AsrStart + 19, - MISCREG_SOFTINT_SET = AsrStart + 20, - MISCREG_SOFTINT_CLR = AsrStart + 21, - MISCREG_SOFTINT = AsrStart + 22, - MISCREG_TICK_CMPR = AsrStart + 23, - MISCREG_STICK = AsrStart + 24, - MISCREG_STICK_CMPR = AsrStart + 25, + MISCREG_Y, + MISCREG_CCR, + MISCREG_ASI, + MISCREG_TICK, + MISCREG_FPRS, + MISCREG_PCR, + MISCREG_PIC, + MISCREG_GSR, + MISCREG_SOFTINT_SET, + MISCREG_SOFTINT_CLR, + MISCREG_SOFTINT, + MISCREG_TICK_CMPR, + MISCREG_STICK, + MISCREG_STICK_CMPR, /** Privilged Registers */ - MISCREG_TPC = PrStart + 0, - MISCREG_TNPC = PrStart + 1, - MISCREG_TSTATE = PrStart + 2, - MISCREG_TT = PrStart + 3, - MISCREG_PRIVTICK = PrStart + 4, - MISCREG_TBA = PrStart + 5, - MISCREG_PSTATE = PrStart + 6, - MISCREG_TL = PrStart + 7, - MISCREG_PIL = PrStart + 8, - MISCREG_CWP = PrStart + 9, - MISCREG_CANSAVE = PrStart + 10, - MISCREG_CANRESTORE = PrStart + 11, - MISCREG_CLEANWIN = PrStart + 12, - MISCREG_OTHERWIN = PrStart + 13, - MISCREG_WSTATE = PrStart + 14, - MISCREG_GL = PrStart + 16, + MISCREG_TPC, + MISCREG_TNPC, + MISCREG_TSTATE, + MISCREG_TT, + MISCREG_PRIVTICK, + MISCREG_TBA, + MISCREG_PSTATE, + MISCREG_TL, + MISCREG_PIL, + MISCREG_CWP, + MISCREG_CANSAVE, + MISCREG_CANRESTORE, + MISCREG_CLEANWIN, + MISCREG_OTHERWIN, + MISCREG_WSTATE, + MISCREG_GL, /** Hyper privileged registers */ - MISCREG_HPSTATE = HprStart + 0, - MISCREG_HTSTATE = HprStart + 1, - MISCREG_HINTP = HprStart + 3, - MISCREG_HTBA = HprStart + 5, - MISCREG_HVER = HprStart + 6, - MISCREG_STRAND_STS_REG = HprStart + 16, - MISCREG_HSTICK_CMPR = HprStart + 31, + MISCREG_HPSTATE, + MISCREG_HTSTATE, + MISCREG_HINTP, + MISCREG_HTBA, + MISCREG_HVER, + MISCREG_STRAND_STS_REG, + MISCREG_HSTICK_CMPR, /** Floating Point Status Register */ - MISCREG_FSR = MiscStart + 0 - + MISCREG_FSR }; // The control registers, broken out into fields @@ -105,93 +101,16 @@ namespace SparcISA private: /* ASR Registers */ - union { - uint64_t y; // Y (used in obsolete multiplication) - struct { - uint64_t value:32; // The actual value stored in y - uint64_t :32; // reserved bits - } yFields; - }; - union { - uint8_t ccr; // Condition Code Register - struct { - union { - uint8_t icc:4; // 32-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } iccFields; - }; - union { - uint8_t xcc:4; // 64-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } xccFields; - }; - } ccrFields; - }; + uint64_t y; // Y (used in obsolete multiplication) + uint8_t ccr; // Condition Code Register uint8_t asi; // Address Space Identifier - union { - uint64_t tick; // Hardware clock-tick counter - struct { - int64_t counter:63; // Clock-tick count - uint64_t npt:1; // Non-priveleged trap - } tickFields; - }; - union { - uint8_t fprs; // Floating-Point Register State - struct { - uint8_t dl:1; // Dirty lower - uint8_t du:1; // Dirty upper - uint8_t fef:1; // FPRS enable floating-Point - } fprsFields; - }; - union { - uint64_t gsr; //General Status Register - struct { - uint64_t mask:32; - uint64_t :4; - uint64_t im:1; - uint64_t irnd:2; - uint64_t :17; - uint64_t scale:5; - uint64_t align:3; - } gsrFields; - }; - union { - uint64_t softint; - struct { - uint64_t tm:1; - uint64_t int_level:14; - uint64_t sm:1; - } softintFields; - }; - union { - uint64_t tick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } tick_cmprFields; - }; - union { - uint64_t stick; // Hardware clock-tick counter - struct { - int64_t :63; // Not used, storage in SparcSystem - uint64_t npt:1; // Non-priveleged trap - } stickFields; - }; - union { - uint64_t stick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } stick_cmprFields; - }; + uint64_t tick; // Hardware clock-tick counter + uint8_t fprs; // Floating-Point Register State + uint64_t gsr; // General Status Register + uint64_t softint; + uint64_t tick_cmpr; // Hardware tick compare registers + uint64_t stick; // Hardware clock-tick counter + uint64_t stick_cmpr; // Hardware tick compare registers /* Privileged Registers */ @@ -199,37 +118,12 @@ namespace SparcISA // previous trap level) uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from // previous trap level) - union { - uint64_t tstate[MaxTL]; // Trap State - struct { - //Values are from previous trap level - uint64_t cwp:5; // Current Window Pointer - uint64_t :3; // Reserved bits - uint64_t pstate:13; // Process State - uint64_t :3; // Reserved bits - uint64_t asi:8; // Address Space Identifier - uint64_t ccr:8; // Condition Code Register - uint64_t gl:8; // Global level - } tstateFields[MaxTL]; - }; + uint64_t tstate[MaxTL]; // Trap State uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured // on the previous level) uint64_t tba; // Trap Base Address - union { - uint16_t pstate; // Process State Register - struct { - uint16_t :1; // reserved - uint16_t ie:1; // Interrupt enable - uint16_t priv:1; // Privelege mode - uint16_t am:1; // Address mask - uint16_t pef:1; // PSTATE enable floating-point - uint16_t :1; // reserved2 - uint16_t mm:2; // Memory Model - uint16_t tle:1; // Trap little-endian - uint16_t cle:1; // Current little-endian - } pstateFields; - }; + uint16_t pstate; // Process State Register uint8_t tl; // Trap Level uint8_t pil; // Process Interrupt Register uint8_t cwp; // Current Window Pointer @@ -237,97 +131,23 @@ namespace SparcISA uint8_t canrestore; // Restorable windows uint8_t cleanwin; // Clean windows uint8_t otherwin; // Other windows - union { - uint8_t wstate; // Window State - struct { - uint8_t normal:3; // Bits TT<4:2> are set to on a normal - // register window trap - uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" - // register window trap - } wstateFields; - }; + uint8_t wstate; // Window State uint8_t gl; // Global level register - /** Hyperprivileged Registers */ - union { - uint64_t hpstate; // Hyperprivileged State Register - struct { - uint8_t tlz: 1; - uint8_t :1; - uint8_t hpriv:1; - uint8_t :2; - uint8_t red:1; - uint8_t :4; - uint8_t ibe:1; - uint8_t id:1; - } hpstateFields; - }; - - uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register + uint64_t hpstate; // Hyperprivileged State Register + uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register uint64_t hintp; - uint64_t htba; // Hyperprivileged Trap Base Address register - union { - uint64_t hstick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } hstick_cmprFields; - }; - - uint64_t strandStatusReg; // Per strand status register + uint64_t htba; // Hyperprivileged Trap Base Address register + uint64_t hstick_cmpr; // Hardware tick compare registers + uint64_t strandStatusReg;// Per strand status register /** Floating point misc registers. */ - union { - uint64_t fsr; // Floating-Point State Register - struct { - union { - uint64_t cexc:5; // Current excpetion - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } cexcFields; - }; - union { - uint64_t aexc:5; // Accrued exception - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } aexcFields; - }; - uint64_t fcc0:2; // Floating-Point condtion codes - uint64_t :1; // Reserved bits - uint64_t qne:1; // Deferred trap queue not empty - // with no queue, it should read 0 - uint64_t ftt:3; // Floating-Point trap type - uint64_t ver:3; // Version (of the FPU) - uint64_t :2; // Reserved bits - uint64_t ns:1; // Nonstandard floating point - union { - uint64_t tem:5; // Trap Enable Mask - struct { - uint64_t nxm:1; // Inexact - uint64_t dzm:1; // Divide by zero - uint64_t ufm:1; // Underflow - uint64_t ofm:1; // Overflow - uint64_t nvm:1; // Invalid operand - } temFields; - }; - uint64_t :2; // Reserved bits - uint64_t rd:2; // Rounding direction - uint64_t fcc1:2; // Floating-Point condition codes - uint64_t fcc2:2; // Floating-Point condition codes - uint64_t fcc3:2; // Floating-Point condition codes - uint64_t :26; // Reserved bits - } fsrFields; - }; + uint64_t fsr; // Floating-Point State Register + + ASI implicitInstAsi; + ASI implicitDataAsi; // These need to check the int_dis field and if 0 then // set appropriate bit in softint and checkinterrutps on the cpu @@ -349,12 +169,6 @@ namespace SparcISA typedef CpuEventWrapper<MiscRegFile, &MiscRegFile::processHSTickCompare> HSTickCompareEvent; HSTickCompareEvent *hSTickCompare; - - /** Fullsystem only register version of ReadRegWithEffect() */ - MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - /** Fullsystem only register version of SetRegWithEffect() */ - Fault setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); #endif public: @@ -374,6 +188,16 @@ namespace SparcISA void setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); + ASI getInstAsid() + { + return implicitInstAsi; + } + + ASI getDataAsid() + { + return implicitDataAsi; + } + void serialize(std::ostream & os); void unserialize(Checkpoint * cp, const std::string & section); @@ -382,9 +206,10 @@ namespace SparcISA protected: - bool isHyperPriv() { return hpstateFields.hpriv; } - bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } + 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/process.cc b/src/arch/sparc/process.cc index a3b7dde7c..11a799ccb 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -29,6 +29,7 @@ * Ali Saidi */ +#include "arch/sparc/asi.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "base/loader/object_file.hh" @@ -105,6 +106,8 @@ SparcLiveProcess::startup() threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); //Set the trap level to 0 threadContexts[0]->setMiscReg(MISCREG_TL, 0); + //Set the ASI register to something fixed + threadContexts[0]->setMiscReg(MISCREG_ASI, ASI_PRIMARY); } m5_auxv_t buildAuxVect(int64_t type, int64_t val) diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 5eb874d39..65e6017da 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -79,24 +79,20 @@ MiscReg RegFile::readMiscReg(int miscReg) return miscRegFile.readReg(miscReg); } -MiscReg RegFile::readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc) +MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc) { - fault = NoFault; return miscRegFile.readRegWithEffect(miscReg, tc); } -Fault RegFile::setMiscReg(int miscReg, const MiscReg &val) +void RegFile::setMiscReg(int miscReg, const MiscReg &val) { miscRegFile.setReg(miscReg, val); - return NoFault; } -Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, +void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { miscRegFile.setRegWithEffect(miscReg, val, tc); - return NoFault; } FloatReg RegFile::readFloatReg(int floatReg, int width) @@ -122,27 +118,26 @@ FloatRegBits RegFile::readFloatRegBits(int floatReg) FloatRegFile::SingleWidth); } -Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) +void RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) { - return floatRegFile.setReg(floatReg, val, width); + floatRegFile.setReg(floatReg, val, width); } -Fault RegFile::setFloatReg(int floatReg, const FloatReg &val) +void RegFile::setFloatReg(int floatReg, const FloatReg &val) { //Use the "natural" width of a single float - return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); + setFloatReg(floatReg, val, FloatRegFile::SingleWidth); } -Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) { - return floatRegFile.setRegBits(floatReg, val, width); + floatRegFile.setRegBits(floatReg, val, width); } -Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) { //Use the "natural" width of a single float - return floatRegFile.setRegBits(floatReg, val, - FloatRegFile::SingleWidth); + floatRegFile.setRegBits(floatReg, val, FloatRegFile::SingleWidth); } IntReg RegFile::readIntReg(int intReg) @@ -150,9 +145,9 @@ IntReg RegFile::readIntReg(int intReg) return intRegFile.readReg(intReg); } -Fault RegFile::setIntReg(int intReg, const IntReg &val) +void RegFile::setIntReg(int intReg, const IntReg &val) { - return intRegFile.setReg(intReg, val); + intRegFile.setReg(intReg, val); } void RegFile::serialize(std::ostream &os) diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 500fbbba4..9f33435f6 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -32,7 +32,6 @@ #ifndef __ARCH_SPARC_REGFILE_HH__ #define __ARCH_SPARC_REGFILE_HH__ -#include "arch/sparc/faults.hh" #include "arch/sparc/floatregfile.hh" #include "arch/sparc/intregfile.hh" #include "arch/sparc/isa_traits.hh" @@ -76,14 +75,23 @@ namespace SparcISA MiscReg readMiscReg(int miscReg); - MiscReg readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc); + MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc); - Fault setMiscReg(int miscReg, const MiscReg &val); + void setMiscReg(int miscReg, const MiscReg &val); - Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); + ASI instAsid() + { + return miscRegFile.getInstAsid(); + } + + ASI dataAsid() + { + return miscRegFile.getDataAsid(); + } + FloatReg readFloatReg(int floatReg, int width); FloatReg readFloatReg(int floatReg); @@ -92,17 +100,17 @@ namespace SparcISA FloatRegBits readFloatRegBits(int floatReg); - Fault setFloatReg(int floatReg, const FloatReg &val, int width); + void setFloatReg(int floatReg, const FloatReg &val, int width); - Fault setFloatReg(int floatReg, const FloatReg &val); + void setFloatReg(int floatReg, const FloatReg &val); - Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width); + void setFloatRegBits(int floatReg, const FloatRegBits &val, int width); - Fault setFloatRegBits(int floatReg, const FloatRegBits &val); + void setFloatRegBits(int floatReg, const FloatRegBits &val); IntReg readIntReg(int intReg); - Fault setIntReg(int intReg, const IntReg &val); + void setIntReg(int intReg, const IntReg &val); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc new file mode 100644 index 000000000..c76f8b820 --- /dev/null +++ b/src/arch/sparc/remote_gdb.cc @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2005 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: Nathan Binkert + */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ + * + * Taken from NetBSD + * + * "Stub" to allow remote cpu to debug over a serial line using gdb. + */ + +#include <sys/signal.h> + +#include <string> +#include <unistd.h> + +#include "arch/vtophys.hh" +#include "arch/sparc/remote_gdb.hh" +#include "base/intmath.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/static_inst.hh" +#include "mem/physical.hh" +#include "mem/port.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) + : BaseRemoteGDB(_system, c, NumGDBRegs) +{} + +/////////////////////////////////////////////////////////// +// RemoteGDB::acc +// +// Determine if the mapping at va..(va+len) is valid. +// +bool +RemoteGDB::acc(Addr va, size_t len) +{ + //@Todo In NetBSD, this function checks if all addresses + //from va to va + len have valid page mape entries. Not + //sure how this will work for other OSes or in general. + return true; +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::getregs +// +// Translate the kernel debugger register format into +// the GDB register format. +void +RemoteGDB::getregs() +{ + memset(gdbregs.regs, 0, gdbregs.size); + + gdbregs.regs[RegPc] = context->readPC(); + gdbregs.regs[RegNpc] = context->readNextPC(); + for(int x = RegG0; x <= RegI0 + 7; x++) + gdbregs.regs[x] = context->readIntReg(x - RegG0); + //Floating point registers are left at 0 in netbsd + //All registers other than the pc, npc and int regs + //are ignored as well. +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::setregs +// +// Translate the GDB register format into the kernel +// debugger register format. +// +void +RemoteGDB::setregs() +{ + context->setPC(gdbregs.regs[RegPc]); + context->setNextPC(gdbregs.regs[RegNpc]); + for(int x = RegG0; x <= RegI0 + 7; x++) + context->setIntReg(x - RegG0, gdbregs.regs[x]); + //Only the integer registers, pc and npc are set in netbsd +} + +void +RemoteGDB::clearSingleStep() +{ + panic("SPARC does not support hardware single stepping\n"); +} + +void +RemoteGDB::setSingleStep() +{ + panic("SPARC does not support hardware single stepping\n"); +} diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh new file mode 100644 index 000000000..e4b66b783 --- /dev/null +++ b/src/arch/sparc/remote_gdb.hh @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2005 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: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ +#define __ARCH_ALPHA_REMOTE_GDB_HH__ + +#include <map> + +#include "arch/types.hh" +#include "base/remote_gdb.hh" +#include "cpu/pc_event.hh" +#include "base/pollevent.hh" + +class System; +class ThreadContext; +class PhysicalMemory; + +namespace SparcISA +{ + class RemoteGDB : public BaseRemoteGDB + { + protected: + enum RegisterConstants + { + RegG0 = 0, RegO0 = 8, RegL0 = 16, RegI0 = 24, + RegF0 = 32, RegF32 = 64, + RegPc = 80, RegNpc, RegCcr, RegFsr, RegFprs, RegY, RegAsi, + RegVer, RegTick, RegPil, RegPstate, + RegTstate, RegTba, RegTl, RegTt, RegTpc, RegTnpc, RegWstate, + RegCwp, RegCansave, RegCanrestore, RegCleanwin, RegOtherwin, + RegAsr16 = 103, + RegIcc = 119, RegXcc, + RegFcc0 = 121, + NumGDBRegs + }; + + public: + RemoteGDB(System *system, ThreadContext *context); + + bool acc(Addr addr, size_t len); + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + }; +} + +#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc new file mode 100644 index 000000000..2eb697bf2 --- /dev/null +++ b/src/arch/sparc/stacktrace.cc @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2005 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: Nathan Binkert + */ + +#include <string> + +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/stacktrace.hh" +#include "arch/sparc/vtophys.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "sim/system.hh" + +using namespace std; +namespace SparcISA +{ + ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) + { + Addr addr = 0; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp->readGtoH<int32_t>(addr); + + tc->delVirtPort(vp); + } + + Addr + ProcessInfo::task(Addr ksp) const + { + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; + + Addr tsk; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + tsk = vp->readGtoH<Addr>(base + task_off); + tc->delVirtPort(vp); + + return tsk; + } + + int + ProcessInfo::pid(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return -1; + + uint16_t pd; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + pd = vp->readGtoH<uint16_t>(task + pid_off); + tc->delVirtPort(vp); + + return pd; + } + + string + ProcessInfo::name(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return "console"; + + char comm[256]; + CopyStringOut(tc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; + + return comm; + } + + StackTrace::StackTrace() + : tc(0), stack(64) + { + } + + StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) + { + trace(_tc, inst); + } + + StackTrace::~StackTrace() + { + } + + void + StackTrace::trace(ThreadContext *_tc, bool is_call) + { +#if 0 + tc = _tc; + + bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + + Addr pc = tc->readNextPC(); + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; + + if (usermode) { + stack.push_back(user); + return; + } + + if (!kernel) { + stack.push_back(console); + return; + } + + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + Addr ksp = tc->readIntReg(TheISA::StackPointerReg); + Addr bottom = ksp & ~0x3fff; + Addr addr; + + if (is_call) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); + + stack.push_back(addr); + pc = tc->readPC(); + } + + Addr ra; + int size; + + while (ksp > bottom) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); + + stack.push_back(addr); + + if (isEntry(addr)) + return; + + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) + return; + + if (size <= 0) { + stack.push_back(unknown); + return; + } + + pc = ra; + ksp += size; + } else { + stack.push_back(unknown); + return; + } + + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; + if (!kernel) + return; + + if (stack.size() >= 1000) + panic("unwinding too far"); + } + + panic("unwinding too far"); +#endif + } + + bool + StackTrace::isEntry(Addr addr) + { +#if 0 + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + return true; +#endif + return false; + } + + bool + StackTrace::decodeStack(MachInst inst, int &disp) + { + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; + + return true; + } + + bool + StackTrace::decodeSave(MachInst inst, int ®, int &disp) + { + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; + } + + return true; + } + + /* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ + bool + StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, + int &size, Addr &ra) + { + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; + } + } + } + } + + return true; + } + +#if TRACING_ON + void + StackTrace::dump() + { + StringWrap name(tc->getCpuPtr()->name()); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == user) + symbol = "user"; + else if (addr == console) + symbol = "console"; + else if (addr == unknown) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); + } + } +#endif +} diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh index 54d3d17be..4bc5d779b 100644 --- a/src/arch/sparc/stacktrace.hh +++ b/src/arch/sparc/stacktrace.hh @@ -35,87 +35,90 @@ #include "cpu/static_inst.hh" class ThreadContext; -class StackTrace; - -class ProcessInfo +namespace SparcISA { - private: - ThreadContext *tc; + class StackTrace; - int thread_info_size; - int task_struct_size; - int task_off; - int pid_off; - int name_off; + class ProcessInfo + { + private: + ThreadContext *tc; - public: - ProcessInfo(ThreadContext *_tc); + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; - Addr task(Addr ksp) const; - int pid(Addr ksp) const; - std::string name(Addr ksp) const; -}; + public: + ProcessInfo(ThreadContext *_tc); -class StackTrace -{ - protected: - typedef TheISA::MachInst MachInst; - private: - ThreadContext *tc; - std::vector<Addr> stack; - - private: - bool isEntry(Addr addr); - bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); - bool decodeSave(MachInst inst, int ®, int &disp); - bool decodeStack(MachInst inst, int &disp); - - void trace(ThreadContext *tc, bool is_call); - - public: - StackTrace(); - StackTrace(ThreadContext *tc, StaticInstPtr inst); - ~StackTrace(); - - void clear() + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; + }; + + class StackTrace { - tc = 0; - stack.clear(); - } + protected: + typedef TheISA::MachInst MachInst; + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); - bool valid() const { return tc != NULL; } - bool trace(ThreadContext *tc, StaticInstPtr inst); + void trace(ThreadContext *tc, bool is_call); - public: - const std::vector<Addr> &getstack() const { return stack; } + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); - static const int user = 1; - static const int console = 2; - static const int unknown = 3; + void clear() + { + tc = 0; + stack.clear(); + } + + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; #if TRACING_ON - private: - void dump(); + private: + void dump(); - public: - void dprintf() { if (DTRACE(Stack)) dump(); } + public: + void dprintf() { if (DTRACE(Stack)) dump(); } #else - public: - void dprintf() {} + public: + void dprintf() {} #endif -}; + }; -inline bool -StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) -{ - if (!inst->isCall() && !inst->isReturn()) - return false; + inline bool + StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) + { + if (!inst->isCall() && !inst->isReturn()) + return false; - if (valid()) - clear(); + if (valid()) + clear(); - trace(tc, !inst->isReturn()); - return true; + trace(tc, !inst->isReturn()); + return true; + } } #endif // __ARCH_SPARC_STACKTRACE_HH__ diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index ef6443d17..4e907f002 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -42,42 +42,49 @@ using namespace BigEndianGuest; SparcSystem::SparcSystem(Params *p) - : System(p), sysTick(0) + : System(p), sysTick(0),funcRomPort(p->name + "-fport") { resetSymtab = new SymbolTable; hypervisorSymtab = new SymbolTable; openbootSymtab = new SymbolTable; + Port *rom_port; + rom_port = params()->rom->getPort("functional"); + funcRomPort.setPeer(rom_port); + rom_port->setPeer(&funcRomPort); /** * Load the boot code, and hypervisor into memory. */ // Read the reset binary - reset = createObjectFile(params()->reset_bin); + reset = createObjectFile(params()->reset_bin, true); if (reset == NULL) fatal("Could not load reset binary %s", params()->reset_bin); // Read the openboot binary - openboot = createObjectFile(params()->openboot_bin); + openboot = createObjectFile(params()->openboot_bin, true); if (openboot == NULL) fatal("Could not load openboot bianry %s", params()->openboot_bin); // Read the hypervisor binary - hypervisor = createObjectFile(params()->hypervisor_bin); + hypervisor = createObjectFile(params()->hypervisor_bin, true); if (hypervisor == NULL) fatal("Could not load hypervisor binary %s", params()->hypervisor_bin); // Load reset binary into memory - reset->loadSections(&functionalPort, SparcISA::LoadAddrMask); + reset->setTextBase(params()->reset_addr); + reset->loadSections(&funcRomPort); // Load the openboot binary - openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask); + openboot->setTextBase(params()->openboot_addr); + openboot->loadSections(&funcRomPort); // Load the hypervisor binary - hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); + hypervisor->setTextBase(params()->hypervisor_addr); + hypervisor->loadSections(&funcRomPort); // load symbols - if (!reset->loadGlobalSymbols(reset)) + if (!reset->loadGlobalSymbols(resetSymtab)) panic("could not load reset symbols\n"); if (!openboot->loadGlobalSymbols(openbootSymtab)) @@ -141,13 +148,19 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<PhysicalMemory *> rom; SimpleEnumParam<System::MemoryMode> mem_mode; + Param<Addr> reset_addr; + Param<Addr> hypervisor_addr; + Param<Addr> openboot_addr; + Param<std::string> kernel; Param<std::string> reset_bin; Param<std::string> hypervisor_bin; Param<std::string> openboot_bin; + Param<Tick> boot_cpu_frequency; Param<std::string> boot_osflags; Param<std::string> readfile; Param<unsigned int> init_param; @@ -156,20 +169,24 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) - INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_PARAM(rom, "ROM for boot code"), INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", System::MemoryModeStrings), + + INIT_PARAM(reset_addr, "Address that reset should be loaded at"), + INIT_PARAM(hypervisor_addr, "Address that hypervisor should be loaded at"), + INIT_PARAM(openboot_addr, "Address that openboot should be loaded at"), + INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), INIT_PARAM(openboot_bin, "file that contains the openboot code"), + INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), - INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) + INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0) END_INIT_SIM_OBJECT_PARAMS(SparcSystem) @@ -179,16 +196,18 @@ CREATE_SIM_OBJECT(SparcSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->rom = rom; p->mem_mode = mem_mode; p->kernel_path = kernel; + p->reset_addr = reset_addr; + p->hypervisor_addr = hypervisor_addr; + p->openboot_addr = openboot_addr; p->reset_bin = reset_bin; p->hypervisor_bin = hypervisor_bin; p->openboot_bin = openboot_bin; p->boot_osflags = boot_osflags; p->init_param = init_param; p->readfile = readfile; - p->system_type = system_type; - p->system_rev = system_rev; return new SparcSystem(p); } diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 614707f6c..9cf3bb568 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -45,12 +45,14 @@ class SparcSystem : public System public: struct Params : public System::Params { + PhysicalMemory *rom; + Addr reset_addr; + Addr hypervisor_addr; + Addr openboot_addr; std::string reset_bin; - std::string hypervison_bin; + std::string hypervisor_bin; std::string openboot_bin; std::string boot_osflags; - uint64_t system_type; - uint64_t system_rev; }; SparcSystem(Params *p); @@ -87,6 +89,9 @@ class SparcSystem : public System /** System Tick for syncronized tick across all cpus. */ Tick sysTick; + /** functional port to ROM */ + FunctionalPort funcRomPort; + protected: const Params *params() const { return (const Params *)_params; } @@ -111,8 +116,11 @@ class SparcSystem : public System return addFuncEvent<T>(openbootSymtab, lbl); } - virtual Addr fixFuncEventAddr(Addr addr); - + virtual Addr fixFuncEventAddr(Addr addr) + { + //XXX This may eventually have to do something useful. + return addr; + } }; #endif diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc new file mode 100644 index 000000000..0b1a2ff5f --- /dev/null +++ b/src/arch/sparc/tlb.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001-2005 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: Nathan Binkert + * Steve Reinhardt + * Andrew Schultz + */ + +#include "arch/sparc/tlb.hh" +#include "sim/builder.hh" + +namespace SparcISA +{ + 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) +} diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 35ff08b43..0fdba6baf 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -31,5 +31,47 @@ #ifndef __ARCH_SPARC_TLB_HH__ #define __ARCH_SPARC_TLB_HH__ +#include "mem/request.hh" +#include "sim/faults.hh" +#include "sim/sim_object.hh" + +class ThreadContext; + +namespace SparcISA +{ + class TLB : public SimObject + { + public: + TLB(const std::string &name, int size) : SimObject(name) + { + } + }; + + class ITB : public TLB + { + public: + ITB(const std::string &name, int size) : TLB(name, size) + { + } + + Fault translate(RequestPtr &req, ThreadContext *tc) const + { + return NoFault; + } + }; + + class DTB : public TLB + { + public: + DTB(const std::string &name, int size) : TLB(name, size) + { + } + + Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const + { + return NoFault; + } + }; +} #endif // __ARCH_SPARC_TLB_HH__ diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 23fddf0e9..e51677cdf 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_SPARC_UTILITY_HH__ #define __ARCH_SPARC_UTILITY_HH__ +#include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "base/misc.hh" #include "base/bitfield.hh" @@ -38,6 +39,14 @@ namespace SparcISA { + + static inline bool + inUserMode(ThreadContext *tc) + { + return !(tc->readMiscReg(MISCREG_PSTATE & (1 << 2)) || + tc->readMiscReg(MISCREG_HPSTATE & (1 << 2))); + } + inline ExtMachInst makeExtMI(MachInst inst, ThreadContext * xc) { ExtMachInst emi = (unsigned MachInst) inst; @@ -99,6 +108,12 @@ namespace SparcISA template <class TC> void zeroRegisters(TC *tc); + inline void initCPU(ThreadContext *tc, int cpuId) + { + static Fault por = new PowerOnReset(); + por->invoke(tc); + } + } // namespace SparcISA #endif diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index f7fd92c15..429126b70 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -32,135 +32,47 @@ #include <string> -#include "arch/alpha/ev5.hh" -#include "arch/alpha/vtophys.hh" +#include "arch/sparc/vtophys.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "mem/vport.hh" using namespace std; -using namespace AlphaISA; -AlphaISA::PageTableEntry -AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr) +namespace SparcISA { - Addr level1_pte = ptbr + vaddr.level1(); - AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte); - if (!level1.valid()) { - DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); - return 0; + PageTableEntry kernel_pte_lookup(FunctionalPort *mem, + Addr ptbr, VAddr vaddr) + { + PageTableEntry pte(4); + return pte; } - Addr level2_pte = level1.paddr() + vaddr.level2(); - AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte); - if (!level2.valid()) { - DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(Addr vaddr) + { + return vaddr; } - Addr level3_pte = level2.paddr() + vaddr.level3(); - AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte); - if (!level3.valid()) { - DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(ThreadContext *tc, Addr addr) + { + return addr; } - return level3; -} -Addr -AlphaISA::vtophys(Addr vaddr) -{ - Addr paddr = 0; - if (AlphaISA::IsUSeg(vaddr)) - DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); - else if (AlphaISA::IsK0Seg(vaddr)) - paddr = AlphaISA::K0Seg2Phys(vaddr); - else - panic("vtophys: ptbr is not set on virtual lookup"); - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - -Addr -AlphaISA::vtophys(ThreadContext *tc, Addr addr) -{ - AlphaISA::VAddr vaddr = addr; - Addr ptbr = tc->readMiscReg(AlphaISA::IPR_PALtemp20); - Addr paddr = 0; - //@todo Andrew couldn't remember why he commented some of this code - //so I put it back in. Perhaps something to do with gdb debugging? - if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { - paddr = vaddr & ~ULL(1); - } else { - if (AlphaISA::IsK0Seg(vaddr)) { - paddr = AlphaISA::K0Seg2Phys(vaddr); - } else if (!ptbr) { - paddr = vaddr; - } else { - AlphaISA::PageTableEntry pte = - kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); - if (pte.valid()) - paddr = pte.paddr() | vaddr.offset(); - } + void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) + { } + void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) + { + } - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - - -void -AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) -{ - uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->readBlob(src, dst, cplen); - - tc->delVirtPort(vp); - -} - -void -AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) -{ - uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->writeBlob(dest, src, cplen); - - tc->delVirtPort(vp); -} - -void -AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) -{ - int len = 0; - VirtualPort *vp = tc->getVirtPort(tc); - - do { - vp->readBlob(vaddr++, (uint8_t*)dst++, 1); - len++; - } while (len < maxlen && dst[len] != 0 ); - - tc->delVirtPort(vp); - dst[len] = 0; -} + void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) + { + } -void -AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) -{ - VirtualPort *vp = tc->getVirtPort(tc); - for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done(); - gen.next()) + void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) { - vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); - src += gen.size(); } - tc->delVirtPort(vp); } |