MIPS: Many style fixes.

White space, commented out code, some other minor fixes.
This commit is contained in:
Gabe Black 2009-07-21 01:08:53 -07:00
parent dc0a017ed0
commit 7548082d3b
28 changed files with 1017 additions and 1494 deletions

View file

@ -28,20 +28,8 @@
* Authors: Jaidev Patwardhan * Authors: Jaidev Patwardhan
*/ */
#include "arch/vtophys.hh"
#include "arch/mips/bare_iron/system.hh" #include "arch/mips/bare_iron/system.hh"
#include "arch/mips/system.hh"
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "dev/platform.hh"
#include "mem/physical.hh"
#include "mem/port.hh"
#include "params/BareIronMipsSystem.hh" #include "params/BareIronMipsSystem.hh"
#include "sim/byteswap.hh"
using namespace std;
using namespace MipsISA;
BareIronMipsSystem::BareIronMipsSystem(Params *p) BareIronMipsSystem::BareIronMipsSystem(Params *p)
: MipsSystem(p) : MipsSystem(p)

View file

@ -31,11 +31,6 @@
#ifndef __ARCH_MIPS_BARE_IRON_SYSTEM_HH__ #ifndef __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
#define __ARCH_MIPS_BARE_IRON_SYSTEM_HH__ #define __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
class ThreadContext;
class BreakPCEvent;
class IdleStartEvent;
#include "arch/mips/system.hh" #include "arch/mips/system.hh"
#include "params/BareIronMipsSystem.hh" #include "params/BareIronMipsSystem.hh"
@ -46,15 +41,9 @@ class IdleStartEvent;
*/ */
class BareIronMipsSystem : public MipsSystem class BareIronMipsSystem : public MipsSystem
{ {
private:
public: public:
static const int CommandLineSize = 256; static const int CommandLineSize = 256;
private:
public:
BareIronMipsSystem(Params *p); BareIronMipsSystem(Params *p);
~BareIronMipsSystem(); ~BareIronMipsSystem();
}; };

View file

@ -85,7 +85,6 @@ FaultName ThreadFault::_name = "Thread Fault";
FaultVect ThreadFault::_vect = 0x00F1; FaultVect ThreadFault::_vect = 0x00F1;
FaultStat ThreadFault::_count; FaultStat ThreadFault::_count;
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception"; FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
FaultVect ArithmeticFault::_vect = 0x180; FaultVect ArithmeticFault::_vect = 0x180;
FaultStat ArithmeticFault::_count; FaultStat ArithmeticFault::_count;
@ -106,7 +105,6 @@ FaultName BreakpointFault::_name = "Breakpoint";
FaultVect BreakpointFault::_vect = 0x0180; FaultVect BreakpointFault::_vect = 0x0180;
FaultStat BreakpointFault::_count; FaultStat BreakpointFault::_count;
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)"; FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
FaultVect ItbInvalidFault::_vect = 0x0180; FaultVect ItbInvalidFault::_vect = 0x0180;
FaultStat ItbInvalidFault::_count; FaultStat ItbInvalidFault::_count;
@ -168,344 +166,366 @@ FaultVect DspStateDisabledFault::_vect = 0x001a;
FaultStat DspStateDisabledFault::_count; FaultStat DspStateDisabledFault::_count;
#if FULL_SYSTEM #if FULL_SYSTEM
void MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc) void
MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
{ {
tc->setPC(HandlerBase); tc->setPC(HandlerBase);
tc->setNextPC(HandlerBase+sizeof(MachInst)); tc->setNextPC(HandlerBase + sizeof(MachInst));
tc->setNextNPC(HandlerBase+2*sizeof(MachInst)); tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
} }
void MipsFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode) void
MipsFault::setExceptionState(ThreadContext *tc, uint8_t ExcCode)
{ {
// modify SRS Ctl - Save CSS, put ESS into CSS // modify SRS Ctl - Save CSS, put ESS into CSS
MiscReg stat = tc->readMiscReg(MipsISA::Status); MiscReg stat = tc->readMiscReg(MipsISA::Status);
if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1) if (bits(stat, Status_EXL) != 1 && bits(stat, Status_BEV) != 1) {
{ // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
// SRS Ctl is modified only if Status_EXL and Status_BEV are not set MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl); uint8_t CSS, ESS;
uint8_t CSS,ESS; CSS = bits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO);
CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO); ESS = bits(srs, SRSCtl_ESS_HI, SRSCtl_ESS_LO);
ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO); // Move CSS to PSS
// Move CSS to PSS replaceBits(srs, SRSCtl_PSS_HI, SRSCtl_PSS_LO, CSS);
replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS); // Move ESS to CSS
// Move ESS to CSS replaceBits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO, ESS);
replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS); tc->setMiscRegNoEffect(MipsISA::SRSCtl, srs);
tc->setMiscRegNoEffect(MipsISA::SRSCtl,srs);
//tc->setShadowSet(ESS);
} }
// set EXL bit (don't care if it is already set!) // set EXL bit (don't care if it is already set!)
replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1); replaceBits(stat, Status_EXL_HI, Status_EXL_LO, 1);
tc->setMiscRegNoEffect(MipsISA::Status,stat); tc->setMiscRegNoEffect(MipsISA::Status, stat);
// write EPC // write EPC
// warn("Set EPC to %x\n",tc->readPC()); // CHECK ME or FIXME or FIX ME or POSSIBLE HACK
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK // Check to see if the exception occurred in the branch delay slot
// Check to see if the exception occurred in the branch delay slot DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
DPRINTF(MipsPRA,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC()); tc->readPC(), tc->readNextPC(), tc->readNextNPC());
int C_BD=0; int C_BD = 0;
if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){ if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC()-sizeof(MachInst)); tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC() - sizeof(MachInst));
// In the branch delay slot? set CAUSE_31 // In the branch delay slot? set CAUSE_31
C_BD = 1; C_BD = 1;
} else { } else {
tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC()); tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC());
// In the branch delay slot? reset CAUSE_31 // In the branch delay slot? reset CAUSE_31
C_BD = 0; C_BD = 0;
} }
// Set Cause_EXCCODE field
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode);
replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD);
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0);
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
// Set Cause_EXCCODE field
MiscReg cause = tc->readMiscReg(MipsISA::Cause);
replaceBits(cause, Cause_EXCCODE_HI, Cause_EXCCODE_LO, ExcCode);
replaceBits(cause, Cause_BD_HI, Cause_BD_LO,C_BD);
replaceBits(cause, Cause_CE_HI, Cause_CE_LO,0);
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
} }
void ArithmeticFault::invoke(ThreadContext *tc) void
ArithmeticFault::invoke(ThreadContext *tc)
{ {
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc,0xC); setExceptionState(tc, 0xC);
// Set new PC
Addr HandlerBase;
MiscReg stat = tc->readMiscReg(MipsISA::Status);
// Here, the handler is dependent on BEV, which is not modified by setExceptionState()
if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
}else{
HandlerBase = 0xBFC00200;
}
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
}
void StoreAddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
setExceptionState(tc,0x5);
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
}
void TrapFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
// warn("%s encountered.\n", name());
setExceptionState(tc,0xD);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
}
void BreakpointFault::invoke(ThreadContext *tc)
{
setExceptionState(tc,0x9);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
}
void DtbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
// warn("%s encountered.\n", name());
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
setExceptionState(tc,0x3);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
}
void AddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
setExceptionState(tc,0x4);
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
}
void ItbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
setExceptionState(tc,0x2);
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
}
void ItbRefillFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered (%x).\n", name(),BadVAddr);
Addr HandlerBase;
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
MiscReg stat = tc->readMiscReg(MipsISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
}else{
HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
}
setExceptionState(tc,0x2);
setHandlerPC(HandlerBase,tc);
}
void DtbRefillFault::invoke(ThreadContext *tc)
{
// Set new PC
DPRINTF(MipsPRA,"%s encountered.\n", name());
Addr HandlerBase;
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
MiscReg stat = tc->readMiscReg(MipsISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
}else{
HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
}
setExceptionState(tc,0x3);
setHandlerPC(HandlerBase,tc);
}
void TLBModifiedFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
// Set new PC // Set new PC
Addr HandlerBase; Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector MiscReg stat = tc->readMiscReg(MipsISA::Status);
setExceptionState(tc,0x1); // Here, the handler is dependent on BEV, which is not modified by
setHandlerPC(HandlerBase,tc); // setExceptionState()
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC)); if (bits(stat, Status_BEV) == 0 ) {
// See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
} else {
HandlerBase = 0xBFC00200;
}
setHandlerPC(HandlerBase, tc);
} }
void SystemCallFault::invoke(ThreadContext *tc) void
StoreAddressErrorFault::invoke(ThreadContext *tc)
{ {
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc,0x8); setExceptionState(tc, 0x5);
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
// Set new PC // Set new PC
Addr HandlerBase; Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc); HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
// warn("Exception Handler At: %x \n",HandlerBase); setHandlerPC(HandlerBase, tc);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC)); }
void
TrapFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc, 0xD);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
}
void
BreakpointFault::invoke(ThreadContext *tc)
{
setExceptionState(tc, 0x9);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
}
void
DtbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
setExceptionState(tc, 0x3);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase,tc);
}
void
AddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc, 0x4);
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
}
void
ItbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc, 0x2);
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase,tc);
DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",
HandlerBase, tc->readMiscReg(MipsISA::EPC));
}
void
ItbRefillFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), BadVAddr);
Addr HandlerBase;
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
MiscReg stat = tc->readMiscReg(MipsISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
// See MIPS ARM Vol 3, Revision 2, Page 38
if (bits(stat, Status_EXL) == 1) {
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
} else {
// Offset 0x000
HandlerBase = tc->readMiscReg(MipsISA::EBase);
}
setExceptionState(tc, 0x2);
setHandlerPC(HandlerBase, tc);
}
void
DtbRefillFault::invoke(ThreadContext *tc)
{
// Set new PC
DPRINTF(MipsPRA, "%s encountered.\n", name());
Addr HandlerBase;
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
MiscReg stat = tc->readMiscReg(MipsISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
// See MIPS ARM Vol 3, Revision 2, Page 38
if(bits(stat, Status_EXL) == 1) {
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
} else {
// Offset 0x000
HandlerBase = tc->readMiscReg(MipsISA::EBase);
}
setExceptionState(tc, 0x3);
setHandlerPC(HandlerBase, tc);
}
void
TLBModifiedFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setExceptionState(tc, 0x1);
setHandlerPC(HandlerBase, tc);
} }
void InterruptFault::invoke(ThreadContext *tc) void
SystemCallFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc, 0x8);
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
}
void
InterruptFault::invoke(ThreadContext *tc)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc,0x0A); setExceptionState(tc, 0x0A);
Addr HandlerBase; Addr HandlerBase;
uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause), Cause_IV);
if (IV) {
// Offset 200 for release 2
HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
} else {
//Ofset at 180 for release 1
HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
}
uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause),Cause_IV); setHandlerPC(HandlerBase, tc);
if (IV)// Offset 200 for release 2
HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
else//Ofset at 180 for release 1
HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
setHandlerPC(HandlerBase,tc);
#endif #endif
} }
#endif // FULL_SYSTEM #endif // FULL_SYSTEM
void ResetFault::invoke(ThreadContext *tc) void
ResetFault::invoke(ThreadContext *tc)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
/* All reset activity must be invoked from here */ /* All reset activity must be invoked from here */
tc->setPC(vect()); tc->setPC(vect());
tc->setNextPC(vect()+sizeof(MachInst)); tc->setNextPC(vect() + sizeof(MachInst));
tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst)); tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
DPRINTF(MipsPRA,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC()); DPRINTF(MipsPRA, "(%x) - ResetFault::invoke : PC set to %x",
(unsigned)tc, (unsigned)tc->readPC());
#endif #endif
// Set Coprocessor 1 (Floating Point) To Usable // Set Coprocessor 1 (Floating Point) To Usable
tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000); tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
} }
void ReservedInstructionFault::invoke(ThreadContext *tc) void
ReservedInstructionFault::invoke(ThreadContext *tc)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc,0x0A); setExceptionState(tc, 0x0A);
Addr HandlerBase; Addr HandlerBase;
HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase); // Offset 0x180 - General Exception Vector // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc); HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
#else #else
panic("%s encountered.\n", name()); panic("%s encountered.\n", name());
#endif #endif
} }
void ThreadFault::invoke(ThreadContext *tc) void
ThreadFault::invoke(ThreadContext *tc)
{ {
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
panic("%s encountered.\n", name()); panic("%s encountered.\n", name());
} }
void DspStateDisabledFault::invoke(ThreadContext *tc) void
DspStateDisabledFault::invoke(ThreadContext *tc)
{ {
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
panic("%s encountered.\n", name()); panic("%s encountered.\n", name());
} }
void CoprocessorUnusableFault::invoke(ThreadContext *tc) void
CoprocessorUnusableFault::invoke(ThreadContext *tc)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
DPRINTF(MipsPRA,"%s encountered.\n", name()); DPRINTF(MipsPRA, "%s encountered.\n", name());
setExceptionState(tc,0xb); setExceptionState(tc, 0xb);
/* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */ // The ID of the coprocessor causing the exception is stored in
MiscReg cause = tc->readMiscReg(MipsISA::Cause); // CoprocessorUnusableFault::coProcID
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID); MiscReg cause = tc->readMiscReg(MipsISA::Cause);
tc->setMiscRegNoEffect(MipsISA::Cause,cause); replaceBits(cause, Cause_CE_HI, Cause_CE_LO, coProcID);
tc->setMiscRegNoEffect(MipsISA::Cause, cause);
Addr HandlerBase; Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc); HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(MipsISA::Status),tc->readMiscReg(MipsISA::Cause));
#else #else
warn("%s (CP%d) encountered.\n", name(), coProcID); warn("%s (CP%d) encountered.\n", name(), coProcID);
#endif #endif

