faults.cc revision 8806
12SN/A/* 210676Sandreas.hansson@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company 39235Sandreas.hansson@arm.com * All rights reserved. 49235Sandreas.hansson@arm.com * 59235Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69235Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79235Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89235Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99235Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109235Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119235Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129235Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139235Sandreas.hansson@arm.com * 141762SN/A * Copyright (c) 2003-2007 The Regents of The University of Michigan 152SN/A * All rights reserved. 162SN/A * 172SN/A * Redistribution and use in source and binary forms, with or without 182SN/A * modification, are permitted provided that the following conditions are 192SN/A * met: redistributions of source code must retain the above copyright 202SN/A * notice, this list of conditions and the following disclaimer; 212SN/A * redistributions in binary form must reproduce the above copyright 222SN/A * notice, this list of conditions and the following disclaimer in the 232SN/A * documentation and/or other materials provided with the distribution; 242SN/A * neither the name of the copyright holders nor the names of its 252SN/A * contributors may be used to endorse or promote products derived from 262SN/A * this software without specific prior written permission. 272SN/A * 282SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Gabe Black 412665SN/A */ 429235Sandreas.hansson@arm.com 432SN/A#include "arch/x86/decoder.hh" 442SN/A#include "arch/x86/faults.hh" 459235Sandreas.hansson@arm.com#include "arch/x86/isa_traits.hh" 469235Sandreas.hansson@arm.com#include "base/trace.hh" 472SN/A#include "cpu/thread_context.hh" 4810481Sandreas.hansson@arm.com#include "debug/Faults.hh" 499412Sandreas.hansson@arm.com#include "sim/full_system.hh" 509412Sandreas.hansson@arm.com 519411Sandreas.hansson@arm.comnamespace X86ISA 529405Sandreas.hansson@arm.com{ 539411Sandreas.hansson@arm.com void X86FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) 549235Sandreas.hansson@arm.com { 559235Sandreas.hansson@arm.com if (!FullSystem) { 5610676Sandreas.hansson@arm.com FaultBase::invoke(tc, inst); 5710676Sandreas.hansson@arm.com return; 5810676Sandreas.hansson@arm.com } 5910676Sandreas.hansson@arm.com 6010676Sandreas.hansson@arm.com PCState pcState = tc->pcState(); 6110676Sandreas.hansson@arm.com Addr pc = pcState.pc(); 6210676Sandreas.hansson@arm.com DPRINTF(Faults, "RIP %#x: vector %d: %s\n", 6310676Sandreas.hansson@arm.com pc, vector, describe()); 6410676Sandreas.hansson@arm.com using namespace X86ISAInst::RomLabels; 6510676Sandreas.hansson@arm.com HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 6610676Sandreas.hansson@arm.com MicroPC entry; 6710676Sandreas.hansson@arm.com if (m5reg.mode == LongMode) { 6810676Sandreas.hansson@arm.com if (isSoft()) { 6910676Sandreas.hansson@arm.com entry = extern_label_longModeSoftInterrupt; 7010676Sandreas.hansson@arm.com } else { 7110676Sandreas.hansson@arm.com entry = extern_label_longModeInterrupt; 729235Sandreas.hansson@arm.com } 732SN/A } else { 742SN/A entry = extern_label_legacyModeInterrupt; 759405Sandreas.hansson@arm.com } 769405Sandreas.hansson@arm.com tc->setIntReg(INTREG_MICRO(1), vector); 779411Sandreas.hansson@arm.com tc->setIntReg(INTREG_MICRO(7), pc); 7810435Snilay@cs.wisc.edu if (errorCode != (uint64_t)(-1)) { 799405Sandreas.hansson@arm.com if (m5reg.mode == LongMode) { 809405Sandreas.hansson@arm.com entry = extern_label_longModeInterruptWithError; 819405Sandreas.hansson@arm.com } else { 829411Sandreas.hansson@arm.com panic("Legacy mode interrupts with error codes " 839411Sandreas.hansson@arm.com "aren't implementde.\n"); 849411Sandreas.hansson@arm.com } 8510676Sandreas.hansson@arm.com // Software interrupts shouldn't have error codes. If one 8610676Sandreas.hansson@arm.com // does, there would need to be microcode to set it up. 8710676Sandreas.hansson@arm.com assert(!isSoft()); 8810676Sandreas.hansson@arm.com tc->setIntReg(INTREG_MICRO(15), errorCode); 899411Sandreas.hansson@arm.com } 909411Sandreas.hansson@arm.com pcState.upc(romMicroPC(entry)); 919411Sandreas.hansson@arm.com pcState.nupc(romMicroPC(entry) + 1); 929411Sandreas.hansson@arm.com tc->pcState(pcState); 939411Sandreas.hansson@arm.com } 949411Sandreas.hansson@arm.com 959411Sandreas.hansson@arm.com std::string 969235Sandreas.hansson@arm.com X86FaultBase::describe() const 972SN/A { 989235Sandreas.hansson@arm.com std::stringstream ss; 9910676Sandreas.hansson@arm.com ccprintf(ss, "%s", mnemonic()); 10010676Sandreas.hansson@arm.com if (errorCode != (uint64_t)(-1)) { 1019411Sandreas.hansson@arm.com ccprintf(ss, "(%#x)", errorCode); 1029411Sandreas.hansson@arm.com } 1039411Sandreas.hansson@arm.com 10410676Sandreas.hansson@arm.com return ss.str(); 10510676Sandreas.hansson@arm.com } 1069411Sandreas.hansson@arm.com 10710676Sandreas.hansson@arm.com void X86Trap::invoke(ThreadContext * tc, StaticInstPtr inst) 10810676Sandreas.hansson@arm.com { 10910676Sandreas.hansson@arm.com X86FaultBase::invoke(tc); 11010676Sandreas.hansson@arm.com if (!FullSystem) 11110676Sandreas.hansson@arm.com return; 11210676Sandreas.hansson@arm.com 11310676Sandreas.hansson@arm.com // This is the same as a fault, but it happens -after- the 11410676Sandreas.hansson@arm.com // instruction. 11510676Sandreas.hansson@arm.com PCState pc = tc->pcState(); 11610676Sandreas.hansson@arm.com pc.uEnd(); 11710676Sandreas.hansson@arm.com } 11810676Sandreas.hansson@arm.com 11910676Sandreas.hansson@arm.com void X86Abort::invoke(ThreadContext * tc, StaticInstPtr inst) 12010676Sandreas.hansson@arm.com { 12110676Sandreas.hansson@arm.com panic("Abort exception!"); 12210676Sandreas.hansson@arm.com } 12310676Sandreas.hansson@arm.com 12410676Sandreas.hansson@arm.com void 12510676Sandreas.hansson@arm.com InvalidOpcode::invoke(ThreadContext * tc, StaticInstPtr inst) 12610676Sandreas.hansson@arm.com { 12710676Sandreas.hansson@arm.com if (FullSystem) { 12810676Sandreas.hansson@arm.com X86Fault::invoke(tc, inst); 12910676Sandreas.hansson@arm.com } else { 13010676Sandreas.hansson@arm.com panic("Unrecognized/invalid instruction executed:\n %s", 1319235Sandreas.hansson@arm.com inst->machInst); 1329235Sandreas.hansson@arm.com } 13310676Sandreas.hansson@arm.com } 13410676Sandreas.hansson@arm.com 1359235Sandreas.hansson@arm.com void PageFault::invoke(ThreadContext * tc, StaticInstPtr inst) 1369235Sandreas.hansson@arm.com { 1379405Sandreas.hansson@arm.com if (FullSystem) { 1389412Sandreas.hansson@arm.com HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 1399412Sandreas.hansson@arm.com X86FaultBase::invoke(tc); 1409412Sandreas.hansson@arm.com /* 1419412Sandreas.hansson@arm.com * If something bad happens while trying to enter the page fault 1429412Sandreas.hansson@arm.com * handler, I'm pretty sure that's a double fault and then all 1439412Sandreas.hansson@arm.com * bets are off. That means it should be safe to update this 14410676Sandreas.hansson@arm.com * state now. 14510676Sandreas.hansson@arm.com */ 1469412Sandreas.hansson@arm.com if (m5reg.mode == LongMode) { 1479412Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR2, addr); 1489412Sandreas.hansson@arm.com } else { 1499412Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR2, (uint32_t)addr); 1509412Sandreas.hansson@arm.com } 1519412Sandreas.hansson@arm.com } else { 15210676Sandreas.hansson@arm.com PageFaultErrorCode code = errorCode; 1539412Sandreas.hansson@arm.com const char *modeStr = ""; 1549412Sandreas.hansson@arm.com if (code.fetch) 1559412Sandreas.hansson@arm.com modeStr = "execute"; 1569412Sandreas.hansson@arm.com else if (code.write) 1579412Sandreas.hansson@arm.com modeStr = "write"; 1589412Sandreas.hansson@arm.com else 1599412Sandreas.hansson@arm.com modeStr = "read"; 16010676Sandreas.hansson@arm.com panic("Tried to %s unmapped address %#x.\n", modeStr, addr); 16110676Sandreas.hansson@arm.com } 1629412Sandreas.hansson@arm.com } 1639412Sandreas.hansson@arm.com 1649412Sandreas.hansson@arm.com std::string 16510676Sandreas.hansson@arm.com PageFault::describe() const 1669412Sandreas.hansson@arm.com { 16710676Sandreas.hansson@arm.com std::stringstream ss; 1689412Sandreas.hansson@arm.com ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr); 1699412Sandreas.hansson@arm.com return ss.str(); 1709412Sandreas.hansson@arm.com } 1719412Sandreas.hansson@arm.com 1729412Sandreas.hansson@arm.com void 1739412Sandreas.hansson@arm.com InitInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 17410676Sandreas.hansson@arm.com { 1759412Sandreas.hansson@arm.com DPRINTF(Faults, "Init interrupt.\n"); 1769412Sandreas.hansson@arm.com // The otherwise unmodified integer registers should be set to 0. 1779412Sandreas.hansson@arm.com for (int index = 0; index < NUM_INTREGS; index++) { 1789412Sandreas.hansson@arm.com tc->setIntReg(index, 0); 1799412Sandreas.hansson@arm.com } 1809411Sandreas.hansson@arm.com 1819411Sandreas.hansson@arm.com CR0 cr0 = tc->readMiscReg(MISCREG_CR0); 1829411Sandreas.hansson@arm.com CR0 newCR0 = 1 << 4; 1839411Sandreas.hansson@arm.com newCR0.cd = cr0.cd; 1849411Sandreas.hansson@arm.com newCR0.nw = cr0.nw; 1859411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR0, newCR0); 1869411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR2, 0); 18710676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR3, 0); 18810676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR4, 0); 18910676Sandreas.hansson@arm.com 19010676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL); 19110676Sandreas.hansson@arm.com 1929411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_EFER, 0); 1939411Sandreas.hansson@arm.com 1949411Sandreas.hansson@arm.com SegAttr dataAttr = 0; 1959411Sandreas.hansson@arm.com dataAttr.dpl = 0; 1969581Sandreas.hansson@arm.com dataAttr.unusable = 0; 1979581Sandreas.hansson@arm.com dataAttr.defaultSize = 0; 1989780Sandreas.hansson@arm.com dataAttr.longMode = 0; 1999581Sandreas.hansson@arm.com dataAttr.avl = 0; 2009411Sandreas.hansson@arm.com dataAttr.granularity = 0; 2019411Sandreas.hansson@arm.com dataAttr.present = 1; 2029411Sandreas.hansson@arm.com dataAttr.type = 3; 2039411Sandreas.hansson@arm.com dataAttr.writable = 1; 2049411Sandreas.hansson@arm.com dataAttr.readable = 1; 2059411Sandreas.hansson@arm.com dataAttr.expandDown = 0; 2069411Sandreas.hansson@arm.com dataAttr.system = 1; 2079411Sandreas.hansson@arm.com 2089411Sandreas.hansson@arm.com for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) { 2099411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SEG_SEL(seg), 0); 2109405Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SEG_BASE(seg), 0); 2119411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0); 2129411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff); 2139405Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr); 2149411Sandreas.hansson@arm.com } 2159411Sandreas.hansson@arm.com 2169411Sandreas.hansson@arm.com SegAttr codeAttr = 0; 2179411Sandreas.hansson@arm.com codeAttr.dpl = 0; 218532SN/A codeAttr.unusable = 0; 2199405Sandreas.hansson@arm.com codeAttr.defaultSize = 0; 2209405Sandreas.hansson@arm.com codeAttr.longMode = 0; 2219405Sandreas.hansson@arm.com codeAttr.avl = 0; 22210435Snilay@cs.wisc.edu codeAttr.granularity = 0; 2239405Sandreas.hansson@arm.com codeAttr.present = 1; 2249405Sandreas.hansson@arm.com codeAttr.type = 10; 2259405Sandreas.hansson@arm.com codeAttr.writable = 0; 2269405Sandreas.hansson@arm.com codeAttr.readable = 1; 2279405Sandreas.hansson@arm.com codeAttr.expandDown = 0; 2289405Sandreas.hansson@arm.com codeAttr.system = 1; 2299405Sandreas.hansson@arm.com 23010678SCurtis.Dunham@arm.com tc->setMiscReg(MISCREG_CS, 0xf000); 23110678SCurtis.Dunham@arm.com tc->setMiscReg(MISCREG_CS_BASE, 23210678SCurtis.Dunham@arm.com 0x00000000ffff0000ULL); 23310678SCurtis.Dunham@arm.com tc->setMiscReg(MISCREG_CS_EFF_BASE, 23410678SCurtis.Dunham@arm.com 0x00000000ffff0000ULL); 2359405Sandreas.hansson@arm.com // This has the base value pre-added. 2369405Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff); 2379405Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS_ATTR, codeAttr); 2389405Sandreas.hansson@arm.com 2399405Sandreas.hansson@arm.com PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE)); 2409405Sandreas.hansson@arm.com tc->pcState(pc); 24110676Sandreas.hansson@arm.com 24210676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSG_BASE, 0); 24310676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); 24410676Sandreas.hansson@arm.com 24510676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IDTR_BASE, 0); 24610676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); 24710676Sandreas.hansson@arm.com 24810676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSL, 0); 24910676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSL_BASE, 0); 25010676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff); 25110676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSL_ATTR, 0); 25210676Sandreas.hansson@arm.com 25310676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TR, 0); 25410676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TR_BASE, 0); 2559411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff); 25610676Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TR_ATTR, 0); 2579411Sandreas.hansson@arm.com 2589411Sandreas.hansson@arm.com // This value should be the family/model/stepping of the processor. 2599411Sandreas.hansson@arm.com // (page 418). It should be consistent with the value from CPUID, but 2609411Sandreas.hansson@arm.com // the actual value probably doesn't matter much. 2619411Sandreas.hansson@arm.com tc->setIntReg(INTREG_RDX, 0); 2629411Sandreas.hansson@arm.com 2639411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR0, 0); 2649411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR1, 0); 2659411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR2, 0); 2669411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR3, 0); 2679411Sandreas.hansson@arm.com 2689411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); 2699411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); 2709411Sandreas.hansson@arm.com 27110676Sandreas.hansson@arm.com // Update the handy M5 Reg. 2729411Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_M5_REG, 0); 2739405Sandreas.hansson@arm.com MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; 2749279Sandreas.hansson@arm.com pc.upc(romMicroPC(entry)); 2759279Sandreas.hansson@arm.com pc.nupc(romMicroPC(entry) + 1); 2769279Sandreas.hansson@arm.com tc->pcState(pc); 2779279Sandreas.hansson@arm.com } 2789279Sandreas.hansson@arm.com 2799279Sandreas.hansson@arm.com void 2809279Sandreas.hansson@arm.com StartupInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 2819279Sandreas.hansson@arm.com { 2829279Sandreas.hansson@arm.com DPRINTF(Faults, "Startup interrupt with vector %#x.\n", vector); 2839279Sandreas.hansson@arm.com HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG); 2849279Sandreas.hansson@arm.com if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) { 28510853Sandreas.hansson@arm.com panic("Startup IPI recived outside of real mode. " 28610853Sandreas.hansson@arm.com "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode); 28710853Sandreas.hansson@arm.com } 28810853Sandreas.hansson@arm.com 28910853Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS, vector << 8); 29010853Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS_BASE, vector << 12); 29110853Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS_EFF_BASE, vector << 12); 2929411Sandreas.hansson@arm.com // This has the base value pre-added. 29310853Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff); 2949411Sandreas.hansson@arm.com 2959411Sandreas.hansson@arm.com tc->pcState(tc->readMiscReg(MISCREG_CS_BASE)); 2969411Sandreas.hansson@arm.com } 2979411Sandreas.hansson@arm.com} // namespace X86ISA 2989411Sandreas.hansson@arm.com 2999411Sandreas.hansson@arm.com