x86: Style fixes in x86's fault implementations.
authorGabe Black <gabeblack@google.com>
Mon, 24 Aug 2020 07:53:43 +0000 (00:53 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 25 Aug 2020 06:25:03 +0000 (06:25 +0000)
Change-Id: I320877a7e753eae5ffba2421e6dfe23b52352664
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/33279
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
src/arch/x86/faults.cc
src/arch/x86/faults.hh

index 0754da3887abcf9cf468abfd0a220469270ed475..36cc47e43cad2dc5b4e07c67b13aa68dd86ae1d0 100644 (file)
 
 namespace X86ISA
 {
-    void X86FaultBase::invoke(ThreadContext * tc, const StaticInstPtr &inst)
-    {
-        if (!FullSystem) {
-            FaultBase::invoke(tc, inst);
-            return;
-        }
 
-        PCState pcState = tc->pcState();
-        Addr pc = pcState.pc();
-        DPRINTF(Faults, "RIP %#x: vector %d: %s\n",
-                pc, vector, describe());
-        using namespace X86ISAInst::RomLabels;
-        HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
-        MicroPC entry;
+void
+X86FaultBase::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    if (!FullSystem) {
+        FaultBase::invoke(tc, inst);
+        return;
+    }
+
+    PCState pcState = tc->pcState();
+    Addr pc = pcState.pc();
+    DPRINTF(Faults, "RIP %#x: vector %d: %s\n", pc, vector, describe());
+    using namespace X86ISAInst::RomLabels;
+    HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+    MicroPC entry;
+    if (m5reg.mode == LongMode) {
+        entry = isSoft() ? extern_label_longModeSoftInterrupt :
+                           extern_label_longModeInterrupt;
+    } else {
+        entry = extern_label_legacyModeInterrupt;
+    }
+    tc->setIntReg(INTREG_MICRO(1), vector);
+    tc->setIntReg(INTREG_MICRO(7), pc);
+    if (errorCode != (uint64_t)(-1)) {
         if (m5reg.mode == LongMode) {
-            if (isSoft()) {
-                entry = extern_label_longModeSoftInterrupt;
-            } else {
-                entry = extern_label_longModeInterrupt;
-            }
+            entry = extern_label_longModeInterruptWithError;
         } else {
-            entry = extern_label_legacyModeInterrupt;
+            panic("Legacy mode interrupts with error codes "
+                    "aren't implemented.");
         }
-        tc->setIntReg(INTREG_MICRO(1), vector);
-        tc->setIntReg(INTREG_MICRO(7), pc);
-        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);
-        }
-        pcState.upc(romMicroPC(entry));
-        pcState.nupc(romMicroPC(entry) + 1);
-        tc->pcState(pcState);
+        // 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);
     }
+    pcState.upc(romMicroPC(entry));
+    pcState.nupc(romMicroPC(entry) + 1);
+    tc->pcState(pcState);
+}
 
-    std::string
-    X86FaultBase::describe() const
-    {
-        std::stringstream ss;
-        ccprintf(ss, "%s", mnemonic());
-        if (errorCode != (uint64_t)(-1)) {
-            ccprintf(ss, "(%#x)", errorCode);
-        }
-
-        return ss.str();
-    }
+std::string
+X86FaultBase::describe() const
+{
+    std::stringstream ss;
+    ccprintf(ss, "%s", mnemonic());
+    if (errorCode != (uint64_t)(-1))
+        ccprintf(ss, "(%#x)", errorCode);
 
-    void X86Trap::invoke(ThreadContext * tc, const StaticInstPtr &inst)
-    {
-        X86FaultBase::invoke(tc);
-        if (!FullSystem)
-            return;
+    return ss.str();
+}
 
-        // This is the same as a fault, but it happens -after- the
-        // instruction.
-        PCState pc = tc->pcState();
-        pc.uEnd();
-    }
+void
+X86Trap::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    X86FaultBase::invoke(tc);
+    if (!FullSystem)
+        return;
+
+    // This is the same as a fault, but it happens -after- the
+    // instruction.
+    PCState pc = tc->pcState();
+    pc.uEnd();
+}
+
+void
+X86Abort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    panic("Abort exception!");
+}
 
-    void X86Abort::invoke(ThreadContext * tc, const StaticInstPtr &inst)
-    {
-        panic("Abort exception!");
+void
+InvalidOpcode::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    if (FullSystem) {
+        X86Fault::invoke(tc, inst);
+    } else {
+        panic("Unrecognized/invalid instruction executed:\n %s",
+                inst->machInst);
     }
+}
 
-    void
-    InvalidOpcode::invoke(ThreadContext * tc, const StaticInstPtr &inst)
-    {
-        if (FullSystem) {
-            X86Fault::invoke(tc, inst);
+void
+PageFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    if (FullSystem) {
+        // Invalidate any matching TLB entries before handling the page fault.
+        tc->getITBPtr()->demapPage(addr, 0);
+        tc->getDTBPtr()->demapPage(addr, 0);
+        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);
+    } else if (!tc->getProcessPtr()->fixupFault(addr)) {
+        PageFaultErrorCode code = errorCode;
+        const char *modeStr = "";
+        if (code.fetch)
+            modeStr = "execute";
+        else if (code.write)
+            modeStr = "write";
+        else
+            modeStr = "read";
+
+        // print information about what we are panic'ing on
+        if (!inst) {
+            panic("Tried to %s unmapped address %#x.", modeStr, addr);
         } else {
-            panic("Unrecognized/invalid instruction executed:\n %s",
-                    inst->machInst);
+            panic("Tried to %s unmapped address %#x.\nPC: %#x, Instr: %s",
+                  modeStr, addr, tc->pcState().pc(),
+                  inst->disassemble(tc->pcState().pc(),
+                      &Loader::debugSymbolTable));
         }
     }
+}
 
-    void PageFault::invoke(ThreadContext * tc, const StaticInstPtr &inst)
-    {
-        if (FullSystem) {
-            /* Invalidate any matching TLB entries before handling the page fault */
-            tc->getITBPtr()->demapPage(addr, 0);
-            tc->getDTBPtr()->demapPage(addr, 0);
-            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);
-            }
-        } else if (!tc->getProcessPtr()->fixupFault(addr)) {
-            PageFaultErrorCode code = errorCode;
-            const char *modeStr = "";
-            if (code.fetch)
-                modeStr = "execute";
-            else if (code.write)
-                modeStr = "write";
-            else
-                modeStr = "read";
-
-            // print information about what we are panic'ing on
-            if (!inst) {
-                panic("Tried to %s unmapped address %#x.\n", modeStr, addr);
-            } else {
-                panic("Tried to %s unmapped address %#x.\nPC: %#x, Instr: %s",
-                      modeStr, addr, tc->pcState().pc(),
-                      inst->disassemble(tc->pcState().pc(),
-                          &Loader::debugSymbolTable));
-            }
-        }
-    }
+std::string
+PageFault::describe() const
+{
+    std::stringstream ss;
+    ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
+    return ss.str();
+}
 
-    std::string
-    PageFault::describe() const
-    {
-        std::stringstream ss;
-        ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
-        return ss.str();
+void
+InitInterrupt::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    DPRINTF(Faults, "Init interrupt.\n");
+    // The otherwise unmodified integer registers should be set to 0.
+    for (int index = 0; index < NUM_INTREGS; index++) {
+        tc->setIntReg(index, 0);
     }
 
-    void
-    InitInterrupt::invoke(ThreadContext *tc, const StaticInstPtr &inst)
-    {
-        DPRINTF(Faults, "Init interrupt.\n");
-        // The otherwise unmodified integer registers should be set to 0.
-        for (int index = 0; index < NUM_INTREGS; index++) {
-            tc->setIntReg(index, 0);
-        }
-
-        CR0 cr0 = tc->readMiscReg(MISCREG_CR0);
-        CR0 newCR0 = 1 << 4;
-        newCR0.cd = cr0.cd;
-        newCR0.nw = cr0.nw;
-        tc->setMiscReg(MISCREG_CR0, newCR0);
-        tc->setMiscReg(MISCREG_CR2, 0);
-        tc->setMiscReg(MISCREG_CR3, 0);
-        tc->setMiscReg(MISCREG_CR4, 0);
-
-        tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL);
-
-        tc->setMiscReg(MISCREG_EFER, 0);
-
-        SegAttr dataAttr = 0;
-        dataAttr.dpl = 0;
-        dataAttr.unusable = 0;
-        dataAttr.defaultSize = 0;
-        dataAttr.longMode = 0;
-        dataAttr.avl = 0;
-        dataAttr.granularity = 0;
-        dataAttr.present = 1;
-        dataAttr.type = 3;
-        dataAttr.writable = 1;
-        dataAttr.readable = 1;
-        dataAttr.expandDown = 0;
-        dataAttr.system = 1;
-
-        for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) {
-            tc->setMiscReg(MISCREG_SEG_SEL(seg), 0);
-            tc->setMiscReg(MISCREG_SEG_BASE(seg), 0);
-            tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0);
-            tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff);
-            tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr);
-        }
+    CR0 cr0 = tc->readMiscReg(MISCREG_CR0);
+    CR0 newCR0 = 1 << 4;
+    newCR0.cd = cr0.cd;
+    newCR0.nw = cr0.nw;
+    tc->setMiscReg(MISCREG_CR0, newCR0);
+    tc->setMiscReg(MISCREG_CR2, 0);
+    tc->setMiscReg(MISCREG_CR3, 0);
+    tc->setMiscReg(MISCREG_CR4, 0);
+
+    tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL);
+
+    tc->setMiscReg(MISCREG_EFER, 0);
+
+    SegAttr dataAttr = 0;
+    dataAttr.dpl = 0;
+    dataAttr.unusable = 0;
+    dataAttr.defaultSize = 0;
+    dataAttr.longMode = 0;
+    dataAttr.avl = 0;
+    dataAttr.granularity = 0;
+    dataAttr.present = 1;
+    dataAttr.type = 3;
+    dataAttr.writable = 1;
+    dataAttr.readable = 1;
+    dataAttr.expandDown = 0;
+    dataAttr.system = 1;
+
+    for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) {
+        tc->setMiscReg(MISCREG_SEG_SEL(seg), 0);
+        tc->setMiscReg(MISCREG_SEG_BASE(seg), 0);
+        tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0);
+        tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff);
+        tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr);
+    }
 