View file

@ -36,10 +36,9 @@
#include "sim/faults.hh" #include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
namespace MipsISA namespace MipsISA
{ {
typedef const Addr FaultVect; typedef const Addr FaultVect;
class MipsFault : public FaultBase class MipsFault : public FaultBase
@ -54,9 +53,9 @@ class MipsFault : public FaultBase
Addr EntryHi_VPN2X; Addr EntryHi_VPN2X;
Addr Context_BadVPN2; Addr Context_BadVPN2;
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc) {}; void invoke(ThreadContext * tc) {};
void setExceptionState(ThreadContext *,uint8_t); void setExceptionState(ThreadContext *, uint8_t);
void setHandlerPC(Addr,ThreadContext *); void setHandlerPC(Addr, ThreadContext *);
#endif #endif
virtual FaultVect vect() = 0; virtual FaultVect vect() = 0;
virtual FaultStat & countStat() = 0; virtual FaultStat & countStat() = 0;
@ -116,6 +115,7 @@ class AddressErrorFault : public MipsFault
#endif #endif
}; };
class StoreAddressErrorFault : public MipsFault class StoreAddressErrorFault : public MipsFault
{ {
private: private:
@ -129,8 +129,8 @@ class StoreAddressErrorFault : public MipsFault
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
}; };
class UnimplementedOpcodeFault : public MipsFault class UnimplementedOpcodeFault : public MipsFault
{ {
private: private:
@ -157,6 +157,7 @@ class TLBRefillIFetchFault : public MipsFault
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
}; };
class TLBInvalidIFetchFault : public MipsFault class TLBInvalidIFetchFault : public MipsFault
{ {
private: private:
@ -259,6 +260,7 @@ class ResetFault : public MipsFault
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
}; };
class SystemCallFault : public MipsFault class SystemCallFault : public MipsFault
{ {
private: private:
@ -284,6 +286,7 @@ class SoftResetFault : public MipsFault
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
}; };
class DebugSingleStep : public MipsFault class DebugSingleStep : public MipsFault
{ {
private: private:
@ -296,6 +299,7 @@ class DebugSingleStep : public MipsFault
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
}; };
class DebugInterrupt : public MipsFault class DebugInterrupt : public MipsFault
{ {
private: private:
@ -350,7 +354,6 @@ class ThreadFault : public MipsFault
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
}; };
class ArithmeticFault : public MipsFault class ArithmeticFault : public MipsFault
{ {
protected: protected:
@ -384,8 +387,6 @@ class InterruptFault : public MipsFault
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
//void invoke(ThreadContext * tc);
}; };
class TrapFault : public MipsFault class TrapFault : public MipsFault
@ -432,6 +433,7 @@ class ItbRefillFault : public MipsFault
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
}; };
class DtbRefillFault : public MipsFault class DtbRefillFault : public MipsFault
{ {
private: private:
@ -475,8 +477,8 @@ class ItbInvalidFault : public MipsFault
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
}; };
class TLBModifiedFault : public MipsFault class TLBModifiedFault : public MipsFault
{ {
private: private:
@ -490,7 +492,6 @@ class TLBModifiedFault : public MipsFault
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
}; };
class DtbInvalidFault : public MipsFault class DtbInvalidFault : public MipsFault
@ -506,7 +507,6 @@ class DtbInvalidFault : public MipsFault
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc); void invoke(ThreadContext * tc);
#endif #endif
}; };
class FloatEnableFault : public MipsFault class FloatEnableFault : public MipsFault

View file

@ -40,9 +40,4 @@ void
IdleStartEvent::process(ThreadContext *tc) IdleStartEvent::process(ThreadContext *tc)
{ {
fatal("Idle Start Event Not Defined for MIPS ISA "); fatal("Idle Start Event Not Defined for MIPS ISA ");
// if (tc->getKernelStats())
// tc->getKernelStats()->setIdleProcess(
// tc->readMiscRegNoEffect(MipsISA::IPR_PALtemp23), tc);
//remove();
} }

View file

@ -38,201 +38,102 @@
namespace MipsISA namespace MipsISA
{ {
static inline uint8_t getCauseIP_(ThreadContext *tc) {
static inline uint8_t
getCauseIP(ThreadContext *tc) {
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); return bits(cause, Cause_IP7, Cause_IP0);
return IP_;
} }
static inline void setCauseIP_(ThreadContext *tc, uint8_t val) { static inline void
setCauseIP_(ThreadContext *tc, uint8_t val) {
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
replaceBits(cause,Cause_IP7,Cause_IP0,val); replaceBits(cause, Cause_IP7, Cause_IP0, val);
tc->setMiscRegNoEffect(MipsISA::Cause,cause); tc->setMiscRegNoEffect(MipsISA::Cause, cause);
} }
/* void
void Interrupts::post(int int_num, int index) Interrupts::post(int int_num, ThreadContext* tc)
{
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
//index should not be used
assert(index == 0);
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
intstatus |= 1 << int_num;
}
void Interrupts::clear(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
//index should not be used
assert(index == 0);
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
intstatus &= ~(1 << int_num);
}
void Interrupts::clearAll()
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
intstatus = 0;
}
Fault Interrupts::getInterrupt(ThreadContext * tc)
{
DPRINTF(Interrupt, "Interrupts getInterrupt\n");
// If a timer interrupt has occured, check to see if a
// mtc0 to Compare register caused this interrupt to
// be cleared. If this is the case, clear intstatus
// bit for timer interrupt
if (oncputimerintr){
DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
//mtc0 to compare must have cleared bit in IP
if ( ((1 << IPTI) & IP_) == 0){
clear(IPTI, 0);
oncputimerintr=false;
}
}
//if there is a on cpu timer interrupt (i.e. Compare == Count)
//update intstatus before proceeding to interrupt
if (onCpuTimerInterrupt(tc)){
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
//determine timer interrupt IP #
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
//set intstatus to correspond
post(IPTI, 0);
oncputimerintr=true;
}
//Check if there are any outstanding interrupts
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
{
// Software interrupts & hardware interrupts are handled in software.
// So if any interrupt that isn't masked is detected, jump to interrupt
// handler
uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
IM = bits(status,Status_IM7,Status_IM0);
IP = intstatus;
//IM and IP are already correctly aligned
if (IM & IP){
DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
IM, IP);
return new InterruptFault;
}
}
return NoFault;
}
void Interrupts::updateIntrInfo(ThreadContext *tc) const
{
//Merge Interrupts.intstatus with mips MipISA::Status
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
tc->setMiscRegNoEffect(MipsISA::Cause,cause);
}
bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
{
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
if (compare == count)
return true;
return false;
}
*/
void Interrupts::post(int int_num, ThreadContext* tc)
{ {
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels) if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
uint8_t intstatus= getCauseIP_(tc); uint8_t intstatus = getCauseIP(tc);
intstatus |= 1 << int_num; intstatus |= 1 << int_num;
setCauseIP_(tc, intstatus); setCauseIP(tc, intstatus);
} }
void Interrupts::post(int int_num, int index) void
Interrupts::post(int int_num, int index)
{ {
fatal("Must use Thread COntext when posting MIPS Interrupts in M5"); fatal("Must use Thread Context when posting MIPS Interrupts in M5");
} }
void Interrupts::clear(int int_num, ThreadContext* tc) void
Interrupts::clear(int int_num, ThreadContext* tc)
{ {
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels) if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
uint8_t intstatus = getCauseIP_(tc); uint8_t intstatus = getCauseIP(tc);
intstatus &= ~(1 << int_num); intstatus &= ~(1 << int_num);
setCauseIP_(tc, intstatus); setCauseIP(tc, intstatus);
} }
void Interrupts::clear(int int_num, int index) void
Interrupts::clear(int int_num, int index)
{ {
fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
} }
void Interrupts::clearAll(ThreadContext *tc) void
Interrupts::clearAll(ThreadContext *tc)
{ {
DPRINTF(Interrupt, "Interrupts all cleared\n"); DPRINTF(Interrupt, "Interrupts all cleared\n");
uint8_t intstatus = 0; uint8_t intstatus = 0;
setCauseIP_(tc, intstatus); setCauseIP(tc, intstatus);
} }
void Interrupts::clearAll() void
Interrupts::clearAll()
{ {
fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
} }
Fault Interrupts::getInterrupt(ThreadContext * tc) Fault
Interrupts::getInterrupt(ThreadContext * tc)
{ {
DPRINTF(Interrupt, "Interrupts getInterrupt\n"); DPRINTF(Interrupt, "Interrupts getInterrupt\n");
//Check if there are any outstanding interrupts //Check if there are any outstanding interrupts
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled // Interrupts must be enabled, error level must be 0 or interrupts
bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited // inhibited, and exception level must be 0 or interrupts inhibited
bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited if (bits(status, Status_IE_LO) == 1 &&
{ bits(status, Status_ERL_HI, Status_ERL_LO) == 0 &&
bits(status, Status_EXL_HI, Status_EXL_LO) == 0) {
// Software interrupts & hardware interrupts are handled in software. // Software interrupts & hardware interrupts are handled in software.
// So if any interrupt that isn't masked is detected, jump to interrupt // So if any interrupt that isn't masked is detected, jump to interrupt
// handler // handler
uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0);
IM = bits(status,Status_IM7,Status_IM0); uint8_t InterruptPending = getCauseIP(tc);
IP = getCauseIP_(tc); // InterruptMask and InterruptPending are already correctly aligned
//IM and IP are already correctly aligned if (InterruptMask && InterruptPending){
if (IM & IP){
DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
IM, IP); InterruptMask, InterruptPending);
return new InterruptFault; return new InterruptFault;
} }
} }
return NoFault; return NoFault;
} }
bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
bool
Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
{ {
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
@ -240,34 +141,32 @@ bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
return true; return true;
return false; return false;
} }
void Interrupts::updateIntrInfo(ThreadContext *tc) const
void
Interrupts::updateIntrInfo(ThreadContext *tc) const
{ {
//Nothing needs to be done. //Nothing needs to be done.
;
} }
bool Interrupts::interruptsPending(ThreadContext *tc) const bool
Interrupts::interruptsPending(ThreadContext *tc) const
{ {
//if there is a on cpu timer interrupt (i.e. Compare == Count) //if there is a on cpu timer interrupt (i.e. Compare == Count)
//update CauseIP before proceeding to interrupt //update CauseIP before proceeding to interrupt
if (onCpuTimerInterrupt(tc)){ if (onCpuTimerInterrupt(tc)) {
DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n");
//determine timer interrupt IP # //determine timer interrupt IP #
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
//set intstatus to correspond //set intstatus to correspond
//post(IPTI, tc); //post(IPTI, tc);
uint8_t intstatus= getCauseIP_(tc); uint8_t intstatus = getCauseIP(tc);
intstatus |= 1 << IPTI; intstatus |= 1 << IPTI;
setCauseIP_(tc, intstatus); setCauseIP(tc, intstatus);
} }
return (getCauseIP_(tc) != 0); return (getCauseIP(tc) != 0);
} }
} }

