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
|
||||
*/
|
||||
|
||||
#include "arch/vtophys.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 "sim/byteswap.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace MipsISA;
|
||||
|
||||
|
||||
BareIronMipsSystem::BareIronMipsSystem(Params *p)
|
||||
: MipsSystem(p)
|
||||
|
|
|
@ -31,11 +31,6 @@
|
|||
#ifndef __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 "params/BareIronMipsSystem.hh"
|
||||
|
||||
|
@ -46,15 +41,9 @@ class IdleStartEvent;
|
|||
*/
|
||||
class BareIronMipsSystem : public MipsSystem
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
static const int CommandLineSize = 256;
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
BareIronMipsSystem(Params *p);
|
||||
~BareIronMipsSystem();
|
||||
};
|
||||
|
|
|
@ -85,7 +85,6 @@ FaultName ThreadFault::_name = "Thread Fault";
|
|||
FaultVect ThreadFault::_vect = 0x00F1;
|
||||
FaultStat ThreadFault::_count;
|
||||
|
||||
|
||||
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
|
||||
FaultVect ArithmeticFault::_vect = 0x180;
|
||||
FaultStat ArithmeticFault::_count;
|
||||
|
@ -106,7 +105,6 @@ FaultName BreakpointFault::_name = "Breakpoint";
|
|||
FaultVect BreakpointFault::_vect = 0x0180;
|
||||
FaultStat BreakpointFault::_count;
|
||||
|
||||
|
||||
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
|
||||
FaultVect ItbInvalidFault::_vect = 0x0180;
|
||||
FaultStat ItbInvalidFault::_count;
|
||||
|
@ -168,344 +166,366 @@ FaultVect DspStateDisabledFault::_vect = 0x001a;
|
|||
FaultStat DspStateDisabledFault::_count;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
|
||||
void
|
||||
MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
|
||||
{
|
||||
tc->setPC(HandlerBase);
|
||||
tc->setNextPC(HandlerBase+sizeof(MachInst));
|
||||
tc->setNextNPC(HandlerBase+2*sizeof(MachInst));
|
||||
tc->setPC(HandlerBase);
|
||||
tc->setNextPC(HandlerBase + 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
|
||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||
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
|
||||
MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
|
||||
uint8_t CSS,ESS;
|
||||
CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO);
|
||||
ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO);
|
||||
// Move CSS to PSS
|
||||
replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS);
|
||||
// Move ESS to CSS
|
||||
replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS);
|
||||
tc->setMiscRegNoEffect(MipsISA::SRSCtl,srs);
|
||||
//tc->setShadowSet(ESS);
|
||||
// modify SRS Ctl - Save CSS, put ESS into CSS
|
||||
MiscReg stat = tc->readMiscReg(MipsISA::Status);
|
||||
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
|
||||
MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
|
||||
uint8_t CSS, ESS;
|
||||
CSS = bits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO);
|
||||
ESS = bits(srs, SRSCtl_ESS_HI, SRSCtl_ESS_LO);
|
||||
// Move CSS to PSS
|
||||
replaceBits(srs, SRSCtl_PSS_HI, SRSCtl_PSS_LO, CSS);
|
||||
// Move ESS to CSS
|
||||
replaceBits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO, ESS);
|
||||
tc->setMiscRegNoEffect(MipsISA::SRSCtl, srs);
|
||||
}
|
||||
|
||||
// set EXL bit (don't care if it is already set!)
|
||||
replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1);
|
||||
tc->setMiscRegNoEffect(MipsISA::Status,stat);
|
||||
// set EXL bit (don't care if it is already set!)
|
||||
replaceBits(stat, Status_EXL_HI, Status_EXL_LO, 1);
|
||||
tc->setMiscRegNoEffect(MipsISA::Status, stat);
|
||||
|
||||
// write EPC
|
||||
// warn("Set EPC to %x\n",tc->readPC());
|
||||
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK
|
||||
// Check to see if the exception occurred in the branch delay slot
|
||||
DPRINTF(MipsPRA,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC());
|
||||
int C_BD=0;
|
||||
if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){
|
||||
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC()-sizeof(MachInst));
|
||||
// In the branch delay slot? set CAUSE_31
|
||||
C_BD = 1;
|
||||
} else {
|
||||
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC());
|
||||
// In the branch delay slot? reset CAUSE_31
|
||||
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);
|
||||
// write EPC
|
||||
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK
|
||||
// Check to see if the exception occurred in the branch delay slot
|
||||
DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
|
||||
tc->readPC(), tc->readNextPC(), tc->readNextNPC());
|
||||
int C_BD = 0;
|
||||
if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
|
||||
tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC() - sizeof(MachInst));
|
||||
// In the branch delay slot? set CAUSE_31
|
||||
C_BD = 1;
|
||||
} else {
|
||||
tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC());
|
||||
// In the branch delay slot? reset CAUSE_31
|
||||
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);
|
||||
}
|
||||
|
||||
void ArithmeticFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
ArithmeticFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
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);
|
||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||
setExceptionState(tc, 0xC);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setExceptionState(tc,0x1);
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SystemCallFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
StoreAddressErrorFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x8);
|
||||
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));
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
// Offset 0x180 - General Exception Vector
|
||||
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||
setHandlerPC(HandlerBase, tc);
|
||||
}
|
||||
|
||||
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
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x0A);
|
||||
Addr HandlerBase;
|
||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||
setExceptionState(tc, 0x0A);
|
||||
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);
|
||||
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);
|
||||
setHandlerPC(HandlerBase, tc);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
void ResetFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
ResetFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
/* All reset activity must be invoked from here */
|
||||
tc->setPC(vect());
|
||||
tc->setNextPC(vect()+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, "%s encountered.\n", name());
|
||||
/* All reset activity must be invoked from here */
|
||||
tc->setPC(vect());
|
||||
tc->setNextPC(vect() + sizeof(MachInst));
|
||||
tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
|
||||
DPRINTF(MipsPRA, "(%x) - ResetFault::invoke : PC set to %x",
|
||||
(unsigned)tc, (unsigned)tc->readPC());
|
||||
#endif
|
||||
|
||||
// Set Coprocessor 1 (Floating Point) To Usable
|
||||
tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
|
||||
// Set Coprocessor 1 (Floating Point) To Usable
|
||||
tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
|
||||
}
|
||||
|
||||
void ReservedInstructionFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
ReservedInstructionFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x0A);
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||
setExceptionState(tc, 0x0A);
|
||||
Addr HandlerBase;
|
||||
// Offset 0x180 - General Exception Vector
|
||||
HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
|
||||
setHandlerPC(HandlerBase, tc);
|
||||
#else
|
||||
panic("%s encountered.\n", name());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
ThreadFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
panic("%s encountered.\n", name());
|
||||
DPRINTF(MipsPRA, "%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());
|
||||
panic("%s encountered.\n", name());
|
||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||
panic("%s encountered.\n", name());
|
||||
}
|
||||
|
||||
void CoprocessorUnusableFault::invoke(ThreadContext *tc)
|
||||
void
|
||||
CoprocessorUnusableFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(MipsPRA,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0xb);
|
||||
/* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */
|
||||
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
||||
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID);
|
||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||
setExceptionState(tc, 0xb);
|
||||
// The ID of the coprocessor causing the exception is stored in
|
||||
// CoprocessorUnusableFault::coProcID
|
||||
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
|
||||
replaceBits(cause, Cause_CE_HI, Cause_CE_LO, coProcID);
|
||||
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
|
||||
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
Addr HandlerBase;
|
||||
// Offset 0x180 - General Exception Vector
|
||||
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
|
||||
setHandlerPC(HandlerBase, tc);
|
||||
|
||||
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(MipsISA::Status),tc->readMiscReg(MipsISA::Cause));
|
||||
#else
|
||||
warn("%s (CP%d) encountered.\n", name(), coProcID);
|
||||
#endif
|
||||
|
|
|
@ -36,10 +36,9 @@
|
|||
|
||||
#include "sim/faults.hh"
|
||||
|
||||
// The design of the "name" and "vect" functions is in sim/faults.hh
|
||||
|
||||
namespace MipsISA
|
||||
{
|
||||
|
||||
typedef const Addr FaultVect;
|
||||
|
||||
class MipsFault : public FaultBase
|
||||
|
@ -54,9 +53,9 @@ class MipsFault : public FaultBase
|
|||
Addr EntryHi_VPN2X;
|
||||
Addr Context_BadVPN2;
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc) {};
|
||||
void setExceptionState(ThreadContext *,uint8_t);
|
||||
void setHandlerPC(Addr,ThreadContext *);
|
||||
void invoke(ThreadContext * tc) {};
|
||||
void setExceptionState(ThreadContext *, uint8_t);
|
||||
void setHandlerPC(Addr, ThreadContext *);
|
||||
#endif
|
||||
virtual FaultVect vect() = 0;
|
||||
virtual FaultStat & countStat() = 0;
|
||||
|
@ -116,6 +115,7 @@ class AddressErrorFault : public MipsFault
|
|||
#endif
|
||||
|
||||
};
|
||||
|
||||
class StoreAddressErrorFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -129,8 +129,8 @@ class StoreAddressErrorFault : public MipsFault
|
|||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class UnimplementedOpcodeFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -157,6 +157,7 @@ class TLBRefillIFetchFault : public MipsFault
|
|||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class TLBInvalidIFetchFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -259,6 +260,7 @@ class ResetFault : public MipsFault
|
|||
void invoke(ThreadContext * tc);
|
||||
|
||||
};
|
||||
|
||||
class SystemCallFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -284,6 +286,7 @@ class SoftResetFault : public MipsFault
|
|||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class DebugSingleStep : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -296,6 +299,7 @@ class DebugSingleStep : public MipsFault
|
|||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class DebugInterrupt : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -350,7 +354,6 @@ class ThreadFault : public MipsFault
|
|||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
|
||||
class ArithmeticFault : public MipsFault
|
||||
{
|
||||
protected:
|
||||
|
@ -384,8 +387,6 @@ class InterruptFault : public MipsFault
|
|||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
//void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class TrapFault : public MipsFault
|
||||
|
@ -432,6 +433,7 @@ class ItbRefillFault : public MipsFault
|
|||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class DtbRefillFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -475,8 +477,8 @@ class ItbInvalidFault : public MipsFault
|
|||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class TLBModifiedFault : public MipsFault
|
||||
{
|
||||
private:
|
||||
|
@ -490,7 +492,6 @@ class TLBModifiedFault : public MipsFault
|
|||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class DtbInvalidFault : public MipsFault
|
||||
|
@ -506,7 +507,6 @@ class DtbInvalidFault : public MipsFault
|
|||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class FloatEnableFault : public MipsFault
|
||||
|
|
|
@ -40,9 +40,4 @@ void
|
|||
IdleStartEvent::process(ThreadContext *tc)
|
||||
{
|
||||
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
|
||||
{
|
||||
static inline uint8_t getCauseIP_(ThreadContext *tc) {
|
||||
|
||||
static inline uint8_t
|
||||
getCauseIP(ThreadContext *tc) {
|
||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
||||
uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
|
||||
return IP_;
|
||||
return bits(cause, Cause_IP7, Cause_IP0);
|
||||
}
|
||||
|
||||
static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
|
||||
static inline void
|
||||
setCauseIP_(ThreadContext *tc, uint8_t val) {
|
||||
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
|
||||
replaceBits(cause,Cause_IP7,Cause_IP0,val);
|
||||
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
|
||||
replaceBits(cause, Cause_IP7, Cause_IP0, val);
|
||||
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
|
||||
}
|
||||
|
||||
/*
|
||||
void Interrupts::post(int int_num, int index)
|
||||
{
|
||||
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)
|
||||
void
|
||||
Interrupts::post(int int_num, ThreadContext* tc)
|
||||
{
|
||||
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
|
||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
uint8_t intstatus= getCauseIP_(tc);
|
||||
uint8_t intstatus = getCauseIP(tc);
|
||||
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);
|
||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
uint8_t intstatus = getCauseIP_(tc);
|
||||
uint8_t intstatus = getCauseIP(tc);
|
||||
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");
|
||||
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");
|
||||
|
||||
|
||||
|
||||
//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_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
|
||||
bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
|
||||
{
|
||||
// Interrupts must be enabled, error level must be 0 or interrupts
|
||||
// inhibited, and 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.
|
||||
// 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 = getCauseIP_(tc);
|
||||
//IM and IP are already correctly aligned
|
||||
if (IM & IP){
|
||||
uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0);
|
||||
uint8_t InterruptPending = getCauseIP(tc);
|
||||
// InterruptMask and InterruptPending are already correctly aligned
|
||||
if (InterruptMask && InterruptPending){
|
||||
DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
|
||||
IM, IP);
|
||||
InterruptMask, InterruptPending);
|
||||
return new InterruptFault;
|
||||
}
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
|
||||
}
|
||||
bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
||||
|
||||
bool
|
||||
Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
||||
{
|
||||
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
|
||||
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
|
||||
|
@ -240,34 +141,32 @@ bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
void Interrupts::updateIntrInfo(ThreadContext *tc) const
|
||||
|
||||
void
|
||||
Interrupts::updateIntrInfo(ThreadContext *tc) const
|
||||
{
|
||||
//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)
|
||||
//update CauseIP before proceeding to interrupt
|
||||
if (onCpuTimerInterrupt(tc)){
|
||||
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
|
||||
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, tc);
|
||||
uint8_t intstatus= getCauseIP_(tc);
|
||||
uint8_t intstatus = getCauseIP(tc);
|
||||
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__
|
||||
#define __ARCH_MIPS_INTERRUPT_HH__
|
||||
|
||||
|
||||
#include "arch/mips/faults.hh"
|
||||
#include "base/compiler.hh"
|
||||
|
||||
|
||||
|
||||
namespace MipsISA
|
||||
{
|
||||
|
||||
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:
|
||||
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, ThreadContext* tc);
|
||||
void post(int int_num, ThreadContext *tc);
|
||||
void post(int int_num, int index);
|
||||
|
||||
// clear(int int_num, int index) is responsible
|
||||
|
@ -139,7 +69,7 @@ class Interrupts
|
|||
// MIPS register Cause is updated by updateIntrInfo
|
||||
// which is called by checkInterrupts
|
||||
//
|
||||
void clearAll(ThreadContext* tc);
|
||||
void clearAll(ThreadContext *tc);
|
||||
void clearAll();
|
||||
|
||||
// getInterrupt(ThreadContext * tc) checks if an interrupt
|
||||
|
@ -148,7 +78,7 @@ class Interrupts
|
|||
// also makes sure interrupts are enabled (IE) and
|
||||
// that ERL and ERX are not set
|
||||
//
|
||||
Fault getInterrupt(ThreadContext * tc);
|
||||
Fault getInterrupt(ThreadContext *tc);
|
||||
|
||||
// updateIntrInfo(ThreadContext *tc) const syncs the
|
||||
// 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");
|
||||
//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");
|
||||
//UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
|
||||
//UNSERIALIZE_SCALAR(intstatus);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
bool newInfoSet;
|
||||
int newIpl;
|
||||
int newSummary;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -447,12 +447,7 @@ ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid)
|
|||
misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg],
|
||||
miscRegFile[misc_reg][reg_sel]);
|
||||
|
||||
|
||||
switch (misc_reg)
|
||||
{
|
||||
default:
|
||||
return miscRegFile[misc_reg][reg_sel];
|
||||
}
|
||||
return miscRegFile[misc_reg][reg_sel];
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -486,7 +481,6 @@ ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid)
|
|||
// (1) Some CP0 Registers have fields that cannot
|
||||
// be overwritten. Make sure to handle those particular registers
|
||||
// with care!
|
||||
//template <class TC>
|
||||
void
|
||||
ISA::setMiscReg(int reg_idx, const MiscReg &val,
|
||||
ThreadContext *tc, ThreadID tid)
|
||||
|
@ -515,21 +509,21 @@ ISA::setMiscReg(int reg_idx, const MiscReg &val,
|
|||
MiscReg
|
||||
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
|
||||
{
|
||||
MiscReg retVal = val;
|
||||
MiscReg retVal = val;
|
||||
|
||||
// Mask off read-only regions
|
||||
retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
|
||||
MiscReg curVal = miscRegFile[misc_reg][reg_sel];
|
||||
// Mask off current alue with inverse mask (clear writeable bits)
|
||||
curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
|
||||
retVal |= curVal; // Combine the two
|
||||
DPRINTF(MipsPRA,
|
||||
"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
|
||||
"current val: %lx, written val: %x\n",
|
||||
miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||
~miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||
val, miscRegFile[misc_reg][reg_sel], retVal);
|
||||
return retVal;
|
||||
// Mask off read-only regions
|
||||
retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
|
||||
MiscReg curVal = miscRegFile[misc_reg][reg_sel];
|
||||
// Mask off current alue with inverse mask (clear writeable bits)
|
||||
curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
|
||||
retVal |= curVal; // Combine the two
|
||||
DPRINTF(MipsPRA,
|
||||
"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
|
||||
"current val: %lx, written val: %x\n",
|
||||
miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||
~miscRegFile_WriteMask[misc_reg][reg_sel],
|
||||
val, miscRegFile[misc_reg][reg_sel], retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -586,8 +580,6 @@ ISA::CP0Event::process()
|
|||
cp0->updateCPU();
|
||||
break;
|
||||
}
|
||||
|
||||
//cp0EventRemoveList.push(this);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
@ -41,133 +41,129 @@
|
|||
|
||||
namespace LittleEndianGuest {};
|
||||
|
||||
#define TARGET_MIPS
|
||||
|
||||
class StaticInstPtr;
|
||||
|
||||
namespace MipsISA
|
||||
{
|
||||
using namespace LittleEndianGuest;
|
||||
|
||||
StaticInstPtr decodeInst(ExtMachInst);
|
||||
using namespace LittleEndianGuest;
|
||||
|
||||
// MIPS DOES have a delay slot
|
||||
#define ISA_HAS_DELAY_SLOT 1
|
||||
StaticInstPtr decodeInst(ExtMachInst);
|
||||
|
||||
const Addr PageShift = 13;
|
||||
const Addr PageBytes = ULL(1) << PageShift;
|
||||
const Addr Page_Mask = ~(PageBytes - 1);
|
||||
const Addr PageOffset = PageBytes - 1;
|
||||
// MIPS DOES have a delay slot
|
||||
#define ISA_HAS_DELAY_SLOT 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 NPtePageShift = PageShift - PteShift;
|
||||
const Addr NPtePage = ULL(1) << NPtePageShift;
|
||||
const Addr PteMask = NPtePage - 1;
|
||||
const Addr PteShift = 3;
|
||||
const Addr NPtePageShift = PageShift - PteShift;
|
||||
const Addr NPtePage = ULL(1) << NPtePageShift;
|
||||
const Addr PteMask = NPtePage - 1;
|
||||
|
||||
//// All 'Mapped' segments go through the TLB
|
||||
//// All other segments are translated by dropping the MSB, to give
|
||||
//// the corresponding physical address
|
||||
// User Segment - Mapped
|
||||
const Addr USegBase = ULL(0x0);
|
||||
const Addr USegEnd = ULL(0x7FFFFFFF);
|
||||
//// All 'Mapped' segments go through the TLB
|
||||
//// All other segments are translated by dropping the MSB, to give
|
||||
//// the corresponding physical address
|
||||
// User Segment - Mapped
|
||||
const Addr USegBase = ULL(0x0);
|
||||
const Addr USegEnd = ULL(0x7FFFFFFF);
|
||||
|
||||
// Kernel Segment 0 - Unmapped
|
||||
const Addr KSeg0End = ULL(0x9FFFFFFF);
|
||||
const Addr KSeg0Base = ULL(0x80000000);
|
||||
const Addr KSeg0Mask = ULL(0x1FFFFFFF);
|
||||
// Kernel Segment 0 - Unmapped
|
||||
const Addr KSeg0End = ULL(0x9FFFFFFF);
|
||||
const Addr KSeg0Base = ULL(0x80000000);
|
||||
const Addr KSeg0Mask = ULL(0x1FFFFFFF);
|
||||
|
||||
// Kernel Segment 1 - Unmapped, Uncached
|
||||
const Addr KSeg1End = ULL(0xBFFFFFFF);
|
||||
const Addr KSeg1Base = ULL(0xA0000000);
|
||||
const Addr KSeg1Mask = ULL(0x1FFFFFFF);
|
||||
// Kernel Segment 1 - Unmapped, Uncached
|
||||
const Addr KSeg1End = ULL(0xBFFFFFFF);
|
||||
const Addr KSeg1Base = ULL(0xA0000000);
|
||||
const Addr KSeg1Mask = ULL(0x1FFFFFFF);
|
||||
|
||||
// Kernel/Supervisor Segment - Mapped
|
||||
const Addr KSSegEnd = ULL(0xDFFFFFFF);
|
||||
const Addr KSSegBase = ULL(0xC0000000);
|
||||
// Kernel/Supervisor Segment - Mapped
|
||||
const Addr KSSegEnd = ULL(0xDFFFFFFF);
|
||||
const Addr KSSegBase = ULL(0xC0000000);
|
||||
|
||||
// Kernel Segment 3 - Mapped
|
||||
const Addr KSeg3End = ULL(0xFFFFFFFF);
|
||||
const Addr KSeg3Base = ULL(0xE0000000);
|
||||
// Kernel Segment 3 - Mapped
|
||||
const Addr KSeg3End = ULL(0xFFFFFFFF);
|
||||
const Addr KSeg3Base = ULL(0xE0000000);
|
||||
|
||||
|
||||
// For loading... XXX This maybe could be USegEnd?? --ali
|
||||
const Addr LoadAddrMask = ULL(0xffffffffff);
|
||||
// For loading... XXX This maybe could be USegEnd?? --ali
|
||||
const Addr LoadAddrMask = ULL(0xffffffffff);
|
||||
|
||||
inline Addr Phys2K0Seg(Addr addr)
|
||||
{
|
||||
// if (addr & PAddrUncachedBit43) {
|
||||
// addr &= PAddrUncachedMask;
|
||||
// addr |= PAddrUncachedBit40;
|
||||
// }
|
||||
return addr | KSeg0Base;
|
||||
}
|
||||
inline Addr Phys2K0Seg(Addr addr)
|
||||
{
|
||||
return addr | KSeg0Base;
|
||||
}
|
||||
|
||||
|
||||
const unsigned VABits = 32;
|
||||
const unsigned PABits = 32; // Is this correct?
|
||||
const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
|
||||
const Addr VAddrUnImplMask = ~VAddrImplMask;
|
||||
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
|
||||
inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
|
||||
inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
|
||||
const unsigned VABits = 32;
|
||||
const unsigned PABits = 32; // Is this correct?
|
||||
const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
|
||||
const Addr VAddrUnImplMask = ~VAddrImplMask;
|
||||
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
|
||||
inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
|
||||
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
|
||||
//
|
||||
enum InterruptLevels
|
||||
{
|
||||
INTLEVEL_SOFTWARE_MIN = 4,
|
||||
INTLEVEL_SOFTWARE_MAX = 19,
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Interrupt levels
|
||||
//
|
||||
enum InterruptLevels
|
||||
{
|
||||
INTLEVEL_SOFTWARE_MIN = 4,
|
||||
INTLEVEL_SOFTWARE_MAX = 19,
|
||||
|
||||
INTLEVEL_EXTERNAL_MIN = 20,
|
||||
INTLEVEL_EXTERNAL_MAX = 34,
|
||||
INTLEVEL_EXTERNAL_MIN = 20,
|
||||
INTLEVEL_EXTERNAL_MAX = 34,
|
||||
|
||||
INTLEVEL_IRQ0 = 20,
|
||||
INTLEVEL_IRQ1 = 21,
|
||||
INTINDEX_ETHERNET = 0,
|
||||
INTINDEX_SCSI = 1,
|
||||
INTLEVEL_IRQ2 = 22,
|
||||
INTLEVEL_IRQ3 = 23,
|
||||
INTLEVEL_IRQ0 = 20,
|
||||
INTLEVEL_IRQ1 = 21,
|
||||
INTINDEX_ETHERNET = 0,
|
||||
INTINDEX_SCSI = 1,
|
||||
INTLEVEL_IRQ2 = 22,
|
||||
INTLEVEL_IRQ3 = 23,
|
||||
|
||||
INTLEVEL_SERIAL = 33,
|
||||
INTLEVEL_SERIAL = 33,
|
||||
|
||||
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
||||
};
|
||||
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
||||
};
|
||||
|
||||
// MIPS modes
|
||||
enum mode_type
|
||||
{
|
||||
mode_kernel = 0, // kernel
|
||||
mode_supervisor = 1, // supervisor
|
||||
mode_user = 2, // user mode
|
||||
mode_debug = 3, // debug mode
|
||||
mode_number // number of modes
|
||||
};
|
||||
// MIPS modes
|
||||
enum mode_type
|
||||
{
|
||||
mode_kernel = 0, // kernel
|
||||
mode_supervisor = 1, // supervisor
|
||||
mode_user = 2, // user mode
|
||||
mode_debug = 3, // debug mode
|
||||
mode_number // number of modes
|
||||
};
|
||||
|
||||
// return a no-op instruction... used for instruction fetch faults
|
||||
const ExtMachInst NoopMachInst = 0x00000000;
|
||||
// return a no-op instruction... used for instruction fetch faults
|
||||
const ExtMachInst NoopMachInst = 0x00000000;
|
||||
|
||||
const int LogVMPageSize = 13; // 8K bytes
|
||||
const int VMPageSize = (1 << LogVMPageSize);
|
||||
const int LogVMPageSize = 13; // 8K bytes
|
||||
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 WordBytes = 4;
|
||||
const int HalfwordBytes = 2;
|
||||
const int ByteBytes = 1;
|
||||
const int MachineBytes = 4;
|
||||
const int WordBytes = 4;
|
||||
const int HalfwordBytes = 2;
|
||||
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__
|
||||
|
|
|
@ -32,11 +32,6 @@
|
|||
#ifndef __ARCH_MIPS_KERNEL_STATS_HH__
|
||||
#define __ARCH_MIPS_KERNEL_STATS_HH__
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "kern/kernel_stats.hh"
|
||||
|
||||
namespace MipsISA {
|
||||
|
|
|
@ -69,7 +69,3 @@ OpenFlagTransTable MipsLinux::openFlagTable[] = {
|
|||
|
||||
const int MipsLinux::NUM_OPEN_FLAGS =
|
||||
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -68,13 +68,13 @@ class MipsLinux : public Linux
|
|||
|
||||
//@{
|
||||
/// For getsysinfo().
|
||||
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
|
||||
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
|
||||
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_CPUS_IN_BOX = 55; //!< number of CPUs in system
|
||||
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_PLATFORM_NAME = 103; //!< platform name as string
|
||||
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
|
||||
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_CPUS_IN_BOX = 55; //!< number of CPUs in system
|
||||
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
|
||||
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);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case 45: { // GSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
*fpcr = 0;
|
||||
fpcr.copyOut(tc->getMemPort());
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 45:
|
||||
{
|
||||
// GSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
*fpcr = 0;
|
||||
fpcr.copyOut(tc->getMemPort());
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
cerr << "sys_getsysinfo: unknown op " << op << endl;
|
||||
abort();
|
||||
|
@ -102,15 +102,16 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
|
||||
switch (op) {
|
||||
|
||||
case 14: { // SSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
fpcr.copyIn(tc->getMemPort());
|
||||
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
|
||||
case 14:
|
||||
{
|
||||
// SSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
// 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));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
cerr << "sys_setsysinfo: unknown op " << op << endl;
|
||||
abort();
|
||||
|
@ -196,8 +197,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
|
||||
/* 73 */ SyscallDesc("sigpending", unimplementedFunc),
|
||||
/* 74 */ SyscallDesc("sethostname", ignoreFunc),
|
||||
/* 75 */ SyscallDesc("setrlimit", unimplementedFunc/*setrlimitFunc<MipsLinux>*/),
|
||||
/* 76 */ SyscallDesc("getrlimit", unimplementedFunc/*getrlimitFunc<MipsLinux>*/),
|
||||
/* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
|
||||
/* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
|
||||
/* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>),
|
||||
/* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
|
||||
/* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
|
||||
|
@ -241,7 +242,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
|
||||
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
|
||||
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
|
||||
/* 120 */ SyscallDesc("clone", unimplementedFunc/*cloneFunc<MipsLinux>*/),
|
||||
/* 120 */ SyscallDesc("clone", unimplementedFunc),
|
||||
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
|
||||
/* 122 */ SyscallDesc("uname", unameFunc),
|
||||
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
|
||||
|
@ -315,12 +316,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 191 */ SyscallDesc("getresgid", unimplementedFunc),
|
||||
/* 192 */ SyscallDesc("prctl", unimplementedFunc),
|
||||
/* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
|
||||
/* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc/*rt_sigactionFunc<MipsLinux>*/),
|
||||
/* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc/*rt_sigprocmaskFunc<MipsLinux>*/),
|
||||
/* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc),
|
||||
/* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
|
||||
/* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
|
||||
/* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
|
||||
/* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
|
||||
/* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc/*rt_sigsuspendFunc<MipsLinux>*/),
|
||||
/* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
|
||||
/* 200 */ SyscallDesc("pread64", unimplementedFunc),
|
||||
/* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
|
||||
/* 202 */ SyscallDesc("chown", unimplementedFunc),
|
||||
|
@ -406,7 +407,6 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 282 */ SyscallDesc("keyctl", unimplementedFunc)
|
||||
};
|
||||
|
||||
|
||||
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
|
||||
ObjectFile *objFile)
|
||||
: MipsLiveProcess(params, objFile),
|
||||
|
|
|
@ -88,7 +88,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
|
|||
virtPort.write(addr, (uint64_t)(Clock::Frequency /
|
||||
p->boot_cpu_frequency));
|
||||
|
||||
|
||||
/**
|
||||
* EV5 only supports 127 ASNs so we are going to tell the kernel that the
|
||||
* paritiuclar EV6 we have only supports 127 asns.
|
||||
|
@ -105,12 +104,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
|
|||
if (!kernelPanicEvent)
|
||||
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
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,17 +45,18 @@
|
|||
|
||||
namespace MipsISA
|
||||
{
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedRead(XC *xc, Request *req)
|
||||
{
|
||||
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
template <class XC>
|
||||
inline bool
|
||||
handleLockedWrite(XC *xc, Request *req)
|
||||
|
@ -89,14 +90,17 @@ handleLockedWrite(XC *xc, Request *req)
|
|||
}
|
||||
|
||||
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){
|
||||
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n",
|
||||
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, "
|
||||
"Store Conditional Failed.\n",
|
||||
req->threadId());
|
||||
} 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());
|
||||
}
|
||||
// store conditional failed already, so don't issue it to mem
|
||||
|
@ -107,7 +111,6 @@ handleLockedWrite(XC *xc, Request *req)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace MipsISA
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,20 +29,9 @@
|
|||
* 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 "cpu/base.hh"
|
||||
#include "cpu/simple_thread.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
|
||||
|
||||
|
@ -52,61 +41,11 @@
|
|||
//
|
||||
void
|
||||
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>
|
||||
void
|
||||
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
|
||||
|
|
|
@ -44,6 +44,7 @@ class ThreadContext;
|
|||
|
||||
namespace MipsISA
|
||||
{
|
||||
|
||||
inline Tick
|
||||
handleIprRead(ThreadContext *xc, Packet *pkt)
|
||||
{
|
||||
|
@ -56,7 +57,6 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
|
|||
panic("No implementation for handleIprWrite in MIPS\n");
|
||||
}
|
||||
|
||||
|
||||
} // namespace MipsISA
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
namespace MipsISA
|
||||
{
|
||||
|
||||
|
||||
template <class TC>
|
||||
inline unsigned
|
||||
getVirtProcNum(TC *tc)
|
||||
|
@ -76,11 +75,13 @@ haltThread(TC *tc)
|
|||
tc->halt();
|
||||
|
||||
// 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());
|
||||
|
||||
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||
tc->readPC(), tc->readNextPC());
|
||||
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
|
||||
curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||
tc->readPC(), tc->readNextPC());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,14 +94,14 @@ restoreThread(TC *tc)
|
|||
IntReg pc = tc->readMiscRegNoEffect(TCRestart);
|
||||
|
||||
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
|
||||
// tc->setPCEvent(pc, pc + 4, pc + 8);
|
||||
tc->setPC(pc);
|
||||
tc->setNextPC(pc + 4);
|
||||
tc->setNextNPC(pc + 8);
|
||||
tc->activate(0);
|
||||
|
||||
warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||
tc->readPC());
|
||||
warn("%i: Restoring thread %i in %s @ PC %x",
|
||||
curTick, tc->threadId(), tc->getCpuPtr()->name(),
|
||||
tc->readPC());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,42 +37,42 @@
|
|||
namespace MipsISA
|
||||
{
|
||||
|
||||
|
||||
void
|
||||
PTE::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(Mask);
|
||||
SERIALIZE_SCALAR(VPN);
|
||||
SERIALIZE_SCALAR(asid);
|
||||
SERIALIZE_SCALAR(G);
|
||||
SERIALIZE_SCALAR(PFN0);
|
||||
SERIALIZE_SCALAR(D0);
|
||||
SERIALIZE_SCALAR(V0);
|
||||
SERIALIZE_SCALAR(C0);
|
||||
SERIALIZE_SCALAR(PFN1);
|
||||
SERIALIZE_SCALAR(D1);
|
||||
SERIALIZE_SCALAR(V1);
|
||||
SERIALIZE_SCALAR(C1);
|
||||
SERIALIZE_SCALAR(AddrShiftAmount);
|
||||
SERIALIZE_SCALAR(OffsetMask);
|
||||
}
|
||||
|
||||
void
|
||||
PTE::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(Mask);
|
||||
UNSERIALIZE_SCALAR(VPN);
|
||||
UNSERIALIZE_SCALAR(asid);
|
||||
UNSERIALIZE_SCALAR(G);
|
||||
UNSERIALIZE_SCALAR(PFN0);
|
||||
UNSERIALIZE_SCALAR(D0);
|
||||
UNSERIALIZE_SCALAR(V0);
|
||||
UNSERIALIZE_SCALAR(C0);
|
||||
UNSERIALIZE_SCALAR(PFN1);
|
||||
UNSERIALIZE_SCALAR(D1);
|
||||
UNSERIALIZE_SCALAR(V1);
|
||||
UNSERIALIZE_SCALAR(C1);
|
||||
UNSERIALIZE_SCALAR(AddrShiftAmount);
|
||||
UNSERIALIZE_SCALAR(OffsetMask);
|
||||
}
|
||||
void
|
||||
PTE::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(Mask);
|
||||
SERIALIZE_SCALAR(VPN);
|
||||
SERIALIZE_SCALAR(asid);
|
||||
SERIALIZE_SCALAR(G);
|
||||
SERIALIZE_SCALAR(PFN0);
|
||||
SERIALIZE_SCALAR(D0);
|
||||
SERIALIZE_SCALAR(V0);
|
||||
SERIALIZE_SCALAR(C0);
|
||||
SERIALIZE_SCALAR(PFN1);
|
||||
SERIALIZE_SCALAR(D1);
|
||||
SERIALIZE_SCALAR(V1);
|
||||
SERIALIZE_SCALAR(C1);
|
||||
SERIALIZE_SCALAR(AddrShiftAmount);
|
||||
SERIALIZE_SCALAR(OffsetMask);
|
||||
}
|
||||
|
||||
void
|
||||
PTE::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(Mask);
|
||||
UNSERIALIZE_SCALAR(VPN);
|
||||
UNSERIALIZE_SCALAR(asid);
|
||||
UNSERIALIZE_SCALAR(G);
|
||||
UNSERIALIZE_SCALAR(PFN0);
|
||||
UNSERIALIZE_SCALAR(D0);
|
||||
UNSERIALIZE_SCALAR(V0);
|
||||
UNSERIALIZE_SCALAR(C0);
|
||||
UNSERIALIZE_SCALAR(PFN1);
|
||||
UNSERIALIZE_SCALAR(D1);
|
||||
UNSERIALIZE_SCALAR(V1);
|
||||
UNSERIALIZE_SCALAR(C1);
|
||||
UNSERIALIZE_SCALAR(AddrShiftAmount);
|
||||
UNSERIALIZE_SCALAR(OffsetMask);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,59 +41,62 @@
|
|||
|
||||
namespace MipsISA {
|
||||
|
||||
struct VAddr
|
||||
{
|
||||
static const int ImplBits = 43;
|
||||
static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
|
||||
static const Addr UnImplMask = ~ImplMask;
|
||||
struct VAddr
|
||||
{
|
||||
static const int ImplBits = 43;
|
||||
static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
|
||||
static const Addr UnImplMask = ~ImplMask;
|
||||
|
||||
VAddr(Addr a) : addr(a) {}
|
||||
Addr addr;
|
||||
operator Addr() const { return addr; }
|
||||
const VAddr &operator=(Addr a) { addr = a; return *this; }
|
||||
VAddr(Addr a) : addr(a) {}
|
||||
Addr addr;
|
||||
operator Addr() const { return addr; }
|
||||
const VAddr &operator=(Addr a) { addr = a; return *this; }
|
||||
|
||||
Addr vpn() const { return (addr & ImplMask) >> PageShift; }
|
||||
Addr page() const { return addr & Page_Mask; }
|
||||
Addr offset() const { return addr & PageOffset; }
|
||||
Addr vpn() const { return (addr & ImplMask) >> PageShift; }
|
||||
Addr page() const { return addr & Page_Mask; }
|
||||
Addr offset() const { return addr & PageOffset; }
|
||||
|
||||
Addr level3() const
|
||||
{ return MipsISA::PteAddr(addr >> PageShift); }
|
||||
Addr level2() const
|
||||
{ return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
|
||||
Addr level1() const
|
||||
{ return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
|
||||
};
|
||||
Addr level3() const
|
||||
{ return MipsISA::PteAddr(addr >> PageShift); }
|
||||
Addr level2() const
|
||||
{ return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
|
||||
Addr level1() const
|
||||
{ return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
|
||||
};
|
||||
|
||||
// ITB/DTB page table entry
|
||||
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 VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi)
|
||||
uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi
|
||||
// ITB/DTB page table entry
|
||||
struct PTE
|
||||
{
|
||||
Addr Mask;
|
||||
Addr VPN;
|
||||
uint8_t asid;
|
||||
|
||||
bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit
|
||||
bool G;
|
||||
|
||||
/* Contents of Entry Lo0 */
|
||||
Addr PFN0; // Physical Frame Number - Even
|
||||
bool D0; // Even entry Dirty Bit
|
||||
bool V0; // Even entry Valid Bit
|
||||
uint8_t C0; // Cache Coherency Bits - Even
|
||||
/* Contents of Entry Lo0 */
|
||||
Addr PFN0; // Physical Frame Number - Even
|
||||
bool D0; // Even entry Dirty Bit
|
||||
bool V0; // Even entry Valid Bit
|
||||
uint8_t C0; // Cache Coherency Bits - Even
|
||||
|
||||
/* Contents of Entry Lo1 */
|
||||
Addr PFN1; // Physical Frame Number - Odd
|
||||
bool D1; // Odd entry Dirty Bit
|
||||
bool V1; // Odd entry Valid Bit
|
||||
uint8_t C1; // Cache Coherency Bits (3 bits)
|
||||
/* Contents of Entry Lo1 */
|
||||
Addr PFN1; // Physical Frame Number - Odd
|
||||
bool D1; // Odd entry Dirty Bit
|
||||
bool V1; // Odd entry Valid Bit
|
||||
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 */
|
||||
int AddrShiftAmount;
|
||||
int OffsetMask;
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
int AddrShiftAmount;
|
||||
int OffsetMask;
|
||||
|
||||
bool Valid() { return (V0 | V1);};
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
bool Valid() { return (V0 | V1); };
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
};
|
||||
#endif // __ARCH_MIPS_PAGETABLE_H__
|
||||
|
|
|
@ -40,57 +40,66 @@ class ThreadContext;
|
|||
|
||||
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:
|
||||
ThreadContext * tc;
|
||||
//The extended machine instruction being generated
|
||||
ExtMachInst emi;
|
||||
return tc;
|
||||
}
|
||||
|
||||
public:
|
||||
Predecoder(ThreadContext * _tc) : tc(_tc)
|
||||
{}
|
||||
void
|
||||
setTC(ThreadContext *_tc)
|
||||
{
|
||||
tc = _tc;
|
||||
}
|
||||
|
||||
ThreadContext * getTC()
|
||||
{
|
||||
return tc;
|
||||
}
|
||||
void
|
||||
process()
|
||||
{
|
||||
}
|
||||
|
||||
void setTC(ThreadContext * _tc)
|
||||
{
|
||||
tc = _tc;
|
||||
}
|
||||
void
|
||||
reset()
|
||||
{}
|
||||
|
||||
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
|
||||
//when there is control flow.
|
||||
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
||||
{
|
||||
emi = inst;
|
||||
}
|
||||
bool
|
||||
extMachInstReady()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool needMoreBytes()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//This returns a constant reference to the ExtMachInst to avoid a copy
|
||||
const ExtMachInst &
|
||||
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__
|
||||
|
|
|
@ -42,35 +42,8 @@
|
|||
using namespace std;
|
||||
using namespace MipsISA;
|
||||
|
||||
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
||||
: tc(_tc)
|
||||
{
|
||||
// Addr addr = 0;
|
||||
|
||||
VirtualPort *vp;
|
||||
|
||||
vp = tc->getVirtPort();
|
||||
|
||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
|
||||
// panic("thread info not compiled into kernel\n");
|
||||
// thread_info_size = vp->readGtoH<int32_t>(addr);
|
||||
|
||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
|
||||
// panic("thread info not compiled into kernel\n");
|
||||
// task_struct_size = vp->readGtoH<int32_t>(addr);
|
||||
|
||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
|
||||
// panic("thread info not compiled into kernel\n");
|
||||
// task_off = vp->readGtoH<int32_t>(addr);
|
||||
|
||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
|
||||
// panic("thread info not compiled into kernel\n");
|
||||
// pid_off = vp->readGtoH<int32_t>(addr);
|
||||
|
||||
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
|
||||
// panic("thread info not compiled into kernel\n");
|
||||
// name_off = vp->readGtoH<int32_t>(addr);
|
||||
}
|
||||
ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
|
||||
{}
|
||||
|
||||
Addr
|
||||
ProcessInfo::task(Addr ksp) const
|
||||
|
@ -140,84 +113,17 @@ void
|
|||
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||
{
|
||||
tc = _tc;
|
||||
/* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
|
||||
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) {
|
||||
stack.push_back(user);
|
||||
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
|
||||
StackTrace::isEntry(Addr addr)
|
||||
{
|
||||
/* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
|
||||
return true;*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -305,7 +211,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
|||
int reg, disp;
|
||||
if (decodeStack(inst, disp)) {
|
||||
if (size) {
|
||||
// panic("decoding frame size again");
|
||||
return true;
|
||||
}
|
||||
size += disp;
|
||||
|
@ -313,7 +218,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
|||
if (!ra && reg == ReturnAddressReg) {
|
||||
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
||||
if (!ra) {
|
||||
// panic("no return address value pc=%#x\n", pc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -327,24 +231,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
|||
void
|
||||
StackTrace::dump()
|
||||
{
|
||||
StringWrap name(tc->getCpuPtr()->name());
|
||||
// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||
|
||||
DPRINTFN("------ Stack ------\n");
|
||||
|
||||
// string symbol;
|
||||
// for (int i = 0, size = stack.size(); i < size; ++i) {
|
||||
// Addr addr = stack[size - i - 1];
|
||||
// if (addr == user)
|
||||
// symbol = "user";
|
||||
// else if (addr == console)
|
||||
// symbol = "console";
|
||||
// else if (addr == unknown)
|
||||
// symbol = "unknown";
|
||||
// else
|
||||
// symtab->findSymbol(addr, symbol);
|
||||
|
||||
// DPRINTFN("%#x: %s\n", addr, symbol);
|
||||
// }
|
||||
panic("Stack trace dump not implemented.\n");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -45,22 +45,17 @@
|
|||
|
||||
using namespace LittleEndianGuest;
|
||||
|
||||
MipsSystem::MipsSystem(Params *p)
|
||||
: System(p)
|
||||
MipsSystem::MipsSystem(Params *p) : System(p)
|
||||
{
|
||||
|
||||
#if FULL_SYSTEM
|
||||
if (p->bare_iron == true) {
|
||||
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");
|
||||
}
|
||||
|
||||
Addr addr = 0;
|
||||
/* Comment out old Alpha Based Code
|
||||
|
||||
Don't need the console before we start looking at booting linux */
|
||||
|
||||
|
||||
consoleSymtab = new SymbolTable;
|
||||
|
||||
|
@ -76,7 +71,7 @@ MipsSystem::MipsSystem(Params *p)
|
|||
if (console == NULL)
|
||||
fatal("Could not load console file %s", params()->console);
|
||||
//Load program sections into memory
|
||||
console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
|
||||
console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
|
||||
|
||||
//load symbols
|
||||
if (!console->loadGlobalSymbols(consoleSymtab))
|
||||
|
@ -110,100 +105,42 @@ MipsSystem::MipsSystem(Params *p)
|
|||
if (consoleSymtab->findAddress("m5_rpb", addr)) {
|
||||
uint64_t data;
|
||||
data = htog(params()->system_type);
|
||||
virtPort.write(addr+0x50, data);
|
||||
virtPort.write(addr + 0x50, data);
|
||||
data = htog(params()->system_rev);
|
||||
virtPort.write(addr+0x58, data);
|
||||
} else
|
||||
virtPort.write(addr + 0x58, data);
|
||||
} else {
|
||||
panic("could not find hwrpb\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
MipsSystem::fixFuncEventAddr(Addr 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;
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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
|
||||
|
||||
bool
|
||||
MipsSystem::breakpoint()
|
||||
{
|
||||
return 0;
|
||||
// return remoteGDB[0]->trap(MIPS_KENTRY_INT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MipsSystem::serialize(std::ostream &os)
|
||||
{
|
||||
System::serialize(os);
|
||||
// consoleSymtab->serialize("console_symtab", os);
|
||||
}
|
||||
|
||||
|
||||
|
@ -211,7 +148,6 @@ void
|
|||
MipsSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
System::unserialize(cp,section);
|
||||
// consoleSymtab->unserialize("console_symtab", cp, section);
|
||||
}
|
||||
|
||||
MipsSystem *
|
||||
|
|
|
@ -54,10 +54,10 @@ class MipsSystem : public System
|
|||
|
||||
virtual bool breakpoint();
|
||||
|
||||
/**
|
||||
* Serialization stuff
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Serialization stuff
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
|
@ -89,7 +89,8 @@ class MipsSystem : public System
|
|||
#if FULL_SYSTEM
|
||||
/** Add a function-based event to the console code. */
|
||||
template <class T>
|
||||
T *addConsoleFuncEvent(const char *lbl)
|
||||
T *
|
||||
addConsoleFuncEvent(const char *lbl)
|
||||
{
|
||||
return addFuncEvent<T>(consoleSymtab, lbl);
|
||||
}
|
||||
|
|
|
@ -56,16 +56,14 @@ using namespace MipsISA;
|
|||
// MIPS TLB
|
||||
//
|
||||
|
||||
#define MODE2MASK(X) (1 << (X))
|
||||
|
||||
static inline mode_type
|
||||
getOperatingMode(MiscReg Stat)
|
||||
{
|
||||
if((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
|
||||
if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
|
||||
return mode_kernel;
|
||||
} else if((Stat & 0x18) == 0x8) {
|
||||
} else if ((Stat & 0x18) == 0x8) {
|
||||
return mode_supervisor;
|
||||
} else if((Stat & 0x18) == 0x10) {
|
||||
} else if ((Stat & 0x18) == 0x10) {
|
||||
return mode_user;
|
||||
} else {
|
||||
return mode_number;
|
||||
|
@ -76,9 +74,9 @@ getOperatingMode(MiscReg Stat)
|
|||
TLB::TLB(const Params *p)
|
||||
: BaseTLB(p), size(p->size), nlu(0)
|
||||
{
|
||||
table = new MipsISA::PTE[size];
|
||||
memset(table, 0, sizeof(MipsISA::PTE[size]));
|
||||
smallPages=0;
|
||||
table = new PTE[size];
|
||||
memset(table, 0, sizeof(PTE[size]));
|
||||
smallPages = 0;
|
||||
}
|
||||
|
||||
TLB::~TLB()
|
||||
|
@ -92,23 +90,23 @@ MipsISA::PTE *
|
|||
TLB::lookup(Addr vpn, uint8_t asn) const
|
||||
{
|
||||
// assume not found...
|
||||
MipsISA::PTE *retval = NULL;
|
||||
PTE *retval = NULL;
|
||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||
if (i != lookupTable.end()) {
|
||||
while (i->first == vpn) {
|
||||
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 */
|
||||
Addr Mask = pte->Mask;
|
||||
Addr InvMask = ~Mask;
|
||||
Addr VPN = pte->VPN;
|
||||
// warn("Valid: %d - %d\n",pte->V0,pte->V1);
|
||||
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
|
||||
{ // We have a VPN + ASID Match
|
||||
if (((vpn & InvMask) == (VPN & InvMask)) &&
|
||||
(pte->G || (asn == pte->asid))) {
|
||||
// We have a VPN + ASID Match
|
||||
retval = pte;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -118,119 +116,96 @@ TLB::lookup(Addr vpn, uint8_t asn) const
|
|||
return retval;
|
||||
}
|
||||
|
||||
MipsISA::PTE* TLB::getEntry(unsigned Index) const
|
||||
MipsISA::PTE*
|
||||
TLB::getEntry(unsigned Index) const
|
||||
{
|
||||
// Make sure that Index is valid
|
||||
assert(Index<size);
|
||||
return &table[Index];
|
||||
}
|
||||
|
||||
int TLB::probeEntry(Addr vpn,uint8_t asn) const
|
||||
int
|
||||
TLB::probeEntry(Addr vpn, uint8_t asn) const
|
||||
{
|
||||
// assume not found...
|
||||
MipsISA::PTE *retval = NULL;
|
||||
int Ind=-1;
|
||||
PTE *retval = NULL;
|
||||
int Ind = -1;
|
||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||
if (i != lookupTable.end()) {
|
||||
while (i->first == vpn) {
|
||||
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 */
|
||||
Addr Mask = pte->Mask;
|
||||
Addr InvMask = ~Mask;
|
||||
Addr VPN = pte->VPN;
|
||||
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
|
||||
{ // We have a VPN + ASID Match
|
||||
Addr VPN = pte->VPN;
|
||||
if (((vpn & InvMask) == (VPN & InvMask)) &&
|
||||
(pte->G || (asn == pte->asid))) {
|
||||
// We have a VPN + ASID Match
|
||||
retval = pte;
|
||||
Ind = index;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
|
||||
return Ind;
|
||||
}
|
||||
Fault inline
|
||||
|
||||
inline Fault
|
||||
TLB::checkCacheability(RequestPtr &req)
|
||||
{
|
||||
Addr VAddrUncacheable = 0xA0000000;
|
||||
// In MIPS, cacheability is controlled by certain bits of the virtual address
|
||||
// or by the TLB entry
|
||||
if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
|
||||
// mark request as 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);
|
||||
Addr VAddrUncacheable = 0xA0000000;
|
||||
// In MIPS, cacheability is controlled by certain bits of the virtual
|
||||
// address or by the TLB entry
|
||||
if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
|
||||
// mark request as uncacheable
|
||||
req->setFlags(Request::UNCACHEABLE);
|
||||
}
|
||||
table[Index]=pte;
|
||||
// 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);
|
||||
}
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
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
|
||||
void
|
||||
TLB::insert(Addr addr, MipsISA::PTE &pte)
|
||||
TLB::insert(Addr addr, PTE &pte)
|
||||
{
|
||||
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();
|
||||
*/
|
||||
fatal("TLB Insert not yet implemented\n");
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flushAll()
|
||||
{
|
||||
DPRINTF(TLB, "flushAll\n");
|
||||
memset(table, 0, sizeof(MipsISA::PTE[size]));
|
||||
memset(table, 0, sizeof(PTE[size]));
|
||||
lookupTable.clear();
|
||||
nlu = 0;
|
||||
}
|
||||
|
@ -328,68 +303,66 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
|||
Process * p = tc->getProcessPtr();
|
||||
|
||||
Fault fault = p->pTable->translate(req);
|
||||
if(fault != NoFault)
|
||||
if (fault != NoFault)
|
||||
return fault;
|
||||
|
||||
return NoFault;
|
||||
#else
|
||||
if(MipsISA::IsKSeg0(req->getVaddr()))
|
||||
{
|
||||
// Address will not be translated through TLB, set response, and go!
|
||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
||||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
|
||||
{
|
||||
if (IsKSeg0(req->getVaddr())) {
|
||||
// Address will not be translated through TLB, set response, and go!
|
||||
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||
if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
|
||||
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();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
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();
|
||||
if(req->isMisaligned()){ // Unaligned address!
|
||||
AddressErrorFault *Flt = new AddressErrorFault();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
return Flt;
|
||||
}
|
||||
MipsISA::PTE *pte = lookup(VPN,Asid);
|
||||
if(pte != NULL)
|
||||
{// Ok, found something
|
||||
PTE *pte = lookup(VPN,Asid);
|
||||
if (pte != NULL) {
|
||||
// Ok, found something
|
||||
/* Check for valid bits */
|
||||
int EvenOdd;
|
||||
bool Valid;
|
||||
if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){
|
||||
// Check even bits
|
||||
Valid = pte->V0;
|
||||
EvenOdd = 0;
|
||||
if ((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) == 0) {
|
||||
// Check even bits
|
||||
Valid = pte->V0;
|
||||
EvenOdd = 0;
|
||||
} else {
|
||||
// Check odd bits
|
||||
Valid = pte->V1;
|
||||
EvenOdd = 1;
|
||||
// Check odd bits
|
||||
Valid = pte->V1;
|
||||
EvenOdd = 1;
|
||||
}
|
||||
|
||||
if(Valid == false)
|
||||
{//Invalid entry
|
||||
if (Valid == false) {
|
||||
//Invalid entry
|
||||
ItbInvalidFault *Flt = new ItbInvalidFault();
|
||||
/* EntryHi VPN, ASID fields must be set */
|
||||
Flt->EntryHi_Asid = Asid;
|
||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
||||
Flt->EntryHi_VPN2 = (VPN >> 2);
|
||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||
|
||||
/* BadVAddr must be set */
|
||||
|
@ -398,43 +371,36 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
|||
/* Context must be set */
|
||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||
return Flt;
|
||||
}
|
||||
else
|
||||
{// Ok, this is really a match, set paddr
|
||||
// hits++;
|
||||
} else {
|
||||
// Ok, this is really a match, set paddr
|
||||
Addr PAddr;
|
||||
if(EvenOdd == 0){
|
||||
if (EvenOdd == 0) {
|
||||
PAddr = pte->PFN0;
|
||||
}else{
|
||||
} else {
|
||||
PAddr = pte->PFN1;
|
||||
}
|
||||
PAddr >>= (pte->AddrShiftAmount-12);
|
||||
PAddr >>= (pte->AddrShiftAmount - 12);
|
||||
PAddr <<= pte->AddrShiftAmount;
|
||||
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
||||
req->setPaddr(PAddr);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Didn't find any match, return a TLB Refill Exception
|
||||
// misses++;
|
||||
ItbRefillFault *Flt=new ItbRefillFault();
|
||||
/* EntryHi VPN, ASID fields must be set */
|
||||
Flt->EntryHi_Asid = Asid;
|
||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||
} else {
|
||||
// Didn't find any match, return a TLB Refill Exception
|
||||
ItbRefillFault *Flt=new ItbRefillFault();
|
||||
/* 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();
|
||||
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
|
||||
/* Context must be set */
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -457,131 +423,118 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
|
|||
Process * p = tc->getProcessPtr();
|
||||
|
||||
Fault fault = p->pTable->translate(req);
|
||||
if(fault != NoFault)
|
||||
if (fault != NoFault)
|
||||
return fault;
|
||||
|
||||
return NoFault;
|
||||
#else
|
||||
if(MipsISA::IsKSeg0(req->getVaddr()))
|
||||
{
|
||||
// Address will not be translated through TLB, set response, and go!
|
||||
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
|
||||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
|
||||
{
|
||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
if (IsKSeg0(req->getVaddr())) {
|
||||
// Address will not be translated through TLB, set response, and go!
|
||||
req->setPaddr(KSeg02Phys(req->getVaddr()));
|
||||
if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
|
||||
req->isMisaligned()) {
|
||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
|
||||
return Flt;
|
||||
return Flt;
|
||||
}
|
||||
}
|
||||
else if(MipsISA::IsKSeg1(req->getVaddr()))
|
||||
{
|
||||
} else if(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=((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
||||
if(smallPages==1){
|
||||
VPN=((req->getVaddr() >> 11));
|
||||
}
|
||||
uint8_t Asid = req->getAsid();
|
||||
MipsISA::PTE *pte = lookup(VPN,Asid);
|
||||
if(req->isMisaligned()){ // Unaligned address!
|
||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
return Flt;
|
||||
}
|
||||
if(pte != NULL)
|
||||
{// Ok, found something
|
||||
/* Check for valid bits */
|
||||
int EvenOdd;
|
||||
bool Valid;
|
||||
bool Dirty;
|
||||
if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){
|
||||
// Check even bits
|
||||
Valid = pte->V0;
|
||||
Dirty = pte->D0;
|
||||
EvenOdd = 0;
|
||||
|
||||
} else {
|
||||
// Check odd bits
|
||||
Valid = pte->V1;
|
||||
Dirty = pte->D1;
|
||||
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;
|
||||
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 = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
|
||||
if (smallPages == 1) {
|
||||
VPN = ((req->getVaddr() >> 11));
|
||||
}
|
||||
uint8_t Asid = req->getAsid();
|
||||
PTE *pte = lookup(VPN, Asid);
|
||||
if (req->isMisaligned()) {
|
||||
// Unaligned address!
|
||||
StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
return Flt;
|
||||
}
|
||||
if (pte != NULL) {
|
||||
// Ok, found something
|
||||
/* Check for valid bits */
|
||||
int EvenOdd;
|
||||
bool Valid;
|
||||
bool Dirty;
|
||||
if (((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) == 0) {
|
||||
// Check even bits
|
||||
Valid = pte->V0;
|
||||
Dirty = pte->D0;
|
||||
EvenOdd = 0;
|
||||
} else {
|
||||
// Check odd bits
|
||||
Valid = pte->V1;
|
||||
Dirty = pte->D1;
|
||||
EvenOdd = 1;
|
||||
}
|
||||
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 */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
|
||||
/* Context must be set */
|
||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||
return Flt;
|
||||
/* Context must be set */
|
||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||
|
||||
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;
|
||||
if(EvenOdd == 0){
|
||||
PAddr = pte->PFN0;
|
||||
}else{
|
||||
PAddr = pte->PFN1;
|
||||
}
|
||||
PAddr >>= (pte->AddrShiftAmount-12);
|
||||
PAddr <<= pte->AddrShiftAmount;
|
||||
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
||||
req->setPaddr(PAddr);
|
||||
Addr PAddr;
|
||||
if (EvenOdd == 0) {
|
||||
PAddr = pte->PFN0;
|
||||
} else {
|
||||
PAddr = pte->PFN1;
|
||||
}
|
||||
PAddr >>= (pte->AddrShiftAmount - 12);
|
||||
PAddr <<= pte->AddrShiftAmount;
|
||||
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
|
||||
req->setPaddr(PAddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Didn't find any match, return a TLB Refill Exception
|
||||
// misses++;
|
||||
DtbRefillFault *Flt=new DtbRefillFault();
|
||||
/* EntryHi VPN, ASID fields must be set */
|
||||
Flt->EntryHi_Asid = Asid;
|
||||
Flt->EntryHi_VPN2 = (VPN>>2);
|
||||
Flt->EntryHi_VPN2X = (VPN & 0x3);
|
||||
} else {
|
||||
// Didn't find any match, return a TLB Refill Exception
|
||||
DtbRefillFault *Flt = new DtbRefillFault();
|
||||
/* 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();
|
||||
|
||||
/* BadVAddr must be set */
|
||||
Flt->BadVAddr = req->getVaddr();
|
||||
|
||||
/* Context must be set */
|
||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||
return Flt;
|
||||
/* Context must be set */
|
||||
Flt->Context_BadVPN2 = (VPN >> 2);
|
||||
return Flt;
|
||||
}
|
||||
}
|
||||
return checkCacheability(req);
|
||||
|
@ -609,7 +562,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
|||
MipsISA::PTE &
|
||||
TLB::index(bool advance)
|
||||
{
|
||||
MipsISA::PTE *pte = &table[nlu];
|
||||
PTE *pte = &table[nlu];
|
||||
|
||||
if (advance)
|
||||
nextnlu();
|
||||
|
@ -620,5 +573,5 @@ TLB::index(bool advance)
|
|||
MipsISA::TLB *
|
||||
MipsTLBParams::create()
|
||||
{
|
||||
return new MipsISA::TLB(this);
|
||||
return new TLB(this);
|
||||
}
|
||||
|
|
|
@ -35,42 +35,43 @@
|
|||
|
||||
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
|
||||
enum ConvertType{
|
||||
SINGLE_TO_DOUBLE,
|
||||
SINGLE_TO_WORD,
|
||||
SINGLE_TO_LONG,
|
||||
typedef uint64_t LargestRead;
|
||||
|
||||
DOUBLE_TO_SINGLE,
|
||||
DOUBLE_TO_WORD,
|
||||
DOUBLE_TO_LONG,
|
||||
//used in FP convert & round function
|
||||
enum ConvertType{
|
||||
SINGLE_TO_DOUBLE,
|
||||
SINGLE_TO_WORD,
|
||||
SINGLE_TO_LONG,
|
||||
|
||||
LONG_TO_SINGLE,
|
||||
LONG_TO_DOUBLE,
|
||||
LONG_TO_WORD,
|
||||
LONG_TO_PS,
|
||||
DOUBLE_TO_SINGLE,
|
||||
DOUBLE_TO_WORD,
|
||||
DOUBLE_TO_LONG,
|
||||
|
||||
WORD_TO_SINGLE,
|
||||
WORD_TO_DOUBLE,
|
||||
WORD_TO_LONG,
|
||||
WORD_TO_PS,
|
||||
LONG_TO_SINGLE,
|
||||
LONG_TO_DOUBLE,
|
||||
LONG_TO_WORD,
|
||||
LONG_TO_PS,
|
||||
|
||||
PL_TO_SINGLE,
|
||||
PU_TO_SINGLE
|
||||
};
|
||||
WORD_TO_SINGLE,
|
||||
WORD_TO_DOUBLE,
|
||||
WORD_TO_LONG,
|
||||
WORD_TO_PS,
|
||||
|
||||
//used in FP convert & round function
|
||||
enum RoundMode{
|
||||
RND_ZERO,
|
||||
RND_DOWN,
|
||||
RND_UP,
|
||||
RND_NEAREST
|
||||
};
|
||||
PL_TO_SINGLE,
|
||||
PU_TO_SINGLE
|
||||
};
|
||||
|
||||
//used in FP convert & round function
|
||||
enum RoundMode{
|
||||
RND_ZERO,
|
||||
RND_DOWN,
|
||||
RND_UP,
|
||||
RND_NEAREST
|
||||
};
|
||||
|
||||
struct CoreSpecific {
|
||||
/* Note: It looks like it will be better to allow simulator users
|
||||
|
@ -81,7 +82,8 @@ struct CoreSpecific {
|
|||
-jpp
|
||||
*/
|
||||
// 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_IPPCI; // Page 94, IP Performance Counter Interrupt
|
||||
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_ProcessorID; // 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_AT; //Page 109
|
||||
unsigned CP0_Config_AR; //Page 109
|
||||
|
|
|
@ -45,87 +45,88 @@ class ThreadContext;
|
|||
|
||||
namespace MipsISA {
|
||||
|
||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Floating Point Utility Functions
|
||||
//
|
||||
uint64_t fpConvert(ConvertType cvt_type, double fp_val);
|
||||
double roundFP(double val, int digits);
|
||||
double truncFP(double val);
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Floating Point Utility Functions
|
||||
//
|
||||
uint64_t fpConvert(ConvertType cvt_type, double fp_val);
|
||||
double roundFP(double val, int digits);
|
||||
double truncFP(double val);
|
||||
|
||||
bool getCondCode(uint32_t fcsr, int cc);
|
||||
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
|
||||
uint32_t genInvalidVector(uint32_t fcsr);
|
||||
bool getCondCode(uint32_t fcsr, int cc);
|
||||
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
|
||||
uint32_t genInvalidVector(uint32_t fcsr);
|
||||
|
||||
bool isNan(void *val_ptr, int size);
|
||||
bool isQnan(void *val_ptr, int size);
|
||||
bool isSnan(void *val_ptr, int size);
|
||||
bool isNan(void *val_ptr, int size);
|
||||
bool isQnan(void *val_ptr, int size);
|
||||
bool isSnan(void *val_ptr, int size);
|
||||
|
||||
static inline bool
|
||||
inUserMode(ThreadContext *tc)
|
||||
{
|
||||
MiscReg Stat = tc->readMiscReg(MipsISA::Status);
|
||||
MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
|
||||
static inline bool
|
||||
inUserMode(ThreadContext *tc)
|
||||
{
|
||||
MiscReg Stat = tc->readMiscReg(MipsISA::Status);
|
||||
MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
|
||||
|
||||
if((Stat & 0x10000006) == 0 // EXL, ERL or CU0 set, CP0 accessible
|
||||
&& (Dbg & 0x40000000) == 0 // DM bit set, CP0 accessible
|
||||
&& (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
|
||||
// Unable to use Status_CU0, etc directly, using bitfields & masks
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if ((Stat & 0x10000006) == 0 && // EXL, ERL or CU0 set, CP0 accessible
|
||||
(Dbg & 0x40000000) == 0 && // DM bit set, CP0 accessible
|
||||
(Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
|
||||
// Unable to use Status_CU0, etc directly, using bitfields & masks
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Instruction address compression hooks
|
||||
static inline Addr realPCToFetchPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
// Instruction address compression hooks
|
||||
static inline Addr realPCToFetchPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline Addr fetchPCToRealPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
static inline Addr fetchPCToRealPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
// the size of "fetched" instructions (not necessarily the size
|
||||
// of real instructions for PISA)
|
||||
static inline size_t fetchInstSize() {
|
||||
return sizeof(MachInst);
|
||||
}
|
||||
// the size of "fetched" instructions (not necessarily the size
|
||||
// of real instructions for PISA)
|
||||
static inline size_t fetchInstSize() {
|
||||
return sizeof(MachInst);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Register File Utility Functions
|
||||
//
|
||||
static inline MachInst makeRegisterCopy(int dest, int src) {
|
||||
panic("makeRegisterCopy not implemented");
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Register File Utility Functions
|
||||
//
|
||||
static inline MachInst makeRegisterCopy(int dest, int src) {
|
||||
panic("makeRegisterCopy not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class CPU>
|
||||
void zeroRegisters(CPU *cpu);
|
||||
template <class CPU>
|
||||
void zeroRegisters(CPU *cpu);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
inline Addr
|
||||
TruncPage(Addr addr)
|
||||
{ return addr & ~(PageBytes - 1); }
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
inline Addr
|
||||
TruncPage(Addr addr)
|
||||
{ return addr & ~(PageBytes - 1); }
|
||||
|
||||
inline Addr
|
||||
RoundPage(Addr addr)
|
||||
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
||||
inline Addr
|
||||
RoundPage(Addr addr)
|
||||
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPU Utility
|
||||
//
|
||||
void startupCPU(ThreadContext *tc, int cpuId);
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPU Utility
|
||||
//
|
||||
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))
|
||||
paddr = MipsISA::KSeg12Phys(vaddr);
|
||||
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);
|
||||
|
||||
|
@ -63,7 +64,6 @@ MipsISA::vtophys(Addr vaddr)
|
|||
Addr
|
||||
MipsISA::vtophys(ThreadContext *tc, Addr addr)
|
||||
{
|
||||
|
||||
fatal("VTOPHYS: Unimplemented on MIPS\n");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue