faults.cc revision 8961
111923Sandreas.sandberg@arm.com/* 211923Sandreas.sandberg@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company 311923Sandreas.sandberg@arm.com * All rights reserved. 411923Sandreas.sandberg@arm.com * 511923Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 611923Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 711923Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 811923Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 911923Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1011923Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1111923Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1211923Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 132889Sbinkertn@umich.edu * 142889Sbinkertn@umich.edu * Copyright (c) 2003-2007 The Regents of The University of Michigan 152889Sbinkertn@umich.edu * All rights reserved. 162889Sbinkertn@umich.edu * 172889Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 182889Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 192889Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 202889Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 212889Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 222889Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 232889Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 242889Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 252889Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 262889Sbinkertn@umich.edu * this software without specific prior written permission. 272889Sbinkertn@umich.edu * 282889Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292889Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302889Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312889Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322889Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332889Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342889Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352889Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362889Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372889Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382889Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392889Sbinkertn@umich.edu * 402889Sbinkertn@umich.edu * Authors: Gabe Black 4112563Sgabeblack@google.com */ 4212563Sgabeblack@google.com 434850Snate@binkert.org#include "arch/x86/generated/decoder.hh" 444850Snate@binkert.org#include "arch/x86/faults.hh" 454850Snate@binkert.org#include "arch/x86/isa_traits.hh" 464850Snate@binkert.org#include "base/trace.hh" 474850Snate@binkert.org#include "cpu/thread_context.hh" 484850Snate@binkert.org#include "debug/Faults.hh" 492889Sbinkertn@umich.edu#include "sim/full_system.hh" 502889Sbinkertn@umich.edu 518327Sgblack@eecs.umich.edunamespace X86ISA 525470Snate@binkert.org{ 538333Snate@binkert.org void X86FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) 548333Snate@binkert.org { 552889Sbinkertn@umich.edu if (!FullSystem) { 568234Snate@binkert.org FaultBase::invoke(tc, inst); 578234Snate@binkert.org return; 588234Snate@binkert.org } 592889Sbinkertn@umich.edu 608234Snate@binkert.org PCState pcState = tc->pcState(); 618234Snate@binkert.org Addr pc = pcState.pc(); 628234Snate@binkert.org DPRINTF(Faults, "RIP %#x: vector %d: %s\n", 638234Snate@binkert.org pc, vector, describe()); 642889Sbinkertn@umich.edu using namespace X86ISAInst::RomLabels; 6511923Sandreas.sandberg@arm.com HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 6611923Sandreas.sandberg@arm.com MicroPC entry; 678234Snate@binkert.org if (m5reg.mode == LongMode) { 688234Snate@binkert.org if (isSoft()) { 698234Snate@binkert.org entry = extern_label_longModeSoftInterrupt; 708234Snate@binkert.org } else { 718234Snate@binkert.org entry = extern_label_longModeInterrupt; 728234Snate@binkert.org } 738234Snate@binkert.org } else { 742889Sbinkertn@umich.edu entry = extern_label_legacyModeInterrupt; 758234Snate@binkert.org } 768234Snate@binkert.org tc->setIntReg(INTREG_MICRO(1), vector); 778234Snate@binkert.org tc->setIntReg(INTREG_MICRO(7), pc); 788234Snate@binkert.org if (errorCode != (uint64_t)(-1)) { 798234Snate@binkert.org if (m5reg.mode == LongMode) { 808234Snate@binkert.org entry = extern_label_longModeInterruptWithError; 818234Snate@binkert.org } else { 828234Snate@binkert.org panic("Legacy mode interrupts with error codes " 838234Snate@binkert.org "aren't implementde.\n"); 848234Snate@binkert.org } 858234Snate@binkert.org // Software interrupts shouldn't have error codes. If one 8611923Sandreas.sandberg@arm.com // does, there would need to be microcode to set it up. 8711923Sandreas.sandberg@arm.com assert(!isSoft()); 8811923Sandreas.sandberg@arm.com tc->setIntReg(INTREG_MICRO(15), errorCode); 8911923Sandreas.sandberg@arm.com } 9012012Sgabeblack@google.com pcState.upc(romMicroPC(entry)); 9112012Sgabeblack@google.com pcState.nupc(romMicroPC(entry) + 1); 9212012Sgabeblack@google.com tc->pcState(pcState); 938234Snate@binkert.org } 948234Snate@binkert.org 958234Snate@binkert.org std::string 968234Snate@binkert.org X86FaultBase::describe() const 978234Snate@binkert.org { 988234Snate@binkert.org std::stringstream ss; 998234Snate@binkert.org ccprintf(ss, "%s", mnemonic()); 1008234Snate@binkert.org if (errorCode != (uint64_t)(-1)) { 1018234Snate@binkert.org ccprintf(ss, "(%#x)", errorCode); 1028234Snate@binkert.org } 1032889Sbinkertn@umich.edu 1048234Snate@binkert.org return ss.str(); 1058234Snate@binkert.org } 1068234Snate@binkert.org 1078234Snate@binkert.org void X86Trap::invoke(ThreadContext * tc, StaticInstPtr inst) 1085773Snate@binkert.org { 1098234Snate@binkert.org X86FaultBase::invoke(tc); 1108234Snate@binkert.org if (!FullSystem) 1118234Snate@binkert.org return; 1128234Snate@binkert.org 1138664SAli.Saidi@ARM.com // This is the same as a fault, but it happens -after- the 1148664SAli.Saidi@ARM.com // instruction. 1158998Suri.wiener@arm.com PCState pc = tc->pcState(); 1168998Suri.wiener@arm.com pc.uEnd(); 11711431Ssascha.bischoff@arm.com } 11811418Ssascha.bischoff@arm.com 11911418Ssascha.bischoff@arm.com void X86Abort::invoke(ThreadContext * tc, StaticInstPtr inst) 1202889Sbinkertn@umich.edu { 1218234Snate@binkert.org panic("Abort exception!"); 1228234Snate@binkert.org } 12311299Ssteve.reinhardt@amd.com 12411299Ssteve.reinhardt@amd.com void 12511299Ssteve.reinhardt@amd.com InvalidOpcode::invoke(ThreadContext * tc, StaticInstPtr inst) 1268234Snate@binkert.org { 1279960Sandreas.hansson@arm.com if (FullSystem) { 1288234Snate@binkert.org X86Fault::invoke(tc, inst); 1299960Sandreas.hansson@arm.com } else { 13011299Ssteve.reinhardt@amd.com panic("Unrecognized/invalid instruction executed:\n %s", 13111304Ssteve.reinhardt@amd.com inst->machInst); 13211338SMichael.Lebeane@amd.com } 13311338SMichael.Lebeane@amd.com } 1349960Sandreas.hansson@arm.com 1359960Sandreas.hansson@arm.com void PageFault::invoke(ThreadContext * tc, StaticInstPtr inst) 1369960Sandreas.hansson@arm.com { 1379960Sandreas.hansson@arm.com if (FullSystem) { 1388234Snate@binkert.org HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 1398234Snate@binkert.org X86FaultBase::invoke(tc); 1402889Sbinkertn@umich.edu /* 1418234Snate@binkert.org * If something bad happens while trying to enter the page fault 1428234Snate@binkert.org * handler, I'm pretty sure that's a double fault and then all 1438234Snate@binkert.org * bets are off. That means it should be safe to update this 1448234Snate@binkert.org * state now. 1456171Snate@binkert.org */ 1468234Snate@binkert.org if (m5reg.mode == LongMode) { 1478234Snate@binkert.org tc->setMiscReg(MISCREG_CR2, addr); 1488234Snate@binkert.org } else { 1498234Snate@binkert.org tc->setMiscReg(MISCREG_CR2, (uint32_t)addr); 1508234Snate@binkert.org } 1518234Snate@binkert.org } else { 1528234Snate@binkert.org PageFaultErrorCode code = errorCode; 1538234Snate@binkert.org const char *modeStr = ""; 1548234Snate@binkert.org if (code.fetch) 1556171Snate@binkert.org modeStr = "execute"; 1568219Snate@binkert.org else if (code.write) 1578327Sgblack@eecs.umich.edu modeStr = "write"; 1589512Sandreas@sandberg.pp.se else 1599512Sandreas@sandberg.pp.se modeStr = "read"; 1609512Sandreas@sandberg.pp.se panic("Tried to %s unmapped address %#x.\n", modeStr, addr); 1619512Sandreas@sandberg.pp.se } 1629512Sandreas@sandberg.pp.se } 1639512Sandreas@sandberg.pp.se 1648219Snate@binkert.org std::string 1658219Snate@binkert.org PageFault::describe() const 1669512Sandreas@sandberg.pp.se { 1679512Sandreas@sandberg.pp.se std::stringstream ss; 1689512Sandreas@sandberg.pp.se ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr); 1699512Sandreas@sandberg.pp.se return ss.str(); 1709512Sandreas@sandberg.pp.se } 1719512Sandreas@sandberg.pp.se 1729512Sandreas@sandberg.pp.se void 1739512Sandreas@sandberg.pp.se InitInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 1749512Sandreas@sandberg.pp.se { 1759512Sandreas@sandberg.pp.se DPRINTF(Faults, "Init interrupt.\n"); 1769512Sandreas@sandberg.pp.se // The otherwise unmodified integer registers should be set to 0. 17711635SCurtis.Dunham@arm.com for (int index = 0; index < NUM_INTREGS; index++) { 1789512Sandreas@sandberg.pp.se tc->setIntReg(index, 0); 1799512Sandreas@sandberg.pp.se } 1809512Sandreas@sandberg.pp.se 1819512Sandreas@sandberg.pp.se CR0 cr0 = tc->readMiscReg(MISCREG_CR0); 1829512Sandreas@sandberg.pp.se CR0 newCR0 = 1 << 4; 1839512Sandreas@sandberg.pp.se newCR0.cd = cr0.cd; 1849512Sandreas@sandberg.pp.se newCR0.nw = cr0.nw; 1859512Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_CR0, newCR0); 1869512Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_CR2, 0); 1879512Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_CR3, 0); 1888219Snate@binkert.org tc->setMiscReg(MISCREG_CR4, 0); 1899512Sandreas@sandberg.pp.se 1909512Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL); 1919512Sandreas@sandberg.pp.se 1928219Snate@binkert.org tc->setMiscReg(MISCREG_EFER, 0); 1938219Snate@binkert.org 1948234Snate@binkert.org SegAttr dataAttr = 0; 1958245Snate@binkert.org dataAttr.dpl = 0; 1968245Snate@binkert.org dataAttr.unusable = 0; 1975801Snate@binkert.org dataAttr.defaultSize = 0; 1985801Snate@binkert.org dataAttr.longMode = 0; 1995801Snate@binkert.org dataAttr.avl = 0; 2004167Sbinkertn@umich.edu dataAttr.granularity = 0; 2014042Sbinkertn@umich.edu dataAttr.present = 1; 2025801Snate@binkert.org dataAttr.type = 3; 2035799Snate@binkert.org dataAttr.writable = 1; 2045799Snate@binkert.org dataAttr.readable = 1; 20511923Sandreas.sandberg@arm.com dataAttr.expandDown = 0; 2068234Snate@binkert.org dataAttr.system = 1; 2078234Snate@binkert.org 2088234Snate@binkert.org for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) { 2098234Snate@binkert.org tc->setMiscReg(MISCREG_SEG_SEL(seg), 0); 2108234Snate@binkert.org tc->setMiscReg(MISCREG_SEG_BASE(seg), 0); 2118234Snate@binkert.org tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0); 21213663Sandreas.sandberg@arm.com tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff); 2138234Snate@binkert.org tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr); 2148245Snate@binkert.org } 2158245Snate@binkert.org 2165799Snate@binkert.org SegAttr codeAttr = 0; 2175799Snate@binkert.org codeAttr.dpl = 0; 2185799Snate@binkert.org codeAttr.unusable = 0; 2195799Snate@binkert.org codeAttr.defaultSize = 0; 2205802Snate@binkert.org codeAttr.longMode = 0; 2212889Sbinkertn@umich.edu codeAttr.avl = 0; 2229983Sstever@gmail.com codeAttr.granularity = 0; 2239983Sstever@gmail.com codeAttr.present = 1; 2249983Sstever@gmail.com codeAttr.type = 10; 2259983Sstever@gmail.com codeAttr.writable = 0; 2265524Sstever@gmail.com codeAttr.readable = 1; 2275524Sstever@gmail.com codeAttr.expandDown = 0; 2285524Sstever@gmail.com codeAttr.system = 1; 2295524Sstever@gmail.com 2305524Sstever@gmail.com tc->setMiscReg(MISCREG_CS, 0xf000); 2315524Sstever@gmail.com tc->setMiscReg(MISCREG_CS_BASE, 2325524Sstever@gmail.com 0x00000000ffff0000ULL); 2335524Sstever@gmail.com tc->setMiscReg(MISCREG_CS_EFF_BASE, 2345524Sstever@gmail.com 0x00000000ffff0000ULL); 23512563Sgabeblack@google.com // This has the base value pre-added. 2365524Sstever@gmail.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff); 2375524Sstever@gmail.com tc->setMiscReg(MISCREG_CS_ATTR, codeAttr); 23812563Sgabeblack@google.com 2395524Sstever@gmail.com PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE)); 24012563Sgabeblack@google.com tc->pcState(pc); 2415524Sstever@gmail.com 2425524Sstever@gmail.com tc->setMiscReg(MISCREG_TSG_BASE, 0); 2435524Sstever@gmail.com tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); 2445524Sstever@gmail.com 2455524Sstever@gmail.com tc->setMiscReg(MISCREG_IDTR_BASE, 0); 2465524Sstever@gmail.com tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); 2475524Sstever@gmail.com 2485524Sstever@gmail.com tc->setMiscReg(MISCREG_TSL, 0); 2495524Sstever@gmail.com tc->setMiscReg(MISCREG_TSL_BASE, 0); 2505524Sstever@gmail.com tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff); 2515524Sstever@gmail.com tc->setMiscReg(MISCREG_TSL_ATTR, 0); 2525524Sstever@gmail.com 2532889Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TR, 0); 2544850Snate@binkert.org tc->setMiscReg(MISCREG_TR_BASE, 0); 2554850Snate@binkert.org tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff); 2564850Snate@binkert.org tc->setMiscReg(MISCREG_TR_ATTR, 0); 25712563Sgabeblack@google.com 25812563Sgabeblack@google.com // This value should be the family/model/stepping of the processor. 25912563Sgabeblack@google.com // (page 418). It should be consistent with the value from CPUID, but 26012563Sgabeblack@google.com // the actual value probably doesn't matter much. 2615801Snate@binkert.org tc->setIntReg(INTREG_RDX, 0); 2624850Snate@binkert.org 2634850Snate@binkert.org tc->setMiscReg(MISCREG_DR0, 0); 2645801Snate@binkert.org tc->setMiscReg(MISCREG_DR1, 0); 26512563Sgabeblack@google.com tc->setMiscReg(MISCREG_DR2, 0); 26612563Sgabeblack@google.com tc->setMiscReg(MISCREG_DR3, 0); 2674850Snate@binkert.org 2682889Sbinkertn@umich.edu tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); 2692889Sbinkertn@umich.edu tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); 27012563Sgabeblack@google.com 27112563Sgabeblack@google.com // Update the handy M5 Reg. 2722889Sbinkertn@umich.edu tc->setMiscReg(MISCREG_M5_REG, 0); 2732889Sbinkertn@umich.edu MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; 2742889Sbinkertn@umich.edu pc.upc(romMicroPC(entry)); 27512563Sgabeblack@google.com pc.nupc(romMicroPC(entry) + 1); 27612563Sgabeblack@google.com tc->pcState(pc); 27712563Sgabeblack@google.com } 27812563Sgabeblack@google.com 2792889Sbinkertn@umich.edu void 2808232Snate@binkert.org StartupInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) 2814053Sbinkertn@umich.edu { 2825799Snate@binkert.org DPRINTF(Faults, "Startup interrupt with vector %#x.\n", vector); 2838232Snate@binkert.org HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG); 2844053Sbinkertn@umich.edu if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) { 2855473Snate@binkert.org panic("Startup IPI recived outside of real mode. " 2865473Snate@binkert.org "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode); 2875473Snate@binkert.org } 28812563Sgabeblack@google.com 2895473Snate@binkert.org tc->setMiscReg(MISCREG_CS, vector << 8); 2905473Snate@binkert.org tc->setMiscReg(MISCREG_CS_BASE, vector << 12); 2915473Snate@binkert.org tc->setMiscReg(MISCREG_CS_EFF_BASE, vector << 12); 2925473Snate@binkert.org // This has the base value pre-added. 29312563Sgabeblack@google.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff); 2945473Snate@binkert.org 2955473Snate@binkert.org tc->pcState(tc->readMiscReg(MISCREG_CS_BASE)); 2965473Snate@binkert.org } 2975473Snate@binkert.org} // namespace X86ISA 2985473Snate@binkert.org 29912563Sgabeblack@google.com