MIPS: Many style fixes.
White space, commented out code, some other minor fixes.
This commit is contained in:
parent
dc0a017ed0
commit
7548082d3b
28 changed files with 1017 additions and 1494 deletions
|
@ -28,20 +28,8 @@
|
||||||
* Authors: Jaidev Patwardhan
|
* Authors: Jaidev Patwardhan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/vtophys.hh"
|
|
||||||
#include "arch/mips/bare_iron/system.hh"
|
#include "arch/mips/bare_iron/system.hh"
|
||||||
#include "arch/mips/system.hh"
|
|
||||||
#include "cpu/thread_context.hh"
|
|
||||||
#include "cpu/base.hh"
|
|
||||||
#include "dev/platform.hh"
|
|
||||||
#include "mem/physical.hh"
|
|
||||||
#include "mem/port.hh"
|
|
||||||
#include "params/BareIronMipsSystem.hh"
|
#include "params/BareIronMipsSystem.hh"
|
||||||
#include "sim/byteswap.hh"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace MipsISA;
|
|
||||||
|
|
||||||
|
|
||||||
BareIronMipsSystem::BareIronMipsSystem(Params *p)
|
BareIronMipsSystem::BareIronMipsSystem(Params *p)
|
||||||
: MipsSystem(p)
|
: MipsSystem(p)
|
||||||
|
|
|
@ -31,11 +31,6 @@
|
||||||
#ifndef __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
|
#ifndef __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
|
||||||
#define __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
|
#define __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
|
||||||
|
|
||||||
class ThreadContext;
|
|
||||||
|
|
||||||
class BreakPCEvent;
|
|
||||||
class IdleStartEvent;
|
|
||||||
|
|
||||||
#include "arch/mips/system.hh"
|
#include "arch/mips/system.hh"
|
||||||
#include "params/BareIronMipsSystem.hh"
|
#include "params/BareIronMipsSystem.hh"
|
||||||
|
|
||||||
|
@ -46,15 +41,9 @@ class IdleStartEvent;
|
||||||
*/
|
*/
|
||||||
class BareIronMipsSystem : public MipsSystem
|
class BareIronMipsSystem : public MipsSystem
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int CommandLineSize = 256;
|
static const int CommandLineSize = 256;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
public:
|
|
||||||
BareIronMipsSystem(Params *p);
|
BareIronMipsSystem(Params *p);
|
||||||
~BareIronMipsSystem();
|
~BareIronMipsSystem();
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,7 +85,6 @@ FaultName ThreadFault::_name = "Thread Fault";
|
||||||
FaultVect ThreadFault::_vect = 0x00F1;
|
FaultVect ThreadFault::_vect = 0x00F1;
|
||||||
FaultStat ThreadFault::_count;
|
FaultStat ThreadFault::_count;
|
||||||
|
|
||||||
|
|
||||||
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
|
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
|
||||||
FaultVect ArithmeticFault::_vect = 0x180;
|
FaultVect ArithmeticFault::_vect = 0x180;
|
||||||
FaultStat ArithmeticFault::_count;
|
FaultStat ArithmeticFault::_count;
|
||||||
|
@ -106,7 +105,6 @@ FaultName BreakpointFault::_name = "Breakpoint";
|
||||||
FaultVect BreakpointFault::_vect = 0x0180;
|
FaultVect BreakpointFault::_vect = 0x0180;
|
||||||
FaultStat BreakpointFault::_count;
|
FaultStat BreakpointFault::_count;
|
||||||
|
|
||||||
|
|
||||||
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
|
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
|
||||||
FaultVect ItbInvalidFault::_vect = 0x0180;
|
FaultVect ItbInvalidFault::_vect = 0x0180;
|
||||||
FaultStat ItbInvalidFault::_count;
|
FaultStat ItbInvalidFault::_count;
|
||||||
|
@ -168,344 +166,366 @@ FaultVect DspStateDisabledFault::_vect = 0x001a;
|
||||||
FaultStat DspStateDisabledFault::_count;
|
FaultStat DspStateDisabledFault::_count;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
|
void
|
||||||
|
MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
|
||||||
{
|
{
|
||||||
tc->setPC(HandlerBase);
|
tc->setPC(HandlerBase);
|
||||||
tc->setNextPC(HandlerBase+sizeof(MachInst));
|
tc->setNextPC(HandlerBase + sizeof(MachInst));
|
||||||
tc->setNextNPC(HandlerBase+2*sizeof(MachInst));
|
tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode)
|
void
|
||||||
|
MipsFault::setExceptionState(ThreadContext *tc, uint8_t ExcCode)
|
||||||
{
|
{
|
||||||
// modify SRS Ctl - Save CSS, put ESS into CSS
|
// modify SRS Ctl - Save CSS, put ESS into CSS
|
||||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||||
if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1)
|
if (bits(stat, Status_EXL) != 1 && bits(stat, Status_BEV) != 1) {
|
||||||
{
|
// SRS Ctl is modified only if Status_EXL and Status_BEV are not set
|
||||||
// SRS Ctl is modified only if Status_EXL and Status_BEV are not set
|
MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
|
||||||
MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
|
uint8_t CSS, ESS;
|
||||||
uint8_t CSS,ESS;
|
CSS = bits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO);
|
||||||
CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO);
|
ESS = bits(srs, SRSCtl_ESS_HI, SRSCtl_ESS_LO);
|
||||||
ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO);
|
// Move CSS to PSS
|
||||||
// Move CSS to PSS
|
replaceBits(srs, SRSCtl_PSS_HI, SRSCtl_PSS_LO, CSS);
|
||||||
replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS);
|
// Move ESS to CSS
|
||||||
// Move ESS to CSS
|
replaceBits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO, ESS);
|
||||||
replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS);
|
tc->setMiscRegNoEffect(MipsISA::SRSCtl, srs);
|
||||||
tc->setMiscRegNoEffect(MipsISA::SRSCtl,srs);
|
|
||||||
//tc->setShadowSet(ESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set EXL bit (don't care if it is already set!)
|
// set EXL bit (don't care if it is already set!)
|
||||||
replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1);
|
replaceBits(stat, Status_EXL_HI, Status_EXL_LO, 1);
|
||||||
tc->setMiscRegNoEffect(MipsISA::Status,stat);
|
tc->setMiscRegNoEffect(MipsISA::Status, stat);
|
||||||
|
|
||||||
// write EPC
|
// write EPC
|
||||||
// warn("Set EPC to %x\n",tc->readPC());
|
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK
|
||||||
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK
|
// Check to see if the exception occurred in the branch delay slot
|
||||||
// Check to see if the exception occurred in the branch delay slot
|
DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
|
||||||
DPRINTF(MipsPRA,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC());
|
tc->readPC(), tc->readNextPC(), tc->readNextNPC());
|
||||||
int C_BD=0;
|
int C_BD = 0;
|
||||||
if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){
|
if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
|
||||||
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC()-sizeof(MachInst));
|
tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC() - sizeof(MachInst));
|
||||||
// In the branch delay slot? set CAUSE_31
|
// In the branch delay slot? set CAUSE_31
|
||||||
C_BD = 1;
|
C_BD = 1;
|
||||||
} else {
|
} else {
|
||||||
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC());
|
tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC());
|
||||||
// In the branch delay slot? reset CAUSE_31
|
// In the branch delay slot? reset CAUSE_31
|
||||||
C_BD = 0;
|
C_BD = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Cause_EXCCODE field
|
|
||||||
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
|
||||||
replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode);
|
|
||||||
replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD);
|
|
||||||
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
|
||||||
|
|
||||||
|
// Set Cause_EXCCODE field
|
||||||
|
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
||||||
|
replaceBits(cause, Cause_EXCCODE_HI, Cause_EXCCODE_LO, ExcCode);
|
||||||
|
replaceBits(cause, Cause_BD_HI, Cause_BD_LO,C_BD);
|
||||||
|
replaceBits(cause, Cause_CE_HI, Cause_CE_LO,0);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArithmeticFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
ArithmeticFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
setExceptionState(tc,0xC);
|
setExceptionState(tc, 0xC);
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
|
||||||
// Here, the handler is dependent on BEV, which is not modified by setExceptionState()
|
|
||||||
if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
|
|
||||||
}else{
|
|
||||||
HandlerBase = 0xBFC00200;
|
|
||||||
}
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreAddressErrorFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
setExceptionState(tc,0x5);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrapFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
// warn("%s encountered.\n", name());
|
|
||||||
setExceptionState(tc,0xD);
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakpointFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
setExceptionState(tc,0x9);
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DtbInvalidFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
// warn("%s encountered.\n", name());
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
|
||||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
|
||||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
|
||||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
|
|
||||||
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
|
||||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
|
|
||||||
setExceptionState(tc,0x3);
|
|
||||||
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddressErrorFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
setExceptionState(tc,0x4);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItbInvalidFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
setExceptionState(tc,0x2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
|
||||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
|
||||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
|
||||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
|
|
||||||
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
|
||||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
|
|
||||||
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItbRefillFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered (%x).\n", name(),BadVAddr);
|
|
||||||
Addr HandlerBase;
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
|
||||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
|
||||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
|
||||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
|
|
||||||
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
|
||||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
|
|
||||||
|
|
||||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
|
||||||
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
|
||||||
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
}else{
|
|
||||||
HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
|
|
||||||
}
|
|
||||||
|
|
||||||
setExceptionState(tc,0x2);
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DtbRefillFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
// Set new PC
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
Addr HandlerBase;
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
|
||||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
|
||||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
|
||||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
|
|
||||||
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
|
||||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
|
|
||||||
|
|
||||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
|
||||||
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
|
||||||
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
|
||||||
}else{
|
|
||||||
HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setExceptionState(tc,0x3);
|
|
||||||
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TLBModifiedFault::invoke(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
|
|
||||||
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
|
||||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
|
||||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
|
||||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
|
|
||||||
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
|
||||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
|
|
||||||
|
|
||||||
// Set new PC
|
// Set new PC
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||||
setExceptionState(tc,0x1);
|
// Here, the handler is dependent on BEV, which is not modified by
|
||||||
setHandlerPC(HandlerBase,tc);
|
// setExceptionState()
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
if (bits(stat, Status_BEV) == 0 ) {
|
||||||
|
// See MIPS ARM Vol 3, Revision 2, Page 38
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
} else {
|
||||||
|
HandlerBase = 0xBFC00200;
|
||||||
|
}
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemCallFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
StoreAddressErrorFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
setExceptionState(tc,0x8);
|
setExceptionState(tc, 0x5);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
|
||||||
// Set new PC
|
// Set new PC
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
// Offset 0x180 - General Exception Vector
|
||||||
setHandlerPC(HandlerBase,tc);
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
setHandlerPC(HandlerBase, tc);
|
||||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TrapFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
setExceptionState(tc, 0xD);
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BreakpointFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
setExceptionState(tc, 0x9);
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DtbInvalidFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
||||||
|
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
|
||||||
|
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
|
||||||
|
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
|
||||||
|
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
||||||
|
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
|
||||||
|
setExceptionState(tc, 0x3);
|
||||||
|
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase,tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddressErrorFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
setExceptionState(tc, 0x4);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ItbInvalidFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
setExceptionState(tc, 0x2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
||||||
|
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
|
||||||
|
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
|
||||||
|
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
|
||||||
|
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
||||||
|
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
|
||||||
|
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase,tc);
|
||||||
|
DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",
|
||||||
|
HandlerBase, tc->readMiscReg(MipsISA::EPC));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ItbRefillFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), BadVAddr);
|
||||||
|
Addr HandlerBase;
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
||||||
|
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
|
||||||
|
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
|
||||||
|
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
|
||||||
|
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
||||||
|
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
|
||||||
|
|
||||||
|
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||||
|
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
||||||
|
// See MIPS ARM Vol 3, Revision 2, Page 38
|
||||||
|
if (bits(stat, Status_EXL) == 1) {
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
} else {
|
||||||
|
// Offset 0x000
|
||||||
|
HandlerBase = tc->readMiscReg(MipsISA::EBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
setExceptionState(tc, 0x2);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DtbRefillFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
// Set new PC
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
Addr HandlerBase;
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
||||||
|
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
|
||||||
|
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
|
||||||
|
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
|
||||||
|
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
||||||
|
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
|
||||||
|
|
||||||
|
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||||
|
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
||||||
|
// See MIPS ARM Vol 3, Revision 2, Page 38
|
||||||
|
if(bits(stat, Status_EXL) == 1) {
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
} else {
|
||||||
|
// Offset 0x000
|
||||||
|
HandlerBase = tc->readMiscReg(MipsISA::EBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
setExceptionState(tc, 0x3);
|
||||||
|
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLBModifiedFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
|
||||||
|
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
|
||||||
|
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
|
||||||
|
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
|
||||||
|
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
|
||||||
|
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
|
||||||
|
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setExceptionState(tc, 0x1);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
SystemCallFault::invoke(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
setExceptionState(tc, 0x8);
|
||||||
|
|
||||||
|
// Set new PC
|
||||||
|
Addr HandlerBase;
|
||||||
|
// Offset 0x180 - General Exception Vector
|
||||||
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InterruptFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
setExceptionState(tc,0x0A);
|
setExceptionState(tc, 0x0A);
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
|
|
||||||
|
uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause), Cause_IV);
|
||||||
|
if (IV) {
|
||||||
|
// Offset 200 for release 2
|
||||||
|
HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
||||||
|
} else {
|
||||||
|
//Ofset at 180 for release 1
|
||||||
|
HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause),Cause_IV);
|
setHandlerPC(HandlerBase, tc);
|
||||||
if (IV)// Offset 200 for release 2
|
|
||||||
HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
|
||||||
else//Ofset at 180 for release 1
|
|
||||||
HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
|
||||||
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
void ResetFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
ResetFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
/* All reset activity must be invoked from here */
|
/* All reset activity must be invoked from here */
|
||||||
tc->setPC(vect());
|
tc->setPC(vect());
|
||||||
tc->setNextPC(vect()+sizeof(MachInst));
|
tc->setNextPC(vect() + sizeof(MachInst));
|
||||||
tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst));
|
tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
|
||||||
DPRINTF(MipsPRA,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC());
|
DPRINTF(MipsPRA, "(%x) - ResetFault::invoke : PC set to %x",
|
||||||
|
(unsigned)tc, (unsigned)tc->readPC());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set Coprocessor 1 (Floating Point) To Usable
|
// Set Coprocessor 1 (Floating Point) To Usable
|
||||||
tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
|
tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReservedInstructionFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
ReservedInstructionFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
setExceptionState(tc,0x0A);
|
setExceptionState(tc, 0x0A);
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
// Offset 0x180 - General Exception Vector
|
||||||
setHandlerPC(HandlerBase,tc);
|
HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
#else
|
#else
|
||||||
panic("%s encountered.\n", name());
|
panic("%s encountered.\n", name());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
ThreadFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
panic("%s encountered.\n", name());
|
panic("%s encountered.\n", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DspStateDisabledFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
DspStateDisabledFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
panic("%s encountered.\n", name());
|
panic("%s encountered.\n", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoprocessorUnusableFault::invoke(ThreadContext *tc)
|
void
|
||||||
|
CoprocessorUnusableFault::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
setExceptionState(tc,0xb);
|
setExceptionState(tc, 0xb);
|
||||||
/* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */
|
// The ID of the coprocessor causing the exception is stored in
|
||||||
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
// CoprocessorUnusableFault::coProcID
|
||||||
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID);
|
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
||||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
replaceBits(cause, Cause_CE_HI, Cause_CE_LO, coProcID);
|
||||||
|
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
|
||||||
|
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
// Offset 0x180 - General Exception Vector
|
||||||
setHandlerPC(HandlerBase,tc);
|
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||||
|
setHandlerPC(HandlerBase, tc);
|
||||||
|
|
||||||
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(MipsISA::Status),tc->readMiscReg(MipsISA::Cause));
|
|
||||||
#else
|
#else
|
||||||
warn("%s (CP%d) encountered.\n", name(), coProcID);
|
warn("%s (CP%d) encountered.\n", name(), coProcID);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,10 +36,9 @@
|
||||||
|
|
||||||
#include "sim/faults.hh"
|
#include "sim/faults.hh"
|
||||||
|
|
||||||
// The design of the "name" and "vect" functions is in sim/faults.hh
|
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef const Addr FaultVect;
|
typedef const Addr FaultVect;
|
||||||
|
|
||||||
class MipsFault : public FaultBase
|
class MipsFault : public FaultBase
|
||||||
|
@ -54,9 +53,9 @@ class MipsFault : public FaultBase
|
||||||
Addr EntryHi_VPN2X;
|
Addr EntryHi_VPN2X;
|
||||||
Addr Context_BadVPN2;
|
Addr Context_BadVPN2;
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc) {};
|
void invoke(ThreadContext * tc) {};
|
||||||
void setExceptionState(ThreadContext *,uint8_t);
|
void setExceptionState(ThreadContext *, uint8_t);
|
||||||
void setHandlerPC(Addr,ThreadContext *);
|
void setHandlerPC(Addr, ThreadContext *);
|
||||||
#endif
|
#endif
|
||||||
virtual FaultVect vect() = 0;
|
virtual FaultVect vect() = 0;
|
||||||
virtual FaultStat & countStat() = 0;
|
virtual FaultStat & countStat() = 0;
|
||||||
|
@ -116,6 +115,7 @@ class AddressErrorFault : public MipsFault
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StoreAddressErrorFault : public MipsFault
|
class StoreAddressErrorFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -129,8 +129,8 @@ class StoreAddressErrorFault : public MipsFault
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnimplementedOpcodeFault : public MipsFault
|
class UnimplementedOpcodeFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -157,6 +157,7 @@ class TLBRefillIFetchFault : public MipsFault
|
||||||
FaultStat & countStat() {return _count;}
|
FaultStat & countStat() {return _count;}
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TLBInvalidIFetchFault : public MipsFault
|
class TLBInvalidIFetchFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -259,6 +260,7 @@ class ResetFault : public MipsFault
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SystemCallFault : public MipsFault
|
class SystemCallFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -284,6 +286,7 @@ class SoftResetFault : public MipsFault
|
||||||
FaultStat & countStat() {return _count;}
|
FaultStat & countStat() {return _count;}
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugSingleStep : public MipsFault
|
class DebugSingleStep : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -296,6 +299,7 @@ class DebugSingleStep : public MipsFault
|
||||||
FaultStat & countStat() {return _count;}
|
FaultStat & countStat() {return _count;}
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugInterrupt : public MipsFault
|
class DebugInterrupt : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -350,7 +354,6 @@ class ThreadFault : public MipsFault
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ArithmeticFault : public MipsFault
|
class ArithmeticFault : public MipsFault
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -384,8 +387,6 @@ class InterruptFault : public MipsFault
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//void invoke(ThreadContext * tc);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TrapFault : public MipsFault
|
class TrapFault : public MipsFault
|
||||||
|
@ -432,6 +433,7 @@ class ItbRefillFault : public MipsFault
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class DtbRefillFault : public MipsFault
|
class DtbRefillFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -475,8 +477,8 @@ class ItbInvalidFault : public MipsFault
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TLBModifiedFault : public MipsFault
|
class TLBModifiedFault : public MipsFault
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -490,7 +492,6 @@ class TLBModifiedFault : public MipsFault
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DtbInvalidFault : public MipsFault
|
class DtbInvalidFault : public MipsFault
|
||||||
|
@ -506,7 +507,6 @@ class DtbInvalidFault : public MipsFault
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FloatEnableFault : public MipsFault
|
class FloatEnableFault : public MipsFault
|
||||||
|
|
|
@ -40,9 +40,4 @@ void
|
||||||
IdleStartEvent::process(ThreadContext *tc)
|
IdleStartEvent::process(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
fatal("Idle Start Event Not Defined for MIPS ISA ");
|
fatal("Idle Start Event Not Defined for MIPS ISA ");
|
||||||
|
|
||||||
// if (tc->getKernelStats())
|
|
||||||
// tc->getKernelStats()->setIdleProcess(
|
|
||||||
// tc->readMiscRegNoEffect(MipsISA::IPR_PALtemp23), tc);
|
|
||||||
//remove();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,201 +38,102 @@
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
static inline uint8_t getCauseIP_(ThreadContext *tc) {
|
|
||||||
|
static inline uint8_t
|
||||||
|
getCauseIP(ThreadContext *tc) {
|
||||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
||||||
uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
|
return bits(cause, Cause_IP7, Cause_IP0);
|
||||||
return IP_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
|
static inline void
|
||||||
|
setCauseIP_(ThreadContext *tc, uint8_t val) {
|
||||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
||||||
replaceBits(cause,Cause_IP7,Cause_IP0,val);
|
replaceBits(cause, Cause_IP7, Cause_IP0, val);
|
||||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void
|
||||||
void Interrupts::post(int int_num, int index)
|
Interrupts::post(int int_num, ThreadContext* tc)
|
||||||
{
|
|
||||||
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
|
|
||||||
|
|
||||||
//index should not be used
|
|
||||||
assert(index == 0);
|
|
||||||
|
|
||||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
intstatus |= 1 << int_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interrupts::clear(int int_num, int index)
|
|
||||||
{
|
|
||||||
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
|
|
||||||
|
|
||||||
//index should not be used
|
|
||||||
assert(index == 0);
|
|
||||||
|
|
||||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
intstatus &= ~(1 << int_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interrupts::clearAll()
|
|
||||||
{
|
|
||||||
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
|
||||||
intstatus = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Fault Interrupts::getInterrupt(ThreadContext * tc)
|
|
||||||
{
|
|
||||||
DPRINTF(Interrupt, "Interrupts getInterrupt\n");
|
|
||||||
// If a timer interrupt has occured, check to see if a
|
|
||||||
// mtc0 to Compare register caused this interrupt to
|
|
||||||
// be cleared. If this is the case, clear intstatus
|
|
||||||
// bit for timer interrupt
|
|
||||||
if (oncputimerintr){
|
|
||||||
DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
|
|
||||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
|
||||||
uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
|
|
||||||
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
|
|
||||||
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
|
|
||||||
//mtc0 to compare must have cleared bit in IP
|
|
||||||
if ( ((1 << IPTI) & IP_) == 0){
|
|
||||||
clear(IPTI, 0);
|
|
||||||
oncputimerintr=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if there is a on cpu timer interrupt (i.e. Compare == Count)
|
|
||||||
//update intstatus before proceeding to interrupt
|
|
||||||
if (onCpuTimerInterrupt(tc)){
|
|
||||||
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
|
|
||||||
//determine timer interrupt IP #
|
|
||||||
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
|
|
||||||
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
|
|
||||||
//set intstatus to correspond
|
|
||||||
post(IPTI, 0);
|
|
||||||
oncputimerintr=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if there are any outstanding interrupts
|
|
||||||
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
|
|
||||||
if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
|
|
||||||
bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
|
|
||||||
bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
|
|
||||||
{
|
|
||||||
// Software interrupts & hardware interrupts are handled in software.
|
|
||||||
// So if any interrupt that isn't masked is detected, jump to interrupt
|
|
||||||
// handler
|
|
||||||
uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
|
|
||||||
IM = bits(status,Status_IM7,Status_IM0);
|
|
||||||
IP = intstatus;
|
|
||||||
//IM and IP are already correctly aligned
|
|
||||||
if (IM & IP){
|
|
||||||
DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
|
|
||||||
IM, IP);
|
|
||||||
return new InterruptFault;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NoFault;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interrupts::updateIntrInfo(ThreadContext *tc) const
|
|
||||||
{
|
|
||||||
//Merge Interrupts.intstatus with mips MipISA::Status
|
|
||||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
|
||||||
replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
|
|
||||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
|
||||||
{
|
|
||||||
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
|
|
||||||
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
|
|
||||||
if (compare == count)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
void Interrupts::post(int int_num, ThreadContext* tc)
|
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
|
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
|
||||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||||
panic("int_num out of bounds\n");
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
uint8_t intstatus= getCauseIP_(tc);
|
uint8_t intstatus = getCauseIP(tc);
|
||||||
intstatus |= 1 << int_num;
|
intstatus |= 1 << int_num;
|
||||||
setCauseIP_(tc, intstatus);
|
setCauseIP(tc, intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interrupts::post(int int_num, int index)
|
void
|
||||||
|
Interrupts::post(int int_num, int index)
|
||||||
{
|
{
|
||||||
fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
|
fatal("Must use Thread Context when posting MIPS Interrupts in M5");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interrupts::clear(int int_num, ThreadContext* tc)
|
void
|
||||||
|
Interrupts::clear(int int_num, ThreadContext* tc)
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
|
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
|
||||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||||
panic("int_num out of bounds\n");
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
uint8_t intstatus = getCauseIP_(tc);
|
uint8_t intstatus = getCauseIP(tc);
|
||||||
intstatus &= ~(1 << int_num);
|
intstatus &= ~(1 << int_num);
|
||||||
setCauseIP_(tc, intstatus);
|
setCauseIP(tc, intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interrupts::clear(int int_num, int index)
|
void
|
||||||
|
Interrupts::clear(int int_num, int index)
|
||||||
{
|
{
|
||||||
fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
|
fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interrupts::clearAll(ThreadContext *tc)
|
void
|
||||||
|
Interrupts::clearAll(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
||||||
uint8_t intstatus = 0;
|
uint8_t intstatus = 0;
|
||||||
setCauseIP_(tc, intstatus);
|
setCauseIP(tc, intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interrupts::clearAll()
|
void
|
||||||
|
Interrupts::clearAll()
|
||||||
{
|
{
|
||||||
fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
|
fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Fault Interrupts::getInterrupt(ThreadContext * tc)
|
Fault
|
||||||
|
Interrupts::getInterrupt(ThreadContext * tc)
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupts getInterrupt\n");
|
DPRINTF(Interrupt, "Interrupts getInterrupt\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Check if there are any outstanding interrupts
|
//Check if there are any outstanding interrupts
|
||||||
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
|
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
|
||||||
if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
|
// Interrupts must be enabled, error level must be 0 or interrupts
|
||||||
bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
|
// inhibited, and exception level must be 0 or interrupts inhibited
|
||||||
bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
|
if (bits(status, Status_IE_LO) == 1 &&
|
||||||
{
|
bits(status, Status_ERL_HI, Status_ERL_LO) == 0 &&
|
||||||
|
bits(status, Status_EXL_HI, Status_EXL_LO) == 0) {
|
||||||
// Software interrupts & hardware interrupts are handled in software.
|
// Software interrupts & hardware interrupts are handled in software.
|
||||||
// So if any interrupt that isn't masked is detected, jump to interrupt
|
// So if any interrupt that isn't masked is detected, jump to interrupt
|
||||||
// handler
|
// handler
|
||||||
uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
|
uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0);
|
||||||
IM = bits(status,Status_IM7,Status_IM0);
|
uint8_t InterruptPending = getCauseIP(tc);
|
||||||
IP = getCauseIP_(tc);
|
// InterruptMask and InterruptPending are already correctly aligned
|
||||||
//IM and IP are already correctly aligned
|
if (InterruptMask && InterruptPending){
|
||||||
if (IM & IP){
|
|
||||||
DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
|
DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
|
||||||
IM, IP);
|
InterruptMask, InterruptPending);
|
||||||
return new InterruptFault;
|
return new InterruptFault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
|
|
||||||
}
|
}
|
||||||
bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
|
||||||
|
bool
|
||||||
|
Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
||||||
{
|
{
|
||||||
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
|
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
|
||||||
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
|
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
|
||||||
|
@ -240,34 +141,32 @@ bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void Interrupts::updateIntrInfo(ThreadContext *tc) const
|
|
||||||
|
void
|
||||||
|
Interrupts::updateIntrInfo(ThreadContext *tc) const
|
||||||
{
|
{
|
||||||
//Nothing needs to be done.
|
//Nothing needs to be done.
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interrupts::interruptsPending(ThreadContext *tc) const
|
bool
|
||||||
|
Interrupts::interruptsPending(ThreadContext *tc) const
|
||||||
{
|
{
|
||||||
//if there is a on cpu timer interrupt (i.e. Compare == Count)
|
//if there is a on cpu timer interrupt (i.e. Compare == Count)
|
||||||
//update CauseIP before proceeding to interrupt
|
//update CauseIP before proceeding to interrupt
|
||||||
if (onCpuTimerInterrupt(tc)){
|
if (onCpuTimerInterrupt(tc)) {
|
||||||
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
|
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n");
|
||||||
//determine timer interrupt IP #
|
//determine timer interrupt IP #
|
||||||
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
|
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
|
||||||
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
|
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
|
||||||
//set intstatus to correspond
|
//set intstatus to correspond
|
||||||
//post(IPTI, tc);
|
//post(IPTI, tc);
|
||||||
uint8_t intstatus= getCauseIP_(tc);
|
uint8_t intstatus = getCauseIP(tc);
|
||||||
intstatus |= 1 << IPTI;
|
intstatus |= 1 << IPTI;
|
||||||
setCauseIP_(tc, intstatus);
|
setCauseIP(tc, intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (getCauseIP_(tc) != 0);
|
return (getCauseIP(tc) != 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,97 +31,27 @@
|
||||||
#ifndef __ARCH_MIPS_INTERRUPT_HH__
|
#ifndef __ARCH_MIPS_INTERRUPT_HH__
|
||||||
#define __ARCH_MIPS_INTERRUPT_HH__
|
#define __ARCH_MIPS_INTERRUPT_HH__
|
||||||
|
|
||||||
|
|
||||||
#include "arch/mips/faults.hh"
|
#include "arch/mips/faults.hh"
|
||||||
#include "base/compiler.hh"
|
#include "base/compiler.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
class Interrupts
|
class Interrupts
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
protected:
|
|
||||||
uint8_t intstatus;
|
|
||||||
bool oncputimerintr;
|
|
||||||
public:
|
|
||||||
Interrupts()
|
|
||||||
{
|
|
||||||
intstatus = 0;
|
|
||||||
newInfoSet = false;
|
|
||||||
oncputimerintr = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
// post(int int_num, int index) is responsible
|
|
||||||
// for posting an interrupt. It sets a bit
|
|
||||||
// in intstatus corresponding to Cause IP*. The
|
|
||||||
// MIPS register Cause is updated by updateIntrInfo
|
|
||||||
// which is called by checkInterrupts
|
|
||||||
//
|
|
||||||
void post(int int_num, int index);
|
|
||||||
// clear(int int_num, int index) is responsible
|
|
||||||
// for clearing an interrupt. It clear a bit
|
|
||||||
// in intstatus corresponding to Cause IP*. The
|
|
||||||
// MIPS register Cause is updated by updateIntrInfo
|
|
||||||
// which is called by checkInterrupts
|
|
||||||
//
|
|
||||||
void clear(int int_num, int index);
|
|
||||||
// clearAll() is responsible
|
|
||||||
// for clearing all interrupts. It clears all bits
|
|
||||||
// in intstatus corresponding to Cause IP*. The
|
|
||||||
// MIPS register Cause is updated by updateIntrInfo
|
|
||||||
// which is called by checkInterrupts
|
|
||||||
//
|
|
||||||
void clearAll();
|
|
||||||
|
|
||||||
// getInterrupt(ThreadContext * tc) checks if an interrupt
|
|
||||||
// should be returned. It ands the interrupt mask and
|
|
||||||
// and interrupt pending bits to see if one exists. It
|
|
||||||
// also makes sure interrupts are enabled (IE) and
|
|
||||||
// that ERL and ERX are not set
|
|
||||||
//
|
|
||||||
Fault getInterrupt(ThreadContext * tc);
|
|
||||||
|
|
||||||
// updateIntrInfo(ThreadContext *tc) const syncs the
|
|
||||||
// MIPS cause register with the instatus variable. instatus
|
|
||||||
// is essentially a copy of the MIPS cause[IP7:IP0]
|
|
||||||
//
|
|
||||||
void updateIntrInfo(ThreadContext *tc) const;
|
|
||||||
void updateIntrInfoCpuTimerIntr(ThreadContext *tc) const;
|
|
||||||
bool onCpuTimerInterrupt(ThreadContext *tc) const;
|
|
||||||
|
|
||||||
bool checkInterrupts(ThreadContext *tc) const {
|
|
||||||
//return (intstatus != 0) && !(tc->readPC() & 0x3);
|
|
||||||
if (oncputimerintr == false){
|
|
||||||
updateIntrInfo(tc);
|
|
||||||
return ((intstatus != 0) || onCpuTimerInterrupt(tc));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//uint8_t intstatus;
|
|
||||||
//bool oncputimerintr;
|
|
||||||
public:
|
public:
|
||||||
Interrupts()
|
Interrupts()
|
||||||
{
|
{
|
||||||
//intstatus = 0;
|
|
||||||
newInfoSet = false;
|
newInfoSet = false;
|
||||||
//oncputimerintr = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// post(int int_num, int index) is responsible
|
// post(int int_num, int index) is responsible
|
||||||
// for posting an interrupt. It sets a bit
|
// for posting an interrupt. It sets a bit
|
||||||
// in intstatus corresponding to Cause IP*. The
|
// in intstatus corresponding to Cause IP*. The
|
||||||
// MIPS register Cause is updated by updateIntrInfo
|
// MIPS register Cause is updated by updateIntrInfo
|
||||||
// which is called by checkInterrupts
|
// which is called by checkInterrupts
|
||||||
//
|
//
|
||||||
void post(int int_num, ThreadContext* tc);
|
void post(int int_num, ThreadContext *tc);
|
||||||
void post(int int_num, int index);
|
void post(int int_num, int index);
|
||||||
|
|
||||||
// clear(int int_num, int index) is responsible
|
// clear(int int_num, int index) is responsible
|
||||||
|
@ -139,7 +69,7 @@ class Interrupts
|
||||||
// MIPS register Cause is updated by updateIntrInfo
|
// MIPS register Cause is updated by updateIntrInfo
|
||||||
// which is called by checkInterrupts
|
// which is called by checkInterrupts
|
||||||
//
|
//
|
||||||
void clearAll(ThreadContext* tc);
|
void clearAll(ThreadContext *tc);
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
|
||||||
// getInterrupt(ThreadContext * tc) checks if an interrupt
|
// getInterrupt(ThreadContext * tc) checks if an interrupt
|
||||||
|
@ -148,7 +78,7 @@ class Interrupts
|
||||||
// also makes sure interrupts are enabled (IE) and
|
// also makes sure interrupts are enabled (IE) and
|
||||||
// that ERL and ERX are not set
|
// that ERL and ERX are not set
|
||||||
//
|
//
|
||||||
Fault getInterrupt(ThreadContext * tc);
|
Fault getInterrupt(ThreadContext *tc);
|
||||||
|
|
||||||
// updateIntrInfo(ThreadContext *tc) const syncs the
|
// updateIntrInfo(ThreadContext *tc) const syncs the
|
||||||
// MIPS cause register with the instatus variable. instatus
|
// MIPS cause register with the instatus variable. instatus
|
||||||
|
@ -165,27 +95,22 @@ class Interrupts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void serialize(std::ostream &os)
|
void
|
||||||
|
serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
fatal("Serialization of Interrupts Unimplemented for MIPS");
|
fatal("Serialization of Interrupts Unimplemented for MIPS");
|
||||||
//SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
|
|
||||||
//SERIALIZE_SCALAR(intstatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
void
|
||||||
|
unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
{
|
{
|
||||||
fatal("Unserialization of Interrupts Unimplemented for MIPS");
|
fatal("Unserialization of Interrupts Unimplemented for MIPS");
|
||||||
//UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
|
|
||||||
//UNSERIALIZE_SCALAR(intstatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool newInfoSet;
|
bool newInfoSet;
|
||||||
int newIpl;
|
int newIpl;
|
||||||
int newSummary;
|
int newSummary;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,12 +447,7 @@ ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid)
|
||||||
misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg],
|
misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg],
|
||||||
miscRegFile[misc_reg][reg_sel]);
|
miscRegFile[misc_reg][reg_sel]);
|
||||||
|
|
||||||
|
return miscRegFile[misc_reg][reg_sel];
|
||||||
switch (misc_reg)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return miscRegFile[misc_reg][reg_sel];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -486,7 +481,6 @@ ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid)
|
||||||
// (1) Some CP0 Registers have fields that cannot
|
// (1) Some CP0 Registers have fields that cannot
|
||||||
// be overwritten. Make sure to handle those particular registers
|
// be overwritten. Make sure to handle those particular registers
|
||||||
// with care!
|
// with care!
|
||||||
//template <class TC>
|
|
||||||
void
|
void
|
||||||
ISA::setMiscReg(int reg_idx, const MiscReg &val,
|
ISA::setMiscReg(int reg_idx, const MiscReg &val,
|
||||||
ThreadContext *tc, ThreadID tid)
|
ThreadContext *tc, ThreadID tid)
|
||||||
|
@ -515,21 +509,21 @@ ISA::setMiscReg(int reg_idx, const MiscReg &val,
|
||||||
MiscReg
|
MiscReg
|
||||||
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
|
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
|
||||||
{
|
{
|
||||||
MiscReg retVal = val;
|
MiscReg retVal = val;
|
||||||
|
|
||||||
// Mask off read-only regions
|
// Mask off read-only regions
|
||||||
retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
|
retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
|
||||||
MiscReg curVal = miscRegFile[misc_reg][reg_sel];
|
MiscReg curVal = miscRegFile[misc_reg][reg_sel];
|
||||||
// Mask off current alue with inverse mask (clear writeable bits)
|
// Mask off current alue with inverse mask (clear writeable bits)
|
||||||
curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
|
curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
|
||||||
retVal |= curVal; // Combine the two
|
retVal |= curVal; // Combine the two
|
||||||
DPRINTF(MipsPRA,
|
DPRINTF(MipsPRA,
|
||||||
"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
|
"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
|
||||||
"current val: %lx, written val: %x\n",
|
"current val: %lx, written val: %x\n",
|
||||||
miscRegFile_WriteMask[misc_reg][reg_sel],
|
miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||||
~miscRegFile_WriteMask[misc_reg][reg_sel],
|
~miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||||
val, miscRegFile[misc_reg][reg_sel], retVal);
|
val, miscRegFile[misc_reg][reg_sel], retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -586,8 +580,6 @@ ISA::CP0Event::process()
|
||||||
cp0->updateCPU();
|
cp0->updateCPU();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cp0EventRemoveList.push(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
|
@ -41,133 +41,129 @@
|
||||||
|
|
||||||
namespace LittleEndianGuest {};
|
namespace LittleEndianGuest {};
|
||||||
|
|
||||||
#define TARGET_MIPS
|
|
||||||
|
|
||||||
class StaticInstPtr;
|
class StaticInstPtr;
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
using namespace LittleEndianGuest;
|
|
||||||
|
|
||||||
StaticInstPtr decodeInst(ExtMachInst);
|
using namespace LittleEndianGuest;
|
||||||
|
|
||||||
// MIPS DOES have a delay slot
|
StaticInstPtr decodeInst(ExtMachInst);
|
||||||
#define ISA_HAS_DELAY_SLOT 1
|
|
||||||
|
|
||||||
const Addr PageShift = 13;
|
// MIPS DOES have a delay slot
|
||||||
const Addr PageBytes = ULL(1) << PageShift;
|
#define ISA_HAS_DELAY_SLOT 1
|
||||||
const Addr Page_Mask = ~(PageBytes - 1);
|
|
||||||
const Addr PageOffset = PageBytes - 1;
|
const Addr PageShift = 13;
|
||||||
|
const Addr PageBytes = ULL(1) << PageShift;
|
||||||
|
const Addr Page_Mask = ~(PageBytes - 1);
|
||||||
|
const Addr PageOffset = PageBytes - 1;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Translation stuff
|
// Translation stuff
|
||||||
//
|
//
|
||||||
|
|
||||||
const Addr PteShift = 3;
|
const Addr PteShift = 3;
|
||||||
const Addr NPtePageShift = PageShift - PteShift;
|
const Addr NPtePageShift = PageShift - PteShift;
|
||||||
const Addr NPtePage = ULL(1) << NPtePageShift;
|
const Addr NPtePage = ULL(1) << NPtePageShift;
|
||||||
const Addr PteMask = NPtePage - 1;
|
const Addr PteMask = NPtePage - 1;
|
||||||
|
|
||||||
//// All 'Mapped' segments go through the TLB
|
//// All 'Mapped' segments go through the TLB
|
||||||
//// All other segments are translated by dropping the MSB, to give
|
//// All other segments are translated by dropping the MSB, to give
|
||||||
//// the corresponding physical address
|
//// the corresponding physical address
|
||||||
// User Segment - Mapped
|
// User Segment - Mapped
|
||||||
const Addr USegBase = ULL(0x0);
|
const Addr USegBase = ULL(0x0);
|
||||||
const Addr USegEnd = ULL(0x7FFFFFFF);
|
const Addr USegEnd = ULL(0x7FFFFFFF);
|
||||||
|
|
||||||
// Kernel Segment 0 - Unmapped
|
// Kernel Segment 0 - Unmapped
|
||||||
const Addr KSeg0End = ULL(0x9FFFFFFF);
|
const Addr KSeg0End = ULL(0x9FFFFFFF);
|
||||||
const Addr KSeg0Base = ULL(0x80000000);
|
const Addr KSeg0Base = ULL(0x80000000);
|
||||||
const Addr KSeg0Mask = ULL(0x1FFFFFFF);
|
const Addr KSeg0Mask = ULL(0x1FFFFFFF);
|
||||||
|
|
||||||
// Kernel Segment 1 - Unmapped, Uncached
|
// Kernel Segment 1 - Unmapped, Uncached
|
||||||
const Addr KSeg1End = ULL(0xBFFFFFFF);
|
const Addr KSeg1End = ULL(0xBFFFFFFF);
|
||||||
const Addr KSeg1Base = ULL(0xA0000000);
|
const Addr KSeg1Base = ULL(0xA0000000);
|
||||||
const Addr KSeg1Mask = ULL(0x1FFFFFFF);
|
const Addr KSeg1Mask = ULL(0x1FFFFFFF);
|
||||||
|
|
||||||
// Kernel/Supervisor Segment - Mapped
|
// Kernel/Supervisor Segment - Mapped
|
||||||
const Addr KSSegEnd = ULL(0xDFFFFFFF);
|
const Addr KSSegEnd = ULL(0xDFFFFFFF);
|
||||||
const Addr KSSegBase = ULL(0xC0000000);
|
const Addr KSSegBase = ULL(0xC0000000);
|
||||||
|
|
||||||
// Kernel Segment 3 - Mapped
|
// Kernel Segment 3 - Mapped
|
||||||
const Addr KSeg3End = ULL(0xFFFFFFFF);
|
const Addr KSeg3End = ULL(0xFFFFFFFF);
|
||||||
const Addr KSeg3Base = ULL(0xE0000000);
|
const Addr KSeg3Base = ULL(0xE0000000);
|
||||||
|
|
||||||
|
|
||||||
// For loading... XXX This maybe could be USegEnd?? --ali
|
// For loading... XXX This maybe could be USegEnd?? --ali
|
||||||
const Addr LoadAddrMask = ULL(0xffffffffff);
|
const Addr LoadAddrMask = ULL(0xffffffffff);
|
||||||
|
|
||||||
inline Addr Phys2K0Seg(Addr addr)
|
inline Addr Phys2K0Seg(Addr addr)
|
||||||
{
|
{
|
||||||
// if (addr & PAddrUncachedBit43) {
|
return addr | KSeg0Base;
|
||||||
// addr &= PAddrUncachedMask;
|
}
|
||||||
// addr |= PAddrUncachedBit40;
|
|
||||||
// }
|
|
||||||
return addr | KSeg0Base;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const unsigned VABits = 32;
|
const unsigned VABits = 32;
|
||||||
const unsigned PABits = 32; // Is this correct?
|
const unsigned PABits = 32; // Is this correct?
|
||||||
const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
|
const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
|
||||||
const Addr VAddrUnImplMask = ~VAddrImplMask;
|
const Addr VAddrUnImplMask = ~VAddrImplMask;
|
||||||
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
|
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
|
||||||
inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
|
inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
|
||||||
inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
|
inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
|
||||||
|
|
||||||
const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
|
const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Interrupt levels
|
// Interrupt levels
|
||||||
//
|
//
|
||||||
enum InterruptLevels
|
enum InterruptLevels
|
||||||
{
|
{
|
||||||
INTLEVEL_SOFTWARE_MIN = 4,
|
INTLEVEL_SOFTWARE_MIN = 4,
|
||||||
INTLEVEL_SOFTWARE_MAX = 19,
|
INTLEVEL_SOFTWARE_MAX = 19,
|
||||||
|
|
||||||
INTLEVEL_EXTERNAL_MIN = 20,
|
INTLEVEL_EXTERNAL_MIN = 20,
|
||||||
INTLEVEL_EXTERNAL_MAX = 34,
|
INTLEVEL_EXTERNAL_MAX = 34,
|
||||||
|
|
||||||
INTLEVEL_IRQ0 = 20,
|
INTLEVEL_IRQ0 = 20,
|
||||||
INTLEVEL_IRQ1 = 21,
|
INTLEVEL_IRQ1 = 21,
|
||||||
INTINDEX_ETHERNET = 0,
|
INTINDEX_ETHERNET = 0,
|
||||||
INTINDEX_SCSI = 1,
|
INTINDEX_SCSI = 1,
|
||||||
INTLEVEL_IRQ2 = 22,
|
INTLEVEL_IRQ2 = 22,
|
||||||
INTLEVEL_IRQ3 = 23,
|
INTLEVEL_IRQ3 = 23,
|
||||||
|
|
||||||
INTLEVEL_SERIAL = 33,
|
INTLEVEL_SERIAL = 33,
|
||||||
|
|
||||||
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
// MIPS modes
|
// MIPS modes
|
||||||
enum mode_type
|
enum mode_type
|
||||||
{
|
{
|
||||||
mode_kernel = 0, // kernel
|
mode_kernel = 0, // kernel
|
||||||
mode_supervisor = 1, // supervisor
|
mode_supervisor = 1, // supervisor
|
||||||
mode_user = 2, // user mode
|
mode_user = 2, // user mode
|
||||||
mode_debug = 3, // debug mode
|
mode_debug = 3, // debug mode
|
||||||
mode_number // number of modes
|
mode_number // number of modes
|
||||||
};
|
};
|
||||||
|
|
||||||
// return a no-op instruction... used for instruction fetch faults
|
// return a no-op instruction... used for instruction fetch faults
|
||||||
const ExtMachInst NoopMachInst = 0x00000000;
|
const ExtMachInst NoopMachInst = 0x00000000;
|
||||||
|
|
||||||
const int LogVMPageSize = 13; // 8K bytes
|
const int LogVMPageSize = 13; // 8K bytes
|
||||||
const int VMPageSize = (1 << LogVMPageSize);
|
const int VMPageSize = (1 << LogVMPageSize);
|
||||||
|
|
||||||
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
|
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
|
||||||
|
|
||||||
const int MachineBytes = 4;
|
const int MachineBytes = 4;
|
||||||
const int WordBytes = 4;
|
const int WordBytes = 4;
|
||||||
const int HalfwordBytes = 2;
|
const int HalfwordBytes = 2;
|
||||||
const int ByteBytes = 1;
|
const int ByteBytes = 1;
|
||||||
|
|
||||||
|
const int ANNOTE_NONE = 0;
|
||||||
|
const uint32_t ITOUCH_ANNOTE = 0xffffffff;
|
||||||
|
|
||||||
const int ANNOTE_NONE = 0;
|
|
||||||
const uint32_t ITOUCH_ANNOTE = 0xffffffff;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_MIPS_ISA_TRAITS_HH__
|
#endif // __ARCH_MIPS_ISA_TRAITS_HH__
|
||||||
|
|
|
@ -32,11 +32,6 @@
|
||||||
#ifndef __ARCH_MIPS_KERNEL_STATS_HH__
|
#ifndef __ARCH_MIPS_KERNEL_STATS_HH__
|
||||||
#define __ARCH_MIPS_KERNEL_STATS_HH__
|
#define __ARCH_MIPS_KERNEL_STATS_HH__
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <stack>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "kern/kernel_stats.hh"
|
#include "kern/kernel_stats.hh"
|
||||||
|
|
||||||
namespace MipsISA {
|
namespace MipsISA {
|
||||||
|
|
|
@ -69,7 +69,3 @@ OpenFlagTransTable MipsLinux::openFlagTable[] = {
|
||||||
|
|
||||||
const int MipsLinux::NUM_OPEN_FLAGS =
|
const int MipsLinux::NUM_OPEN_FLAGS =
|
||||||
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
|
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -68,13 +68,13 @@ class MipsLinux : public Linux
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// For getsysinfo().
|
/// For getsysinfo().
|
||||||
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
|
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
|
||||||
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
|
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
|
||||||
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
|
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
|
||||||
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
|
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
|
||||||
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
|
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
|
||||||
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
|
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
|
||||||
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
|
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -74,15 +74,15 @@ sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||||
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case 45:
|
||||||
case 45: { // GSI_IEEE_FP_CONTROL
|
{
|
||||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
// GSI_IEEE_FP_CONTROL
|
||||||
// I don't think this exactly matches the HW FPCR
|
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||||
*fpcr = 0;
|
// I don't think this exactly matches the HW FPCR
|
||||||
fpcr.copyOut(tc->getMemPort());
|
*fpcr = 0;
|
||||||
return 0;
|
fpcr.copyOut(tc->getMemPort());
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
cerr << "sys_getsysinfo: unknown op " << op << endl;
|
cerr << "sys_getsysinfo: unknown op " << op << endl;
|
||||||
abort();
|
abort();
|
||||||
|
@ -102,15 +102,16 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
|
||||||
case 14: { // SSI_IEEE_FP_CONTROL
|
case 14:
|
||||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
{
|
||||||
// I don't think this exactly matches the HW FPCR
|
// SSI_IEEE_FP_CONTROL
|
||||||
fpcr.copyIn(tc->getMemPort());
|
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||||
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
|
// I don't think this exactly matches the HW FPCR
|
||||||
|
fpcr.copyIn(tc->getMemPort());
|
||||||
|
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
|
||||||
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
|
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cerr << "sys_setsysinfo: unknown op " << op << endl;
|
cerr << "sys_setsysinfo: unknown op " << op << endl;
|
||||||
abort();
|
abort();
|
||||||
|
@ -196,8 +197,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||||
/* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
|
/* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
|
||||||
/* 73 */ SyscallDesc("sigpending", unimplementedFunc),
|
/* 73 */ SyscallDesc("sigpending", unimplementedFunc),
|
||||||
/* 74 */ SyscallDesc("sethostname", ignoreFunc),
|
/* 74 */ SyscallDesc("sethostname", ignoreFunc),
|
||||||
/* 75 */ SyscallDesc("setrlimit", unimplementedFunc/*setrlimitFunc<MipsLinux>*/),
|
/* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
|
||||||
/* 76 */ SyscallDesc("getrlimit", unimplementedFunc/*getrlimitFunc<MipsLinux>*/),
|
/* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
|
||||||
/* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>),
|
/* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>),
|
||||||
/* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
|
/* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
|
||||||
/* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
|
/* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
|
||||||
|
@ -241,7 +242,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||||
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
|
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
|
||||||
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
|
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
|
||||||
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
|
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
|
||||||
/* 120 */ SyscallDesc("clone", unimplementedFunc/*cloneFunc<MipsLinux>*/),
|
/* 120 */ SyscallDesc("clone", unimplementedFunc),
|
||||||
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
|
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
|
||||||
/* 122 */ SyscallDesc("uname", unameFunc),
|
/* 122 */ SyscallDesc("uname", unameFunc),
|
||||||
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
|
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
|
||||||
|
@ -315,12 +316,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||||
/* 191 */ SyscallDesc("getresgid", unimplementedFunc),
|
/* 191 */ SyscallDesc("getresgid", unimplementedFunc),
|
||||||
/* 192 */ SyscallDesc("prctl", unimplementedFunc),
|
/* 192 */ SyscallDesc("prctl", unimplementedFunc),
|
||||||
/* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
|
/* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
|
||||||
/* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc/*rt_sigactionFunc<MipsLinux>*/),
|
/* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc),
|
||||||
/* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc/*rt_sigprocmaskFunc<MipsLinux>*/),
|
/* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
|
||||||
/* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
|
/* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
|
||||||
/* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
|
/* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
|
||||||
/* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
|
/* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
|
||||||
/* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc/*rt_sigsuspendFunc<MipsLinux>*/),
|
/* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
|
||||||
/* 200 */ SyscallDesc("pread64", unimplementedFunc),
|
/* 200 */ SyscallDesc("pread64", unimplementedFunc),
|
||||||
/* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
|
/* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
|
||||||
/* 202 */ SyscallDesc("chown", unimplementedFunc),
|
/* 202 */ SyscallDesc("chown", unimplementedFunc),
|
||||||
|
@ -406,7 +407,6 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||||
/* 282 */ SyscallDesc("keyctl", unimplementedFunc)
|
/* 282 */ SyscallDesc("keyctl", unimplementedFunc)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
|
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
|
||||||
ObjectFile *objFile)
|
ObjectFile *objFile)
|
||||||
: MipsLiveProcess(params, objFile),
|
: MipsLiveProcess(params, objFile),
|
||||||
|
|
|
@ -88,7 +88,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
|
||||||
virtPort.write(addr, (uint64_t)(Clock::Frequency /
|
virtPort.write(addr, (uint64_t)(Clock::Frequency /
|
||||||
p->boot_cpu_frequency));
|
p->boot_cpu_frequency));
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EV5 only supports 127 ASNs so we are going to tell the kernel that the
|
* EV5 only supports 127 ASNs so we are going to tell the kernel that the
|
||||||
* paritiuclar EV6 we have only supports 127 asns.
|
* paritiuclar EV6 we have only supports 127 asns.
|
||||||
|
@ -105,12 +104,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
|
||||||
if (!kernelPanicEvent)
|
if (!kernelPanicEvent)
|
||||||
panic("could not find kernel symbol \'panic\'");
|
panic("could not find kernel symbol \'panic\'");
|
||||||
|
|
||||||
#if 0
|
|
||||||
kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
|
|
||||||
if (!kernelDieEvent)
|
|
||||||
panic("could not find kernel symbol \'die_if_kernel\'");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,17 +45,18 @@
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class XC>
|
template <class XC>
|
||||||
inline void
|
inline void
|
||||||
handleLockedRead(XC *xc, Request *req)
|
handleLockedRead(XC *xc, Request *req)
|
||||||
{
|
{
|
||||||
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf);
|
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf);
|
||||||
xc->setMiscRegNoEffect(LLFlag, true);
|
xc->setMiscRegNoEffect(LLFlag, true);
|
||||||
DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n",
|
DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link"
|
||||||
|
" Address set to %x.\n",
|
||||||
req->threadId(), req->getPaddr() & ~0xf);
|
req->threadId(), req->getPaddr() & ~0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class XC>
|
template <class XC>
|
||||||
inline bool
|
inline bool
|
||||||
handleLockedWrite(XC *xc, Request *req)
|
handleLockedWrite(XC *xc, Request *req)
|
||||||
|
@ -89,14 +90,17 @@ handleLockedWrite(XC *xc, Request *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stCondFailures == 5000) {
|
if (stCondFailures == 5000) {
|
||||||
panic("Max (5000) Store Conditional Fails Reached. Check Code For Deadlock.\n");
|
panic("Max (5000) Store Conditional Fails Reached. "
|
||||||
|
"Check Code For Deadlock.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lock_flag){
|
if (!lock_flag){
|
||||||
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n",
|
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, "
|
||||||
|
"Store Conditional Failed.\n",
|
||||||
req->threadId());
|
req->threadId());
|
||||||
} else if ((req->getPaddr() & ~0xf) != lock_addr) {
|
} else if ((req->getPaddr() & ~0xf) != lock_addr) {
|
||||||
DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n",
|
DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, "
|
||||||
|
"Store Conditional Failed.\n",
|
||||||
req->threadId());
|
req->threadId());
|
||||||
}
|
}
|
||||||
// store conditional failed already, so don't issue it to mem
|
// store conditional failed already, so don't issue it to mem
|
||||||
|
@ -107,7 +111,6 @@ handleLockedWrite(XC *xc, Request *req)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace MipsISA
|
} // namespace MipsISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,20 +29,9 @@
|
||||||
* Steve Reinhardt
|
* Steve Reinhardt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/mips/faults.hh"
|
|
||||||
#include "arch/mips/isa_traits.hh"
|
|
||||||
#include "arch/mips/tlb.hh"
|
|
||||||
//#include "base/kgdb.h"
|
|
||||||
#include "base/remote_gdb.hh"
|
|
||||||
#include "base/stats/events.hh"
|
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "kern/kernel_stats.hh"
|
|
||||||
#include "sim/debug.hh"
|
|
||||||
#include "sim/sim_exit.hh"
|
|
||||||
#include "arch/mips/mips_core_specific.hh"
|
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
|
||||||
|
@ -52,61 +41,11 @@
|
||||||
//
|
//
|
||||||
void
|
void
|
||||||
MipsISA::initCPU(ThreadContext *tc, int cpuId)
|
MipsISA::initCPU(ThreadContext *tc, int cpuId)
|
||||||
{
|
{}
|
||||||
|
|
||||||
// MipsFault *reset = new ResetFault;
|
|
||||||
// tc->setPC(reset->vect());
|
|
||||||
// tc->setNextPC(tc->readPC() + sizeof(MachInst));
|
|
||||||
|
|
||||||
// delete reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class CPU>
|
template <class CPU>
|
||||||
void
|
void
|
||||||
MipsISA::processInterrupts(CPU *cpu)
|
MipsISA::processInterrupts(CPU *cpu)
|
||||||
{
|
{}
|
||||||
//Check if there are any outstanding interrupts
|
|
||||||
//Handle the interrupts
|
|
||||||
/* int ipl = 0;
|
|
||||||
int summary = 0;
|
|
||||||
|
|
||||||
cpu->checkInterrupts = false;
|
|
||||||
|
|
||||||
if (cpu->readMiscReg(IPR_ASTRR))
|
|
||||||
panic("asynchronous traps not implemented\n");
|
|
||||||
|
|
||||||
if (cpu->readMiscReg(IPR_SIRR)) {
|
|
||||||
for (int i = INTLEVEL_SOFTWARE_MIN;
|
|
||||||
i < INTLEVEL_SOFTWARE_MAX; i++) {
|
|
||||||
if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
|
|
||||||
// See table 4-19 of the 21164 hardware reference
|
|
||||||
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
|
|
||||||
summary |= (ULL(1) << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t interrupts = cpu->intr_status();
|
|
||||||
|
|
||||||
if (interrupts) {
|
|
||||||
for (int i = INTLEVEL_EXTERNAL_MIN;
|
|
||||||
i < INTLEVEL_EXTERNAL_MAX; i++) {
|
|
||||||
if (interrupts & (ULL(1) << i)) {
|
|
||||||
// See table 4-19 of the 21164 hardware reference
|
|
||||||
ipl = i;
|
|
||||||
summary |= (ULL(1) << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
|
|
||||||
cpu->setMiscReg(IPR_ISR, summary);
|
|
||||||
cpu->setMiscReg(IPR_INTID, ipl);
|
|
||||||
cpu->trap(new InterruptFault);
|
|
||||||
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
|
||||||
cpu->readMiscReg(IPR_IPLR), ipl, summary);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FULL_SYSTEM || BARE_IRON
|
#endif // FULL_SYSTEM || BARE_IRON
|
||||||
|
|
|
@ -44,6 +44,7 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
inline Tick
|
inline Tick
|
||||||
handleIprRead(ThreadContext *xc, Packet *pkt)
|
handleIprRead(ThreadContext *xc, Packet *pkt)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,6 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
|
||||||
panic("No implementation for handleIprWrite in MIPS\n");
|
panic("No implementation for handleIprWrite in MIPS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace MipsISA
|
} // namespace MipsISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
template <class TC>
|
template <class TC>
|
||||||
inline unsigned
|
inline unsigned
|
||||||
getVirtProcNum(TC *tc)
|
getVirtProcNum(TC *tc)
|
||||||
|
@ -76,11 +75,13 @@ haltThread(TC *tc)
|
||||||
tc->halt();
|
tc->halt();
|
||||||
|
|
||||||
// Save last known PC in TCRestart
|
// Save last known PC in TCRestart
|
||||||
// @TODO: Needs to check if this is a branch and if so, take previous instruction
|
// @TODO: Needs to check if this is a branch and if so,
|
||||||
|
// take previous instruction
|
||||||
tc->setMiscReg(TCRestart, tc->readNextPC());
|
tc->setMiscReg(TCRestart, tc->readNextPC());
|
||||||
|
|
||||||
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
|
||||||
tc->readPC(), tc->readNextPC());
|
curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||||
|
tc->readPC(), tc->readNextPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,14 +94,14 @@ restoreThread(TC *tc)
|
||||||
IntReg pc = tc->readMiscRegNoEffect(TCRestart);
|
IntReg pc = tc->readMiscRegNoEffect(TCRestart);
|
||||||
|
|
||||||
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
|
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
|
||||||
// tc->setPCEvent(pc, pc + 4, pc + 8);
|
|
||||||
tc->setPC(pc);
|
tc->setPC(pc);
|
||||||
tc->setNextPC(pc + 4);
|
tc->setNextPC(pc + 4);
|
||||||
tc->setNextNPC(pc + 8);
|
tc->setNextNPC(pc + 8);
|
||||||
tc->activate(0);
|
tc->activate(0);
|
||||||
|
|
||||||
warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
warn("%i: Restoring thread %i in %s @ PC %x",
|
||||||
tc->readPC());
|
curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||||
|
tc->readPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,42 +37,42 @@
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void
|
||||||
void
|
PTE::serialize(std::ostream &os)
|
||||||
PTE::serialize(std::ostream &os)
|
{
|
||||||
{
|
SERIALIZE_SCALAR(Mask);
|
||||||
SERIALIZE_SCALAR(Mask);
|
SERIALIZE_SCALAR(VPN);
|
||||||
SERIALIZE_SCALAR(VPN);
|
SERIALIZE_SCALAR(asid);
|
||||||
SERIALIZE_SCALAR(asid);
|
SERIALIZE_SCALAR(G);
|
||||||
SERIALIZE_SCALAR(G);
|
SERIALIZE_SCALAR(PFN0);
|
||||||
SERIALIZE_SCALAR(PFN0);
|
SERIALIZE_SCALAR(D0);
|
||||||
SERIALIZE_SCALAR(D0);
|
SERIALIZE_SCALAR(V0);
|
||||||
SERIALIZE_SCALAR(V0);
|
SERIALIZE_SCALAR(C0);
|
||||||
SERIALIZE_SCALAR(C0);
|
SERIALIZE_SCALAR(PFN1);
|
||||||
SERIALIZE_SCALAR(PFN1);
|
SERIALIZE_SCALAR(D1);
|
||||||
SERIALIZE_SCALAR(D1);
|
SERIALIZE_SCALAR(V1);
|
||||||
SERIALIZE_SCALAR(V1);
|
SERIALIZE_SCALAR(C1);
|
||||||
SERIALIZE_SCALAR(C1);
|
SERIALIZE_SCALAR(AddrShiftAmount);
|
||||||
SERIALIZE_SCALAR(AddrShiftAmount);
|
SERIALIZE_SCALAR(OffsetMask);
|
||||||
SERIALIZE_SCALAR(OffsetMask);
|
}
|
||||||
}
|
|
||||||
|
void
|
||||||
void
|
PTE::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
PTE::unserialize(Checkpoint *cp, const std::string §ion)
|
{
|
||||||
{
|
UNSERIALIZE_SCALAR(Mask);
|
||||||
UNSERIALIZE_SCALAR(Mask);
|
UNSERIALIZE_SCALAR(VPN);
|
||||||
UNSERIALIZE_SCALAR(VPN);
|
UNSERIALIZE_SCALAR(asid);
|
||||||
UNSERIALIZE_SCALAR(asid);
|
UNSERIALIZE_SCALAR(G);
|
||||||
UNSERIALIZE_SCALAR(G);
|
UNSERIALIZE_SCALAR(PFN0);
|
||||||
UNSERIALIZE_SCALAR(PFN0);
|
UNSERIALIZE_SCALAR(D0);
|
||||||
UNSERIALIZE_SCALAR(D0);
|
UNSERIALIZE_SCALAR(V0);
|
||||||
UNSERIALIZE_SCALAR(V0);
|
UNSERIALIZE_SCALAR(C0);
|
||||||
UNSERIALIZE_SCALAR(C0);
|
UNSERIALIZE_SCALAR(PFN1);
|
||||||
UNSERIALIZE_SCALAR(PFN1);
|
UNSERIALIZE_SCALAR(D1);
|
||||||
UNSERIALIZE_SCALAR(D1);
|
UNSERIALIZE_SCALAR(V1);
|
||||||
UNSERIALIZE_SCALAR(V1);
|
UNSERIALIZE_SCALAR(C1);
|
||||||
UNSERIALIZE_SCALAR(C1);
|
UNSERIALIZE_SCALAR(AddrShiftAmount);
|
||||||
UNSERIALIZE_SCALAR(AddrShiftAmount);
|
UNSERIALIZE_SCALAR(OffsetMask);
|
||||||
UNSERIALIZE_SCALAR(OffsetMask);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,59 +41,62 @@
|
||||||
|
|
||||||
namespace MipsISA {
|
namespace MipsISA {
|
||||||
|
|
||||||
struct VAddr
|
struct VAddr
|
||||||
{
|
{
|
||||||
static const int ImplBits = 43;
|
static const int ImplBits = 43;
|
||||||
static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
|
static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
|
||||||
static const Addr UnImplMask = ~ImplMask;
|
static const Addr UnImplMask = ~ImplMask;
|
||||||
|
|
||||||
VAddr(Addr a) : addr(a) {}
|
VAddr(Addr a) : addr(a) {}
|
||||||
Addr addr;
|
Addr addr;
|
||||||
operator Addr() const { return addr; }
|
operator Addr() const { return addr; }
|
||||||
const VAddr &operator=(Addr a) { addr = a; return *this; }
|
const VAddr &operator=(Addr a) { addr = a; return *this; }
|
||||||
|
|
||||||
Addr vpn() const { return (addr & ImplMask) >> PageShift; }
|
Addr vpn() const { return (addr & ImplMask) >> PageShift; }
|
||||||
Addr page() const { return addr & Page_Mask; }
|
Addr page() const { return addr & Page_Mask; }
|
||||||
Addr offset() const { return addr & PageOffset; }
|
Addr offset() const { return addr & PageOffset; }
|
||||||
|
|
||||||
Addr level3() const
|
Addr level3() const
|
||||||
{ return MipsISA::PteAddr(addr >> PageShift); }
|
{ return MipsISA::PteAddr(addr >> PageShift); }
|
||||||
Addr level2() const
|
Addr level2() const
|
||||||
{ return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
|
{ return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
|
||||||
Addr level1() const
|
Addr level1() const
|
||||||
{ return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
|
{ return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ITB/DTB page table entry
|
// ITB/DTB page table entry
|
||||||
struct PTE
|
struct PTE
|
||||||
{
|
{
|
||||||
Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask)
|
Addr Mask;
|
||||||
Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi)
|
Addr VPN;
|
||||||
uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi
|
uint8_t asid;
|
||||||
|
|
||||||
bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit
|
bool G;
|
||||||
|
|
||||||
/* Contents of Entry Lo0 */
|
/* Contents of Entry Lo0 */
|
||||||
Addr PFN0; // Physical Frame Number - Even
|
Addr PFN0; // Physical Frame Number - Even
|
||||||
bool D0; // Even entry Dirty Bit
|
bool D0; // Even entry Dirty Bit
|
||||||
bool V0; // Even entry Valid Bit
|
bool V0; // Even entry Valid Bit
|
||||||
uint8_t C0; // Cache Coherency Bits - Even
|
uint8_t C0; // Cache Coherency Bits - Even
|
||||||
|
|
||||||
/* Contents of Entry Lo1 */
|
/* Contents of Entry Lo1 */
|
||||||
Addr PFN1; // Physical Frame Number - Odd
|
Addr PFN1; // Physical Frame Number - Odd
|
||||||
bool D1; // Odd entry Dirty Bit
|
bool D1; // Odd entry Dirty Bit
|
||||||
bool V1; // Odd entry Valid Bit
|
bool V1; // Odd entry Valid Bit
|
||||||
uint8_t C1; // Cache Coherency Bits (3 bits)
|
uint8_t C1; // Cache Coherency Bits (3 bits)
|
||||||
|
|
||||||
/* The next few variables are put in as optimizations to reduce TLB lookup overheads */
|
/*
|
||||||
/* For a given Mask, what is the address shift amount, and what is the OffsetMask */
|
* The next few variables are put in as optimizations to reduce
|
||||||
int AddrShiftAmount;
|
* TLB lookup overheads. For a given Mask, what is the address shift
|
||||||
int OffsetMask;
|
* amount, and what is the OffsetMask
|
||||||
|
*/
|
||||||
|
int AddrShiftAmount;
|
||||||
|
int OffsetMask;
|
||||||
|
|
||||||
bool Valid() { return (V0 | V1);};
|
bool Valid() { return (V0 | V1); };
|
||||||
void serialize(std::ostream &os);
|
void serialize(std::ostream &os);
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif // __ARCH_MIPS_PAGETABLE_H__
|
#endif // __ARCH_MIPS_PAGETABLE_H__
|
||||||
|
|
|
@ -40,57 +40,66 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
class Predecoder
|
|
||||||
|
class Predecoder
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ThreadContext * tc;
|
||||||
|
//The extended machine instruction being generated
|
||||||
|
ExtMachInst emi;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Predecoder(ThreadContext * _tc) : tc(_tc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ThreadContext *getTC()
|
||||||
{
|
{
|
||||||
protected:
|
return tc;
|
||||||
ThreadContext * tc;
|
}
|
||||||
//The extended machine instruction being generated
|
|
||||||
ExtMachInst emi;
|
|
||||||
|
|
||||||
public:
|
void
|
||||||
Predecoder(ThreadContext * _tc) : tc(_tc)
|
setTC(ThreadContext *_tc)
|
||||||
{}
|
{
|
||||||
|
tc = _tc;
|
||||||
|
}
|
||||||
|
|
||||||
ThreadContext * getTC()
|
void
|
||||||
{
|
process()
|
||||||
return tc;
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTC(ThreadContext * _tc)
|
void
|
||||||
{
|
reset()
|
||||||
tc = _tc;
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void process()
|
//Use this to give data to the predecoder. This should be used
|
||||||
{
|
//when there is control flow.
|
||||||
}
|
void
|
||||||
|
moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
||||||
|
{
|
||||||
|
emi = inst;
|
||||||
|
}
|
||||||
|
|
||||||
void reset()
|
bool
|
||||||
{}
|
needMoreBytes()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//Use this to give data to the predecoder. This should be used
|
bool
|
||||||
//when there is control flow.
|
extMachInstReady()
|
||||||
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
{
|
||||||
{
|
return true;
|
||||||
emi = inst;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool needMoreBytes()
|
//This returns a constant reference to the ExtMachInst to avoid a copy
|
||||||
{
|
const ExtMachInst &
|
||||||
return true;
|
getExtMachInst()
|
||||||
}
|
{
|
||||||
|
return emi;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool extMachInstReady()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//This returns a constant reference to the ExtMachInst to avoid a copy
|
|
||||||
const ExtMachInst & getExtMachInst()
|
|
||||||
{
|
|
||||||
return emi;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_MIPS_PREDECODER_HH__
|
#endif // __ARCH_MIPS_PREDECODER_HH__
|
||||||
|
|
|
@ -42,35 +42,8 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace MipsISA;
|
using namespace MipsISA;
|
||||||
|
|
||||||
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
|
||||||
: tc(_tc)
|
{}
|
||||||
{
|
|
||||||
// Addr addr = 0;
|
|
||||||
|
|
||||||
VirtualPort *vp;
|
|
||||||
|
|
||||||
vp = tc->getVirtPort();
|
|
||||||
|
|
||||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
|
|
||||||
// panic("thread info not compiled into kernel\n");
|
|
||||||
// thread_info_size = vp->readGtoH<int32_t>(addr);
|
|
||||||
|
|
||||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
|
|
||||||
// panic("thread info not compiled into kernel\n");
|
|
||||||
// task_struct_size = vp->readGtoH<int32_t>(addr);
|
|
||||||
|
|
||||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
|
|
||||||
// panic("thread info not compiled into kernel\n");
|
|
||||||
// task_off = vp->readGtoH<int32_t>(addr);
|
|
||||||
|
|
||||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
|
|
||||||
// panic("thread info not compiled into kernel\n");
|
|
||||||
// pid_off = vp->readGtoH<int32_t>(addr);
|
|
||||||
|
|
||||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
|
|
||||||
// panic("thread info not compiled into kernel\n");
|
|
||||||
// name_off = vp->readGtoH<int32_t>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr
|
Addr
|
||||||
ProcessInfo::task(Addr ksp) const
|
ProcessInfo::task(Addr ksp) const
|
||||||
|
@ -140,84 +113,17 @@ void
|
||||||
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||||
{
|
{
|
||||||
tc = _tc;
|
tc = _tc;
|
||||||
/* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
|
|
||||||
bool usermode = 0;
|
bool usermode = 0;
|
||||||
//(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0;
|
|
||||||
|
|
||||||
// Addr pc = tc->readNextPC();
|
|
||||||
// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
|
||||||
// pc <= tc->getSystemPtr()->kernelEnd;
|
|
||||||
|
|
||||||
if (usermode) {
|
if (usermode) {
|
||||||
stack.push_back(user);
|
stack.push_back(user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!kernel) {
|
|
||||||
// stack.push_back(console);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
|
||||||
// Addr ksp = tc->readIntReg(MipsISA::StackPointerReg);
|
|
||||||
// Addr bottom = ksp & ~0x3fff;
|
|
||||||
// Addr addr;
|
|
||||||
|
|
||||||
// if (is_call) {
|
|
||||||
// if (!symtab->findNearestAddr(pc, addr))
|
|
||||||
// panic("could not find address %#x", pc);
|
|
||||||
|
|
||||||
// stack.push_back(addr);
|
|
||||||
// pc = tc->readPC();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Addr ra;
|
|
||||||
// int size;
|
|
||||||
|
|
||||||
// while (ksp > bottom) {
|
|
||||||
// if (!symtab->findNearestAddr(pc, addr))
|
|
||||||
// panic("could not find symbol for pc=%#x", pc);
|
|
||||||
// assert(pc >= addr && "symbol botch: callpc < func");
|
|
||||||
|
|
||||||
// stack.push_back(addr);
|
|
||||||
|
|
||||||
// if (isEntry(addr))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// if (decodePrologue(ksp, pc, addr, size, ra)) {
|
|
||||||
// if (!ra)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// if (size <= 0) {
|
|
||||||
// stack.push_back(unknown);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pc = ra;
|
|
||||||
// ksp += size;
|
|
||||||
// } else {
|
|
||||||
// stack.push_back(unknown);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
|
||||||
// pc <= tc->getSystemPtr()->kernelEnd;
|
|
||||||
// if (!kernel)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// if (stack.size() >= 1000)
|
|
||||||
// panic("unwinding too far");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// panic("unwinding too far");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StackTrace::isEntry(Addr addr)
|
StackTrace::isEntry(Addr addr)
|
||||||
{
|
{
|
||||||
/* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
|
|
||||||
return true;*/
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +211,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
||||||
int reg, disp;
|
int reg, disp;
|
||||||
if (decodeStack(inst, disp)) {
|
if (decodeStack(inst, disp)) {
|
||||||
if (size) {
|
if (size) {
|
||||||
// panic("decoding frame size again");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
size += disp;
|
size += disp;
|
||||||
|
@ -313,7 +218,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
||||||
if (!ra && reg == ReturnAddressReg) {
|
if (!ra && reg == ReturnAddressReg) {
|
||||||
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
||||||
if (!ra) {
|
if (!ra) {
|
||||||
// panic("no return address value pc=%#x\n", pc);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,24 +231,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
||||||
void
|
void
|
||||||
StackTrace::dump()
|
StackTrace::dump()
|
||||||
{
|
{
|
||||||
StringWrap name(tc->getCpuPtr()->name());
|
panic("Stack trace dump not implemented.\n");
|
||||||
// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
|
||||||
|
|
||||||
DPRINTFN("------ Stack ------\n");
|
|
||||||
|
|
||||||
// string symbol;
|
|
||||||
// for (int i = 0, size = stack.size(); i < size; ++i) {
|
|
||||||
// Addr addr = stack[size - i - 1];
|
|
||||||
// if (addr == user)
|
|
||||||
// symbol = "user";
|
|
||||||
// else if (addr == console)
|
|
||||||
// symbol = "console";
|
|
||||||
// else if (addr == unknown)
|
|
||||||
// symbol = "unknown";
|
|
||||||
// else
|
|
||||||
// symtab->findSymbol(addr, symbol);
|
|
||||||
|
|
||||||
// DPRINTFN("%#x: %s\n", addr, symbol);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,22 +45,17 @@
|
||||||
|
|
||||||
using namespace LittleEndianGuest;
|
using namespace LittleEndianGuest;
|
||||||
|
|
||||||
MipsSystem::MipsSystem(Params *p)
|
MipsSystem::MipsSystem(Params *p) : System(p)
|
||||||
: System(p)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
if (p->bare_iron == true) {
|
if (p->bare_iron == true) {
|
||||||
hexFile = new HexFile(params()->hex_file_name);
|
hexFile = new HexFile(params()->hex_file_name);
|
||||||
if(!hexFile->loadSections(&functionalPort,MipsISA::LoadAddrMask))
|
if (!hexFile->loadSections(&functionalPort, MipsISA::LoadAddrMask))
|
||||||
panic("Could not load hex file\n");
|
panic("Could not load hex file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr addr = 0;
|
Addr addr = 0;
|
||||||
/* Comment out old Alpha Based Code
|
|
||||||
|
|
||||||
Don't need the console before we start looking at booting linux */
|
|
||||||
|
|
||||||
|
|
||||||
consoleSymtab = new SymbolTable;
|
consoleSymtab = new SymbolTable;
|
||||||
|
|
||||||
|
@ -76,7 +71,7 @@ MipsSystem::MipsSystem(Params *p)
|
||||||
if (console == NULL)
|
if (console == NULL)
|
||||||
fatal("Could not load console file %s", params()->console);
|
fatal("Could not load console file %s", params()->console);
|
||||||
//Load program sections into memory
|
//Load program sections into memory
|
||||||
console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
|
console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
|
||||||
|
|
||||||
//load symbols
|
//load symbols
|
||||||
if (!console->loadGlobalSymbols(consoleSymtab))
|
if (!console->loadGlobalSymbols(consoleSymtab))
|
||||||
|
@ -110,100 +105,42 @@ MipsSystem::MipsSystem(Params *p)
|
||||||
if (consoleSymtab->findAddress("m5_rpb", addr)) {
|
if (consoleSymtab->findAddress("m5_rpb", addr)) {
|
||||||
uint64_t data;
|
uint64_t data;
|
||||||
data = htog(params()->system_type);
|
data = htog(params()->system_type);
|
||||||
virtPort.write(addr+0x50, data);
|
virtPort.write(addr + 0x50, data);
|
||||||
data = htog(params()->system_rev);
|
data = htog(params()->system_rev);
|
||||||
virtPort.write(addr+0x58, data);
|
virtPort.write(addr + 0x58, data);
|
||||||
} else
|
} else {
|
||||||
panic("could not find hwrpb\n");
|
panic("could not find hwrpb\n");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MipsSystem::~MipsSystem()
|
MipsSystem::~MipsSystem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#if FULL_SYSTEM
|
|
||||||
/**
|
|
||||||
* This function fixes up addresses that are used to match PCs for
|
|
||||||
* hooking simulator events on to target function executions.
|
|
||||||
*
|
|
||||||
* Mips binaries may have multiple global offset table (GOT)
|
|
||||||
* sections. A function that uses the GOT starts with a
|
|
||||||
* two-instruction prolog which sets the global pointer (gp == r29) to
|
|
||||||
* the appropriate GOT section. The proper gp value is calculated
|
|
||||||
* based on the function address, which must be passed by the caller
|
|
||||||
* in the procedure value register (pv aka t12 == r27). This sequence
|
|
||||||
* looks like the following:
|
|
||||||
*
|
|
||||||
* opcode Ra Rb offset
|
|
||||||
* ldah gp,X(pv) 09 29 27 X
|
|
||||||
* lda gp,Y(gp) 08 29 29 Y
|
|
||||||
*
|
|
||||||
* for some constant offsets X and Y. The catch is that the linker
|
|
||||||
* (or maybe even the compiler, I'm not sure) may recognize that the
|
|
||||||
* caller and callee are using the same GOT section, making this
|
|
||||||
* prolog redundant, and modify the call target to skip these
|
|
||||||
* instructions. If we check for execution of the first instruction
|
|
||||||
* of a function (the one the symbol points to) to detect when to skip
|
|
||||||
* it, we'll miss all these modified calls. It might work to
|
|
||||||
* unconditionally check for the third instruction, but not all
|
|
||||||
* functions have this prolog, and there's some chance that those
|
|
||||||
* first two instructions could have undesired consequences. So we do
|
|
||||||
* the Right Thing and pattern-match the first two instructions of the
|
|
||||||
* function to decide where to patch.
|
|
||||||
*
|
|
||||||
* Eventually this code should be moved into an ISA-specific file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
Addr
|
Addr
|
||||||
MipsSystem::fixFuncEventAddr(Addr addr)
|
MipsSystem::fixFuncEventAddr(Addr addr)
|
||||||
{
|
{
|
||||||
/*
|
return addr;
|
||||||
// mask for just the opcode, Ra, and Rb fields (not the offset)
|
|
||||||
const uint32_t inst_mask = 0xffff0000;
|
|
||||||
// ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
|
|
||||||
const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
|
|
||||||
// lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
|
|
||||||
const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
|
|
||||||
|
|
||||||
uint32_t i1 = virtPort.read<uint32_t>(addr);
|
|
||||||
uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(MipsISA::MachInst));
|
|
||||||
|
|
||||||
if ((i1 & inst_mask) == gp_ldah_pattern &&
|
|
||||||
(i2 & inst_mask) == gp_lda_pattern) {
|
|
||||||
Addr new_addr = addr + 2* sizeof(MipsISA::MachInst);
|
|
||||||
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
|
|
||||||
return new_addr;
|
|
||||||
} else {
|
|
||||||
return addr;
|
|
||||||
}*/
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MipsSystem::setMipsAccess(Addr access)
|
MipsSystem::setMipsAccess(Addr access)
|
||||||
{
|
{}
|
||||||
Addr addr = 0;
|
|
||||||
if (consoleSymtab->findAddress("m5MipsAccess", addr)) {
|
|
||||||
// virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access)));
|
|
||||||
} else
|
|
||||||
panic("could not find m5MipsAccess\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MipsSystem::breakpoint()
|
MipsSystem::breakpoint()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
// return remoteGDB[0]->trap(MIPS_KENTRY_INT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MipsSystem::serialize(std::ostream &os)
|
MipsSystem::serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
System::serialize(os);
|
System::serialize(os);
|
||||||
// consoleSymtab->serialize("console_symtab", os);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,7 +148,6 @@ void
|
||||||
MipsSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
MipsSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
{
|
{
|
||||||
System::unserialize(cp,section);
|
System::unserialize(cp,section);
|
||||||
// consoleSymtab->unserialize("console_symtab", cp, section);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MipsSystem *
|
MipsSystem *
|
||||||
|
|
|
@ -54,10 +54,10 @@ class MipsSystem : public System
|
||||||
|
|
||||||
virtual bool breakpoint();
|
virtual bool breakpoint();
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization stuff
|
|
||||||
*/
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Serialization stuff
|
||||||
|
*/
|
||||||
virtual void serialize(std::ostream &os);
|
virtual void serialize(std::ostream &os);
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
||||||
|
@ -89,7 +89,8 @@ class MipsSystem : public System
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
/** Add a function-based event to the console code. */
|
/** Add a function-based event to the console code. */
|
||||||
template <class T>
|
template <class T>
|
||||||
T *addConsoleFuncEvent(const char *lbl)
|
T *
|
||||||
|
addConsoleFuncEvent(const char *lbl)
|
||||||
{
|
{
|
||||||
return addFuncEvent<T>(consoleSymtab, lbl);
|
return addFuncEvent<T>(consoleSymtab, lbl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,16 +56,14 @@ using namespace MipsISA;
|
||||||
// MIPS TLB
|
// MIPS TLB
|
||||||
//
|
//
|
||||||
|
|
||||||
#define MODE2MASK(X) (1 << (X))
|
|
||||||
|
|
||||||
static inline mode_type
|
static inline mode_type
|
||||||
getOperatingMode(MiscReg Stat)
|
getOperatingMode(MiscReg Stat)
|
||||||
{
|
{
|
||||||
if((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
|
if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
|
||||||
return mode_kernel;
|
return mode_kernel;
|
||||||
} else if((Stat & 0x18) == 0x8) {
|
} else if ((Stat & 0x18) == 0x8) {
|
||||||
return mode_supervisor;
|
return mode_supervisor;
|
||||||
} else if((Stat & 0x18) == 0x10) {
|
} else if ((Stat & 0x18) == 0x10) {
|
||||||
return mode_user;
|
return mode_user;
|
||||||
} else {
|
} else {
|
||||||
return mode_number;
|
return mode_number;
|
||||||
|
@ -76,9 +74,9 @@ getOperatingMode(MiscReg Stat)
|
||||||
TLB::TLB(const Params *p)
|
TLB::TLB(const Params *p)
|
||||||
: BaseTLB(p), size(p->size), nlu(0)
|
: BaseTLB(p), size(p->size), nlu(0)
|
||||||
{
|
{
|
||||||
table = new MipsISA::PTE[size];
|
table = new PTE[size];
|
||||||
memset(table, 0, sizeof(MipsISA::PTE[size]));
|
memset(table, 0, sizeof(PTE[size]));
|
||||||
smallPages=0;
|
smallPages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TLB::~TLB()
|
TLB::~TLB()
|
||||||
|
@ -92,23 +90,23 @@ MipsISA::PTE *
|
||||||
TLB::lookup(Addr vpn, uint8_t asn) const
|
TLB::lookup(Addr vpn, uint8_t asn) const
|
||||||
{
|
{
|
||||||
// assume not found...
|
// assume not found...
|
||||||
MipsISA::PTE *retval = NULL;
|
PTE *retval = NULL;
|
||||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||||
if (i != lookupTable.end()) {
|
if (i != lookupTable.end()) {
|
||||||
while (i->first == vpn) {
|
while (i->first == vpn) {
|
||||||
int index = i->second;
|
int index = i->second;
|
||||||
MipsISA::PTE *pte = &table[index];
|
PTE *pte = &table[index];
|
||||||
|
|
||||||
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
|
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
|
||||||
Addr Mask = pte->Mask;
|
Addr Mask = pte->Mask;
|
||||||
Addr InvMask = ~Mask;
|
Addr InvMask = ~Mask;
|
||||||
Addr VPN = pte->VPN;
|
Addr VPN = pte->VPN;
|
||||||
// warn("Valid: %d - %d\n",pte->V0,pte->V1);
|
if (((vpn & InvMask) == (VPN & InvMask)) &&
|
||||||
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
|
(pte->G || (asn == pte->asid))) {
|
||||||
{ // We have a VPN + ASID Match
|
// We have a VPN + ASID Match
|
||||||
retval = pte;
|
retval = pte;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,119 +116,96 @@ TLB::lookup(Addr vpn, uint8_t asn) const
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
MipsISA::PTE* TLB::getEntry(unsigned Index) const
|
MipsISA::PTE*
|
||||||
|
TLB::getEntry(unsigned Index) const
|
||||||
{
|
{
|
||||||
// Make sure that Index is valid
|
// Make sure that Index is valid
|
||||||
assert(Index<size);
|
assert(Index<size);
|
||||||
return &table[Index];
|
return &table[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
int TLB::probeEntry(Addr vpn,uint8_t asn) const
|
int
|
||||||
|
TLB::probeEntry(Addr vpn, uint8_t asn) const
|
||||||
{
|
{
|
||||||
// assume not found...
|
// assume not found...
|
||||||
MipsISA::PTE *retval = NULL;
|
PTE *retval = NULL;
|
||||||
int Ind=-1;
|
int Ind = -1;
|
||||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||||
if (i != lookupTable.end()) {
|
if (i != lookupTable.end()) {
|
||||||
while (i->first == vpn) {
|
while (i->first == vpn) {
|
||||||
int index = i->second;
|
int index = i->second;
|
||||||
MipsISA::PTE *pte = &table[index];
|
PTE *pte = &table[index];
|
||||||
|
|
||||||
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
|
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
|
||||||
Addr Mask = pte->Mask;
|
Addr Mask = pte->Mask;
|
||||||
Addr InvMask = ~Mask;
|
Addr InvMask = ~Mask;
|
||||||
Addr VPN = pte->VPN;
|
Addr VPN = pte->VPN;
|
||||||
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
|
if (((vpn & InvMask) == (VPN & InvMask)) &&
|
||||||
{ // We have a VPN + ASID Match
|
(pte->G || (asn == pte->asid))) {
|
||||||
|
// We have a VPN + ASID Match
|
||||||
retval = pte;
|
retval = pte;
|
||||||
Ind = index;
|
Ind = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
|
DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
|
||||||
return Ind;
|
return Ind;
|
||||||
}
|
}
|
||||||
Fault inline
|
|
||||||
|
inline Fault
|
||||||
TLB::checkCacheability(RequestPtr &req)
|
TLB::checkCacheability(RequestPtr &req)
|
||||||
{
|
{
|
||||||
Addr VAddrUncacheable = 0xA0000000;
|
Addr VAddrUncacheable = 0xA0000000;
|
||||||
// In MIPS, cacheability is controlled by certain bits of the virtual address
|
// In MIPS, cacheability is controlled by certain bits of the virtual
|
||||||
// or by the TLB entry
|
// address or by the TLB entry
|
||||||
if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
|
if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
|
||||||
// mark request as uncacheable
|
// mark request as uncacheable
|
||||||
req->setFlags(Request::UNCACHEABLE);
|
req->setFlags(Request::UNCACHEABLE);
|
||||||
}
|
|
||||||
return NoFault;
|
|
||||||
}
|
|
||||||
void TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages)
|
|
||||||
{
|
|
||||||
smallPages=_smallPages;
|
|
||||||
if(Index > size){
|
|
||||||
warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size);
|
|
||||||
} else {
|
|
||||||
// Update TLB
|
|
||||||
DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
|
|
||||||
((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
|
|
||||||
if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid
|
|
||||||
PageTable::iterator i = lookupTable.find(table[Index].VPN);
|
|
||||||
lookupTable.erase(i);
|
|
||||||
}
|
}
|
||||||
table[Index]=pte;
|
return NoFault;
|
||||||
// Update fast lookup table
|
}
|
||||||
lookupTable.insert(make_pair(table[Index].VPN, Index));
|
|
||||||
// int TestIndex=probeEntry(pte.VPN,pte.asid);
|
|
||||||
// warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
|
||||||
|
{
|
||||||
|
smallPages = _smallPages;
|
||||||
|
if (Index > size) {
|
||||||
|
warn("Attempted to write at index (%d) beyond TLB size (%d)",
|
||||||
|
Index, size);
|
||||||
|
} else {
|
||||||
|
// Update TLB
|
||||||
|
DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
|
||||||
|
Index, pte.Mask << 11,
|
||||||
|
((pte.VPN << 11) | pte.asid),
|
||||||
|
((pte.PFN0 << 6) | (pte.C0 << 3) |
|
||||||
|
(pte.D0 << 2) | (pte.V0 <<1) | pte.G),
|
||||||
|
((pte.PFN1 <<6) | (pte.C1 << 3) |
|
||||||
|
(pte.D1 << 2) | (pte.V1 <<1) | pte.G));
|
||||||
|
if (table[Index].V0 == true || table[Index].V1 == true) {
|
||||||
|
// Previous entry is valid
|
||||||
|
PageTable::iterator i = lookupTable.find(table[Index].VPN);
|
||||||
|
lookupTable.erase(i);
|
||||||
|
}
|
||||||
|
table[Index]=pte;
|
||||||
|
// Update fast lookup table
|
||||||
|
lookupTable.insert(make_pair(table[Index].VPN, Index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert a new TLB entry
|
// insert a new TLB entry
|
||||||
void
|
void
|
||||||
TLB::insert(Addr addr, MipsISA::PTE &pte)
|
TLB::insert(Addr addr, PTE &pte)
|
||||||
{
|
{
|
||||||
fatal("TLB Insert not yet implemented\n");
|
fatal("TLB Insert not yet implemented\n");
|
||||||
|
|
||||||
|
|
||||||
/* MipsISA::VAddr vaddr = addr;
|
|
||||||
if (table[nlu].valid) {
|
|
||||||
Addr oldvpn = table[nlu].tag;
|
|
||||||
PageTable::iterator i = lookupTable.find(oldvpn);
|
|
||||||
|
|
||||||
if (i == lookupTable.end())
|
|
||||||
panic("TLB entry not found in lookupTable");
|
|
||||||
|
|
||||||
int index;
|
|
||||||
while ((index = i->second) != nlu) {
|
|
||||||
if (table[index].tag != oldvpn)
|
|
||||||
panic("TLB entry not found in lookupTable");
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
|
|
||||||
|
|
||||||
lookupTable.erase(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
|
|
||||||
|
|
||||||
table[nlu] = pte;
|
|
||||||
table[nlu].tag = vaddr.vpn();
|
|
||||||
table[nlu].valid = true;
|
|
||||||
|
|
||||||
lookupTable.insert(make_pair(vaddr.vpn(), nlu));
|
|
||||||
nextnlu();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TLB::flushAll()
|
TLB::flushAll()
|
||||||
{
|
{
|
||||||
DPRINTF(TLB, "flushAll\n");
|
DPRINTF(TLB, "flushAll\n");
|
||||||
memset(table, 0, sizeof(MipsISA::PTE[size]));
|
memset(table, 0, sizeof(PTE[size]));
|
||||||
lookupTable.clear();
|
lookupTable.clear();
|
||||||
nlu = 0;
|
nlu = 0;
|
||||||
}
|
}
|
||||||
|
@ -328,68 +303,66 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
||||||
Process * p = tc->getProcessPtr();
|
Process * p = tc->getProcessPtr();
|
||||||
|
|
||||||
Fault fault = p->pTable->translate(req);
|
Fault fault = p->pTable->translate(req);
|
||||||
if(fault != NoFault)
|
if (fault != NoFault)
|
||||||
return fault;
|
return fault;
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
#else
|
#else
|
||||||
if(MipsISA::IsKSeg0(req->getVaddr()))
|
if (IsKSeg0(req->getVaddr())) {
|
||||||
{
|
// Address will not be translated through TLB, set response, and go!
|
||||||
// Address will not be translated through TLB, set response, and go!
|
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
|
||||||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
|
req->isMisaligned()) {
|
||||||
{
|
AddressErrorFault *Flt = new AddressErrorFault();
|
||||||
|
/* BadVAddr must be set */
|
||||||
|
Flt->BadVAddr = req->getVaddr();
|
||||||
|
return Flt;
|
||||||
|
}
|
||||||
|
} else if(IsKSeg1(req->getVaddr())) {
|
||||||
|
// Address will not be translated through TLB, set response, and go!
|
||||||
|
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is an optimization - smallPages is updated every time a TLB
|
||||||
|
* operation is performed. That way, we don't need to look at
|
||||||
|
* Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
|
||||||
|
*/
|
||||||
|
Addr VPN;
|
||||||
|
if (smallPages == 1) {
|
||||||
|
VPN = ((req->getVaddr() >> 11));
|
||||||
|
} else {
|
||||||
|
VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
||||||
|
}
|
||||||
|
uint8_t Asid = req->getAsid();
|
||||||
|
if (req->isMisaligned()) {
|
||||||
|
// Unaligned address!
|
||||||
AddressErrorFault *Flt = new AddressErrorFault();
|
AddressErrorFault *Flt = new AddressErrorFault();
|
||||||
/* BadVAddr must be set */
|
/* BadVAddr must be set */
|
||||||
Flt->BadVAddr = req->getVaddr();
|
Flt->BadVAddr = req->getVaddr();
|
||||||
return Flt;
|
return Flt;
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(MipsISA::IsKSeg1(req->getVaddr()))
|
|
||||||
{
|
|
||||||
// Address will not be translated through TLB, set response, and go!
|
|
||||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is an optimization - smallPages is updated every time a TLB operation is performed
|
|
||||||
That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
|
|
||||||
do a TLB lookup */
|
|
||||||
Addr VPN;
|
|
||||||
if(smallPages==1){
|
|
||||||
VPN=((req->getVaddr() >> 11));
|
|
||||||
} else {
|
|
||||||
VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
|
||||||
}
|
}
|
||||||
uint8_t Asid = req->getAsid();
|
PTE *pte = lookup(VPN,Asid);
|
||||||
if(req->isMisaligned()){ // Unaligned address!
|
if (pte != NULL) {
|
||||||
AddressErrorFault *Flt = new AddressErrorFault();
|
// Ok, found something
|
||||||
/* BadVAddr must be set */
|
|
||||||
Flt->BadVAddr = req->getVaddr();
|
|
||||||
return Flt;
|
|
||||||
}
|
|
||||||
MipsISA::PTE *pte = lookup(VPN,Asid);
|
|
||||||
if(pte != NULL)
|
|
||||||
{// Ok, found something
|
|
||||||
/* Check for valid bits */
|
/* Check for valid bits */
|
||||||
int EvenOdd;
|
int EvenOdd;
|
||||||
bool Valid;
|
bool Valid;
|
||||||
if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){
|
if ((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) == 0) {
|
||||||
// Check even bits
|
// Check even bits
|
||||||
Valid = pte->V0;
|
Valid = pte->V0;
|
||||||
EvenOdd = 0;
|
EvenOdd = 0;
|
||||||
} else {
|
} else {
|
||||||
// Check odd bits
|
// Check odd bits
|
||||||
Valid = pte->V1;
|
Valid = pte->V1;
|
||||||
EvenOdd = 1;
|
EvenOdd = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Valid == false)
|
if (Valid == false) {
|
||||||
{//Invalid entry
|
//Invalid entry
|
||||||
ItbInvalidFault *Flt = new ItbInvalidFault();
|
ItbInvalidFault *Flt = new ItbInvalidFault();
|
||||||
/* EntryHi VPN, ASID fields must be set */
|
/* EntryHi VPN, ASID fields must be set */
|
||||||
Flt->EntryHi_Asid = Asid;
|
Flt->EntryHi_Asid = Asid;
|
||||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
Flt->EntryHi_VPN2 = (VPN >> 2);
|
||||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||||
|
|
||||||
/* BadVAddr must be set */
|
/* BadVAddr must be set */
|
||||||
|
@ -398,43 +371,36 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
||||||
/* Context must be set */
|
/* Context must be set */
|
||||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||||
return Flt;
|
return Flt;
|
||||||
}
|
} else {
|
||||||
else
|
// Ok, this is really a match, set paddr
|
||||||
{// Ok, this is really a match, set paddr
|
|
||||||
// hits++;
|
|
||||||
Addr PAddr;
|
Addr PAddr;
|
||||||
if(EvenOdd == 0){
|
if (EvenOdd == 0) {
|
||||||
PAddr = pte->PFN0;
|
PAddr = pte->PFN0;
|
||||||
}else{
|
} else {
|
||||||
PAddr = pte->PFN1;
|
PAddr = pte->PFN1;
|
||||||
}
|
}
|
||||||
PAddr >>= (pte->AddrShiftAmount-12);
|
PAddr >>= (pte->AddrShiftAmount - 12);
|
||||||
PAddr <<= pte->AddrShiftAmount;
|
PAddr <<= pte->AddrShiftAmount;
|
||||||
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
||||||
req->setPaddr(PAddr);
|
req->setPaddr(PAddr);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
// Didn't find any match, return a TLB Refill Exception
|
||||||
{ // Didn't find any match, return a TLB Refill Exception
|
ItbRefillFault *Flt=new ItbRefillFault();
|
||||||
// misses++;
|
/* EntryHi VPN, ASID fields must be set */
|
||||||
ItbRefillFault *Flt=new ItbRefillFault();
|
Flt->EntryHi_Asid = Asid;
|
||||||
/* EntryHi VPN, ASID fields must be set */
|
Flt->EntryHi_VPN2 = (VPN >> 2);
|
||||||
Flt->EntryHi_Asid = Asid;
|
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
|
||||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
|
||||||
|
|
||||||
|
/* BadVAddr must be set */
|
||||||
|
Flt->BadVAddr = req->getVaddr();
|
||||||
|
|
||||||
/* BadVAddr must be set */
|
/* Context must be set */
|
||||||
Flt->BadVAddr = req->getVaddr();
|
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||||
|
return Flt;
|
||||||
/* Context must be set */
|
|
||||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
|
||||||
return Flt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkCacheability(req);
|
return checkCacheability(req);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,131 +423,118 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
|
||||||
Process * p = tc->getProcessPtr();
|
Process * p = tc->getProcessPtr();
|
||||||
|
|
||||||
Fault fault = p->pTable->translate(req);
|
Fault fault = p->pTable->translate(req);
|
||||||
if(fault != NoFault)
|
if (fault != NoFault)
|
||||||
return fault;
|
return fault;
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
#else
|
#else
|
||||||
if(MipsISA::IsKSeg0(req->getVaddr()))
|
if (IsKSeg0(req->getVaddr())) {
|
||||||
{
|
// Address will not be translated through TLB, set response, and go!
|
||||||
// Address will not be translated through TLB, set response, and go!
|
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
|
||||||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
|
req->isMisaligned()) {
|
||||||
{
|
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
/* BadVAddr must be set */
|
||||||
/* BadVAddr must be set */
|
Flt->BadVAddr = req->getVaddr();
|
||||||
Flt->BadVAddr = req->getVaddr();
|
|
||||||
|
|
||||||
return Flt;
|
return Flt;
|
||||||
}
|
}
|
||||||
}
|
} else if(IsKSeg1(req->getVaddr())) {
|
||||||
else if(MipsISA::IsKSeg1(req->getVaddr()))
|
|
||||||
{
|
|
||||||
// Address will not be translated through TLB, set response, and go!
|
// Address will not be translated through TLB, set response, and go!
|
||||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||||
}
|
} else {
|
||||||
else
|
/*
|
||||||
{
|
* This is an optimization - smallPages is updated every time a TLB
|
||||||
/* This is an optimization - smallPages is updated every time a TLB operation is performed
|
* operation is performed. That way, we don't need to look at
|
||||||
That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
|
* Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
|
||||||
do a TLB lookup */
|
*/
|
||||||
Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
Addr VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
||||||
if(smallPages==1){
|
if (smallPages == 1) {
|
||||||
VPN=((req->getVaddr() >> 11));
|
VPN = ((req->getVaddr() >> 11));
|
||||||
}
|
}
|
||||||
uint8_t Asid = req->getAsid();
|
uint8_t Asid = req->getAsid();
|
||||||
MipsISA::PTE *pte = lookup(VPN,Asid);
|
PTE *pte = lookup(VPN, Asid);
|
||||||
if(req->isMisaligned()){ // Unaligned address!
|
if (req->isMisaligned()) {
|
||||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
// Unaligned address!
|
||||||
/* BadVAddr must be set */
|
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||||
Flt->BadVAddr = req->getVaddr();
|
/* BadVAddr must be set */
|
||||||
return Flt;
|
Flt->BadVAddr = req->getVaddr();
|
||||||
}
|
return Flt;
|
||||||
if(pte != NULL)
|
}
|
||||||
{// Ok, found something
|
if (pte != NULL) {
|
||||||
/* Check for valid bits */
|
// Ok, found something
|
||||||
int EvenOdd;
|
/* Check for valid bits */
|
||||||
bool Valid;
|
int EvenOdd;
|
||||||
bool Dirty;
|
bool Valid;
|
||||||
if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){
|
bool Dirty;
|
||||||
// Check even bits
|
if (((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) == 0) {
|
||||||
Valid = pte->V0;
|
// Check even bits
|
||||||
Dirty = pte->D0;
|
Valid = pte->V0;
|
||||||
EvenOdd = 0;
|
Dirty = pte->D0;
|
||||||
|
EvenOdd = 0;
|
||||||
} else {
|
} else {
|
||||||
// Check odd bits
|
// Check odd bits
|
||||||
Valid = pte->V1;
|
Valid = pte->V1;
|
||||||
Dirty = pte->D1;
|
Dirty = pte->D1;
|
||||||
EvenOdd = 1;
|
EvenOdd = 1;
|
||||||
}
|
|
||||||
|
|
||||||
if(Valid == false)
|
|
||||||
{//Invalid entry
|
|
||||||
// invalids++;
|
|
||||||
DtbInvalidFault *Flt = new DtbInvalidFault();
|
|
||||||
/* EntryHi VPN, ASID fields must be set */
|
|
||||||
Flt->EntryHi_Asid = Asid;
|
|
||||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
|
||||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
|
||||||
|
|
||||||
|
|
||||||
/* BadVAddr must be set */
|
|
||||||
Flt->BadVAddr = req->getVaddr();
|
|
||||||
|
|
||||||
/* Context must be set */
|
|
||||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
|
||||||
|
|
||||||
return Flt;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{// Ok, this is really a match, set paddr
|
|
||||||
// hits++;
|
|
||||||
if(!Dirty)
|
|
||||||
{
|
|
||||||
TLBModifiedFault *Flt = new TLBModifiedFault();
|
|
||||||
/* EntryHi VPN, ASID fields must be set */
|
|
||||||
Flt->EntryHi_Asid = Asid;
|
|
||||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
|
||||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
|
||||||
|
|
||||||
|
if (Valid == false) {
|
||||||
|
//Invalid entry
|
||||||
|
DtbInvalidFault *Flt = new DtbInvalidFault();
|
||||||
|
/* EntryHi VPN, ASID fields must be set */
|
||||||
|
Flt->EntryHi_Asid = Asid;
|
||||||
|
Flt->EntryHi_VPN2 = (VPN>>2);
|
||||||
|
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||||
|
|
||||||
/* BadVAddr must be set */
|
/* BadVAddr must be set */
|
||||||
Flt->BadVAddr = req->getVaddr();
|
Flt->BadVAddr = req->getVaddr();
|
||||||
|
|
||||||
/* Context must be set */
|
/* Context must be set */
|
||||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||||
return Flt;
|
|
||||||
|
|
||||||
|
return Flt;
|
||||||
|
} else {
|
||||||
|
// Ok, this is really a match, set paddr
|
||||||
|
if (!Dirty) {
|
||||||
|
TLBModifiedFault *Flt = new TLBModifiedFault();
|
||||||
|
/* EntryHi VPN, ASID fields must be set */
|
||||||
|
Flt->EntryHi_Asid = Asid;
|
||||||
|
Flt->EntryHi_VPN2 = (VPN >> 2);
|
||||||
|
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||||
|
|
||||||
|
/* BadVAddr must be set */
|
||||||
|
Flt->BadVAddr = req->getVaddr();
|
||||||
|
|
||||||
|
/* Context must be set */
|
||||||
|
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||||
|
return Flt;
|
||||||
}
|
}
|
||||||
Addr PAddr;
|
Addr PAddr;
|
||||||
if(EvenOdd == 0){
|
if (EvenOdd == 0) {
|
||||||
PAddr = pte->PFN0;
|
PAddr = pte->PFN0;
|
||||||
}else{
|
} else {
|
||||||
PAddr = pte->PFN1;
|
PAddr = pte->PFN1;
|
||||||
}
|
}
|
||||||
PAddr >>= (pte->AddrShiftAmount-12);
|
PAddr >>= (pte->AddrShiftAmount - 12);
|
||||||
PAddr <<= pte->AddrShiftAmount;
|
PAddr <<= pte->AddrShiftAmount;
|
||||||
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
||||||
req->setPaddr(PAddr);
|
req->setPaddr(PAddr);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
// Didn't find any match, return a TLB Refill Exception
|
||||||
{ // Didn't find any match, return a TLB Refill Exception
|
DtbRefillFault *Flt = new DtbRefillFault();
|
||||||
// misses++;
|
/* EntryHi VPN, ASID fields must be set */
|
||||||
DtbRefillFault *Flt=new DtbRefillFault();
|
Flt->EntryHi_Asid = Asid;
|
||||||
/* EntryHi VPN, ASID fields must be set */
|
Flt->EntryHi_VPN2 = (VPN >> 2);
|
||||||
Flt->EntryHi_Asid = Asid;
|
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
|
||||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
|
||||||
|
|
||||||
|
/* BadVAddr must be set */
|
||||||
|
Flt->BadVAddr = req->getVaddr();
|
||||||
|
|
||||||
/* BadVAddr must be set */
|
/* Context must be set */
|
||||||
Flt->BadVAddr = req->getVaddr();
|
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||||
|
return Flt;
|
||||||
/* Context must be set */
|
|
||||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
|
||||||
return Flt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkCacheability(req);
|
return checkCacheability(req);
|
||||||
|
@ -609,7 +562,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
MipsISA::PTE &
|
MipsISA::PTE &
|
||||||
TLB::index(bool advance)
|
TLB::index(bool advance)
|
||||||
{
|
{
|
||||||
MipsISA::PTE *pte = &table[nlu];
|
PTE *pte = &table[nlu];
|
||||||
|
|
||||||
if (advance)
|
if (advance)
|
||||||
nextnlu();
|
nextnlu();
|
||||||
|
@ -620,5 +573,5 @@ TLB::index(bool advance)
|
||||||
MipsISA::TLB *
|
MipsISA::TLB *
|
||||||
MipsTLBParams::create()
|
MipsTLBParams::create()
|
||||||
{
|
{
|
||||||
return new MipsISA::TLB(this);
|
return new TLB(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,42 +35,43 @@
|
||||||
|
|
||||||
namespace MipsISA
|
namespace MipsISA
|
||||||
{
|
{
|
||||||
typedef uint32_t MachInst;
|
|
||||||
typedef uint64_t ExtMachInst;
|
|
||||||
|
|
||||||
typedef uint64_t LargestRead;
|
typedef uint32_t MachInst;
|
||||||
|
typedef uint64_t ExtMachInst;
|
||||||
|
|
||||||
//used in FP convert & round function
|
typedef uint64_t LargestRead;
|
||||||
enum ConvertType{
|
|
||||||
SINGLE_TO_DOUBLE,
|
|
||||||
SINGLE_TO_WORD,
|
|
||||||
SINGLE_TO_LONG,
|
|
||||||
|
|
||||||
DOUBLE_TO_SINGLE,
|
//used in FP convert & round function
|
||||||
DOUBLE_TO_WORD,
|
enum ConvertType{
|
||||||
DOUBLE_TO_LONG,
|
SINGLE_TO_DOUBLE,
|
||||||
|
SINGLE_TO_WORD,
|
||||||
|
SINGLE_TO_LONG,
|
||||||
|
|
||||||
LONG_TO_SINGLE,
|
DOUBLE_TO_SINGLE,
|
||||||
LONG_TO_DOUBLE,
|
DOUBLE_TO_WORD,
|
||||||
LONG_TO_WORD,
|
DOUBLE_TO_LONG,
|
||||||
LONG_TO_PS,
|
|
||||||
|
|
||||||
WORD_TO_SINGLE,
|
LONG_TO_SINGLE,
|
||||||
WORD_TO_DOUBLE,
|
LONG_TO_DOUBLE,
|
||||||
WORD_TO_LONG,
|
LONG_TO_WORD,
|
||||||
WORD_TO_PS,
|
LONG_TO_PS,
|
||||||
|
|
||||||
PL_TO_SINGLE,
|
WORD_TO_SINGLE,
|
||||||
PU_TO_SINGLE
|
WORD_TO_DOUBLE,
|
||||||
};
|
WORD_TO_LONG,
|
||||||
|
WORD_TO_PS,
|
||||||
|
|
||||||
//used in FP convert & round function
|
PL_TO_SINGLE,
|
||||||
enum RoundMode{
|
PU_TO_SINGLE
|
||||||
RND_ZERO,
|
};
|
||||||
RND_DOWN,
|
|
||||||
RND_UP,
|
//used in FP convert & round function
|
||||||
RND_NEAREST
|
enum RoundMode{
|
||||||
};
|
RND_ZERO,
|
||||||
|
RND_DOWN,
|
||||||
|
RND_UP,
|
||||||
|
RND_NEAREST
|
||||||
|
};
|
||||||
|
|
||||||
struct CoreSpecific {
|
struct CoreSpecific {
|
||||||
/* Note: It looks like it will be better to allow simulator users
|
/* Note: It looks like it will be better to allow simulator users
|
||||||
|
@ -81,7 +82,8 @@ struct CoreSpecific {
|
||||||
-jpp
|
-jpp
|
||||||
*/
|
*/
|
||||||
// MIPS CP0 State - First individual variables
|
// MIPS CP0 State - First individual variables
|
||||||
// Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM, Volume III (PRA)
|
// Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM,
|
||||||
|
// Volume III (PRA)
|
||||||
unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt
|
unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt
|
||||||
unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt
|
unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt
|
||||||
unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set
|
unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set
|
||||||
|
@ -89,7 +91,8 @@ struct CoreSpecific {
|
||||||
unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS)
|
unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS)
|
||||||
unsigned CP0_PRId_ProcessorID; // Page 105
|
unsigned CP0_PRId_ProcessorID; // Page 105
|
||||||
unsigned CP0_PRId_Revision; // Page 105
|
unsigned CP0_PRId_Revision; // Page 105
|
||||||
unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor system
|
unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor
|
||||||
|
//system
|
||||||
unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode
|
unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode
|
||||||
unsigned CP0_Config_AT; //Page 109
|
unsigned CP0_Config_AT; //Page 109
|
||||||
unsigned CP0_Config_AR; //Page 109
|
unsigned CP0_Config_AR; //Page 109
|
||||||
|
|
|
@ -45,87 +45,88 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace MipsISA {
|
namespace MipsISA {
|
||||||
|
|
||||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Floating Point Utility Functions
|
// Floating Point Utility Functions
|
||||||
//
|
//
|
||||||
uint64_t fpConvert(ConvertType cvt_type, double fp_val);
|
uint64_t fpConvert(ConvertType cvt_type, double fp_val);
|
||||||
double roundFP(double val, int digits);
|
double roundFP(double val, int digits);
|
||||||
double truncFP(double val);
|
double truncFP(double val);
|
||||||
|
|
||||||
bool getCondCode(uint32_t fcsr, int cc);
|
bool getCondCode(uint32_t fcsr, int cc);
|
||||||
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
|
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
|
||||||
uint32_t genInvalidVector(uint32_t fcsr);
|
uint32_t genInvalidVector(uint32_t fcsr);
|
||||||
|
|
||||||
bool isNan(void *val_ptr, int size);
|
bool isNan(void *val_ptr, int size);
|
||||||
bool isQnan(void *val_ptr, int size);
|
bool isQnan(void *val_ptr, int size);
|
||||||
bool isSnan(void *val_ptr, int size);
|
bool isSnan(void *val_ptr, int size);
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
inUserMode(ThreadContext *tc)
|
inUserMode(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
MiscReg Stat = tc->readMiscReg(MipsISA::Status);
|
MiscReg Stat = tc->readMiscReg(MipsISA::Status);
|
||||||
MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
|
MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
|
||||||
|
|
||||||
if((Stat & 0x10000006) == 0 // EXL, ERL or CU0 set, CP0 accessible
|
if ((Stat & 0x10000006) == 0 && // EXL, ERL or CU0 set, CP0 accessible
|
||||||
&& (Dbg & 0x40000000) == 0 // DM bit set, CP0 accessible
|
(Dbg & 0x40000000) == 0 && // DM bit set, CP0 accessible
|
||||||
&& (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
|
(Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
|
||||||
// Unable to use Status_CU0, etc directly, using bitfields & masks
|
// Unable to use Status_CU0, etc directly, using bitfields & masks
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Instruction address compression hooks
|
// Instruction address compression hooks
|
||||||
static inline Addr realPCToFetchPC(const Addr &addr) {
|
static inline Addr realPCToFetchPC(const Addr &addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Addr fetchPCToRealPC(const Addr &addr) {
|
static inline Addr fetchPCToRealPC(const Addr &addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the size of "fetched" instructions (not necessarily the size
|
// the size of "fetched" instructions (not necessarily the size
|
||||||
// of real instructions for PISA)
|
// of real instructions for PISA)
|
||||||
static inline size_t fetchInstSize() {
|
static inline size_t fetchInstSize() {
|
||||||
return sizeof(MachInst);
|
return sizeof(MachInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Register File Utility Functions
|
// Register File Utility Functions
|
||||||
//
|
//
|
||||||
static inline MachInst makeRegisterCopy(int dest, int src) {
|
static inline MachInst makeRegisterCopy(int dest, int src) {
|
||||||
panic("makeRegisterCopy not implemented");
|
panic("makeRegisterCopy not implemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class CPU>
|
template <class CPU>
|
||||||
void zeroRegisters(CPU *cpu);
|
void zeroRegisters(CPU *cpu);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Translation stuff
|
// Translation stuff
|
||||||
//
|
//
|
||||||
inline Addr
|
inline Addr
|
||||||
TruncPage(Addr addr)
|
TruncPage(Addr addr)
|
||||||
{ return addr & ~(PageBytes - 1); }
|
{ return addr & ~(PageBytes - 1); }
|
||||||
|
|
||||||
inline Addr
|
inline Addr
|
||||||
RoundPage(Addr addr)
|
RoundPage(Addr addr)
|
||||||
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// CPU Utility
|
// CPU Utility
|
||||||
//
|
//
|
||||||
void startupCPU(ThreadContext *tc, int cpuId);
|
void startupCPU(ThreadContext *tc, int cpuId);
|
||||||
|
|
||||||
|
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ MipsISA::vtophys(Addr vaddr)
|
||||||
else if(MipsISA::IsKSeg1(vaddr))
|
else if(MipsISA::IsKSeg1(vaddr))
|
||||||
paddr = MipsISA::KSeg12Phys(vaddr);
|
paddr = MipsISA::KSeg12Phys(vaddr);
|
||||||
else
|
else
|
||||||
panic("vtophys: ptbr is not set on virtual lookup for vaddr %#x", vaddr);
|
panic("vtophys: ptbr is not set on "
|
||||||
|
"virtual lookup for vaddr %#x", vaddr);
|
||||||
|
|
||||||
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
||||||
|
|
||||||
|
@ -63,7 +64,6 @@ MipsISA::vtophys(Addr vaddr)
|
||||||
Addr
|
Addr
|
||||||
MipsISA::vtophys(ThreadContext *tc, Addr addr)
|
MipsISA::vtophys(ThreadContext *tc, Addr addr)
|
||||||
{
|
{
|
||||||
|
|
||||||
fatal("VTOPHYS: Unimplemented on MIPS\n");
|
fatal("VTOPHYS: Unimplemented on MIPS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue