utility.cc revision 5294:7222bdaed33b
113511Sgabeblack@google.com/* 213511Sgabeblack@google.com * Copyright (c) 2007 The Hewlett-Packard Development Company 313511Sgabeblack@google.com * All rights reserved. 413511Sgabeblack@google.com * 513511Sgabeblack@google.com * Redistribution and use of this software in source and binary forms, 613511Sgabeblack@google.com * with or without modification, are permitted provided that the 713511Sgabeblack@google.com * following conditions are met: 813511Sgabeblack@google.com * 913511Sgabeblack@google.com * The software must be used only for Non-Commercial Use which means any 1013511Sgabeblack@google.com * use which is NOT directed to receiving any direct monetary 1113511Sgabeblack@google.com * compensation for, or commercial advantage from such use. Illustrative 1213511Sgabeblack@google.com * examples of non-commercial use are academic research, personal study, 1313511Sgabeblack@google.com * teaching, education and corporate research & development. 1413511Sgabeblack@google.com * Illustrative examples of commercial use are distributing products for 1513511Sgabeblack@google.com * commercial advantage and providing services using the software for 1613511Sgabeblack@google.com * commercial advantage. 1713511Sgabeblack@google.com * 1813511Sgabeblack@google.com * If you wish to use this software or functionality therein that may be 1913511Sgabeblack@google.com * covered by patents for commercial use, please contact: 2013511Sgabeblack@google.com * Director of Intellectual Property Licensing 2113511Sgabeblack@google.com * Office of Strategy and Technology 2213511Sgabeblack@google.com * Hewlett-Packard Company 2313511Sgabeblack@google.com * 1501 Page Mill Road 2413511Sgabeblack@google.com * Palo Alto, California 94304 2513511Sgabeblack@google.com * 2613511Sgabeblack@google.com * Redistributions of source code must retain the above copyright notice, 2713511Sgabeblack@google.com * this list of conditions and the following disclaimer. Redistributions 2813511Sgabeblack@google.com * in binary form must reproduce the above copyright notice, this list of 2913511Sgabeblack@google.com * conditions and the following disclaimer in the documentation and/or 3013511Sgabeblack@google.com * other materials provided with the distribution. Neither the name of 3113511Sgabeblack@google.com * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 3213511Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 3313511Sgabeblack@google.com * this software without specific prior written permission. No right of 3413511Sgabeblack@google.com * sublicense is granted herewith. Derivatives of the software and 3513511Sgabeblack@google.com * output created using the software may be prepared, but only for 3613511Sgabeblack@google.com * Non-Commercial Uses. Derivatives of the software may be shared with 3713511Sgabeblack@google.com * others provided: (i) the others agree to abide by the list of 3813511Sgabeblack@google.com * conditions herein which includes the Non-Commercial Use restrictions; 3913511Sgabeblack@google.com * and (ii) such Derivatives of the software include the above copyright 4013511Sgabeblack@google.com * notice to acknowledge the contribution from this software where 4113511Sgabeblack@google.com * applicable, this list of conditions and the disclaimer below. 4213511Sgabeblack@google.com * 4313511Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4413511Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 4513511Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 4613511Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 4713511Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4813511Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 4913511Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5013511Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5113511Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5213511Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 5313511Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5413511Sgabeblack@google.com * 5513511Sgabeblack@google.com * Authors: Gabe Black 5613511Sgabeblack@google.com */ 5713511Sgabeblack@google.com 5813511Sgabeblack@google.com#include "arch/x86/intregs.hh" 5913511Sgabeblack@google.com#include "arch/x86/miscregs.hh" 6013511Sgabeblack@google.com#include "arch/x86/segmentregs.hh" 6113511Sgabeblack@google.com#include "arch/x86/utility.hh" 6213511Sgabeblack@google.com#include "arch/x86/x86_traits.hh" 6313511Sgabeblack@google.com#include "sim/system.hh" 6413511Sgabeblack@google.com 6513511Sgabeblack@google.comnamespace X86ISA { 6613511Sgabeblack@google.com 6713511Sgabeblack@google.comuint64_t getArgument(ThreadContext *tc, int number, bool fp) { 6813511Sgabeblack@google.com#if FULL_SYSTEM 6913511Sgabeblack@google.com panic("getArgument() not implemented for x86!\n"); 7013511Sgabeblack@google.com#else 7113511Sgabeblack@google.com panic("getArgument() only implemented for FULL_SYSTEM\n"); 7213511Sgabeblack@google.com M5_DUMMY_RETURN 7313511Sgabeblack@google.com#endif 7413511Sgabeblack@google.com} 7513511Sgabeblack@google.com 7613511Sgabeblack@google.com# if FULL_SYSTEM 7713511Sgabeblack@google.comvoid initCPU(ThreadContext *tc, int cpuId) 7813511Sgabeblack@google.com{ 7913511Sgabeblack@google.com // The otherwise unmodified integer registers should be set to 0. 8013511Sgabeblack@google.com for (int index = 0; index < NUM_INTREGS; index++) { 8113511Sgabeblack@google.com tc->setIntReg(index, 0); 8213511Sgabeblack@google.com } 8313511Sgabeblack@google.com 8413511Sgabeblack@google.com // These next two loops zero internal microcode and implicit registers. 8513511Sgabeblack@google.com // They aren't specified by the ISA but are used internally by M5's 8613511Sgabeblack@google.com // implementation. 8713511Sgabeblack@google.com for (int index = 0; index < NumMicroIntRegs; index++) { 8813511Sgabeblack@google.com tc->setIntReg(INTREG_MICRO(index), 0); 8913511Sgabeblack@google.com } 9013511Sgabeblack@google.com 9113511Sgabeblack@google.com for (int index = 0; index < NumImplicitIntRegs; index++) { 9213511Sgabeblack@google.com tc->setIntReg(INTREG_IMPLICIT(index), 0); 9313511Sgabeblack@google.com } 9413511Sgabeblack@google.com 9513511Sgabeblack@google.com // Set integer register EAX to 0 to indicate that the optional BIST 9613511Sgabeblack@google.com // passed. No BIST actually runs, but software may still check this 9713511Sgabeblack@google.com // register for errors. 9813511Sgabeblack@google.com tc->setIntReg(INTREG_RAX, 0); 9913511Sgabeblack@google.com 10013511Sgabeblack@google.com //The following values are dictated by the architecture for after a RESET# 10113511Sgabeblack@google.com tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL); 10213511Sgabeblack@google.com tc->setMiscReg(MISCREG_CR2, 0); 10313511Sgabeblack@google.com tc->setMiscReg(MISCREG_CR3, 0); 10413511Sgabeblack@google.com tc->setMiscReg(MISCREG_CR4, 0); 10513511Sgabeblack@google.com tc->setMiscReg(MISCREG_CR8, 0); 10613511Sgabeblack@google.com 10713511Sgabeblack@google.com tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL); 10813511Sgabeblack@google.com 10913511Sgabeblack@google.com tc->setMiscReg(MISCREG_EFER, 0); 11013511Sgabeblack@google.com 11113511Sgabeblack@google.com SegAttr dataAttr = 0; 11213511Sgabeblack@google.com dataAttr.writable = 1; 11313511Sgabeblack@google.com dataAttr.readable = 1; 11413511Sgabeblack@google.com dataAttr.expandDown = 0; 11513511Sgabeblack@google.com dataAttr.dpl = 0; 11613511Sgabeblack@google.com dataAttr.defaultSize = 0; 11713511Sgabeblack@google.com 11813511Sgabeblack@google.com for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) { 11913511Sgabeblack@google.com tc->setMiscReg(MISCREG_SEG_SEL(seg), 0); 12013511Sgabeblack@google.com tc->setMiscReg(MISCREG_SEG_BASE(seg), 0); 12113511Sgabeblack@google.com tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0); 12213511Sgabeblack@google.com tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff); 12313511Sgabeblack@google.com tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr); 12413511Sgabeblack@google.com } 12513511Sgabeblack@google.com 12613511Sgabeblack@google.com SegAttr codeAttr = 0; 12713511Sgabeblack@google.com codeAttr.writable = 0; 12813511Sgabeblack@google.com codeAttr.readable = 1; 12913511Sgabeblack@google.com codeAttr.expandDown = 0; 13013511Sgabeblack@google.com codeAttr.dpl = 0; 13113511Sgabeblack@google.com codeAttr.defaultSize = 0; 13213511Sgabeblack@google.com 13313511Sgabeblack@google.com tc->setMiscReg(MISCREG_CS, 0xf000); 13413511Sgabeblack@google.com tc->setMiscReg(MISCREG_CS_BASE, 13513511Sgabeblack@google.com 0x00000000ffff0000ULL); 13613511Sgabeblack@google.com tc->setMiscReg(MISCREG_CS_EFF_BASE, 13713511Sgabeblack@google.com 0x00000000ffff0000ULL); 13813511Sgabeblack@google.com // This has the base value pre-added. 13913511Sgabeblack@google.com tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff); 14013511Sgabeblack@google.com tc->setMiscReg(MISCREG_CS_ATTR, codeAttr); 14113511Sgabeblack@google.com 14213511Sgabeblack@google.com tc->setPC(0x000000000000fff0ULL + 14313511Sgabeblack@google.com tc->readMiscReg(MISCREG_CS_BASE)); 14413511Sgabeblack@google.com tc->setNextPC(tc->readPC() + sizeof(MachInst)); 14513511Sgabeblack@google.com 14613511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSG_BASE, 0); 14713511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); 14813511Sgabeblack@google.com 14913511Sgabeblack@google.com tc->setMiscReg(MISCREG_IDTR_BASE, 0); 15013511Sgabeblack@google.com tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); 15113511Sgabeblack@google.com 15213511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSL, 0); 15313511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSL_BASE, 0); 15413511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff); 15513511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSL_ATTR, 0); 15613511Sgabeblack@google.com 15713511Sgabeblack@google.com tc->setMiscReg(MISCREG_TR, 0); 15813511Sgabeblack@google.com tc->setMiscReg(MISCREG_TR_BASE, 0); 15913511Sgabeblack@google.com tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff); 16013511Sgabeblack@google.com tc->setMiscReg(MISCREG_TR_ATTR, 0); 16113511Sgabeblack@google.com 16213511Sgabeblack@google.com // This value should be the family/model/stepping of the processor. 16313511Sgabeblack@google.com // (page 418). It should be consistent with the value from CPUID, but the 16413511Sgabeblack@google.com // actual value probably doesn't matter much. 16513511Sgabeblack@google.com tc->setIntReg(INTREG_RDX, 0); 16613511Sgabeblack@google.com 16713511Sgabeblack@google.com // TODO initialize x87, 64 bit, and 128 bit media state 16813511Sgabeblack@google.com 16913511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRRCAP, 0x0508); 17013511Sgabeblack@google.com for (int i = 0; i < 8; i++) { 17113511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0); 17213511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0); 17313511Sgabeblack@google.com } 17413511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0); 17513511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0); 17613511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0); 17713511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0); 17813511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0); 17913511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0); 18013511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0); 18113511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0); 18213511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0); 18313511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0); 18413511Sgabeblack@google.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0); 18513511Sgabeblack@google.com 18613511Sgabeblack@google.com tc->setMiscReg(MISCREG_DEF_TYPE, 0); 18713511Sgabeblack@google.com 18813511Sgabeblack@google.com tc->setMiscReg(MISCREG_MCG_CAP, 0x104); 18913511Sgabeblack@google.com tc->setMiscReg(MISCREG_MCG_STATUS, 0); 19013511Sgabeblack@google.com tc->setMiscReg(MISCREG_MCG_CTL, 0); 19113511Sgabeblack@google.com 19213511Sgabeblack@google.com for (int i = 0; i < 5; i++) { 19313511Sgabeblack@google.com tc->setMiscReg(MISCREG_MC_CTL(i), 0); 19413511Sgabeblack@google.com tc->setMiscReg(MISCREG_MC_STATUS(i), 0); 19513511Sgabeblack@google.com tc->setMiscReg(MISCREG_MC_ADDR(i), 0); 19613511Sgabeblack@google.com tc->setMiscReg(MISCREG_MC_MISC(i), 0); 19713511Sgabeblack@google.com } 19813511Sgabeblack@google.com 19913511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR0, 0); 20013511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR1, 0); 20113511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR2, 0); 20213511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR3, 0); 20313511Sgabeblack@google.com 20413511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); 20513511Sgabeblack@google.com tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); 20613511Sgabeblack@google.com 20713511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSC, 0); 20813511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSC_AUX, 0); 20913511Sgabeblack@google.com 21013511Sgabeblack@google.com for (int i = 0; i < 4; i++) { 21113511Sgabeblack@google.com tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0); 21213511Sgabeblack@google.com tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0); 21313511Sgabeblack@google.com } 21413511Sgabeblack@google.com 21513511Sgabeblack@google.com tc->setMiscReg(MISCREG_STAR, 0); 21613511Sgabeblack@google.com tc->setMiscReg(MISCREG_LSTAR, 0); 21713511Sgabeblack@google.com tc->setMiscReg(MISCREG_CSTAR, 0); 21813511Sgabeblack@google.com 21913511Sgabeblack@google.com tc->setMiscReg(MISCREG_SF_MASK, 0); 22013511Sgabeblack@google.com 22113511Sgabeblack@google.com tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0); 22213511Sgabeblack@google.com 22313511Sgabeblack@google.com tc->setMiscReg(MISCREG_SYSENTER_CS, 0); 22413511Sgabeblack@google.com tc->setMiscReg(MISCREG_SYSENTER_ESP, 0); 22513511Sgabeblack@google.com tc->setMiscReg(MISCREG_SYSENTER_EIP, 0); 22613511Sgabeblack@google.com 22713511Sgabeblack@google.com tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL); 22813511Sgabeblack@google.com 22913511Sgabeblack@google.com tc->setMiscReg(MISCREG_SYSCFG, 0x20601); 23013511Sgabeblack@google.com 23113511Sgabeblack@google.com tc->setMiscReg(MISCREG_IORR_BASE0, 0); 23213511Sgabeblack@google.com tc->setMiscReg(MISCREG_IORR_BASE1, 0); 23313511Sgabeblack@google.com 23413511Sgabeblack@google.com tc->setMiscReg(MISCREG_IORR_MASK0, 0); 23513511Sgabeblack@google.com tc->setMiscReg(MISCREG_IORR_MASK1, 0); 23613511Sgabeblack@google.com 23713511Sgabeblack@google.com tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000); 23813511Sgabeblack@google.com tc->setMiscReg(MISCREG_TOP_MEM2, 0x0); 23913511Sgabeblack@google.com 24013511Sgabeblack@google.com tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0); 24113511Sgabeblack@google.com tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0); 24213511Sgabeblack@google.com tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0); 24313511Sgabeblack@google.com tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0); 24413511Sgabeblack@google.com tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0); 24513511Sgabeblack@google.com 24613511Sgabeblack@google.com // Invalidate the caches (this should already be done for us) 24713511Sgabeblack@google.com 24813511Sgabeblack@google.com // TODO Turn on the APIC. This should be handled elsewhere but it isn't 24913511Sgabeblack@google.com // currently being handled at all. 25013511Sgabeblack@google.com 25113511Sgabeblack@google.com // TODO Set the SMRAM base address (SMBASE) to 0x00030000 25213511Sgabeblack@google.com 25313511Sgabeblack@google.com tc->setMiscReg(MISCREG_VM_CR, 0); 25413511Sgabeblack@google.com tc->setMiscReg(MISCREG_IGNNE, 0); 25513511Sgabeblack@google.com tc->setMiscReg(MISCREG_SMM_CTL, 0); 25613511Sgabeblack@google.com tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0); 25713511Sgabeblack@google.com} 25813511Sgabeblack@google.com 25913511Sgabeblack@google.com#endif 26013511Sgabeblack@google.com 26113511Sgabeblack@google.com#if FULL_SYSTEM 26213511Sgabeblack@google.comvoid startupCPU(ThreadContext *tc, int cpuId) 26313511Sgabeblack@google.com{ 26413511Sgabeblack@google.com if (cpuId == 0) { 26513511Sgabeblack@google.com // This is the boot strap processor (BSP). Initialize it to look like 26613511Sgabeblack@google.com // the boot loader has just turned control over to the 64 bit OS. We 26713511Sgabeblack@google.com // won't actually set up real mode or legacy protected mode descriptor 26813511Sgabeblack@google.com // tables because we aren't executing any code that would require 26913511Sgabeblack@google.com // them. We do, however toggle the control bits in the correct order 27013511Sgabeblack@google.com // while allowing consistency checks and the underlying mechansims 27113511Sgabeblack@google.com // just to be safe. 27213511Sgabeblack@google.com 27313511Sgabeblack@google.com const int NumPDTs = 4; 27413511Sgabeblack@google.com 27513511Sgabeblack@google.com const Addr PageMapLevel4 = 0x70000; 27613511Sgabeblack@google.com const Addr PageDirPtrTable = 0x71000; 27713511Sgabeblack@google.com const Addr PageDirTable[NumPDTs] = 27813511Sgabeblack@google.com {0x72000, 0x73000, 0x74000, 0x75000}; 27913511Sgabeblack@google.com const Addr GDTBase = 0x76000; 28013511Sgabeblack@google.com 28113511Sgabeblack@google.com const int PML4Bits = 9; 28213511Sgabeblack@google.com const int PDPTBits = 9; 28313511Sgabeblack@google.com const int PDTBits = 9; 28413511Sgabeblack@google.com 28513511Sgabeblack@google.com // Get a port to write the page tables and descriptor tables. 28613511Sgabeblack@google.com FunctionalPort * physPort = tc->getPhysPort(); 28713511Sgabeblack@google.com 28813511Sgabeblack@google.com /* 28913511Sgabeblack@google.com * Set up the gdt. 29013511Sgabeblack@google.com */ 29113511Sgabeblack@google.com // Place holder at selector 0 29213511Sgabeblack@google.com uint64_t nullDescriptor = 0; 29313511Sgabeblack@google.com physPort->writeBlob(GDTBase, (uint8_t *)(&nullDescriptor), 8); 29413511Sgabeblack@google.com 29513511Sgabeblack@google.com //64 bit code segment 29613511Sgabeblack@google.com SegDescriptor csDesc = 0; 29713511Sgabeblack@google.com csDesc.type.c = 0; // Not conforming 29813511Sgabeblack@google.com csDesc.dpl = 0; // Privelege level 0 29913511Sgabeblack@google.com csDesc.p = 1; // Present 30013511Sgabeblack@google.com csDesc.l = 1; // 64 bit 30113511Sgabeblack@google.com csDesc.d = 0; // default operand size 30213511Sgabeblack@google.com //Because we're dealing with a pointer and I don't think it's 30313511Sgabeblack@google.com //guaranteed that there isn't anything in a nonvirtual class between 30413511Sgabeblack@google.com //it's beginning in memory and it's actual data, we'll use an 30513511Sgabeblack@google.com //intermediary. 30613511Sgabeblack@google.com uint64_t csDescVal = csDesc; 30713511Sgabeblack@google.com physPort->writeBlob(GDTBase, (uint8_t *)(&csDescVal), 8); 30813511Sgabeblack@google.com 30913511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSG_BASE, GDTBase); 31013511Sgabeblack@google.com tc->setMiscReg(MISCREG_TSG_LIMIT, 0xF); 31113511Sgabeblack@google.com 31213511Sgabeblack@google.com /* 31313511Sgabeblack@google.com * Identity map the first 4GB of memory. In order to map this region 31413511Sgabeblack@google.com * of memory in long mode, there needs to be one actual page map level 31513511Sgabeblack@google.com * 4 entry which points to one page directory pointer table which 31613511Sgabeblack@google.com * points to 4 different page directory tables which are full of two 31713511Sgabeblack@google.com * megabyte pages. All of the other entries in valid tables are set 31813511Sgabeblack@google.com * to indicate that they don't pertain to anything valid and will 31913511Sgabeblack@google.com * cause a fault if used. 32013511Sgabeblack@google.com */ 32113511Sgabeblack@google.com 32213511Sgabeblack@google.com // Put valid values in all of the various table entries which indicate 32313511Sgabeblack@google.com // that those entries don't point to further tables or pages. Then 32413511Sgabeblack@google.com // set the values of those entries which are needed. 32513511Sgabeblack@google.com 32613511Sgabeblack@google.com // Page Map Level 4 32713511Sgabeblack@google.com 32813511Sgabeblack@google.com // read/write, user, not present 329 uint64_t pml4e = X86ISA::htog(0x6); 330 for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) { 331 physPort->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8); 332 } 333 // Point to the only PDPT 334 pml4e = X86ISA::htog(0x7 | PageDirPtrTable); 335 physPort->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8); 336 337 // Page Directory Pointer Table 338 339 // read/write, user, not present 340 uint64_t pdpe = X86ISA::htog(0x6); 341 for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) { 342 physPort->writeBlob(PageDirPtrTable + offset, 343 (uint8_t *)(&pdpe), 8); 344 } 345 // Point to the PDTs 346 for (int table = 0; table < NumPDTs; table++) { 347 pdpe = X86ISA::htog(0x7 | PageDirTable[table]); 348 physPort->writeBlob(PageDirPtrTable + table * 8, 349 (uint8_t *)(&pdpe), 8); 350 } 351 352 // Page Directory Tables 353 354 Addr base = 0; 355 const Addr pageSize = 2 << 20; 356 for (int table = 0; table < NumPDTs; table++) { 357 for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) { 358 // read/write, user, present, 4MB 359 uint64_t pdte = X86ISA::htog(0x87 | base); 360 physPort->writeBlob(PageDirTable[table] + offset, 361 (uint8_t *)(&pdte), 8); 362 base += pageSize; 363 } 364 } 365 366 /* 367 * Transition from real mode all the way up to Long mode 368 */ 369 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 370 //Turn off paging. 371 cr0.pg = 0; 372 tc->setMiscReg(MISCREG_CR0, cr0); 373 //Turn on protected mode. 374 cr0.pe = 1; 375 tc->setMiscReg(MISCREG_CR0, cr0); 376 377 CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); 378 //Turn on pae. 379 cr4.pae = 1; 380 tc->setMiscReg(MISCREG_CR4, cr4); 381 382 //Point to the page tables. 383 tc->setMiscReg(MISCREG_CR3, PageMapLevel4); 384 385 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER); 386 //Enable long mode. 387 efer.lme = 1; 388 tc->setMiscReg(MISCREG_EFER, efer); 389 390 //Activate long mode. 391 cr0.pg = 1; 392 tc->setMiscReg(MISCREG_CR0, cr0); 393 394 /* 395 * Far jump into 64 bit mode. 396 */ 397 // Set the selector 398 tc->setMiscReg(MISCREG_CS, 1); 399 // Manually set up the segment attributes. In the future when there's 400 // other existing functionality to do this, that could be used 401 // instead. 402 SegAttr csAttr = 0; 403 csAttr.writable = 0; 404 csAttr.readable = 1; 405 csAttr.expandDown = 0; 406 csAttr.dpl = 0; 407 csAttr.defaultSize = 0; 408 csAttr.longMode = 1; 409 tc->setMiscReg(MISCREG_CS_ATTR, csAttr); 410 411 tc->setPC(tc->getSystemPtr()->kernelEntry); 412 tc->setNextPC(tc->readPC()); 413 414 // We should now be in long mode. Yay! 415 416 tc->activate(0); 417 } else { 418 // This is an application processor (AP). It should be initialized to 419 // look like only the BIOS POST has run on it and put then put it into 420 // a halted state. 421 tc->suspend(); 422 } 423} 424 425#else 426 427void startupCPU(ThreadContext *tc, int cpuId) 428{ 429 tc->activate(0); 430} 431 432#endif 433 434} //namespace X86_ISA 435