diff options
Diffstat (limited to 'src/arch/sparc')
45 files changed, 3066 insertions, 1502 deletions
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 555bfba3d..e342c79cf 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -29,65 +29,38 @@ # Authors: Gabe Black # Steve Reinhardt -import os -import sys -from os.path import isdir +Import('*') -# Import build environment variable from SConstruct. -Import('env') +if env['TARGET_ISA'] == 'sparc': + Source('asi.cc') + Source('faults.cc') + Source('floatregfile.cc') + Source('intregfile.cc') + Source('miscregfile.cc') + Source('regfile.cc') + Source('remote_gdb.cc') -################################################### -# -# Define needed sources. -# -################################################### - -# Base sources used by all configurations. -base_sources = Split(''' - asi.cc - faults.cc - floatregfile.cc - intregfile.cc - miscregfile.cc - regfile.cc - remote_gdb.cc - ''') - -# Full-system sources -full_system_sources = Split(''' - arguments.cc - pagetable.cc - stacktrace.cc - system.cc - tlb.cc - ua2005.cc - vtophys.cc - ''') - -# Syscall emulation (non-full-system) sources -syscall_emulation_sources = Split(''' - linux/linux.cc - linux/process.cc - process.cc - solaris/process.cc - solaris/solaris.cc - ''') - -sources = base_sources - -if env['FULL_SYSTEM']: - sources += full_system_sources -else: - sources += syscall_emulation_sources + if env['FULL_SYSTEM']: + Source('arguments.cc') + Source('pagetable.cc') + Source('stacktrace.cc') + Source('system.cc') + Source('tlb.cc') + Source('ua2005.cc') + Source('vtophys.cc') + else: + Source('process.cc') -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] + Source('linux/linux.cc') + Source('linux/process.cc') + Source('linux/syscalls.cc') -# Add in files generated by the ISA description. -isa_desc_files = env.ISADesc('isa/main.isa') -# Only non-header files need to be compiled. -isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] -sources += isa_desc_sources + Source('solaris/process.cc') + Source('solaris/solaris.cc') -Return('sources') + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/src/arch/sparc/SConsopts b/src/arch/sparc/SConsopts new file mode 100644 index 000000000..c35606281 --- /dev/null +++ b/src/arch/sparc/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# 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: Nathan Binkert + +Import('*') + +all_isa_list.append('sparc') diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh index 8f925dd25..5596f7408 100644 --- a/src/arch/sparc/arguments.hh +++ b/src/arch/sparc/arguments.hh @@ -33,9 +33,9 @@ #include <assert.h> -#include "arch/sparc/vtophys.hh" #include "base/refcnt.hh" #include "sim/host.hh" +#include "mem/vport.hh" class ThreadContext; diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc index 3d553955f..254635bff 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -247,7 +247,8 @@ namespace SparcISA bool AsiIsCmt(ASI asi) { return - (asi == ASI_CMT_PER_STRAND); + (asi == ASI_CMT_PER_STRAND) || + (asi == ASI_CMT_SHARED); } bool AsiIsQueue(ASI asi) @@ -294,7 +295,9 @@ namespace SparcISA bool AsiIsReg(ASI asi) { - return AsiIsMmu(asi) || AsiIsScratchPad(asi) | AsiIsSparcError(asi); + return AsiIsMmu(asi) || AsiIsScratchPad(asi) || + AsiIsSparcError(asi) || AsiIsInterrupt(asi) + || AsiIsCmt(asi); } bool AsiIsSparcError(ASI asi) diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 166c3867e..eba2d518f 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -115,6 +115,7 @@ namespace SparcISA ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1 = 0x3E, ASI_IMMU_CTXT_NONZERO_CONFIG = 0x3F, ASI_STREAM_MA = 0x40, + ASI_CMT_SHARED = 0x41, //0x41 implementation dependent ASI_SPARC_BIST_CONTROL = 0x42, ASI_INST_MASK_REG = 0x42, diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index a6f4343ae..88c086090 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -208,6 +208,10 @@ template<> SparcFaultBase::FaultVals {"trap_level_zero", 0x05F, 202, {H, H, SH}}; template<> SparcFaultBase::FaultVals + SparcFault<InterruptVector>::vals = + {"interrupt_vector", 0x060, 2630, {H, H, H}}; + +template<> SparcFaultBase::FaultVals SparcFault<PAWatchpoint>::vals = {"PA_watchpoint", 0x061, 1209, {H, H, H}}; @@ -263,12 +267,6 @@ template<> SparcFaultBase::FaultVals SparcFault<TrapInstruction>::vals = {"trap_instruction", 0x100, 1602, {P, P, H}}; -#if !FULL_SYSTEM -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. @@ -278,17 +276,17 @@ void enterREDState(ThreadContext *tc) { //@todo Disable the mmu? //@todo Disable watchpoints? - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); //HPSTATE.red = 1 HPSTATE |= (1 << 5); //HPSTATE.hpriv = 1 HPSTATE |= (1 << 2); - tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE); + tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); //PSTATE.priv is set to 1 here. The manual says it should be 0, but //Legion sets it to 1. - MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE |= (1 << 2); - tc->setMiscRegWithEffect(MISCREG_PSTATE, PSTATE); + tc->setMiscReg(MISCREG_PSTATE, PSTATE); } /** @@ -298,17 +296,17 @@ void enterREDState(ThreadContext *tc) 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 TL = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); - MiscReg ASI = tc->readMiscReg(MISCREG_ASI); - MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); - MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3); - MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); + MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); + //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3); + MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -331,25 +329,25 @@ void doREDFault(ThreadContext *tc, TrapType tt) replaceBits(TSTATE, 4, 0, CWP); //Write back TSTATE - tc->setMiscReg(MISCREG_TSTATE, TSTATE); + tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscReg(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, PC); //set TNPC to NPC - tc->setMiscReg(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); //set HTSTATE.hpstate to hpstate - tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); //TT = trap type; - tc->setMiscReg(MISCREG_TT, tt); + tc->setMiscRegNoEffect(MISCREG_TT, tt); //Update GL - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit PSTATE |= (1 << 4); //set PSTATE.pef to 1 - tc->setMiscReg(MISCREG_PSTATE, PSTATE); + tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); //set HPSTATE.red to 1 HPSTATE |= (1 << 5); @@ -359,7 +357,7 @@ void doREDFault(ThreadContext *tc, TrapType tt) HPSTATE &= ~(1 << 10); //set HPSTATE.tlz to 0 HPSTATE &= ~(1 << 0); - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); bool changedCWP = true; if(tt == 0x24) @@ -374,7 +372,7 @@ void doREDFault(ThreadContext *tc, TrapType tt) if(changedCWP) { CWP = (CWP + NWindows) % NWindows; - tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + tc->setMiscReg(MISCREG_CWP, CWP); } } @@ -385,17 +383,17 @@ void doREDFault(ThreadContext *tc, TrapType tt) void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) { - 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 TL = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); - MiscReg ASI = tc->readMiscReg(MISCREG_ASI); - MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); + MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); + //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); - MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -406,7 +404,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) //Increment the trap level TL++; - tc->setMiscReg(MISCREG_TL, TL); + tc->setMiscRegNoEffect(MISCREG_TL, TL); //Save off state @@ -422,24 +420,24 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) replaceBits(TSTATE, 4, 0, CWP); //Write back TSTATE - tc->setMiscReg(MISCREG_TSTATE, TSTATE); + tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscReg(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, PC); //set TNPC to NPC - tc->setMiscReg(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); //set HTSTATE.hpstate to hpstate - tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); //TT = trap type; - tc->setMiscReg(MISCREG_TT, tt); + tc->setMiscRegNoEffect(MISCREG_TT, tt); //Update the global register level if (!gotoHpriv) - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxPGL)); else - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); //PSTATE.mm is unchanged PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present @@ -456,12 +454,12 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1 HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0 //HPSTATE.tlz is unchanged - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); } else { // we are going to priv PSTATE |= (1 << 2); //PSTATE.priv = 1 replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle } - tc->setMiscReg(MISCREG_PSTATE, PSTATE); + tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); bool changedCWP = true; @@ -477,7 +475,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) if (changedCWP) { CWP = (CWP + NWindows) % NWindows; - tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + tc->setMiscReg(MISCREG_CWP, CWP); } } @@ -491,14 +489,14 @@ void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT) { - Addr HTBA = tc->readMiscReg(MISCREG_HTBA); + Addr HTBA = tc->readMiscRegNoEffect(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); + Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA); PC = (TBA & ~mask(15)) | (TL > 1 ? (1 << 14) : 0) | ((TT << 5) & mask(14)); @@ -515,10 +513,10 @@ void SparcFaultBase::invoke(ThreadContext * tc) //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); + MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT); + MiscReg pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); Addr PC, NPC; @@ -567,15 +565,15 @@ void PowerOnReset::invoke(ThreadContext * tc) //on reset Trap which sets the processor into the following state. //Bits that aren't set aren't defined on startup. - tc->setMiscReg(MISCREG_TL, MaxTL); - tc->setMiscReg(MISCREG_TT, trapType()); - tc->setMiscRegWithEffect(MISCREG_GL, MaxGL); + tc->setMiscRegNoEffect(MISCREG_TL, MaxTL); + tc->setMiscRegNoEffect(MISCREG_TT, trapType()); + tc->setMiscReg(MISCREG_GL, MaxGL); //Turn on pef and priv, set everything else to 0 - tc->setMiscReg(MISCREG_PSTATE, (1 << 4) | (1 << 2)); + tc->setMiscRegNoEffect(MISCREG_PSTATE, (1 << 4) | (1 << 2)); //Turn on red and hpriv, set everything else to 0 - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); //HPSTATE.red = 1 HPSTATE |= (1 << 5); //HPSTATE.hpriv = 1 @@ -584,10 +582,10 @@ void PowerOnReset::invoke(ThreadContext * tc) HPSTATE &= ~(1 << 10); //HPSTATE.tlz = 0 HPSTATE &= ~(1 << 0); - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); //The tick register is unreadable by nonprivileged software - tc->setMiscReg(MISCREG_TICK, 1ULL << 63); + tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63); //Enter RED state. We do this last so that the actual state preserved in //the trap stack is the state from before this fault. @@ -605,7 +603,7 @@ void PowerOnReset::invoke(ThreadContext * tc) // Clear all the soft interrupt bits softint = 0; // disable timer compare interrupts, reset tick_cmpr - tc->setMiscReg(MISCREG_ + tc->setMiscRegNoEffect(MISCREG_ tick_cmprFields.int_dis = 1; tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing stickFields.npt = 1; //The TICK register is unreadable by by !priv @@ -656,26 +654,24 @@ void FillNNormal::invoke(ThreadContext *tc) tc->setNextNPC(fillStart + 2*sizeof(MachInst)); } -void PageTableFault::invoke(ThreadContext *tc) +void TrapInstruction::invoke(ThreadContext *tc) { + //In SE, this mechanism is how the process requests a service from the + //operating system. We'll get the process object from the thread context + //and let it service the request. + Process *p = tc->getProcessPtr(); - // We've accessed the next page of the stack, so extend the stack - // to cover it. - if(vaddr < p->stack_min && vaddr >= p->stack_min - PageBytes) - { - p->stack_min -= PageBytes; - if(p->stack_base - p->stack_min > 8*1024*1024) - fatal("Over max stack size for one thread\n"); - p->pTable->allocate(p->stack_min, PageBytes); - warn("Increasing stack size by one page."); - } - // Otherwise, we have an unexpected page fault. Report that fact, - // and what address was accessed to cause the fault. - else - { - panic("Page table fault when accessing virtual address %#x\n", vaddr); - } + SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); + assert(lp); + + lp->handleTrap(_n, tc); + + //We need to explicitly advance the pc, since that's not done for us + //on a faulting instruction + tc->setPC(tc->readNextPC()); + tc->setNextPC(tc->readNextNPC()); + tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst)); } #endif diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 3c0d9674f..10ef89279 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -193,6 +193,8 @@ class HstickMatch : public SparcFault<HstickMatch> {}; class TrapLevelZero : public SparcFault<TrapLevelZero> {}; +class InterruptVector : public SparcFault<InterruptVector> {}; + class PAWatchpoint : public SparcFault<PAWatchpoint> {}; class VAWatchpoint : public SparcFault<VAWatchpoint> {}; @@ -246,26 +248,13 @@ class FillNOther : public EnumeratedFault<FillNOther> class TrapInstruction : public EnumeratedFault<TrapInstruction> { - public: TrapInstruction(uint32_t n) : EnumeratedFault<TrapInstruction>(n) {;} -}; - + //In SE, trap instructions are requesting services from the OS. #if !FULL_SYSTEM -class PageTableFault : public SparcFault<PageTableFault> -{ - private: - Addr vaddr; - public: - PageTableFault(Addr va) : vaddr(va) {} void invoke(ThreadContext * tc); -}; - -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} #endif +}; static inline Fault genMachineCheckFault() { diff --git a/src/arch/sparc/handlers.hh b/src/arch/sparc/handlers.hh new file mode 100644 index 000000000..ce5b69427 --- /dev/null +++ b/src/arch/sparc/handlers.hh @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2003-2004 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_HANDLERS_HH__ +#define __ARCH_SPARC_HANDLERS_HH__ + +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" +#include "sim/byteswap.hh" + +namespace SparcISA { + +//We only use 19 instructions for the trap handlers, but there would be +//space for 32 in a real SPARC trap table. +const int numFillInsts = 32; +const int numSpillInsts = 32; + +const MachInst fillHandler64[numFillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 + htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 + htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 + htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3 + htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4 + htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5 + htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6 + htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7 + htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0 + htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1 + htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2 + htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3 + htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4 + htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5 + htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6 + htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7 + htog(0x83880000), //restored + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst fillHandler32[numFillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe083a000), //lduwa [%sp + (0*4)] %asi, %l0 + htog(0xe283a004), //lduwa [%sp + (1*4)] %asi, %l1 + htog(0xe483a008), //lduwa [%sp + (2*4)] %asi, %l2 + htog(0xe683a00c), //lduwa [%sp + (3*4)] %asi, %l3 + htog(0xe883a010), //lduwa [%sp + (4*4)] %asi, %l4 + htog(0xea83a014), //lduwa [%sp + (5*4)] %asi, %l5 + htog(0xec83a018), //lduwa [%sp + (6*4)] %asi, %l6 + htog(0xee83a01c), //lduwa [%sp + (7*4)] %asi, %l7 + htog(0xf083a020), //lduwa [%sp + (8*4)] %asi, %i0 + htog(0xf283a024), //lduwa [%sp + (9*4)] %asi, %i1 + htog(0xf483a028), //lduwa [%sp + (10*4)] %asi, %i2 + htog(0xf683a02c), //lduwa [%sp + (11*4)] %asi, %i3 + htog(0xf883a030), //lduwa [%sp + (12*4)] %asi, %i4 + htog(0xfa83a034), //lduwa [%sp + (13*4)] %asi, %i5 + htog(0xfc83a038), //lduwa [%sp + (14*4)] %asi, %i6 + htog(0xfe83a03c), //lduwa [%sp + (15*4)] %asi, %i7 + htog(0x83880000), //restored + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst spillHandler64[numSpillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi + htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi + htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi + htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi + htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi + htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi + htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi + htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi + htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi + htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi + htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi + htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi + htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi + htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi + htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi + htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi + htog(0x81880000), //saved + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst spillHandler32[numSpillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0a3a000), //stwa %l0, [%sp + (0*4)] %asi + htog(0xe2a3a004), //stwa %l1, [%sp + (1*4)] %asi + htog(0xe4a3a008), //stwa %l2, [%sp + (2*4)] %asi + htog(0xe6a3a00c), //stwa %l3, [%sp + (3*4)] %asi + htog(0xe8a3a010), //stwa %l4, [%sp + (4*4)] %asi + htog(0xeaa3a014), //stwa %l5, [%sp + (5*4)] %asi + htog(0xeca3a018), //stwa %l6, [%sp + (6*4)] %asi + htog(0xeea3a01c), //stwa %l7, [%sp + (7*4)] %asi + htog(0xf0a3a020), //stwa %i0, [%sp + (8*4)] %asi + htog(0xf2a3a024), //stwa %i1, [%sp + (9*4)] %asi + htog(0xf4a3a028), //stwa %i2, [%sp + (10*4)] %asi + htog(0xf6a3a02c), //stwa %i3, [%sp + (11*4)] %asi + htog(0xf8a3a030), //stwa %i4, [%sp + (12*4)] %asi + htog(0xfaa3a034), //stwa %i5, [%sp + (13*4)] %asi + htog(0xfca3a038), //stwa %i6, [%sp + (14*4)] %asi + htog(0xfea3a03c), //stwa %i7, [%sp + (15*4)] %asi + htog(0x81880000), //saved + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +} // namespace SparcISA +#endif // __ARCH_SPARC_HANDLERS_HH__ diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index dc3b235fe..4ad3385fb 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -24,82 +24,86 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Lisa Hsu */ #ifndef __ARCH_SPARC_INTERRUPT_HH__ #define __ARCH_SPARC_INTERRUPT_HH__ #include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" #include "cpu/thread_context.hh" namespace SparcISA { -enum interrupts_t { - trap_level_zero, - hstick_match, - interrupt_vector, - cpu_mondo, - dev_mondo, - resumable_error, - soft_interrupt, - num_interrupt_types -}; - class Interrupts { private: - bool interrupts[num_interrupt_types]; - int numPosted; + uint64_t interrupts[NumInterruptTypes]; + uint64_t intStatus; public: Interrupts() { - for (int i = 0; i < num_interrupt_types; ++i) { - interrupts[i] = false; - } - numPosted = 0; + clear_all(); } - void post(int int_type) + int InterruptLevel(uint64_t softint) { - if (int_type < 0 || int_type >= num_interrupt_types) - panic("posting unknown interrupt!\n"); - if (interrupts[int_type] == false) { - interrupts[int_type] = true; - ++numPosted; - } + if (softint & 0x10000 || softint & 0x1) + return 14; + + int level = 15; + while (level > 0 && !(1 << level & softint)) + level--; + if (1 << level & softint) + return level; + return 0; } void post(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + assert(int_num >= 0 && int_num < NumInterruptTypes); + assert(index >= 0 && index < 64); + interrupts[int_num] |= ULL(1) << index; + intStatus |= ULL(1) << int_num; } void clear(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + assert(int_num >= 0 && int_num < NumInterruptTypes); + assert(index >= 0 && index < 64); + interrupts[int_num] &= ~(ULL(1) << index); + if (!interrupts[int_num]) + intStatus &= ~(ULL(1) << int_num); } void clear_all() { - + for (int i = 0; i < NumInterruptTypes; ++i) { + interrupts[i] = 0; + } + intStatus = 0; } bool check_interrupts(ThreadContext * tc) const { - if (numPosted) - return true; - else - return false; + return intStatus; } Fault getInterrupt(ThreadContext * tc) { - int hpstate = tc->readMiscReg(MISCREG_HPSTATE); - int pstate = tc->readMiscReg(MISCREG_PSTATE); + int hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + int pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); bool ie = pstate & PSTATE::ie; // THESE ARE IN ORDER OF PRIORITY @@ -109,84 +113,45 @@ class Interrupts // in the right order of processing if (hpstate & HPSTATE::hpriv) { if (ie) { - if (interrupts[hstick_match]) { - if (tc->readMiscReg(MISCREG_HINTP) & 1) { - interrupts[hstick_match] = false; - --numPosted; - return new HstickMatch; - } - } - if (interrupts[interrupt_vector]) { - interrupts[interrupt_vector] = false; - --numPosted; - //HAVEN'T IMPLed THIS YET - return NoFault; + if (interrupts[IT_HINTP]) { + // This will be cleaned by a HINTP write + return new HstickMatch; } - } else { - if (interrupts[hstick_match]) { - return NoFault; + if (interrupts[IT_INT_VEC]) { + // this will be cleared by an ASI read (or write) + return new InterruptVector; } - } } else { - if (interrupts[trap_level_zero]) { - if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) { - interrupts[trap_level_zero] = false; - --numPosted; + if (interrupts[IT_TRAP_LEVEL_ZERO]) { + // this is cleared by deasserting HPSTATE::tlz return new TrapLevelZero; - } } - if (interrupts[hstick_match]) { - if (tc->readMiscReg(MISCREG_HINTP) & 1) { - interrupts[hstick_match] = false; - --numPosted; - return new HstickMatch; - } + // HStick matches always happen in priv mode (ie doesn't matter) + if (interrupts[IT_HINTP]) { + return new HstickMatch; + } + if (interrupts[IT_INT_VEC]) { + // this will be cleared by an ASI read (or write) + return new InterruptVector; } if (ie) { - if (interrupts[cpu_mondo]) { - interrupts[cpu_mondo] = false; - --numPosted; + if (interrupts[IT_CPU_MONDO]) { return new CpuMondo; } - if (interrupts[dev_mondo]) { - interrupts[dev_mondo] = false; - --numPosted; + if (interrupts[IT_DEV_MONDO]) { return new DevMondo; } - if (interrupts[soft_interrupt]) { - int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); - // it seems that interrupt vectors are right in - // the middle of interrupt levels with regard to - // priority, so have to check - if ((il < 6) && - interrupts[interrupt_vector]) { - // may require more details here since there - // may be lots of interrupts embedded in an - // platform interrupt vector - interrupts[interrupt_vector] = false; - --numPosted; - //HAVEN'T IMPLed YET - return NoFault; - } else { - if (il > tc->readMiscReg(MISCREG_PIL)) { - uint64_t si = tc->readMiscReg(MISCREG_SOFTINT); - uint64_t more = si & ~(1 << (il + 1)); - if (!InterruptLevel(more)) { - interrupts[soft_interrupt] = false; - --numPosted; - } - return new InterruptLevelN(il); - } - } + if (interrupts[IT_SOFT_INT]) { + return new + InterruptLevelN(InterruptLevel(interrupts[IT_SOFT_INT])); } - if (interrupts[resumable_error]) { - interrupts[resumable_error] = false; - --numPosted; + + if (interrupts[IT_RES_ERROR]) { return new ResumableError; } - } - } + } // !hpriv && ie + } // !hpriv return NoFault; } @@ -195,16 +160,22 @@ class Interrupts } + uint64_t get_vec(int int_num) + { + assert(int_num >= 0 && int_num < NumInterruptTypes); + return interrupts[int_num]; + } + void serialize(std::ostream &os) { - SERIALIZE_ARRAY(interrupts,num_interrupt_types); - SERIALIZE_SCALAR(numPosted); + SERIALIZE_ARRAY(interrupts,NumInterruptTypes); + SERIALIZE_SCALAR(intStatus); } void unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(interrupts,num_interrupt_types); - UNSERIALIZE_SCALAR(numPosted); + UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes); + UNSERIALIZE_SCALAR(intStatus); } }; } // namespace SPARC_ISA diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 665c7aa31..83ef1d17b 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -82,7 +82,7 @@ namespace SparcISA IntReg * regView[NumFrames]; static const int RegGlobalOffset = 0; - static const int FrameOffset = MaxGL * RegsPerFrame; + static const int FrameOffset = (MaxGL + 1) * RegsPerFrame; int offset[NumFrames]; public: diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 693cc6876..bba63f407 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -492,8 +492,8 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (xc->readMiscRegWithEffect(MISCREG_PSTATE) & PSTATE::pef && - xc->readMiscRegWithEffect(MISCREG_FPRS) & 0x4) + if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef && + xc->readMiscReg(MISCREG_FPRS) & 0x4) return NoFault; else return new FpDisabled; diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index e75680d2b..afa8f88a2 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -54,6 +54,7 @@ def bitfield FCN <29:25>; def bitfield I <13>; def bitfield IMM_ASI <12:5>; def bitfield IMM22 <21:0>; +def bitfield M5FUNC <15:7>; def bitfield MMASK <3:0>; def bitfield OP <31:30>; def bitfield OP2 <24:22>; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index fb606c7cc..556bb4bca 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -185,25 +185,25 @@ decode OP default Unknown::unknown() }}, ',a'); } default: decode BPCC { - 0x0: fbpcc0(22, {{ + 0x0: fbpfcc0(19, {{ if(passesFpCondition(Fsr<11:10>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x1: fbpcc1(22, {{ + 0x1: fbpfcc1(19, {{ if(passesFpCondition(Fsr<33:32>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x2: fbpcc2(22, {{ + 0x2: fbpfcc2(19, {{ if(passesFpCondition(Fsr<35:34>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x3: fbpcc3(22, {{ + 0x3: fbpfcc3(19, {{ if(passesFpCondition(Fsr<37:36>, COND2)) NNPC = xc->readPC() + disp; else @@ -426,19 +426,22 @@ decode OP default Unknown::unknown() {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} ); 0x24: mulscc({{ - int64_t resTemp, multiplicand = Rs2_or_imm13; - int32_t multiplier = Rs1<31:0>; int32_t savedLSB = Rs1<0:>; - multiplier = multiplier<31:1> | - ((Ccr<3:3> ^ Ccr<1:1>) << 32); - if(!Y<0:>) - multiplicand = 0; - Rd = resTemp = multiplicand + multiplier; + + //Step 1 + int64_t multiplicand = Rs2_or_imm13; + //Step 2 + int32_t partialP = Rs1<31:1> | + ((Ccr<3:3> ^ Ccr<1:1>) << 31); + //Step 3 + int32_t added = Y<0:> ? multiplicand : 0; + Rd = partialP + added; + //Steps 4 & 5 Y = Y<31:1> | (savedLSB << 31);}}, - {{((multiplicand<31:0> + multiplier<31:0>)<32:0>)}}, - {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}}, - {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}}, - {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}} + {{((partialP<31:0> + added<31:0>)<32:0>)}}, + {{partialP<31:> == added<31:> && added<31:> != Rd<31:>}}, + {{((partialP >> 1) + (added >> 1) + (partialP & added & 0x1))<63:>}}, + {{partialP<63:> == added<63:> && partialP<63:> != Rd<63:>}} ); } format IntOp @@ -472,8 +475,8 @@ decode OP default Unknown::unknown() }}); //7-14 should cause an illegal instruction exception 0x0F: decode I { - 0x0: Nop::stbar({{/*stuff*/}}); - 0x1: Nop::membar({{/*stuff*/}}); + 0x0: Nop::stbar({{/*stuff*/}}, IsWriteBarrier, MemWriteOp); + 0x1: Nop::membar({{/*stuff*/}}, IsMemBarrier, MemReadOp); } 0x10: Priv::rdpcr({{Rd = Pcr;}}); 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}}); @@ -620,10 +623,6 @@ decode OP default Unknown::unknown() }}); 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); 0x1A: Priv::wrstrand_sts_reg({{ - if(Pstate<2:> && !Hpstate<2:>) - StrandStsReg = StrandStsReg<63:1> | - (Rs1 ^ Rs2_or_imm13)<0:>; - else StrandStsReg = Rs1 ^ Rs2_or_imm13; }}); //0x1A is supposed to be reserved, but it writes the strand @@ -820,6 +819,58 @@ decode OP default Unknown::unknown() } 0x35: decode OPF{ format FpBasic{ + 0x01: fmovs_fcc0({{ + if(passesFpCondition(Fsr<11:10>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x02: fmovd_fcc0({{ + if(passesFpCondition(Fsr<11:10>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x03: FpUnimpl::fmovq_fcc0(); + 0x25: fmovrsz({{ + if(Rs1 == 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x26: fmovrdz({{ + if(Rs1 == 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x27: FpUnimpl::fmovrqz(); + 0x41: fmovs_fcc1({{ + if(passesFpCondition(Fsr<33:32>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x42: fmovd_fcc1({{ + if(passesFpCondition(Fsr<33:32>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x43: FpUnimpl::fmovq_fcc1(); + 0x45: fmovrslez({{ + if(Rs1 <= 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x46: fmovrdlez({{ + if(Rs1 <= 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x47: FpUnimpl::fmovrqlez(); 0x51: fcmps({{ uint8_t fcc; if(isnan(Frs1s) || isnan(Frs2s)) @@ -878,6 +929,110 @@ decode OP default Unknown::unknown() Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); }}); 0x57: FpUnimpl::fcmpeq(); + 0x65: fmovrslz({{ + if(Rs1 < 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x66: fmovrdlz({{ + if(Rs1 < 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x67: FpUnimpl::fmovrqlz(); + 0x81: fmovs_fcc2({{ + if(passesFpCondition(Fsr<35:34>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x82: fmovd_fcc2({{ + if(passesFpCondition(Fsr<35:34>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x83: FpUnimpl::fmovq_fcc2(); + 0xA5: fmovrsnz({{ + if(Rs1 != 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xA6: fmovrdnz({{ + if(Rs1 != 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xA7: FpUnimpl::fmovrqnz(); + 0xC1: fmovs_fcc3({{ + if(passesFpCondition(Fsr<37:36>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xC2: fmovd_fcc3({{ + if(passesFpCondition(Fsr<37:36>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xC3: FpUnimpl::fmovq_fcc3(); + 0xC5: fmovrsgz({{ + if(Rs1 > 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xC6: fmovrdgz({{ + if(Rs1 > 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xC7: FpUnimpl::fmovrqgz(); + 0xE5: fmovrsgez({{ + if(Rs1 >= 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xE6: fmovrdgez({{ + if(Rs1 >= 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xE7: FpUnimpl::fmovrqgez(); + 0x101: fmovs_icc({{ + if(passesCondition(Ccr<3:0>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x102: fmovd_icc({{ + if(passesCondition(Ccr<3:0>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x103: FpUnimpl::fmovq_icc(); + 0x181: fmovs_xcc({{ + if(passesCondition(Ccr<7:4>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x182: fmovd_xcc({{ + if(passesCondition(Ccr<7:4>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x183: FpUnimpl::fmovq_xcc(); default: FailUnimpl::fpop2(); } } @@ -1009,7 +1164,25 @@ decode OP default Unknown::unknown() 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); 0x81: FailUnimpl::siam(); } - 0x37: Trap::impdep2({{fault = new IllegalInstruction;}}); + // M5 special opcodes use the reserved IMPDEP2A opcode space + 0x37: decode M5FUNC { +#if FULL_SYSTEM + format BasicOperate { + // we have 7 bits of space here to play with... + 0x21: m5exit({{PseudoInst::m5exit(xc->tcBase(), O0); + }}, No_OpClass, IsNonSpeculative); + 0x50: m5readfile({{ + O0 = PseudoInst::readfile(xc->tcBase(), O0, O1, O2); + }}, IsNonSpeculative); + 0x51: m5break({{PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x54: m5panic({{ + panic("M5 panic instruction called at pc=%#x.", xc->readPC()); + }}, No_OpClass, IsNonSpeculative); + } +#endif + default: Trap::impdep2({{fault = new IllegalInstruction;}}); + } 0x38: Branch::jmpl({{ Addr target = Rs1 + Rs2_or_imm13; if(target & 0x3) @@ -1053,31 +1226,22 @@ decode OP default Unknown::unknown() 0x0: Trap::tcci({{ if(passesCondition(Ccr<3:0>, COND2)) { -#if FULL_SYSTEM int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); -#else - DPRINTF(Sparc, "The syscall number is %d\n", R1); - xc->syscall(R1); -#endif } }}, IsSerializeAfter, IsNonSpeculative); 0x2: Trap::tccx({{ if(passesCondition(Ccr<7:4>, COND2)) { -#if FULL_SYSTEM int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); -#else - DPRINTF(Sparc, "The syscall number is %d\n", R1); - xc->syscall(R1); -#endif } }}, IsSerializeAfter, IsNonSpeculative); } - 0x3B: Nop::flush({{/*Instruction memory flush*/}}); + 0x3B: Nop::flush({{/*Instruction memory flush*/}}, IsWriteBarrier, + MemWriteOp); 0x3C: save({{ if(Cansave == 0) { @@ -1151,16 +1315,18 @@ decode OP default Unknown::unknown() 0x01: ldub({{Rd = Mem.ub;}}); 0x02: lduh({{Rd = Mem.uhw;}}); 0x03: ldtw({{ - uint64_t val = Mem.udw; - RdLow = val<31:0>; - RdHigh = val<63:32>; + RdLow = (Mem.tuw).a; + RdHigh = (Mem.tuw).b; }}); } format Store { 0x04: stw({{Mem.uw = Rd.sw;}}); 0x05: stb({{Mem.ub = Rd.sb;}}); 0x06: sth({{Mem.uhw = Rd.shw;}}); - 0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}}); + 0x07: sttw({{ + (Mem.tuw).a = RdLow<31:0>; + (Mem.tuw).b = RdHigh<31:0>; + }}); } format Load { 0x08: ldsw({{Rd = (int32_t)Mem.sw;}}); @@ -1168,15 +1334,17 @@ decode OP default Unknown::unknown() 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}}); 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}}); } - 0x0D: LoadStore::ldstub( - {{uReg0 = Mem.ub;}}, - {{Rd.ub = uReg0; - Mem.ub = 0xFF;}}); + 0x0D: Swap::ldstub({{Mem.ub = 0xFF;}}, + {{ + uint8_t tmp = mem_data; + Rd.ub = tmp; + }}, MEM_SWAP); 0x0E: Store::stx({{Mem.udw = Rd}}); - 0x0F: LoadStore::swap( - {{ uReg0 = Mem.uw}}, - {{ Mem.uw = Rd.uw; - Rd.uw = uReg0;}}); + 0x0F: Swap::swap({{Mem.uw = Rd.uw}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, MEM_SWAP); format LoadAlt { 0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}}); 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}}); @@ -1184,38 +1352,63 @@ decode OP default Unknown::unknown() 0x13: decode EXT_ASI { //ASI_LDTD_AIUP 0x22: TwinLoad::ldtx_aiup( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTD_AIUS 0x23: TwinLoad::ldtx_aius( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_QUAD_LDD 0x24: TwinLoad::ldtx_quad_ldd( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_REAL 0x26: TwinLoad::ldtx_real( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); - //ASI_LDTX_N - 0x27: TwinLoad::ldtx_n( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); - //ASI_LDTX_L - 0x2C: TwinLoad::ldtx_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_N + 0x27: TwinLoad::ldtx_n( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_AIUP_L + 0x2A: TwinLoad::ldtx_aiup_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_AIUS_L + 0x2B: TwinLoad::ldtx_aius_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_L + 0x2C: TwinLoad::ldtx_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_REAL_L 0x2E: TwinLoad::ldtx_real_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_N_L 0x2F: TwinLoad::ldtx_n_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_P 0xE2: TwinLoad::ldtx_p( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_S 0xE3: TwinLoad::ldtx_s( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_PL + 0xEA: TwinLoad::ldtx_pl( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_SL + 0xEB: TwinLoad::ldtx_sl( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); default: ldtwa({{ - uint64_t val = Mem.udw; - RdLow = val<31:0>; - RdHigh = val<63:32>; + RdLow = (Mem.tuw).a; + RdHigh = (Mem.tuw).b; }}, {{EXT_ASI}}); } } @@ -1223,7 +1416,10 @@ decode OP default Unknown::unknown() 0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}}); 0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}}); 0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}}); - 0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}}); + 0x17: sttwa({{ + (Mem.tuw).a = RdLow<31:0>; + (Mem.tuw).b = RdHigh<31:0>; + }}, {{EXT_ASI}}); } format LoadAlt { 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}}); @@ -1231,15 +1427,18 @@ decode OP default Unknown::unknown() 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}}); 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}}); } - 0x1D: LoadStoreAlt::ldstuba( - {{uReg0 = Mem.ub;}}, - {{Rd.ub = uReg0; - Mem.ub = 0xFF;}}, {{EXT_ASI}}); + 0x1D: SwapAlt::ldstuba({{Mem.ub = 0xFF;}}, + {{ + uint8_t tmp = mem_data; + Rd.ub = tmp; + }}, {{EXT_ASI}}, MEM_SWAP); 0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}}); - 0x1F: LoadStoreAlt::swapa( - {{ uReg0 = Mem.uw}}, - {{ Mem.uw = Rd.uw; - Rd.uw = uReg0;}}, {{EXT_ASI}}); + 0x1F: SwapAlt::swapa({{Mem.uw = Rd.uw}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, {{EXT_ASI}}, MEM_SWAP); + format Trap { 0x20: Load::ldf({{Frds.uw = Mem.uw;}}); 0x21: decode RD { @@ -1438,21 +1637,17 @@ decode OP default Unknown::unknown() {{fault = new DataAccessException;}}); } } - 0x3C: Cas::casa( - {{uReg0 = Mem.uw;}}, - {{if(Rs2.uw == uReg0) - Mem.uw = Rd.uw; - else - storeCond = false; - Rd.uw = uReg0;}}, {{EXT_ASI}}); + 0x3C: CasAlt::casa({{ + mem_data = htog(Rs2.uw); + Mem.uw = Rd.uw;}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, {{EXT_ASI}}, MEM_SWAP_COND); 0x3D: Nop::prefetcha({{ }}); - 0x3E: Cas::casxa( - {{uReg0 = Mem.udw;}}, - {{if(Rs2 == uReg0) - Mem.udw = Rd; - else - storeCond = false; - Rd = uReg0;}}, {{EXT_ASI}}); + 0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2); + Mem.udw = Rd.udw; }}, + {{ Rd.udw = mem_data; }}, {{EXT_ASI}}, MEM_SWAP_COND); } } } diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 5cd3ab598..f5ab940bb 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -40,7 +40,7 @@ output header {{ { protected: // Constructor - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : + Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { } @@ -56,7 +56,7 @@ output header {{ { protected: // Constructor - BranchDisp(const char *mnem, MachInst _machInst, + BranchDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Branch(mnem, _machInst, __opClass) { @@ -76,7 +76,7 @@ output header {{ { protected: // Constructor - BranchNBits(const char *mnem, MachInst _machInst, + BranchNBits(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { @@ -91,7 +91,7 @@ output header {{ { protected: // Constructor - BranchSplit(const char *mnem, MachInst _machInst, + BranchSplit(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { @@ -107,7 +107,7 @@ output header {{ { protected: // Constructor - BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : + BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) { } diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index 1d9075a57..751262811 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -52,22 +52,20 @@ def template MemDeclare {{ }}; let {{ - def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags): + def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' iop = InstObjParams(name, Name, 'Mem', - {"code": code, "fault_check": faultCode, - "ea_code": addrCalcReg}, - opt_flags) + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags) iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', - {"code": code, "fault_check": faultCode, - "ea_code": addrCalcImm}, - opt_flags) + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcImm}, opt_flags) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, - execute, faultCode, name, name + "Imm", + exec_output = doDualSplitExecute(code, postacc_code, addrCalcReg, + addrCalcImm, execute, faultCode, name, name + "Imm", Name, Name + "Imm", asi, opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; @@ -103,3 +101,13 @@ def format Store(code, *opt_flags) {{ decode_block) = doMemFormat(code, StoreFuncs, '', name, Name, 0, opt_flags) }}; + +def format TwinLoad(code, asi, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, LoadFuncs, + AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck, + name, Name, asi, opt_flags) +}}; + diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 9795d2342..499685a5c 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -91,65 +91,6 @@ output header {{ }; }}; -output header {{ - - class TwinMem : public SparcMacroInst - { - protected: - - // Constructor - // We make the assumption that all block memory operations - // Will take 8 instructions to execute - TwinMem(const char *mnem, ExtMachInst _machInst) : - SparcMacroInst(mnem, _machInst, No_OpClass, 2) - {} - }; - - class TwinMemImm : public BlockMem - { - protected: - - // Constructor - TwinMemImm(const char *mnem, ExtMachInst _machInst) : - BlockMem(mnem, _machInst) - {} - }; - - class TwinMemMicro : public SparcMicroInst - { - protected: - - // Constructor - TwinMemMicro(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, int8_t _offset) : - SparcMicroInst(mnem, _machInst, __opClass), - offset(_offset) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - const int8_t offset; - }; - - class TwinMemImmMicro : public BlockMemMicro - { - protected: - - // Constructor - TwinMemImmMicro(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, int8_t _offset) : - BlockMemMicro(mnem, _machInst, __opClass, _offset), - imm(sext<13>(SIMM13)) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - const int32_t imm; - }; -}}; - output decoder {{ std::string BlockMemMicro::generateDisassembly(Addr pc, const SymbolTable *symtab) const @@ -208,64 +149,6 @@ output decoder {{ }}; -output decoder {{ - std::string TwinMemMicro::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[0]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[!save ? 0 : 1]); - ccprintf(response, " + "); - printReg(response, _srcRegIdx[!save ? 1 : 2]); - ccprintf(response, " ]"); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } - - std::string TwinMemImmMicro::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[1]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[0]); - if(imm >= 0) - ccprintf(response, " + 0x%x ]", imm); - else - ccprintf(response, " + -0x%x ]", -imm); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } - -}}; - def template BlockMemDeclare {{ /** * Static instruction class for a block memory operation @@ -359,39 +242,6 @@ def template BlockMemDeclare {{ }; }}; -def template TwinMemDeclare {{ - /** - * Static instruction class for a block memory operation - */ - class %(class_name)s : public %(base_class)s - { - public: - //Constructor - %(class_name)s(ExtMachInst machInst); - - protected: - class %(class_name)s_0 : public %(base_class)sMicro - { - public: - //Constructor - %(class_name)s_0(ExtMachInst machInst); - %(BasicExecDeclare)s - %(InitiateAccDeclare)s - %(CompleteAccDeclare)s - }; - - class %(class_name)s_1 : public %(base_class)sMicro - { - public: - //Constructor - %(class_name)s_1(ExtMachInst machInst); - %(BasicExecDeclare)s - %(InitiateAccDeclare)s - %(CompleteAccDeclare)s - }; - }; -}}; - // Basic instruction class constructor template. def template BlockMemConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) @@ -409,17 +259,6 @@ def template BlockMemConstructor {{ } }}; -// Basic instruction class constructor template. -def template TwinMemConstructor {{ - inline %(class_name)s::%(class_name)s(ExtMachInst machInst) - : %(base_class)s("%(mnemonic)s", machInst) - { - %(constructor)s; - microOps[0] = new %(class_name)s_0(machInst); - microOps[1] = new %(class_name)s_1(machInst); - } -}}; - def template BlockMemMicroConstructor {{ inline %(class_name)s:: %(class_name)s_%(micro_pc)s:: @@ -467,47 +306,7 @@ let {{ decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( - pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, - makeMicroName(name, microPc), - makeMicroName(name + "Imm", microPc), - makeMicroName(Name, microPc), - makeMicroName(Name + "Imm", microPc), - asi, opt_flags); - faultCode = '' - return (header_output, decoder_output, exec_output, decode_block) - - def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags): - addrCalcReg = 'EA = Rs1 + Rs2 + offset;' - addrCalcImm = 'EA = Rs1 + imm + offset;' - iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags) - iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags) - header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm) - decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm) - decode_block = ROrImmDecode.subst(iop) - matcher = re.compile(r'RdTwin') - exec_output = '' - for microPc in range(2): - flag_code = '' - pcedCode = '' - if (microPc == 1): - flag_code = "flags[IsLastMicroOp] = true;" - pcedCode = "RdLow = uReg0;\n" - pcedCode += matcher.sub("RdHigh", code) - else: - flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;" - pcedCode = matcher.sub("uReg0", code) - iop = InstObjParams(name, Name, 'TwinMem', - {"code": pcedCode, "ea_code": addrCalcReg, - "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}, opt_flags) - iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', - {"code": pcedCode, "ea_code": addrCalcImm, - "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}, opt_flags) - decoder_output += BlockMemMicroConstructor.subst(iop) - decoder_output += BlockMemMicroConstructor.subst(iop_imm) - exec_output += doDualSplitExecute( - pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode, + pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode, makeMicroName(name, microPc), makeMicroName(name + "Imm", microPc), makeMicroName(Name, microPc), @@ -515,7 +314,6 @@ let {{ asi, opt_flags); faultCode = '' return (header_output, decoder_output, exec_output, decode_block) - }}; def format BlockLoad(code, asi, *opt_flags) {{ @@ -541,11 +339,3 @@ def format BlockStore(code, asi, *opt_flags) {{ decode_block) = doBlockMemFormat(code, faultCode, StoreFuncs, name, Name, asi, opt_flags) }}; - -def format TwinLoad(code, asi, *opt_flags) {{ - faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck - (header_output, - decoder_output, - exec_output, - decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags) -}}; diff --git a/src/arch/sparc/isa/formats/mem/mem.isa b/src/arch/sparc/isa/formats/mem/mem.isa index fedece2b8..db45e226d 100644 --- a/src/arch/sparc/isa/formats/mem/mem.isa +++ b/src/arch/sparc/isa/formats/mem/mem.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -42,4 +42,4 @@ ##include "blockmem.isa" //Include the load/store and cas memory format -##include "loadstore.isa" +##include "swap.isa" diff --git a/src/arch/sparc/isa/formats/mem/swap.isa b/src/arch/sparc/isa/formats/mem/swap.isa new file mode 100644 index 000000000..818597a84 --- /dev/null +++ b/src/arch/sparc/isa/formats/mem/swap.isa @@ -0,0 +1,183 @@ +// Copyright (c) 2007 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 +// Ali Saidi + +//This template provides the execute functions for a swap +def template SwapExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + //This is to support the conditional store in cas instructions. + //It should be optomized out in all the others + bool storeCond = true; + Addr EA; + %(fp_enable_check)s; + %(op_decl)s; + uint64_t mem_data; + + %(op_rd)s; + %(ea_code)s; + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } + if(storeCond && fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, + EA, %(asi_val)s, &mem_data); + } + if(fault == NoFault) + { + //Handle the swapping + %(postacc_code)s; + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; + + +def template SwapInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + Addr EA; + %(fp_enable_check)s; + uint64_t mem_data = 0; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); + %(fault_check)s; + + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, + EA, %(asi_val)s, &mem_data); + } + return fault; + } +}}; + + + +def template SwapCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + + uint64_t mem_data = pkt->get<uint%(mem_acc_size)s_t>(); + + if(fault == NoFault) + { + //Handle the swapping + %(postacc_code)s; + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; + +let {{ + SwapFuncs = [SwapExecute, SwapInitiateAcc, SwapCompleteAcc] +}}; + + +def format Swap(code, postacc_code, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + flags = string.join(mem_flags, '|') + + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, SwapFuncs, '', name, Name, flags, + opt_flags, postacc_code) +}}; + +def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + mem_flags.append(asi) + flags = string.join(mem_flags, '|') + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, SwapFuncs, AlternateASIPrivFaultCheck, + name, Name, flags, opt_flags, postacc_code) +}}; + + +let {{ + def doCasFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''): + addrCalcReg = 'EA = Rs1;' + iop = InstObjParams(name, Name, 'Mem', + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags) + header_output = MemDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + microParams = {"code": code, "postacc_code" : postacc_code, + "ea_code" : addrCalcReg, "fault_check" : faultCode} + exec_output = doSplitExecute(execute, name, Name, asi, opt_flags, + microParams); + return (header_output, decoder_output, exec_output, decode_block) +}}; + + +def format CasAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + mem_flags.append(asi) + flags = string.join(mem_flags, '|') + (header_output, + decoder_output, + exec_output, + decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck, + name, Name, flags, opt_flags, postacc_code) +}}; + + diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index dbaabdca4..dfe937371 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -149,7 +149,7 @@ def template LoadExecute {{ %(fault_check)s; if(fault == NoFault) { - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s); + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s); } if(fault == NoFault) { @@ -179,7 +179,7 @@ def template LoadInitiateAcc {{ %(fault_check)s; if(fault == NoFault) { - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s); + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s); } return fault; } @@ -224,7 +224,7 @@ def template StoreExecute {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, EA, %(asi_val)s, 0); } if(fault == NoFault) @@ -246,6 +246,7 @@ def template StoreInitiateAcc {{ Addr EA; %(fp_enable_check)s; %(op_decl)s; + %(op_rd)s; %(ea_code)s; DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); @@ -256,7 +257,7 @@ def template StoreInitiateAcc {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, EA, %(asi_val)s, 0); } if(fault == NoFault) @@ -290,6 +291,7 @@ def template CompleteAccDeclare {{ let {{ LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] + # The LSB can be zero, since it's really the MSB in doubles and quads # and we're dealing with doubles BlockAlignmentFaultCheck = ''' @@ -337,14 +339,14 @@ let {{ return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) - def doDualSplitExecute(code, eaRegCode, eaImmCode, execute, + def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute, faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags): executeCode = '' for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): - microParams = {"code": code, "ea_code": eaCode, - "fault_check": faultCode} + microParams = {"code": code, "postacc_code" : postacc_code, + "ea_code": eaCode, "fault_check": faultCode} executeCode += doSplitExecute(execute, name, Name, asi, opt_flags, microParams) return executeCode diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index d2ef67154..05e9e8731 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -70,10 +70,15 @@ output exec {{ #include <ieeefp.h> #endif +#if FULL_SYSTEM +#include "sim/pseudo_inst.hh" +#endif + #include <limits> #include <cmath> #include "arch/sparc/asi.hh" +#include "base/bigint.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 140055010..038919bd1 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -37,6 +37,8 @@ def operand_types {{ 'uw' : ('unsigned int', 32), 'sdw' : ('signed int', 64), 'udw' : ('unsigned int', 64), + 'tudw' : ('twin64 int', 64), + 'tuw' : ('twin32 int', 32), 'sf' : ('float', 32), 'df' : ('float', 64), 'qf' : ('float', 128) @@ -99,6 +101,12 @@ def operands {{ 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), 'R16': ('IntReg', 'udw', '16', None, 9), + 'O0': ('IntReg', 'udw', '8', 'IsInteger', 10), + 'O1': ('IntReg', 'udw', '9', 'IsInteger', 11), + 'O2': ('IntReg', 'udw', '10', 'IsInteger', 12), + 'O3': ('IntReg', 'udw', '11', 'IsInteger', 13), + 'O4': ('IntReg', 'udw', '12', 'IsInteger', 14), + 'O5': ('IntReg', 'udw', '13', 'IsInteger', 15), # Control registers # 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 64ae6abd8..d0b8827f3 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -87,6 +87,11 @@ namespace SparcISA const int LogVMPageSize = 13; const int VMPageSize = (1 << LogVMPageSize); + // real address virtual mapping + // sort of like alpha super page, but less frequently used + const Addr SegKPMEnd = ULL(0xfffffffc00000000); + const Addr SegKPMBase = ULL(0xfffffac000000000); + //Why does both the previous set of constants and this one exist? const int PageShift = 13; const int PageBytes = 1ULL << PageShift; @@ -108,6 +113,18 @@ namespace SparcISA const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF); const Addr BytesInPageMask = ULL(0x1FFF); + enum InterruptTypes + { + IT_TRAP_LEVEL_ZERO, + IT_HINTP, + IT_INT_VEC, + IT_CPU_MONDO, + IT_DEV_MONDO, + IT_RES_ERROR, + IT_SOFT_INT, + NumInterruptTypes + }; + #endif } diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh index fefd27197..f396eb5cd 100644 --- a/src/arch/sparc/linux/linux.hh +++ b/src/arch/sparc/linux/linux.hh @@ -79,4 +79,32 @@ class SparcLinux : public Linux static const unsigned TGT_MAP_ANONYMOUS = 0x20; }; +class Sparc32Linux : public SparcLinux +{ + public: + + typedef struct { + uint64_t st_dev; + uint64_t st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + uint8_t __pad3[8]; + int64_t st_size; + int32_t st_blksize; + uint8_t __pad4[8]; + int64_t st_blocks; + uint64_t st_atimeX; + uint64_t st_atime_nsec; + uint64_t st_mtimeX; + uint64_t st_mtime_nsec; + uint64_t st_ctimeX; + uint64_t st_ctime_nsec; + uint32_t __unused4; + uint32_t __unused5; + } tgt_stat64; +}; + #endif diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index 565975fe0..9e3f74075 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -44,373 +44,89 @@ using namespace std; using namespace SparcISA; - -/// Target uname() handler. -static SyscallReturn -unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, - ThreadContext *tc) +SyscallDesc* +SparcLinuxProcess::getDesc(int callnum) { - TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); - - strcpy(name->sysname, "Linux"); - strcpy(name->nodename, "m5.eecs.umich.edu"); - strcpy(name->release, "2.4.20"); - strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); - strcpy(name->machine, "sparc"); - - name.copyOut(tc->getMemPort()); - - return 0; + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; } - -SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num, - LiveProcess *p, ThreadContext *tc) +SyscallDesc* +SparcLinuxProcess::getDesc32(int callnum) { - const IntReg id = htog(100); - Addr ruid = tc->getSyscallArg(0); - Addr euid = tc->getSyscallArg(1); - Addr suid = tc->getSyscallArg(2); - //Handle the EFAULT case - //Set the ruid - if(ruid) - { - BufferArg ruidBuff(ruid, sizeof(IntReg)); - memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); - ruidBuff.copyOut(tc->getMemPort()); - } - //Set the euid - if(euid) - { - BufferArg euidBuff(euid, sizeof(IntReg)); - memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); - euidBuff.copyOut(tc->getMemPort()); - } - //Set the suid - if(suid) - { - BufferArg suidBuff(suid, sizeof(IntReg)); - memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); - suidBuff.copyOut(tc->getMemPort()); - } - return 0; + if (callnum < 0 || callnum > Num_Syscall32_Descs) + return NULL; + return &syscall32Descs[callnum]; } -SyscallDesc SparcLinuxProcess::syscallDescs[] = { - /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), - /* 1 */ SyscallDesc("exit", exitFunc), - /* 2 */ SyscallDesc("fork", unimplementedFunc), - /* 3 */ SyscallDesc("read", readFunc), - /* 4 */ SyscallDesc("write", writeFunc), - /* 5 */ SyscallDesc("open", openFunc<SparcLinux>), - /* 6 */ SyscallDesc("close", closeFunc), - /* 7 */ SyscallDesc("wait4", unimplementedFunc), - /* 8 */ SyscallDesc("creat", unimplementedFunc), - /* 9 */ SyscallDesc("link", unimplementedFunc), - /* 10 */ SyscallDesc("unlink", unlinkFunc), - /* 11 */ SyscallDesc("execv", unimplementedFunc), - /* 12 */ SyscallDesc("chdir", unimplementedFunc), - /* 13 */ SyscallDesc("chown", chownFunc), - /* 14 */ SyscallDesc("mknod", unimplementedFunc), - /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), - /* 16 */ SyscallDesc("lchown", unimplementedFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), - /* 18 */ SyscallDesc("perfctr", unimplementedFunc), - /* 19 */ SyscallDesc("lseek", lseekFunc), - /* 20 */ SyscallDesc("getpid", getpidFunc), - /* 21 */ SyscallDesc("capget", unimplementedFunc), - /* 22 */ SyscallDesc("capset", unimplementedFunc), - /* 23 */ SyscallDesc("setuid", setuidFunc), - /* 24 */ SyscallDesc("getuid", getuidFunc), - /* 25 */ SyscallDesc("time", unimplementedFunc), - /* 26 */ SyscallDesc("ptrace", unimplementedFunc), - /* 27 */ SyscallDesc("alarm", unimplementedFunc), - /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), - /* 29 */ SyscallDesc("pause", unimplementedFunc), - /* 30 */ SyscallDesc("utime", unimplementedFunc), - /* 31 */ SyscallDesc("lchown32", unimplementedFunc), - /* 32 */ SyscallDesc("fchown32", unimplementedFunc), - /* 33 */ SyscallDesc("access", unimplementedFunc), - /* 34 */ SyscallDesc("nice", unimplementedFunc), - /* 35 */ SyscallDesc("chown32", unimplementedFunc), - /* 36 */ SyscallDesc("sync", unimplementedFunc), - /* 37 */ SyscallDesc("kill", unimplementedFunc), - /* 38 */ SyscallDesc("stat", unimplementedFunc), - /* 39 */ SyscallDesc("sendfile", unimplementedFunc), - /* 40 */ SyscallDesc("lstat", unimplementedFunc), - /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", pipePseudoFunc), - /* 43 */ SyscallDesc("times", unimplementedFunc), - /* 44 */ SyscallDesc("getuid32", unimplementedFunc), - /* 45 */ SyscallDesc("umount2", unimplementedFunc), - /* 46 */ SyscallDesc("setgid", unimplementedFunc), - /* 47 */ SyscallDesc("getgid", getgidFunc), - /* 48 */ SyscallDesc("signal", unimplementedFunc), - /* 49 */ SyscallDesc("geteuid", geteuidFunc), - /* 50 */ SyscallDesc("getegid", getegidFunc), - /* 51 */ SyscallDesc("acct", unimplementedFunc), - /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), - /* 53 */ SyscallDesc("getgid32", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", unimplementedFunc), - /* 55 */ SyscallDesc("reboot", unimplementedFunc), - /* 56 */ SyscallDesc("mmap2", unimplementedFunc), - /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), - /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), - /* 61 */ SyscallDesc("chroot", unimplementedFunc), - /* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>), - /* 63 */ SyscallDesc("fstat64", unimplementedFunc), - /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), - /* 65 */ SyscallDesc("msync", unimplementedFunc), - /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("pread64", unimplementedFunc), - /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), - /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), - /* 70 */ SyscallDesc("getdgid32", unimplementedFunc), - /* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>), - /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), - /* 73 */ SyscallDesc("munmap", munmapFunc), - /* 74 */ SyscallDesc("mprotect", unimplementedFunc), - /* 75 */ SyscallDesc("madvise", unimplementedFunc), - /* 76 */ SyscallDesc("vhangup", unimplementedFunc), - /* 77 */ SyscallDesc("truncate64", unimplementedFunc), - /* 78 */ SyscallDesc("mincore", unimplementedFunc), - /* 79 */ SyscallDesc("getgroups", unimplementedFunc), - /* 80 */ SyscallDesc("setgroups", unimplementedFunc), - /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), - /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), - /* 83 */ SyscallDesc("setitimer", unimplementedFunc), - /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), - /* 85 */ SyscallDesc("swapon", unimplementedFunc), - /* 86 */ SyscallDesc("getitimer", unimplementedFunc), - /* 87 */ SyscallDesc("setuid32", unimplementedFunc), - /* 88 */ SyscallDesc("sethostname", unimplementedFunc), - /* 89 */ SyscallDesc("setgid32", unimplementedFunc), - /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), - /* 92 */ SyscallDesc("fcntl", unimplementedFunc), - /* 93 */ SyscallDesc("select", unimplementedFunc), - /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), - /* 95 */ SyscallDesc("fsync", unimplementedFunc), - /* 96 */ SyscallDesc("setpriority", unimplementedFunc), - /* 97 */ SyscallDesc("socket", unimplementedFunc), - /* 98 */ SyscallDesc("connect", unimplementedFunc), - /* 99 */ SyscallDesc("accept", unimplementedFunc), - /* 100 */ SyscallDesc("getpriority", unimplementedFunc), - /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), - /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), - /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), - /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), - /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), - /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), - /* 108 */ SyscallDesc("setresuid", unimplementedFunc), - /* 109 */ SyscallDesc("getresuid", getresuidFunc), - /* 110 */ SyscallDesc("setresgid", unimplementedFunc), - /* 111 */ SyscallDesc("getresgid", unimplementedFunc), - /* 112 */ SyscallDesc("setregid32", unimplementedFunc), - /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), - /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), - /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), - /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), - /* 117 */ SyscallDesc("getrusage", unimplementedFunc), - /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), - /* 119 */ SyscallDesc("getcwd", unimplementedFunc), - /* 120 */ SyscallDesc("readv", unimplementedFunc), - /* 121 */ SyscallDesc("writev", unimplementedFunc), - /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), - /* 123 */ SyscallDesc("fchown", unimplementedFunc), - /* 124 */ SyscallDesc("fchmod", unimplementedFunc), - /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), - /* 126 */ SyscallDesc("setreuid", unimplementedFunc), - /* 127 */ SyscallDesc("setregid", unimplementedFunc), - /* 128 */ SyscallDesc("rename", unimplementedFunc), - /* 129 */ SyscallDesc("truncate", unimplementedFunc), - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), - /* 131 */ SyscallDesc("flock", unimplementedFunc), - /* 132 */ SyscallDesc("lstat64", unimplementedFunc), - /* 133 */ SyscallDesc("sendto", unimplementedFunc), - /* 134 */ SyscallDesc("shutdown", unimplementedFunc), - /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), - /* 137 */ SyscallDesc("rmdir", unimplementedFunc), - /* 138 */ SyscallDesc("utimes", unimplementedFunc), - /* 139 */ SyscallDesc("stat64", unimplementedFunc), - /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), - /* 141 */ SyscallDesc("getpeername", unimplementedFunc), - /* 142 */ SyscallDesc("futex", unimplementedFunc), - /* 143 */ SyscallDesc("gettid", unimplementedFunc), - /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), - /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), - /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), - /* 147 */ SyscallDesc("prctl", unimplementedFunc), - /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), - /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), - /* 150 */ SyscallDesc("getsockname", unimplementedFunc), - /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), - /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), - /* 153 */ SyscallDesc("poll", unimplementedFunc), - /* 154 */ SyscallDesc("getdents64", unimplementedFunc), - /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), - /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), - /* 157 */ SyscallDesc("statfs", unimplementedFunc), - /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), - /* 159 */ SyscallDesc("umount", unimplementedFunc), - /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc), - /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc), - /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), - /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), - /* 164 */ SyscallDesc("utrap_install", unimplementedFunc), - /* 165 */ SyscallDesc("quotactl", unimplementedFunc), - /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), - /* 167 */ SyscallDesc("mount", unimplementedFunc), - /* 168 */ SyscallDesc("ustat", unimplementedFunc), - /* 169 */ SyscallDesc("setxattr", unimplementedFunc), - /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), - /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), - /* 172 */ SyscallDesc("getxattr", unimplementedFunc), - /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), - /* 174 */ SyscallDesc("getdents", unimplementedFunc), - /* 175 */ SyscallDesc("setsid", unimplementedFunc), - /* 176 */ SyscallDesc("fchdir", unimplementedFunc), - /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), - /* 178 */ SyscallDesc("listxattr", unimplementedFunc), - /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), - /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), - /* 181 */ SyscallDesc("removexattr", unimplementedFunc), - /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), - /* 183 */ SyscallDesc("sigpending", unimplementedFunc), - /* 184 */ SyscallDesc("query_module", unimplementedFunc), - /* 185 */ SyscallDesc("setpgid", unimplementedFunc), - /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), - /* 187 */ SyscallDesc("tkill", unimplementedFunc), - /* 188 */ SyscallDesc("exit_group", exitFunc), - /* 189 */ SyscallDesc("uname", unameFunc), - /* 190 */ SyscallDesc("init_module", unimplementedFunc), - /* 191 */ SyscallDesc("personality", unimplementedFunc), - /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), - /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), - /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), - /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), - /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), - /* 197 */ SyscallDesc("getppid", getppidFunc), - /* 198 */ SyscallDesc("sigaction", ignoreFunc), - /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), - /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), - /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), - /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), - /* 203 */ SyscallDesc("uselib", unimplementedFunc), - /* 204 */ SyscallDesc("readdir", unimplementedFunc), - /* 205 */ SyscallDesc("readahead", unimplementedFunc), - /* 206 */ SyscallDesc("socketcall", unimplementedFunc), - /* 207 */ SyscallDesc("syslog", unimplementedFunc), - /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), - /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), - /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), - /* 211 */ SyscallDesc("tgkill", unimplementedFunc), - /* 212 */ SyscallDesc("waitpid", unimplementedFunc), - /* 213 */ SyscallDesc("swapoff", unimplementedFunc), - /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), - /* 215 */ SyscallDesc("ipc", unimplementedFunc), - /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), - /* 217 */ SyscallDesc("clone", unimplementedFunc), - /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), - /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), - /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), - /* 221 */ SyscallDesc("create_module", unimplementedFunc), - /* 222 */ SyscallDesc("delete_module", unimplementedFunc), - /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), - /* 224 */ SyscallDesc("getpgid", unimplementedFunc), - /* 225 */ SyscallDesc("bdflush", unimplementedFunc), - /* 226 */ SyscallDesc("sysfs", unimplementedFunc), - /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), - /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), - /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 230 */ SyscallDesc("_newselect", unimplementedFunc), - /* 231 */ SyscallDesc("time", unimplementedFunc), - /* 232 */ SyscallDesc("oldstat", unimplementedFunc), - /* 233 */ SyscallDesc("stime", unimplementedFunc), - /* 234 */ SyscallDesc("statfs64", unimplementedFunc), - /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), - /* 236 */ SyscallDesc("_llseek", unimplementedFunc), - /* 237 */ SyscallDesc("mlock", unimplementedFunc), - /* 238 */ SyscallDesc("munlock", unimplementedFunc), - /* 239 */ SyscallDesc("mlockall", unimplementedFunc), - /* 240 */ SyscallDesc("munlockall", unimplementedFunc), - /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), - /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), - /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), - /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), - /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), - /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), - /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), - /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), - /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 250 */ SyscallDesc("mremap", unimplementedFunc), - /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), - /* 252 */ SyscallDesc("getsid", unimplementedFunc), - /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), - /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), - /* 255 */ SyscallDesc("aplib", unimplementedFunc), - /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), - /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), - /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), - /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), - /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), - /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), - /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), - /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), - /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), - /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), - /* 266 */ SyscallDesc("timer_create", unimplementedFunc), - /* 267 */ SyscallDesc("vserver", unimplementedFunc), - /* 268 */ SyscallDesc("io_setup", unimplementedFunc), - /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), - /* 270 */ SyscallDesc("io_submit", unimplementedFunc), - /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), - /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), - /* 273 */ SyscallDesc("mq_open", unimplementedFunc), - /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), - /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), - /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), - /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), - /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), - /* 279 */ SyscallDesc("waitid", unimplementedFunc), - /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), - /* 281 */ SyscallDesc("add_key", unimplementedFunc), - /* 282 */ SyscallDesc("request_key", unimplementedFunc), - /* 283 */ SyscallDesc("keyctl", unimplementedFunc) -}; - -SparcLinuxProcess::SparcLinuxProcess(const std::string &name, - ObjectFile *objFile, - System * system, - int stdin_fd, - int stdout_fd, - int stderr_fd, - std::vector<std::string> &argv, - std::vector<std::string> &envp, - const std::string &cwd, - uint64_t _uid, uint64_t _euid, - uint64_t _gid, uint64_t _egid, - uint64_t _pid, uint64_t _ppid) - : SparcLiveProcess(name, objFile, system, - stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid), - Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +SparcLinuxProcess::SparcLinuxProcess() : + Num_Syscall_Descs(284), //sizeof(syscallDescs) / sizeof(SyscallDesc)), + Num_Syscall32_Descs(299) //sizeof(syscall32Descs) / sizeof(SyscallDesc)) { // The sparc syscall table must be <= 284 entries because that is all there // is space for. assert(Num_Syscall_Descs <= 284); + // The sparc 32 bit syscall table bust be <= 299 entries because that is + // all there is space for. + assert(Num_Syscall_Descs <= 299); } +Sparc32LinuxProcess::Sparc32LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : Sparc32LiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) +{} +void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + case 0x10: //Linux 32 bit syscall trap + tc->syscall(tc->readIntReg(1)); + break; + default: + SparcLiveProcess::handleTrap(trapNum, tc); + } +} -SyscallDesc* -SparcLinuxProcess::getDesc(int callnum) +Sparc64LinuxProcess::Sparc64LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : Sparc64LiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) +{} + +void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) { - if (callnum < 0 || callnum > Num_Syscall_Descs) - return NULL; - return &syscallDescs[callnum]; + switch(trapNum) + { + //case 0x10: //Linux 32 bit syscall trap + case 0x6d: //Linux 64 bit syscall trap + tc->syscall(tc->readIntReg(1)); + break; + default: + SparcLiveProcess::handleTrap(trapNum, tc); + } } diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index e212de973..6c7f30a43 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -38,12 +38,34 @@ namespace SparcISA { +//This contains all of the common elements of a SPARC Linux process which +//are not shared by other operating systems. The rest come from the common +//SPARC process class. +class SparcLinuxProcess +{ + public: + SparcLinuxProcess(); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + /// Array of 32 bit compatibility syscall descriptors, + /// indexed by call number. + static SyscallDesc syscall32Descs[]; + + SyscallDesc* getDesc(int callnum); + SyscallDesc* getDesc32(int callnum); + + const int Num_Syscall_Descs; + const int Num_Syscall32_Descs; +}; + /// A process with emulated SPARC/Linux syscalls. -class SparcLinuxProcess : public SparcLiveProcess +class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32LiveProcess { public: /// Constructor. - SparcLinuxProcess(const std::string &name, + Sparc32LinuxProcess(const std::string &name, ObjectFile *objFile, System * system, int stdin_fd, int stdout_fd, int stderr_fd, @@ -54,19 +76,40 @@ class SparcLinuxProcess : public SparcLiveProcess uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); - virtual SyscallDesc* getDesc(int callnum); + SyscallDesc* getDesc(int callnum) + { + return SparcLinuxProcess::getDesc32(callnum); + } - /// The target system's hostname. - static const char *hostname; + void handleTrap(int trapNum, ThreadContext *tc); +}; - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; +/// A process with emulated 32 bit SPARC/Linux syscalls. +class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64LiveProcess +{ + public: + /// Constructor. + Sparc64LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid); - const int Num_Syscall_Descs; + SyscallDesc* getDesc(int callnum) + { + return SparcLinuxProcess::getDesc(callnum); + } + + void handleTrap(int trapNum, ThreadContext *tc); }; SyscallReturn getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); } // namespace SparcISA -#endif // __ALPHA_LINUX_PROCESS_HH__ +#endif // __SPARC_LINUX_PROCESS_HH__ diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc new file mode 100644 index 000000000..03c8bafe2 --- /dev/null +++ b/src/arch/sparc/linux/syscalls.cc @@ -0,0 +1,681 @@ +/* + * 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: Gabe Black + */ + +#include "arch/sparc/linux/process.hh" +#include "arch/sparc/syscallreturn.hh" +#include "sim/syscall_emul.hh" + +class LiveProcess; +class ThreadContext; + +namespace SparcISA { + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.6.12-9-sparc64"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "sparc"); + + name.copyOut(tc->getMemPort()); + + return 0; +} + + +SyscallReturn getresuidFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc) +{ + const IntReg id = htog(100); + Addr ruid = tc->getSyscallArg(0); + Addr euid = tc->getSyscallArg(1); + Addr suid = tc->getSyscallArg(2); + //Handle the EFAULT case + //Set the ruid + if(ruid) + { + BufferArg ruidBuff(ruid, sizeof(IntReg)); + memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); + ruidBuff.copyOut(tc->getMemPort()); + } + //Set the euid + if(euid) + { + BufferArg euidBuff(euid, sizeof(IntReg)); + memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); + euidBuff.copyOut(tc->getMemPort()); + } + //Set the suid + if(suid) + { + BufferArg suidBuff(suid, sizeof(IntReg)); + memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); + suidBuff.copyOut(tc->getMemPort()); + } + return 0; +} + +SyscallDesc SparcLinuxProcess::syscall32Descs[] = { + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), //32 bit + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<Sparc32Linux>), //32 bit + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), //32 bit + /* 8 */ SyscallDesc("creat", unimplementedFunc), //32 bit + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("chown", chownFunc), //32 bit + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", unimplementedFunc), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), //32 bit + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("perfctr", unimplementedFunc), //32 bit + /* 19 */ SyscallDesc("lseek", lseekFunc), //32 bit + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("capget", unimplementedFunc), + /* 22 */ SyscallDesc("capset", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), //32 bit + /* 24 */ SyscallDesc("getuid", getuidFunc), //32 bit + /* 25 */ SyscallDesc("time", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), //32 bit + /* 29 */ SyscallDesc("pause", unimplementedFunc), //32 bit + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("lchown32", unimplementedFunc), + /* 32 */ SyscallDesc("fchown32", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), //32 bit + /* 34 */ SyscallDesc("nice", unimplementedFunc), //32 bit + /* 35 */ SyscallDesc("chown32", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), //32 bit + /* 38 */ SyscallDesc("stat", unimplementedFunc), + /* 39 */ SyscallDesc("sendfile", unimplementedFunc), //32 bit + /* 40 */ SyscallDesc("lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", ignoreFunc), + /* 44 */ SyscallDesc("getuid32", unimplementedFunc), + /* 45 */ SyscallDesc("umount2", unimplementedFunc), //32 bit + /* 46 */ SyscallDesc("setgid", unimplementedFunc), //32 bit + /* 47 */ SyscallDesc("getgid", getgidFunc), //32 bit + /* 48 */ SyscallDesc("signal", unimplementedFunc), //32 bit + /* 49 */ SyscallDesc("geteuid", geteuidFunc), //32 bit + /* 50 */ SyscallDesc("getegid", getegidFunc), //32 bit + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), + /* 53 */ SyscallDesc("getgid32", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), //32 bit + /* 56 */ SyscallDesc("mmap2", unimplementedFunc), //32 bit + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), //32 bit + /* 59 */ SyscallDesc("execve", unimplementedFunc), //32 bit + /* 60 */ SyscallDesc("umask", unimplementedFunc), //32 bit + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("fstat", unimplementedFunc), + /* 63 */ SyscallDesc("fstat64", fstat64Func<Sparc32Linux>), + /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), + /* 65 */ SyscallDesc("msync", unimplementedFunc), //32 bit + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pread64", unimplementedFunc), //32 bit + /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), //32 bit + /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 70 */ SyscallDesc("getegid32", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<Sparc32Linux>), + /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", unimplementedFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("truncate64", unimplementedFunc), //32 bit + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), //32 bit + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), //32 bit + /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), //32 bit + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), //32 bit + /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), //32 bit + /* 85 */ SyscallDesc("swapon", unimplementedFunc), //32 bit + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), //32 bit + /* 87 */ SyscallDesc("setuid32", unimplementedFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), //32 bit + /* 89 */ SyscallDesc("setgid32", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 92 */ SyscallDesc("fcntl", unimplementedFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), //32 bit + /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), //32 bit + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), //32 bit + /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), //32 bit + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), //32 bit + /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), //32 bit + /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), //32 bit + /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), //32 bit + /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 108 */ SyscallDesc("setresuid32", unimplementedFunc), + /* 109 */ SyscallDesc("getresuid32", getresuidFunc), + /* 110 */ SyscallDesc("setresgid32", unimplementedFunc), + /* 111 */ SyscallDesc("getresgid32", unimplementedFunc), + /* 112 */ SyscallDesc("setregid32", unimplementedFunc), + /* 113 */ SyscallDesc("revcmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), //32 bit + /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), //32 bit + /* 117 */ SyscallDesc("getrusage", unimplementedFunc), //32 bit + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), //32 bit + /* 123 */ SyscallDesc("fchown", unimplementedFunc), //32 bit + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), //32 bit + /* 127 */ SyscallDesc("setregid", unimplementedFunc), //32 bit + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("lstat64", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), //32 bit + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), //32 bit + /* 139 */ SyscallDesc("stat64", unimplementedFunc), + /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), //32 bit + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("futex", unimplementedFunc), //32 bit + /* 143 */ SyscallDesc("gettid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 147 */ SyscallDesc("prctl", unimplementedFunc), //32 bit + /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 153 */ SyscallDesc("poll", unimplementedFunc), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), + /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 157 */ SyscallDesc("statfs", unimplementedFunc), + /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 159 */ SyscallDesc("umount", unimplementedFunc), + /* 160 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 161 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), //32 bit + /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), //32 bit + /* 164 */ SyscallDesc("ni_syscall", unimplementedFunc), + /* 165 */ SyscallDesc("quotactl", unimplementedFunc), + /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 167 */ SyscallDesc("mount", unimplementedFunc), + /* 168 */ SyscallDesc("ustat", unimplementedFunc), + /* 169 */ SyscallDesc("setxattr", unimplementedFunc), //32 bit + /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), //32 bit + /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), //32 bit + /* 172 */ SyscallDesc("getxattr", unimplementedFunc), + /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), + /* 175 */ SyscallDesc("setsid", unimplementedFunc), + /* 176 */ SyscallDesc("fchdir", unimplementedFunc), + /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), //32 bit + /* 178 */ SyscallDesc("listxattr", unimplementedFunc), + /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), //32 bit + /* 181 */ SyscallDesc("removexattr", unimplementedFunc), + /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 183 */ SyscallDesc("sigpending", unimplementedFunc), + /* 184 */ SyscallDesc("query_module", unimplementedFunc), + /* 185 */ SyscallDesc("setpgid", unimplementedFunc), //32 bit + /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), //32 bit + /* 187 */ SyscallDesc("tkill", unimplementedFunc), //32 bit + /* 188 */ SyscallDesc("exit_group", exitFunc), //32 bit + /* 189 */ SyscallDesc("uname", unameFunc), + /* 190 */ SyscallDesc("init_module", unimplementedFunc), //32 bit + /* 191 */ SyscallDesc("personality", unimplementedFunc), + /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), //32 bit + /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), //32 bit + /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), //32 bit + /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), //32 bit + /* 197 */ SyscallDesc("getppid", getppidFunc), + /* 198 */ SyscallDesc("sigaction", unimplementedFunc), //32 bit + /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 203 */ SyscallDesc("uselib", unimplementedFunc), + /* 204 */ SyscallDesc("readdir", unimplementedFunc), + /* 205 */ SyscallDesc("readahead", unimplementedFunc), //32 bit + /* 206 */ SyscallDesc("socketcall", unimplementedFunc), //32 bit + /* 207 */ SyscallDesc("syslog", unimplementedFunc), //32 bit + /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), //32 bit + /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), //32 bit + /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), //32 bit + /* 211 */ SyscallDesc("tgkill", unimplementedFunc), //32 bit + /* 212 */ SyscallDesc("waitpid", unimplementedFunc), //32 bit + /* 213 */ SyscallDesc("swapoff", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), //32 bit + /* 215 */ SyscallDesc("ipc", unimplementedFunc), //32 bit + /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), //32 bit + /* 217 */ SyscallDesc("clone", unimplementedFunc), + /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), //32 bit + /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), //32 bit + /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), //32 bit + /* 221 */ SyscallDesc("create_module", unimplementedFunc), + /* 222 */ SyscallDesc("delete_module", unimplementedFunc), //32 bit + /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 224 */ SyscallDesc("getpgid", unimplementedFunc), //32 bit + /* 225 */ SyscallDesc("bdflush", unimplementedFunc), //32 bit + /* 226 */ SyscallDesc("sysfs", unimplementedFunc), //32 bit + /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), //32 bit + /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), //32 bit + /* 230 */ SyscallDesc("_newselect", unimplementedFunc), //32 bit + /* 231 */ SyscallDesc("time", ignoreFunc), + /* 232 */ SyscallDesc("oldstat", unimplementedFunc), + /* 233 */ SyscallDesc("stime", unimplementedFunc), + /* 234 */ SyscallDesc("statfs64", unimplementedFunc), + /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", _llseekFunc), + /* 237 */ SyscallDesc("mlock", unimplementedFunc), + /* 238 */ SyscallDesc("munlock", unimplementedFunc), + /* 239 */ SyscallDesc("mlockall", unimplementedFunc), //32 bit + /* 240 */ SyscallDesc("munlockall", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), //32 bit + /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), //32 bit + /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), //32 bit + /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), //32 bit + /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), //32 bit + /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), //32 bit + /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), //32 bit + /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", unimplementedFunc), //32 bit + /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), //32 bit + /* 252 */ SyscallDesc("getsid", unimplementedFunc), //32 bit + /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), //32 bit + /* 255 */ SyscallDesc("aplib", unimplementedFunc), + /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), //32 bit + /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), //32 bit + /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 266 */ SyscallDesc("timer_create", unimplementedFunc), + /* 267 */ SyscallDesc("vserver", unimplementedFunc), + /* 268 */ SyscallDesc("io_setup", unimplementedFunc), + /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 270 */ SyscallDesc("io_submit", unimplementedFunc), //32 bit + /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 273 */ SyscallDesc("mq_open", unimplementedFunc), //32 bit + /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 279 */ SyscallDesc("waitid", unimplementedFunc), + /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 281 */ SyscallDesc("add_key", unimplementedFunc), + /* 282 */ SyscallDesc("request_key", unimplementedFunc), + /* 283 */ SyscallDesc("keyctl", unimplementedFunc), + /* 284 */ SyscallDesc("openat", unimplementedFunc), + /* 285 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 286 */ SyscallDesc("mknodat", unimplementedFunc), + /* 287 */ SyscallDesc("fchownat", unimplementedFunc), + /* 288 */ SyscallDesc("futimesat", unimplementedFunc), + /* 289 */ SyscallDesc("fstatat64", unimplementedFunc), + /* 290 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 291 */ SyscallDesc("renameat", unimplementedFunc), + /* 292 */ SyscallDesc("linkat", unimplementedFunc), + /* 293 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 294 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 295 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 296 */ SyscallDesc("faccessat", unimplementedFunc), + /* 297 */ SyscallDesc("pselect6", unimplementedFunc), + /* 298 */ SyscallDesc("ppoll", unimplementedFunc), + /* 299 */ SyscallDesc("unshare", unimplementedFunc) +}; + +SyscallDesc SparcLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<SparcLinux>), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("chown", chownFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("perfctr", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("capget", unimplementedFunc), + /* 22 */ SyscallDesc("capset", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), + /* 25 */ SyscallDesc("time", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("lchown32", unimplementedFunc), + /* 32 */ SyscallDesc("fchown32", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("chown32", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("stat", unimplementedFunc), + /* 39 */ SyscallDesc("sendfile", unimplementedFunc), + /* 40 */ SyscallDesc("lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", ignoreFunc), + /* 44 */ SyscallDesc("getuid32", unimplementedFunc), + /* 45 */ SyscallDesc("umount2", unimplementedFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), + /* 48 */ SyscallDesc("signal", unimplementedFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), + /* 53 */ SyscallDesc("getgid32", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), + /* 56 */ SyscallDesc("mmap2", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>), + /* 63 */ SyscallDesc("fstat64", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), + /* 65 */ SyscallDesc("msync", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pread64", unimplementedFunc), + /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 70 */ SyscallDesc("getegid32", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>), + /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", unimplementedFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("truncate64", unimplementedFunc), + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 85 */ SyscallDesc("swapon", unimplementedFunc), + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("setuid32", unimplementedFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("setgid32", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 92 */ SyscallDesc("fcntl", unimplementedFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), + /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 108 */ SyscallDesc("setresuid", unimplementedFunc), + /* 109 */ SyscallDesc("getresuid", getresuidFunc), + /* 110 */ SyscallDesc("setresgid", unimplementedFunc), + /* 111 */ SyscallDesc("getresgid", unimplementedFunc), + /* 112 */ SyscallDesc("setregid32", unimplementedFunc), + /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), + /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 117 */ SyscallDesc("getrusage", unimplementedFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", unimplementedFunc), + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("lstat64", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), + /* 139 */ SyscallDesc("stat64", unimplementedFunc), + /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("futex", unimplementedFunc), + /* 143 */ SyscallDesc("gettid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 147 */ SyscallDesc("prctl", unimplementedFunc), + /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 153 */ SyscallDesc("poll", unimplementedFunc), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), + /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 157 */ SyscallDesc("statfs", unimplementedFunc), + /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 159 */ SyscallDesc("umount", unimplementedFunc), + /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc), + /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc), + /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), + /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 164 */ SyscallDesc("utrap_install", unimplementedFunc), + /* 165 */ SyscallDesc("quotactl", unimplementedFunc), + /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 167 */ SyscallDesc("mount", unimplementedFunc), + /* 168 */ SyscallDesc("ustat", unimplementedFunc), + /* 169 */ SyscallDesc("setxattr", unimplementedFunc), + /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 172 */ SyscallDesc("getxattr", unimplementedFunc), + /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), + /* 175 */ SyscallDesc("setsid", unimplementedFunc), + /* 176 */ SyscallDesc("fchdir", unimplementedFunc), + /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 178 */ SyscallDesc("listxattr", unimplementedFunc), + /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 181 */ SyscallDesc("removexattr", unimplementedFunc), + /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 183 */ SyscallDesc("sigpending", unimplementedFunc), + /* 184 */ SyscallDesc("query_module", unimplementedFunc), + /* 185 */ SyscallDesc("setpgid", unimplementedFunc), + /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 187 */ SyscallDesc("tkill", unimplementedFunc), + /* 188 */ SyscallDesc("exit_group", exitFunc), + /* 189 */ SyscallDesc("uname", unameFunc), + /* 190 */ SyscallDesc("init_module", unimplementedFunc), + /* 191 */ SyscallDesc("personality", unimplementedFunc), + /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 197 */ SyscallDesc("getppid", getppidFunc), + /* 198 */ SyscallDesc("sigaction", ignoreFunc), + /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 203 */ SyscallDesc("uselib", unimplementedFunc), + /* 204 */ SyscallDesc("readdir", unimplementedFunc), + /* 205 */ SyscallDesc("readahead", unimplementedFunc), + /* 206 */ SyscallDesc("socketcall", unimplementedFunc), + /* 207 */ SyscallDesc("syslog", unimplementedFunc), + /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), + /* 211 */ SyscallDesc("tgkill", unimplementedFunc), + /* 212 */ SyscallDesc("waitpid", unimplementedFunc), + /* 213 */ SyscallDesc("swapoff", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 215 */ SyscallDesc("ipc", unimplementedFunc), + /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 217 */ SyscallDesc("clone", unimplementedFunc), + /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 221 */ SyscallDesc("create_module", unimplementedFunc), + /* 222 */ SyscallDesc("delete_module", unimplementedFunc), + /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 224 */ SyscallDesc("getpgid", unimplementedFunc), + /* 225 */ SyscallDesc("bdflush", unimplementedFunc), + /* 226 */ SyscallDesc("sysfs", unimplementedFunc), + /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 230 */ SyscallDesc("_newselect", unimplementedFunc), + /* 231 */ SyscallDesc("time", ignoreFunc), + /* 232 */ SyscallDesc("oldstat", unimplementedFunc), + /* 233 */ SyscallDesc("stime", unimplementedFunc), + /* 234 */ SyscallDesc("statfs64", unimplementedFunc), + /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", _llseekFunc), + /* 237 */ SyscallDesc("mlock", unimplementedFunc), + /* 238 */ SyscallDesc("munlock", unimplementedFunc), + /* 239 */ SyscallDesc("mlockall", unimplementedFunc), + /* 240 */ SyscallDesc("munlockall", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", unimplementedFunc), + /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 252 */ SyscallDesc("getsid", unimplementedFunc), + /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 255 */ SyscallDesc("aplib", unimplementedFunc), + /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 266 */ SyscallDesc("timer_create", unimplementedFunc), + /* 267 */ SyscallDesc("vserver", unimplementedFunc), + /* 268 */ SyscallDesc("io_setup", unimplementedFunc), + /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 270 */ SyscallDesc("io_submit", unimplementedFunc), + /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 273 */ SyscallDesc("mq_open", unimplementedFunc), + /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 279 */ SyscallDesc("waitid", unimplementedFunc), + /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 281 */ SyscallDesc("add_key", unimplementedFunc), + /* 282 */ SyscallDesc("request_key", unimplementedFunc), + /* 283 */ SyscallDesc("keyctl", unimplementedFunc) +}; + +} // namespace SparcISA diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 8b612e8b4..5bd572d38 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -54,7 +54,15 @@ string SparcISA::getMiscRegName(RegIndex index) "wstate",*/ "gl", "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", "hstick_cmpr", - "fsr"}; + "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", "itbTsbC0Ps0", + "itbTsbC0Ps1", "iTlbC0Cnfg", "itbTsbCXPs0", "itbTsbCXPs1", + "iTlbCXCnfg","iTlbSfsr", "iTlbTagAcs", "dtbTsbC0Ps0", + "dtbTsbC0Ps1", "dTlbC0Cnfg", "dtbTsbCXPs0", "dtbTsbCXPs1", + "dTlbCXCnfg","dTlbSfsr", "dTlbSfar", "dTlbTagAcs", + "scratch0", "scratch1", "scratch2", "scratch3", "scratch4", + "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail", + "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail", + "nresErrorHead", "nresErrorTail", "TlbData" }; return miscRegName[index]; } @@ -132,7 +140,7 @@ void MiscRegFile::clear() #endif } -MiscReg MiscRegFile::readReg(int miscReg) +MiscReg MiscRegFile::readRegNoEffect(int miscReg) { switch (miscReg) { case MISCREG_TLB_DATA: @@ -223,8 +231,6 @@ MiscReg MiscRegFile::readReg(int miscReg) return hintp; case MISCREG_HTBA: return htba; - case MISCREG_HVER: - return NWindows | MaxTL << 8 | MaxGL << 16; case MISCREG_STRAND_STS_REG: return strandStatusReg; case MISCREG_HSTICK_CMPR: @@ -317,7 +323,7 @@ MiscReg MiscRegFile::readReg(int miscReg) } } -MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) +MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) { switch (miscReg) { // tick and stick are aliased to each other in niagra @@ -360,7 +366,7 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM case MISCREG_HPSTATE: - return readFSRegWithEffect(miscReg, tc); + return readFSReg(miscReg, tc); #else case MISCREG_HPSTATE: //HPSTATE is special because because sometimes in privilege checks for instructions @@ -372,10 +378,10 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) #endif } - return readReg(miscReg); + return readRegNoEffect(miscReg); } -void MiscRegFile::setReg(int miscReg, const MiscReg &val) +void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) { switch (miscReg) { // case MISCREG_Y: @@ -602,13 +608,12 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) case MISCREG_QUEUE_NRES_ERROR_TAIL: nres_error_tail = val; break; - default: panic("Miscellaneous register %d not implemented\n", miscReg); } } -void MiscRegFile::setRegWithEffect(int miscReg, +void MiscRegFile::setReg(int miscReg, const MiscReg &val, ThreadContext * tc) { MiscReg new_val = val; @@ -633,9 +638,20 @@ void MiscRegFile::setRegWithEffect(int miscReg, return; case MISCREG_TL: tl = val; +#if FULL_SYSTEM + if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) + tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); +#endif return; case MISCREG_CWP: - new_val = val > NWindows ? NWindows - 1 : val; + new_val = val >= NWindows ? NWindows - 1 : val; + if (val >= NWindows) { + new_val = NWindows - 1; + warn("Attempted to set the CWP to %d with NWindows = %d\n", + val, NWindows); + } tc->changeRegFileContext(CONTEXT_CWP, new_val); break; case MISCREG_GL: @@ -663,7 +679,7 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM case MISCREG_HPSTATE: - setFSRegWithEffect(miscReg, val, tc); + setFSReg(miscReg, val, tc); return; #else case MISCREG_HPSTATE: @@ -673,7 +689,7 @@ void MiscRegFile::setRegWithEffect(int miscReg, panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val); #endif } - setReg(miscReg, new_val); + setRegNoEffect(miscReg, new_val); } void MiscRegFile::serialize(std::ostream & os) diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 66c9f17df..867f959e1 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -39,6 +39,8 @@ #include <string> +class Checkpoint; + namespace SparcISA { //These functions map register indices to names @@ -161,6 +163,23 @@ namespace SparcISA const static int ie = 0x2; }; + struct STS { + const static int st_idle = 0x00; + const static int st_wait = 0x01; + const static int st_halt = 0x02; + const static int st_run = 0x05; + const static int st_spec_run = 0x07; + const static int st_spec_rdy = 0x13; + const static int st_ready = 0x19; + const static int active = 0x01; + const static int speculative = 0x04; + const static int shft_id = 8; + const static int shft_fsm0 = 31; + const static int shft_fsm1 = 26; + const static int shft_fsm2 = 21; + const static int shft_fsm3 = 16; + }; + const int NumMiscArchRegs = MISCREG_NUMMISCREGS; const int NumMiscRegs = MISCREG_NUMMISCREGS; @@ -255,9 +274,11 @@ namespace SparcISA // These need to check the int_dis field and if 0 then // set appropriate bit in softint and checkinterrutps on the cpu #if FULL_SYSTEM - void setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc); - MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc); + void setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc); + MiscReg readFSReg(int miscReg, ThreadContext * tc); + + // Update interrupt state on softint or pil change + void checkSoftInt(ThreadContext *tc); /** Process a tick compare event and generate an interrupt on the cpu if * appropriate. */ @@ -286,13 +307,13 @@ namespace SparcISA clear(); } - MiscReg readReg(int miscReg); + MiscReg readRegNoEffect(int miscReg); - MiscReg readRegWithEffect(int miscReg, ThreadContext *tc); + MiscReg readReg(int miscReg, ThreadContext *tc); - void setReg(int miscReg, const MiscReg &val); + void setRegNoEffect(int miscReg, const MiscReg &val); - void setRegWithEffect(int miscReg, + void setReg(int miscReg, const MiscReg &val, ThreadContext * tc); int getInstAsid() diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index fc01e82da..980225052 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -45,6 +45,22 @@ struct VAddr VAddr(Addr a) { panic("not implemented yet."); } }; +class TteTag +{ + private: + uint64_t entry; + bool populated; + + public: + TteTag() : entry(0), populated(false) {} + TteTag(uint64_t e) : entry(e), populated(true) {} + const TteTag &operator=(uint64_t e) { populated = true; + entry = e; return *this; } + bool valid() const {assert(populated); return !bits(entry,62,62); } + Addr va() const {assert(populated); return bits(entry,41,0); } +}; + + class PageTableEntry { public: @@ -110,13 +126,14 @@ class PageTableEntry entry4u = e; return *this; } const PageTableEntry &operator=(const PageTableEntry &e) - { populated = true; entry4u = e.entry4u; return *this; } + { populated = true; entry4u = e.entry4u; type = e.type; return *this; } bool valid() const { return bits(entry4u,63,63) && populated; } uint8_t _size() const { assert(populated); return bits(entry4u, 62,61) | bits(entry4u, 48,48) << 2; } Addr size() const { assert(_size() < 6); return pageSizes[_size()]; } + Addr sizeMask() const { assert(_size() < 6); return pageSizes[_size()]-1;} bool ie() const { return bits(entry4u, 59,59); } Addr pfn() const { assert(populated); return bits(entry4u,39,13); } Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);} @@ -127,6 +144,8 @@ class PageTableEntry bool writable() const { assert(populated); return bits(entry4u,1,1); } bool nofault() const { assert(populated); return bits(entry4u,60,60); } bool sideffect() const { assert(populated); return bits(entry4u,3,3); } + Addr paddrMask() const { assert(populated); + return mbits(entry4u, 39,13) & ~sizeMask(); } }; struct TlbRange { diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh new file mode 100644 index 000000000..4a8c9dc4a --- /dev/null +++ b/src/arch/sparc/predecoder.hh @@ -0,0 +1,113 @@ +/* + * 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_PREDECODER_HH__ +#define __ARCH_SPARC_PREDECODER_HH__ + +#include "arch/sparc/types.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace SparcISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst inst) + { + assert(off == 0); + + emi = inst; + //The I bit, bit 13, is used to figure out where the ASI + //should come from. Use that in the ExtMachInst. This is + //slightly redundant, but it removes the need to put a condition + //into all the execute functions + if(inst & (1 << 13)) + emi |= (static_cast<ExtMachInst>( + tc->readMiscRegNoEffect(MISCREG_ASI)) + << (sizeof(MachInst) * 8)); + else + emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) + << (sizeof(MachInst) * 8)); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_SPARC_PREDECODER_HH__ diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 1e639b9a5..e4774ab54 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -30,6 +30,7 @@ */ #include "arch/sparc/asi.hh" +#include "arch/sparc/handlers.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "arch/sparc/types.hh" @@ -59,14 +60,6 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = roundUp(brk_point, VMPageSize); - // Set up stack. On SPARC Linux, stack goes from the top of memory - // downward, less the hole for the kernel address space. - stack_base = (Addr)0x80000000000ULL; - - // Set up region for mmaps. Tru64 seems to start just above 0 and - // grow up from there. - mmap_start = mmap_end = 0xfffff80000000000ULL; - // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); @@ -75,136 +68,118 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, spillStart = 0; } +void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + case 0x03: //Flush window trap + warn("Ignoring request to flush register windows.\n"); + break; + default: + panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); + } +} + void -SparcLiveProcess::startup() +Sparc32LiveProcess::startup() { - argsInit(sizeof(IntReg), VMPageSize); + argsInit(32 / 8, VMPageSize); //From the SPARC ABI //The process runs in user mode - threadContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE, 0x02); + threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); //Setup default FP state - threadContexts[0]->setMiscReg(MISCREG_FSR, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); - threadContexts[0]->setMiscReg(MISCREG_TICK, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); // /* * Register window management registers */ //No windows contain info from other programs - //threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); //There are no windows to pop - //threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); //All windows are available to save into - //threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); //All windows are "clean" - //threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); //Start with register window 0 - threadContexts[0]->setMiscReg(MISCREG_CWP, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); //Always use spill and fill traps 0 - //threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); //Set the trap level to 0 - threadContexts[0]->setMiscReg(MISCREG_TL, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); //Set the ASI register to something fixed - threadContexts[0]->setMiscReg(MISCREG_ASI, ASI_PRIMARY); + threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); } -m5_auxv_t buildAuxVect(int64_t type, int64_t val) +void +Sparc64LiveProcess::startup() { - m5_auxv_t result; - result.a_type = TheISA::htog(type); - result.a_val = TheISA::htog(val); - return result; -} + argsInit(sizeof(IntReg), VMPageSize); + + //From the SPARC ABI + + //The process runs in user mode + threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); + + //Setup default FP state + threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); + + threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); + // + /* + * Register window management registers + */ -//We only use 19 instructions for the trap handlers, but there would be -//space for 32 in a real SPARC trap table. -const int numFillInsts = 32; -const int numSpillInsts = 32; + //No windows contain info from other programs + //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); + //There are no windows to pop + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); + //All windows are available to save into + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); + threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); + //All windows are "clean" + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); + threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); + //Start with register window 0 + threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); + //Always use spill and fill traps 0 + //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); + //Set the trap level to 0 + threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); + //Set the ASI register to something fixed + threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); +} -MachInst fillHandler[numFillInsts] = +M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val) { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi - htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 - htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 - htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 - htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3 - htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4 - htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5 - htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6 - htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7 - htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0 - htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1 - htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2 - htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3 - htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4 - htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5 - htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6 - htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7 - htog(0x83880000), //restored - htog(0x83F00000), //retry - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000) //illtrap -}; - -MachInst spillHandler[numSpillInsts] = + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} + +M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi - htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi - htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi - htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi - htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi - htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi - htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi - htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi - htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi - htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi - htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi - htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi - htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi - htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi - htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi - htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi - htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi - htog(0x81880000), //saved - htog(0x83F00000), //retry - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000) //illtrap -}; + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} void -SparcLiveProcess::argsInit(int intSize, int pageSize) +Sparc64LiveProcess::argsInit(int intSize, int pageSize) { + typedef M5_64_auxv_t auxv_t; Process::startup(); string filename; @@ -265,34 +240,34 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) if(elfObject) { //Bits which describe the system hardware capabilities - auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap)); //The system page size - auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); //Defined to be 100 in the kernel source. //Frequency at which times() increments - auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100)); + auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100)); // For statically linked executables, this is the virtual address of the // program header tables if they appear in the executable image - auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable())); + auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable())); // This is the size of a program header entry from the elf file. - auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize())); + auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize())); // This is the number of program headers from the original elf file. - auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount())); + auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount())); //This is the address of the elf "interpreter", It should be set //to 0 for regular executables. It should be something else //(not sure what) for dynamic libraries. - auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); + auxv.push_back(auxv_t(SPARC_AT_BASE, 0)); //This is hardwired to 0 in the elf loading code in the kernel - auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); + auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); //The entry point to the program - auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint())); + auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); //Different user and group IDs - auxv.push_back(buildAuxVect(SPARC_AT_UID, uid())); - auxv.push_back(buildAuxVect(SPARC_AT_EUID, euid())); - auxv.push_back(buildAuxVect(SPARC_AT_GID, gid())); - auxv.push_back(buildAuxVect(SPARC_AT_EGID, egid())); + auxv.push_back(auxv_t(SPARC_AT_UID, uid())); + auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); + auxv.push_back(auxv_t(SPARC_AT_GID, gid())); + auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); //Whether to enable "secure mode" in the executable - auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0)); + auxv.push_back(auxv_t(SPARC_AT_SECURE, 0)); } //Figure out how big the initial stack needs to be @@ -419,8 +394,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) int spillSize = sizeof(MachInst) * numSpillInsts; fillStart = stack_base; spillStart = fillStart + fillSize; - initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler, fillSize); - initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler, spillSize); + initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize); + initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize); //Set up the thread context to start running the process threadContexts[0]->setIntReg(ArgumentReg0, argc); @@ -437,3 +412,231 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) // num_processes++; } + +void +Sparc32LiveProcess::argsInit(int intSize, int pageSize) +{ + typedef M5_32_auxv_t auxv_t; + Process::startup(); + + string filename; + if(argv.size() < 1) + filename = ""; + else + filename = argv[0]; + + //Even though this is a 32 bit process, the ABI says we still need to + //maintain double word alignment of the stack pointer. + Addr alignmentMask = ~(8 - 1); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + //These are the auxilliary vector types + enum auxTypes + { + SPARC_AT_HWCAP = 16, + SPARC_AT_PAGESZ = 6, + SPARC_AT_CLKTCK = 17, + SPARC_AT_PHDR = 3, + SPARC_AT_PHENT = 4, + SPARC_AT_PHNUM = 5, + SPARC_AT_BASE = 7, + SPARC_AT_FLAGS = 8, + SPARC_AT_ENTRY = 9, + SPARC_AT_UID = 11, + SPARC_AT_EUID = 12, + SPARC_AT_GID = 13, + SPARC_AT_EGID = 14, + SPARC_AT_SECURE = 23 + }; + + enum hardwareCaps + { + M5_HWCAP_SPARC_FLUSH = 1, + M5_HWCAP_SPARC_STBAR = 2, + M5_HWCAP_SPARC_SWAP = 4, + M5_HWCAP_SPARC_MULDIV = 8, + M5_HWCAP_SPARC_V9 = 16, + //This one should technically only be set + //if there is a cheetah or cheetah_plus tlb, + //but we'll use it all the time + M5_HWCAP_SPARC_ULTRA3 = 32 + }; + + const int64_t hwcap = + M5_HWCAP_SPARC_FLUSH | + M5_HWCAP_SPARC_STBAR | + M5_HWCAP_SPARC_SWAP | + M5_HWCAP_SPARC_MULDIV | + M5_HWCAP_SPARC_V9 | + M5_HWCAP_SPARC_ULTRA3; + + + //Setup the auxilliary vectors. These will already have endian conversion. + //Auxilliary vectors are loaded only for elf formatted executables. + ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); + if(elfObject) + { + //Bits which describe the system hardware capabilities + auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap)); + //The system page size + auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + //Defined to be 100 in the kernel source. + //Frequency at which times() increments + auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100)); + // For statically linked executables, this is the virtual address of the + // program header tables if they appear in the executable image + auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount())); + //This is the address of the elf "interpreter", It should be set + //to 0 for regular executables. It should be something else + //(not sure what) for dynamic libraries. + auxv.push_back(auxv_t(SPARC_AT_BASE, 0)); + //This is hardwired to 0 in the elf loading code in the kernel + auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(auxv_t(SPARC_AT_UID, uid())); + auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); + auxv.push_back(auxv_t(SPARC_AT_GID, gid())); + auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); + //Whether to enable "secure mode" in the executable + auxv.push_back(auxv_t(SPARC_AT_SECURE, 0)); + } + + //Figure out how big the initial stack needs to be + + // The unaccounted for 8 byte 0 at the top of the stack + int mysterious_size = 8; + + //This is the name of the file which is present on the initial stack + //It's purpose is to let the user space linker examine the original file. + int file_name_size = filename.size() + 1; + + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + + //The info_block - This seems to need an pad for some reason. + int info_block_size = + (mysterious_size + + file_name_size + + env_data_size + + arg_data_size + intSize); + + //Each auxilliary vector is two 4 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + int window_save_size = intSize * 16; + + int space_needed = + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size + + window_save_size; + + stack_min = stack_base - space_needed; + stack_min &= alignmentMask; + stack_size = stack_base - stack_min; + + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); + + // map out initial stack contents + uint32_t window_save_base = stack_min; + uint32_t argc_base = window_save_base + window_save_size; + uint32_t argv_array_base = argc_base + argc_size; + uint32_t envp_array_base = argv_array_base + argv_array_size; + uint32_t auxv_array_base = envp_array_base + envp_array_size; + //The info block is pushed up against the top of the stack, while + //the rest of the initial stack frame is aligned to an 8 byte boudary. + uint32_t arg_data_base = stack_base - info_block_size + intSize; + uint32_t env_data_base = arg_data_base + arg_data_size; + uint32_t file_name_base = env_data_base + env_data_size; + uint32_t mysterious_base = file_name_base + file_name_size; + + DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); + DPRINTF(Sparc, "0x%x - file name\n", file_name_base); + DPRINTF(Sparc, "0x%x - env data\n", env_data_base); + DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base); + DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base); + DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base); + DPRINTF(Sparc, "0x%x - argc \n", argc_base); + DPRINTF(Sparc, "0x%x - window save\n", window_save_base); + DPRINTF(Sparc, "0x%x - stack min\n", stack_min); + + // write contents to stack + + // figure out argc + uint32_t argc = argv.size(); + uint32_t guestArgc = TheISA::htog(argc); + + //Write out the mysterious 0 + uint64_t mysterious_zero = 0; + initVirtMem->writeBlob(mysterious_base, + (uint8_t*)&mysterious_zero, mysterious_size); + + //Write the file name + initVirtMem->writeString(file_name_base, filename.c_str()); + + //Copy the aux stuff + for(int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + //Write out the terminating zeroed auxilliary vector + const uint64_t zero = 0; + initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), + (uint8_t*)&zero, 2 * intSize); + + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + + //Stuff the trap handlers into the processes address space. + //Since the stack grows down and is the highest area in the processes + //address space, we can put stuff above it and stay out of the way. + int fillSize = sizeof(MachInst) * numFillInsts; + int spillSize = sizeof(MachInst) * numSpillInsts; + fillStart = stack_base; + spillStart = fillStart + fillSize; + initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize); + initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize); + + //Set up the thread context to start running the process + //threadContexts[0]->setIntReg(ArgumentReg0, argc); + //threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + threadContexts[0]->setIntReg(StackPointerReg, stack_min); + + uint32_t prog_entry = objFile->entryPoint(); + threadContexts[0]->setPC(prog_entry); + threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); + +// num_processes++; +} diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 1cf7ec224..2512441c6 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -39,27 +39,13 @@ class ObjectFile; class System; -typedef struct -{ - int64_t a_type; - union { - int64_t a_val; - Addr a_ptr; - Addr a_fcn; - }; -} m5_auxv_t; - class SparcLiveProcess : public LiveProcess { protected: - static const Addr StackBias = 2047; - //The locations of the fill and spill handlers Addr fillStart, spillStart; - std::vector<m5_auxv_t> auxv; - SparcLiveProcess(const std::string &nm, ObjectFile *objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, @@ -69,11 +55,10 @@ class SparcLiveProcess : public LiveProcess uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); - void startup(); - public: - void argsInit(int intSize, int pageSize); + //Handles traps which request services from the operating system + virtual void handleTrap(int trapNum, ThreadContext *tc); Addr readFillStart() { return fillStart; } @@ -83,4 +68,107 @@ class SparcLiveProcess : public LiveProcess }; +struct M5_32_auxv_t +{ + int32_t a_type; + union { + int32_t a_val; + int32_t a_ptr; + int32_t a_fcn; + }; + + M5_32_auxv_t() + {} + + M5_32_auxv_t(int32_t type, int32_t val); +}; + +class Sparc32LiveProcess : public SparcLiveProcess +{ + protected: + + std::vector<M5_32_auxv_t> auxv; + + Sparc32LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) : + SparcLiveProcess(nm, objFile, _system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) + { + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = (Addr)0xf0000000ULL; + + // Set up region for mmaps. + mmap_start = mmap_end = 0x70000000; + } + + void startup(); + + public: + + void argsInit(int intSize, int pageSize); + +}; + +struct M5_64_auxv_t +{ + int64_t a_type; + union { + int64_t a_val; + int64_t a_ptr; + int64_t a_fcn; + }; + + M5_64_auxv_t() + {} + + M5_64_auxv_t(int64_t type, int64_t val); +}; + +class Sparc64LiveProcess : public SparcLiveProcess +{ + protected: + + static const Addr StackBias = 2047; + + std::vector<M5_64_auxv_t> auxv; + + Sparc64LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) : + SparcLiveProcess(nm, objFile, _system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) + { + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = (Addr)0x80000000000ULL; + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0xfffff80000000000ULL; + } + + void startup(); + + public: + + void argsInit(int intSize, int pageSize); + +}; + #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 827e22c31..667b1f002 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -75,25 +75,25 @@ void RegFile::clear() miscRegFile.clear(); } -MiscReg RegFile::readMiscReg(int miscReg) +MiscReg RegFile::readMiscRegNoEffect(int miscReg) { - return miscRegFile.readReg(miscReg); + return miscRegFile.readRegNoEffect(miscReg); } -MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc) +MiscReg RegFile::readMiscReg(int miscReg, ThreadContext *tc) { - return miscRegFile.readRegWithEffect(miscReg, tc); + return miscRegFile.readReg(miscReg, tc); } -void RegFile::setMiscReg(int miscReg, const MiscReg &val) +void RegFile::setMiscRegNoEffect(int miscReg, const MiscReg &val) { - miscRegFile.setReg(miscReg, val); + miscRegFile.setRegNoEffect(miscReg, val); } -void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, +void RegFile::setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setReg(miscReg, val, tc); } FloatReg RegFile::readFloatReg(int floatReg, int width) @@ -153,8 +153,8 @@ void RegFile::setIntReg(int intReg, const IntReg &val) int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) { - int gl = tc->readMiscReg(MISCREG_GL); - int cwp = tc->readMiscReg(MISCREG_CWP); + int gl = tc->readMiscRegNoEffect(MISCREG_GL); + int cwp = tc->readMiscRegNoEffect(MISCREG_CWP); //DPRINTF(Sparc, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); int newReg; //The total number of global registers @@ -254,162 +254,149 @@ void RegFile::changeContext(RegContextParam param, RegContextVal val) } } -int SparcISA::InterruptLevel(uint64_t softint) -{ - if (softint & 0x10000 || softint & 0x1) - return 14; - - int level = 15; - while (level > 0 && !(1 << level & softint)) - level--; - if (1 << level & softint) - return level; - return 0; -} - void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) { - uint8_t tl = src->readMiscReg(MISCREG_TL); + uint8_t tl = src->readMiscRegNoEffect(MISCREG_TL); // Read all the trap level dependent registers and save them off for(int i = 1; i <= MaxTL; i++) { - src->setMiscReg(MISCREG_TL, i); - dest->setMiscReg(MISCREG_TL, i); + src->setMiscRegNoEffect(MISCREG_TL, i); + dest->setMiscRegNoEffect(MISCREG_TL, i); - dest->setMiscReg(MISCREG_TT, src->readMiscReg(MISCREG_TT)); - dest->setMiscReg(MISCREG_TPC, src->readMiscReg(MISCREG_TPC)); - dest->setMiscReg(MISCREG_TNPC, src->readMiscReg(MISCREG_TNPC)); - dest->setMiscReg(MISCREG_TSTATE, src->readMiscReg(MISCREG_TSTATE)); + dest->setMiscRegNoEffect(MISCREG_TT, src->readMiscRegNoEffect(MISCREG_TT)); + dest->setMiscRegNoEffect(MISCREG_TPC, src->readMiscRegNoEffect(MISCREG_TPC)); + dest->setMiscRegNoEffect(MISCREG_TNPC, src->readMiscRegNoEffect(MISCREG_TNPC)); + dest->setMiscRegNoEffect(MISCREG_TSTATE, src->readMiscRegNoEffect(MISCREG_TSTATE)); } // Save off the traplevel - dest->setMiscReg(MISCREG_TL, tl); - src->setMiscReg(MISCREG_TL, tl); + dest->setMiscRegNoEffect(MISCREG_TL, tl); + src->setMiscRegNoEffect(MISCREG_TL, tl); // ASRs -// dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); -// dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); - dest->setMiscReg(MISCREG_ASI, src->readMiscReg(MISCREG_ASI)); - dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); - dest->setMiscReg(MISCREG_FPRS, src->readMiscReg(MISCREG_FPRS)); - dest->setMiscReg(MISCREG_SOFTINT, src->readMiscReg(MISCREG_SOFTINT)); - dest->setMiscReg(MISCREG_TICK_CMPR, src->readMiscReg(MISCREG_TICK_CMPR)); - dest->setMiscReg(MISCREG_STICK, src->readMiscReg(MISCREG_STICK)); - dest->setMiscReg(MISCREG_STICK_CMPR, src->readMiscReg(MISCREG_STICK_CMPR)); +// dest->setMiscRegNoEffect(MISCREG_Y, src->readMiscRegNoEffect(MISCREG_Y)); +// dest->setMiscRegNoEffect(MISCREG_CCR, src->readMiscRegNoEffect(MISCREG_CCR)); + dest->setMiscRegNoEffect(MISCREG_ASI, src->readMiscRegNoEffect(MISCREG_ASI)); + dest->setMiscRegNoEffect(MISCREG_TICK, src->readMiscRegNoEffect(MISCREG_TICK)); + dest->setMiscRegNoEffect(MISCREG_FPRS, src->readMiscRegNoEffect(MISCREG_FPRS)); + dest->setMiscRegNoEffect(MISCREG_SOFTINT, src->readMiscRegNoEffect(MISCREG_SOFTINT)); + dest->setMiscRegNoEffect(MISCREG_TICK_CMPR, src->readMiscRegNoEffect(MISCREG_TICK_CMPR)); + dest->setMiscRegNoEffect(MISCREG_STICK, src->readMiscRegNoEffect(MISCREG_STICK)); + dest->setMiscRegNoEffect(MISCREG_STICK_CMPR, src->readMiscRegNoEffect(MISCREG_STICK_CMPR)); // Priv Registers - dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); - dest->setMiscReg(MISCREG_TBA, src->readMiscReg(MISCREG_TBA)); - dest->setMiscReg(MISCREG_PSTATE, src->readMiscReg(MISCREG_PSTATE)); - dest->setMiscReg(MISCREG_PIL, src->readMiscReg(MISCREG_PIL)); - dest->setMiscReg(MISCREG_CWP, src->readMiscReg(MISCREG_CWP)); -// dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE)); -// dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE)); -// dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN)); -// dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN)); -// dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE)); - dest->setMiscReg(MISCREG_GL, src->readMiscReg(MISCREG_GL)); + dest->setMiscRegNoEffect(MISCREG_TICK, src->readMiscRegNoEffect(MISCREG_TICK)); + dest->setMiscRegNoEffect(MISCREG_TBA, src->readMiscRegNoEffect(MISCREG_TBA)); + dest->setMiscRegNoEffect(MISCREG_PSTATE, src->readMiscRegNoEffect(MISCREG_PSTATE)); + dest->setMiscRegNoEffect(MISCREG_PIL, src->readMiscRegNoEffect(MISCREG_PIL)); + dest->setMiscRegNoEffect(MISCREG_CWP, src->readMiscRegNoEffect(MISCREG_CWP)); +// dest->setMiscRegNoEffect(MISCREG_CANSAVE, src->readMiscRegNoEffect(MISCREG_CANSAVE)); +// dest->setMiscRegNoEffect(MISCREG_CANRESTORE, src->readMiscRegNoEffect(MISCREG_CANRESTORE)); +// dest->setMiscRegNoEffect(MISCREG_OTHERWIN, src->readMiscRegNoEffect(MISCREG_OTHERWIN)); +// dest->setMiscRegNoEffect(MISCREG_CLEANWIN, src->readMiscRegNoEffect(MISCREG_CLEANWIN)); +// dest->setMiscRegNoEffect(MISCREG_WSTATE, src->readMiscRegNoEffect(MISCREG_WSTATE)); + dest->setMiscRegNoEffect(MISCREG_GL, src->readMiscRegNoEffect(MISCREG_GL)); // Hyperprivilged registers - dest->setMiscReg(MISCREG_HPSTATE, src->readMiscReg(MISCREG_HPSTATE)); - dest->setMiscReg(MISCREG_HINTP, src->readMiscReg(MISCREG_HINTP)); - dest->setMiscReg(MISCREG_HTBA, src->readMiscReg(MISCREG_HTBA)); - dest->setMiscReg(MISCREG_STRAND_STS_REG, - src->readMiscReg(MISCREG_STRAND_STS_REG)); - dest->setMiscReg(MISCREG_HSTICK_CMPR, - src->readMiscReg(MISCREG_HSTICK_CMPR)); + dest->setMiscRegNoEffect(MISCREG_HPSTATE, src->readMiscRegNoEffect(MISCREG_HPSTATE)); + dest->setMiscRegNoEffect(MISCREG_HINTP, src->readMiscRegNoEffect(MISCREG_HINTP)); + dest->setMiscRegNoEffect(MISCREG_HTBA, src->readMiscRegNoEffect(MISCREG_HTBA)); + dest->setMiscRegNoEffect(MISCREG_STRAND_STS_REG, + src->readMiscRegNoEffect(MISCREG_STRAND_STS_REG)); + dest->setMiscRegNoEffect(MISCREG_HSTICK_CMPR, + src->readMiscRegNoEffect(MISCREG_HSTICK_CMPR)); // FSR - dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR)); + dest->setMiscRegNoEffect(MISCREG_FSR, src->readMiscRegNoEffect(MISCREG_FSR)); //Strand Status Register - dest->setMiscReg(MISCREG_STRAND_STS_REG, - src->readMiscReg(MISCREG_STRAND_STS_REG)); + dest->setMiscRegNoEffect(MISCREG_STRAND_STS_REG, + src->readMiscRegNoEffect(MISCREG_STRAND_STS_REG)); // MMU Registers - dest->setMiscReg(MISCREG_MMU_P_CONTEXT, - src->readMiscReg(MISCREG_MMU_P_CONTEXT)); - dest->setMiscReg(MISCREG_MMU_S_CONTEXT, - src->readMiscReg(MISCREG_MMU_S_CONTEXT)); - dest->setMiscReg(MISCREG_MMU_PART_ID, - src->readMiscReg(MISCREG_MMU_PART_ID)); - dest->setMiscReg(MISCREG_MMU_LSU_CTRL, - src->readMiscReg(MISCREG_MMU_LSU_CTRL)); - - dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0, - src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1, - src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG, - src->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0, - src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1, - src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG, - src->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); - dest->setMiscReg(MISCREG_MMU_ITLB_SFSR, - src->readMiscReg(MISCREG_MMU_ITLB_SFSR)); - dest->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, - src->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS)); - - dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0, - src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1, - src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG, - src->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0, - src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1, - src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG, - src->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); - dest->setMiscReg(MISCREG_MMU_DTLB_SFSR, - src->readMiscReg(MISCREG_MMU_DTLB_SFSR)); - dest->setMiscReg(MISCREG_MMU_DTLB_SFAR, - src->readMiscReg(MISCREG_MMU_DTLB_SFAR)); - dest->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, - src->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS)); + dest->setMiscRegNoEffect(MISCREG_MMU_P_CONTEXT, + src->readMiscRegNoEffect(MISCREG_MMU_P_CONTEXT)); + dest->setMiscRegNoEffect(MISCREG_MMU_S_CONTEXT, + src->readMiscRegNoEffect(MISCREG_MMU_S_CONTEXT)); + dest->setMiscRegNoEffect(MISCREG_MMU_PART_ID, + src->readMiscRegNoEffect(MISCREG_MMU_PART_ID)); + dest->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, + src->readMiscRegNoEffect(MISCREG_MMU_LSU_CTRL)); + + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); + + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); // Scratchpad Registers - dest->setMiscReg(MISCREG_SCRATCHPAD_R0, - src->readMiscReg(MISCREG_SCRATCHPAD_R0)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R1, - src->readMiscReg(MISCREG_SCRATCHPAD_R1)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R2, - src->readMiscReg(MISCREG_SCRATCHPAD_R2)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R3, - src->readMiscReg(MISCREG_SCRATCHPAD_R3)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R4, - src->readMiscReg(MISCREG_SCRATCHPAD_R4)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R5, - src->readMiscReg(MISCREG_SCRATCHPAD_R5)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R6, - src->readMiscReg(MISCREG_SCRATCHPAD_R6)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R7, - src->readMiscReg(MISCREG_SCRATCHPAD_R7)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R0, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R0)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R1, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R1)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R2, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R2)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R3, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R3)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R4, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R4)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R5, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R5)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R6, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R6)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R7, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R7)); // Queue Registers - dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD, - src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL, - src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD, - src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL, - src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD, - src->readMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL, - src->readMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD, - src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL, - src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_TAIL)); } void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest) diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index d9af0757c..f3e253f7e 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -73,13 +73,13 @@ namespace SparcISA int FlattenIntIndex(int reg); - MiscReg readMiscReg(int miscReg); + MiscReg readMiscRegNoEffect(int miscReg); - MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc); + MiscReg readMiscReg(int miscReg, ThreadContext *tc); - void setMiscReg(int miscReg, const MiscReg &val); + void setMiscRegNoEffect(int miscReg, const MiscReg &val); - void setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc); int instAsid() @@ -126,8 +126,6 @@ namespace SparcISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest); - int InterruptLevel(uint64_t softint); - } // namespace SparcISA #endif diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index 21c4a468c..85b0c03a3 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -138,7 +138,7 @@ using namespace std; using namespace TheISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) - : BaseRemoteGDB(_system, c, NumGDBRegs) + : BaseRemoteGDB(_system, c, NumGDBRegs), nextBkpt(0) {} /////////////////////////////////////////////////////////// @@ -152,7 +152,9 @@ 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; + if (va) + return true; + return false; } /////////////////////////////////////////////////////////// @@ -165,10 +167,37 @@ 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); + if (context->readMiscReg(MISCREG_PSTATE) & + PSTATE::am) { + uint32_t *regs; + regs = (uint32_t*)gdbregs.regs; + regs[Reg32Pc] = htobe((uint32_t)context->readPC()); + regs[Reg32Npc] = htobe((uint32_t)context->readNextPC()); + for(int x = RegG0; x <= RegI0 + 7; x++) + regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0)); + + regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1)); + regs[Reg32Psr] = htobe((uint32_t)context->readMiscReg(MISCREG_PSTATE)); + regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); + regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); + } else { + gdbregs.regs[RegPc] = htobe(context->readPC()); + gdbregs.regs[RegNpc] = htobe(context->readNextPC()); + for(int x = RegG0; x <= RegI0 + 7; x++) + gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0)); + + gdbregs.regs[RegFsr] = htobe(context->readMiscReg(MISCREG_FSR)); + gdbregs.regs[RegFprs] = htobe(context->readMiscReg(MISCREG_FPRS)); + gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1)); + gdbregs.regs[RegState] = htobe( + context->readMiscReg(MISCREG_CWP) | + context->readMiscReg(MISCREG_PSTATE) << 8 | + context->readMiscReg(MISCREG_ASI) << 24 | + context->readIntReg(NumIntArchRegs + 2) << 32); + } + + DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]); + //Floating point registers are left at 0 in netbsd //All registers other than the pc, npc and int regs //are ignored as well. @@ -193,12 +222,13 @@ RemoteGDB::setregs() void RemoteGDB::clearSingleStep() { - warn("SPARC single stepping not implemented, " - "but clearSingleStep called\n"); + if (nextBkpt) + clearTempBreakpoint(nextBkpt); } void RemoteGDB::setSingleStep() { - panic("SPARC single stepping not implemented.\n"); + nextBkpt = context->readNextPC(); + setTempBreakpoint(nextBkpt); } diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh index e4b66b783..dbdf810c4 100644 --- a/src/arch/sparc/remote_gdb.hh +++ b/src/arch/sparc/remote_gdb.hh @@ -28,12 +28,12 @@ * Authors: Nathan Binkert */ -#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ -#define __ARCH_ALPHA_REMOTE_GDB_HH__ +#ifndef __ARCH_SPARC_REMOTE_GDB_HH__ +#define __ARCH_SPARC_REMOTE_GDB_HH__ #include <map> -#include "arch/types.hh" +#include "arch/sparc/types.hh" #include "base/remote_gdb.hh" #include "cpu/pc_event.hh" #include "base/pollevent.hh" @@ -50,15 +50,12 @@ namespace SparcISA 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 + RegF0 = 32, + RegPc = 64, RegNpc, RegState, RegFsr, RegFprs, RegY, + /*RegState contains data in same format as tstate */ + Reg32Y = 64, Reg32Psr = 65, Reg32Tbr = 66, Reg32Pc = 67, + Reg32Npc = 68, Reg32Fsr = 69, Reg32Csr = 70, + NumGDBRegs = RegY }; public: @@ -72,7 +69,9 @@ namespace SparcISA void clearSingleStep(); void setSingleStep(); + + Addr nextBkpt; }; } -#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ +#endif /* __ARCH_SPARC_REMOTE_GDB_H__ */ diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc index 2eb697bf2..2d7991267 100644 --- a/src/arch/sparc/stacktrace.cc +++ b/src/arch/sparc/stacktrace.cc @@ -146,7 +146,7 @@ namespace SparcISA #if 0 tc = _tc; - bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + bool usermode = (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; Addr pc = tc->readNextPC(); bool kernel = tc->getSystemPtr()->kernelStart <= pc && @@ -221,22 +221,22 @@ namespace SparcISA StackTrace::isEntry(Addr addr) { #if 0 - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2)) return true; #endif return false; diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index d92b12790..cf13fc3e8 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -49,13 +49,13 @@ namespace SparcISA // no error, clear XCC.C tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) & 0xEE); - //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) & 0xEE); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, set XCC.C tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) | 0x11); - //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); tc->setIntReg(ReturnValueReg, -return_value.value()); } } diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 293f667d6..09266fd6e 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -40,11 +40,11 @@ #include "mem/packet_access.hh" #include "mem/request.hh" #include "sim/builder.hh" +#include "sim/system.hh" /* @todo remove some of the magic constants. -- ali * */ -namespace SparcISA -{ +namespace SparcISA { TLB::TLB(const std::string &name, int s) : SimObject(name), size(s), usedEntries(0), lastReplaced(0), @@ -204,7 +204,8 @@ insertAllLocked: TlbEntry* -TLB::lookup(Addr va, int partition_id, bool real, int context_id) +TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool + update_used) { MapIter i; TlbRange tr; @@ -230,7 +231,10 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id) t = i->second; DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), t->pte.size()); - if (!t->used) { + + // Update the used bits only if this is a real access (not a fake one from + // virttophys() + if (!t->used && update_used) { t->used = true; usedEntries++; if (usedEntries == size) { @@ -392,7 +396,7 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, bool se, FaultTypes ft, int asi) { uint64_t sfsr; - sfsr = tc->readMiscReg(reg); + sfsr = tc->readMiscRegNoEffect(reg); if (sfsr & 0x1) sfsr = 0x3; @@ -406,7 +410,7 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, sfsr |= 1 << 6; sfsr |= ft << 7; sfsr |= asi << 16; - tc->setMiscRegWithEffect(reg, sfsr); + tc->setMiscReg(reg, sfsr); } void @@ -415,7 +419,7 @@ TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n", va, context, mbits(va, 63,13) | mbits(context,12,0)); - tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); + tc->setMiscReg(reg, mbits(va, 63,13) | mbits(context,12,0)); } void @@ -440,7 +444,7 @@ DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", a, (int)write, ct, ft, asi); TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); + tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); } void @@ -454,7 +458,7 @@ DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) Fault ITB::translate(RequestPtr &req, ThreadContext *tc) { - uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); TlbEntry *e; @@ -568,7 +572,7 @@ Fault DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) { /* @todo this could really use some profiling and fixing to make it faster! */ - uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); Addr size = req->getSize(); ASI asi; @@ -592,21 +596,36 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) // Be fast if we can! if (cacheValid && cacheState == tlbdata) { - if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && - cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr && - (!write || cacheEntry[0]->pte.writable())) { - req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | - vaddr & cacheEntry[0]->pte.size()-1 ); - return NoFault; - } - if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && - cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr && - (!write || cacheEntry[1]->pte.writable())) { - req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | - vaddr & cacheEntry[1]->pte.size()-1 ); - return NoFault; - } - } + + + + if (cacheEntry[0]) { + TlbEntry *ce = cacheEntry[0]; + Addr ce_va = ce->range.va; + if (cacheAsi[0] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + if (cacheEntry[1]) { + TlbEntry *ce = cacheEntry[1]; + Addr ce_va = ce->range.va; + if (cacheAsi[1] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + } bool red = bits(tlbdata,1,1); bool priv = bits(tlbdata,2,2); @@ -673,9 +692,12 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (AsiIsPartialStore(asi)) panic("Partial Store ASIs not supported\n"); - if (AsiIsInterrupt(asi)) - panic("Interrupt ASIs not supported\n"); + if (AsiIsCmt(asi)) + panic("Cmt ASI registers not implmented\n"); + + if (AsiIsInterrupt(asi)) + goto handleIntRegAccess; if (AsiIsMmu(asi)) goto handleMmuRegAccess; if (AsiIsScratchPad(asi)) @@ -752,7 +774,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } - if (e->pte.sideffect()) + if (e->pte.sideffect() || (e->pte.paddr() >> 39) & 1) req->setFlags(req->getFlags() | UNCACHEABLE); // cache translation date for next translation @@ -775,7 +797,25 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) vaddr & e->pte.size()-1); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; + /** Normal flow ends here. */ +handleIntRegAccess: + if (!hpriv) { + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + if (priv) + return new DataAccessException; + else + return new PrivilegedAction; + } + + if (asi == ASI_SWVR_UDB_INTR_W && !write || + asi == ASI_SWVR_UDB_INTR_R && write) { + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + return new DataAccessException; + } + + goto regAccessOk; + handleScratchRegAccess: if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { @@ -797,13 +837,11 @@ handleQueueRegAccess: handleSparcErrorRegAccess: if (!hpriv) { - if (priv) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + if (priv) return new DataAccessException; - } else { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + else return new PrivilegedAction; - } } goto regAccessOk; @@ -821,8 +859,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) { Addr va = pkt->getAddr(); ASI asi = (ASI)pkt->req->getAsi(); - uint64_t temp, data; - uint64_t tsbtemp, cnftemp; + uint64_t temp; DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr()); @@ -830,90 +867,90 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); + pkt->set(tc->readMiscReg(MISCREG_MMU_LSU_CTRL)); break; case ASI_MMU: switch (va) { case 0x8: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); + pkt->set(tc->readMiscReg(MISCREG_MMU_P_CONTEXT)); break; case 0x10: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); + pkt->set(tc->readMiscReg(MISCREG_MMU_S_CONTEXT)); break; default: goto doMmuReadError; } break; case ASI_QUEUE: - pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + + pkt->set(tc->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD + (va >> 4) - 0x3c)); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0)); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1)); break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG)); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0)); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1)); break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG)); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0)); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1)); break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0)); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1)); break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); break; case ASI_SPARC_ERROR_STATUS_REG: pkt->set((uint64_t)0); break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: - pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); + pkt->set(tc->readMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3))); break; case ASI_IMMU: switch (va) { case 0x0: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); + temp = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_SFSR)); break; case 0x30: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS)); break; default: goto doMmuReadError; @@ -922,86 +959,65 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x0: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + temp = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFSR)); break; case 0x20: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFAR)); break; case 0x30: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS)); break; case 0x80: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); + pkt->set(tc->readMiscReg(MISCREG_MMU_PART_ID)); break; default: goto doMmuReadError; } break; case ASI_DMMU_TSB_PS0_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - data |= temp >> (9 + bits(cnftemp,2,0) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps0, + tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); break; case ASI_DMMU_TSB_PS1_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - if (bits(tsbtemp,12,12)) - data |= ULL(1) << (13+bits(tsbtemp,3,0)); - data |= temp >> (9 + bits(cnftemp,10,8) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps1, + tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); break; case ASI_IMMU_TSB_PS0_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - data |= temp >> (9 + bits(cnftemp,2,0) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps0, + tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); break; case ASI_IMMU_TSB_PS1_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - if (bits(tsbtemp,12,12)) - data |= ULL(1) << (13+bits(tsbtemp,3,0)); - data |= temp >> (9 + bits(cnftemp,10,8) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps1, + tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); + break; + case ASI_SWVR_INTR_RECEIVE: + pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); + break; + case ASI_SWVR_UDB_INTR_R: + temp = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); + pkt->set(temp); break; - default: doMmuReadError: panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", @@ -1035,15 +1051,15 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); + tc->setMiscReg(MISCREG_MMU_LSU_CTRL, data); break; case ASI_MMU: switch (va) { case 0x8: - tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); + tc->setMiscReg(MISCREG_MMU_P_CONTEXT, data); break; case 0x10: - tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); + tc->setMiscReg(MISCREG_MMU_S_CONTEXT, data); break; default: goto doMmuWriteError; @@ -1051,56 +1067,56 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_QUEUE: assert(mbits(data,13,6) == data); - tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + + tc->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD + (va >> 4) - 0x3c, data); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0, data); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1, data); break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG, data); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0, data); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1, data); break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG, data); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0, data); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1, data); break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG, data); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0, data); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1, data); break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG, data); break; case ASI_SPARC_ERROR_EN_REG: case ASI_SPARC_ERROR_STATUS_REG: @@ -1108,16 +1124,16 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: - tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); + tc->setMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); break; case ASI_IMMU: switch (va) { case 0x18: - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data); + tc->setMiscReg(MISCREG_MMU_ITLB_SFSR, data); break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); + tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, data); break; default: goto doMmuWriteError; @@ -1127,10 +1143,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_ITLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); + ta_insert = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); - part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); @@ -1141,10 +1157,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_DTLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + ta_insert = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); - part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); @@ -1153,10 +1169,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_IMMU_DEMAP: ignore = false; ctx_id = -1; - part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: ignore = true; @@ -1188,14 +1204,14 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x18: - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data); + tc->setMiscReg(MISCREG_MMU_DTLB_SFSR, data); break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); + tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, data); break; case 0x80: - tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); + tc->setMiscReg(MISCREG_MMU_PART_ID, data); break; default: goto doMmuWriteError; @@ -1204,13 +1220,13 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_DMMU_DEMAP: ignore = false; ctx_id = -1; - part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); break; case 3: ctx_id = 0; @@ -1235,7 +1251,19 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) panic("Invalid type for IMMU demap\n"); } break; - default: + case ASI_SWVR_INTR_RECEIVE: + int msb; + // clear all the interrupts that aren't set in the write + while(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data) { + msb = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); + } + break; + case ASI_SWVR_UDB_INTR_W: + tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> + post_interrupt(bits(data,5,0),0); + break; + default: doMmuWriteError: panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); @@ -1245,6 +1273,64 @@ doMmuWriteError: } void +DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs) +{ + uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0); + ptrs[0] = MakeTsbPtr(Ps0, tag_access, + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + ptrs[1] = MakeTsbPtr(Ps1, tag_access, + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + ptrs[2] = MakeTsbPtr(Ps0, tag_access, + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); + ptrs[3] = MakeTsbPtr(Ps1, tag_access, + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); +} + + + + + +uint64_t +DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, + uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config) +{ + uint64_t tsb; + uint64_t config; + + if (bits(tag_access, 12,0) == 0) { + tsb = c0_tsb; + config = c0_config; + } else { + tsb = cX_tsb; + config = cX_config; + } + + uint64_t ptr = mbits(tsb,63,13); + bool split = bits(tsb,12,12); + int tsb_size = bits(tsb,3,0); + int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8); + + if (ps == Ps1 && split) + ptr |= ULL(1) << (13 + tsb_size); + ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4); + + return ptr; +} + + +void TLB::serialize(std::ostream &os) { SERIALIZE_SCALAR(size); @@ -1298,6 +1384,9 @@ TLB::unserialize(Checkpoint *cp, const std::string §ion) } } +/* end namespace SparcISA */ } + +using namespace SparcISA; DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) @@ -1340,4 +1429,3 @@ CREATE_SIM_OBJECT(DTB) } REGISTER_SIM_OBJECT("SparcDTB", DTB) -} diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 34e5f5feb..b5f02c62e 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -78,17 +78,25 @@ class TLB : public SimObject Nucleus = 2 }; - + enum TsbPageSize { + Ps0, + Ps1 + }; + public: /** lookup an entry in the TLB based on the partition id, and real bit if * real is true or the partition id, and context id if real is false. * @param va the virtual address not shifted (e.g. bottom 13 bits are 0) * @param paritition_id partition this entry is for * @param real is this a real->phys or virt->phys translation * @param context_id if this is virt->phys what context + * @param update_used should ew update the used bits in the entries on not + * useful if we are trying to do a va->pa without mucking with any state for + * a debug read for example. * @return A pointer to a tlb entry */ - TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0); - + TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0, + bool update_used = true); + protected: /** Insert a PTE into the TLB. */ void insert(Addr vpn, int partition_id, int context_id, bool real, const PageTableEntry& PTE, int entry = -1); @@ -163,12 +171,17 @@ class DTB : public TLB Fault translate(RequestPtr &req, ThreadContext *tc, bool write); Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); + void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs); private: void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, bool se, FaultTypes ft, int asi); void writeTagAccess(ThreadContext *tc, Addr va, int context); + uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, + uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config); + + TlbEntry *cacheEntry[2]; ASI cacheAsi[2]; }; diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh index 88fb24153..15386adca 100644 --- a/src/arch/sparc/types.hh +++ b/src/arch/sparc/types.hh @@ -32,6 +32,7 @@ #define __ARCH_SPARC_TYPES_HH__ #include <inttypes.h> +#include "base/bigint.hh" namespace SparcISA { @@ -39,6 +40,7 @@ namespace SparcISA typedef uint64_t ExtMachInst; typedef uint64_t IntReg; + typedef Twin64_t LargestRead; typedef uint64_t MiscReg; typedef double FloatReg; typedef uint64_t FloatRegBits; diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index ecb63bb9a..48e97a531 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -26,106 +26,181 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/sparc/kernel_stats.hh" #include "arch/sparc/miscregfile.hh" #include "base/bitfield.hh" #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#include "sim/system.hh" using namespace SparcISA; + +void +MiscRegFile::checkSoftInt(ThreadContext *tc) +{ + // If PIL < 14, copy over the tm and sm bits + if (pil < 14 && softint & 0x10000) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,16); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,16); + if (pil < 14 && softint & 0x1) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,0); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,0); + + // Copy over any of the other bits that are set + for (int bit = 15; bit > 0; --bit) { + if (1 << bit & softint && bit > pil) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,bit); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,bit); + } +} + + void -MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc) +MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) { int64_t time; switch (miscReg) { /* Full system only ASRs */ case MISCREG_SOFTINT: - setReg(miscReg, val);; + setRegNoEffect(miscReg, val);; + checkSoftInt(tc); break; - case MISCREG_SOFTINT_CLR: - return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); + return setReg(MISCREG_SOFTINT, ~val & softint, tc); case MISCREG_SOFTINT_SET: - tc->getCpuPtr()->post_interrupt(soft_interrupt); - return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc); + return setReg(MISCREG_SOFTINT, val | softint, tc); case MISCREG_TICK_CMPR: if (tickCompare == NULL) tickCompare = new TickCompareEvent(this, tc); - setReg(miscReg, val); - if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) + setRegNoEffect(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) + if (!(tick_cmpr & ~mask(63)) && time > 0) { + if (tickCompare->scheduled()) + tickCompare->deschedule(); tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + } panic("writing to TICK compare register %#X\n", val); break; case MISCREG_STICK_CMPR: if (sTickCompare == NULL) sTickCompare = new STickCompareEvent(this, tc); - setReg(miscReg, val); + setRegNoEffect(miscReg, val); if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) sTickCompare->deschedule(); time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); - if (!(stick_cmpr & ~mask(63)) && time > 0) + if (!(stick_cmpr & ~mask(63)) && time > 0) { + if (sTickCompare->scheduled()) + sTickCompare->deschedule(); sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick); + } DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); break; case MISCREG_PSTATE: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); case MISCREG_PIL: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); + checkSoftInt(tc); break; case MISCREG_HVER: panic("Shouldn't be writing HVER\n"); case MISCREG_HINTP: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); + if (hintp) + tc->getCpuPtr()->post_interrupt(IT_HINTP,0); + else + tc->getCpuPtr()->clear_interrupt(IT_HINTP,0); + break; case MISCREG_HTBA: // clear lower 7 bits on writes. - setReg(miscReg, val & ULL(~0x7FFF)); + setRegNoEffect(miscReg, val & ULL(~0x7FFF)); break; case MISCREG_QUEUE_CPU_MONDO_HEAD: case MISCREG_QUEUE_CPU_MONDO_TAIL: + setRegNoEffect(miscReg, val); + if (cpu_mondo_head != cpu_mondo_tail) + tc->getCpuPtr()->post_interrupt(IT_CPU_MONDO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_CPU_MONDO,0); + break; case MISCREG_QUEUE_DEV_MONDO_HEAD: case MISCREG_QUEUE_DEV_MONDO_TAIL: + setRegNoEffect(miscReg, val); + if (dev_mondo_head != dev_mondo_tail) + tc->getCpuPtr()->post_interrupt(IT_DEV_MONDO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_DEV_MONDO,0); + break; case MISCREG_QUEUE_RES_ERROR_HEAD: case MISCREG_QUEUE_RES_ERROR_TAIL: + setRegNoEffect(miscReg, val); + if (res_error_head != res_error_tail) + tc->getCpuPtr()->post_interrupt(IT_RES_ERROR,0); + else + tc->getCpuPtr()->clear_interrupt(IT_RES_ERROR,0); + break; case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: - setReg(miscReg, val); - //do something to post mondo interrupt + setRegNoEffect(miscReg, val); + // This one doesn't have an interrupt to report to the guest OS break; case MISCREG_HSTICK_CMPR: if (hSTickCompare == NULL) hSTickCompare = new HSTickCompareEvent(this, tc); - setReg(miscReg, val); + setRegNoEffect(miscReg, val); if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) hSTickCompare->deschedule(); time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); - if (!(hstick_cmpr & ~mask(63)) && time > 0) + if (!(hstick_cmpr & ~mask(63)) && time > 0) { + if (hSTickCompare->scheduled()) + hSTickCompare->deschedule(); hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1)); + } DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); break; case MISCREG_HPSTATE: // T1000 spec says impl. dependent val must always be 1 - setReg(miscReg, val | HPSTATE::id); + setRegNoEffect(miscReg, val | HPSTATE::id); +#if FULL_SYSTEM + if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) + tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); +#endif break; case MISCREG_HTSTATE: + setRegNoEffect(miscReg, val); + break; + case MISCREG_STRAND_STS_REG: - setReg(miscReg, val); + if (bits(val,2,2)) + panic("No support for setting spec_en bit\n"); + setRegNoEffect(miscReg, bits(val,0,0)); + if (!bits(val,0,0)) { + DPRINTF(Quiesce, "Cpu executed quiescing instruction\n"); + // Time to go to sleep + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); + } break; default: @@ -134,8 +209,10 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, } MiscReg -MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) +MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) { + uint64_t temp; + switch (miscReg) { /* Privileged registers. */ case MISCREG_QUEUE_CPU_MONDO_HEAD: @@ -153,15 +230,52 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_HPSTATE: case MISCREG_HINTP: case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: case MISCREG_HSTICK_CMPR: - return readReg(miscReg) ; + return readRegNoEffect(miscReg) ; case MISCREG_HTBA: - return readReg(miscReg) & ULL(~0x7FFF); + return readRegNoEffect(miscReg) & ULL(~0x7FFF); case MISCREG_HVER: - return NWindows | MaxTL << 8 | MaxGL << 16; + // XXX set to match Legion + return ULL(0x3e) << 48 | + ULL(0x23) << 32 | + ULL(0x20) << 24 | + //MaxGL << 16 | XXX For some reason legion doesn't set GL + MaxTL << 8 | + (NWindows -1) << 0; + case MISCREG_STRAND_STS_REG: + System *sys; + int x; + sys = tc->getSystemPtr(); + + temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); + // Check that the CPU array is fully populated (by calling getNumCPus()) + assert(sys->getNumCPUs() > tc->readCpuId()); + + temp |= tc->readCpuId() << STS::shft_id; + + for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) { + switch (sys->threadContexts[x]->status()) { + case ThreadContext::Active: + temp |= STS::st_run << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Suspended: + // should this be idle? + temp |= STS::st_idle << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Halted: + temp |= STS::st_halt << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + default: + panic("What state are we in?!\n"); + } // switch + } // for + + return temp; default: panic("Invalid read to FS misc register\n"); } @@ -194,12 +308,11 @@ MiscRegFile::processSTickCompare(ThreadContext *tc) tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "stick compare missed interrupt cycle"); - if (ticks == 0) { + if (ticks == 0 || tc->status() == ThreadContext::Suspended) { DPRINTF(Timer, "STick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); - if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) { - tc->getCpuPtr()->post_interrupt(soft_interrupt); - setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); + if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) { + setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); } } else sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); @@ -212,19 +325,22 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) // we're actually at the correct cycle or we need to wait a little while // more int ticks; + if ( tc->status() == ThreadContext::Halted || + tc->status() == ThreadContext::Unallocated) + return; + ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "hstick compare missed interrupt cycle"); - if (ticks == 0) { + if (ticks == 0 || tc->status() == ThreadContext::Suspended) { DPRINTF(Timer, "HSTick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); - if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { - setRegWithEffect(MISCREG_HINTP, 1, tc); - tc->getCpuPtr()->post_interrupt(hstick_match); + if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { + setReg(MISCREG_HINTP, 1, tc); } // Need to do something to cause interrupt to happen here !!! @todo } else - sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); + hSTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); } diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 3c8bdcd01..1458231f2 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -44,24 +44,8 @@ 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 = (MachInst) inst; - //The I bit, bit 13, is used to figure out where the ASI - //should come from. Use that in the ExtMachInst. This is - //slightly redundant, but it removes the need to put a condition - //into all the execute functions - if(inst & (1 << 13)) - emi |= (static_cast<ExtMachInst>(xc->readMiscReg(MISCREG_ASI)) - << (sizeof(MachInst) * 8)); - else - emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) - << (sizeof(MachInst) * 8)); - return emi; + return !(tc->readMiscRegNoEffect(MISCREG_PSTATE & (1 << 2)) || + tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2))); } inline bool isCallerSaveIntegerRegister(unsigned int reg) { @@ -112,7 +96,20 @@ namespace SparcISA inline void initCPU(ThreadContext *tc, int cpuId) { static Fault por = new PowerOnReset(); - por->invoke(tc); + if (cpuId == 0) + por->invoke(tc); + + } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { +#if FULL_SYSTEM + // Other CPUs will get activated by IPIs + if (cpuId == 0) + tc->activate(0); +#else + tc->activate(0); +#endif } } // namespace SparcISA diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index 429126b70..9a93950d2 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -25,14 +25,14 @@ * (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 - * Ali Saidi + * Authors: Ali Saidi */ #include <string> #include "arch/sparc/vtophys.hh" +#include "arch/sparc/tlb.hh" +#include "base/compiler.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" @@ -42,37 +42,83 @@ using namespace std; namespace SparcISA { - PageTableEntry kernel_pte_lookup(FunctionalPort *mem, - Addr ptbr, VAddr vaddr) - { - PageTableEntry pte(4); - return pte; - } - Addr vtophys(Addr vaddr) { - return vaddr; + // In SPARC it's almost always impossible to turn a VA->PA w/o a context + // The only times we can kinda do it are if we have a SegKPM mapping + // and can find the real address in the tlb or we have a physical + // adddress already (beacuse we are looking at the hypervisor) + // Either case is rare, so we'll just panic. + + panic("vtophys() without context on SPARC largly worthless\n"); + M5_DUMMY_RETURN } Addr vtophys(ThreadContext *tc, Addr addr) { - return addr; - } + // Here we have many options and are really implementing something like + // a fill handler to find the address since there isn't a multilevel + // table for us to walk around. + // + // 1. We are currently hyperpriv, return the address unmodified + // 2. The mmu is off return(ra->pa) + // 3. We are currently priv, use ctx0* tsbs to find the page + // 4. We are not priv, use ctxN0* tsbs to find the page + // For all accesses we check the tlbs first since it's possible that + // long standing pages (e.g. locked kernel mappings) won't be in the tsb + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + bool hpriv = bits(tlbdata,0,0); + //bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool data_real = !bits(tlbdata,5,5); + bool inst_real = !bits(tlbdata,4,4); + bool ctx_zero = bits(tlbdata,18,16) > 0; + int part_id = bits(tlbdata,15,8); + int pri_context = bits(tlbdata,47,32); + //int sec_context = bits(tlbdata,63,48); - void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) - { - } + FunctionalPort *mem = tc->getPhysPort(); + ITB* itb = tc->getITBPtr(); + DTB* dtb = tc->getDTBPtr(); + TlbEntry* tbe; + PageTableEntry pte; + Addr tsbs[4]; + Addr va_tag; + TteTag ttetag; - void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) - { - } + if (hpriv) + return addr; - void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) - { - } + if (addr_mask) + addr = addr & VAddrAMask; - void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) - { + tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false); + if (tbe) goto foundtbe; + + tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false); + if (tbe) goto foundtbe; + + // We didn't find it in the tlbs, so lets look at the TSBs + dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); + va_tag = bits(addr, 63, 22); + for (int x = 0; x < 4; x++) { + ttetag = betoh(mem->read<uint64_t>(tsbs[x])); + if (ttetag.valid() && ttetag.va() == va_tag) { + pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)), + PageTableEntry::sun4v); // I think it's sun4v at least! + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr, + pte.paddrMask() | addr & pte.sizeMask()); + goto foundpte; + } + } + panic("couldn't translate %#x\n", addr); + +foundtbe: + pte = tbe->pte; + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, + pte.paddrMask() | addr & pte.sizeMask()); +foundpte: + return pte.paddrMask() | addr & pte.sizeMask(); } } diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh index 66679a565..f55967b53 100644 --- a/src/arch/sparc/vtophys.hh +++ b/src/arch/sparc/vtophys.hh @@ -46,11 +46,6 @@ kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, SparcISA::VAddr vaddr); Addr vtophys(Addr vaddr); Addr vtophys(ThreadContext *tc, Addr vaddr); -void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len); -void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len); -void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); -void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); - }; #endif // __ARCH_SPARC_VTOPHYS_H__ |