template<> SparcFaultBase::FaultVals
SparcFault<InterruptLevelN>::vals =
- {"interrupt_level_n", 0x041, 0, {P, P, SH}};
+ {"interrupt_level_n", 0x040, 0, {P, P, SH}};
template<> SparcFaultBase::FaultVals
SparcFault<HstickMatch>::vals =
SparcFault<TrapLevelZero>::vals =
{"trap_level_zero", 0x05F, 202, {H, H, SH}};
+template<> SparcFaultBase::FaultVals
+ SparcFault<InterruptVector>::vals =
+ {"interrupt_vector", 0x060, 2630, {H, H, H}};
+
template<> SparcFaultBase::FaultVals
SparcFault<PAWatchpoint>::vals =
{"PA_watchpoint", 0x061, 1209, {H, H, H}};
{"dev_mondo", 0x07D, 1611, {P, P, SH}};
template<> SparcFaultBase::FaultVals
- SparcFault<ResumeableError>::vals =
+ SparcFault<ResumableError>::vals =
{"resume_error", 0x07E, 3330, {P, P, SH}};
template<> SparcFaultBase::FaultVals
SparcFault<TrapInstruction>::vals =
{"trap_instruction", 0x100, 1602, {P, P, H}};
-#if !FULL_SYSTEM
-template<> SparcFaultBase::FaultVals
- SparcFault<PageTableFault>::vals =
- {"page_table_fault", 0x0000, 0, {SH, SH, SH}};
-#endif
-
/**
* This causes the thread context to enter RED state. This causes the side
* effects which go with entering RED state because of a trap.
{
//@todo Disable the mmu?
//@todo Disable watchpoints?
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
//HPSTATE.red = 1
HPSTATE |= (1 << 5);
//HPSTATE.hpriv = 1
HPSTATE |= (1 << 2);
- tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE);
+ tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
//PSTATE.priv is set to 1 here. The manual says it should be 0, but
//Legion sets it to 1.
- MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
+ MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE);
PSTATE |= (1 << 2);
- tc->setMiscRegWithEffect(MISCREG_PSTATE, PSTATE);
+ tc->setMiscReg(MISCREG_PSTATE, PSTATE);
}
/**
void doREDFault(ThreadContext *tc, TrapType tt)
{
- MiscReg TL = tc->readMiscReg(MISCREG_TL);
- MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
- MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
- MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
- MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
- MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
- MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
- MiscReg GL = tc->readMiscReg(MISCREG_GL);
+ MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
+ MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
+ MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+ MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+ //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR);
+ MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
+ MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
+ MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
+ //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE);
+ MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3);
+ MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
MiscReg PC = tc->readPC();
MiscReg NPC = tc->readNextPC();
TL++;
+ if (bits(PSTATE, 3,3)) {
+ PC &= mask(32);
+ NPC &= mask(32);
+ }
+
//set TSTATE.gl to gl
replaceBits(TSTATE, 42, 40, GL);
//set TSTATE.ccr to ccr
replaceBits(TSTATE, 4, 0, CWP);
//Write back TSTATE
- tc->setMiscReg(MISCREG_TSTATE, TSTATE);
+ tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
//set TPC to PC
- tc->setMiscReg(MISCREG_TPC, PC);
+ tc->setMiscRegNoEffect(MISCREG_TPC, PC);
//set TNPC to NPC
- tc->setMiscReg(MISCREG_TNPC, NPC);
+ tc->setMiscRegNoEffect(MISCREG_TNPC, NPC);
//set HTSTATE.hpstate to hpstate
- tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
+ tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE);
//TT = trap type;
- tc->setMiscReg(MISCREG_TT, tt);
+ tc->setMiscRegNoEffect(MISCREG_TT, tt);
//Update GL
- tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
-
- //set PSTATE.mm to 00
- //set PSTATE.pef to 1
- PSTATE |= (1 << 4);
- //set PSTATE.am to 0
- PSTATE &= ~(1 << 3);
-/* //set PSTATE.priv to 0
- PSTATE &= ~(1 << 2);*/
- //set PSTATE.ie to 0
- //PSTATE.priv is set to 1 here. The manual says it should be 0, but
- //Legion sets it to 1.
- PSTATE |= (1 << 2);
- //set PSTATE.cle to 0
- PSTATE &= ~(1 << 9);
- //PSTATE.tle is unchanged
- //XXX Where is the tct bit?
- //set PSTATE.tct to 0
- tc->setMiscReg(MISCREG_PSTATE, PSTATE);
+ tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL));
+
+ PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit
+ PSTATE |= (1 << 4); //set PSTATE.pef to 1
+ tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE);
//set HPSTATE.red to 1
HPSTATE |= (1 << 5);
HPSTATE &= ~(1 << 10);
//set HPSTATE.tlz to 0
HPSTATE &= ~(1 << 0);
- tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
+ tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE);
bool changedCWP = true;
if(tt == 0x24)
if(changedCWP)
{
CWP = (CWP + NWindows) % NWindows;
- tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
+ tc->setMiscReg(MISCREG_CWP, CWP);
}
}
void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
{
- MiscReg TL = tc->readMiscReg(MISCREG_TL);
- MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
- MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
- MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
- MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
- MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
- MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
- MiscReg GL = tc->readMiscReg(MISCREG_GL);
+ MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
+ MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
+ MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+ MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+ //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR);
+ MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
+ MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
+ MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
+ //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE);
+ MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3);
+ MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
MiscReg PC = tc->readPC();
MiscReg NPC = tc->readNextPC();
+ if (bits(PSTATE, 3,3)) {
+ PC &= mask(32);
+ NPC &= mask(32);
+ }
+
//Increment the trap level
TL++;
- tc->setMiscReg(MISCREG_TL, TL);
+ tc->setMiscRegNoEffect(MISCREG_TL, TL);
//Save off state
replaceBits(TSTATE, 4, 0, CWP);
//Write back TSTATE
- tc->setMiscReg(MISCREG_TSTATE, TSTATE);
+ tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
//set TPC to PC
- tc->setMiscReg(MISCREG_TPC, PC);
+ tc->setMiscRegNoEffect(MISCREG_TPC, PC);
//set TNPC to NPC
- tc->setMiscReg(MISCREG_TNPC, NPC);
+ tc->setMiscRegNoEffect(MISCREG_TNPC, NPC);
//set HTSTATE.hpstate to hpstate
- tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
+ tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE);
//TT = trap type;
- tc->setMiscReg(MISCREG_TT, tt);
+ tc->setMiscRegNoEffect(MISCREG_TT, tt);
//Update the global register level
- if(!gotoHpriv)
- tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL));
+ if (!gotoHpriv)
+ tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxPGL));
else
- tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
+ tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL));
//PSTATE.mm is unchanged
- //PSTATE.pef = whether or not an fpu is present
- //XXX We'll say there's one present, even though there aren't
- //implementations for a decent number of the instructions
- PSTATE |= (1 << 4);
- //PSTATE.am = 0
- PSTATE &= ~(1 << 3);
- if(!gotoHpriv)
- {
- //PSTATE.priv = 1
- PSTATE |= (1 << 2);
- //PSTATE.cle = PSTATE.tle
- replaceBits(PSTATE, 9, 9, PSTATE >> 8);
- }
- else
- {
- //PSTATE.priv = 0
- //PSTATE.priv is set to 1 here. The manual says it should be 0, but
- //Legion sets it to 1.
- PSTATE |= (1 << 2);
- //PSTATE.cle = 0
- PSTATE &= ~(1 << 9);
- }
- //PSTATE.ie = 0
- PSTATE &= ~(1 << 1);
+ PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present
+ PSTATE &= ~(1 << 3); //PSTATE.am = 0
+ PSTATE &= ~(1 << 1); //PSTATE.ie = 0
//PSTATE.tle is unchanged
//PSTATE.tct = 0
- //XXX Where exactly is this field?
- tc->setMiscReg(MISCREG_PSTATE, PSTATE);
- if(gotoHpriv)
+ if (gotoHpriv)
{
- //HPSTATE.red = 0
- HPSTATE &= ~(1 << 5);
- //HPSTATE.hpriv = 1
- HPSTATE |= (1 << 2);
- //HPSTATE.ibe = 0
- HPSTATE &= ~(1 << 10);
+ PSTATE &= ~(1 << 9); // PSTATE.cle = 0
+ //The manual says PSTATE.priv should be 0, but Legion leaves it alone
+ HPSTATE &= ~(1 << 5); //HPSTATE.red = 0
+ HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1
+ HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0
//HPSTATE.tlz is unchanged
- tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
+ tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE);
+ } else { // we are going to priv
+ PSTATE |= (1 << 2); //PSTATE.priv = 1
+ replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle
}
+ tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE);
+
bool changedCWP = true;
- if(tt == 0x24)
+ if (tt == 0x24)
CWP++;
- else if(0x80 <= tt && tt <= 0xbf)
+ else if (0x80 <= tt && tt <= 0xbf)
CWP += (CANSAVE + 2);
- else if(0xc0 <= tt && tt <= 0xff)
+ else if (0xc0 <= tt && tt <= 0xff)
CWP--;
else
changedCWP = false;
- if(changedCWP)
+ if (changedCWP)
{
CWP = (CWP + NWindows) % NWindows;
- tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
+ tc->setMiscReg(MISCREG_CWP, CWP);
}
}
void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT)
{
- Addr HTBA = tc->readMiscReg(MISCREG_HTBA);
+ Addr HTBA = tc->readMiscRegNoEffect(MISCREG_HTBA);
PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14));
NPC = PC + sizeof(MachInst);
}
void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL)
{
- Addr TBA = tc->readMiscReg(MISCREG_TBA);
+ Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA);
PC = (TBA & ~mask(15)) |
(TL > 1 ? (1 << 14) : 0) |
((TT << 5) & mask(14));
//We can refer to this to see what the trap level -was-, but something
//in the middle could change it in the regfile out from under us.
- MiscReg TL = tc->readMiscReg(MISCREG_TL);
- MiscReg TT = tc->readMiscReg(MISCREG_TT);
- MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL);
+ MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT);
+ MiscReg pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+ MiscReg hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
Addr PC, NPC;
PrivilegeLevel current;
- if(HPSTATE & (1 << 2))
+ if (hpstate & HPSTATE::hpriv)
current = Hyperprivileged;
- else if(PSTATE & (1 << 2))
+ else if (pstate & PSTATE::priv)
current = Privileged;
else
current = User;
PrivilegeLevel level = getNextLevel(current);
- if(HPSTATE & (1 << 5) || TL == MaxTL - 1) {
+ if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) {
getREDVector(5, PC, NPC);
- doREDFault(tc, TT);
+ doREDFault(tc, tt);
//This changes the hpstate and pstate, so we need to make sure we
//save the old version on the trap stack in doREDFault.
enterREDState(tc);
- } else if(TL == MaxTL) {
+ } else if (tl == MaxTL) {
panic("Should go to error state here.. crap\n");
//Do error_state somehow?
//Probably inject a WDR fault using the interrupt mechanism.
//What should the PC and NPC be set to?
- } else if(TL > MaxPTL && level == Privileged) {
+ } else if (tl > MaxPTL && level == Privileged) {
//guest_watchdog fault
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, 2);
- } else if(level == Hyperprivileged ||
- level == Privileged && trapType() >= 384) {
+ } else if (level == Hyperprivileged ||
+ (level == Privileged && trapType() >= 384)) {
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, trapType());
} else {
doNormalFault(tc, trapType(), false);
- getPrivVector(tc, PC, NPC, trapType(), TL+1);
+ getPrivVector(tc, PC, NPC, trapType(), tl+1);
}
tc->setPC(PC);
//on reset Trap which sets the processor into the following state.
//Bits that aren't set aren't defined on startup.
- tc->setMiscReg(MISCREG_TL, MaxTL);
- tc->setMiscReg(MISCREG_TT, trapType());
- tc->setMiscRegWithEffect(MISCREG_GL, MaxGL);
+ tc->setMiscRegNoEffect(MISCREG_TL, MaxTL);
+ tc->setMiscRegNoEffect(MISCREG_TT, trapType());
+ tc->setMiscReg(MISCREG_GL, MaxGL);
//Turn on pef and priv, set everything else to 0
- tc->setMiscReg(MISCREG_PSTATE, (1 << 4) | (1 << 2));
+ tc->setMiscRegNoEffect(MISCREG_PSTATE, (1 << 4) | (1 << 2));
//Turn on red and hpriv, set everything else to 0
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
//HPSTATE.red = 1
HPSTATE |= (1 << 5);
//HPSTATE.hpriv = 1
HPSTATE &= ~(1 << 10);
//HPSTATE.tlz = 0
HPSTATE &= ~(1 << 0);
- tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
+ tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE);
//The tick register is unreadable by nonprivileged software
- tc->setMiscReg(MISCREG_TICK, 1ULL << 63);
+ tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63);
//Enter RED state. We do this last so that the actual state preserved in
//the trap stack is the state from before this fault.
// Clear all the soft interrupt bits
softint = 0;
// disable timer compare interrupts, reset tick_cmpr
- tc->setMiscReg(MISCREG_
+ tc->setMiscRegNoEffect(MISCREG_
tick_cmprFields.int_dis = 1;
tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
stickFields.npt = 1; //The TICK register is unreadable by by !priv
#else // !FULL_SYSTEM
+void FastInstructionAccessMMUMiss::invoke(ThreadContext *tc)
+{
+ Process *p = tc->getProcessPtr();
+ TlbEntry entry;
+ bool success = p->pTable->lookup(vaddr, entry);
+ if(!success) {
+ panic("Tried to execute unmapped address %#x.\n", vaddr);
+ } else {
+ Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/,
+ p->M5_pid /*context id*/, false, entry.pte);
+ }
+}
+
+void FastDataAccessMMUMiss::invoke(ThreadContext *tc)
+{
+ Process *p = tc->getProcessPtr();
+ TlbEntry entry;
+ bool success = p->pTable->lookup(vaddr, entry);
+ if(!success) {
+ p->checkAndAllocNextPage(vaddr);
+ success = p->pTable->lookup(vaddr, entry);
+ }
+ if(!success) {
+ panic("Tried to access unmapped address %#x.\n", vaddr);
+ } else {
+ Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/,
+ p->M5_pid /*context id*/, false, entry.pte);
+ }
+}
+
void SpillNNormal::invoke(ThreadContext *tc)
{
doNormalFault(tc, trapType(), false);
tc->setNextNPC(fillStart + 2*sizeof(MachInst));
}
-void PageTableFault::invoke(ThreadContext *tc)
+void TrapInstruction::invoke(ThreadContext *tc)
{
+ //In SE, this mechanism is how the process requests a service from the
+ //operating system. We'll get the process object from the thread context
+ //and let it service the request.
+
Process *p = tc->getProcessPtr();
- // address is higher than the stack region or in the current stack region
- if (vaddr > p->stack_base || vaddr > p->stack_min)
- FaultBase::invoke(tc);
-
- // We've accessed the next page
- if (vaddr > p->stack_min - PageBytes) {
- p->stack_min -= PageBytes;
- if (p->stack_base - p->stack_min > 8*1024*1024)
- fatal("Over max stack size for one thread\n");
- p->pTable->allocate(p->stack_min, PageBytes);
- warn("Increasing stack size by one page.");
- } else {
- FaultBase::invoke(tc);
- }
+ SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
+ assert(lp);
+
+ lp->handleTrap(_n, tc);
+
+ //We need to explicitly advance the pc, since that's not done for us
+ //on a faulting instruction
+ tc->setPC(tc->readNextPC());
+ tc->setNextPC(tc->readNextNPC());
+ tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
}
#endif