-        SegAttr codeAttr = 0;
-        codeAttr.dpl = 0;
-        codeAttr.unusable = 0;
-        codeAttr.defaultSize = 0;
-        codeAttr.longMode = 0;
-        codeAttr.avl = 0;
-        codeAttr.granularity = 0;
-        codeAttr.present = 1;
-        codeAttr.type = 10;
-        codeAttr.writable = 0;
-        codeAttr.readable = 1;
-        codeAttr.expandDown = 0;
-        codeAttr.system = 1;
-
-        tc->setMiscReg(MISCREG_CS, 0xf000);
-        tc->setMiscReg(MISCREG_CS_BASE,
-                0x00000000ffff0000ULL);
-        tc->setMiscReg(MISCREG_CS_EFF_BASE,
-                0x00000000ffff0000ULL);
-        // This has the base value pre-added.
-        tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
-        tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);
-
-        PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE));
-        tc->pcState(pc);
-
-        tc->setMiscReg(MISCREG_TSG_BASE, 0);
-        tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
-
-        tc->setMiscReg(MISCREG_IDTR_BASE, 0);
-        tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);
-
-        SegAttr tslAttr = 0;
-        tslAttr.present = 1;
-        tslAttr.type = 2; // LDT
-        tc->setMiscReg(MISCREG_TSL, 0);
-        tc->setMiscReg(MISCREG_TSL_BASE, 0);
-        tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff);
-        tc->setMiscReg(MISCREG_TSL_ATTR, tslAttr);
-
-        SegAttr trAttr = 0;
-        trAttr.present = 1;
-        trAttr.type = 3; // Busy 16-bit TSS
-        tc->setMiscReg(MISCREG_TR, 0);
-        tc->setMiscReg(MISCREG_TR_BASE, 0);
-        tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff);
-        tc->setMiscReg(MISCREG_TR_ATTR, trAttr);
-
-        // This value should be the family/model/stepping of the processor.
-        // (page 418). It should be consistent with the value from CPUID, but
-        // the actual value probably doesn't matter much.
-        tc->setIntReg(INTREG_RDX, 0);
-
-        tc->setMiscReg(MISCREG_DR0, 0);
-        tc->setMiscReg(MISCREG_DR1, 0);
-        tc->setMiscReg(MISCREG_DR2, 0);
-        tc->setMiscReg(MISCREG_DR3, 0);
-
-        tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
-        tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);
-
-        tc->setMiscReg(MISCREG_MXCSR, 0x1f80);
-
-        // Flag all elements on the x87 stack as empty.
-        tc->setMiscReg(MISCREG_FTW, 0xFFFF);
-
-        // Update the handy M5 Reg.
-        tc->setMiscReg(MISCREG_M5_REG, 0);
-        MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt;
-        pc.upc(romMicroPC(entry));
-        pc.nupc(romMicroPC(entry) + 1);
-        tc->pcState(pc);
+    SegAttr codeAttr = 0;
+    codeAttr.dpl = 0;
+    codeAttr.unusable = 0;
+    codeAttr.defaultSize = 0;
+    codeAttr.longMode = 0;
+    codeAttr.avl = 0;
+    codeAttr.granularity = 0;
+    codeAttr.present = 1;
+    codeAttr.type = 10;
+    codeAttr.writable = 0;
+    codeAttr.readable = 1;
+    codeAttr.expandDown = 0;
+    codeAttr.system = 1;
+
+    tc->setMiscReg(MISCREG_CS, 0xf000);
+    tc->setMiscReg(MISCREG_CS_BASE,
+            0x00000000ffff0000ULL);
+    tc->setMiscReg(MISCREG_CS_EFF_BASE,
+            0x00000000ffff0000ULL);
+    // This has the base value pre-added.
+    tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
+    tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);
+
+    PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE));
+    tc->pcState(pc);
+
+    tc->setMiscReg(MISCREG_TSG_BASE, 0);
+    tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
+
+    tc->setMiscReg(MISCREG_IDTR_BASE, 0);
+    tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);
+
+    SegAttr tslAttr = 0;
+    tslAttr.present = 1;
+    tslAttr.type = 2; // LDT
+    tc->setMiscReg(MISCREG_TSL, 0);
+    tc->setMiscReg(MISCREG_TSL_BASE, 0);
+    tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff);
+    tc->setMiscReg(MISCREG_TSL_ATTR, tslAttr);
+
+    SegAttr trAttr = 0;
+    trAttr.present = 1;
+    trAttr.type = 3; // Busy 16-bit TSS
+    tc->setMiscReg(MISCREG_TR, 0);
+    tc->setMiscReg(MISCREG_TR_BASE, 0);
+    tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff);
+    tc->setMiscReg(MISCREG_TR_ATTR, trAttr);
+
+    // This value should be the family/model/stepping of the processor.
+    // (page 418). It should be consistent with the value from CPUID, but
+    // the actual value probably doesn't matter much.
+    tc->setIntReg(INTREG_RDX, 0);
+
+    tc->setMiscReg(MISCREG_DR0, 0);
+    tc->setMiscReg(MISCREG_DR1, 0);
+    tc->setMiscReg(MISCREG_DR2, 0);
+    tc->setMiscReg(MISCREG_DR3, 0);
+
+    tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
+    tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);
+
+    tc->setMiscReg(MISCREG_MXCSR, 0x1f80);
+
+    // Flag all elements on the x87 stack as empty.
+    tc->setMiscReg(MISCREG_FTW, 0xFFFF);
+
+    // Update the handy M5 Reg.
+    tc->setMiscReg(MISCREG_M5_REG, 0);
+    MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt;
+    pc.upc(romMicroPC(entry));
+    pc.nupc(romMicroPC(entry) + 1);
+    tc->pcState(pc);
+}
+
+void
+StartupInterrupt::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    DPRINTF(Faults, "Startup interrupt with vector %#x.\n", vector);
+    HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG);
+    if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) {
+        panic("Startup IPI recived outside of real mode. "
+                "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode);
     }
 
-    void
-    StartupInterrupt::invoke(ThreadContext *tc, const StaticInstPtr &inst)
-    {
-        DPRINTF(Faults, "Startup interrupt with vector %#x.\n", vector);
-        HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG);
-        if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) {
-            panic("Startup IPI recived outside of real mode. "
-                    "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode);
-        }
+    tc->setMiscReg(MISCREG_CS, vector << 8);
+    tc->setMiscReg(MISCREG_CS_BASE, vector << 12);
+    tc->setMiscReg(MISCREG_CS_EFF_BASE, vector << 12);
+    // This has the base value pre-added.
+    tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff);
 
