X86: All x86 fault classes now attempt to do something useful.

This commit is contained in:
Gabe Black 2009-02-01 17:09:08 -08:00
parent 923a14dde7
commit 5a4eed5d34
3 changed files with 69 additions and 25 deletions

View file

@ -101,35 +101,68 @@
namespace X86ISA namespace X86ISA
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
void X86Trap::invoke(ThreadContext * tc) void X86FaultBase::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)
{ {
using namespace X86ISAInst::RomLabels; using namespace X86ISAInst::RomLabels;
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
MicroPC entry; MicroPC entry;
if (m5reg.mode == LongMode) { if (m5reg.mode == LongMode) {
entry = extern_label_longModeInterrupt; if (isSoft()) {
entry = extern_label_longModeSoftInterrupt;
} else {
entry = extern_label_longModeInterrupt;
}
} else { } else {
entry = extern_label_legacyModeInterrupt; entry = extern_label_legacyModeInterrupt;
} }
tc->setIntReg(INTREG_MICRO(1), vector); tc->setIntReg(INTREG_MICRO(1), vector);
tc->setIntReg(INTREG_MICRO(7), tc->readPC()); tc->setIntReg(INTREG_MICRO(7), tc->readPC());
if (errorCode != (uint64_t)(-1)) { 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->setIntReg(INTREG_MICRO(15), errorCode);
} }
tc->setMicroPC(romMicroPC(entry)); tc->setMicroPC(romMicroPC(entry));
tc->setNextMicroPC(romMicroPC(entry) + 1); 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) void FakeITLBFault::invoke(ThreadContext * tc)
{ {
// Start the page table walker. // Start the page table walker.

View file

@ -95,11 +95,14 @@ namespace X86ISA
return mnem; return mnem;
} }
void virtual bool isSoft()
invoke(ThreadContext * tc)
{ {
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 // 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) : const uint8_t _vector, uint64_t _errorCode = -1) :
X86FaultBase(name, mnem, _vector, _errorCode) X86FaultBase(name, mnem, _vector, _errorCode)
{} {}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
}; };
class UnimpInstFault : public FaultBase class UnimpInstFault : public FaultBase
@ -321,13 +320,16 @@ namespace X86ISA
Bitfield<4> fetch; Bitfield<4> fetch;
EndBitUnion(PageFaultErrorCode) EndBitUnion(PageFaultErrorCode)
Addr addr;
public: public:
PageFault(uint32_t _errorCode) : PageFault(Addr _addr, uint32_t _errorCode) :
X86Fault("Page-Fault", "#PF", 14, _errorCode) X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
{} {}
PageFault(bool present, bool write, bool user,
bool reserved, bool fetch) : PageFault(Addr _addr, bool present, bool write,
X86Fault("Page-Fault", "#PF", 14, 0) bool user, bool reserved, bool fetch) :
X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
{ {
PageFaultErrorCode code = 0; PageFaultErrorCode code = 0;
code.present = present; code.present = present;
@ -337,6 +339,10 @@ namespace X86ISA
code.fetch = fetch; code.fetch = fetch;
errorCode = code; errorCode = code;
} }
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
}; };
class X87FpExceptionPending : public X86Fault class X87FpExceptionPending : public X86Fault
@ -410,6 +416,11 @@ namespace X86ISA
SoftwareInterrupt(uint8_t _vector) : SoftwareInterrupt(uint8_t _vector) :
X86Interrupt("Software Interrupt", "INTn", _vector) X86Interrupt("Software Interrupt", "INTn", _vector)
{} {}
bool isSoft()
{
return true;
}
}; };
// These faults aren't part of the ISA definition. They trigger filling // These faults aren't part of the ISA definition. They trigger filling

View file

@ -95,7 +95,7 @@ def rom
# If we're here, it's because the stack isn't being switched. # If we're here, it's because the stack isn't being switched.
# Set t6 to the new aligned rsp. # Set t6 to the new aligned rsp.
mov t6, rsp, dataSize=8 mov t6, t6, rsp, dataSize=8
andi t6, t6, 0xF0, dataSize=1 andi t6, t6, 0xF0, dataSize=1
subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8