View file

@ -31,97 +31,27 @@
#ifndef __ARCH_MIPS_INTERRUPT_HH__ #ifndef __ARCH_MIPS_INTERRUPT_HH__
#define __ARCH_MIPS_INTERRUPT_HH__ #define __ARCH_MIPS_INTERRUPT_HH__
#include "arch/mips/faults.hh" #include "arch/mips/faults.hh"
#include "base/compiler.hh" #include "base/compiler.hh"
namespace MipsISA namespace MipsISA
{ {
class Interrupts class Interrupts
{ {
/*
protected:
uint8_t intstatus;
bool oncputimerintr;
public:
Interrupts()
{
intstatus = 0;
newInfoSet = false;
oncputimerintr = false;
}
// post(int int_num, int index) is responsible
// for posting an interrupt. It sets a bit
// in intstatus corresponding to Cause IP*. The
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
void post(int int_num, int index);
// clear(int int_num, int index) is responsible
// for clearing an interrupt. It clear a bit
// in intstatus corresponding to Cause IP*. The
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
void clear(int int_num, int index);
// clearAll() is responsible
// for clearing all interrupts. It clears all bits
// in intstatus corresponding to Cause IP*. The
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
void clearAll();
// getInterrupt(ThreadContext * tc) checks if an interrupt
// should be returned. It ands the interrupt mask and
// and interrupt pending bits to see if one exists. It
// also makes sure interrupts are enabled (IE) and
// that ERL and ERX are not set
//
Fault getInterrupt(ThreadContext * tc);
// updateIntrInfo(ThreadContext *tc) const syncs the
// MIPS cause register with the instatus variable. instatus
// is essentially a copy of the MIPS cause[IP7:IP0]
//
void updateIntrInfo(ThreadContext *tc) const;
void updateIntrInfoCpuTimerIntr(ThreadContext *tc) const;
bool onCpuTimerInterrupt(ThreadContext *tc) const;
bool checkInterrupts(ThreadContext *tc) const {
//return (intstatus != 0) && !(tc->readPC() & 0x3);
if (oncputimerintr == false){
updateIntrInfo(tc);
return ((intstatus != 0) || onCpuTimerInterrupt(tc));
}
else
return true;
}
*/
protected:
//uint8_t intstatus;
//bool oncputimerintr;
public: public:
Interrupts() Interrupts()
{ {
//intstatus = 0;
newInfoSet = false; newInfoSet = false;
//oncputimerintr = false;
} }
// post(int int_num, int index) is responsible // post(int int_num, int index) is responsible
// for posting an interrupt. It sets a bit // for posting an interrupt. It sets a bit
// in intstatus corresponding to Cause IP*. The // in intstatus corresponding to Cause IP*. The
// MIPS register Cause is updated by updateIntrInfo // MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts // which is called by checkInterrupts
// //
void post(int int_num, ThreadContext* tc); void post(int int_num, ThreadContext *tc);
void post(int int_num, int index); void post(int int_num, int index);
// clear(int int_num, int index) is responsible // clear(int int_num, int index) is responsible
@ -139,7 +69,7 @@ class Interrupts
// MIPS register Cause is updated by updateIntrInfo // MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts // which is called by checkInterrupts
// //
void clearAll(ThreadContext* tc); void clearAll(ThreadContext *tc);
void clearAll(); void clearAll();
// getInterrupt(ThreadContext * tc) checks if an interrupt // getInterrupt(ThreadContext * tc) checks if an interrupt
@ -148,7 +78,7 @@ class Interrupts
// also makes sure interrupts are enabled (IE) and // also makes sure interrupts are enabled (IE) and
// that ERL and ERX are not set // that ERL and ERX are not set
// //
Fault getInterrupt(ThreadContext * tc); Fault getInterrupt(ThreadContext *tc);
// updateIntrInfo(ThreadContext *tc) const syncs the // updateIntrInfo(ThreadContext *tc) const syncs the
// MIPS cause register with the instatus variable. instatus // MIPS cause register with the instatus variable. instatus
@ -165,27 +95,22 @@ class Interrupts
} }
void serialize(std::ostream &os) void
serialize(std::ostream &os)
{ {
fatal("Serialization of Interrupts Unimplemented for MIPS"); fatal("Serialization of Interrupts Unimplemented for MIPS");
//SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
//SERIALIZE_SCALAR(intstatus);
} }
void unserialize(Checkpoint *cp, const std::string &section) void
unserialize(Checkpoint *cp, const std::string &section)
{ {
fatal("Unserialization of Interrupts Unimplemented for MIPS"); fatal("Unserialization of Interrupts Unimplemented for MIPS");
//UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
//UNSERIALIZE_SCALAR(intstatus);
} }
private: private:
bool newInfoSet; bool newInfoSet;
int newIpl; int newIpl;
int newSummary; int newSummary;
}; };
} }

View file

@ -447,12 +447,7 @@ ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid)
misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg],
miscRegFile[misc_reg][reg_sel]); miscRegFile[misc_reg][reg_sel]);
return miscRegFile[misc_reg][reg_sel];
switch (misc_reg)
{
default:
return miscRegFile[misc_reg][reg_sel];
}
} }
void void
@ -486,7 +481,6 @@ ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid)
// (1) Some CP0 Registers have fields that cannot // (1) Some CP0 Registers have fields that cannot
// be overwritten. Make sure to handle those particular registers // be overwritten. Make sure to handle those particular registers
// with care! // with care!
//template <class TC>
void void
ISA::setMiscReg(int reg_idx, const MiscReg &val, ISA::setMiscReg(int reg_idx, const MiscReg &val,
ThreadContext *tc, ThreadID tid) ThreadContext *tc, ThreadID tid)
@ -515,21 +509,21 @@ ISA::setMiscReg(int reg_idx, const MiscReg &val,
MiscReg MiscReg
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
{ {
MiscReg retVal = val; MiscReg retVal = val;
// Mask off read-only regions // Mask off read-only regions
retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
MiscReg curVal = miscRegFile[misc_reg][reg_sel]; MiscReg curVal = miscRegFile[misc_reg][reg_sel];
// Mask off current alue with inverse mask (clear writeable bits) // Mask off current alue with inverse mask (clear writeable bits)
curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
retVal |= curVal; // Combine the two retVal |= curVal; // Combine the two
DPRINTF(MipsPRA, DPRINTF(MipsPRA,
"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, " "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
"current val: %lx, written val: %x\n", "current val: %lx, written val: %x\n",
miscRegFile_WriteMask[misc_reg][reg_sel], miscRegFile_WriteMask[misc_reg][reg_sel],
~miscRegFile_WriteMask[misc_reg][reg_sel], ~miscRegFile_WriteMask[misc_reg][reg_sel],
val, miscRegFile[misc_reg][reg_sel], retVal); val, miscRegFile[misc_reg][reg_sel], retVal);
return retVal; return retVal;
} }
void void
@ -586,8 +580,6 @@ ISA::CP0Event::process()
cp0->updateCPU(); cp0->updateCPU();
break; break;
} }
//cp0EventRemoveList.push(this);
} }
const char * const char *

View file

