system.cc revision 7087
110515SAli.Saidi@ARM.com/*
210515SAli.Saidi@ARM.com * Copyright (c) 2007 The Hewlett-Packard Development Company
311201Sandreas.hansson@arm.com * All rights reserved.
411201Sandreas.hansson@arm.com *
511201Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
610515SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
711201Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
811201Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
911201Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1011201Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1111201Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1211201Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1311201Sandreas.hansson@arm.com *
1410515SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
1510515SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
1611201Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
1711201Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
1811201Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1911201Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
2011201Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
2111201Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
2211201Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
2311201Sandreas.hansson@arm.com * this software without specific prior written permission.
2411201Sandreas.hansson@arm.com *
2510585Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2611201Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2711201Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2811201Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2911201Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3011201Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3111201Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3211201Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3311201Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410585Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3511201Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3611201Sandreas.hansson@arm.com *
3711201Sandreas.hansson@arm.com * Authors: Gabe Black
3811201Sandreas.hansson@arm.com */
3911201Sandreas.hansson@arm.com
4011201Sandreas.hansson@arm.com#include "arch/x86/bios/smbios.hh"
4111201Sandreas.hansson@arm.com#include "arch/x86/bios/intelmp.hh"
4211201Sandreas.hansson@arm.com#include "arch/x86/miscregs.hh"
4311201Sandreas.hansson@arm.com#include "arch/x86/system.hh"
4411201Sandreas.hansson@arm.com#include "arch/vtophys.hh"
4511138Sandreas.hansson@arm.com#include "base/intmath.hh"
4611201Sandreas.hansson@arm.com#include "base/loader/object_file.hh"
4711201Sandreas.hansson@arm.com#include "base/loader/symtab.hh"
4811201Sandreas.hansson@arm.com#include "base/remote_gdb.hh"
4911201Sandreas.hansson@arm.com#include "base/trace.hh"
5011201Sandreas.hansson@arm.com#include "cpu/thread_context.hh"
5111201Sandreas.hansson@arm.com#include "mem/physical.hh"
5211201Sandreas.hansson@arm.com#include "params/X86System.hh"
5311201Sandreas.hansson@arm.com#include "sim/byteswap.hh"
5411201Sandreas.hansson@arm.com
5511201Sandreas.hansson@arm.com
5611201Sandreas.hansson@arm.comusing namespace LittleEndianGuest;
5711201Sandreas.hansson@arm.comusing namespace X86ISA;
5811201Sandreas.hansson@arm.com
5911201Sandreas.hansson@arm.comX86System::X86System(Params *p) :
6011201Sandreas.hansson@arm.com    System(p), smbiosTable(p->smbios_table),
6111201Sandreas.hansson@arm.com    mpFloatingPointer(p->intel_mp_pointer),
6211201Sandreas.hansson@arm.com    mpConfigTable(p->intel_mp_table),
6311201Sandreas.hansson@arm.com    rsdp(p->acpi_description_table_pointer)
6411167Sjthestness@gmail.com{}
6511201Sandreas.hansson@arm.com
6611201Sandreas.hansson@arm.comstatic void
6711201Sandreas.hansson@arm.cominstallSegDesc(ThreadContext *tc, SegmentRegIndex seg,
6811201Sandreas.hansson@arm.com        SegDescriptor desc, bool longmode)
6911201Sandreas.hansson@arm.com{
7011201Sandreas.hansson@arm.com    uint64_t base = desc.baseLow + (desc.baseHigh << 24);
7111201Sandreas.hansson@arm.com    bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
7211201Sandreas.hansson@arm.com                                  seg == SEGMENT_REG_GS ||
7311201Sandreas.hansson@arm.com                                  seg == SEGMENT_REG_TSL ||
7411201Sandreas.hansson@arm.com                                  seg == SYS_SEGMENT_REG_TR;
7511201Sandreas.hansson@arm.com    uint64_t limit = desc.limitLow | (desc.limitHigh << 16);
7611201Sandreas.hansson@arm.com
7711201Sandreas.hansson@arm.com    SegAttr attr = 0;
7811201Sandreas.hansson@arm.com
7911201Sandreas.hansson@arm.com    attr.dpl = desc.dpl;
8011201Sandreas.hansson@arm.com    attr.unusable = 0;
8111201Sandreas.hansson@arm.com    attr.defaultSize = desc.d;
8211201Sandreas.hansson@arm.com    attr.longMode = desc.l;
8311201Sandreas.hansson@arm.com    attr.avl = desc.avl;
8411201Sandreas.hansson@arm.com    attr.granularity = desc.g;
8511201Sandreas.hansson@arm.com    attr.present = desc.p;
8611201Sandreas.hansson@arm.com    attr.system = desc.s;
8711201Sandreas.hansson@arm.com    attr.type = desc.type;
8811201Sandreas.hansson@arm.com    if (desc.s) {
8911201Sandreas.hansson@arm.com        if (desc.type.codeOrData) {
9011201Sandreas.hansson@arm.com            // Code segment
9111201Sandreas.hansson@arm.com            attr.expandDown = 0;
9211201Sandreas.hansson@arm.com            attr.readable = desc.type.r;
9311201Sandreas.hansson@arm.com            attr.writable = 0;
9411201Sandreas.hansson@arm.com        } else {
9511201Sandreas.hansson@arm.com            // Data segment
9611201Sandreas.hansson@arm.com            attr.expandDown = desc.type.e;
9711201Sandreas.hansson@arm.com            attr.readable = 1;
9810515SAli.Saidi@ARM.com            attr.writable = desc.type.w;
9911201Sandreas.hansson@arm.com        }
10011201Sandreas.hansson@arm.com    } else {
10110515SAli.Saidi@ARM.com        attr.readable = 1;
10210515SAli.Saidi@ARM.com        attr.writable = 1;
10310515SAli.Saidi@ARM.com        attr.expandDown = 0;
10410515SAli.Saidi@ARM.com    }
10510515SAli.Saidi@ARM.com
10610515SAli.Saidi@ARM.com    tc->setMiscReg(MISCREG_SEG_BASE(seg), base);
10711201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0);
10810515SAli.Saidi@ARM.com    tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit);
10910515SAli.Saidi@ARM.com    tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr);
11010515SAli.Saidi@ARM.com}
11110515SAli.Saidi@ARM.com
11210515SAli.Saidi@ARM.comvoid
11310515SAli.Saidi@ARM.comX86System::startup()
11411201Sandreas.hansson@arm.com{
11511201Sandreas.hansson@arm.com    System::startup();
11611201Sandreas.hansson@arm.com    ThreadContext *tc = threadContexts[0];
11711201Sandreas.hansson@arm.com    // This is the boot strap processor (BSP). Initialize it to look like
11811201Sandreas.hansson@arm.com    // the boot loader has just turned control over to the 64 bit OS. We
11911201Sandreas.hansson@arm.com    // won't actually set up real mode or legacy protected mode descriptor
12011201Sandreas.hansson@arm.com    // tables because we aren't executing any code that would require
12111201Sandreas.hansson@arm.com    // them. We do, however toggle the control bits in the correct order
12211201Sandreas.hansson@arm.com    // while allowing consistency checks and the underlying mechansims
12311201Sandreas.hansson@arm.com    // just to be safe.
12411201Sandreas.hansson@arm.com
12511201Sandreas.hansson@arm.com    const int NumPDTs = 4;
12611201Sandreas.hansson@arm.com
12711201Sandreas.hansson@arm.com    const Addr PageMapLevel4 = 0x70000;
12811201Sandreas.hansson@arm.com    const Addr PageDirPtrTable = 0x71000;
12911201Sandreas.hansson@arm.com    const Addr PageDirTable[NumPDTs] =
13011201Sandreas.hansson@arm.com        {0x72000, 0x73000, 0x74000, 0x75000};
13111201Sandreas.hansson@arm.com    const Addr GDTBase = 0x76000;
13211201Sandreas.hansson@arm.com
13311201Sandreas.hansson@arm.com    const int PML4Bits = 9;
13411201Sandreas.hansson@arm.com    const int PDPTBits = 9;
13511201Sandreas.hansson@arm.com    const int PDTBits = 9;
13611138Sandreas.hansson@arm.com
13711201Sandreas.hansson@arm.com    // Get a port to write the page tables and descriptor tables.
13811201Sandreas.hansson@arm.com    FunctionalPort * physPort = tc->getPhysPort();
13910515SAli.Saidi@ARM.com
14010515SAli.Saidi@ARM.com    /*
14110515SAli.Saidi@ARM.com     * Set up the gdt.
14210515SAli.Saidi@ARM.com     */
14310515SAli.Saidi@ARM.com    uint8_t numGDTEntries = 0;
14410515SAli.Saidi@ARM.com    // Place holder at selector 0
14510515SAli.Saidi@ARM.com    uint64_t nullDescriptor = 0;
14610515SAli.Saidi@ARM.com    physPort->writeBlob(GDTBase + numGDTEntries * 8,
14710515SAli.Saidi@ARM.com            (uint8_t *)(&nullDescriptor), 8);
14810515SAli.Saidi@ARM.com    numGDTEntries++;
14910515SAli.Saidi@ARM.com
15010515SAli.Saidi@ARM.com    //64 bit code segment
15110515SAli.Saidi@ARM.com    SegDescriptor csDesc = 0;
15210515SAli.Saidi@ARM.com    csDesc.type.codeOrData = 1;
15310515SAli.Saidi@ARM.com    csDesc.type.c = 0; // Not conforming
15410515SAli.Saidi@ARM.com    csDesc.type.r = 1; // Readable
15510515SAli.Saidi@ARM.com    csDesc.dpl = 0; // Privelege level 0
15610515SAli.Saidi@ARM.com    csDesc.p = 1; // Present
15710515SAli.Saidi@ARM.com    csDesc.l = 1; // 64 bit
15810515SAli.Saidi@ARM.com    csDesc.d = 0; // default operand size
15910515SAli.Saidi@ARM.com    csDesc.g = 1; // Page granularity
16010515SAli.Saidi@ARM.com    csDesc.s = 1; // Not a system segment
16110515SAli.Saidi@ARM.com    csDesc.limitHigh = 0xF;
16211201Sandreas.hansson@arm.com    csDesc.limitLow = 0xFF;
16311201Sandreas.hansson@arm.com    //Because we're dealing with a pointer and I don't think it's
16411201Sandreas.hansson@arm.com    //guaranteed that there isn't anything in a nonvirtual class between
16511201Sandreas.hansson@arm.com    //it's beginning in memory and it's actual data, we'll use an
16611201Sandreas.hansson@arm.com    //intermediary.
16711201Sandreas.hansson@arm.com    uint64_t csDescVal = csDesc;
16811201Sandreas.hansson@arm.com    physPort->writeBlob(GDTBase + numGDTEntries * 8,
16911201Sandreas.hansson@arm.com            (uint8_t *)(&csDescVal), 8);
17011201Sandreas.hansson@arm.com
17111201Sandreas.hansson@arm.com    numGDTEntries++;
17211201Sandreas.hansson@arm.com
17311201Sandreas.hansson@arm.com    SegSelector cs = 0;
17411201Sandreas.hansson@arm.com    cs.si = numGDTEntries - 1;
17511201Sandreas.hansson@arm.com
17611201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CS, (MiscReg)cs);
17711201Sandreas.hansson@arm.com
17811201Sandreas.hansson@arm.com    //32 bit data segment
17911201Sandreas.hansson@arm.com    SegDescriptor dsDesc = 0;
18011201Sandreas.hansson@arm.com    dsDesc.type.codeOrData = 0;
18111201Sandreas.hansson@arm.com    dsDesc.type.e = 0; // Not expand down
18211201Sandreas.hansson@arm.com    dsDesc.type.w = 1; // Writable
18311201Sandreas.hansson@arm.com    dsDesc.dpl = 0; // Privelege level 0
18411201Sandreas.hansson@arm.com    dsDesc.p = 1; // Present
18511201Sandreas.hansson@arm.com    dsDesc.d = 1; // default operand size
18611201Sandreas.hansson@arm.com    dsDesc.g = 1; // Page granularity
18711201Sandreas.hansson@arm.com    dsDesc.s = 1; // Not a system segment
18811201Sandreas.hansson@arm.com    dsDesc.limitHigh = 0xF;
18911201Sandreas.hansson@arm.com    dsDesc.limitLow = 0xFF;
19011201Sandreas.hansson@arm.com    uint64_t dsDescVal = dsDesc;
19111201Sandreas.hansson@arm.com    physPort->writeBlob(GDTBase + numGDTEntries * 8,
19211201Sandreas.hansson@arm.com            (uint8_t *)(&dsDescVal), 8);
19311201Sandreas.hansson@arm.com
19411201Sandreas.hansson@arm.com    numGDTEntries++;
19511201Sandreas.hansson@arm.com
19611201Sandreas.hansson@arm.com    SegSelector ds = 0;
19711201Sandreas.hansson@arm.com    ds.si = numGDTEntries - 1;
19811201Sandreas.hansson@arm.com
19911201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_DS, (MiscReg)ds);
20011201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_ES, (MiscReg)ds);
20111201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_FS, (MiscReg)ds);
20211201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_GS, (MiscReg)ds);
20311201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_SS, (MiscReg)ds);
20411201Sandreas.hansson@arm.com
20511201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_TSL, 0);
20611201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_TSG_BASE, GDTBase);
20711201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);
20811201Sandreas.hansson@arm.com
20911201Sandreas.hansson@arm.com    SegDescriptor tssDesc = 0;
21011201Sandreas.hansson@arm.com    tssDesc.type = 0xB;
21111201Sandreas.hansson@arm.com    tssDesc.dpl = 0; // Privelege level 0
21211201Sandreas.hansson@arm.com    tssDesc.p = 1; // Present
21311201Sandreas.hansson@arm.com    tssDesc.d = 1; // default operand size
21411201Sandreas.hansson@arm.com    tssDesc.g = 1; // Page granularity
21511201Sandreas.hansson@arm.com    tssDesc.s = 1; // Not a system segment
21611201Sandreas.hansson@arm.com    tssDesc.limitHigh = 0xF;
21711201Sandreas.hansson@arm.com    tssDesc.limitLow = 0xFF;
21811201Sandreas.hansson@arm.com    uint64_t tssDescVal = tssDesc;
21911201Sandreas.hansson@arm.com    physPort->writeBlob(GDTBase + numGDTEntries * 8,
22011201Sandreas.hansson@arm.com            (uint8_t *)(&tssDescVal), 8);
22111201Sandreas.hansson@arm.com
22211201Sandreas.hansson@arm.com    numGDTEntries++;
22311201Sandreas.hansson@arm.com
22411201Sandreas.hansson@arm.com    SegSelector tss = 0;
22511201Sandreas.hansson@arm.com    tss.si = numGDTEntries - 1;
22611201Sandreas.hansson@arm.com
22711201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_TR, (MiscReg)tss);
22811201Sandreas.hansson@arm.com    installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true);
22910892Sandreas.hansson@arm.com
23010892Sandreas.hansson@arm.com    /*
23110892Sandreas.hansson@arm.com     * Identity map the first 4GB of memory. In order to map this region
23211201Sandreas.hansson@arm.com     * of memory in long mode, there needs to be one actual page map level
23311201Sandreas.hansson@arm.com     * 4 entry which points to one page directory pointer table which
23411201Sandreas.hansson@arm.com     * points to 4 different page directory tables which are full of two
23511201Sandreas.hansson@arm.com     * megabyte pages. All of the other entries in valid tables are set
23611201Sandreas.hansson@arm.com     * to indicate that they don't pertain to anything valid and will
23711201Sandreas.hansson@arm.com     * cause a fault if used.
23811201Sandreas.hansson@arm.com     */
23911201Sandreas.hansson@arm.com
24011201Sandreas.hansson@arm.com    // Put valid values in all of the various table entries which indicate
24111201Sandreas.hansson@arm.com    // that those entries don't point to further tables or pages. Then
24211201Sandreas.hansson@arm.com    // set the values of those entries which are needed.
24311201Sandreas.hansson@arm.com
24411201Sandreas.hansson@arm.com    // Page Map Level 4
24511201Sandreas.hansson@arm.com
24611201Sandreas.hansson@arm.com    // read/write, user, not present
24711201Sandreas.hansson@arm.com    uint64_t pml4e = X86ISA::htog(0x6);
24811201Sandreas.hansson@arm.com    for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
24911201Sandreas.hansson@arm.com        physPort->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8);
25011201Sandreas.hansson@arm.com    }
25111201Sandreas.hansson@arm.com    // Point to the only PDPT
25211201Sandreas.hansson@arm.com    pml4e = X86ISA::htog(0x7 | PageDirPtrTable);
25311201Sandreas.hansson@arm.com    physPort->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8);
25411201Sandreas.hansson@arm.com
25511201Sandreas.hansson@arm.com    // Page Directory Pointer Table
25611201Sandreas.hansson@arm.com
25711201Sandreas.hansson@arm.com    // read/write, user, not present
25811201Sandreas.hansson@arm.com    uint64_t pdpe = X86ISA::htog(0x6);
25911167Sjthestness@gmail.com    for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) {
26011167Sjthestness@gmail.com        physPort->writeBlob(PageDirPtrTable + offset,
26111201Sandreas.hansson@arm.com                (uint8_t *)(&pdpe), 8);
26211201Sandreas.hansson@arm.com    }
26311201Sandreas.hansson@arm.com    // Point to the PDTs
26411201Sandreas.hansson@arm.com    for (int table = 0; table < NumPDTs; table++) {
26511201Sandreas.hansson@arm.com        pdpe = X86ISA::htog(0x7 | PageDirTable[table]);
26611201Sandreas.hansson@arm.com        physPort->writeBlob(PageDirPtrTable + table * 8,
26711201Sandreas.hansson@arm.com                (uint8_t *)(&pdpe), 8);
26811201Sandreas.hansson@arm.com    }
26911201Sandreas.hansson@arm.com
27011201Sandreas.hansson@arm.com    // Page Directory Tables
27111201Sandreas.hansson@arm.com
27211201Sandreas.hansson@arm.com    Addr base = 0;
27311201Sandreas.hansson@arm.com    const Addr pageSize = 2 << 20;
27410515SAli.Saidi@ARM.com    for (int table = 0; table < NumPDTs; table++) {
27511201Sandreas.hansson@arm.com        for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
27611167Sjthestness@gmail.com            // read/write, user, present, 4MB
27711167Sjthestness@gmail.com            uint64_t pdte = X86ISA::htog(0x87 | base);
27811167Sjthestness@gmail.com            physPort->writeBlob(PageDirTable[table] + offset,
27911167Sjthestness@gmail.com                    (uint8_t *)(&pdte), 8);
28010515SAli.Saidi@ARM.com            base += pageSize;
28111138Sandreas.hansson@arm.com        }
28211138Sandreas.hansson@arm.com    }
28311138Sandreas.hansson@arm.com
28411201Sandreas.hansson@arm.com    /*
28511201Sandreas.hansson@arm.com     * Transition from real mode all the way up to Long mode
28611201Sandreas.hansson@arm.com     */
28711201Sandreas.hansson@arm.com    CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
28811167Sjthestness@gmail.com    //Turn off paging.
28911201Sandreas.hansson@arm.com    cr0.pg = 0;
29011201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CR0, cr0);
29111201Sandreas.hansson@arm.com    //Turn on protected mode.
29211201Sandreas.hansson@arm.com    cr0.pe = 1;
29311201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CR0, cr0);
29411201Sandreas.hansson@arm.com
29511201Sandreas.hansson@arm.com    CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
29611201Sandreas.hansson@arm.com    //Turn on pae.
29711201Sandreas.hansson@arm.com    cr4.pae = 1;
29811201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CR4, cr4);
29911201Sandreas.hansson@arm.com
30011201Sandreas.hansson@arm.com    //Point to the page tables.
30111201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
30211201Sandreas.hansson@arm.com
30310628Sandreas.hansson@arm.com    Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
30411201Sandreas.hansson@arm.com    //Enable long mode.
30510628Sandreas.hansson@arm.com    efer.lme = 1;
30611201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_EFER, efer);
30711201Sandreas.hansson@arm.com
30811201Sandreas.hansson@arm.com    //Start using longmode segments.
30911201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
31011201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true);
31111201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true);
31211201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true);
31311201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
31411201Sandreas.hansson@arm.com    installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);
31511201Sandreas.hansson@arm.com
31611201Sandreas.hansson@arm.com    //Activate long mode.
31710628Sandreas.hansson@arm.com    cr0.pg = 1;
31811201Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_CR0, cr0);
31910628Sandreas.hansson@arm.com
32011201Sandreas.hansson@arm.com    tc->setPC(tc->getSystemPtr()->kernelEntry);
32110585Sandreas.hansson@arm.com    tc->setNextPC(tc->readPC());
32211201Sandreas.hansson@arm.com
32311201Sandreas.hansson@arm.com    // We should now be in long mode. Yay!
32411201Sandreas.hansson@arm.com
32511201Sandreas.hansson@arm.com    Addr ebdaPos = 0xF0000;
32610585Sandreas.hansson@arm.com    Addr fixed, table;
32711201Sandreas.hansson@arm.com
32811201Sandreas.hansson@arm.com    //Write out the SMBios/DMI table
32910585Sandreas.hansson@arm.com    writeOutSMBiosTable(ebdaPos, fixed, table);
33011167Sjthestness@gmail.com    ebdaPos += (fixed + table);
33111201Sandreas.hansson@arm.com    ebdaPos = roundUp(ebdaPos, 16);
33211201Sandreas.hansson@arm.com
33311201Sandreas.hansson@arm.com    //Write out the Intel MP Specification configuration table
33410585Sandreas.hansson@arm.com    writeOutMPTable(ebdaPos, fixed, table);
33511167Sjthestness@gmail.com    ebdaPos += (fixed + table);
33610585Sandreas.hansson@arm.com}
33710585Sandreas.hansson@arm.com
33810585Sandreas.hansson@arm.comvoid
33910585Sandreas.hansson@arm.comX86System::writeOutSMBiosTable(Addr header,
34010585Sandreas.hansson@arm.com        Addr &headerSize, Addr &structSize, Addr table)
34110585Sandreas.hansson@arm.com{
34211201Sandreas.hansson@arm.com    // Get a port to write the table and header to memory.
34311201Sandreas.hansson@arm.com    FunctionalPort * physPort = threadContexts[0]->getPhysPort();
34411201Sandreas.hansson@arm.com
34511201Sandreas.hansson@arm.com    // If the table location isn't specified, just put it after the header.
34611201Sandreas.hansson@arm.com    // The header size as of the 2.5 SMBios specification is 0x1F bytes
34710585Sandreas.hansson@arm.com    if (!table)
34811201Sandreas.hansson@arm.com        table = header + 0x1F;
34911201Sandreas.hansson@arm.com    smbiosTable->setTableAddr(table);
35011201Sandreas.hansson@arm.com
35110585Sandreas.hansson@arm.com    smbiosTable->writeOut(physPort, header, headerSize, structSize);
35210628Sandreas.hansson@arm.com
35310628Sandreas.hansson@arm.com    // Do some bounds checking to make sure we at least didn't step on
35410628Sandreas.hansson@arm.com    // ourselves.
35510628Sandreas.hansson@arm.com    assert(header > table || header + headerSize <= table);
35610628Sandreas.hansson@arm.com    assert(table > header || table + structSize <= header);
35710628Sandreas.hansson@arm.com}
35810628Sandreas.hansson@arm.com
35910628Sandreas.hansson@arm.comvoid
36010585Sandreas.hansson@arm.comX86System::writeOutMPTable(Addr fp,
36110585Sandreas.hansson@arm.com        Addr &fpSize, Addr &tableSize, Addr table)
36210585Sandreas.hansson@arm.com{
36310585Sandreas.hansson@arm.com    // Get a port to write the table and header to memory.
36410585Sandreas.hansson@arm.com    FunctionalPort * physPort = threadContexts[0]->getPhysPort();
36510585Sandreas.hansson@arm.com
36610585Sandreas.hansson@arm.com    // If the table location isn't specified and it exists, just put
36710585Sandreas.hansson@arm.com    // it after the floating pointer. The fp size as of the 1.4 Intel MP
36810585Sandreas.hansson@arm.com    // specification is 0x10 bytes.
36910585Sandreas.hansson@arm.com    if (mpConfigTable) {
37010585Sandreas.hansson@arm.com        if (!table)
37110585Sandreas.hansson@arm.com            table = fp + 0x10;
37210585Sandreas.hansson@arm.com        mpFloatingPointer->setTableAddr(table);
37310585Sandreas.hansson@arm.com    }
37410585Sandreas.hansson@arm.com
37510585Sandreas.hansson@arm.com    fpSize = mpFloatingPointer->writeOut(physPort, fp);
37610585Sandreas.hansson@arm.com    if (mpConfigTable)
37710585Sandreas.hansson@arm.com        tableSize = mpConfigTable->writeOut(physPort, table);
37810585Sandreas.hansson@arm.com    else
37910585Sandreas.hansson@arm.com        tableSize = 0;
38010585Sandreas.hansson@arm.com
38111201Sandreas.hansson@arm.com    // Do some bounds checking to make sure we at least didn't step on
38211201Sandreas.hansson@arm.com    // ourselves and the fp structure was the size we thought it was.
38311201Sandreas.hansson@arm.com    assert(fp > table || fp + fpSize <= table);
38411201Sandreas.hansson@arm.com    assert(table > fp || table + tableSize <= fp);
38511201Sandreas.hansson@arm.com    assert(fpSize == 0x10);
38611201Sandreas.hansson@arm.com}
38711201Sandreas.hansson@arm.com
38811201Sandreas.hansson@arm.com
38911201Sandreas.hansson@arm.comX86System::~X86System()
39011201Sandreas.hansson@arm.com{
39111201Sandreas.hansson@arm.com    delete smbiosTable;
39211201Sandreas.hansson@arm.com}
39311201Sandreas.hansson@arm.com
39411201Sandreas.hansson@arm.comvoid
39511201Sandreas.hansson@arm.comX86System::serialize(std::ostream &os)
39611201Sandreas.hansson@arm.com{
39711201Sandreas.hansson@arm.com    System::serialize(os);
39811201Sandreas.hansson@arm.com}
39911201Sandreas.hansson@arm.com
40011201Sandreas.hansson@arm.com
40111201Sandreas.hansson@arm.comvoid
40211201Sandreas.hansson@arm.comX86System::unserialize(Checkpoint *cp, const std::string &section)
40311201Sandreas.hansson@arm.com{
40411201Sandreas.hansson@arm.com    System::unserialize(cp,section);
40511201Sandreas.hansson@arm.com}
40611201Sandreas.hansson@arm.com
40711201Sandreas.hansson@arm.comX86System *
40811201Sandreas.hansson@arm.comX86SystemParams::create()
40911201Sandreas.hansson@arm.com{
41011201Sandreas.hansson@arm.com    return new X86System(this);
41111201Sandreas.hansson@arm.com}
41211201Sandreas.hansson@arm.com