utility.cc revision 9765
110915Sandreas.sandberg@arm.com/* 210915Sandreas.sandberg@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company 310915Sandreas.sandberg@arm.com * Copyright (c) 2011 Advanced Micro Devices, Inc. 410915Sandreas.sandberg@arm.com * All rights reserved. 510915Sandreas.sandberg@arm.com * 610915Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 710915Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 810915Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 910915Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 1010915Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1110915Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1210915Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1310915Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 1410915Sandreas.sandberg@arm.com * 1510915Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 1610915Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 1710915Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 1810915Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 1910915Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 2010915Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 2110915Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 2210915Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 2310915Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 2410915Sandreas.sandberg@arm.com * this software without specific prior written permission. 2510915Sandreas.sandberg@arm.com * 2610915Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2710915Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2810915Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2910915Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3010915Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3110915Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3210915Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3310915Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3410915Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3510915Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3610915Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3710915Sandreas.sandberg@arm.com * 3810915Sandreas.sandberg@arm.com * Authors: Gabe Black 3910915Sandreas.sandberg@arm.com */ 4010915Sandreas.sandberg@arm.com 4110915Sandreas.sandberg@arm.com#include "arch/x86/interrupts.hh" 4210915Sandreas.sandberg@arm.com#include "arch/x86/registers.hh" 4310915Sandreas.sandberg@arm.com#include "arch/x86/tlb.hh" 4410915Sandreas.sandberg@arm.com#include "arch/x86/utility.hh" 4510915Sandreas.sandberg@arm.com#include "arch/x86/x86_traits.hh" 4610915Sandreas.sandberg@arm.com#include "cpu/base.hh" 4710915Sandreas.sandberg@arm.com#include "sim/system.hh" 4810915Sandreas.sandberg@arm.com 4910915Sandreas.sandberg@arm.comnamespace X86ISA { 5010915Sandreas.sandberg@arm.com 5110915Sandreas.sandberg@arm.comuint64_t 5210915Sandreas.sandberg@arm.comgetArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) 5310915Sandreas.sandberg@arm.com{ 5410915Sandreas.sandberg@arm.com panic("getArgument() not implemented for x86!\n"); 5510915Sandreas.sandberg@arm.com M5_DUMMY_RETURN 5610915Sandreas.sandberg@arm.com} 5710915Sandreas.sandberg@arm.com 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 271uint16_t 272genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) 273{ 274 const uint8_t new_top((top + spm + 8) % 8); 275 276 if (spm > 0) { 277 // Removing elements from the stack. Flag the elements as empty. 278 for (int i = top; i != new_top; i = (i + 1 + 8) % 8) 279 ftw |= 0x3 << (2 * i); 280 } else if (spm < 0) { 281 // Adding elements to the stack. Flag the new elements as 282 // valid. We should ideally decode them and "do the right 283 // thing". 284 for (int i = new_top; i != top; i = (i + 1 + 8) % 8) 285 ftw &= ~(0x3 << (2 * i)); 286 } 287 288 return ftw; 289} 290 291} // namespace X86_ISA 292