diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
commit | d080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch) | |
tree | cc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/arch/x86/faults.cc | |
parent | 7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff) | |
parent | 639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff) | |
download | gem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz |
Merge ARM into the head. ARM will compile but may not actually work.
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 |