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
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue