diff options
Diffstat (limited to 'src/arch/x86/faults.cc')
-rw-r--r-- | src/arch/x86/faults.cc | 112 |
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 |