@ -41,133 +41,129 @@
namespace LittleEndianGuest {}; namespace LittleEndianGuest {};
#define TARGET_MIPS
class StaticInstPtr; class StaticInstPtr;
namespace MipsISA namespace MipsISA
{ {
using namespace LittleEndianGuest;
StaticInstPtr decodeInst(ExtMachInst); using namespace LittleEndianGuest;
// MIPS DOES have a delay slot StaticInstPtr decodeInst(ExtMachInst);
#define ISA_HAS_DELAY_SLOT 1
const Addr PageShift = 13; // MIPS DOES have a delay slot
const Addr PageBytes = ULL(1) << PageShift; #define ISA_HAS_DELAY_SLOT 1
const Addr Page_Mask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1; const Addr PageShift = 13;
const Addr PageBytes = ULL(1) << PageShift;
const Addr Page_Mask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Translation stuff // Translation stuff
// //
const Addr PteShift = 3; const Addr PteShift = 3;
const Addr NPtePageShift = PageShift - PteShift; const Addr NPtePageShift = PageShift - PteShift;
const Addr NPtePage = ULL(1) << NPtePageShift; const Addr NPtePage = ULL(1) << NPtePageShift;
const Addr PteMask = NPtePage - 1; const Addr PteMask = NPtePage - 1;
//// All 'Mapped' segments go through the TLB //// All 'Mapped' segments go through the TLB
//// All other segments are translated by dropping the MSB, to give //// All other segments are translated by dropping the MSB, to give
//// the corresponding physical address //// the corresponding physical address
// User Segment - Mapped // User Segment - Mapped
const Addr USegBase = ULL(0x0); const Addr USegBase = ULL(0x0);
const Addr USegEnd = ULL(0x7FFFFFFF); const Addr USegEnd = ULL(0x7FFFFFFF);
// Kernel Segment 0 - Unmapped // Kernel Segment 0 - Unmapped
const Addr KSeg0End = ULL(0x9FFFFFFF); const Addr KSeg0End = ULL(0x9FFFFFFF);
const Addr KSeg0Base = ULL(0x80000000); const Addr KSeg0Base = ULL(0x80000000);
const Addr KSeg0Mask = ULL(0x1FFFFFFF); const Addr KSeg0Mask = ULL(0x1FFFFFFF);
// Kernel Segment 1 - Unmapped, Uncached // Kernel Segment 1 - Unmapped, Uncached
const Addr KSeg1End = ULL(0xBFFFFFFF); const Addr KSeg1End = ULL(0xBFFFFFFF);
const Addr KSeg1Base = ULL(0xA0000000); const Addr KSeg1Base = ULL(0xA0000000);
const Addr KSeg1Mask = ULL(0x1FFFFFFF); const Addr KSeg1Mask = ULL(0x1FFFFFFF);
// Kernel/Supervisor Segment - Mapped // Kernel/Supervisor Segment - Mapped
const Addr KSSegEnd = ULL(0xDFFFFFFF); const Addr KSSegEnd = ULL(0xDFFFFFFF);
const Addr KSSegBase = ULL(0xC0000000); const Addr KSSegBase = ULL(0xC0000000);
// Kernel Segment 3 - Mapped // Kernel Segment 3 - Mapped
const Addr KSeg3End = ULL(0xFFFFFFFF); const Addr KSeg3End = ULL(0xFFFFFFFF);
const Addr KSeg3Base = ULL(0xE0000000); const Addr KSeg3Base = ULL(0xE0000000);
// For loading... XXX This maybe could be USegEnd?? --ali // For loading... XXX This maybe could be USegEnd?? --ali
const Addr LoadAddrMask = ULL(0xffffffffff); const Addr LoadAddrMask = ULL(0xffffffffff);
inline Addr Phys2K0Seg(Addr addr) inline Addr Phys2K0Seg(Addr addr)
{ {
// if (addr & PAddrUncachedBit43) { return addr | KSeg0Base;
// addr &= PAddrUncachedMask; }
// addr |= PAddrUncachedBit40;
// }
return addr | KSeg0Base;
}
const unsigned VABits = 32; const unsigned VABits = 32;
const unsigned PABits = 32; // Is this correct? const unsigned PABits = 32; // Is this correct?
const Addr VAddrImplMask = (ULL(1) << VABits) - 1; const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
const Addr VAddrUnImplMask = ~VAddrImplMask; const Addr VAddrUnImplMask = ~VAddrImplMask;
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; } inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; } inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
const Addr PAddrImplMask = (ULL(1) << PABits) - 1; const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Interrupt levels // Interrupt levels
// //
enum InterruptLevels enum InterruptLevels
{ {
INTLEVEL_SOFTWARE_MIN = 4, INTLEVEL_SOFTWARE_MIN = 4,
INTLEVEL_SOFTWARE_MAX = 19, INTLEVEL_SOFTWARE_MAX = 19,
INTLEVEL_EXTERNAL_MIN = 20, INTLEVEL_EXTERNAL_MIN = 20,
INTLEVEL_EXTERNAL_MAX = 34, INTLEVEL_EXTERNAL_MAX = 34,
INTLEVEL_IRQ0 = 20, INTLEVEL_IRQ0 = 20,
INTLEVEL_IRQ1 = 21, INTLEVEL_IRQ1 = 21,
INTINDEX_ETHERNET = 0, INTINDEX_ETHERNET = 0,
INTINDEX_SCSI = 1, INTINDEX_SCSI = 1,
INTLEVEL_IRQ2 = 22, INTLEVEL_IRQ2 = 22,
INTLEVEL_IRQ3 = 23, INTLEVEL_IRQ3 = 23,
INTLEVEL_SERIAL = 33, INTLEVEL_SERIAL = 33,
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
}; };
// MIPS modes // MIPS modes
enum mode_type enum mode_type
{ {
mode_kernel = 0, // kernel mode_kernel = 0, // kernel
mode_supervisor = 1, // supervisor mode_supervisor = 1, // supervisor
mode_user = 2, // user mode mode_user = 2, // user mode
mode_debug = 3, // debug mode mode_debug = 3, // debug mode
mode_number // number of modes mode_number // number of modes
}; };
// return a no-op instruction... used for instruction fetch faults // return a no-op instruction... used for instruction fetch faults
const ExtMachInst NoopMachInst = 0x00000000; const ExtMachInst NoopMachInst = 0x00000000;
const int LogVMPageSize = 13; // 8K bytes const int LogVMPageSize = 13; // 8K bytes
const int VMPageSize = (1 << LogVMPageSize); const int VMPageSize = (1 << LogVMPageSize);
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
const int MachineBytes = 4; const int MachineBytes = 4;
const int WordBytes = 4; const int WordBytes = 4;
const int HalfwordBytes = 2; const int HalfwordBytes = 2;
const int ByteBytes = 1; const int ByteBytes = 1;
const int ANNOTE_NONE = 0;
const uint32_t ITOUCH_ANNOTE = 0xffffffff;
const int ANNOTE_NONE = 0;
const uint32_t ITOUCH_ANNOTE = 0xffffffff;
}; };
#endif // __ARCH_MIPS_ISA_TRAITS_HH__ #endif // __ARCH_MIPS_ISA_TRAITS_HH__

View file

@ -32,11 +32,6 @@
#ifndef __ARCH_MIPS_KERNEL_STATS_HH__ #ifndef __ARCH_MIPS_KERNEL_STATS_HH__
#define __ARCH_MIPS_KERNEL_STATS_HH__ #define __ARCH_MIPS_KERNEL_STATS_HH__
#include <map>
#include <stack>
#include <string>
#include <vector>
#include "kern/kernel_stats.hh" #include "kern/kernel_stats.hh"
namespace MipsISA { namespace MipsISA {

View file

@ -69,7 +69,3 @@ OpenFlagTransTable MipsLinux::openFlagTable[] = {
const int MipsLinux::NUM_OPEN_FLAGS = const int MipsLinux::NUM_OPEN_FLAGS =
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0])); (sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));

View file

@ -68,13 +68,13 @@ class MipsLinux : public Linux
//@{ //@{
/// For getsysinfo(). /// For getsysinfo().
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
static const unsigned GSI_CPU_INFO = 59; //!< CPU information static const unsigned GSI_CPU_INFO = 59; //!< CPU information
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
//@} //@}
//@{ //@{

View file

@ -74,15 +74,15 @@ sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
// unsigned nbytes = process->getSyscallArg(tc, 2); // unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) { switch (op) {
case 45:
case 45: { // GSI_IEEE_FP_CONTROL {
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); // GSI_IEEE_FP_CONTROL
// I don't think this exactly matches the HW FPCR TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
*fpcr = 0; // I don't think this exactly matches the HW FPCR
fpcr.copyOut(tc->getMemPort()); *fpcr = 0;
return 0; fpcr.copyOut(tc->getMemPort());
} return 0;
}
default: default:
cerr << "sys_getsysinfo: unknown op " << op << endl; cerr << "sys_getsysinfo: unknown op " << op << endl;
abort(); abort();
@ -102,15 +102,16 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
switch (op) { switch (op) {
case 14: { // SSI_IEEE_FP_CONTROL case 14:
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); {
// I don't think this exactly matches the HW FPCR // SSI_IEEE_FP_CONTROL
fpcr.copyIn(tc->getMemPort()); TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): " // I don't think this exactly matches the HW FPCR
fpcr.copyIn(tc->getMemPort());
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0; return 0;
} }
default: default:
cerr << "sys_setsysinfo: unknown op " << op << endl; cerr << "sys_setsysinfo: unknown op " << op << endl;
abort(); abort();
@ -196,8 +197,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
/* 73 */ SyscallDesc("sigpending", unimplementedFunc), /* 73 */ SyscallDesc("sigpending", unimplementedFunc),
/* 74 */ SyscallDesc("sethostname", ignoreFunc), /* 74 */ SyscallDesc("sethostname", ignoreFunc),
/* 75 */ SyscallDesc("setrlimit", unimplementedFunc/*setrlimitFunc<MipsLinux>*/), /* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
/* 76 */ SyscallDesc("getrlimit", unimplementedFunc/*getrlimitFunc<MipsLinux>*/), /* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
/* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>), /* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>),
/* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
/* 79 */ SyscallDesc("settimeofday", unimplementedFunc), /* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
@ -241,7 +242,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
/* 120 */ SyscallDesc("clone", unimplementedFunc/*cloneFunc<MipsLinux>*/), /* 120 */ SyscallDesc("clone", unimplementedFunc),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc), /* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc), /* 122 */ SyscallDesc("uname", unameFunc),
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
@ -315,12 +316,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 191 */ SyscallDesc("getresgid", unimplementedFunc), /* 191 */ SyscallDesc("getresgid", unimplementedFunc),
/* 192 */ SyscallDesc("prctl", unimplementedFunc), /* 192 */ SyscallDesc("prctl", unimplementedFunc),
/* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc), /* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
/* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc/*rt_sigactionFunc<MipsLinux>*/), /* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc),
/* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc/*rt_sigprocmaskFunc<MipsLinux>*/), /* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
/* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), /* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc), /* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
/* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc/*rt_sigsuspendFunc<MipsLinux>*/), /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 200 */ SyscallDesc("pread64", unimplementedFunc), /* 200 */ SyscallDesc("pread64", unimplementedFunc),
/* 201 */ SyscallDesc("pwrite64", unimplementedFunc), /* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
/* 202 */ SyscallDesc("chown", unimplementedFunc), /* 202 */ SyscallDesc("chown", unimplementedFunc),
@ -406,7 +407,6 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 282 */ SyscallDesc("keyctl", unimplementedFunc) /* 282 */ SyscallDesc("keyctl", unimplementedFunc)
}; };
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params, MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
ObjectFile *objFile) ObjectFile *objFile)
: MipsLiveProcess(params, objFile), : MipsLiveProcess(params, objFile),

View file

@ -88,7 +88,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
virtPort.write(addr, (uint64_t)(Clock::Frequency / virtPort.write(addr, (uint64_t)(Clock::Frequency /
p->boot_cpu_frequency)); p->boot_cpu_frequency));
/** /**
* EV5 only supports 127 ASNs so we are going to tell the kernel that the * EV5 only supports 127 ASNs so we are going to tell the kernel that the
* paritiuclar EV6 we have only supports 127 asns. * paritiuclar EV6 we have only supports 127 asns.
@ -105,12 +104,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
if (!kernelPanicEvent) if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'"); panic("could not find kernel symbol \'panic\'");
#if 0
kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
if (!kernelDieEvent)
panic("could not find kernel symbol \'die_if_kernel\'");
#endif
#endif #endif
/** /**

View file

@ -45,17 +45,18 @@
namespace MipsISA namespace MipsISA
{ {
template <class XC> template <class XC>
inline void inline void
handleLockedRead(XC *xc, Request *req) handleLockedRead(XC *xc, Request *req)
{ {
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf); xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf);
xc->setMiscRegNoEffect(LLFlag, true); xc->setMiscRegNoEffect(LLFlag, true);
DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n", DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link"
" Address set to %x.\n",
req->threadId(), req->getPaddr() & ~0xf); req->threadId(), req->getPaddr() & ~0xf);
} }
template <class XC> template <class XC>
inline bool inline bool
handleLockedWrite(XC *xc, Request *req) handleLockedWrite(XC *xc, Request *req)
@ -89,14 +90,17 @@ handleLockedWrite(XC *xc, Request *req)
} }
if (stCondFailures == 5000) { if (stCondFailures == 5000) {
panic("Max (5000) Store Conditional Fails Reached. Check Code For Deadlock.\n"); panic("Max (5000) Store Conditional Fails Reached. "
"Check Code For Deadlock.\n");
} }
if (!lock_flag){ if (!lock_flag){
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n", DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, "
"Store Conditional Failed.\n",
req->threadId()); req->threadId());
} else if ((req->getPaddr() & ~0xf) != lock_addr) { } else if ((req->getPaddr() & ~0xf) != lock_addr) {
DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n", DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, "
"Store Conditional Failed.\n",
req->threadId()); req->threadId());
} }
// store conditional failed already, so don't issue it to mem // store conditional failed already, so don't issue it to mem
@ -107,7 +111,6 @@ handleLockedWrite(XC *xc, Request *req)
return true; return true;
} }
} // namespace MipsISA } // namespace MipsISA
#endif #endif

View file

@ -29,20 +29,9 @@
* Steve Reinhardt * Steve Reinhardt
*/ */
#include "arch/mips/faults.hh"
#include "arch/mips/isa_traits.hh"
#include "arch/mips/tlb.hh"
//#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
#include "config/full_system.hh" #include "config/full_system.hh"
#include "cpu/base.hh" #include "cpu/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "kern/kernel_stats.hh"
#include "sim/debug.hh"
#include "sim/sim_exit.hh"
#include "arch/mips/mips_core_specific.hh"
#if FULL_SYSTEM #if FULL_SYSTEM
@ -52,61 +41,11 @@
// //
void void
MipsISA::initCPU(ThreadContext *tc, int cpuId) MipsISA::initCPU(ThreadContext *tc, int cpuId)
{ {}
// MipsFault *reset = new ResetFault;
// tc->setPC(reset->vect());
// tc->setNextPC(tc->readPC() + sizeof(MachInst));
// delete reset;
}
template <class CPU> template <class CPU>
void void
MipsISA::processInterrupts(CPU *cpu) MipsISA::processInterrupts(CPU *cpu)
{ {}
//Check if there are any outstanding interrupts
//Handle the interrupts
/* int ipl = 0;
int summary = 0;
cpu->checkInterrupts = false;
if (cpu->readMiscReg(IPR_ASTRR))
panic("asynchronous traps not implemented\n");
if (cpu->readMiscReg(IPR_SIRR)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
uint64_t interrupts = cpu->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = i;
summary |= (ULL(1) << i);
}
}
}
if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
cpu->setMiscReg(IPR_ISR, summary);
cpu->setMiscReg(IPR_INTID, ipl);
cpu->trap(new InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
cpu->readMiscReg(IPR_IPLR), ipl, summary);
}
*/
}
#endif // FULL_SYSTEM || BARE_IRON #endif // FULL_SYSTEM || BARE_IRON

