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