x86: Style fixes in x86's fault implementations.

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>
This commit is contained in:
Gabe Black
2020-08-24 00:53:43 -07:00
parent 0677b1596a
commit 5c1213d63d
2 changed files with 536 additions and 590 deletions

View File

@@ -51,272 +51,269 @@
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);
}
std::string
X86FaultBase::describe() const
{
std::stringstream ss;
ccprintf(ss, "%s", mnemonic());
if (errorCode != (uint64_t)(-1))
ccprintf(ss, "(%#x)", errorCode);
return ss.str();
return ss.str();
}
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
InvalidOpcode::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
X86Fault::invoke(tc, inst);
} else {
panic("Unrecognized/invalid instruction executed:\n %s",
inst->machInst);
}
}
void X86Trap::invoke(ThreadContext * tc, const StaticInstPtr &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 (!FullSystem)
return;
// 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";
// 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
InvalidOpcode::invoke(ThreadContext * tc, const StaticInstPtr &inst)
{
if (FullSystem) {
X86Fault::invoke(tc, inst);
// 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";
std::string
PageFault::describe() const
{
std::stringstream ss;
ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
return ss.str();
}
// 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));
}
}
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);
}
std::string
PageFault::describe() const
{
std::stringstream ss;
ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
return ss.str();
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);
}
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);
}
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;
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_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);
tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL);
PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE));
tc->pcState(pc);
tc->setMiscReg(MISCREG_EFER, 0);
tc->setMiscReg(MISCREG_TSG_BASE, 0);
tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
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;
tc->setMiscReg(MISCREG_IDTR_BASE, 0);
tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);
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 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 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;
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);
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);
// 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);
PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE));
tc->pcState(pc);
tc->setMiscReg(MISCREG_DR0, 0);
tc->setMiscReg(MISCREG_DR1, 0);
tc->setMiscReg(MISCREG_DR2, 0);
tc->setMiscReg(MISCREG_DR3, 0);
tc->setMiscReg(MISCREG_TSG_BASE, 0);
tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);
tc->setMiscReg(MISCREG_IDTR_BASE, 0);
tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);
tc->setMiscReg(MISCREG_MXCSR, 0x1f80);
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);
// Flag all elements on the x87 stack as empty.
tc->setMiscReg(MISCREG_FTW, 0xFFFF);
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);
// 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);
}
// 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

View File

