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
-
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__