-        tc->setMiscReg(MISCREG_CS, vector << 8);
-        tc->setMiscReg(MISCREG_CS_BASE, vector << 12);
-        tc->setMiscReg(MISCREG_CS_EFF_BASE, vector << 12);
-        // This has the base value pre-added.
-        tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff);
+    tc->pcState(tc->readMiscReg(MISCREG_CS_BASE));
+}
 
-        tc->pcState(tc->readMiscReg(MISCREG_CS_BASE));
-    }
 } // namespace X86ISA
-
index 0721865bee4575eec4f37dfdef8be4accae935b6..7dfd36c2b68ce938eef4769fb76a6b4ccfdaf5bb 100644 (file)
 
 namespace X86ISA
 {
-    // Base class for all x86 "faults" where faults is in the m5 sense
-    class X86FaultBase : public FaultBase
-    {
-      protected:
-        const char * faultName;
-        const char * mnem;
-        uint8_t vector;
-        uint64_t errorCode;
-
-        X86FaultBase(const char * _faultName, const char * _mnem,
-                     const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1)
-            : faultName(_faultName), mnem(_mnem),
-              vector(_vector), errorCode(_errorCode)
-        {
-        }
-
-        const char * name() const
-        {
-            return faultName;
-        }
-
-        virtual bool isBenign()
-        {
-            return true;
-        }
-
-        virtual const char * mnemonic() const
-        {
-            return mnem;
-        }
-
-        virtual bool isSoft()
-        {
-            return false;
-        }
-
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-
-        virtual std::string describe() const;
-
-      public:
-        /**
-         * Get the vector of an interrupt.
-         *
-         * @return interrupt vector number.
-         */
-        virtual uint8_t getVector() const { return vector; }
-    };
-
-    // Base class for x86 faults which behave as if the underlying instruction
-    // didn't happen.
-    class X86Fault : public X86FaultBase
-    {
-      protected:
-        X86Fault(const char * name, const char * mnem,
-                 const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
-            : X86FaultBase(name, mnem, vector, _errorCode)
-        {}
-    };
-
-    // Base class for x86 traps which behave as if the underlying instruction
-    // completed.
-    class X86Trap : public X86FaultBase
-    {
-      protected:
-        X86Trap(const char * name, const char * mnem,
-                const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
-            : X86FaultBase(name, mnem, vector, _errorCode)
-        {}
-
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-    };
-
-    // Base class for x86 aborts which seem to be catastrophic failures.
-    class X86Abort : public X86FaultBase
-    {
-      protected:
-        X86Abort(const char * name, const char * mnem,
-                const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
-            : X86FaultBase(name, mnem, vector, _errorCode)
-        {}
-
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-    };
-
-    // Base class for x86 interrupts.
-    class X86Interrupt : public X86FaultBase
-    {
-      protected:
-        X86Interrupt(const char * name, const char * mnem,
-                const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1)
-            : X86FaultBase(name, mnem, _vector, _errorCode)
-        {}
-    };
-
-    class UnimpInstFault : public FaultBase
-    {
-      public:
-        const char * name() const
-        {
-            return "unimplemented_micro";
-        }
-
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr)
-        {
-            panic("Unimplemented instruction!");
-        }
-    };
-
-    // Below is a summary of the interrupt/exception information in the
-    // architecture manuals.
-
-    // Class  |  Type    | vector |               Cause                 | mnem
-    //------------------------------------------------------------------------
-    //Contrib   Fault     0         Divide Error                          #DE
-    //Benign    Either    1         Debug                                 #DB
-    //Benign    Interrupt 2         Non-Maskable-Interrupt                #NMI
-    //Benign    Trap      3         Breakpoint                            #BP
-    //Benign    Trap      4         Overflow                              #OF
-    //Benign    Fault     5         Bound-Range                           #BR
-    //Benign    Fault     6         Invalid-Opcode                        #UD
-    //Benign    Fault     7         Device-Not-Available                  #NM
-    //Benign    Abort     8         Double-Fault                          #DF
-    //                    9         Coprocessor-Segment-Overrun
-    //Contrib   Fault     10        Invalid-TSS                           #TS
-    //Contrib   Fault     11        Segment-Not-Present                   #NP
-    //Contrib   Fault     12        Stack                                 #SS
-    //Contrib   Fault     13        General-Protection                    #GP
-    //Either    Fault     14        Page-Fault                            #PF
-    //                    15        Reserved
-    //Benign    Fault     16        x87 Floating-Point Exception Pending  #MF
-    //Benign    Fault     17        Alignment-Check                       #AC
-    //Benign    Abort     18        Machine-Check                         #MC
-    //Benign    Fault     19        SIMD Floating-Point                   #XF
-    //                    20-29     Reserved
-    //Contrib   ?         30        Security Exception                    #SX
-    //                    31        Reserved
-    //Benign    Interrupt 0-255     External Interrupts                   #INTR
-    //Benign    Interrupt 0-255     Software Interrupts                   INTn
-
-    // Note that
-    class DivideError : public X86Fault
-    {
-      public:
-        DivideError() :
-            X86Fault("Divide-Error", "#DE", 0)
-        {}
-    };
 
-    class DebugException : public X86FaultBase
-    {
-      public:
-        DebugException() :
-            X86FaultBase("Debug", "#DB", 1)
-        {}
-    };
+// Base class for all x86 "faults" where faults is in the m5 sense
+class X86FaultBase : public FaultBase
+{
+  protected:
+    const char *faultName;
+    const char *mnem;
+    uint8_t vector;
+    uint64_t errorCode;
+
+    X86FaultBase(const char *_faultName, const char *_mnem,
+                 const uint8_t _vector, uint64_t _errorCode=(uint64_t)-1) :
+        faultName(_faultName), mnem(_mnem),
+        vector(_vector), errorCode(_errorCode)
+    {}
+
+    const char *name() const override { return faultName; }
+    virtual bool isBenign() { return true; }
+    virtual const char *mnemonic() const { return mnem; }
+    virtual bool isSoft() { return false; }
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override;
+
+    virtual std::string describe() const;
+
+  public:
+    /**
+     * Get the vector of an interrupt.
+     *
+     * @return interrupt vector number.
+     */
+    virtual uint8_t getVector() const { return vector; }
+};
+
+// Base class for x86 faults which behave as if the underlying instruction
+// didn't happen.
+class X86Fault : public X86FaultBase
+{
+  protected:
+    using X86FaultBase::X86FaultBase;
+};
 
-    class NonMaskableInterrupt : public X86Interrupt
-    {
-      public:
-        NonMaskableInterrupt(uint8_t _vector) :
-            X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector)
-        {}
-    };
+// Base class for x86 traps which behave as if the underlying instruction
+// completed.
+class X86Trap : public X86FaultBase
+{
+  protected:
+    using X86FaultBase::X86FaultBase;
 
-    class Breakpoint : public X86Trap
-    {
-      public:
-        Breakpoint() :
-            X86Trap("Breakpoint", "#BP", 3)
-        {}
-    };
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override;
+};
 
-    class OverflowTrap : public X86Trap
-    {
-      public:
-        OverflowTrap() :
-            X86Trap("Overflow", "#OF", 4)
-        {}
-    };
+// Base class for x86 aborts which seem to be catastrophic failures.
+class X86Abort : public X86FaultBase
+{
+  protected:
+    using X86FaultBase::X86FaultBase;
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override;
+};
+
+// Base class for x86 interrupts.
+class X86Interrupt : public X86FaultBase
+{
+  protected:
+    using X86FaultBase::X86FaultBase;
+};
 
-    class BoundRange : public X86Fault
+class UnimpInstFault : public FaultBase
+{
+  public:
+    const char *
+    name() const override
     {
-      public:
-        BoundRange() :
-            X86Fault("Bound-Range", "#BR", 5)
-        {}
-    };
+        return "unimplemented_micro";
+    }
 
-    class InvalidOpcode : public X86Fault
+    void
+    invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override
     {
-      public:
-        InvalidOpcode() :
-            X86Fault("Invalid-Opcode", "#UD", 6)
-        {}
+        panic("Unimplemented instruction!");
+    }
+};
+
+// Below is a summary of the interrupt/exception information in the
+// architecture manuals.
+
+// Class  |  Type    | vector |               Cause                 | mnem
+//------------------------------------------------------------------------
+//Contrib   Fault     0         Divide Error                          #DE
+//Benign    Either    1         Debug                                 #DB
+//Benign    Interrupt 2         Non-Maskable-Interrupt                #NMI
+//Benign    Trap      3         Breakpoint                            #BP
+//Benign    Trap      4         Overflow                              #OF
+//Benign    Fault     5         Bound-Range                           #BR
+//Benign    Fault     6         Invalid-Opcode                        #UD
+//Benign    Fault     7         Device-Not-Available                  #NM
+//Benign    Abort     8         Double-Fault                          #DF
+//                    9         Coprocessor-Segment-Overrun
+//Contrib   Fault     10        Invalid-TSS                           #TS
+//Contrib   Fault     11        Segment-Not-Present                   #NP
+//Contrib   Fault     12        Stack                                 #SS
+//Contrib   Fault     13        General-Protection                    #GP
+//Either    Fault     14        Page-Fault                            #PF
+//                    15        Reserved
+//Benign    Fault     16        x87 Floating-Point Exception Pending  #MF
+//Benign    Fault     17        Alignment-Check                       #AC
+//Benign    Abort     18        Machine-Check                         #MC
+//Benign    Fault     19        SIMD Floating-Point                   #XF
+//                    20-29     Reserved
+//Contrib   ?         30        Security Exception                    #SX
+//                    31        Reserved
+//Benign    Interrupt 0-255     External Interrupts                   #INTR
+//Benign    Interrupt 0-255     Software Interrupts                   INTn
+
+// Note that
+class DivideError : public X86Fault
+{
+  public:
+    DivideError() : X86Fault("Divide-Error", "#DE", 0) {}
+};
 
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-    };
+class DebugException : public X86FaultBase
+{
+  public:
+    DebugException() : X86FaultBase("Debug", "#DB", 1) {}
+};
 
