X86: All x86 fault classes now attempt to do something useful.
This commit is contained in:
parent
923a14dde7
commit
5a4eed5d34
3 changed files with 69 additions and 25 deletions
|
@ -101,34 +101,67 @@
|
|||
namespace X86ISA
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
void X86Trap::invoke(ThreadContext * tc)
|
||||
{
|
||||
panic("X86 faults are not implemented!");
|
||||
}
|
||||
|
||||
void X86Abort::invoke(ThreadContext * tc)
|
||||
{
|
||||
panic("X86 faults are not implemented!");
|
||||
}
|
||||
|
||||
void X86Interrupt::invoke(ThreadContext * tc)
|
||||
void X86FaultBase::invoke(ThreadContext * tc)
|
||||
{
|
||||
using namespace X86ISAInst::RomLabels;
|
||||
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
||||
MicroPC entry;
|
||||
if (m5reg.mode == LongMode) {
|
||||
entry = extern_label_longModeInterrupt;
|
||||
if (isSoft()) {
|
||||
entry = extern_label_longModeSoftInterrupt;
|
||||
} else {
|
||||
entry = extern_label_longModeInterrupt;
|
||||
}
|
||||
} else {
|
||||
entry = extern_label_legacyModeInterrupt;
|
||||
}
|
||||
tc->setIntReg(INTREG_MICRO(1), vector);
|
||||
tc->setIntReg(INTREG_MICRO(7), tc->readPC());
|
||||
if (errorCode != (uint64_t)(-1)) {
|
||||
if (m5reg.mode == LongMode) {
|
||||
entry = extern_label_longModeInterruptWithError;
|
||||
} else {
|
||||
panic("Legacy mode interrupts with error codes "
|
||||
"aren't implementde.\n");
|
||||
}
|
||||
// Software interrupts shouldn't have error codes. If one does,
|
||||
// there would need to be microcode to set it up.
|
||||
assert(!isSoft());
|
||||
tc->setIntReg(INTREG_MICRO(15), errorCode);
|
||||
}
|
||||
tc->setMicroPC(romMicroPC(entry));
|
||||
tc->setNextMicroPC(romMicroPC(entry) + 1);
|
||||
}
|
||||
|
||||
void X86Trap::invoke(ThreadContext * tc)
|
||||
{
|
||||
X86FaultBase::invoke(tc);
|
||||
// This is the same as a fault, but it happens -after- the instruction.
|
||||
tc->setPC(tc->readNextPC());
|
||||
tc->setNextPC(tc->readNextNPC());
|
||||
tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
|
||||
}
|
||||
|
||||
void X86Abort::invoke(ThreadContext * tc)
|
||||
{
|
||||
panic("Abort exception!");
|
||||
}
|
||||
|
||||
void PageFault::invoke(ThreadContext * tc)
|
||||
{
|
||||
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
||||
X86FaultBase::invoke(tc);
|
||||
/*
|
||||
* If something bad happens while trying to enter the page fault
|
||||
* handler, I'm pretty sure that's a double fault and then all bets are
|
||||
* off. That means it should be safe to update this state now.
|
||||
*/
|
||||
if (m5reg.mode == LongMode) {
|
||||
tc->setMiscReg(MISCREG_CR2, addr);
|
||||
} else {
|
||||
tc->setMiscReg(MISCREG_CR2, (uint32_t)addr);
|
||||
}
|
||||
}
|
||||
|
||||
void FakeITLBFault::invoke(ThreadContext * tc)
|
||||
{
|
||||
|
|
|
@ -95,11 +95,14 @@ namespace X86ISA
|
|||
return mnem;
|
||||
}
|
||||
|
||||
void
|
||||
invoke(ThreadContext * tc)
|
||||
virtual bool isSoft()
|
||||
{
|
||||
panic("Unimplemented fault %s.\n", name());
|
||||
return false;
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
// Base class for x86 faults which behave as if the underlying instruction
|
||||
|
@ -150,10 +153,6 @@ namespace X86ISA
|
|||
const uint8_t _vector, uint64_t _errorCode = -1) :
|
||||
X86FaultBase(name, mnem, _vector, _errorCode)
|
||||
{}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class UnimpInstFault : public FaultBase
|
||||
|
@ -321,13 +320,16 @@ namespace X86ISA
|
|||
Bitfield<4> fetch;
|
||||
EndBitUnion(PageFaultErrorCode)
|
||||
|
||||
Addr addr;
|
||||
|
||||
public:
|
||||
PageFault(uint32_t _errorCode) :
|
||||
X86Fault("Page-Fault", "#PF", 14, _errorCode)
|
||||
PageFault(Addr _addr, uint32_t _errorCode) :
|
||||
X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
|
||||
{}
|
||||
PageFault(bool present, bool write, bool user,
|
||||
bool reserved, bool fetch) :
|
||||
X86Fault("Page-Fault", "#PF", 14, 0)
|
||||
|
||||
PageFault(Addr _addr, bool present, bool write,
|
||||
bool user, bool reserved, bool fetch) :
|
||||
X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
|
||||
{
|
||||
PageFaultErrorCode code = 0;
|
||||
code.present = present;
|
||||
|
@ -337,6 +339,10 @@ namespace X86ISA
|
|||
code.fetch = fetch;
|
||||
errorCode = code;
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class X87FpExceptionPending : public X86Fault
|
||||
|
@ -410,6 +416,11 @@ namespace X86ISA
|
|||
SoftwareInterrupt(uint8_t _vector) :
|
||||
X86Interrupt("Software Interrupt", "INTn", _vector)
|
||||
{}
|
||||
|
||||
bool isSoft()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// These faults aren't part of the ISA definition. They trigger filling
|
||||
|
|
|
@ -95,7 +95,7 @@ def rom
|
|||
|
||||
# If we're here, it's because the stack isn't being switched.
|
||||
# Set t6 to the new aligned rsp.
|
||||
mov t6, rsp, dataSize=8
|
||||
mov t6, t6, rsp, dataSize=8
|
||||
andi t6, t6, 0xF0, dataSize=1
|
||||
subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8
|
||||
|
||||
|
|
Loading…
Reference in a new issue