View file

@ -44,6 +44,7 @@ class ThreadContext;
namespace MipsISA namespace MipsISA
{ {
inline Tick inline Tick
handleIprRead(ThreadContext *xc, Packet *pkt) handleIprRead(ThreadContext *xc, Packet *pkt)
{ {
@ -56,7 +57,6 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
panic("No implementation for handleIprWrite in MIPS\n"); panic("No implementation for handleIprWrite in MIPS\n");
} }
} // namespace MipsISA } // namespace MipsISA
#endif #endif

View file

@ -51,7 +51,6 @@
namespace MipsISA namespace MipsISA
{ {
template <class TC> template <class TC>
inline unsigned inline unsigned
getVirtProcNum(TC *tc) getVirtProcNum(TC *tc)
@ -76,11 +75,13 @@ haltThread(TC *tc)
tc->halt(); tc->halt();
// Save last known PC in TCRestart // Save last known PC in TCRestart
// @TODO: Needs to check if this is a branch and if so, take previous instruction // @TODO: Needs to check if this is a branch and if so,
// take previous instruction
tc->setMiscReg(TCRestart, tc->readNextPC()); tc->setMiscReg(TCRestart, tc->readNextPC());
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
tc->readPC(), tc->readNextPC()); curTick, tc->threadId(), tc->getCpuPtr()->name(),
tc->readPC(), tc->readNextPC());
} }
} }
@ -93,14 +94,14 @@ restoreThread(TC *tc)
IntReg pc = tc->readMiscRegNoEffect(TCRestart); IntReg pc = tc->readMiscRegNoEffect(TCRestart);
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
// tc->setPCEvent(pc, pc + 4, pc + 8);
tc->setPC(pc); tc->setPC(pc);
tc->setNextPC(pc + 4); tc->setNextPC(pc + 4);
tc->setNextNPC(pc + 8); tc->setNextNPC(pc + 8);
tc->activate(0); tc->activate(0);
warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), warn("%i: Restoring thread %i in %s @ PC %x",
tc->readPC()); curTick, tc->threadId(), tc->getCpuPtr()->name(),
tc->readPC());
} }
} }

View file

@ -37,42 +37,42 @@
namespace MipsISA namespace MipsISA
{ {
void
void PTE::serialize(std::ostream &os)
PTE::serialize(std::ostream &os) {
{ SERIALIZE_SCALAR(Mask);
SERIALIZE_SCALAR(Mask); SERIALIZE_SCALAR(VPN);
SERIALIZE_SCALAR(VPN); SERIALIZE_SCALAR(asid);
SERIALIZE_SCALAR(asid); SERIALIZE_SCALAR(G);
SERIALIZE_SCALAR(G); SERIALIZE_SCALAR(PFN0);
SERIALIZE_SCALAR(PFN0); SERIALIZE_SCALAR(D0);
SERIALIZE_SCALAR(D0); SERIALIZE_SCALAR(V0);
SERIALIZE_SCALAR(V0); SERIALIZE_SCALAR(C0);
SERIALIZE_SCALAR(C0); SERIALIZE_SCALAR(PFN1);
SERIALIZE_SCALAR(PFN1); SERIALIZE_SCALAR(D1);
SERIALIZE_SCALAR(D1); SERIALIZE_SCALAR(V1);
SERIALIZE_SCALAR(V1); SERIALIZE_SCALAR(C1);
SERIALIZE_SCALAR(C1); SERIALIZE_SCALAR(AddrShiftAmount);
SERIALIZE_SCALAR(AddrShiftAmount); SERIALIZE_SCALAR(OffsetMask);
SERIALIZE_SCALAR(OffsetMask); }
}
void
void PTE::unserialize(Checkpoint *cp, const std::string &section)
PTE::unserialize(Checkpoint *cp, const std::string &section) {
{ UNSERIALIZE_SCALAR(Mask);
UNSERIALIZE_SCALAR(Mask); UNSERIALIZE_SCALAR(VPN);
UNSERIALIZE_SCALAR(VPN); UNSERIALIZE_SCALAR(asid);
UNSERIALIZE_SCALAR(asid); UNSERIALIZE_SCALAR(G);
UNSERIALIZE_SCALAR(G); UNSERIALIZE_SCALAR(PFN0);
UNSERIALIZE_SCALAR(PFN0); UNSERIALIZE_SCALAR(D0);
UNSERIALIZE_SCALAR(D0); UNSERIALIZE_SCALAR(V0);
UNSERIALIZE_SCALAR(V0); UNSERIALIZE_SCALAR(C0);
UNSERIALIZE_SCALAR(C0); UNSERIALIZE_SCALAR(PFN1);
UNSERIALIZE_SCALAR(PFN1); UNSERIALIZE_SCALAR(D1);
UNSERIALIZE_SCALAR(D1); UNSERIALIZE_SCALAR(V1);
UNSERIALIZE_SCALAR(V1); UNSERIALIZE_SCALAR(C1);
UNSERIALIZE_SCALAR(C1); UNSERIALIZE_SCALAR(AddrShiftAmount);
UNSERIALIZE_SCALAR(AddrShiftAmount); UNSERIALIZE_SCALAR(OffsetMask);
UNSERIALIZE_SCALAR(OffsetMask); }
}
} }

View file

@ -41,59 +41,62 @@
namespace MipsISA { namespace MipsISA {
struct VAddr struct VAddr
{ {
static const int ImplBits = 43; static const int ImplBits = 43;
static const Addr ImplMask = (ULL(1) << ImplBits) - 1; static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
static const Addr UnImplMask = ~ImplMask; static const Addr UnImplMask = ~ImplMask;
VAddr(Addr a) : addr(a) {} VAddr(Addr a) : addr(a) {}
Addr addr; Addr addr;
operator Addr() const { return addr; } operator Addr() const { return addr; }
const VAddr &operator=(Addr a) { addr = a; return *this; } const VAddr &operator=(Addr a) { addr = a; return *this; }
Addr vpn() const { return (addr & ImplMask) >> PageShift; } Addr vpn() const { return (addr & ImplMask) >> PageShift; }
Addr page() const { return addr & Page_Mask; } Addr page() const { return addr & Page_Mask; }
Addr offset() const { return addr & PageOffset; } Addr offset() const { return addr & PageOffset; }
Addr level3() const Addr level3() const
{ return MipsISA::PteAddr(addr >> PageShift); } { return MipsISA::PteAddr(addr >> PageShift); }
Addr level2() const Addr level2() const
{ return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); } { return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
Addr level1() const Addr level1() const
{ return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); } { return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
}; };
// ITB/DTB page table entry // ITB/DTB page table entry
struct PTE struct PTE
{ {
Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask) Addr Mask;
Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi) Addr VPN;
uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi uint8_t asid;
bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit bool G;
/* Contents of Entry Lo0 */ /* Contents of Entry Lo0 */
Addr PFN0; // Physical Frame Number - Even Addr PFN0; // Physical Frame Number - Even
bool D0; // Even entry Dirty Bit bool D0; // Even entry Dirty Bit
bool V0; // Even entry Valid Bit bool V0; // Even entry Valid Bit
uint8_t C0; // Cache Coherency Bits - Even uint8_t C0; // Cache Coherency Bits - Even
/* Contents of Entry Lo1 */ /* Contents of Entry Lo1 */
Addr PFN1; // Physical Frame Number - Odd Addr PFN1; // Physical Frame Number - Odd
bool D1; // Odd entry Dirty Bit bool D1; // Odd entry Dirty Bit
bool V1; // Odd entry Valid Bit bool V1; // Odd entry Valid Bit
uint8_t C1; // Cache Coherency Bits (3 bits) uint8_t C1; // Cache Coherency Bits (3 bits)
/* The next few variables are put in as optimizations to reduce TLB lookup overheads */ /*
/* For a given Mask, what is the address shift amount, and what is the OffsetMask */ * The next few variables are put in as optimizations to reduce
int AddrShiftAmount; * TLB lookup overheads. For a given Mask, what is the address shift
int OffsetMask; * amount, and what is the OffsetMask
*/
int AddrShiftAmount;
int OffsetMask;
bool Valid() { return (V0 | V1);}; bool Valid() { return (V0 | V1); };
void serialize(std::ostream &os); void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section); void unserialize(Checkpoint *cp, const std::string &section);
}; };
}; };
#endif // __ARCH_MIPS_PAGETABLE_H__ #endif // __ARCH_MIPS_PAGETABLE_H__

View file

@ -40,57 +40,66 @@ class ThreadContext;
namespace MipsISA namespace MipsISA
{ {
class Predecoder
class Predecoder
{
protected:
ThreadContext * tc;
//The extended machine instruction being generated
ExtMachInst emi;
public:
Predecoder(ThreadContext * _tc) : tc(_tc)
{}
ThreadContext *getTC()
{ {
protected: return tc;
ThreadContext * tc; }
//The extended machine instruction being generated
ExtMachInst emi;
public: void
Predecoder(ThreadContext * _tc) : tc(_tc) setTC(ThreadContext *_tc)
{} {
tc = _tc;
}
ThreadContext * getTC() void
{ process()
return tc; {
} }
void setTC(ThreadContext * _tc) void
{ reset()
tc = _tc; {}
}
void process() //Use this to give data to the predecoder. This should be used
{ //when there is control flow.
} void
moreBytes(Addr pc, Addr fetchPC, MachInst inst)
{
emi = inst;
}
void reset() bool
{} needMoreBytes()
{
return true;
}
//Use this to give data to the predecoder. This should be used bool
//when there is control flow. extMachInstReady()
void moreBytes(Addr pc, Addr fetchPC, MachInst inst) {
{ return true;
emi = inst; }
}
bool needMoreBytes() //This returns a constant reference to the ExtMachInst to avoid a copy
{ const ExtMachInst &
return true; getExtMachInst()
} {
return emi;
}
};
bool extMachInstReady()
{
return true;
}
//This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst & getExtMachInst()
{
return emi;
}
};
}; };
#endif // __ARCH_MIPS_PREDECODER_HH__ #endif // __ARCH_MIPS_PREDECODER_HH__

View file