@@ -47,385 +47,334 @@
namespace X86ISA
{
// Base class for all x86 "faults" where faults is in the m5 sense
class X86FaultBase : public FaultBase
// 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;
};
// Base class for x86 traps which behave as if the underlying instruction
// completed.
class X86Trap : public X86FaultBase
{
protected:
using X86FaultBase::X86FaultBase;
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
// 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 UnimpInstFault : public FaultBase
{
public:
const char *
name() const override
{
protected:
const char * faultName;
const char * mnem;
uint8_t vector;
uint64_t errorCode;
return "unimplemented_micro";
}
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
void
invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override
{
protected:
X86Fault(const char * name, const char * mnem,
const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
: X86FaultBase(name, mnem, vector, _errorCode)
{}
};
panic("Unimplemented instruction!");
}
};
// Base class for x86 traps which behave as if the underlying instruction
// completed.
class X86Trap : public X86FaultBase
// 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) {}
};
class NonMaskableInterrupt : public X86Interrupt
{
public:
NonMaskableInterrupt(uint8_t _vector) :
X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector)
{}
};
class Breakpoint : public X86Trap
{
public:
Breakpoint() : X86Trap("Breakpoint", "#BP", 3) {}
};
class OverflowTrap : public X86Trap
{
public:
OverflowTrap() : X86Trap("Overflow", "#OF", 4) {}
};
class BoundRange : public X86Fault
{
public:
BoundRange() : X86Fault("Bound-Range", "#BR", 5) {}
};
class InvalidOpcode : public X86Fault
{
public:
InvalidOpcode() : X86Fault("Invalid-Opcode", "#UD", 6) {}
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
};
class DeviceNotAvailable : public X86Fault
{
public:
DeviceNotAvailable() : X86Fault("Device-Not-Available", "#NM", 7) {}
};
class DoubleFault : public X86Abort
{
public:
DoubleFault() : X86Abort("Double-Fault", "#DF", 8, 0) {}
};
class InvalidTSS : public X86Fault
{
public:
InvalidTSS(uint32_t _errorCode) :
X86Fault("Invalid-TSS", "#TS", 10, _errorCode)
{}
};
class SegmentNotPresent : public X86Fault
{
public:
SegmentNotPresent(uint32_t _errorCode) :
X86Fault("Segment-Not-Present", "#NP", 11, _errorCode)
{}
};
class StackFault : public X86Fault
{
public:
StackFault(uint32_t _errorCode) : X86Fault("Stack", "#SS", 12, _errorCode)
{}
};
class GeneralProtection : public X86Fault
{
public:
GeneralProtection(uint32_t _errorCode) :
X86Fault("General-Protection", "#GP", 13, _errorCode)
{}
};
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)
{
protected:
X86Trap(const char * name, const char * mnem,
const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
: X86FaultBase(name, mnem, vector, _errorCode)
{}
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);
};
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)
{}
virtual std::string describe() const;
};
void invoke(ThreadContext * tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr);
};
class X87FpExceptionPending : public X86Fault
{
public:
X87FpExceptionPending() :
X86Fault("x87 Floating-Point Exception Pending", "#MF", 16)
{}
};
// 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 AlignmentCheck : public X86Fault
{
public:
AlignmentCheck() : X86Fault("Alignment-Check", "#AC", 17, 0) {}
};
class UnimpInstFault : public FaultBase
{
public:
const char * name() const
{
return "unimplemented_micro";
}
class MachineCheck : public X86Abort
{
public:
MachineCheck() : X86Abort("Machine-Check", "#MC", 18) {}
};
void invoke(ThreadContext * tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr)
{
panic("Unimplemented instruction!");
}
};
class SIMDFloatingPointFault : public X86Fault
{
public:
SIMDFloatingPointFault() : X86Fault("SIMD Floating-Point", "#XF", 19) {}
};
// Below is a summary of the interrupt/exception information in the
// architecture manuals.
class SecurityException : public X86FaultBase
{
public:
SecurityException() : X86FaultBase("Security Exception", "#SX", 30) {}
};
// 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
class ExternalInterrupt : public X86Interrupt
{
public:
ExternalInterrupt(uint8_t _vector) :
X86Interrupt("External Interrupt", "#INTR", _vector)
{}
};
// Note that
class DivideError : public X86Fault
{
public:
DivideError() :
X86Fault("Divide-Error", "#DE", 0)
{}
};
class SystemManagementInterrupt : public X86Interrupt
{
public:
SystemManagementInterrupt() :
X86Interrupt("System Management Interrupt", "#SMI", 0)
{}
};
class DebugException : public X86FaultBase
{
public:
DebugException() :
X86FaultBase("Debug", "#DB", 1)
{}
};
class InitInterrupt : public X86Interrupt
{
public:
InitInterrupt(uint8_t _vector) :
X86Interrupt("INIT Interrupt", "#INIT", _vector)
{}
class NonMaskableInterrupt : public X86Interrupt
{
public:
NonMaskableInterrupt(uint8_t _vector) :
X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector)
{}
};
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
class Breakpoint : public X86Trap
{
public:
Breakpoint() :
X86Trap("Breakpoint", "#BP", 3)
{}
};
class StartupInterrupt : public X86Interrupt
{
public:
StartupInterrupt(uint8_t _vector) :
X86Interrupt("Startup Interrupt", "#SIPI", _vector)
{}
class OverflowTrap : public X86Trap
{
public:
OverflowTrap() :
X86Trap("Overflow", "#OF", 4)
{}
};
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
class BoundRange : public X86Fault
{
public:
BoundRange() :
X86Fault("Bound-Range", "#BR", 5)
{}
};
class SoftwareInterrupt : public X86Interrupt
{
public:
SoftwareInterrupt(uint8_t _vector) :
X86Interrupt("Software Interrupt", "#INTR", _vector)
{}
class InvalidOpcode : public X86Fault
{
public:
InvalidOpcode() :
X86Fault("Invalid-Opcode", "#UD", 6)
{}
bool isSoft() override { return true; }
};
void invoke(ThreadContext * tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr);
};
class DeviceNotAvailable : public X86Fault
{
public:
DeviceNotAvailable() :
X86Fault("Device-Not-Available", "#NM", 7)
{}
};
class DoubleFault : public X86Abort
{
public:
DoubleFault() :
X86Abort("Double-Fault", "#DF", 8, 0)
{}
};
class InvalidTSS : public X86Fault
{
public:
InvalidTSS(uint32_t _errorCode) :
X86Fault("Invalid-TSS", "#TS", 10, _errorCode)
{}
};
class SegmentNotPresent : public X86Fault
{
public:
SegmentNotPresent(uint32_t _errorCode) :
X86Fault("Segment-Not-Present", "#NP", 11, _errorCode)
{}
};
class StackFault : public X86Fault
{
public:
StackFault(uint32_t _errorCode) :
X86Fault("Stack", "#SS", 12, _errorCode)
{}
};
class GeneralProtection : public X86Fault
{
public:
GeneralProtection(uint32_t _errorCode) :
X86Fault("General-Protection", "#GP", 13, _errorCode)
{}
};
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 AlignmentCheck : public X86Fault
{
public:
AlignmentCheck() :
X86Fault("Alignment-Check", "#AC", 17, 0)
{}
};
class MachineCheck : public X86Abort
{
public:
MachineCheck() :
X86Abort("Machine-Check", "#MC", 18)
{}
};
class SIMDFloatingPointFault : public X86Fault
{
public:
SIMDFloatingPointFault() :
X86Fault("SIMD Floating-Point", "#XF", 19)
{}
};
class SecurityException : public X86FaultBase
{
public:
SecurityException() :
X86FaultBase("Security Exception", "#SX", 30)
{}
};
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);
};
class StartupInterrupt : public X86Interrupt
{
public:
StartupInterrupt(uint8_t _vector) :
X86Interrupt("Startup Interrupt", "#SIPI", _vector)
{}
void invoke(ThreadContext * tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr);
};
class SoftwareInterrupt : public X86Interrupt
{
public:
SoftwareInterrupt(uint8_t _vector) :
X86Interrupt("Software Interrupt", "#INTR", _vector)
{}
bool isSoft()
{
return true;
}
};
}
} // namespace X86ISA
#endif // __ARCH_X86_FAULTS_HH__