summaryrefslogtreecommitdiff
path: root/src/arch/x86/faults.cc
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-02-01 17:09:08 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-02-01 17:09:08 -0800
commit5a4eed5d34c814486086bf45d7750905de32d972 (patch)
treef29003f1a2e6cf8072fb9c4c1514b4381807290f /src/arch/x86/faults.cc
parent923a14dde749ad6b1887ccea764439a167555772 (diff)
downloadgem5-5a4eed5d34c814486086bf45d7750905de32d972.tar.xz
X86: All x86 fault classes now attempt to do something useful.
Diffstat (limited to 'src/arch/x86/faults.cc')
-rw-r--r--src/arch/x86/faults.cc57
1 files changed, 45 insertions, 12 deletions
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc
index 7702d98eb..1234e68e5 100644
--- a/src/arch/x86/faults.cc
+++ b/src/arch/x86/faults.cc
@@ -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)
{