-    class DeviceNotAvailable : public X86Fault
-    {
-      public:
-        DeviceNotAvailable() :
-            X86Fault("Device-Not-Available", "#NM", 7)
-        {}
-    };
+class NonMaskableInterrupt : public X86Interrupt
+{
+  public:
+    NonMaskableInterrupt(uint8_t _vector) :
+        X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector)
+    {}
+};
 
-    class DoubleFault : public X86Abort
-    {
-      public:
-        DoubleFault() :
-            X86Abort("Double-Fault", "#DF", 8, 0)
-        {}
-    };
+class Breakpoint : public X86Trap
+{
+  public:
+    Breakpoint() : X86Trap("Breakpoint", "#BP", 3) {}
+};
 
-    class InvalidTSS : public X86Fault
-    {
-      public:
-        InvalidTSS(uint32_t _errorCode) :
-            X86Fault("Invalid-TSS", "#TS", 10, _errorCode)
-        {}
-    };
+class OverflowTrap : public X86Trap
+{
+  public:
+    OverflowTrap() : X86Trap("Overflow", "#OF", 4) {}
+};
 
-    class SegmentNotPresent : public X86Fault
-    {
-      public:
-        SegmentNotPresent(uint32_t _errorCode) :
-            X86Fault("Segment-Not-Present", "#NP", 11, _errorCode)
-        {}
-    };
+class BoundRange : public X86Fault
+{
+  public:
+    BoundRange() : X86Fault("Bound-Range", "#BR", 5) {}
+};
 
