summaryrefslogtreecommitdiff
path: root/src/arch/x86/faults.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/faults.cc')
-rw-r--r--src/arch/x86/faults.cc112
1 files changed, 66 insertions, 46 deletions
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc
index 1c94a1251..b81400cc3 100644
--- a/src/arch/x86/faults.cc
+++ b/src/arch/x86/faults.cc
@@ -85,6 +85,7 @@
* Authors: Gabe Black
*/
+#include "arch/x86/decoder.hh"
#include "arch/x86/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
@@ -100,71 +101,90 @@
namespace X86ISA
{
#if FULL_SYSTEM
- void X86Trap::invoke(ThreadContext * tc)
+ void X86FaultBase::invoke(ThreadContext * tc)
{
- panic("X86 faults are not implemented!");
+ Addr pc = tc->readPC();
+ 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) {
+ if (isSoft()) {
+ entry = extern_label_longModeSoftInterrupt;
+ } else {
+ entry = extern_label_longModeInterrupt;
+ }
+ } else {
+ entry = extern_label_legacyModeInterrupt;
+ }
+ tc->setIntReg(INTREG_MICRO(1), vector);
+ tc->setIntReg(INTREG_MICRO(7), 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);
+ }
+ tc->setMicroPC(romMicroPC(entry));
+ tc->setNextMicroPC(romMicroPC(entry) + 1);
}
- void X86Abort::invoke(ThreadContext * tc)
+ std::string
+ X86FaultBase::describe() const
{
- panic("X86 faults are not implemented!");
- }
+ std::stringstream ss;
+ ccprintf(ss, "%s", mnemonic());
+ if (errorCode != (uint64_t)(-1)) {
+ ccprintf(ss, "(%#x)", errorCode);
+ }
- void X86Interrupt::invoke(ThreadContext * tc)
- {
- panic("X86 faults are not implemented!");
+ return ss.str();
}
-
- void FakeITLBFault::invoke(ThreadContext * tc)
+
+ void X86Trap::invoke(ThreadContext * tc)
{
- // Start the page table walker.
- tc->getITBPtr()->walk(tc, vaddr);
+ X86FaultBase::invoke(tc);
+ // This is the same as a fault, but it happens -after- the instruction.
+ tc->setPC(tc->readNextPC());
+ tc->setNextPC(tc->readNextNPC());
+ tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
}
- void FakeDTLBFault::invoke(ThreadContext * tc)
+ void X86Abort::invoke(ThreadContext * tc)
{
- // Start the page table walker.
- tc->getDTBPtr()->walk(tc, vaddr);
+ panic("Abort exception!");
}
-#else // !FULL_SYSTEM
- void FakeITLBFault::invoke(ThreadContext * tc)
+ void PageFault::invoke(ThreadContext * tc)
{
- DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n",
- vaddr, tc->readPC());
- Process *p = tc->getProcessPtr();
- TlbEntry entry;
- bool success = p->pTable->lookup(vaddr, entry);
- if(!success) {
- panic("Tried to execute unmapped address %#x.\n", vaddr);
+ 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 {
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
- DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
- entry.pageStart());
- tc->getITBPtr()->insert(alignedVaddr, entry);
+ tc->setMiscReg(MISCREG_CR2, (uint32_t)addr);
}
}
- void FakeDTLBFault::invoke(ThreadContext * tc)
+ std::string
+ PageFault::describe() const
{
- DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n",
- vaddr, tc->readPC());
- Process *p = tc->getProcessPtr();
- TlbEntry entry;
- bool success = p->pTable->lookup(vaddr, entry);
- if(!success) {
- p->checkAndAllocNextPage(vaddr);
- success = p->pTable->lookup(vaddr, entry);
- }
- if(!success) {
- panic("Tried to access unmapped address %#x.\n", vaddr);
- } else {
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
- DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
- entry.pageStart());
- tc->getDTBPtr()->insert(alignedVaddr, entry);
- }
+ std::stringstream ss;
+ ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
+ return ss.str();
}
+
#endif
} // namespace X86ISA