system.cc revision 5615
15132Sgblack@eecs.umich.edu/*
25132Sgblack@eecs.umich.edu * Copyright (c) 2007 The Hewlett-Packard Development Company
35132Sgblack@eecs.umich.edu * All rights reserved.
45132Sgblack@eecs.umich.edu *
55132Sgblack@eecs.umich.edu * Redistribution and use of this software in source and binary forms,
65132Sgblack@eecs.umich.edu * with or without modification, are permitted provided that the
75132Sgblack@eecs.umich.edu * following conditions are met:
85132Sgblack@eecs.umich.edu *
95132Sgblack@eecs.umich.edu * The software must be used only for Non-Commercial Use which means any
105132Sgblack@eecs.umich.edu * use which is NOT directed to receiving any direct monetary
115132Sgblack@eecs.umich.edu * compensation for, or commercial advantage from such use.  Illustrative
125132Sgblack@eecs.umich.edu * examples of non-commercial use are academic research, personal study,
135132Sgblack@eecs.umich.edu * teaching, education and corporate research & development.
145132Sgblack@eecs.umich.edu * Illustrative examples of commercial use are distributing products for
155132Sgblack@eecs.umich.edu * commercial advantage and providing services using the software for
165132Sgblack@eecs.umich.edu * commercial advantage.
175132Sgblack@eecs.umich.edu *
185132Sgblack@eecs.umich.edu * If you wish to use this software or functionality therein that may be
195132Sgblack@eecs.umich.edu * covered by patents for commercial use, please contact:
205132Sgblack@eecs.umich.edu *     Director of Intellectual Property Licensing
215132Sgblack@eecs.umich.edu *     Office of Strategy and Technology
225132Sgblack@eecs.umich.edu *     Hewlett-Packard Company
235132Sgblack@eecs.umich.edu *     1501 Page Mill Road
245132Sgblack@eecs.umich.edu *     Palo Alto, California  94304
255132Sgblack@eecs.umich.edu *
265132Sgblack@eecs.umich.edu * Redistributions of source code must retain the above copyright notice,
275132Sgblack@eecs.umich.edu * this list of conditions and the following disclaimer.  Redistributions
285132Sgblack@eecs.umich.edu * in binary form must reproduce the above copyright notice, this list of
295132Sgblack@eecs.umich.edu * conditions and the following disclaimer in the documentation and/or
305132Sgblack@eecs.umich.edu * other materials provided with the distribution.  Neither the name of
315132Sgblack@eecs.umich.edu * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
325132Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
335132Sgblack@eecs.umich.edu * this software without specific prior written permission.  No right of
345132Sgblack@eecs.umich.edu * sublicense is granted herewith.  Derivatives of the software and
355132Sgblack@eecs.umich.edu * output created using the software may be prepared, but only for
365132Sgblack@eecs.umich.edu * Non-Commercial Uses.  Derivatives of the software may be shared with
375132Sgblack@eecs.umich.edu * others provided: (i) the others agree to abide by the list of
385132Sgblack@eecs.umich.edu * conditions herein which includes the Non-Commercial Use restrictions;
395132Sgblack@eecs.umich.edu * and (ii) such Derivatives of the software include the above copyright
405132Sgblack@eecs.umich.edu * notice to acknowledge the contribution from this software where
415132Sgblack@eecs.umich.edu * applicable, this list of conditions and the disclaimer below.
425132Sgblack@eecs.umich.edu *
435132Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
445132Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
455132Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
465132Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
475132Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
485132Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
495132Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
505132Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
515132Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
525132Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
535132Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
545132Sgblack@eecs.umich.edu *
555132Sgblack@eecs.umich.edu * Authors: Gabe Black
565132Sgblack@eecs.umich.edu */
575132Sgblack@eecs.umich.edu
585612Sgblack@eecs.umich.edu#include "arch/x86/bios/smbios.hh"
595299Sgblack@eecs.umich.edu#include "arch/x86/miscregs.hh"
605132Sgblack@eecs.umich.edu#include "arch/x86/system.hh"
615132Sgblack@eecs.umich.edu#include "arch/vtophys.hh"
625132Sgblack@eecs.umich.edu#include "base/remote_gdb.hh"
635132Sgblack@eecs.umich.edu#include "base/loader/object_file.hh"
645132Sgblack@eecs.umich.edu#include "base/loader/symtab.hh"
655132Sgblack@eecs.umich.edu#include "base/trace.hh"
665299Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
675132Sgblack@eecs.umich.edu#include "mem/physical.hh"
685132Sgblack@eecs.umich.edu#include "params/X86System.hh"
695132Sgblack@eecs.umich.edu#include "sim/byteswap.hh"
705132Sgblack@eecs.umich.edu
715132Sgblack@eecs.umich.edu
725299Sgblack@eecs.umich.eduusing namespace LittleEndianGuest;
735299Sgblack@eecs.umich.eduusing namespace X86ISA;
745132Sgblack@eecs.umich.edu
755132Sgblack@eecs.umich.eduX86System::X86System(Params *p)
765615Sgblack@eecs.umich.edu    : System(p), smbiosTable(p->smbios_table)
775615Sgblack@eecs.umich.edu{}
785132Sgblack@eecs.umich.edu
795299Sgblack@eecs.umich.eduvoid
805299Sgblack@eecs.umich.eduX86System::startup()
815299Sgblack@eecs.umich.edu{
825299Sgblack@eecs.umich.edu    System::startup();
835299Sgblack@eecs.umich.edu    // This is the boot strap processor (BSP). Initialize it to look like
845299Sgblack@eecs.umich.edu    // the boot loader has just turned control over to the 64 bit OS. We
855299Sgblack@eecs.umich.edu    // won't actually set up real mode or legacy protected mode descriptor
865299Sgblack@eecs.umich.edu    // tables because we aren't executing any code that would require
875299Sgblack@eecs.umich.edu    // them. We do, however toggle the control bits in the correct order
885299Sgblack@eecs.umich.edu    // while allowing consistency checks and the underlying mechansims
895299Sgblack@eecs.umich.edu    // just to be safe.
905299Sgblack@eecs.umich.edu
915299Sgblack@eecs.umich.edu    const int NumPDTs = 4;
925299Sgblack@eecs.umich.edu
935299Sgblack@eecs.umich.edu    const Addr PageMapLevel4 = 0x70000;
945299Sgblack@eecs.umich.edu    const Addr PageDirPtrTable = 0x71000;
955299Sgblack@eecs.umich.edu    const Addr PageDirTable[NumPDTs] =
965299Sgblack@eecs.umich.edu        {0x72000, 0x73000, 0x74000, 0x75000};
975299Sgblack@eecs.umich.edu    const Addr GDTBase = 0x76000;
985299Sgblack@eecs.umich.edu
995299Sgblack@eecs.umich.edu    const int PML4Bits = 9;
1005299Sgblack@eecs.umich.edu    const int PDPTBits = 9;
1015299Sgblack@eecs.umich.edu    const int PDTBits = 9;
1025299Sgblack@eecs.umich.edu
1035299Sgblack@eecs.umich.edu    // Get a port to write the page tables and descriptor tables.
1045299Sgblack@eecs.umich.edu    FunctionalPort * physPort = threadContexts[0]->getPhysPort();
1055299Sgblack@eecs.umich.edu
1065299Sgblack@eecs.umich.edu    /*
1075299Sgblack@eecs.umich.edu     * Set up the gdt.
1085299Sgblack@eecs.umich.edu     */
1095299Sgblack@eecs.umich.edu    // Place holder at selector 0
1105299Sgblack@eecs.umich.edu    uint64_t nullDescriptor = 0;
1115299Sgblack@eecs.umich.edu    physPort->writeBlob(GDTBase, (uint8_t *)(&nullDescriptor), 8);
1125299Sgblack@eecs.umich.edu
1135299Sgblack@eecs.umich.edu    //64 bit code segment
1145299Sgblack@eecs.umich.edu    SegDescriptor csDesc = 0;
1155299Sgblack@eecs.umich.edu    csDesc.type.c = 0; // Not conforming
1165299Sgblack@eecs.umich.edu    csDesc.dpl = 0; // Privelege level 0
1175299Sgblack@eecs.umich.edu    csDesc.p = 1; // Present
1185299Sgblack@eecs.umich.edu    csDesc.l = 1; // 64 bit
1195299Sgblack@eecs.umich.edu    csDesc.d = 0; // default operand size
1205299Sgblack@eecs.umich.edu    //Because we're dealing with a pointer and I don't think it's
1215299Sgblack@eecs.umich.edu    //guaranteed that there isn't anything in a nonvirtual class between
1225299Sgblack@eecs.umich.edu    //it's beginning in memory and it's actual data, we'll use an
1235299Sgblack@eecs.umich.edu    //intermediary.
1245299Sgblack@eecs.umich.edu    uint64_t csDescVal = csDesc;
1255299Sgblack@eecs.umich.edu    physPort->writeBlob(GDTBase, (uint8_t *)(&csDescVal), 8);
1265299Sgblack@eecs.umich.edu
1275299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_TSG_BASE, GDTBase);
1285299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_TSG_LIMIT, 0xF);
1295299Sgblack@eecs.umich.edu
1305299Sgblack@eecs.umich.edu    /*
1315299Sgblack@eecs.umich.edu     * Identity map the first 4GB of memory. In order to map this region
1325299Sgblack@eecs.umich.edu     * of memory in long mode, there needs to be one actual page map level
1335299Sgblack@eecs.umich.edu     * 4 entry which points to one page directory pointer table which
1345299Sgblack@eecs.umich.edu     * points to 4 different page directory tables which are full of two
1355299Sgblack@eecs.umich.edu     * megabyte pages. All of the other entries in valid tables are set
1365299Sgblack@eecs.umich.edu     * to indicate that they don't pertain to anything valid and will
1375299Sgblack@eecs.umich.edu     * cause a fault if used.
1385299Sgblack@eecs.umich.edu     */
1395299Sgblack@eecs.umich.edu
1405299Sgblack@eecs.umich.edu    // Put valid values in all of the various table entries which indicate
1415299Sgblack@eecs.umich.edu    // that those entries don't point to further tables or pages. Then
1425299Sgblack@eecs.umich.edu    // set the values of those entries which are needed.
1435299Sgblack@eecs.umich.edu
1445299Sgblack@eecs.umich.edu    // Page Map Level 4
1455299Sgblack@eecs.umich.edu
1465299Sgblack@eecs.umich.edu    // read/write, user, not present
1475299Sgblack@eecs.umich.edu    uint64_t pml4e = X86ISA::htog(0x6);
1485299Sgblack@eecs.umich.edu    for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
1495299Sgblack@eecs.umich.edu        physPort->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8);
1505299Sgblack@eecs.umich.edu    }
1515299Sgblack@eecs.umich.edu    // Point to the only PDPT
1525299Sgblack@eecs.umich.edu    pml4e = X86ISA::htog(0x7 | PageDirPtrTable);
1535299Sgblack@eecs.umich.edu    physPort->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8);
1545299Sgblack@eecs.umich.edu
1555299Sgblack@eecs.umich.edu    // Page Directory Pointer Table
1565299Sgblack@eecs.umich.edu
1575299Sgblack@eecs.umich.edu    // read/write, user, not present
1585299Sgblack@eecs.umich.edu    uint64_t pdpe = X86ISA::htog(0x6);
1595299Sgblack@eecs.umich.edu    for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) {
1605299Sgblack@eecs.umich.edu        physPort->writeBlob(PageDirPtrTable + offset,
1615299Sgblack@eecs.umich.edu                (uint8_t *)(&pdpe), 8);
1625299Sgblack@eecs.umich.edu    }
1635299Sgblack@eecs.umich.edu    // Point to the PDTs
1645299Sgblack@eecs.umich.edu    for (int table = 0; table < NumPDTs; table++) {
1655299Sgblack@eecs.umich.edu        pdpe = X86ISA::htog(0x7 | PageDirTable[table]);
1665299Sgblack@eecs.umich.edu        physPort->writeBlob(PageDirPtrTable + table * 8,
1675299Sgblack@eecs.umich.edu                (uint8_t *)(&pdpe), 8);
1685299Sgblack@eecs.umich.edu    }
1695299Sgblack@eecs.umich.edu
1705299Sgblack@eecs.umich.edu    // Page Directory Tables
1715299Sgblack@eecs.umich.edu
1725299Sgblack@eecs.umich.edu    Addr base = 0;
1735299Sgblack@eecs.umich.edu    const Addr pageSize = 2 << 20;
1745299Sgblack@eecs.umich.edu    for (int table = 0; table < NumPDTs; table++) {
1755299Sgblack@eecs.umich.edu        for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
1765299Sgblack@eecs.umich.edu            // read/write, user, present, 4MB
1775299Sgblack@eecs.umich.edu            uint64_t pdte = X86ISA::htog(0x87 | base);
1785299Sgblack@eecs.umich.edu            physPort->writeBlob(PageDirTable[table] + offset,
1795299Sgblack@eecs.umich.edu                    (uint8_t *)(&pdte), 8);
1805299Sgblack@eecs.umich.edu            base += pageSize;
1815299Sgblack@eecs.umich.edu        }
1825299Sgblack@eecs.umich.edu    }
1835299Sgblack@eecs.umich.edu
1845299Sgblack@eecs.umich.edu    /*
1855299Sgblack@eecs.umich.edu     * Transition from real mode all the way up to Long mode
1865299Sgblack@eecs.umich.edu     */
1875299Sgblack@eecs.umich.edu    CR0 cr0 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR0);
1885299Sgblack@eecs.umich.edu    //Turn off paging.
1895299Sgblack@eecs.umich.edu    cr0.pg = 0;
1905299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
1915299Sgblack@eecs.umich.edu    //Turn on protected mode.
1925299Sgblack@eecs.umich.edu    cr0.pe = 1;
1935299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
1945299Sgblack@eecs.umich.edu
1955299Sgblack@eecs.umich.edu    CR4 cr4 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR4);
1965299Sgblack@eecs.umich.edu    //Turn on pae.
1975299Sgblack@eecs.umich.edu    cr4.pae = 1;
1985299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CR4, cr4);
1995299Sgblack@eecs.umich.edu
2005299Sgblack@eecs.umich.edu    //Point to the page tables.
2015299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CR3, PageMapLevel4);
2025299Sgblack@eecs.umich.edu
2035299Sgblack@eecs.umich.edu    Efer efer = threadContexts[0]->readMiscRegNoEffect(MISCREG_EFER);
2045299Sgblack@eecs.umich.edu    //Enable long mode.
2055299Sgblack@eecs.umich.edu    efer.lme = 1;
2065299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_EFER, efer);
2075299Sgblack@eecs.umich.edu
2085299Sgblack@eecs.umich.edu    //Activate long mode.
2095299Sgblack@eecs.umich.edu    cr0.pg = 1;
2105299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
2115299Sgblack@eecs.umich.edu
2125299Sgblack@eecs.umich.edu    /*
2135299Sgblack@eecs.umich.edu     * Far jump into 64 bit mode.
2145299Sgblack@eecs.umich.edu     */
2155299Sgblack@eecs.umich.edu    // Set the selector
2165299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CS, 1);
2175299Sgblack@eecs.umich.edu    // Manually set up the segment attributes. In the future when there's
2185299Sgblack@eecs.umich.edu    // other existing functionality to do this, that could be used
2195299Sgblack@eecs.umich.edu    // instead.
2205299Sgblack@eecs.umich.edu    SegAttr csAttr = 0;
2215299Sgblack@eecs.umich.edu    csAttr.writable = 0;
2225299Sgblack@eecs.umich.edu    csAttr.readable = 1;
2235299Sgblack@eecs.umich.edu    csAttr.expandDown = 0;
2245299Sgblack@eecs.umich.edu    csAttr.dpl = 0;
2255299Sgblack@eecs.umich.edu    csAttr.defaultSize = 0;
2265299Sgblack@eecs.umich.edu    csAttr.longMode = 1;
2275299Sgblack@eecs.umich.edu    threadContexts[0]->setMiscReg(MISCREG_CS_ATTR, csAttr);
2285299Sgblack@eecs.umich.edu
2295299Sgblack@eecs.umich.edu    threadContexts[0]->setPC(threadContexts[0]->getSystemPtr()->kernelEntry);
2305299Sgblack@eecs.umich.edu    threadContexts[0]->setNextPC(threadContexts[0]->readPC());
2315299Sgblack@eecs.umich.edu
2325299Sgblack@eecs.umich.edu    // We should now be in long mode. Yay!
2335334Sgblack@eecs.umich.edu
2345615Sgblack@eecs.umich.edu    Addr ebdaPos = 0xF0000;
2355615Sgblack@eecs.umich.edu
2365615Sgblack@eecs.umich.edu    Addr headerSize, structSize;
2375334Sgblack@eecs.umich.edu    //Write out the SMBios/DMI table
2385615Sgblack@eecs.umich.edu    writeOutSMBiosTable(ebdaPos, headerSize, structSize);
2395615Sgblack@eecs.umich.edu    ebdaPos += (headerSize + structSize);
2405299Sgblack@eecs.umich.edu}
2415299Sgblack@eecs.umich.edu
2425334Sgblack@eecs.umich.eduvoid
2435615Sgblack@eecs.umich.eduX86System::writeOutSMBiosTable(Addr header,
2445615Sgblack@eecs.umich.edu        Addr &headerSize, Addr &structSize, Addr table)
2455334Sgblack@eecs.umich.edu{
2465334Sgblack@eecs.umich.edu    // Get a port to write the table and header to memory.
2475334Sgblack@eecs.umich.edu    FunctionalPort * physPort = threadContexts[0]->getPhysPort();
2485334Sgblack@eecs.umich.edu
2495334Sgblack@eecs.umich.edu    // If the table location isn't specified, just put it after the header.
2505334Sgblack@eecs.umich.edu    // The header size as of the 2.5 SMBios specification is 0x1F bytes
2515615Sgblack@eecs.umich.edu    if (!table)
2525615Sgblack@eecs.umich.edu        table = header + 0x1F;
2535615Sgblack@eecs.umich.edu    smbiosTable->setTableAddr(table);
2545334Sgblack@eecs.umich.edu
2555615Sgblack@eecs.umich.edu    smbiosTable->writeOut(physPort, header, headerSize, structSize);
2565615Sgblack@eecs.umich.edu
2575615Sgblack@eecs.umich.edu    // Do some bounds checking to make sure we at least didn't step on
2585615Sgblack@eecs.umich.edu    // ourselves.
2595615Sgblack@eecs.umich.edu    assert(header > table || header + headerSize <= table);
2605615Sgblack@eecs.umich.edu    assert(table > header || table + structSize <= header);
2615334Sgblack@eecs.umich.edu}
2625334Sgblack@eecs.umich.edu
2635334Sgblack@eecs.umich.edu
2645132Sgblack@eecs.umich.eduX86System::~X86System()
2655132Sgblack@eecs.umich.edu{
2665334Sgblack@eecs.umich.edu    delete smbiosTable;
2675132Sgblack@eecs.umich.edu}
2685132Sgblack@eecs.umich.edu
2695132Sgblack@eecs.umich.eduvoid
2705132Sgblack@eecs.umich.eduX86System::serialize(std::ostream &os)
2715132Sgblack@eecs.umich.edu{
2725132Sgblack@eecs.umich.edu    System::serialize(os);
2735132Sgblack@eecs.umich.edu}
2745132Sgblack@eecs.umich.edu
2755132Sgblack@eecs.umich.edu
2765132Sgblack@eecs.umich.eduvoid
2775132Sgblack@eecs.umich.eduX86System::unserialize(Checkpoint *cp, const std::string &section)
2785132Sgblack@eecs.umich.edu{
2795132Sgblack@eecs.umich.edu    System::unserialize(cp,section);
2805132Sgblack@eecs.umich.edu}
2815132Sgblack@eecs.umich.edu
2825132Sgblack@eecs.umich.eduX86System *
2835132Sgblack@eecs.umich.eduX86SystemParams::create()
2845132Sgblack@eecs.umich.edu{
2855132Sgblack@eecs.umich.edu    return new X86System(this);
2865132Sgblack@eecs.umich.edu}
287