-    class StackFault : public X86Fault
-    {
-      public:
-        StackFault(uint32_t _errorCode) :
-            X86Fault("Stack", "#SS", 12, _errorCode)
-        {}
-    };
+class InvalidOpcode : public X86Fault
+{
+  public:
+    InvalidOpcode() : X86Fault("Invalid-Opcode", "#UD", 6) {}
 
-    class GeneralProtection : public X86Fault
-    {
-      public:
-        GeneralProtection(uint32_t _errorCode) :
-            X86Fault("General-Protection", "#GP", 13, _errorCode)
-        {}
-    };
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst =
+                StaticInst::nullStaticInstPtr) override;
+};
 
-    class PageFault : public X86Fault
-    {
-      protected:
-        BitUnion32(PageFaultErrorCode)
-            Bitfield<0> present;
-            Bitfield<1> write;
-            Bitfield<2> user;
-            Bitfield<3> reserved;
-            Bitfield<4> fetch;
-        EndBitUnion(PageFaultErrorCode)
-
-        Addr addr;
-
-      public:
-        PageFault(Addr _addr, uint32_t _errorCode) :
-            X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
-        {}
-
-        PageFault(Addr _addr, bool present, BaseTLB::Mode mode,
-                bool user, bool reserved) :
-            X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
-        {
-            PageFaultErrorCode code = 0;
-            code.present = present;
-            code.write = (mode == BaseTLB::Write);
-            code.user = user;
-            code.reserved = reserved;
-            code.fetch = (mode == BaseTLB::Execute);
-            errorCode = code;
-        }
-
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-
-        virtual std::string describe() const;
-    };
-
-    class X87FpExceptionPending : public X86Fault
-    {
-      public:
-        X87FpExceptionPending() :
-            X86Fault("x87 Floating-Point Exception Pending", "#MF", 16)
-        {}
-    };
+class DeviceNotAvailable : public X86Fault
+{
+  public:
+    DeviceNotAvailable() : X86Fault("Device-Not-Available", "#NM", 7) {}
+};
 
-    class AlignmentCheck : public X86Fault
-    {
-      public:
-        AlignmentCheck() :
-            X86Fault("Alignment-Check", "#AC", 17, 0)
-        {}
-    };
+class DoubleFault : public X86Abort
+{
+  public:
+    DoubleFault() : X86Abort("Double-Fault", "#DF", 8, 0) {}
+};
 
-    class MachineCheck : public X86Abort
-    {
-      public:
-        MachineCheck() :
-            X86Abort("Machine-Check", "#MC", 18)
-        {}
-    };
+class InvalidTSS : public X86Fault
+{
+  public:
+    InvalidTSS(uint32_t _errorCode) :
+        X86Fault("Invalid-TSS", "#TS", 10, _errorCode)
+    {}
+};
 
-    class SIMDFloatingPointFault : public X86Fault
-    {
-      public:
-        SIMDFloatingPointFault() :
-            X86Fault("SIMD Floating-Point", "#XF", 19)
-        {}
-    };
+class SegmentNotPresent : public X86Fault
+{
+  public:
+    SegmentNotPresent(uint32_t _errorCode) :
+        X86Fault("Segment-Not-Present", "#NP", 11, _errorCode)
+    {}
+};
 
-    class SecurityException : public X86FaultBase
-    {
-      public:
-        SecurityException() :
-            X86FaultBase("Security Exception", "#SX", 30)
-        {}
-    };
+class StackFault : public X86Fault
+{
+  public:
+    StackFault(uint32_t _errorCode) : X86Fault("Stack", "#SS", 12, _errorCode)
+    {}
+};
 
