faults.cc revision 9763:f44ff0beb51b
17405SAli.Saidi@ARM.com/* 212667Schuan.zhu@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97405SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137405SAli.Saidi@ARM.com * 147405SAli.Saidi@ARM.com * Copyright (c) 2003-2007 The Regents of The University of Michigan 157405SAli.Saidi@ARM.com * All rights reserved. 167405SAli.Saidi@ARM.com * 177405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 187405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 197405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 207405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 217405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 227405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 237405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 247405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 257405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 267405SAli.Saidi@ARM.com * this software without specific prior written permission. 277405SAli.Saidi@ARM.com * 287405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 347405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 367405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 377405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 387405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397405SAli.Saidi@ARM.com * 407405SAli.Saidi@ARM.com * Authors: Gabe Black 417405SAli.Saidi@ARM.com */ 4210461SAndreas.Sandberg@ARM.com 439050Schander.sudanthi@arm.com#include "arch/x86/generated/decoder.hh" 4412406Sgabeblack@google.com#include "arch/x86/faults.hh" 4512605Sgiacomo.travaglini@arm.com#include "arch/x86/isa_traits.hh" 4611793Sbrandon.potter@amd.com#include "base/trace.hh" 478887Sgeoffrey.blake@arm.com#include "cpu/thread_context.hh" 488232Snate@binkert.org#include "debug/Faults.hh" 498232Snate@binkert.org#include "sim/full_system.hh" 5010844Sandreas.sandberg@arm.com 5113531Sjairo.balart@metempsy.comnamespace X86ISA 5213531Sjairo.balart@metempsy.com{ 539384SAndreas.Sandberg@arm.com void X86FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) 547678Sgblack@eecs.umich.edu { 558059SAli.Saidi@ARM.com if (!FullSystem) { 568284SAli.Saidi@ARM.com FaultBase::invoke(tc, inst); 577405SAli.Saidi@ARM.com return; 587405SAli.Saidi@ARM.com } 597405SAli.Saidi@ARM.com 607405SAli.Saidi@ARM.com PCState pcState = tc->pcState(); 619384SAndreas.Sandberg@arm.com Addr pc = pcState.pc(); 6210461SAndreas.Sandberg@ARM.com DPRINTF(Faults, "RIP %#x: vector %d: %s\n", 6310461SAndreas.Sandberg@ARM.com pc, vector, describe()); 6411165SRekai.GonzalezAlberquilla@arm.com using namespace X86ISAInst::RomLabels; 6512109SRekai.GonzalezAlberquilla@arm.com HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 6612714Sgiacomo.travaglini@arm.com MicroPC entry; 6712714Sgiacomo.travaglini@arm.com if (m5reg.mode == LongMode) { 689384SAndreas.Sandberg@arm.com if (isSoft()) { 6911770SCurtis.Dunham@arm.com entry = extern_label_longModeSoftInterrupt; 7010037SARM gem5 Developers } else { 7110461SAndreas.Sandberg@ARM.com entry = extern_label_longModeInterrupt; 7210461SAndreas.Sandberg@ARM.com } 7310461SAndreas.Sandberg@ARM.com } else { 7410461SAndreas.Sandberg@ARM.com entry = extern_label_legacyModeInterrupt; 7510461SAndreas.Sandberg@ARM.com } 7610461SAndreas.Sandberg@ARM.com tc->setIntReg(INTREG_MICRO(1), vector); 7710609Sandreas.sandberg@arm.com tc->setIntReg(INTREG_MICRO(7), pc); 7810609Sandreas.sandberg@arm.com if (errorCode != (uint64_t)(-1)) { 7910609Sandreas.sandberg@arm.com if (m5reg.mode == LongMode) { 8010037SARM gem5 Developers entry = extern_label_longModeInterruptWithError; 8110037SARM gem5 Developers } else { 8210037SARM gem5 Developers panic("Legacy mode interrupts with error codes " 8310037SARM gem5 Developers "aren't implementde.\n"); 8411771SCurtis.Dunham@arm.com } 8510037SARM gem5 Developers // Software interrupts shouldn't have error codes. If one 8610037SARM gem5 Developers // does, there would need to be microcode to set it up. 8713173Sgiacomo.travaglini@arm.com assert(!isSoft()); 8810037SARM gem5 Developers tc->setIntReg(INTREG_MICRO(15), errorCode); 8910037SARM gem5 Developers } 9013114Sgiacomo.travaglini@arm.com pcState.upc(romMicroPC(entry)); 9110037SARM gem5 Developers pcState.nupc(romMicroPC(entry) + 1); 9211771SCurtis.Dunham@arm.com tc->pcState(pcState); 9310037SARM gem5 Developers } 9413499Sgiacomo.travaglini@arm.com 9510037SARM gem5 Developers std::string 9613114Sgiacomo.travaglini@arm.com X86FaultBase::describe() const 9710037SARM gem5 Developers { 9810037SARM gem5 Developers std::stringstream ss; 9913531Sjairo.balart@metempsy.com ccprintf(ss, "%s", mnemonic()); 10013531Sjairo.balart@metempsy.com if (errorCode != (uint64_t)(-1)) { 10113531Sjairo.balart@metempsy.com ccprintf(ss, "(%#x)", errorCode); 10213531Sjairo.balart@metempsy.com } 10313531Sjairo.balart@metempsy.com 10413531Sjairo.balart@metempsy.com return ss.str(); 10513531Sjairo.balart@metempsy.com } 10612477SCurtis.Dunham@arm.com 10710037SARM gem5 Developers void X86Trap::invoke(ThreadContext * tc, StaticInstPtr inst) 10810037SARM gem5 Developers { 1099384SAndreas.Sandberg@arm.com X86FaultBase::invoke(tc); 1109384SAndreas.Sandberg@arm.com if (!FullSystem) 1119384SAndreas.Sandberg@arm.com return; 11212479SCurtis.Dunham@arm.com 11312479SCurtis.Dunham@arm.com // This is the same as a fault, but it happens -after- the 1149384SAndreas.Sandberg@arm.com // instruction. 1159384SAndreas.Sandberg@arm.com PCState pc = tc->pcState(); 1169384SAndreas.Sandberg@arm.com pc.uEnd(); 1179384SAndreas.Sandberg@arm.com } 1189384SAndreas.Sandberg@arm.com 1199384SAndreas.Sandberg@arm.com void X86Abort::invoke(ThreadContext * tc, StaticInstPtr inst) 1207427Sgblack@eecs.umich.edu { 1217427Sgblack@eecs.umich.edu panic("Abort exception!"); 1227427Sgblack@eecs.umich.edu } 1239385SAndreas.Sandberg@arm.com 1249385SAndreas.Sandberg@arm.com void 1257427Sgblack@eecs.umich.edu InvalidOpcode::invoke(ThreadContext * tc, StaticInstPtr inst) 1267427Sgblack@eecs.umich.edu { 12710037SARM gem5 Developers if (FullSystem) { 12813114Sgiacomo.travaglini@arm.com X86Fault::invoke(tc, inst); 12910037SARM gem5 Developers } else { 13013114Sgiacomo.travaglini@arm.com panic("Unrecognized/invalid instruction executed:\n %s", 13113114Sgiacomo.travaglini@arm.com inst->machInst); 13213114Sgiacomo.travaglini@arm.com } 13313114Sgiacomo.travaglini@arm.com } 13413114Sgiacomo.travaglini@arm.com 13512690Sgiacomo.travaglini@arm.com void PageFault::invoke(ThreadContext * tc, StaticInstPtr inst) 13610037SARM gem5 Developers { 1377427Sgblack@eecs.umich.edu if (FullSystem) { 1387427Sgblack@eecs.umich.edu HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 13910037SARM gem5 Developers X86FaultBase::invoke(tc); 1407427Sgblack@eecs.umich.edu /* 1417427Sgblack@eecs.umich.edu * If something bad happens while trying to enter the page fault 1427427Sgblack@eecs.umich.edu * handler, I'm pretty sure that's a double fault and then all 1437427Sgblack@eecs.umich.edu * bets are off. That means it should be safe to update this 1447427Sgblack@eecs.umich.edu * state now. 1457427Sgblack@eecs.umich.edu */ 1467427Sgblack@eecs.umich.edu if (m5reg.mode == LongMode) { 1477427Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CR2, addr); 1487427Sgblack@eecs.umich.edu } else { 1497427Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CR2, (uint32_t)addr); 1507427Sgblack@eecs.umich.edu } 1517427Sgblack@eecs.umich.edu } else { 1527427Sgblack@eecs.umich.edu PageFaultErrorCode code = errorCode; 1537427Sgblack@eecs.umich.edu const char *modeStr = ""; 1547427Sgblack@eecs.umich.edu if (code.fetch) 1557427Sgblack@eecs.umich.edu modeStr = "execute"; 1567427Sgblack@eecs.umich.edu else if (code.write) 1577427Sgblack@eecs.umich.edu modeStr = "write"; 1587427Sgblack@eecs.umich.edu else 1597427Sgblack@eecs.umich.edu modeStr = "read"; 1607427Sgblack@eecs.umich.edu panic("Tried to %s unmapped address %#x.\n", modeStr, addr); 1617427Sgblack@eecs.umich.edu } 1627427Sgblack@eecs.umich.edu } 1637436Sdam.sunwoo@arm.com 1647436Sdam.sunwoo@arm.com std::string 16510037SARM gem5 Developers PageFault::describe() const 16610037SARM gem5 Developers { 1677436Sdam.sunwoo@arm.com std::stringstream ss; 1687436Sdam.sunwoo@arm.com ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr); 1697436Sdam.sunwoo@arm.com return ss.str(); 1707436Sdam.sunwoo@arm.com } 1717436Sdam.sunwoo@arm.com 1727436Sdam.sunwoo@arm.com void 1737436Sdam.sunwoo@arm.com InitInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 1747436Sdam.sunwoo@arm.com { 1757436Sdam.sunwoo@arm.com DPRINTF(Faults, "Init interrupt.\n"); 1767436Sdam.sunwoo@arm.com // The otherwise unmodified integer registers should be set to 0. 1777436Sdam.sunwoo@arm.com for (int index = 0; index < NUM_INTREGS; index++) { 1787436Sdam.sunwoo@arm.com tc->setIntReg(index, 0); 17913393Sgiacomo.travaglini@arm.com } 18010037SARM gem5 Developers 1817436Sdam.sunwoo@arm.com CR0 cr0 = tc->readMiscReg(MISCREG_CR0); 1827436Sdam.sunwoo@arm.com CR0 newCR0 = 1 << 4; 1837436Sdam.sunwoo@arm.com newCR0.cd = cr0.cd; 1847436Sdam.sunwoo@arm.com newCR0.nw = cr0.nw; 1857436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_CR0, newCR0); 1867436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_CR2, 0); 1877436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_CR3, 0); 1887436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_CR4, 0); 1897436Sdam.sunwoo@arm.com 1907436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL); 1917436Sdam.sunwoo@arm.com 1927436Sdam.sunwoo@arm.com tc->setMiscReg(MISCREG_EFER, 0); 1937436Sdam.sunwoo@arm.com 1947436Sdam.sunwoo@arm.com SegAttr dataAttr = 0; 1957436Sdam.sunwoo@arm.com dataAttr.dpl = 0; 1967436Sdam.sunwoo@arm.com dataAttr.unusable = 0; 19713393Sgiacomo.travaglini@arm.com dataAttr.defaultSize = 0; 19813393Sgiacomo.travaglini@arm.com dataAttr.longMode = 0; 19913393Sgiacomo.travaglini@arm.com dataAttr.avl = 0; 20013393Sgiacomo.travaglini@arm.com dataAttr.granularity = 0; 20113393Sgiacomo.travaglini@arm.com dataAttr.present = 1; 20213393Sgiacomo.travaglini@arm.com dataAttr.type = 3; 20313393Sgiacomo.travaglini@arm.com dataAttr.writable = 1; 20413393Sgiacomo.travaglini@arm.com dataAttr.readable = 1; 20513393Sgiacomo.travaglini@arm.com dataAttr.expandDown = 0; 20613393Sgiacomo.travaglini@arm.com dataAttr.system = 1; 20713393Sgiacomo.travaglini@arm.com 20813393Sgiacomo.travaglini@arm.com for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) { 20913393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_SEG_SEL(seg), 0); 21013393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_SEG_BASE(seg), 0); 21113393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0); 21213393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff); 21313396Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr); 21413396Sgiacomo.travaglini@arm.com } 21513396Sgiacomo.travaglini@arm.com 21613396Sgiacomo.travaglini@arm.com SegAttr codeAttr = 0; 21713393Sgiacomo.travaglini@arm.com codeAttr.dpl = 0; 21813393Sgiacomo.travaglini@arm.com codeAttr.unusable = 0; 21913393Sgiacomo.travaglini@arm.com codeAttr.defaultSize = 0; 22013393Sgiacomo.travaglini@arm.com codeAttr.longMode = 0; 22113393Sgiacomo.travaglini@arm.com codeAttr.avl = 0; 22213393Sgiacomo.travaglini@arm.com codeAttr.granularity = 0; 22313393Sgiacomo.travaglini@arm.com codeAttr.present = 1; 22413393Sgiacomo.travaglini@arm.com codeAttr.type = 10; 22513393Sgiacomo.travaglini@arm.com codeAttr.writable = 0; 22613393Sgiacomo.travaglini@arm.com codeAttr.readable = 1; 22713393Sgiacomo.travaglini@arm.com codeAttr.expandDown = 0; 22813393Sgiacomo.travaglini@arm.com codeAttr.system = 1; 22913393Sgiacomo.travaglini@arm.com 23013393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_CS, 0xf000); 23113393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_CS_BASE, 23213393Sgiacomo.travaglini@arm.com 0x00000000ffff0000ULL); 23313393Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_CS_EFF_BASE, 23413393Sgiacomo.travaglini@arm.com 0x00000000ffff0000ULL); 2357644Sali.saidi@arm.com // This has the base value pre-added. 2368147SAli.Saidi@ARM.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff); 2379385SAndreas.Sandberg@arm.com tc->setMiscReg(MISCREG_CS_ATTR, codeAttr); 2389385SAndreas.Sandberg@arm.com 23910037SARM gem5 Developers PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE)); 24010037SARM gem5 Developers tc->pcState(pc); 24110037SARM gem5 Developers 24210037SARM gem5 Developers tc->setMiscReg(MISCREG_TSG_BASE, 0); 24310037SARM gem5 Developers tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); 24410037SARM gem5 Developers 24510037SARM gem5 Developers tc->setMiscReg(MISCREG_IDTR_BASE, 0); 24610037SARM gem5 Developers tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); 24710037SARM gem5 Developers 24810037SARM gem5 Developers tc->setMiscReg(MISCREG_TSL, 0); 24910037SARM gem5 Developers tc->setMiscReg(MISCREG_TSL_BASE, 0); 25010037SARM gem5 Developers tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff); 25110037SARM gem5 Developers tc->setMiscReg(MISCREG_TSL_ATTR, 0); 25210037SARM gem5 Developers 25310037SARM gem5 Developers tc->setMiscReg(MISCREG_TR, 0); 25410037SARM gem5 Developers tc->setMiscReg(MISCREG_TR_BASE, 0); 2558147SAli.Saidi@ARM.com tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff); 2567427Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_TR_ATTR, 0); 2577427Sgblack@eecs.umich.edu 2587427Sgblack@eecs.umich.edu // This value should be the family/model/stepping of the processor. 25910037SARM gem5 Developers // (page 418). It should be consistent with the value from CPUID, but 26010037SARM gem5 Developers // the actual value probably doesn't matter much. 26110037SARM gem5 Developers tc->setIntReg(INTREG_RDX, 0); 26210037SARM gem5 Developers 26313396Sgiacomo.travaglini@arm.com tc->setMiscReg(MISCREG_DR0, 0); 26410037SARM gem5 Developers tc->setMiscReg(MISCREG_DR1, 0); 26510037SARM gem5 Developers tc->setMiscReg(MISCREG_DR2, 0); 26610037SARM gem5 Developers tc->setMiscReg(MISCREG_DR3, 0); 26710037SARM gem5 Developers 26810037SARM gem5 Developers tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); 26910037SARM gem5 Developers tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); 27010037SARM gem5 Developers 27110037SARM gem5 Developers tc->setMiscReg(MISCREG_MXCSR, 0x1f80); 27210037SARM gem5 Developers 27310037SARM gem5 Developers // Update the handy M5 Reg. 27410037SARM gem5 Developers tc->setMiscReg(MISCREG_M5_REG, 0); 27510037SARM gem5 Developers MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; 27610037SARM gem5 Developers pc.upc(romMicroPC(entry)); 27710037SARM gem5 Developers pc.nupc(romMicroPC(entry) + 1); 27810037SARM gem5 Developers tc->pcState(pc); 27910037SARM gem5 Developers } 28010037SARM gem5 Developers 28110037SARM gem5 Developers void 28210037SARM gem5 Developers StartupInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 28310037SARM gem5 Developers { 28410037SARM gem5 Developers DPRINTF(Faults, "Startup interrupt with vector %#x.\n", vector); 28510037SARM gem5 Developers HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG); 28610037SARM gem5 Developers if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) { 28710037SARM gem5 Developers panic("Startup IPI recived outside of real mode. " 28810037SARM gem5 Developers "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode); 28910037SARM gem5 Developers } 29010037SARM gem5 Developers 29110037SARM gem5 Developers tc->setMiscReg(MISCREG_CS, vector << 8); 29210037SARM gem5 Developers tc->setMiscReg(MISCREG_CS_BASE, vector << 12); 29310037SARM gem5 Developers tc->setMiscReg(MISCREG_CS_EFF_BASE, vector << 12); 29410037SARM gem5 Developers // This has the base value pre-added. 29511770SCurtis.Dunham@arm.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff); 29610037SARM gem5 Developers 29711574SCurtis.Dunham@arm.com tc->pcState(tc->readMiscReg(MISCREG_CS_BASE)); 29811770SCurtis.Dunham@arm.com } 29911770SCurtis.Dunham@arm.com} // namespace X86ISA 30010037SARM gem5 Developers 30111770SCurtis.Dunham@arm.com