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)
{
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
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
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;
code.fetch = fetch;
errorCode = code;
}
+
+#if FULL_SYSTEM
+ void invoke(ThreadContext * tc);
+#endif
};
class X87FpExceptionPending : public X86Fault
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
# 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