-    class ExternalInterrupt : public X86Interrupt
-    {
-      public:
-        ExternalInterrupt(uint8_t _vector) :
-            X86Interrupt("External Interrupt", "#INTR", _vector)
-        {}
-    };
+class GeneralProtection : public X86Fault
+{
+  public:
+    GeneralProtection(uint32_t _errorCode) :
+        X86Fault("General-Protection", "#GP", 13, _errorCode)
+    {}
+};
 
-    class SystemManagementInterrupt : public X86Interrupt
+class PageFault : public X86Fault
+{
+  protected:
+    BitUnion32(PageFaultErrorCode)
+        Bitfield<0> present;
+        Bitfield<1> write;
+        Bitfield<2> user;
+        Bitfield<3> reserved;
+        Bitfield<4> fetch;
+    EndBitUnion(PageFaultErrorCode)
+
+    Addr addr;
+
+  public:
+    PageFault(Addr _addr, uint32_t _errorCode) :
+        X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
+    {}
+
+    PageFault(Addr _addr, bool present, BaseTLB::Mode mode,
+            bool user, bool reserved) :
+        X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
     {
-      public:
-        SystemManagementInterrupt() :
-            X86Interrupt("System Management Interrupt", "#SMI", 0)
-        {}
-    };
+        PageFaultErrorCode code = 0;
+        code.present = present;
+        code.write = (mode == BaseTLB::Write);
+        code.user = user;
+        code.reserved = reserved;
+        code.fetch = (mode == BaseTLB::Execute);
+        errorCode = code;
+    }
+
+    void
+    invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr);
+
+    virtual std::string describe() const;
+};
+
+class X87FpExceptionPending : public X86Fault
+{
+  public:
+    X87FpExceptionPending() :
+        X86Fault("x87 Floating-Point Exception Pending", "#MF", 16)
+    {}
+};
 
-    class InitInterrupt : public X86Interrupt
-    {
-      public:
-        InitInterrupt(uint8_t _vector) :
-            X86Interrupt("INIT Interrupt", "#INIT", _vector)
-        {}
+class AlignmentCheck : public X86Fault
+{
+  public:
+    AlignmentCheck() : X86Fault("Alignment-Check", "#AC", 17, 0) {}
+};
 
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-    };
+class MachineCheck : public X86Abort
+{
+  public:
+    MachineCheck() : X86Abort("Machine-Check", "#MC", 18) {}
+};
 
-    class StartupInterrupt : public X86Interrupt
-    {
-      public:
-        StartupInterrupt(uint8_t _vector) :
-            X86Interrupt("Startup Interrupt", "#SIPI", _vector)
-        {}
+class SIMDFloatingPointFault : public X86Fault
+{
+  public:
+    SIMDFloatingPointFault() : X86Fault("SIMD Floating-Point", "#XF", 19) {}
+};
 
-        void invoke(ThreadContext * tc, const StaticInstPtr &inst =
-                    StaticInst::nullStaticInstPtr);
-    };
+class SecurityException : public X86FaultBase
+{
+  public:
+    SecurityException() : X86FaultBase("Security Exception", "#SX", 30) {}
+};
 
-    class SoftwareInterrupt : public X86Interrupt
-    {
-      public:
-        SoftwareInterrupt(uint8_t _vector) :
-            X86Interrupt("Software Interrupt", "#INTR", _vector)
-        {}
-
-        bool isSoft()
-        {
-            return true;
-        }
-    };
-}
+class ExternalInterrupt : public X86Interrupt
+{
+  public:
+    ExternalInterrupt(uint8_t _vector) :
+        X86Interrupt("External Interrupt", "#INTR", _vector)
+    {}
+};
+
+class SystemManagementInterrupt : public X86Interrupt
+{
+  public:
+    SystemManagementInterrupt() :
+        X86Interrupt("System Management Interrupt", "#SMI", 0)
+    {}
+};
+
+class InitInterrupt : public X86Interrupt
+{
+  public:
+    InitInterrupt(uint8_t _vector) :
+        X86Interrupt("INIT Interrupt", "#INIT", _vector)
+    {}
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override;
+};
+
+class StartupInterrupt : public X86Interrupt
+{
+  public:
+    StartupInterrupt(uint8_t _vector) :
+        X86Interrupt("Startup Interrupt", "#SIPI", _vector)
+    {}
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst=
+                StaticInst::nullStaticInstPtr) override;
+};
+
+class SoftwareInterrupt : public X86Interrupt
+{
+  public:
+    SoftwareInterrupt(uint8_t _vector) :
+        X86Interrupt("Software Interrupt", "#INTR", _vector)
+    {}
+
+    bool isSoft() override { return true; }
+};
+
+} // namespace X86ISA
 
 #endif // __ARCH_X86_FAULTS_HH__