utility.cc revision 9880
12SN/A/* 21762SN/A * Copyright (c) 2007 The Hewlett-Packard Development Company 32SN/A * Copyright (c) 2011 Advanced Micro Devices, Inc. 42SN/A * All rights reserved. 52SN/A * 62SN/A * The license below extends only to copyright in the software and shall 72SN/A * not be construed as granting a license to any other intellectual 82SN/A * property including but not limited to intellectual property relating 92SN/A * to a hardware implementation of the functionality of the software 102SN/A * licensed hereunder. You may use the software subject to the license 112SN/A * terms below provided that you ensure that this notice is replicated 122SN/A * unmodified and in its entirety in all distributions of the software, 132SN/A * modified or unmodified, in source code or in binary form. 142SN/A * 152SN/A * Redistribution and use in source and binary forms, with or without 162SN/A * modification, are permitted provided that the following conditions are 172SN/A * met: redistributions of source code must retain the above copyright 182SN/A * notice, this list of conditions and the following disclaimer; 192SN/A * redistributions in binary form must reproduce the above copyright 202SN/A * notice, this list of conditions and the following disclaimer in the 212SN/A * documentation and/or other materials provided with the distribution; 222SN/A * neither the name of the copyright holders nor the names of its 232SN/A * contributors may be used to endorse or promote products derived from 242SN/A * this software without specific prior written permission. 252SN/A * 262SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282760Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292760Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 322SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 332SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34363SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35363SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 361354SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372SN/A * 382SN/A * Authors: Gabe Black 392SN/A */ 402SN/A 412SN/A#include "arch/x86/interrupts.hh" 422SN/A#include "arch/x86/registers.hh" 43363SN/A#include "arch/x86/tlb.hh" 4456SN/A#include "arch/x86/utility.hh" 451388SN/A#include "arch/x86/x86_traits.hh" 46217SN/A#include "cpu/base.hh" 47363SN/A#include "sim/system.hh" 4856SN/A 4956SN/Anamespace X86ISA { 5056SN/A 511638SN/Auint64_t 5256SN/AgetArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) 532SN/A{ 542356SN/A panic("getArgument() not implemented for x86!\n"); 552356SN/A M5_DUMMY_RETURN 562356SN/A} 572SN/A 582SN/Avoid initCPU(ThreadContext *tc, int cpuId) 594000Ssaidi@eecs.umich.edu{ 604000Ssaidi@eecs.umich.edu // This function is essentially performing a reset. The actual INIT 614762Snate@binkert.org // interrupt does a subset of this, so we'll piggyback on some of its 624762Snate@binkert.org // functionality. 634762Snate@binkert.org InitInterrupt init(0); 644762Snate@binkert.org init.invoke(tc); 654762Snate@binkert.org 664762Snate@binkert.org PCState pc = tc->pcState(); 674762Snate@binkert.org pc.upc(0); 684762Snate@binkert.org pc.nupc(1); 694762Snate@binkert.org tc->pcState(pc); 704762Snate@binkert.org 714762Snate@binkert.org // These next two loops zero internal microcode and implicit registers. 724762Snate@binkert.org // They aren't specified by the ISA but are used internally by M5's 734762Snate@binkert.org // implementation. 744762Snate@binkert.org for (int index = 0; index < NumMicroIntRegs; index++) { 754762Snate@binkert.org tc->setIntReg(INTREG_MICRO(index), 0); 764762Snate@binkert.org } 774762Snate@binkert.org 784762Snate@binkert.org for (int index = 0; index < NumImplicitIntRegs; index++) { 794762Snate@binkert.org tc->setIntReg(INTREG_IMPLICIT(index), 0); 804762Snate@binkert.org } 814762Snate@binkert.org 824762Snate@binkert.org // Set integer register EAX to 0 to indicate that the optional BIST 834762Snate@binkert.org // passed. No BIST actually runs, but software may still check this 844762Snate@binkert.org // register for errors. 854762Snate@binkert.org tc->setIntReg(INTREG_RAX, 0); 864762Snate@binkert.org 874762Snate@binkert.org tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL); 884762Snate@binkert.org tc->setMiscReg(MISCREG_CR8, 0); 894762Snate@binkert.org 904762Snate@binkert.org // TODO initialize x87, 64 bit, and 128 bit media state 914762Snate@binkert.org 924762Snate@binkert.org tc->setMiscReg(MISCREG_MTRRCAP, 0x0508); 934762Snate@binkert.org for (int i = 0; i < 8; i++) { 944762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0); 954762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0); 964762Snate@binkert.org } 974762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0); 984762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0); 994762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0); 1004762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0); 1014762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0); 1024762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0); 1034762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0); 1044762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0); 1054762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0); 1064762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0); 1074762Snate@binkert.org tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0); 1084762Snate@binkert.org 1094762Snate@binkert.org tc->setMiscReg(MISCREG_DEF_TYPE, 0); 1104762Snate@binkert.org 1114762Snate@binkert.org tc->setMiscReg(MISCREG_MCG_CAP, 0x104); 1124762Snate@binkert.org tc->setMiscReg(MISCREG_MCG_STATUS, 0); 1134762Snate@binkert.org tc->setMiscReg(MISCREG_MCG_CTL, 0); 1144762Snate@binkert.org 1154762Snate@binkert.org for (int i = 0; i < 5; i++) { 1164762Snate@binkert.org tc->setMiscReg(MISCREG_MC_CTL(i), 0); 1174762Snate@binkert.org tc->setMiscReg(MISCREG_MC_STATUS(i), 0); 1184762Snate@binkert.org tc->setMiscReg(MISCREG_MC_ADDR(i), 0); 1194762Snate@binkert.org tc->setMiscReg(MISCREG_MC_MISC(i), 0); 1204762Snate@binkert.org } 1214762Snate@binkert.org 1224762Snate@binkert.org tc->setMiscReg(MISCREG_TSC, 0); 1234762Snate@binkert.org tc->setMiscReg(MISCREG_TSC_AUX, 0); 1244762Snate@binkert.org 1254762Snate@binkert.org for (int i = 0; i < 4; i++) { 1264762Snate@binkert.org tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0); 1274762Snate@binkert.org tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0); 1284762Snate@binkert.org } 1294762Snate@binkert.org 1304762Snate@binkert.org tc->setMiscReg(MISCREG_STAR, 0); 1314762Snate@binkert.org tc->setMiscReg(MISCREG_LSTAR, 0); 1324762Snate@binkert.org tc->setMiscReg(MISCREG_CSTAR, 0); 1334762Snate@binkert.org 1344762Snate@binkert.org tc->setMiscReg(MISCREG_SF_MASK, 0); 1354762Snate@binkert.org 1364762Snate@binkert.org tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0); 1374762Snate@binkert.org 1384762Snate@binkert.org tc->setMiscReg(MISCREG_SYSENTER_CS, 0); 1394762Snate@binkert.org tc->setMiscReg(MISCREG_SYSENTER_ESP, 0); 1404762Snate@binkert.org tc->setMiscReg(MISCREG_SYSENTER_EIP, 0); 1414762Snate@binkert.org 1424762Snate@binkert.org tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL); 1434762Snate@binkert.org 1444762Snate@binkert.org tc->setMiscReg(MISCREG_SYSCFG, 0x20601); 1454762Snate@binkert.org 1464762Snate@binkert.org tc->setMiscReg(MISCREG_IORR_BASE0, 0); 1474762Snate@binkert.org tc->setMiscReg(MISCREG_IORR_BASE1, 0); 1484762Snate@binkert.org 1494762Snate@binkert.org tc->setMiscReg(MISCREG_IORR_MASK0, 0); 1504762Snate@binkert.org tc->setMiscReg(MISCREG_IORR_MASK1, 0); 1514762Snate@binkert.org 1524762Snate@binkert.org tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000); 1534762Snate@binkert.org tc->setMiscReg(MISCREG_TOP_MEM2, 0x0); 1544762Snate@binkert.org 1554762Snate@binkert.org tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0); 1562287SN/A tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0); 1572287SN/A tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0); 1582287SN/A tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0); 1591637SN/A tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0); 1602SN/A 161395SN/A // Invalidate the caches (this should already be done for us) 1622SN/A 163217SN/A LocalApicBase lApicBase = 0; 1642SN/A lApicBase.base = 0xFEE00000 >> 12; 1652SN/A lApicBase.enable = 1; 1662SN/A lApicBase.bsp = (cpuId == 0); 167395SN/A tc->setMiscReg(MISCREG_APIC_BASE, lApicBase); 1682SN/A 169217SN/A Interrupts * interrupts = dynamic_cast<Interrupts *>( 1702SN/A tc->getCpuPtr()->getInterruptController()); 1712SN/A assert(interrupts); 172217SN/A 1732SN/A interrupts->setRegNoEffect(APIC_ID, cpuId << 24); 174502SN/A 1752SN/A interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); 176217SN/A 177217SN/A // TODO Set the SMRAM base address (SMBASE) to 0x00030000 178217SN/A 1792SN/A tc->setMiscReg(MISCREG_VM_CR, 0); 1802SN/A tc->setMiscReg(MISCREG_IGNNE, 0); 181217SN/A tc->setMiscReg(MISCREG_SMM_CTL, 0); 182217SN/A tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0); 183217SN/A} 184237SN/A 185502SN/Avoid startupCPU(ThreadContext *tc, int cpuId) 1862SN/A{ 187217SN/A if (cpuId == 0 || !FullSystem) { 188237SN/A tc->activate(Cycles(0)); 189217SN/A } else { 190217SN/A // This is an application processor (AP). It should be initialized to 1912SN/A // look like only the BIOS POST has run on it and put then put it into 1922SN/A // a halted state. 193217SN/A tc->suspend(Cycles(0)); 194217SN/A } 195217SN/A} 196217SN/A 197217SN/Avoid 198217SN/AcopyMiscRegs(ThreadContext *src, ThreadContext *dest) 199217SN/A{ 200217SN/A // This function assumes no side effects other than TLB invalidation 201217SN/A // need to be considered while copying state. That will likely not be 202217SN/A // true in the future. 203217SN/A for (int i = 0; i < NUM_MISCREGS; ++i) { 204217SN/A if ( ( i != MISCREG_CR1 && 205217SN/A !(i > MISCREG_CR4 && i < MISCREG_CR8) && 206217SN/A !(i > MISCREG_CR8 && i <= MISCREG_CR15) ) == false) { 207217SN/A continue; 208217SN/A } 209217SN/A dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); 210217SN/A } 211217SN/A 212237SN/A // The TSC has to be updated with side-effects if the CPUs in a 213217SN/A // CPU switch have different frequencies. 214217SN/A dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC)); 215217SN/A 216237SN/A dest->getITBPtr()->flushAll(); 217217SN/A dest->getDTBPtr()->flushAll(); 218217SN/A} 219217SN/A 220217SN/Avoid 221217SN/AcopyRegs(ThreadContext *src, ThreadContext *dest) 222217SN/A{ 223217SN/A //copy int regs 224217SN/A for (int i = 0; i < NumIntRegs; ++i) 225217SN/A dest->setIntReg(i, src->readIntReg(i)); 226217SN/A //copy float regs 227217SN/A for (int i = 0; i < NumFloatRegs; ++i) 228217SN/A dest->setFloatRegBits(i, src->readFloatRegBits(i)); 229217SN/A copyMiscRegs(src, dest); 230217SN/A dest->pcState(src->pcState()); 231217SN/A} 232217SN/A 233217SN/Avoid 234217SN/AskipFunction(ThreadContext *tc) 235217SN/A{ 236217SN/A panic("Not implemented for x86\n"); 237217SN/A} 238217SN/A 239217SN/Auint64_t 240217SN/AgetRFlags(ThreadContext *tc) 241217SN/A{ 242217SN/A const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS)); 243217SN/A const uint64_t cc_flags(tc->readIntReg(X86ISA::INTREG_PSEUDO(0))); 244217SN/A const uint64_t cfof_bits(tc->readIntReg(X86ISA::INTREG_PSEUDO(1))); 245217SN/A const uint64_t df_bit(tc->readIntReg(X86ISA::INTREG_PSEUDO(2))); 246217SN/A // ecf (PSEUDO(3)) & ezf (PSEUDO(4)) are only visible to 247217SN/A // microcode, so we can safely ignore them. 248217SN/A 249217SN/A // Reconstruct the real rflags state, mask out internal flags, and 250217SN/A // make sure reserved bits have the expected values. 251217SN/A return ((ncc_flags | cc_flags | cfof_bits | df_bit) & 0x3F7FD5) 252217SN/A | 0x2; 253217SN/A} 254217SN/A 255237SN/Avoid 256237SN/AsetRFlags(ThreadContext *tc, uint64_t val) 2574000Ssaidi@eecs.umich.edu{ 258237SN/A tc->setIntReg(X86ISA::INTREG_PSEUDO(0), val & ccFlagMask); 259237SN/A tc->setIntReg(X86ISA::INTREG_PSEUDO(1), val & cfofMask); 260237SN/A tc->setIntReg(X86ISA::INTREG_PSEUDO(2), val & DFBit); 261237SN/A 262237SN/A // Internal microcode registers (ECF & EZF) 263237SN/A tc->setIntReg(X86ISA::INTREG_PSEUDO(3), 0); 264237SN/A tc->setIntReg(X86ISA::INTREG_PSEUDO(4), 0); 265221SN/A 266221SN/A // Update the RFLAGS misc reg with whatever didn't go into the 267237SN/A // magic registers. 268221SN/A tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); 269237SN/A} 270221SN/A 271221SN/Auint8_t 272221SN/AconvX87TagsToXTags(uint16_t ftw) 273237SN/A{ 274221SN/A uint8_t ftwx(0); 275237SN/A for (int i = 0; i < 8; ++i) { 276217SN/A // Extract the tag for the current element on the FP stack 277217SN/A const unsigned tag((ftw >> (2 * i)) & 0x3); 2781642SN/A 2791642SN/A /* 2801642SN/A * Check the type of the current FP element. Valid values are: 2811642SN/A * 0 == Valid 2821642SN/A * 1 == Zero 2831642SN/A * 2 == Special (Nan, unsupported, infinity, denormal) 2841642SN/A * 3 == Empty 2851642SN/A */ 2861642SN/A // The xsave version of the tag word only keeps track of 2871642SN/A // whether the element is empty or not. Set the corresponding 288219SN/A // bit in the ftwx if it's not empty, 289217SN/A if (tag != 0x3) 290217SN/A ftwx |= 1 << i; 291217SN/A } 292395SN/A 293395SN/A return ftwx; 294395SN/A} 295395SN/A 296395SN/Auint16_t 2972SN/AconvX87XTagsToTags(uint8_t ftwx) 298395SN/A{ 299512SN/A uint16_t ftw(0); 300510SN/A for (int i = 0; i < 8; ++i) { 301395SN/A const unsigned xtag(((ftwx >> i) & 0x1)); 302395SN/A 3032SN/A // The xtag for an x87 stack position is 0 for empty stack positions. 304395SN/A if (!xtag) { 305395SN/A // Set the tag word to 3 (empty) for the current element. 3062SN/A ftw |= 0x3 << (2 * i); 307512SN/A } else { 308395SN/A // TODO: We currently assume that non-empty elements are 3092SN/A // valid (0x0), but we should ideally reconstruct the full 310395SN/A // state (valid/zero/special). 3112SN/A } 3122SN/A } 3132SN/A 314510SN/A return ftw; 3152SN/A} 316395SN/A 317395SN/Auint16_t 318395SN/AgenX87Tags(uint16_t ftw, uint8_t top, int8_t spm) 319395SN/A{ 320395SN/A const uint8_t new_top((top + spm + 8) % 8); 3212SN/A 3222SN/A if (spm > 0) { 3232SN/A // Removing elements from the stack. Flag the elements as empty. 324395SN/A for (int i = top; i != new_top; i = (i + 1 + 8) % 8) 3252SN/A ftw |= 0x3 << (2 * i); 326395SN/A } else if (spm < 0) { 327395SN/A // Adding elements to the stack. Flag the new elements as 3282SN/A // valid. We should ideally decode them and "do the right 329395SN/A // thing". 3302SN/A for (int i = new_top; i != top; i = (i + 1 + 8) % 8) 3312SN/A ftw &= ~(0x3 << (2 * i)); 3322SN/A } 3332868Sktlim@umich.edu 3342SN/A return ftw; 3352868Sktlim@umich.edu} 336449SN/A 337363SN/A} // namespace X86_ISA 338449SN/A