@ -42,35 +42,8 @@
using namespace std; using namespace std;
using namespace MipsISA; using namespace MipsISA;
ProcessInfo::ProcessInfo(ThreadContext *_tc) ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
: tc(_tc) {}
{
// Addr addr = 0;
VirtualPort *vp;
vp = tc->getVirtPort();
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
// panic("thread info not compiled into kernel\n");
// thread_info_size = vp->readGtoH<int32_t>(addr);
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
// panic("thread info not compiled into kernel\n");
// task_struct_size = vp->readGtoH<int32_t>(addr);
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
// panic("thread info not compiled into kernel\n");
// task_off = vp->readGtoH<int32_t>(addr);
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
// panic("thread info not compiled into kernel\n");
// pid_off = vp->readGtoH<int32_t>(addr);
// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
// panic("thread info not compiled into kernel\n");
// name_off = vp->readGtoH<int32_t>(addr);
}
Addr Addr
ProcessInfo::task(Addr ksp) const ProcessInfo::task(Addr ksp) const
@ -140,84 +113,17 @@ void
StackTrace::trace(ThreadContext *_tc, bool is_call) StackTrace::trace(ThreadContext *_tc, bool is_call)
{ {
tc = _tc; tc = _tc;
/* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
bool usermode = 0; bool usermode = 0;
//(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0;
// Addr pc = tc->readNextPC();
// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
// pc <= tc->getSystemPtr()->kernelEnd;
if (usermode) { if (usermode) {
stack.push_back(user); stack.push_back(user);
return; return;
} }
// if (!kernel) {
// stack.push_back(console);
// return;
// }
// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
// Addr ksp = tc->readIntReg(MipsISA::StackPointerReg);
// Addr bottom = ksp & ~0x3fff;
// Addr addr;
// if (is_call) {
// if (!symtab->findNearestAddr(pc, addr))
// panic("could not find address %#x", pc);
// stack.push_back(addr);
// pc = tc->readPC();
// }
// Addr ra;
// int size;
// while (ksp > bottom) {
// if (!symtab->findNearestAddr(pc, addr))
// panic("could not find symbol for pc=%#x", pc);
// assert(pc >= addr && "symbol botch: callpc < func");
// stack.push_back(addr);
// if (isEntry(addr))
// return;
// if (decodePrologue(ksp, pc, addr, size, ra)) {
// if (!ra)
// return;
// if (size <= 0) {
// stack.push_back(unknown);
// return;
// }
// pc = ra;
// ksp += size;
// } else {
// stack.push_back(unknown);
// return;
// }
// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
// pc <= tc->getSystemPtr()->kernelEnd;
// if (!kernel)
// return;
// if (stack.size() >= 1000)
// panic("unwinding too far");
// }
// panic("unwinding too far");
} }
bool bool
StackTrace::isEntry(Addr addr) StackTrace::isEntry(Addr addr)
{ {
/* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
return true;*/
return false; return false;
} }
@ -305,7 +211,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
int reg, disp; int reg, disp;
if (decodeStack(inst, disp)) { if (decodeStack(inst, disp)) {
if (size) { if (size) {
// panic("decoding frame size again");
return true; return true;
} }
size += disp; size += disp;
@ -313,7 +218,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
if (!ra && reg == ReturnAddressReg) { if (!ra && reg == ReturnAddressReg) {
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
if (!ra) { if (!ra) {
// panic("no return address value pc=%#x\n", pc);
return false; return false;
} }
} }
@ -327,24 +231,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
void void
StackTrace::dump() StackTrace::dump()
{ {
StringWrap name(tc->getCpuPtr()->name()); panic("Stack trace dump not implemented.\n");
// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n");
// string symbol;
// for (int i = 0, size = stack.size(); i < size; ++i) {
// Addr addr = stack[size - i - 1];
// if (addr == user)
// symbol = "user";
// else if (addr == console)
// symbol = "console";
// else if (addr == unknown)
// symbol = "unknown";
// else
// symtab->findSymbol(addr, symbol);
// DPRINTFN("%#x: %s\n", addr, symbol);
// }
} }
#endif #endif

View file

@ -45,22 +45,17 @@
using namespace LittleEndianGuest; using namespace LittleEndianGuest;
MipsSystem::MipsSystem(Params *p) MipsSystem::MipsSystem(Params *p) : System(p)
: System(p)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
if (p->bare_iron == true) { if (p->bare_iron == true) {
hexFile = new HexFile(params()->hex_file_name); hexFile = new HexFile(params()->hex_file_name);
if(!hexFile->loadSections(&functionalPort,MipsISA::LoadAddrMask)) if (!hexFile->loadSections(&functionalPort, MipsISA::LoadAddrMask))
panic("Could not load hex file\n"); panic("Could not load hex file\n");
} }
Addr addr = 0; Addr addr = 0;
/* Comment out old Alpha Based Code
Don't need the console before we start looking at booting linux */
consoleSymtab = new SymbolTable; consoleSymtab = new SymbolTable;
@ -76,7 +71,7 @@ MipsSystem::MipsSystem(Params *p)
if (console == NULL) if (console == NULL)
fatal("Could not load console file %s", params()->console); fatal("Could not load console file %s", params()->console);
//Load program sections into memory //Load program sections into memory
console->loadSections(&functionalPort, MipsISA::LoadAddrMask); console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
//load symbols //load symbols
if (!console->loadGlobalSymbols(consoleSymtab)) if (!console->loadGlobalSymbols(consoleSymtab))
@ -110,100 +105,42 @@ MipsSystem::MipsSystem(Params *p)
if (consoleSymtab->findAddress("m5_rpb", addr)) { if (consoleSymtab->findAddress("m5_rpb", addr)) {
uint64_t data; uint64_t data;
data = htog(params()->system_type); data = htog(params()->system_type);
virtPort.write(addr+0x50, data); virtPort.write(addr + 0x50, data);
data = htog(params()->system_rev); data = htog(params()->system_rev);
virtPort.write(addr+0x58, data); virtPort.write(addr + 0x58, data);
} else } else {
panic("could not find hwrpb\n"); panic("could not find hwrpb\n");
}
#endif #endif
} }
MipsSystem::~MipsSystem() MipsSystem::~MipsSystem()
{ {
} }
#if FULL_SYSTEM
/**
* This function fixes up addresses that are used to match PCs for
* hooking simulator events on to target function executions.
*
* Mips binaries may have multiple global offset table (GOT)
* sections. A function that uses the GOT starts with a
* two-instruction prolog which sets the global pointer (gp == r29) to
* the appropriate GOT section. The proper gp value is calculated
* based on the function address, which must be passed by the caller
* in the procedure value register (pv aka t12 == r27). This sequence
* looks like the following:
*
* opcode Ra Rb offset
* ldah gp,X(pv) 09 29 27 X
* lda gp,Y(gp) 08 29 29 Y
*
* for some constant offsets X and Y. The catch is that the linker
* (or maybe even the compiler, I'm not sure) may recognize that the
* caller and callee are using the same GOT section, making this
* prolog redundant, and modify the call target to skip these
* instructions. If we check for execution of the first instruction
* of a function (the one the symbol points to) to detect when to skip
* it, we'll miss all these modified calls. It might work to
* unconditionally check for the third instruction, but not all
* functions have this prolog, and there's some chance that those
* first two instructions could have undesired consequences. So we do
* the Right Thing and pattern-match the first two instructions of the
* function to decide where to patch.
*
* Eventually this code should be moved into an ISA-specific file.
*/
#if FULL_SYSTEM
Addr Addr
MipsSystem::fixFuncEventAddr(Addr addr) MipsSystem::fixFuncEventAddr(Addr addr)
{ {
/* return addr;
// mask for just the opcode, Ra, and Rb fields (not the offset)
const uint32_t inst_mask = 0xffff0000;
// ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
// lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
uint32_t i1 = virtPort.read<uint32_t>(addr);
uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(MipsISA::MachInst));
if ((i1 & inst_mask) == gp_ldah_pattern &&
(i2 & inst_mask) == gp_lda_pattern) {
Addr new_addr = addr + 2* sizeof(MipsISA::MachInst);
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
return new_addr;
} else {
return addr;
}*/
return addr;
} }
void void
MipsSystem::setMipsAccess(Addr access) MipsSystem::setMipsAccess(Addr access)
{ {}
Addr addr = 0;
if (consoleSymtab->findAddress("m5MipsAccess", addr)) {
// virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access)));
} else
panic("could not find m5MipsAccess\n");
}
#endif #endif
bool bool
MipsSystem::breakpoint() MipsSystem::breakpoint()
{ {
return 0; return 0;
// return remoteGDB[0]->trap(MIPS_KENTRY_INT);
} }
void void
MipsSystem::serialize(std::ostream &os) MipsSystem::serialize(std::ostream &os)
{ {
System::serialize(os); System::serialize(os);
// consoleSymtab->serialize("console_symtab", os);
} }
@ -211,7 +148,6 @@ void
MipsSystem::unserialize(Checkpoint *cp, const std::string &section) MipsSystem::unserialize(Checkpoint *cp, const std::string &section)
{ {
System::unserialize(cp,section); System::unserialize(cp,section);
// consoleSymtab->unserialize("console_symtab", cp, section);
} }
MipsSystem * MipsSystem *

View file

@ -54,10 +54,10 @@ class MipsSystem : public System
virtual bool breakpoint(); virtual bool breakpoint();
/**
* Serialization stuff
*/
public: public:
/**
* Serialization stuff
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
@ -89,7 +89,8 @@ class MipsSystem : public System
#if FULL_SYSTEM #if FULL_SYSTEM
/** Add a function-based event to the console code. */ /** Add a function-based event to the console code. */
template <class T> template <class T>
T *addConsoleFuncEvent(const char *lbl) T *
addConsoleFuncEvent(const char *lbl)
{ {
return addFuncEvent<T>(consoleSymtab, lbl); return addFuncEvent<T>(consoleSymtab, lbl);
} }

View file

