system.cc revision 9762:4574c5123153
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2007 The Hewlett-Packard Development Company 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * The license below extends only to copyright in the software and shall 611308Santhony.gutierrez@amd.com * not be construed as granting a license to any other intellectual 711308Santhony.gutierrez@amd.com * property including but not limited to intellectual property relating 811308Santhony.gutierrez@amd.com * to a hardware implementation of the functionality of the software 911308Santhony.gutierrez@amd.com * licensed hereunder. You may use the software subject to the license 1011308Santhony.gutierrez@amd.com * terms below provided that you ensure that this notice is replicated 1111308Santhony.gutierrez@amd.com * unmodified and in its entirety in all distributions of the software, 1211308Santhony.gutierrez@amd.com * modified or unmodified, in source code or in binary form. 1311308Santhony.gutierrez@amd.com * 1411308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 1511308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 1611308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 1711308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 1811308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1911308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 2011308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 2111308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 2211308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 2311308Santhony.gutierrez@amd.com * this software without specific prior written permission. 2411308Santhony.gutierrez@amd.com * 2511308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2611308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2711308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2811308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2911308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3011308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3111308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3211308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3311308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3411308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3511308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3611308Santhony.gutierrez@amd.com * 3711308Santhony.gutierrez@amd.com * Authors: Gabe Black 3811308Santhony.gutierrez@amd.com */ 3911308Santhony.gutierrez@amd.com 4011308Santhony.gutierrez@amd.com#include "arch/x86/bios/intelmp.hh" 4111308Santhony.gutierrez@amd.com#include "arch/x86/bios/smbios.hh" 4211308Santhony.gutierrez@amd.com#include "arch/x86/regs/misc.hh" 4311308Santhony.gutierrez@amd.com#include "arch/x86/isa_traits.hh" 4411308Santhony.gutierrez@amd.com#include "arch/x86/system.hh" 4511308Santhony.gutierrez@amd.com#include "arch/vtophys.hh" 4611308Santhony.gutierrez@amd.com#include "base/loader/object_file.hh" 4711308Santhony.gutierrez@amd.com#include "base/loader/symtab.hh" 4811308Santhony.gutierrez@amd.com#include "base/intmath.hh" 4911308Santhony.gutierrez@amd.com#include "base/trace.hh" 5011308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh" 5111308Santhony.gutierrez@amd.com#include "mem/port_proxy.hh" 5211308Santhony.gutierrez@amd.com#include "params/X86System.hh" 5311308Santhony.gutierrez@amd.com#include "sim/byteswap.hh" 5411308Santhony.gutierrez@amd.com 5511308Santhony.gutierrez@amd.comusing namespace LittleEndianGuest; 5611308Santhony.gutierrez@amd.comusing namespace X86ISA; 5711308Santhony.gutierrez@amd.com 5811308Santhony.gutierrez@amd.comX86System::X86System(Params *p) : 5911308Santhony.gutierrez@amd.com System(p), smbiosTable(p->smbios_table), 6011308Santhony.gutierrez@amd.com mpFloatingPointer(p->intel_mp_pointer), 6111308Santhony.gutierrez@amd.com mpConfigTable(p->intel_mp_table), 6211308Santhony.gutierrez@amd.com rsdp(p->acpi_description_table_pointer) 6311308Santhony.gutierrez@amd.com{ 6411308Santhony.gutierrez@amd.com} 6511308Santhony.gutierrez@amd.com 6611308Santhony.gutierrez@amd.comstatic void 6711308Santhony.gutierrez@amd.cominstallSegDesc(ThreadContext *tc, SegmentRegIndex seg, 6811308Santhony.gutierrez@amd.com SegDescriptor desc, bool longmode) 6911308Santhony.gutierrez@amd.com{ 7011308Santhony.gutierrez@amd.com uint64_t base = desc.baseLow + (desc.baseHigh << 24); 7111308Santhony.gutierrez@amd.com bool honorBase = !longmode || seg == SEGMENT_REG_FS || 7211308Santhony.gutierrez@amd.com seg == SEGMENT_REG_GS || 7311308Santhony.gutierrez@amd.com seg == SEGMENT_REG_TSL || 7411308Santhony.gutierrez@amd.com seg == SYS_SEGMENT_REG_TR; 7511308Santhony.gutierrez@amd.com uint64_t limit = desc.limitLow | (desc.limitHigh << 16); 7611308Santhony.gutierrez@amd.com 7711308Santhony.gutierrez@amd.com SegAttr attr = 0; 7811308Santhony.gutierrez@amd.com 7911308Santhony.gutierrez@amd.com attr.dpl = desc.dpl; 8011308Santhony.gutierrez@amd.com attr.unusable = 0; 8111308Santhony.gutierrez@amd.com attr.defaultSize = desc.d; 8211308Santhony.gutierrez@amd.com attr.longMode = desc.l; 8311308Santhony.gutierrez@amd.com attr.avl = desc.avl; 8411308Santhony.gutierrez@amd.com attr.granularity = desc.g; 8511308Santhony.gutierrez@amd.com attr.present = desc.p; 8611308Santhony.gutierrez@amd.com attr.system = desc.s; 8711308Santhony.gutierrez@amd.com attr.type = desc.type; 8811308Santhony.gutierrez@amd.com if (desc.s) { 8911308Santhony.gutierrez@amd.com if (desc.type.codeOrData) { 9011308Santhony.gutierrez@amd.com // Code segment 9111308Santhony.gutierrez@amd.com attr.expandDown = 0; 9211308Santhony.gutierrez@amd.com attr.readable = desc.type.r; 9311308Santhony.gutierrez@amd.com attr.writable = 0; 9411308Santhony.gutierrez@amd.com } else { 9511308Santhony.gutierrez@amd.com // Data segment 9611308Santhony.gutierrez@amd.com attr.expandDown = desc.type.e; 9711308Santhony.gutierrez@amd.com attr.readable = 1; 9811308Santhony.gutierrez@amd.com attr.writable = desc.type.w; 9911308Santhony.gutierrez@amd.com } 10011308Santhony.gutierrez@amd.com } else { 10111308Santhony.gutierrez@amd.com attr.readable = 1; 10211308Santhony.gutierrez@amd.com attr.writable = 1; 10311308Santhony.gutierrez@amd.com attr.expandDown = 0; 10411308Santhony.gutierrez@amd.com } 10511308Santhony.gutierrez@amd.com 10611308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_SEG_BASE(seg), base); 10711308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0); 10811308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit); 10911308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr); 11011308Santhony.gutierrez@amd.com} 11111308Santhony.gutierrez@amd.com 11211308Santhony.gutierrez@amd.comvoid 11311308Santhony.gutierrez@amd.comX86System::initState() 11411308Santhony.gutierrez@amd.com{ 11511308Santhony.gutierrez@amd.com System::initState(); 11611308Santhony.gutierrez@amd.com 11711308Santhony.gutierrez@amd.com if (!kernel) 11811308Santhony.gutierrez@amd.com fatal("No kernel to load.\n"); 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.com if (kernel->getArch() == ObjectFile::I386) 12111308Santhony.gutierrez@amd.com fatal("Loading a 32 bit x86 kernel is not supported.\n"); 12211308Santhony.gutierrez@amd.com 12311308Santhony.gutierrez@amd.com ThreadContext *tc = threadContexts[0]; 12411308Santhony.gutierrez@amd.com // This is the boot strap processor (BSP). Initialize it to look like 12511308Santhony.gutierrez@amd.com // the boot loader has just turned control over to the 64 bit OS. We 12611308Santhony.gutierrez@amd.com // won't actually set up real mode or legacy protected mode descriptor 12711308Santhony.gutierrez@amd.com // tables because we aren't executing any code that would require 12811308Santhony.gutierrez@amd.com // them. We do, however toggle the control bits in the correct order 12911308Santhony.gutierrez@amd.com // while allowing consistency checks and the underlying mechansims 13011308Santhony.gutierrez@amd.com // just to be safe. 13111308Santhony.gutierrez@amd.com 13211308Santhony.gutierrez@amd.com const int NumPDTs = 4; 13311308Santhony.gutierrez@amd.com 13411308Santhony.gutierrez@amd.com const Addr PageMapLevel4 = 0x70000; 13511308Santhony.gutierrez@amd.com const Addr PageDirPtrTable = 0x71000; 13611308Santhony.gutierrez@amd.com const Addr PageDirTable[NumPDTs] = 13711308Santhony.gutierrez@amd.com {0x72000, 0x73000, 0x74000, 0x75000}; 13811308Santhony.gutierrez@amd.com const Addr GDTBase = 0x76000; 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.com const int PML4Bits = 9; 14111308Santhony.gutierrez@amd.com const int PDPTBits = 9; 14211308Santhony.gutierrez@amd.com const int PDTBits = 9; 14311308Santhony.gutierrez@amd.com 14411308Santhony.gutierrez@amd.com /* 14511308Santhony.gutierrez@amd.com * Set up the gdt. 14611308Santhony.gutierrez@amd.com */ 14711308Santhony.gutierrez@amd.com uint8_t numGDTEntries = 0; 14811308Santhony.gutierrez@amd.com // Place holder at selector 0 14911308Santhony.gutierrez@amd.com uint64_t nullDescriptor = 0; 15011308Santhony.gutierrez@amd.com physProxy.writeBlob(GDTBase + numGDTEntries * 8, 15111308Santhony.gutierrez@amd.com (uint8_t *)(&nullDescriptor), 8); 15211308Santhony.gutierrez@amd.com numGDTEntries++; 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com //64 bit code segment 15511308Santhony.gutierrez@amd.com SegDescriptor csDesc = 0; 15611308Santhony.gutierrez@amd.com csDesc.type.codeOrData = 1; 15711308Santhony.gutierrez@amd.com csDesc.type.c = 0; // Not conforming 15811308Santhony.gutierrez@amd.com csDesc.type.r = 1; // Readable 15911308Santhony.gutierrez@amd.com csDesc.dpl = 0; // Privelege level 0 16011308Santhony.gutierrez@amd.com csDesc.p = 1; // Present 16111308Santhony.gutierrez@amd.com csDesc.l = 1; // 64 bit 16211308Santhony.gutierrez@amd.com csDesc.d = 0; // default operand size 16311308Santhony.gutierrez@amd.com csDesc.g = 1; // Page granularity 16411308Santhony.gutierrez@amd.com csDesc.s = 1; // Not a system segment 16511308Santhony.gutierrez@amd.com csDesc.limitHigh = 0xF; 16611308Santhony.gutierrez@amd.com csDesc.limitLow = 0xFFFF; 16711308Santhony.gutierrez@amd.com //Because we're dealing with a pointer and I don't think it's 16811308Santhony.gutierrez@amd.com //guaranteed that there isn't anything in a nonvirtual class between 16911308Santhony.gutierrez@amd.com //it's beginning in memory and it's actual data, we'll use an 17011308Santhony.gutierrez@amd.com //intermediary. 17111308Santhony.gutierrez@amd.com uint64_t csDescVal = csDesc; 17211308Santhony.gutierrez@amd.com physProxy.writeBlob(GDTBase + numGDTEntries * 8, 17311308Santhony.gutierrez@amd.com (uint8_t *)(&csDescVal), 8); 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com numGDTEntries++; 17611308Santhony.gutierrez@amd.com 17711308Santhony.gutierrez@amd.com SegSelector cs = 0; 17811308Santhony.gutierrez@amd.com cs.si = numGDTEntries - 1; 17911308Santhony.gutierrez@amd.com 18011308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CS, (MiscReg)cs); 18111308Santhony.gutierrez@amd.com 18211308Santhony.gutierrez@amd.com //32 bit data segment 18311308Santhony.gutierrez@amd.com SegDescriptor dsDesc = 0; 18411308Santhony.gutierrez@amd.com dsDesc.type.codeOrData = 0; 18511308Santhony.gutierrez@amd.com dsDesc.type.e = 0; // Not expand down 18611308Santhony.gutierrez@amd.com dsDesc.type.w = 1; // Writable 18711308Santhony.gutierrez@amd.com dsDesc.dpl = 0; // Privelege level 0 18811308Santhony.gutierrez@amd.com dsDesc.p = 1; // Present 18911308Santhony.gutierrez@amd.com dsDesc.d = 1; // default operand size 19011308Santhony.gutierrez@amd.com dsDesc.g = 1; // Page granularity 19111308Santhony.gutierrez@amd.com dsDesc.s = 1; // Not a system segment 19211308Santhony.gutierrez@amd.com dsDesc.limitHigh = 0xF; 19311308Santhony.gutierrez@amd.com dsDesc.limitLow = 0xFFFF; 19411308Santhony.gutierrez@amd.com uint64_t dsDescVal = dsDesc; 19511308Santhony.gutierrez@amd.com physProxy.writeBlob(GDTBase + numGDTEntries * 8, 19611308Santhony.gutierrez@amd.com (uint8_t *)(&dsDescVal), 8); 19711308Santhony.gutierrez@amd.com 19811308Santhony.gutierrez@amd.com numGDTEntries++; 19911308Santhony.gutierrez@amd.com 20011308Santhony.gutierrez@amd.com SegSelector ds = 0; 20111308Santhony.gutierrez@amd.com ds.si = numGDTEntries - 1; 20211308Santhony.gutierrez@amd.com 20311308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_DS, (MiscReg)ds); 20411308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_ES, (MiscReg)ds); 20511308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_FS, (MiscReg)ds); 20611308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_GS, (MiscReg)ds); 20711308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_SS, (MiscReg)ds); 20811308Santhony.gutierrez@amd.com 20911308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_TSL, 0); 21011308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_TSG_BASE, GDTBase); 21111308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1); 21211308Santhony.gutierrez@amd.com 21311308Santhony.gutierrez@amd.com SegDescriptor tssDesc = 0; 21411308Santhony.gutierrez@amd.com tssDesc.type = 0xB; 21511308Santhony.gutierrez@amd.com tssDesc.dpl = 0; // Privelege level 0 21611308Santhony.gutierrez@amd.com tssDesc.p = 1; // Present 21711308Santhony.gutierrez@amd.com tssDesc.d = 1; // default operand size 21811308Santhony.gutierrez@amd.com tssDesc.g = 1; // Page granularity 21911308Santhony.gutierrez@amd.com tssDesc.s = 0; 22011308Santhony.gutierrez@amd.com tssDesc.limitHigh = 0xF; 22111308Santhony.gutierrez@amd.com tssDesc.limitLow = 0xFFFF; 22211308Santhony.gutierrez@amd.com uint64_t tssDescVal = tssDesc; 22311308Santhony.gutierrez@amd.com physProxy.writeBlob(GDTBase + numGDTEntries * 8, 22411308Santhony.gutierrez@amd.com (uint8_t *)(&tssDescVal), 8); 22511308Santhony.gutierrez@amd.com 22611308Santhony.gutierrez@amd.com numGDTEntries++; 22711308Santhony.gutierrez@amd.com 22811308Santhony.gutierrez@amd.com SegSelector tss = 0; 22911308Santhony.gutierrez@amd.com tss.si = numGDTEntries - 1; 23011308Santhony.gutierrez@amd.com 23111308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_TR, (MiscReg)tss); 23211308Santhony.gutierrez@amd.com installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true); 23311308Santhony.gutierrez@amd.com 23411308Santhony.gutierrez@amd.com /* 23511308Santhony.gutierrez@amd.com * Identity map the first 4GB of memory. In order to map this region 23611308Santhony.gutierrez@amd.com * of memory in long mode, there needs to be one actual page map level 23711308Santhony.gutierrez@amd.com * 4 entry which points to one page directory pointer table which 23811308Santhony.gutierrez@amd.com * points to 4 different page directory tables which are full of two 23911308Santhony.gutierrez@amd.com * megabyte pages. All of the other entries in valid tables are set 24011308Santhony.gutierrez@amd.com * to indicate that they don't pertain to anything valid and will 24111308Santhony.gutierrez@amd.com * cause a fault if used. 24211308Santhony.gutierrez@amd.com */ 24311308Santhony.gutierrez@amd.com 24411308Santhony.gutierrez@amd.com // Put valid values in all of the various table entries which indicate 24511308Santhony.gutierrez@amd.com // that those entries don't point to further tables or pages. Then 24611308Santhony.gutierrez@amd.com // set the values of those entries which are needed. 24711308Santhony.gutierrez@amd.com 24811308Santhony.gutierrez@amd.com // Page Map Level 4 24911308Santhony.gutierrez@amd.com 25011308Santhony.gutierrez@amd.com // read/write, user, not present 25111308Santhony.gutierrez@amd.com uint64_t pml4e = X86ISA::htog(0x6); 25211308Santhony.gutierrez@amd.com for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) { 25311308Santhony.gutierrez@amd.com physProxy.writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8); 25411308Santhony.gutierrez@amd.com } 25511308Santhony.gutierrez@amd.com // Point to the only PDPT 25611308Santhony.gutierrez@amd.com pml4e = X86ISA::htog(0x7 | PageDirPtrTable); 25711308Santhony.gutierrez@amd.com physProxy.writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8); 25811308Santhony.gutierrez@amd.com 25911308Santhony.gutierrez@amd.com // Page Directory Pointer Table 26011308Santhony.gutierrez@amd.com 26111308Santhony.gutierrez@amd.com // read/write, user, not present 26211308Santhony.gutierrez@amd.com uint64_t pdpe = X86ISA::htog(0x6); 26311308Santhony.gutierrez@amd.com for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) { 26411308Santhony.gutierrez@amd.com physProxy.writeBlob(PageDirPtrTable + offset, 26511308Santhony.gutierrez@amd.com (uint8_t *)(&pdpe), 8); 26611308Santhony.gutierrez@amd.com } 26711308Santhony.gutierrez@amd.com // Point to the PDTs 26811308Santhony.gutierrez@amd.com for (int table = 0; table < NumPDTs; table++) { 26911308Santhony.gutierrez@amd.com pdpe = X86ISA::htog(0x7 | PageDirTable[table]); 27011308Santhony.gutierrez@amd.com physProxy.writeBlob(PageDirPtrTable + table * 8, 27111308Santhony.gutierrez@amd.com (uint8_t *)(&pdpe), 8); 27211308Santhony.gutierrez@amd.com } 27311308Santhony.gutierrez@amd.com 27411308Santhony.gutierrez@amd.com // Page Directory Tables 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com Addr base = 0; 27711308Santhony.gutierrez@amd.com const Addr pageSize = 2 << 20; 27811308Santhony.gutierrez@amd.com for (int table = 0; table < NumPDTs; table++) { 27911308Santhony.gutierrez@amd.com for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) { 28011308Santhony.gutierrez@amd.com // read/write, user, present, 4MB 28111308Santhony.gutierrez@amd.com uint64_t pdte = X86ISA::htog(0x87 | base); 28211308Santhony.gutierrez@amd.com physProxy.writeBlob(PageDirTable[table] + offset, 28311308Santhony.gutierrez@amd.com (uint8_t *)(&pdte), 8); 28411308Santhony.gutierrez@amd.com base += pageSize; 28511308Santhony.gutierrez@amd.com } 28611308Santhony.gutierrez@amd.com } 28711308Santhony.gutierrez@amd.com 28811308Santhony.gutierrez@amd.com /* 28911308Santhony.gutierrez@amd.com * Transition from real mode all the way up to Long mode 29011308Santhony.gutierrez@amd.com */ 29111308Santhony.gutierrez@amd.com CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 29211308Santhony.gutierrez@amd.com //Turn off paging. 29311308Santhony.gutierrez@amd.com cr0.pg = 0; 29411308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CR0, cr0); 29511308Santhony.gutierrez@amd.com //Turn on protected mode. 29611308Santhony.gutierrez@amd.com cr0.pe = 1; 29711308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CR0, cr0); 29811308Santhony.gutierrez@amd.com 29911308Santhony.gutierrez@amd.com CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); 30011308Santhony.gutierrez@amd.com //Turn on pae. 30111308Santhony.gutierrez@amd.com cr4.pae = 1; 30211308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CR4, cr4); 30311308Santhony.gutierrez@amd.com 30411308Santhony.gutierrez@amd.com //Point to the page tables. 30511308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CR3, PageMapLevel4); 30611308Santhony.gutierrez@amd.com 30711308Santhony.gutierrez@amd.com Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER); 30811308Santhony.gutierrez@amd.com //Enable long mode. 30911308Santhony.gutierrez@amd.com efer.lme = 1; 31011308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_EFER, efer); 31111308Santhony.gutierrez@amd.com 31211308Santhony.gutierrez@amd.com //Start using longmode segments. 31311308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_CS, csDesc, true); 31411308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true); 31511308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true); 31611308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true); 31711308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true); 31811308Santhony.gutierrez@amd.com installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true); 31911308Santhony.gutierrez@amd.com 32011308Santhony.gutierrez@amd.com //Activate long mode. 32111308Santhony.gutierrez@amd.com cr0.pg = 1; 32211308Santhony.gutierrez@amd.com tc->setMiscReg(MISCREG_CR0, cr0); 32311308Santhony.gutierrez@amd.com 32411308Santhony.gutierrez@amd.com tc->pcState(tc->getSystemPtr()->kernelEntry); 32511308Santhony.gutierrez@amd.com 32611308Santhony.gutierrez@amd.com // We should now be in long mode. Yay! 32711308Santhony.gutierrez@amd.com 32811308Santhony.gutierrez@amd.com Addr ebdaPos = 0xF0000; 32911308Santhony.gutierrez@amd.com Addr fixed, table; 33011308Santhony.gutierrez@amd.com 33111308Santhony.gutierrez@amd.com //Write out the SMBios/DMI table 33211308Santhony.gutierrez@amd.com writeOutSMBiosTable(ebdaPos, fixed, table); 33311308Santhony.gutierrez@amd.com ebdaPos += (fixed + table); 33411308Santhony.gutierrez@amd.com ebdaPos = roundUp(ebdaPos, 16); 33511308Santhony.gutierrez@amd.com 33611308Santhony.gutierrez@amd.com //Write out the Intel MP Specification configuration table 33711308Santhony.gutierrez@amd.com writeOutMPTable(ebdaPos, fixed, table); 33811308Santhony.gutierrez@amd.com ebdaPos += (fixed + table); 33911308Santhony.gutierrez@amd.com} 34011308Santhony.gutierrez@amd.com 34111308Santhony.gutierrez@amd.comvoid 34211308Santhony.gutierrez@amd.comX86System::writeOutSMBiosTable(Addr header, 34311308Santhony.gutierrez@amd.com Addr &headerSize, Addr &structSize, Addr table) 34411308Santhony.gutierrez@amd.com{ 34511308Santhony.gutierrez@amd.com // If the table location isn't specified, just put it after the header. 34611308Santhony.gutierrez@amd.com // The header size as of the 2.5 SMBios specification is 0x1F bytes 34711308Santhony.gutierrez@amd.com if (!table) 34811308Santhony.gutierrez@amd.com table = header + 0x1F; 34911308Santhony.gutierrez@amd.com smbiosTable->setTableAddr(table); 35011308Santhony.gutierrez@amd.com 35111308Santhony.gutierrez@amd.com smbiosTable->writeOut(physProxy, header, headerSize, structSize); 35211308Santhony.gutierrez@amd.com 35311308Santhony.gutierrez@amd.com // Do some bounds checking to make sure we at least didn't step on 35411308Santhony.gutierrez@amd.com // ourselves. 35511308Santhony.gutierrez@amd.com assert(header > table || header + headerSize <= table); 35611308Santhony.gutierrez@amd.com assert(table > header || table + structSize <= header); 35711308Santhony.gutierrez@amd.com} 35811308Santhony.gutierrez@amd.com 35911308Santhony.gutierrez@amd.comvoid 36011308Santhony.gutierrez@amd.comX86System::writeOutMPTable(Addr fp, 36111308Santhony.gutierrez@amd.com Addr &fpSize, Addr &tableSize, Addr table) 36211308Santhony.gutierrez@amd.com{ 36311308Santhony.gutierrez@amd.com // If the table location isn't specified and it exists, just put 36411308Santhony.gutierrez@amd.com // it after the floating pointer. The fp size as of the 1.4 Intel MP 36511308Santhony.gutierrez@amd.com // specification is 0x10 bytes. 36611308Santhony.gutierrez@amd.com if (mpConfigTable) { 36711308Santhony.gutierrez@amd.com if (!table) 36811308Santhony.gutierrez@amd.com table = fp + 0x10; 36911308Santhony.gutierrez@amd.com mpFloatingPointer->setTableAddr(table); 37011308Santhony.gutierrez@amd.com } 37111308Santhony.gutierrez@amd.com 37211308Santhony.gutierrez@amd.com fpSize = mpFloatingPointer->writeOut(physProxy, fp); 37311308Santhony.gutierrez@amd.com if (mpConfigTable) 37411308Santhony.gutierrez@amd.com tableSize = mpConfigTable->writeOut(physProxy, table); 37511308Santhony.gutierrez@amd.com else 37611308Santhony.gutierrez@amd.com tableSize = 0; 37711308Santhony.gutierrez@amd.com 37811308Santhony.gutierrez@amd.com // Do some bounds checking to make sure we at least didn't step on 37911308Santhony.gutierrez@amd.com // ourselves and the fp structure was the size we thought it was. 38011308Santhony.gutierrez@amd.com assert(fp > table || fp + fpSize <= table); 38111308Santhony.gutierrez@amd.com assert(table > fp || table + tableSize <= fp); 38211308Santhony.gutierrez@amd.com assert(fpSize == 0x10); 38311308Santhony.gutierrez@amd.com} 38411308Santhony.gutierrez@amd.com 38511308Santhony.gutierrez@amd.com 38611308Santhony.gutierrez@amd.comX86System::~X86System() 38711308Santhony.gutierrez@amd.com{ 38811308Santhony.gutierrez@amd.com delete smbiosTable; 38911308Santhony.gutierrez@amd.com} 39011308Santhony.gutierrez@amd.com 39111308Santhony.gutierrez@amd.comX86System * 39211308Santhony.gutierrez@amd.comX86SystemParams::create() 39311308Santhony.gutierrez@amd.com{ 39411308Santhony.gutierrez@amd.com return new X86System(this); 39511308Santhony.gutierrez@amd.com} 39611308Santhony.gutierrez@amd.com