utility.cc revision 9880
1/* 2 * Copyright (c) 2007 The Hewlett-Packard Development Company 3 * Copyright (c) 2011 Advanced Micro Devices, Inc. 4 * All rights reserved. 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions are 17 * met: redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer; 19 * redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution; 22 * neither the name of the copyright holders nor the names of its 23 * contributors may be used to endorse or promote products derived from 24 * this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 * 38 * Authors: Gabe Black 39 */ 40 41#include "arch/x86/interrupts.hh" 42#include "arch/x86/registers.hh" 43#include "arch/x86/tlb.hh" 44#include "arch/x86/utility.hh" 45#include "arch/x86/x86_traits.hh" 46#include "cpu/base.hh" 47#include "sim/system.hh" 48 49namespace X86ISA { 50 51uint64_t 52getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) 53{ 54 panic("getArgument() not implemented for x86!\n"); 55 M5_DUMMY_RETURN 56} 57 58void initCPU(ThreadContext *tc, int cpuId) 59{ 60 // This function is essentially performing a reset. The actual INIT 61 // interrupt does a subset of this, so we'll piggyback on some of its 62 // functionality. 63 InitInterrupt init(0); 64 init.invoke(tc); 65 66 PCState pc = tc->pcState(); 67 pc.upc(0); 68 pc.nupc(1); 69 tc->pcState(pc); 70 71 // These next two loops zero internal microcode and implicit registers. 72 // They aren't specified by the ISA but are used internally by M5's 73 // implementation. 74 for (int index = 0; index < NumMicroIntRegs; index++) { 75 tc->setIntReg(INTREG_MICRO(index), 0); 76 } 77 78 for (int index = 0; index < NumImplicitIntRegs; index++) { 79 tc->setIntReg(INTREG_IMPLICIT(index), 0); 80 } 81 82 // Set integer register EAX to 0 to indicate that the optional BIST 83 // passed. No BIST actually runs, but software may still check this 84 // register for errors. 85 tc->setIntReg(INTREG_RAX, 0); 86 87 tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL); 88 tc->setMiscReg(MISCREG_CR8, 0); 89 90 // TODO initialize x87, 64 bit, and 128 bit media state 91 92 tc->setMiscReg(MISCREG_MTRRCAP, 0x0508); 93 for (int i = 0; i < 8; i++) { 94 tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0); 95 tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0); 96 } 97 tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0); 98 tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0); 99 tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0); 100 tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0); 101 tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0); 102 tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0); 103 tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0); 104 tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0); 105 tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0); 106 tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0); 107 tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0); 108 109 tc->setMiscReg(MISCREG_DEF_TYPE, 0); 110 111 tc->setMiscReg(MISCREG_MCG_CAP, 0x104); 112 tc->setMiscReg(MISCREG_MCG_STATUS, 0); 113 tc->setMiscReg(MISCREG_MCG_CTL, 0); 114 115 for (int i = 0; i < 5; i++) { 116 tc->setMiscReg(MISCREG_MC_CTL(i), 0); 117 tc->setMiscReg(MISCREG_MC_STATUS(i), 0); 118 tc->setMiscReg(MISCREG_MC_ADDR(i), 0); 119 tc->setMiscReg(MISCREG_MC_MISC(i), 0); 120 } 121 122 tc->setMiscReg(MISCREG_TSC, 0); 123 tc->setMiscReg(MISCREG_TSC_AUX, 0); 124 125 for (int i = 0; i < 4; i++) { 126 tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0); 127 tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0); 128 } 129 130 tc->setMiscReg(MISCREG_STAR, 0); 131 tc->setMiscReg(MISCREG_LSTAR, 0); 132 tc->setMiscReg(MISCREG_CSTAR, 0); 133 134 tc->setMiscReg(MISCREG_SF_MASK, 0); 135 136 tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0); 137 138 tc->setMiscReg(MISCREG_SYSENTER_CS, 0); 139 tc->setMiscReg(MISCREG_SYSENTER_ESP, 0); 140 tc->setMiscReg(MISCREG_SYSENTER_EIP, 0); 141 142 tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL); 143 144 tc->setMiscReg(MISCREG_SYSCFG, 0x20601); 145 146 tc->setMiscReg(MISCREG_IORR_BASE0, 0); 147 tc->setMiscReg(MISCREG_IORR_BASE1, 0); 148 149 tc->setMiscReg(MISCREG_IORR_MASK0, 0); 150 tc->setMiscReg(MISCREG_IORR_MASK1, 0); 151 152 tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000); 153 tc->setMiscReg(MISCREG_TOP_MEM2, 0x0); 154 155 tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0); 156 tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0); 157 tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0); 158 tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0); 159 tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0); 160 161 // Invalidate the caches (this should already be done for us) 162 163 LocalApicBase lApicBase = 0; 164 lApicBase.base = 0xFEE00000 >> 12; 165 lApicBase.enable = 1; 166 lApicBase.bsp = (cpuId == 0); 167 tc->setMiscReg(MISCREG_APIC_BASE, lApicBase); 168 169 Interrupts * interrupts = dynamic_cast<Interrupts *>( 170 tc->getCpuPtr()->getInterruptController()); 171 assert(interrupts); 172 173 interrupts->setRegNoEffect(APIC_ID, cpuId << 24); 174 175 interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); 176 177 // TODO Set the SMRAM base address (SMBASE) to 0x00030000 178 179 tc->setMiscReg(MISCREG_VM_CR, 0); 180 tc->setMiscReg(MISCREG_IGNNE, 0); 181 tc->setMiscReg(MISCREG_SMM_CTL, 0); 182 tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0); 183} 184 185void startupCPU(ThreadContext *tc, int cpuId) 186{ 187 if (cpuId == 0 || !FullSystem) { 188 tc->activate(Cycles(0)); 189 } else { 190 // This is an application processor (AP). It should be initialized to 191 // look like only the BIOS POST has run on it and put then put it into 192 // a halted state. 193 tc->suspend(Cycles(0)); 194 } 195} 196 197void 198copyMiscRegs(ThreadContext *src, ThreadContext *dest) 199{ 200 // This function assumes no side effects other than TLB invalidation 201 // need to be considered while copying state. That will likely not be 202 // true in the future. 203 for (int i = 0; i < NUM_MISCREGS; ++i) { 204 if ( ( i != MISCREG_CR1 && 205 !(i > MISCREG_CR4 && i < MISCREG_CR8) && 206 !(i > MISCREG_CR8 && i <= MISCREG_CR15) ) == false) { 207 continue; 208 } 209 dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); 210 } 211 212 // The TSC has to be updated with side-effects if the CPUs in a 213 // CPU switch have different frequencies. 214 dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC)); 215 216 dest->getITBPtr()->flushAll(); 217 dest->getDTBPtr()->flushAll(); 218} 219 220void 221copyRegs(ThreadContext *src, ThreadContext *dest) 222{ 223 //copy int regs 224 for (int i = 0; i < NumIntRegs; ++i) 225 dest->setIntReg(i, src->readIntReg(i)); 226 //copy float regs 227 for (int i = 0; i < NumFloatRegs; ++i) 228 dest->setFloatRegBits(i, src->readFloatRegBits(i)); 229 copyMiscRegs(src, dest); 230 dest->pcState(src->pcState()); 231} 232 233void 234skipFunction(ThreadContext *tc) 235{ 236 panic("Not implemented for x86\n"); 237} 238 239uint64_t 240getRFlags(ThreadContext *tc) 241{ 242 const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS)); 243 const uint64_t cc_flags(tc->readIntReg(X86ISA::INTREG_PSEUDO(0))); 244 const uint64_t cfof_bits(tc->readIntReg(X86ISA::INTREG_PSEUDO(1))); 245 const uint64_t df_bit(tc->readIntReg(X86ISA::INTREG_PSEUDO(2))); 246 // ecf (PSEUDO(3)) & ezf (PSEUDO(4)) are only visible to 247 // microcode, so we can safely ignore them. 248 249 // Reconstruct the real rflags state, mask out internal flags, and 250 // make sure reserved bits have the expected values. 251 return ((ncc_flags | cc_flags | cfof_bits | df_bit) & 0x3F7FD5) 252 | 0x2; 253} 254 255void 256setRFlags(ThreadContext *tc, uint64_t val) 257{ 258 tc->setIntReg(X86ISA::INTREG_PSEUDO(0), val & ccFlagMask); 259 tc->setIntReg(X86ISA::INTREG_PSEUDO(1), val & cfofMask); 260 tc->setIntReg(X86ISA::INTREG_PSEUDO(2), val & DFBit); 261 262 // Internal microcode registers (ECF & EZF) 263 tc->setIntReg(X86ISA::INTREG_PSEUDO(3), 0); 264 tc->setIntReg(X86ISA::INTREG_PSEUDO(4), 0); 265 266 // Update the RFLAGS misc reg with whatever didn't go into the 267 // magic registers. 268 tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); 269} 270 271uint8_t 272convX87TagsToXTags(uint16_t ftw) 273{ 274 uint8_t ftwx(0); 275 for (int i = 0; i < 8; ++i) { 276 // Extract the tag for the current element on the FP stack 277 const unsigned tag((ftw >> (2 * i)) & 0x3); 278 279 /* 280 * Check the type of the current FP element. Valid values are: 281 * 0 == Valid 282 * 1 == Zero 283 * 2 == Special (Nan, unsupported, infinity, denormal) 284 * 3 == Empty 285 */ 286 // The xsave version of the tag word only keeps track of 287 // whether the element is empty or not. Set the corresponding 288 // bit in the ftwx if it's not empty, 289 if (tag != 0x3) 290 ftwx |= 1 << i; 291 } 292 293 return ftwx; 294} 295 296uint16_t 297convX87XTagsToTags(uint8_t ftwx) 298{ 299 uint16_t ftw(0); 300 for (int i = 0; i < 8; ++i) { 301 const unsigned xtag(((ftwx >> i) & 0x1)); 302 303 // The xtag for an x87 stack position is 0 for empty stack positions. 304 if (!xtag) { 305 // Set the tag word to 3 (empty) for the current element. 306 ftw |= 0x3 << (2 * i); 307 } else { 308 // TODO: We currently assume that non-empty elements are 309 // valid (0x0), but we should ideally reconstruct the full 310 // state (valid/zero/special). 311 } 312 } 313 314 return ftw; 315} 316 317uint16_t 318genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) 319{ 320 const uint8_t new_top((top + spm + 8) % 8); 321 322 if (spm > 0) { 323 // Removing elements from the stack. Flag the elements as empty. 324 for (int i = top; i != new_top; i = (i + 1 + 8) % 8) 325 ftw |= 0x3 << (2 * i); 326 } else if (spm < 0) { 327 // Adding elements to the stack. Flag the new elements as 328 // valid. We should ideally decode them and "do the right 329 // thing". 330 for (int i = new_top; i != top; i = (i + 1 + 8) % 8) 331 ftw &= ~(0x3 << (2 * i)); 332 } 333 334 return ftw; 335} 336 337} // namespace X86_ISA 338