@ -56,16 +56,14 @@ using namespace MipsISA;
// MIPS TLB // MIPS TLB
// //
#define MODE2MASK(X) (1 << (X))
static inline mode_type static inline mode_type
getOperatingMode(MiscReg Stat) getOperatingMode(MiscReg Stat)
{ {
if((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) { if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
return mode_kernel; return mode_kernel;
} else if((Stat & 0x18) == 0x8) { } else if ((Stat & 0x18) == 0x8) {
return mode_supervisor; return mode_supervisor;
} else if((Stat & 0x18) == 0x10) { } else if ((Stat & 0x18) == 0x10) {
return mode_user; return mode_user;
} else { } else {
return mode_number; return mode_number;
@ -76,9 +74,9 @@ getOperatingMode(MiscReg Stat)
TLB::TLB(const Params *p) TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), nlu(0) : BaseTLB(p), size(p->size), nlu(0)
{ {
table = new MipsISA::PTE[size]; table = new PTE[size];
memset(table, 0, sizeof(MipsISA::PTE[size])); memset(table, 0, sizeof(PTE[size]));
smallPages=0; smallPages = 0;
} }
TLB::~TLB() TLB::~TLB()
@ -92,23 +90,23 @@ MipsISA::PTE *
TLB::lookup(Addr vpn, uint8_t asn) const TLB::lookup(Addr vpn, uint8_t asn) const
{ {
// assume not found... // assume not found...
MipsISA::PTE *retval = NULL; PTE *retval = NULL;
PageTable::const_iterator i = lookupTable.find(vpn); PageTable::const_iterator i = lookupTable.find(vpn);
if (i != lookupTable.end()) { if (i != lookupTable.end()) {
while (i->first == vpn) { while (i->first == vpn) {
int index = i->second; int index = i->second;
MipsISA::PTE *pte = &table[index]; PTE *pte = &table[index];
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
Addr Mask = pte->Mask; Addr Mask = pte->Mask;
Addr InvMask = ~Mask; Addr InvMask = ~Mask;
Addr VPN = pte->VPN; Addr VPN = pte->VPN;
// warn("Valid: %d - %d\n",pte->V0,pte->V1); if (((vpn & InvMask) == (VPN & InvMask)) &&
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) (pte->G || (asn == pte->asid))) {
{ // We have a VPN + ASID Match // We have a VPN + ASID Match
retval = pte; retval = pte;
break; break;
} }
++i; ++i;
} }
} }
@ -118,119 +116,96 @@ TLB::lookup(Addr vpn, uint8_t asn) const
return retval; return retval;
} }
MipsISA::PTE* TLB::getEntry(unsigned Index) const MipsISA::PTE*
TLB::getEntry(unsigned Index) const
{ {
// Make sure that Index is valid // Make sure that Index is valid
assert(Index<size); assert(Index<size);
return &table[Index]; return &table[Index];
} }
int TLB::probeEntry(Addr vpn,uint8_t asn) const int
TLB::probeEntry(Addr vpn, uint8_t asn) const
{ {
// assume not found... // assume not found...
MipsISA::PTE *retval = NULL; PTE *retval = NULL;
int Ind=-1; int Ind = -1;
PageTable::const_iterator i = lookupTable.find(vpn); PageTable::const_iterator i = lookupTable.find(vpn);
if (i != lookupTable.end()) { if (i != lookupTable.end()) {
while (i->first == vpn) { while (i->first == vpn) {
int index = i->second; int index = i->second;
MipsISA::PTE *pte = &table[index]; PTE *pte = &table[index];
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
Addr Mask = pte->Mask; Addr Mask = pte->Mask;
Addr InvMask = ~Mask; Addr InvMask = ~Mask;
Addr VPN = pte->VPN; Addr VPN = pte->VPN;
if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) if (((vpn & InvMask) == (VPN & InvMask)) &&
{ // We have a VPN + ASID Match (pte->G || (asn == pte->asid))) {
// We have a VPN + ASID Match
retval = pte; retval = pte;
Ind = index; Ind = index;
break; break;
} }
++i; ++i;
} }
} }
DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
return Ind; return Ind;
} }
Fault inline
inline Fault
TLB::checkCacheability(RequestPtr &req) TLB::checkCacheability(RequestPtr &req)
{ {
Addr VAddrUncacheable = 0xA0000000; Addr VAddrUncacheable = 0xA0000000;
// In MIPS, cacheability is controlled by certain bits of the virtual address // In MIPS, cacheability is controlled by certain bits of the virtual
// or by the TLB entry // address or by the TLB entry
if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
// mark request as uncacheable // mark request as uncacheable
req->setFlags(Request::UNCACHEABLE); req->setFlags(Request::UNCACHEABLE);
}
return NoFault;
}
void TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages)
{
smallPages=_smallPages;
if(Index > size){
warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size);
} else {
// Update TLB
DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid
PageTable::iterator i = lookupTable.find(table[Index].VPN);
lookupTable.erase(i);
} }
table[Index]=pte; return NoFault;
// Update fast lookup table }
lookupTable.insert(make_pair(table[Index].VPN, Index));
// int TestIndex=probeEntry(pte.VPN,pte.asid);
// warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
}
void
TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
{
smallPages = _smallPages;
if (Index > size) {
warn("Attempted to write at index (%d) beyond TLB size (%d)",
Index, size);
} else {
// Update TLB
DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
Index, pte.Mask << 11,
((pte.VPN << 11) | pte.asid),
((pte.PFN0 << 6) | (pte.C0 << 3) |
(pte.D0 << 2) | (pte.V0 <<1) | pte.G),
((pte.PFN1 <<6) | (pte.C1 << 3) |
(pte.D1 << 2) | (pte.V1 <<1) | pte.G));
if (table[Index].V0 == true || table[Index].V1 == true) {
// Previous entry is valid
PageTable::iterator i = lookupTable.find(table[Index].VPN);
lookupTable.erase(i);
}
table[Index]=pte;
// Update fast lookup table
lookupTable.insert(make_pair(table[Index].VPN, Index));
}
} }
// insert a new TLB entry // insert a new TLB entry
void void
TLB::insert(Addr addr, MipsISA::PTE &pte) TLB::insert(Addr addr, PTE &pte)
{ {
fatal("TLB Insert not yet implemented\n"); fatal("TLB Insert not yet implemented\n");
/* MipsISA::VAddr vaddr = addr;
if (table[nlu].valid) {
Addr oldvpn = table[nlu].tag;
PageTable::iterator i = lookupTable.find(oldvpn);
if (i == lookupTable.end())
panic("TLB entry not found in lookupTable");
int index;
while ((index = i->second) != nlu) {
if (table[index].tag != oldvpn)
panic("TLB entry not found in lookupTable");
++i;
}
DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
lookupTable.erase(i);
}
DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
table[nlu] = pte;
table[nlu].tag = vaddr.vpn();
table[nlu].valid = true;
lookupTable.insert(make_pair(vaddr.vpn(), nlu));
nextnlu();
*/
} }
void void
TLB::flushAll() TLB::flushAll()
{ {
DPRINTF(TLB, "flushAll\n"); DPRINTF(TLB, "flushAll\n");
memset(table, 0, sizeof(MipsISA::PTE[size])); memset(table, 0, sizeof(PTE[size]));
lookupTable.clear(); lookupTable.clear();
nlu = 0; nlu = 0;
} }
@ -328,68 +303,66 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
Process * p = tc->getProcessPtr(); Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req); Fault fault = p->pTable->translate(req);
if(fault != NoFault) if (fault != NoFault)
return fault; return fault;
return NoFault; return NoFault;
#else #else
if(MipsISA::IsKSeg0(req->getVaddr())) if (IsKSeg0(req->getVaddr())) {
{ // Address will not be translated through TLB, set response, and go!
// Address will not be translated through TLB, set response, and go! req->setPaddr(KSeg02Phys(req->getVaddr()));
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned()) req->isMisaligned()) {
{ AddressErrorFault *Flt = new AddressErrorFault();
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
return Flt;
}
} else if(IsKSeg1(req->getVaddr())) {
// Address will not be translated through TLB, set response, and go!
req->setPaddr(KSeg02Phys(req->getVaddr()));
} else {
/*
* This is an optimization - smallPages is updated every time a TLB
* operation is performed. That way, we don't need to look at
* Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
*/
Addr VPN;
if (smallPages == 1) {
VPN = ((req->getVaddr() >> 11));
} else {
VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
}
uint8_t Asid = req->getAsid();
if (req->isMisaligned()) {
// Unaligned address!
AddressErrorFault *Flt = new AddressErrorFault(); AddressErrorFault *Flt = new AddressErrorFault();
/* BadVAddr must be set */ /* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr(); Flt->BadVAddr = req->getVaddr();
return Flt; return Flt;
}
}
else if(MipsISA::IsKSeg1(req->getVaddr()))
{
// Address will not be translated through TLB, set response, and go!
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
}
else
{
/* This is an optimization - smallPages is updated every time a TLB operation is performed
That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
do a TLB lookup */
Addr VPN;
if(smallPages==1){
VPN=((req->getVaddr() >> 11));
} else {
VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
} }
uint8_t Asid = req->getAsid(); PTE *pte = lookup(VPN,Asid);
if(req->isMisaligned()){ // Unaligned address! if (pte != NULL) {
AddressErrorFault *Flt = new AddressErrorFault(); // Ok, found something
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
return Flt;
}
MipsISA::PTE *pte = lookup(VPN,Asid);
if(pte != NULL)
{// Ok, found something
/* Check for valid bits */ /* Check for valid bits */
int EvenOdd; int EvenOdd;
bool Valid; bool Valid;
if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){ if ((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) == 0) {
// Check even bits // Check even bits
Valid = pte->V0; Valid = pte->V0;
EvenOdd = 0; EvenOdd = 0;
} else { } else {
// Check odd bits // Check odd bits
Valid = pte->V1; Valid = pte->V1;
EvenOdd = 1; EvenOdd = 1;
} }
if(Valid == false) if (Valid == false) {
{//Invalid entry //Invalid entry
ItbInvalidFault *Flt = new ItbInvalidFault(); ItbInvalidFault *Flt = new ItbInvalidFault();
/* EntryHi VPN, ASID fields must be set */ /* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid; Flt->EntryHi_Asid = Asid;
Flt->EntryHi_VPN2 = (VPN>>2); Flt->EntryHi_VPN2 = (VPN >> 2);
Flt->EntryHi_VPN2X = (VPN & 0x3); Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */ /* BadVAddr must be set */
@ -398,43 +371,36 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
/* Context must be set */ /* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2); Flt->Context_BadVPN2 = (VPN >> 2);
return Flt; return Flt;
} } else {
else // Ok, this is really a match, set paddr
{// Ok, this is really a match, set paddr
// hits++;
Addr PAddr; Addr PAddr;
if(EvenOdd == 0){ if (EvenOdd == 0) {
PAddr = pte->PFN0; PAddr = pte->PFN0;
}else{ } else {
PAddr = pte->PFN1; PAddr = pte->PFN1;
} }
PAddr >>= (pte->AddrShiftAmount-12); PAddr >>= (pte->AddrShiftAmount - 12);
PAddr <<= pte->AddrShiftAmount; PAddr <<= pte->AddrShiftAmount;
PAddr |= ((req->getVaddr()) & pte->OffsetMask); PAddr |= ((req->getVaddr()) & pte->OffsetMask);
req->setPaddr(PAddr); req->setPaddr(PAddr);
} }
} } else {
else // Didn't find any match, return a TLB Refill Exception
{ // Didn't find any match, return a TLB Refill Exception ItbRefillFault *Flt=new ItbRefillFault();
// misses++; /* EntryHi VPN, ASID fields must be set */
ItbRefillFault *Flt=new ItbRefillFault(); Flt->EntryHi_Asid = Asid;
/* EntryHi VPN, ASID fields must be set */ Flt->EntryHi_VPN2 = (VPN >> 2);
Flt->EntryHi_Asid = Asid; Flt->EntryHi_VPN2X = (VPN & 0x3);
Flt->EntryHi_VPN2 = (VPN>>2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* BadVAddr must be set */ /* Context must be set */
Flt->BadVAddr = req->getVaddr(); Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
} }
} }
return checkCacheability(req); return checkCacheability(req);
#endif #endif
} }
@ -457,131 +423,118 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
Process * p = tc->getProcessPtr(); Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req); Fault fault = p->pTable->translate(req);
if(fault != NoFault) if (fault != NoFault)
return fault; return fault;
return NoFault; return NoFault;
#else #else
if(MipsISA::IsKSeg0(req->getVaddr())) if (IsKSeg0(req->getVaddr())) {
{ // Address will not be translated through TLB, set response, and go!
// Address will not be translated through TLB, set response, and go! req->setPaddr(KSeg02Phys(req->getVaddr()));
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned()) req->isMisaligned()) {
{ StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); /* BadVAddr must be set */
/* BadVAddr must be set */ Flt->BadVAddr = req->getVaddr();
Flt->BadVAddr = req->getVaddr();
return Flt; return Flt;
} }
} } else if(IsKSeg1(req->getVaddr())) {
else if(MipsISA::IsKSeg1(req->getVaddr()))
{
// Address will not be translated through TLB, set response, and go! // Address will not be translated through TLB, set response, and go!
req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); req->setPaddr(KSeg02Phys(req->getVaddr()));
} } else {
else /*
{ * This is an optimization - smallPages is updated every time a TLB
/* This is an optimization - smallPages is updated every time a TLB operation is performed * operation is performed. That way, we don't need to look at
That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
do a TLB lookup */ */
Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC); Addr VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
if(smallPages==1){ if (smallPages == 1) {
VPN=((req->getVaddr() >> 11)); VPN = ((req->getVaddr() >> 11));
} }
uint8_t Asid = req->getAsid(); uint8_t Asid = req->getAsid();
MipsISA::PTE *pte = lookup(VPN,Asid); PTE *pte = lookup(VPN, Asid);
if(req->isMisaligned()){ // Unaligned address! if (req->isMisaligned()) {
StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); // Unaligned address!
/* BadVAddr must be set */ StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
Flt->BadVAddr = req->getVaddr(); /* BadVAddr must be set */
return Flt; Flt->BadVAddr = req->getVaddr();
} return Flt;
if(pte != NULL) }
{// Ok, found something if (pte != NULL) {
/* Check for valid bits */ // Ok, found something
int EvenOdd; /* Check for valid bits */
bool Valid; int EvenOdd;
bool Dirty; bool Valid;
if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){ bool Dirty;
// Check even bits if (((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) == 0) {
Valid = pte->V0; // Check even bits
Dirty = pte->D0; Valid = pte->V0;
EvenOdd = 0; Dirty = pte->D0;
EvenOdd = 0;
} else { } else {
// Check odd bits // Check odd bits
Valid = pte->V1; Valid = pte->V1;
Dirty = pte->D1; Dirty = pte->D1;
EvenOdd = 1; EvenOdd = 1;
}
if(Valid == false)
{//Invalid entry
// invalids++;
DtbInvalidFault *Flt = new DtbInvalidFault();
/* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid;
Flt->EntryHi_VPN2 = (VPN>>2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
} }
else
{// Ok, this is really a match, set paddr
// hits++;
if(!Dirty)
{
TLBModifiedFault *Flt = new TLBModifiedFault();
/* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid;
Flt->EntryHi_VPN2 = (VPN>>2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
if (Valid == false) {
//Invalid entry
DtbInvalidFault *Flt = new DtbInvalidFault();
/* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid;
Flt->EntryHi_VPN2 = (VPN>>2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */ /* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr(); Flt->BadVAddr = req->getVaddr();
/* Context must be set */ /* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2); Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
return Flt;
} else {
// Ok, this is really a match, set paddr
if (!Dirty) {
TLBModifiedFault *Flt = new TLBModifiedFault();
/* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid;
Flt->EntryHi_VPN2 = (VPN >> 2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
} }
Addr PAddr; Addr PAddr;
if(EvenOdd == 0){ if (EvenOdd == 0) {
PAddr = pte->PFN0; PAddr = pte->PFN0;
}else{ } else {
PAddr = pte->PFN1; PAddr = pte->PFN1;
} }
PAddr >>= (pte->AddrShiftAmount-12); PAddr >>= (pte->AddrShiftAmount - 12);
PAddr <<= pte->AddrShiftAmount; PAddr <<= pte->AddrShiftAmount;
PAddr |= ((req->getVaddr()) & pte->OffsetMask); PAddr |= ((req->getVaddr()) & pte->OffsetMask);
req->setPaddr(PAddr); req->setPaddr(PAddr);
} }
} } else {
else // Didn't find any match, return a TLB Refill Exception
{ // Didn't find any match, return a TLB Refill Exception DtbRefillFault *Flt = new DtbRefillFault();
// misses++; /* EntryHi VPN, ASID fields must be set */
DtbRefillFault *Flt=new DtbRefillFault(); Flt->EntryHi_Asid = Asid;
/* EntryHi VPN, ASID fields must be set */ Flt->EntryHi_VPN2 = (VPN >> 2);
Flt->EntryHi_Asid = Asid; Flt->EntryHi_VPN2X = (VPN & 0x3);
Flt->EntryHi_VPN2 = (VPN>>2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* BadVAddr must be set */ /* Context must be set */
Flt->BadVAddr = req->getVaddr(); Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
} }
} }
return checkCacheability(req); return checkCacheability(req);
@ -609,7 +562,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
MipsISA::PTE & MipsISA::PTE &
TLB::index(bool advance) TLB::index(bool advance)
{ {
MipsISA::PTE *pte = &table[nlu]; PTE *pte = &table[nlu];
if (advance) if (advance)
nextnlu(); nextnlu();
@ -620,5 +573,5 @@ TLB::index(bool advance)
MipsISA::TLB * MipsISA::TLB *
MipsTLBParams::create() MipsTLBParams::create()
{ {
return new MipsISA::TLB(this); return new TLB(this);
} }

View file

@ -35,42 +35,43 @@
namespace MipsISA namespace MipsISA
{ {
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
typedef uint64_t LargestRead; typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
//used in FP convert & round function typedef uint64_t LargestRead;
enum ConvertType{
SINGLE_TO_DOUBLE,
SINGLE_TO_WORD,
SINGLE_TO_LONG,
DOUBLE_TO_SINGLE, //used in FP convert & round function
DOUBLE_TO_WORD, enum ConvertType{
DOUBLE_TO_LONG, SINGLE_TO_DOUBLE,
SINGLE_TO_WORD,
SINGLE_TO_LONG,
LONG_TO_SINGLE, DOUBLE_TO_SINGLE,
LONG_TO_DOUBLE, DOUBLE_TO_WORD,
LONG_TO_WORD, DOUBLE_TO_LONG,
LONG_TO_PS,
WORD_TO_SINGLE, LONG_TO_SINGLE,
WORD_TO_DOUBLE, LONG_TO_DOUBLE,
WORD_TO_LONG, LONG_TO_WORD,
WORD_TO_PS, LONG_TO_PS,
PL_TO_SINGLE, WORD_TO_SINGLE,
PU_TO_SINGLE WORD_TO_DOUBLE,
}; WORD_TO_LONG,
WORD_TO_PS,
//used in FP convert & round function PL_TO_SINGLE,
enum RoundMode{ PU_TO_SINGLE
RND_ZERO, };
RND_DOWN,
RND_UP, //used in FP convert & round function
RND_NEAREST enum RoundMode{
}; RND_ZERO,
RND_DOWN,
RND_UP,
RND_NEAREST
};
struct CoreSpecific { struct CoreSpecific {
/* Note: It looks like it will be better to allow simulator users /* Note: It looks like it will be better to allow simulator users
@ -81,7 +82,8 @@ struct CoreSpecific {
-jpp -jpp
*/ */
// MIPS CP0 State - First individual variables // MIPS CP0 State - First individual variables
// Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM, Volume III (PRA) // Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM,
// Volume III (PRA)
unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt
unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt
unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set
@ -89,7 +91,8 @@ struct CoreSpecific {
unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS) unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS)
unsigned CP0_PRId_ProcessorID; // Page 105 unsigned CP0_PRId_ProcessorID; // Page 105
unsigned CP0_PRId_Revision; // Page 105 unsigned CP0_PRId_Revision; // Page 105
unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor system unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor
//system
unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode
unsigned CP0_Config_AT; //Page 109 unsigned CP0_Config_AT; //Page 109
unsigned CP0_Config_AR; //Page 109 unsigned CP0_Config_AR; //Page 109

View file

@ -45,87 +45,88 @@ class ThreadContext;
namespace MipsISA { namespace MipsISA {
uint64_t getArgument(ThreadContext *tc, int number, bool fp); uint64_t getArgument(ThreadContext *tc, int number, bool fp);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Floating Point Utility Functions // Floating Point Utility Functions
// //
uint64_t fpConvert(ConvertType cvt_type, double fp_val); uint64_t fpConvert(ConvertType cvt_type, double fp_val);
double roundFP(double val, int digits); double roundFP(double val, int digits);
double truncFP(double val); double truncFP(double val);
bool getCondCode(uint32_t fcsr, int cc); bool getCondCode(uint32_t fcsr, int cc);
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val); uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
uint32_t genInvalidVector(uint32_t fcsr); uint32_t genInvalidVector(uint32_t fcsr);
bool isNan(void *val_ptr, int size); bool isNan(void *val_ptr, int size);
bool isQnan(void *val_ptr, int size); bool isQnan(void *val_ptr, int size);
bool isSnan(void *val_ptr, int size); bool isSnan(void *val_ptr, int size);
static inline bool static inline bool
inUserMode(ThreadContext *tc) inUserMode(ThreadContext *tc)
{ {
MiscReg Stat = tc->readMiscReg(MipsISA::Status); MiscReg Stat = tc->readMiscReg(MipsISA::Status);
MiscReg Dbg = tc->readMiscReg(MipsISA::Debug); MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
if((Stat & 0x10000006) == 0 // EXL, ERL or CU0 set, CP0 accessible if ((Stat & 0x10000006) == 0 && // EXL, ERL or CU0 set, CP0 accessible
&& (Dbg & 0x40000000) == 0 // DM bit set, CP0 accessible (Dbg & 0x40000000) == 0 && // DM bit set, CP0 accessible
&& (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
// Unable to use Status_CU0, etc directly, using bitfields & masks // Unable to use Status_CU0, etc directly, using bitfields & masks
return true; return true;
} else { } else {
return false; return false;
}
} }
}
// Instruction address compression hooks // Instruction address compression hooks
static inline Addr realPCToFetchPC(const Addr &addr) { static inline Addr realPCToFetchPC(const Addr &addr) {
return addr; return addr;
} }
static inline Addr fetchPCToRealPC(const Addr &addr) { static inline Addr fetchPCToRealPC(const Addr &addr) {
return addr; return addr;
} }
// the size of "fetched" instructions (not necessarily the size // the size of "fetched" instructions (not necessarily the size
// of real instructions for PISA) // of real instructions for PISA)
static inline size_t fetchInstSize() { static inline size_t fetchInstSize() {
return sizeof(MachInst); return sizeof(MachInst);
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Register File Utility Functions // Register File Utility Functions
// //
static inline MachInst makeRegisterCopy(int dest, int src) { static inline MachInst makeRegisterCopy(int dest, int src) {
panic("makeRegisterCopy not implemented"); panic("makeRegisterCopy not implemented");
return 0; return 0;
} }
template <class CPU> template <class CPU>
void zeroRegisters(CPU *cpu); void zeroRegisters(CPU *cpu);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Translation stuff // Translation stuff
// //
inline Addr inline Addr
TruncPage(Addr addr) TruncPage(Addr addr)
{ return addr & ~(PageBytes - 1); } { return addr & ~(PageBytes - 1); }
inline Addr inline Addr
RoundPage(Addr addr) RoundPage(Addr addr)
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); } { return (addr + PageBytes - 1) & ~(PageBytes - 1); }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// CPU Utility // CPU Utility
// //
void startupCPU(ThreadContext *tc, int cpuId); void startupCPU(ThreadContext *tc, int cpuId);
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
}; };

View file

@ -53,7 +53,8 @@ MipsISA::vtophys(Addr vaddr)
else if(MipsISA::IsKSeg1(vaddr)) else if(MipsISA::IsKSeg1(vaddr))
paddr = MipsISA::KSeg12Phys(vaddr); paddr = MipsISA::KSeg12Phys(vaddr);
else else
panic("vtophys: ptbr is not set on virtual lookup for vaddr %#x", vaddr); panic("vtophys: ptbr is not set on "
"virtual lookup for vaddr %#x", vaddr);
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
@ -63,7 +64,6 @@ MipsISA::vtophys(Addr vaddr)
Addr Addr
MipsISA::vtophys(ThreadContext *tc, Addr addr) MipsISA::vtophys(ThreadContext *tc, Addr addr)
{ {
fatal("VTOPHYS: Unimplemented on MIPS\n"); fatal("VTOPHYS: Unimplemented on MIPS\n");
} }