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) { diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 9c9cf3909..6a6dfc80a 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -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 diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index ea41d2ca8..1345c3d05 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -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