MIPS: Consolidate TLB related faults.
Pass in a bool to indicate if the fault is from a store instead of having two different classes. The classes were also misleadingly named since loads are also processed by the DTB but should return ITB faults since they aren't stores. The TLB may be returning the wrong fault in this case, but I haven't looked at it closely.
This commit is contained in:
parent
efcded334c
commit
48b6636d01
3 changed files with 23 additions and 117 deletions
|
@ -85,17 +85,11 @@ template <> FaultVals MipsFault<TrapFault>::vals =
|
||||||
template <> FaultVals MipsFault<BreakpointFault>::vals =
|
template <> FaultVals MipsFault<BreakpointFault>::vals =
|
||||||
{ "Breakpoint", 0x0180 };
|
{ "Breakpoint", 0x0180 };
|
||||||
|
|
||||||
template <> FaultVals MipsFault<ItbInvalidFault>::vals =
|
template <> FaultVals MipsFault<TlbInvalidFault>::vals =
|
||||||
{ "Invalid TLB Entry Exception (I-Fetch/LW)", 0x0180 };
|
{ "Invalid TLB Entry Exception", 0x0180 };
|
||||||
|
|
||||||
template <> FaultVals MipsFault<ItbRefillFault>::vals =
|
template <> FaultVals MipsFault<TlbRefillFault>::vals =
|
||||||
{ "TLB Refill Exception (I-Fetch/LW)", 0x0180 };
|
{ "TLB Refill Exception", 0x0180 };
|
||||||
|
|
||||||
template <> FaultVals MipsFault<DtbInvalidFault>::vals =
|
|
||||||
{ "Invalid TLB Entry Exception (Store)", 0x0180 };
|
|
||||||
|
|
||||||
template <> FaultVals MipsFault<DtbRefillFault>::vals =
|
|
||||||
{ "TLB Refill Exception (Store)", 0x0180 };
|
|
||||||
|
|
||||||
template <> FaultVals MipsFault<TLBModifiedFault>::vals =
|
template <> FaultVals MipsFault<TLBModifiedFault>::vals =
|
||||||
{ "TLB Modified Exception", 0x0180 };
|
{ "TLB Modified Exception", 0x0180 };
|
||||||
|
@ -199,9 +193,10 @@ BreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DtbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
TlbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
||||||
|
setExceptionState(tc, store ? 0x3 : 0x2);
|
||||||
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
||||||
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
||||||
|
@ -213,8 +208,6 @@ DtbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
|
ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
|
||||||
context.badVPN2 = contextBadVPN2;
|
context.badVPN2 = contextBadVPN2;
|
||||||
tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
|
tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
|
||||||
setExceptionState(tc, 0x3);
|
|
||||||
|
|
||||||
|
|
||||||
// Set new PC
|
// Set new PC
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
|
@ -238,35 +231,11 @@ AddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ItbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
TlbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
{
|
|
||||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
|
||||||
setExceptionState(tc, 0x2);
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
|
||||||
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
|
||||||
entryHi.asid = entryHiAsid;
|
|
||||||
entryHi.vpn2 = entryHiVPN2;
|
|
||||||
entryHi.vpn2x = entryHiVPN2X;
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
|
|
||||||
|
|
||||||
ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
|
|
||||||
context.badVPN2 = contextBadVPN2;
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
|
|
||||||
|
|
||||||
|
|
||||||
// Set new PC
|
|
||||||
Addr HandlerBase;
|
|
||||||
// Offset 0x180 - General Exception Vector
|
|
||||||
HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
|
|
||||||
setHandlerPC(HandlerBase,tc);
|
|
||||||
DPRINTF(MipsPRA, "Exception Handler At: %x , EPC set to %x\n",
|
|
||||||
HandlerBase, tc->readMiscReg(MISCREG_EPC));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ItbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
|
||||||
{
|
{
|
||||||
DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR);
|
DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR);
|
||||||
|
setExceptionState(tc, store ? 0x3 : 0x2);
|
||||||
|
|
||||||
Addr HandlerBase;
|
Addr HandlerBase;
|
||||||
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
||||||
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
||||||
|
@ -288,41 +257,6 @@ ItbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
||||||
// Offset 0x000
|
// Offset 0x000
|
||||||
HandlerBase = tc->readMiscReg(MISCREG_EBASE);
|
HandlerBase = tc->readMiscReg(MISCREG_EBASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
setExceptionState(tc, 0x2);
|
|
||||||
setHandlerPC(HandlerBase, tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DtbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
|
|
||||||
{
|
|
||||||
// Set new PC
|
|
||||||
DPRINTF(MipsPRA, "%s encountered.\n", name());
|
|
||||||
Addr HandlerBase;
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
|
|
||||||
EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
|
|
||||||
entryHi.asid = entryHiAsid;
|
|
||||||
entryHi.vpn2 = entryHiVPN2;
|
|
||||||
entryHi.vpn2x = entryHiVPN2X;
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
|
|
||||||
|
|
||||||
ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
|
|
||||||
context.badVPN2 = contextBadVPN2;
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
|
|
||||||
|
|
||||||
StatusReg status = tc->readMiscReg(MISCREG_STATUS);
|
|
||||||
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
|
||||||
// See MIPS ARM Vol 3, Revision 2, Page 38
|
|
||||||
if (status.exl) {
|
|
||||||
// Offset 0x180 - General Exception Vector
|
|
||||||
HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
|
|
||||||
} else {
|
|
||||||
// Offset 0x000
|
|
||||||
HandlerBase = tc->readMiscReg(MISCREG_EBASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
setExceptionState(tc, 0x3);
|
|
||||||
|
|
||||||
setHandlerPC(HandlerBase, tc);
|
setHandlerPC(HandlerBase, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,10 +199,13 @@ class BreakpointFault : public MipsFault<BreakpointFault>
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class ItbRefillFault : public MipsFault<ItbRefillFault>
|
class TlbRefillFault : public MipsFault<TlbRefillFault>
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
bool store;
|
||||||
public:
|
public:
|
||||||
ItbRefillFault(Addr asid, Addr vaddr, Addr vpn)
|
TlbRefillFault(Addr asid, Addr vaddr, Addr vpn, bool _store) :
|
||||||
|
store(_store)
|
||||||
{
|
{
|
||||||
entryHiAsid = asid;
|
entryHiAsid = asid;
|
||||||
entryHiVPN2 = vpn >> 2;
|
entryHiVPN2 = vpn >> 2;
|
||||||
|
@ -216,27 +219,13 @@ class ItbRefillFault : public MipsFault<ItbRefillFault>
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class DtbRefillFault : public MipsFault<DtbRefillFault>
|
class TlbInvalidFault : public MipsFault<TlbInvalidFault>
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
bool store;
|
||||||
public:
|
public:
|
||||||
DtbRefillFault(Addr asid, Addr vaddr, Addr vpn)
|
TlbInvalidFault(Addr asid, Addr vaddr, Addr vpn, bool _store) :
|
||||||
{
|
store(_store)
|
||||||
entryHiAsid = asid;
|
|
||||||
entryHiVPN2 = vpn >> 2;
|
|
||||||
entryHiVPN2X = vpn & 0x3;
|
|
||||||
badVAddr = vaddr;
|
|
||||||
contextBadVPN2 = vpn >> 2;
|
|
||||||
}
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
void invoke(ThreadContext * tc,
|
|
||||||
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class ItbInvalidFault : public MipsFault<ItbInvalidFault>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ItbInvalidFault(Addr asid, Addr vaddr, Addr vpn)
|
|
||||||
{
|
{
|
||||||
entryHiAsid = asid;
|
entryHiAsid = asid;
|
||||||
entryHiVPN2 = vpn >> 2;
|
entryHiVPN2 = vpn >> 2;
|
||||||
|
@ -267,23 +256,6 @@ class TLBModifiedFault : public MipsFault<TLBModifiedFault>
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class DtbInvalidFault : public MipsFault<DtbInvalidFault>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DtbInvalidFault(Addr asid, Addr vaddr, Addr vpn)
|
|
||||||
{
|
|
||||||
entryHiAsid = asid;
|
|
||||||
entryHiVPN2 = vpn >> 2;
|
|
||||||
entryHiVPN2X = vpn & 0x3;
|
|
||||||
badVAddr = vaddr;
|
|
||||||
contextBadVPN2 = vpn >> 2;
|
|
||||||
}
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
void invoke(ThreadContext * tc,
|
|
||||||
StaticInst::StaticInstPtr inst = nullStaticInstPtr);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class DspStateDisabledFault : public MipsFault<DspStateDisabledFault>
|
class DspStateDisabledFault : public MipsFault<DspStateDisabledFault>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -352,7 +352,7 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Valid == false) {
|
if (Valid == false) {
|
||||||
return new ItbInvalidFault(Asid, vaddr, vpn);
|
return new InvalidFault(Asid, vaddr, vpn, false);
|
||||||
} else {
|
} else {
|
||||||
// Ok, this is really a match, set paddr
|
// Ok, this is really a match, set paddr
|
||||||
Addr PAddr;
|
Addr PAddr;
|
||||||
|
@ -368,7 +368,7 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Didn't find any match, return a TLB Refill Exception
|
// Didn't find any match, return a TLB Refill Exception
|
||||||
return new ItbRefillFault(Asid, vaddr, vpn);
|
return new RefillFault(Asid, vaddr, vpn, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkCacheability(req);
|
return checkCacheability(req);
|
||||||
|
@ -447,7 +447,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Valid == false) {
|
if (Valid == false) {
|
||||||
return new DtbInvalidFault(Asid, vaddr, VPN);
|
return new InvalidFault(Asid, vaddr, VPN, true);
|
||||||
} else {
|
} else {
|
||||||
// Ok, this is really a match, set paddr
|
// Ok, this is really a match, set paddr
|
||||||
if (!Dirty) {
|
if (!Dirty) {
|
||||||
|
@ -466,7 +466,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Didn't find any match, return a TLB Refill Exception
|
// Didn't find any match, return a TLB Refill Exception
|
||||||
return new DtbRefillFault(Asid, vaddr, VPN);
|
return new RefillFault(Asid, vaddr, VPN, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkCacheability(req);
|
return checkCacheability(req);
|
||||||
|
|
Loading…
Reference in a new issue