process.cc revision 11800:54436a1784dc
18012Ssaidi@eecs.umich.edu/* 28013Sbinkertn@umich.edu * Copyright (c) 2014 Advanced Micro Devices, Inc. 38013Sbinkertn@umich.edu * Copyright (c) 2007 The Hewlett-Packard Development Company 48013Sbinkertn@umich.edu * All rights reserved. 58013Sbinkertn@umich.edu * 68013Sbinkertn@umich.edu * The license below extends only to copyright in the software and shall 78013Sbinkertn@umich.edu * not be construed as granting a license to any other intellectual 88013Sbinkertn@umich.edu * property including but not limited to intellectual property relating 98013Sbinkertn@umich.edu * to a hardware implementation of the functionality of the software 108013Sbinkertn@umich.edu * licensed hereunder. You may use the software subject to the license 118013Sbinkertn@umich.edu * terms below provided that you ensure that this notice is replicated 128013Sbinkertn@umich.edu * unmodified and in its entirety in all distributions of the software, 138013Sbinkertn@umich.edu * modified or unmodified, in source code or in binary form. 148013Sbinkertn@umich.edu * 158013Sbinkertn@umich.edu * Copyright (c) 2003-2006 The Regents of The University of Michigan 168013Sbinkertn@umich.edu * All rights reserved. 178013Sbinkertn@umich.edu * 188013Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 198013Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 208013Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 218013Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 228013Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 238013Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 248013Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 258013Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 268013Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 278013Sbinkertn@umich.edu * this software without specific prior written permission. 288013Sbinkertn@umich.edu * 298013Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307977Shsul@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 318013Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 328013Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 338013Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 348013Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 358013Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 368013Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 378013Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 388013Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 398013Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 408013Sbinkertn@umich.edu * 418013Sbinkertn@umich.edu * Authors: Gabe Black 428013Sbinkertn@umich.edu * Ali Saidi 438013Sbinkertn@umich.edu */ 448013Sbinkertn@umich.edu 458013Sbinkertn@umich.edu#include "arch/x86/process.hh" 468013Sbinkertn@umich.edu 478013Sbinkertn@umich.edu#include "arch/x86/isa_traits.hh" 488013Sbinkertn@umich.edu#include "arch/x86/regs/misc.hh" 498013Sbinkertn@umich.edu#include "arch/x86/regs/segment.hh" 508013Sbinkertn@umich.edu#include "arch/x86/system.hh" 518013Sbinkertn@umich.edu#include "arch/x86/types.hh" 528013Sbinkertn@umich.edu#include "base/loader/elf_object.hh" 538013Sbinkertn@umich.edu#include "base/loader/object_file.hh" 547977Shsul@eecs.umich.edu#include "base/misc.hh" 557977Shsul@eecs.umich.edu#include "base/trace.hh" 568013Sbinkertn@umich.edu#include "cpu/thread_context.hh" 577977Shsul@eecs.umich.edu#include "debug/Stack.hh" 587977Shsul@eecs.umich.edu#include "mem/multi_level_page_table.hh" 598013Sbinkertn@umich.edu#include "mem/page_table.hh" 608013Sbinkertn@umich.edu#include "sim/process_impl.hh" 617978Sbinkertn@umich.edu#include "sim/syscall_desc.hh" 627978Sbinkertn@umich.edu#include "sim/syscall_return.hh" 637978Sbinkertn@umich.edu#include "sim/system.hh" 648013Sbinkertn@umich.edu 657977Shsul@eecs.umich.eduusing namespace std; 667977Shsul@eecs.umich.eduusing namespace X86ISA; 677977Shsul@eecs.umich.edu 687977Shsul@eecs.umich.edustatic const int ArgumentReg[] = { 697977Shsul@eecs.umich.edu INTREG_RDI, 708013Sbinkertn@umich.edu INTREG_RSI, 718013Sbinkertn@umich.edu INTREG_RDX, 728018Smserrano@umich.edu //This argument register is r10 for syscalls and rcx for C. 738018Smserrano@umich.edu INTREG_R10W, 747977Shsul@eecs.umich.edu //INTREG_RCX, 757977Shsul@eecs.umich.edu INTREG_R8W, 768013Sbinkertn@umich.edu INTREG_R9W 777977Shsul@eecs.umich.edu}; 788013Sbinkertn@umich.edu 798013Sbinkertn@umich.edustatic const int NumArgumentRegs M5_VAR_USED = 808013Sbinkertn@umich.edu sizeof(ArgumentReg) / sizeof(const int); 817977Shsul@eecs.umich.edu 828013Sbinkertn@umich.edustatic const int ArgumentReg32[] = { 838013Sbinkertn@umich.edu INTREG_EBX, 848013Sbinkertn@umich.edu INTREG_ECX, 858013Sbinkertn@umich.edu INTREG_EDX, 868013Sbinkertn@umich.edu INTREG_ESI, 877977Shsul@eecs.umich.edu INTREG_EDI, 887977Shsul@eecs.umich.edu INTREG_EBP 898013Sbinkertn@umich.edu}; 907977Shsul@eecs.umich.edu 918010Ssaidi@eecs.umich.edustatic const int NumArgumentRegs32 M5_VAR_USED = 927977Shsul@eecs.umich.edu sizeof(ArgumentReg) / sizeof(const int); 937977Shsul@eecs.umich.edu 947977Shsul@eecs.umich.eduX86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile, 957977Shsul@eecs.umich.edu SyscallDesc *_syscallDescs, int _numSyscallDescs) : 968013Sbinkertn@umich.edu LiveProcess(params, objFile), syscallDescs(_syscallDescs), 978013Sbinkertn@umich.edu numSyscallDescs(_numSyscallDescs) 988013Sbinkertn@umich.edu{ 998013Sbinkertn@umich.edu brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); 1008013Sbinkertn@umich.edu brk_point = roundUp(brk_point, PageBytes); 1018009Ssaidi@eecs.umich.edu} 1028009Ssaidi@eecs.umich.edu 1037977Shsul@eecs.umich.eduX86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params, 1048016Sbinkertn@umich.edu ObjectFile *objFile, SyscallDesc *_syscallDescs, 1058013Sbinkertn@umich.edu int _numSyscallDescs) : 1068013Sbinkertn@umich.edu X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) 1078013Sbinkertn@umich.edu{ 1087977Shsul@eecs.umich.edu 1097977Shsul@eecs.umich.edu vsyscallPage.base = 0xffffffffff600000ULL; 1108015Sbinkertn@umich.edu vsyscallPage.size = PageBytes; 1118013Sbinkertn@umich.edu vsyscallPage.vtimeOffset = 0x400; 1127977Shsul@eecs.umich.edu vsyscallPage.vgettimeofdayOffset = 0x0; 1138013Sbinkertn@umich.edu 1147977Shsul@eecs.umich.edu // Set up stack. On X86_64 Linux, stack goes from the top of memory 1158013Sbinkertn@umich.edu // downward, less the hole for the kernel address space plus one page 1167977Shsul@eecs.umich.edu // for undertermined purposes. 1177977Shsul@eecs.umich.edu stack_base = (Addr)0x7FFFFFFFF000ULL; 1187977Shsul@eecs.umich.edu 1198013Sbinkertn@umich.edu // Set pointer for next thread stack. Reserve 8M for main stack. 1208013Sbinkertn@umich.edu next_thread_stack_base = stack_base - (8 * 1024 * 1024); 1218013Sbinkertn@umich.edu 1228013Sbinkertn@umich.edu // "mmap_base" is a function which defines where mmap region starts in 1238013Sbinkertn@umich.edu // the process address space. 1248013Sbinkertn@umich.edu // mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd()) 1257977Shsul@eecs.umich.edu // TASK_SIZE: (1<<47)-PAGE_SIZE 1267977Shsul@eecs.umich.edu // MIN_GAP: 128*1024*1024+stack_maxrandom_size() 1277977Shsul@eecs.umich.edu // We do not use any address space layout randomization in gem5 1287977Shsul@eecs.umich.edu // therefore the random fields become zero; the smallest gap space was 1297977Shsul@eecs.umich.edu // chosen but gap could potentially be much larger. 1307977Shsul@eecs.umich.edu mmap_end = (Addr)0x7FFFF7FFF000ULL; 1317977Shsul@eecs.umich.edu} 1327977Shsul@eecs.umich.edu 1338013Sbinkertn@umich.eduvoid 1347977Shsul@eecs.umich.eduI386LiveProcess::syscall(int64_t callnum, ThreadContext *tc) 1357977Shsul@eecs.umich.edu{ 1368013Sbinkertn@umich.edu TheISA::PCState pc = tc->pcState(); 1378013Sbinkertn@umich.edu Addr eip = pc.pc(); 1387977Shsul@eecs.umich.edu if (eip >= vsyscallPage.base && 1397977Shsul@eecs.umich.edu eip < vsyscallPage.base + vsyscallPage.size) { 1407977Shsul@eecs.umich.edu pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset); 1418013Sbinkertn@umich.edu tc->pcState(pc); 1428013Sbinkertn@umich.edu } 1437978Sbinkertn@umich.edu X86LiveProcess::syscall(callnum, tc); 1448015Sbinkertn@umich.edu} 1457978Sbinkertn@umich.edu 1467978Sbinkertn@umich.edu 1478013Sbinkertn@umich.eduI386LiveProcess::I386LiveProcess(LiveProcessParams *params, 1488013Sbinkertn@umich.edu ObjectFile *objFile, SyscallDesc *_syscallDescs, 1497977Shsul@eecs.umich.edu int _numSyscallDescs) : 1508015Sbinkertn@umich.edu X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) 1517977Shsul@eecs.umich.edu{ 1527977Shsul@eecs.umich.edu _gdtStart = ULL(0xffffd000); 1537978Sbinkertn@umich.edu _gdtSize = PageBytes; 1547978Sbinkertn@umich.edu 1558013Sbinkertn@umich.edu vsyscallPage.base = 0xffffe000ULL; 1568013Sbinkertn@umich.edu vsyscallPage.size = PageBytes; 1578013Sbinkertn@umich.edu vsyscallPage.vsyscallOffset = 0x400; 1587977Shsul@eecs.umich.edu vsyscallPage.vsysexitOffset = 0x410; 1597978Sbinkertn@umich.edu 1607977Shsul@eecs.umich.edu stack_base = _gdtStart; 1617977Shsul@eecs.umich.edu 1628013Sbinkertn@umich.edu // Set pointer for next thread stack. Reserve 8M for main stack. 1638013Sbinkertn@umich.edu next_thread_stack_base = stack_base - (8 * 1024 * 1024); 1647977Shsul@eecs.umich.edu 1658013Sbinkertn@umich.edu // "mmap_base" is a function which defines where mmap region starts in 1668015Sbinkertn@umich.edu // the process address space. 1677977Shsul@eecs.umich.edu // mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd()) 1688013Sbinkertn@umich.edu // TASK_SIZE: 0xC0000000 1698013Sbinkertn@umich.edu // MIN_GAP: 128*1024*1024+stack_maxrandom_size() 1708013Sbinkertn@umich.edu // We do not use any address space layout randomization in gem5 1718015Sbinkertn@umich.edu // therefore the random fields become zero; the smallest gap space was 1728013Sbinkertn@umich.edu // chosen but gap could potentially be much larger. 1738001Ssaidi@eecs.umich.edu mmap_end = (Addr)0xB7FFF000ULL; 1748015Sbinkertn@umich.edu} 1758015Sbinkertn@umich.edu 1768015Sbinkertn@umich.eduSyscallDesc* 1778015Sbinkertn@umich.eduX86LiveProcess::getDesc(int callnum) 1788015Sbinkertn@umich.edu{ 1798015Sbinkertn@umich.edu if (callnum < 0 || callnum >= numSyscallDescs) 1808015Sbinkertn@umich.edu return NULL; 1818015Sbinkertn@umich.edu return &syscallDescs[callnum]; 1828015Sbinkertn@umich.edu} 1838015Sbinkertn@umich.edu 1848015Sbinkertn@umich.eduvoid 1858015Sbinkertn@umich.eduX86_64LiveProcess::initState() 1868015Sbinkertn@umich.edu{ 1878015Sbinkertn@umich.edu X86LiveProcess::initState(); 1888015Sbinkertn@umich.edu 1898015Sbinkertn@umich.edu argsInit(sizeof(uint64_t), PageBytes); 1908015Sbinkertn@umich.edu 1918015Sbinkertn@umich.edu // Set up the vsyscall page for this process. 1927977Shsul@eecs.umich.edu allocateMem(vsyscallPage.base, vsyscallPage.size); 1938013Sbinkertn@umich.edu uint8_t vtimeBlob[] = { 1948013Sbinkertn@umich.edu 0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax 1958013Sbinkertn@umich.edu 0x0f,0x05, // syscall 1968013Sbinkertn@umich.edu 0xc3 // retq 1977977Shsul@eecs.umich.edu }; 1988013Sbinkertn@umich.edu initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset, 1998013Sbinkertn@umich.edu vtimeBlob, sizeof(vtimeBlob)); 2008013Sbinkertn@umich.edu 2018016Sbinkertn@umich.edu uint8_t vgettimeofdayBlob[] = { 2027977Shsul@eecs.umich.edu 0x48,0xc7,0xc0,0x60,0x00,0x00,0x00, // mov $0x60,%rax 2038016Sbinkertn@umich.edu 0x0f,0x05, // syscall 2048016Sbinkertn@umich.edu 0xc3 // retq 2057977Shsul@eecs.umich.edu }; 2067977Shsul@eecs.umich.edu initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset, 2077977Shsul@eecs.umich.edu vgettimeofdayBlob, sizeof(vgettimeofdayBlob)); 2087977Shsul@eecs.umich.edu 2097977Shsul@eecs.umich.edu if (kvmInSE) { 2108013Sbinkertn@umich.edu PortProxy physProxy = system->physProxy; 2118013Sbinkertn@umich.edu 2128013Sbinkertn@umich.edu /* 2138013Sbinkertn@umich.edu * Set up the gdt. 2148013Sbinkertn@umich.edu */ 2158013Sbinkertn@umich.edu uint8_t numGDTEntries = 0; 2168013Sbinkertn@umich.edu uint64_t nullDescriptor = 0; 2178013Sbinkertn@umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 2188013Sbinkertn@umich.edu (uint8_t *)(&nullDescriptor), 8); 2198013Sbinkertn@umich.edu numGDTEntries++; 2208013Sbinkertn@umich.edu 2218013Sbinkertn@umich.edu SegDescriptor initDesc = 0; 2228013Sbinkertn@umich.edu initDesc.type.codeOrData = 0; // code or data type 2238013Sbinkertn@umich.edu initDesc.type.c = 0; // conforming 2248013Sbinkertn@umich.edu initDesc.type.r = 1; // readable 2258013Sbinkertn@umich.edu initDesc.dpl = 0; // privilege 2268013Sbinkertn@umich.edu initDesc.p = 1; // present 2278013Sbinkertn@umich.edu initDesc.l = 1; // longmode - 64 bit 2288013Sbinkertn@umich.edu initDesc.d = 0; // operand size 2298013Sbinkertn@umich.edu initDesc.g = 1; // granularity 2308013Sbinkertn@umich.edu initDesc.s = 1; // system segment 2318013Sbinkertn@umich.edu initDesc.limitHigh = 0xFFFF; 2328013Sbinkertn@umich.edu initDesc.limitLow = 0xF; 2338013Sbinkertn@umich.edu initDesc.baseHigh = 0x0; 2348013Sbinkertn@umich.edu initDesc.baseLow = 0x0; 2358013Sbinkertn@umich.edu 2368013Sbinkertn@umich.edu //64 bit code segment 2378013Sbinkertn@umich.edu SegDescriptor csLowPLDesc = initDesc; 2388013Sbinkertn@umich.edu csLowPLDesc.type.codeOrData = 1; 2398013Sbinkertn@umich.edu csLowPLDesc.dpl = 0; 2408013Sbinkertn@umich.edu uint64_t csLowPLDescVal = csLowPLDesc; 2418013Sbinkertn@umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 2428013Sbinkertn@umich.edu (uint8_t *)(&csLowPLDescVal), 8); 2438013Sbinkertn@umich.edu 2448013Sbinkertn@umich.edu numGDTEntries++; 2458013Sbinkertn@umich.edu 2468013Sbinkertn@umich.edu SegSelector csLowPL = 0; 2478013Sbinkertn@umich.edu csLowPL.si = numGDTEntries - 1; 2488013Sbinkertn@umich.edu csLowPL.rpl = 0; 2497977Shsul@eecs.umich.edu 2508013Sbinkertn@umich.edu //64 bit data segment 2518013Sbinkertn@umich.edu SegDescriptor dsLowPLDesc = initDesc; 2528013Sbinkertn@umich.edu dsLowPLDesc.type.codeOrData = 0; 2538013Sbinkertn@umich.edu dsLowPLDesc.dpl = 0; 2547977Shsul@eecs.umich.edu uint64_t dsLowPLDescVal = dsLowPLDesc; 2557977Shsul@eecs.umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 2568013Sbinkertn@umich.edu (uint8_t *)(&dsLowPLDescVal), 8); 2578013Sbinkertn@umich.edu 2588013Sbinkertn@umich.edu numGDTEntries++; 2598013Sbinkertn@umich.edu 2607977Shsul@eecs.umich.edu SegSelector dsLowPL = 0; 2618013Sbinkertn@umich.edu dsLowPL.si = numGDTEntries - 1; 2628013Sbinkertn@umich.edu dsLowPL.rpl = 0; 2638013Sbinkertn@umich.edu 2648013Sbinkertn@umich.edu //64 bit data segment 2658013Sbinkertn@umich.edu SegDescriptor dsDesc = initDesc; 2668013Sbinkertn@umich.edu dsDesc.type.codeOrData = 0; 2678013Sbinkertn@umich.edu dsDesc.dpl = 3; 2688013Sbinkertn@umich.edu uint64_t dsDescVal = dsDesc; 2698013Sbinkertn@umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 2708013Sbinkertn@umich.edu (uint8_t *)(&dsDescVal), 8); 2718013Sbinkertn@umich.edu 2728013Sbinkertn@umich.edu numGDTEntries++; 2738013Sbinkertn@umich.edu 2748013Sbinkertn@umich.edu SegSelector ds = 0; 2758013Sbinkertn@umich.edu ds.si = numGDTEntries - 1; 2768013Sbinkertn@umich.edu ds.rpl = 3; 2778013Sbinkertn@umich.edu 2788013Sbinkertn@umich.edu //64 bit code segment 2798013Sbinkertn@umich.edu SegDescriptor csDesc = initDesc; 2808013Sbinkertn@umich.edu csDesc.type.codeOrData = 1; 2818013Sbinkertn@umich.edu csDesc.dpl = 3; 2828013Sbinkertn@umich.edu uint64_t csDescVal = csDesc; 2838013Sbinkertn@umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 2848013Sbinkertn@umich.edu (uint8_t *)(&csDescVal), 8); 2858013Sbinkertn@umich.edu 2868013Sbinkertn@umich.edu numGDTEntries++; 2878013Sbinkertn@umich.edu 2887977Shsul@eecs.umich.edu SegSelector cs = 0; 2897977Shsul@eecs.umich.edu cs.si = numGDTEntries - 1; 2907977Shsul@eecs.umich.edu cs.rpl = 3; 2918013Sbinkertn@umich.edu 2928013Sbinkertn@umich.edu SegSelector scall = 0; 2938013Sbinkertn@umich.edu scall.si = csLowPL.si; 2948013Sbinkertn@umich.edu scall.rpl = 0; 2958013Sbinkertn@umich.edu 2967977Shsul@eecs.umich.edu SegSelector sret = 0; 2977977Shsul@eecs.umich.edu sret.si = dsLowPL.si; 2988013Sbinkertn@umich.edu sret.rpl = 3; 2998013Sbinkertn@umich.edu 3008013Sbinkertn@umich.edu /* In long mode the TSS has been extended to 16 Bytes */ 3018013Sbinkertn@umich.edu TSSlow TSSDescLow = 0; 3028013Sbinkertn@umich.edu TSSDescLow.type = 0xB; 3037977Shsul@eecs.umich.edu TSSDescLow.dpl = 0; // Privelege level 0 3047977Shsul@eecs.umich.edu TSSDescLow.p = 1; // Present 3057977Shsul@eecs.umich.edu TSSDescLow.g = 1; // Page granularity 3067977Shsul@eecs.umich.edu TSSDescLow.limitHigh = 0xF; 3077977Shsul@eecs.umich.edu TSSDescLow.limitLow = 0xFFFF; 3087977Shsul@eecs.umich.edu TSSDescLow.baseLow = bits(TSSVirtAddr, 23, 0); 3098013Sbinkertn@umich.edu TSSDescLow.baseHigh = bits(TSSVirtAddr, 31, 24); 3108013Sbinkertn@umich.edu 3118013Sbinkertn@umich.edu TSShigh TSSDescHigh = 0; 3128013Sbinkertn@umich.edu TSSDescHigh.base = bits(TSSVirtAddr, 63, 32); 3138013Sbinkertn@umich.edu 3148013Sbinkertn@umich.edu struct TSSDesc { 3158013Sbinkertn@umich.edu uint64_t low; 3168013Sbinkertn@umich.edu uint64_t high; 3178013Sbinkertn@umich.edu } tssDescVal = {TSSDescLow, TSSDescHigh}; 3188013Sbinkertn@umich.edu 3198013Sbinkertn@umich.edu physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8, 3208013Sbinkertn@umich.edu (uint8_t *)(&tssDescVal), sizeof(tssDescVal)); 3218013Sbinkertn@umich.edu 3228013Sbinkertn@umich.edu numGDTEntries++; 3238013Sbinkertn@umich.edu 3248013Sbinkertn@umich.edu SegSelector tssSel = 0; 3258013Sbinkertn@umich.edu tssSel.si = numGDTEntries - 1; 3267977Shsul@eecs.umich.edu 3277977Shsul@eecs.umich.edu uint64_t tss_base_addr = (TSSDescHigh.base << 32) | 3287977Shsul@eecs.umich.edu (TSSDescLow.baseHigh << 24) | 3297977Shsul@eecs.umich.edu TSSDescLow.baseLow; 3307977Shsul@eecs.umich.edu uint64_t tss_limit = TSSDescLow.limitLow | (TSSDescLow.limitHigh << 16); 3317977Shsul@eecs.umich.edu 3327977Shsul@eecs.umich.edu SegAttr tss_attr = 0; 3337977Shsul@eecs.umich.edu 3348013Sbinkertn@umich.edu tss_attr.type = TSSDescLow.type; 3358013Sbinkertn@umich.edu tss_attr.dpl = TSSDescLow.dpl; 3368013Sbinkertn@umich.edu tss_attr.present = TSSDescLow.p; 3378013Sbinkertn@umich.edu tss_attr.granularity = TSSDescLow.g; 3388013Sbinkertn@umich.edu tss_attr.unusable = 0; 3397977Shsul@eecs.umich.edu 3407977Shsul@eecs.umich.edu for (int i = 0; i < contextIds.size(); i++) { 3417977Shsul@eecs.umich.edu ThreadContext * tc = system->getThreadContext(contextIds[i]); 3428013Sbinkertn@umich.edu 3438013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_CS, cs); 3448013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_DS, ds); 3458013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_ES, ds); 3468013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_FS, ds); 3478013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_GS, ds); 3488013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_SS, ds); 3497977Shsul@eecs.umich.edu 3507977Shsul@eecs.umich.edu // LDT 3517977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_TSL, 0); 3528013Sbinkertn@umich.edu SegAttr tslAttr = 0; 3538013Sbinkertn@umich.edu tslAttr.present = 1; 3547977Shsul@eecs.umich.edu tslAttr.type = 2; 3557977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_TSL_ATTR, tslAttr); 3568013Sbinkertn@umich.edu 3577977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_TSG_BASE, GDTVirtAddr); 3588013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1); 3598013Sbinkertn@umich.edu 3608013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TR, tssSel); 3618013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TR_BASE, tss_base_addr); 3627977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_TR_EFF_BASE, 0); 3637977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_TR_LIMIT, tss_limit); 3648013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TR_ATTR, tss_attr); 3658013Sbinkertn@umich.edu 3668013Sbinkertn@umich.edu //Start using longmode segments. 3677977Shsul@eecs.umich.edu installSegDesc(tc, SEGMENT_REG_CS, csDesc, true); 3687977Shsul@eecs.umich.edu installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true); 3698013Sbinkertn@umich.edu installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true); 3708013Sbinkertn@umich.edu installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true); 3718013Sbinkertn@umich.edu installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true); 3728013Sbinkertn@umich.edu installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true); 3738013Sbinkertn@umich.edu 3748013Sbinkertn@umich.edu Efer efer = 0; 3757977Shsul@eecs.umich.edu efer.sce = 1; // Enable system call extensions. 3768013Sbinkertn@umich.edu efer.lme = 1; // Enable long mode. 3778013Sbinkertn@umich.edu efer.lma = 1; // Activate long mode. 3788013Sbinkertn@umich.edu efer.nxe = 0; // Enable nx support. 3797977Shsul@eecs.umich.edu efer.svme = 1; // Enable svm support for now. 3807977Shsul@eecs.umich.edu efer.ffxsr = 0; // Turn on fast fxsave and fxrstor. 3818013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_EFER, efer); 3827977Shsul@eecs.umich.edu 3837977Shsul@eecs.umich.edu //Set up the registers that describe the operating mode. 3848013Sbinkertn@umich.edu CR0 cr0 = 0; 3858013Sbinkertn@umich.edu cr0.pg = 1; // Turn on paging. 3867977Shsul@eecs.umich.edu cr0.cd = 0; // Don't disable caching. 3878016Sbinkertn@umich.edu cr0.nw = 0; // This is bit is defined to be ignored. 3888013Sbinkertn@umich.edu cr0.am = 1; // No alignment checking 3898013Sbinkertn@umich.edu cr0.wp = 1; // Supervisor mode can write read only pages 3907977Shsul@eecs.umich.edu cr0.ne = 1; 3917977Shsul@eecs.umich.edu cr0.et = 1; // This should always be 1 3928013Sbinkertn@umich.edu cr0.ts = 0; // We don't do task switching, so causing fp exceptions 3938013Sbinkertn@umich.edu // would be pointless. 3948013Sbinkertn@umich.edu cr0.em = 0; // Allow x87 instructions to execute natively. 3957977Shsul@eecs.umich.edu cr0.mp = 1; // This doesn't really matter, but the manual suggests 3967978Sbinkertn@umich.edu // setting it to one. 3977978Sbinkertn@umich.edu cr0.pe = 1; // We're definitely in protected mode. 3987977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_CR0, cr0); 3998013Sbinkertn@umich.edu 4007977Shsul@eecs.umich.edu CR0 cr2 = 0; 4018013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_CR2, cr2); 4028016Sbinkertn@umich.edu 4037977Shsul@eecs.umich.edu CR3 cr3 = pageTablePhysAddr; 4048013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_CR3, cr3); 4058013Sbinkertn@umich.edu 4068013Sbinkertn@umich.edu CR4 cr4 = 0; 4078013Sbinkertn@umich.edu //Turn on pae. 4088013Sbinkertn@umich.edu cr4.osxsave = 1; // Enable XSAVE and Proc Extended States 4098013Sbinkertn@umich.edu cr4.osxmmexcpt = 1; // Operating System Unmasked Exception 4107977Shsul@eecs.umich.edu cr4.osfxsr = 1; // Operating System FXSave/FSRSTOR Support 4118013Sbinkertn@umich.edu cr4.pce = 0; // Performance-Monitoring Counter Enable 4128013Sbinkertn@umich.edu cr4.pge = 0; // Page-Global Enable 4138013Sbinkertn@umich.edu cr4.mce = 0; // Machine Check Enable 4148013Sbinkertn@umich.edu cr4.pae = 1; // Physical-Address Extension 4158013Sbinkertn@umich.edu cr4.pse = 0; // Page Size Extensions 4168013Sbinkertn@umich.edu cr4.de = 0; // Debugging Extensions 4178013Sbinkertn@umich.edu cr4.tsd = 0; // Time Stamp Disable 4188013Sbinkertn@umich.edu cr4.pvi = 0; // Protected-Mode Virtual Interrupts 4198013Sbinkertn@umich.edu cr4.vme = 0; // Virtual-8086 Mode Extensions 4208013Sbinkertn@umich.edu 4218013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_CR4, cr4); 4227977Shsul@eecs.umich.edu 4238013Sbinkertn@umich.edu CR4 cr8 = 0; 4247977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_CR8, cr8); 4258013Sbinkertn@umich.edu 4268013Sbinkertn@umich.edu const Addr PageMapLevel4 = pageTablePhysAddr; 4278013Sbinkertn@umich.edu //Point to the page tables. 4288013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_CR3, PageMapLevel4); 4298013Sbinkertn@umich.edu 4308013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_MXCSR, 0x1f80); 4318013Sbinkertn@umich.edu 4328013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_APIC_BASE, 0xfee00900); 4338013Sbinkertn@umich.edu 4348013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TSG_BASE, GDTVirtAddr); 4358013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); 4368013Sbinkertn@umich.edu 4378013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_IDTR_BASE, IDTVirtAddr); 4388013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); 4398013Sbinkertn@umich.edu 4408013Sbinkertn@umich.edu /* enabling syscall and sysret */ 4417977Shsul@eecs.umich.edu MiscReg star = ((MiscReg)sret << 48) | ((MiscReg)scall << 32); 4428013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_STAR, star); 4437977Shsul@eecs.umich.edu MiscReg lstar = (MiscReg)syscallCodeVirtAddr; 4448013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_LSTAR, lstar); 4457977Shsul@eecs.umich.edu MiscReg sfmask = (1 << 8) | (1 << 10); // TF | DF 4468016Sbinkertn@umich.edu tc->setMiscReg(MISCREG_SF_MASK, sfmask); 4477977Shsul@eecs.umich.edu } 4488016Sbinkertn@umich.edu 4498013Sbinkertn@umich.edu /* Set up the content of the TSS and write it to physical memory. */ 4508013Sbinkertn@umich.edu 4518013Sbinkertn@umich.edu struct { 4528013Sbinkertn@umich.edu uint32_t reserved0; // +00h 4538013Sbinkertn@umich.edu uint32_t RSP0_low; // +04h 4548013Sbinkertn@umich.edu uint32_t RSP0_high; // +08h 4557977Shsul@eecs.umich.edu uint32_t RSP1_low; // +0Ch 4568013Sbinkertn@umich.edu uint32_t RSP1_high; // +10h 4577977Shsul@eecs.umich.edu uint32_t RSP2_low; // +14h 4588013Sbinkertn@umich.edu uint32_t RSP2_high; // +18h 4598013Sbinkertn@umich.edu uint32_t reserved1; // +1Ch 4608013Sbinkertn@umich.edu uint32_t reserved2; // +20h 4618013Sbinkertn@umich.edu uint32_t IST1_low; // +24h 4628013Sbinkertn@umich.edu uint32_t IST1_high; // +28h 4638013Sbinkertn@umich.edu uint32_t IST2_low; // +2Ch 4647977Shsul@eecs.umich.edu uint32_t IST2_high; // +30h 4658013Sbinkertn@umich.edu uint32_t IST3_low; // +34h 4668013Sbinkertn@umich.edu uint32_t IST3_high; // +38h 4677977Shsul@eecs.umich.edu uint32_t IST4_low; // +3Ch 4688013Sbinkertn@umich.edu uint32_t IST4_high; // +40h 4698013Sbinkertn@umich.edu uint32_t IST5_low; // +44h 4707977Shsul@eecs.umich.edu uint32_t IST5_high; // +48h 4718013Sbinkertn@umich.edu uint32_t IST6_low; // +4Ch 4728013Sbinkertn@umich.edu uint32_t IST6_high; // +50h 4738013Sbinkertn@umich.edu uint32_t IST7_low; // +54h 4748013Sbinkertn@umich.edu uint32_t IST7_high; // +58h 4758018Smserrano@umich.edu uint32_t reserved3; // +5Ch 4768013Sbinkertn@umich.edu uint32_t reserved4; // +60h 4778013Sbinkertn@umich.edu uint16_t reserved5; // +64h 4787977Shsul@eecs.umich.edu uint16_t IO_MapBase; // +66h 4797977Shsul@eecs.umich.edu } tss; 4808013Sbinkertn@umich.edu 4818013Sbinkertn@umich.edu /** setting Interrupt Stack Table */ 4828013Sbinkertn@umich.edu uint64_t IST_start = ISTVirtAddr + PageBytes; 4838013Sbinkertn@umich.edu tss.IST1_low = IST_start; 4848013Sbinkertn@umich.edu tss.IST1_high = IST_start >> 32; 4858013Sbinkertn@umich.edu tss.RSP0_low = tss.IST1_low; 4868013Sbinkertn@umich.edu tss.RSP0_high = tss.IST1_high; 4878013Sbinkertn@umich.edu tss.RSP1_low = tss.IST1_low; 4888013Sbinkertn@umich.edu tss.RSP1_high = tss.IST1_high; 4898013Sbinkertn@umich.edu tss.RSP2_low = tss.IST1_low; 4907977Shsul@eecs.umich.edu tss.RSP2_high = tss.IST1_high; 4917977Shsul@eecs.umich.edu physProxy.writeBlob(TSSPhysAddr, (uint8_t *)(&tss), sizeof(tss)); 4927977Shsul@eecs.umich.edu 4937977Shsul@eecs.umich.edu /* Setting IDT gates */ 4948013Sbinkertn@umich.edu GateDescriptorLow PFGateLow = 0; 4958018Smserrano@umich.edu PFGateLow.offsetHigh = bits(PFHandlerVirtAddr, 31, 16); 4968013Sbinkertn@umich.edu PFGateLow.offsetLow = bits(PFHandlerVirtAddr, 15, 0); 4978018Smserrano@umich.edu PFGateLow.selector = csLowPL; 4988013Sbinkertn@umich.edu PFGateLow.p = 1; 4998013Sbinkertn@umich.edu PFGateLow.dpl = 0; 5008013Sbinkertn@umich.edu PFGateLow.type = 0xe; // gate interrupt type 5017977Shsul@eecs.umich.edu PFGateLow.IST = 0; // setting IST to 0 and using RSP0 5028013Sbinkertn@umich.edu 5038013Sbinkertn@umich.edu GateDescriptorHigh PFGateHigh = 0; 5048013Sbinkertn@umich.edu PFGateHigh.offset = bits(PFHandlerVirtAddr, 63, 32); 5058013Sbinkertn@umich.edu 5067977Shsul@eecs.umich.edu struct { 5078013Sbinkertn@umich.edu uint64_t low; 5088013Sbinkertn@umich.edu uint64_t high; 5098013Sbinkertn@umich.edu } PFGate = {PFGateLow, PFGateHigh}; 5108013Sbinkertn@umich.edu 5117977Shsul@eecs.umich.edu physProxy.writeBlob(IDTPhysAddr + 0xE0, 5128013Sbinkertn@umich.edu (uint8_t *)(&PFGate), sizeof(PFGate)); 5138013Sbinkertn@umich.edu 5148013Sbinkertn@umich.edu /* System call handler */ 5157977Shsul@eecs.umich.edu uint8_t syscallBlob[] = { 5167977Shsul@eecs.umich.edu // mov %rax, (0xffffc90000005600) 5178013Sbinkertn@umich.edu 0x48, 0xa3, 0x00, 0x60, 0x00, 5188018Smserrano@umich.edu 0x00, 0x00, 0xc9, 0xff, 0xff, 5198013Sbinkertn@umich.edu // sysret 5207977Shsul@eecs.umich.edu 0x48, 0x0f, 0x07 5218013Sbinkertn@umich.edu }; 5228013Sbinkertn@umich.edu 5238013Sbinkertn@umich.edu physProxy.writeBlob(syscallCodePhysAddr, 5248013Sbinkertn@umich.edu syscallBlob, sizeof(syscallBlob)); 5258013Sbinkertn@umich.edu 5268013Sbinkertn@umich.edu /** Page fault handler */ 5278013Sbinkertn@umich.edu uint8_t faultBlob[] = { 5288013Sbinkertn@umich.edu // mov %rax, (0xffffc90000005700) 5298013Sbinkertn@umich.edu 0x48, 0xa3, 0x00, 0x61, 0x00, 5308018Smserrano@umich.edu 0x00, 0x00, 0xc9, 0xff, 0xff, 5318018Smserrano@umich.edu // add $0x8, %rsp # skip error 5328018Smserrano@umich.edu 0x48, 0x83, 0xc4, 0x08, 5338018Smserrano@umich.edu // iretq 5348018Smserrano@umich.edu 0x48, 0xcf 5358018Smserrano@umich.edu }; 5368018Smserrano@umich.edu 5378018Smserrano@umich.edu physProxy.writeBlob(PFHandlerPhysAddr, faultBlob, sizeof(faultBlob)); 5387977Shsul@eecs.umich.edu 5398013Sbinkertn@umich.edu MultiLevelPageTable<PageTableOps> *pt = 5408013Sbinkertn@umich.edu dynamic_cast<MultiLevelPageTable<PageTableOps> *>(pTable); 5418013Sbinkertn@umich.edu 5428018Smserrano@umich.edu /* Syscall handler */ 5438013Sbinkertn@umich.edu pt->map(syscallCodeVirtAddr, syscallCodePhysAddr, PageBytes, false); 5448013Sbinkertn@umich.edu /* GDT */ 5458013Sbinkertn@umich.edu pt->map(GDTVirtAddr, GDTPhysAddr, PageBytes, false); 5468013Sbinkertn@umich.edu /* IDT */ 5478013Sbinkertn@umich.edu pt->map(IDTVirtAddr, IDTPhysAddr, PageBytes, false); 5488013Sbinkertn@umich.edu /* TSS */ 5498013Sbinkertn@umich.edu pt->map(TSSVirtAddr, TSSPhysAddr, PageBytes, false); 5508013Sbinkertn@umich.edu /* IST */ 5518013Sbinkertn@umich.edu pt->map(ISTVirtAddr, ISTPhysAddr, PageBytes, false); 5528013Sbinkertn@umich.edu /* PF handler */ 5537977Shsul@eecs.umich.edu pt->map(PFHandlerVirtAddr, PFHandlerPhysAddr, PageBytes, false); 5548018Smserrano@umich.edu /* MMIO region for m5ops */ 5557977Shsul@eecs.umich.edu pt->map(MMIORegionVirtAddr, MMIORegionPhysAddr, 16*PageBytes, false); 5568013Sbinkertn@umich.edu } else { 5577977Shsul@eecs.umich.edu for (int i = 0; i < contextIds.size(); i++) { 5588013Sbinkertn@umich.edu ThreadContext * tc = system->getThreadContext(contextIds[i]); 5598013Sbinkertn@umich.edu 5607977Shsul@eecs.umich.edu SegAttr dataAttr = 0; 5618013Sbinkertn@umich.edu dataAttr.dpl = 3; 5628013Sbinkertn@umich.edu dataAttr.unusable = 0; 5638013Sbinkertn@umich.edu dataAttr.defaultSize = 1; 5647977Shsul@eecs.umich.edu dataAttr.longMode = 1; 5658013Sbinkertn@umich.edu dataAttr.avl = 0; 5668013Sbinkertn@umich.edu dataAttr.granularity = 1; 5678013Sbinkertn@umich.edu dataAttr.present = 1; 5688013Sbinkertn@umich.edu dataAttr.type = 3; 5697977Shsul@eecs.umich.edu dataAttr.writable = 1; 5708013Sbinkertn@umich.edu dataAttr.readable = 1; 5718013Sbinkertn@umich.edu dataAttr.expandDown = 0; 5728013Sbinkertn@umich.edu dataAttr.system = 1; 5737977Shsul@eecs.umich.edu 5748013Sbinkertn@umich.edu //Initialize the segment registers. 5758013Sbinkertn@umich.edu for (int seg = 0; seg < NUM_SEGMENTREGS; seg++) { 5768013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0); 5778013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0); 5787977Shsul@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr); 5798013Sbinkertn@umich.edu } 5808013Sbinkertn@umich.edu 5818013Sbinkertn@umich.edu SegAttr csAttr = 0; 5828013Sbinkertn@umich.edu csAttr.dpl = 3; 5837977Shsul@eecs.umich.edu csAttr.unusable = 0; 5848013Sbinkertn@umich.edu csAttr.defaultSize = 0; 5857977Shsul@eecs.umich.edu csAttr.longMode = 1; 5868013Sbinkertn@umich.edu csAttr.avl = 0; 5878013Sbinkertn@umich.edu csAttr.granularity = 1; 5888013Sbinkertn@umich.edu csAttr.present = 1; 5898013Sbinkertn@umich.edu csAttr.type = 10; 5907977Shsul@eecs.umich.edu csAttr.writable = 0; 5918013Sbinkertn@umich.edu csAttr.readable = 1; 5927977Shsul@eecs.umich.edu csAttr.expandDown = 0; 5938013Sbinkertn@umich.edu csAttr.system = 1; 5948013Sbinkertn@umich.edu 5958013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); 5967977Shsul@eecs.umich.edu 5978013Sbinkertn@umich.edu Efer efer = 0; 5988013Sbinkertn@umich.edu efer.sce = 1; // Enable system call extensions. 5998013Sbinkertn@umich.edu efer.lme = 1; // Enable long mode. 6007977Shsul@eecs.umich.edu efer.lma = 1; // Activate long mode. 6018018Smserrano@umich.edu efer.nxe = 1; // Enable nx support. 6028013Sbinkertn@umich.edu efer.svme = 0; // Disable svm support for now. It isn't implemented. 6037977Shsul@eecs.umich.edu efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. 6048013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_EFER, efer); 6058013Sbinkertn@umich.edu 6067977Shsul@eecs.umich.edu //Set up the registers that describe the operating mode. 6078013Sbinkertn@umich.edu CR0 cr0 = 0; 6088013Sbinkertn@umich.edu cr0.pg = 1; // Turn on paging. 6098013Sbinkertn@umich.edu cr0.cd = 0; // Don't disable caching. 6107977Shsul@eecs.umich.edu cr0.nw = 0; // This is bit is defined to be ignored. 6118013Sbinkertn@umich.edu cr0.am = 0; // No alignment checking 6127977Shsul@eecs.umich.edu cr0.wp = 0; // Supervisor mode can write read only pages 6138013Sbinkertn@umich.edu cr0.ne = 1; 6148013Sbinkertn@umich.edu cr0.et = 1; // This should always be 1 6158013Sbinkertn@umich.edu cr0.ts = 0; // We don't do task switching, so causing fp exceptions 6168013Sbinkertn@umich.edu // would be pointless. 6178013Sbinkertn@umich.edu cr0.em = 0; // Allow x87 instructions to execute natively. 6187977Shsul@eecs.umich.edu cr0.mp = 1; // This doesn't really matter, but the manual suggests 6198013Sbinkertn@umich.edu // setting it to one. 6208013Sbinkertn@umich.edu cr0.pe = 1; // We're definitely in protected mode. 6217977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_CR0, cr0); 6228013Sbinkertn@umich.edu 6237977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_MXCSR, 0x1f80); 6248022Sbinkertn@umich.edu } 6258013Sbinkertn@umich.edu } 6267977Shsul@eecs.umich.edu} 6278013Sbinkertn@umich.edu 6288013Sbinkertn@umich.eduvoid 6298013Sbinkertn@umich.eduI386LiveProcess::initState() 6308019Sbenash@umich.edu{ 6318019Sbenash@umich.edu X86LiveProcess::initState(); 6328019Sbenash@umich.edu 6337977Shsul@eecs.umich.edu argsInit(sizeof(uint32_t), PageBytes); 6348013Sbinkertn@umich.edu 6358013Sbinkertn@umich.edu /* 6367977Shsul@eecs.umich.edu * Set up a GDT for this process. The whole GDT wouldn't really be for 6378013Sbinkertn@umich.edu * this process, but the only parts we care about are. 6387977Shsul@eecs.umich.edu */ 6398013Sbinkertn@umich.edu allocateMem(_gdtStart, _gdtSize); 6408013Sbinkertn@umich.edu uint64_t zero = 0; 6418013Sbinkertn@umich.edu assert(_gdtSize % sizeof(zero) == 0); 6428013Sbinkertn@umich.edu for (Addr gdtCurrent = _gdtStart; 6438013Sbinkertn@umich.edu gdtCurrent < _gdtStart + _gdtSize; gdtCurrent += sizeof(zero)) { 6448013Sbinkertn@umich.edu initVirtMem.write(gdtCurrent, zero); 6458013Sbinkertn@umich.edu } 6468013Sbinkertn@umich.edu 6477977Shsul@eecs.umich.edu // Set up the vsyscall page for this process. 6488013Sbinkertn@umich.edu allocateMem(vsyscallPage.base, vsyscallPage.size); 6498013Sbinkertn@umich.edu uint8_t vsyscallBlob[] = { 6507977Shsul@eecs.umich.edu 0x51, // push %ecx 6518013Sbinkertn@umich.edu 0x52, // push %edp 6528013Sbinkertn@umich.edu 0x55, // push %ebp 6538013Sbinkertn@umich.edu 0x89, 0xe5, // mov %esp, %ebp 6547977Shsul@eecs.umich.edu 0x0f, 0x34 // sysenter 6557977Shsul@eecs.umich.edu }; 6568013Sbinkertn@umich.edu initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset, 6578013Sbinkertn@umich.edu vsyscallBlob, sizeof(vsyscallBlob)); 6588013Sbinkertn@umich.edu 6597977Shsul@eecs.umich.edu uint8_t vsysexitBlob[] = { 6608013Sbinkertn@umich.edu 0x5d, // pop %ebp 6618013Sbinkertn@umich.edu 0x5a, // pop %edx 6628013Sbinkertn@umich.edu 0x59, // pop %ecx 6638013Sbinkertn@umich.edu 0xc3 // ret 6648013Sbinkertn@umich.edu }; 6658013Sbinkertn@umich.edu initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset, 6668013Sbinkertn@umich.edu vsysexitBlob, sizeof(vsysexitBlob)); 6677977Shsul@eecs.umich.edu 6688013Sbinkertn@umich.edu for (int i = 0; i < contextIds.size(); i++) { 6697977Shsul@eecs.umich.edu ThreadContext * tc = system->getThreadContext(contextIds[i]); 6708013Sbinkertn@umich.edu 6718013Sbinkertn@umich.edu SegAttr dataAttr = 0; 6728013Sbinkertn@umich.edu dataAttr.dpl = 3; 6738013Sbinkertn@umich.edu dataAttr.unusable = 0; 6747977Shsul@eecs.umich.edu dataAttr.defaultSize = 1; 6758013Sbinkertn@umich.edu dataAttr.longMode = 0; 6768013Sbinkertn@umich.edu dataAttr.avl = 0; 6778013Sbinkertn@umich.edu dataAttr.granularity = 1; 6788013Sbinkertn@umich.edu dataAttr.present = 1; 6798013Sbinkertn@umich.edu dataAttr.type = 3; 6808013Sbinkertn@umich.edu dataAttr.writable = 1; 6817977Shsul@eecs.umich.edu dataAttr.readable = 1; 6828013Sbinkertn@umich.edu dataAttr.expandDown = 0; 6838013Sbinkertn@umich.edu dataAttr.system = 1; 6848013Sbinkertn@umich.edu 6858013Sbinkertn@umich.edu //Initialize the segment registers. 6867977Shsul@eecs.umich.edu for (int seg = 0; seg < NUM_SEGMENTREGS; seg++) { 6878013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0); 6888013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0); 6897977Shsul@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr); 6908013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_SEL(seg), 0xB); 6918013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_SEG_LIMIT(seg), (uint32_t)(-1)); 6927977Shsul@eecs.umich.edu } 6938013Sbinkertn@umich.edu 6948013Sbinkertn@umich.edu SegAttr csAttr = 0; 6958013Sbinkertn@umich.edu csAttr.dpl = 3; 6968013Sbinkertn@umich.edu csAttr.unusable = 0; 6978013Sbinkertn@umich.edu csAttr.defaultSize = 1; 6987977Shsul@eecs.umich.edu csAttr.longMode = 0; 6998013Sbinkertn@umich.edu csAttr.avl = 0; 7008013Sbinkertn@umich.edu csAttr.granularity = 1; 7018013Sbinkertn@umich.edu csAttr.present = 1; 7027977Shsul@eecs.umich.edu csAttr.type = 0xa; 7038013Sbinkertn@umich.edu csAttr.writable = 0; 7048013Sbinkertn@umich.edu csAttr.readable = 1; 7058013Sbinkertn@umich.edu csAttr.expandDown = 0; 7068013Sbinkertn@umich.edu csAttr.system = 1; 7078013Sbinkertn@umich.edu 7088013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); 7097977Shsul@eecs.umich.edu 7108013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_TSG_BASE, _gdtStart); 7118013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_TSG_EFF_BASE, _gdtStart); 7127977Shsul@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_TSG_LIMIT, _gdtStart + _gdtSize - 1); 7138013Sbinkertn@umich.edu 7148013Sbinkertn@umich.edu // Set the LDT selector to 0 to deactivate it. 7158013Sbinkertn@umich.edu tc->setMiscRegNoEffect(MISCREG_TSL, 0); 7167977Shsul@eecs.umich.edu 7178013Sbinkertn@umich.edu Efer efer = 0; 7188013Sbinkertn@umich.edu efer.sce = 1; // Enable system call extensions. 7198013Sbinkertn@umich.edu efer.lme = 1; // Enable long mode. 7208013Sbinkertn@umich.edu efer.lma = 0; // Deactivate long mode. 7218013Sbinkertn@umich.edu efer.nxe = 1; // Enable nx support. 7228013Sbinkertn@umich.edu efer.svme = 0; // Disable svm support for now. It isn't implemented. 7238013Sbinkertn@umich.edu efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. 7248013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_EFER, efer); 7258013Sbinkertn@umich.edu 7268013Sbinkertn@umich.edu //Set up the registers that describe the operating mode. 7278013Sbinkertn@umich.edu CR0 cr0 = 0; 7288013Sbinkertn@umich.edu cr0.pg = 1; // Turn on paging. 7297977Shsul@eecs.umich.edu cr0.cd = 0; // Don't disable caching. 7308013Sbinkertn@umich.edu cr0.nw = 0; // This is bit is defined to be ignored. 7317977Shsul@eecs.umich.edu cr0.am = 0; // No alignment checking 7328013Sbinkertn@umich.edu cr0.wp = 0; // Supervisor mode can write read only pages 7338013Sbinkertn@umich.edu cr0.ne = 1; 7348013Sbinkertn@umich.edu cr0.et = 1; // This should always be 1 7358013Sbinkertn@umich.edu cr0.ts = 0; // We don't do task switching, so causing fp exceptions 7368013Sbinkertn@umich.edu // would be pointless. 7378013Sbinkertn@umich.edu cr0.em = 0; // Allow x87 instructions to execute natively. 7388013Sbinkertn@umich.edu cr0.mp = 1; // This doesn't really matter, but the manual suggests 7397977Shsul@eecs.umich.edu // setting it to one. 7407977Shsul@eecs.umich.edu cr0.pe = 1; // We're definitely in protected mode. 7417977Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_CR0, cr0); 7427977Shsul@eecs.umich.edu 7438013Sbinkertn@umich.edu tc->setMiscReg(MISCREG_MXCSR, 0x1f80); 7448016Sbinkertn@umich.edu } 7458016Sbinkertn@umich.edu} 7468016Sbinkertn@umich.edu 7478015Sbinkertn@umich.edutemplate<class IntType> 7488013Sbinkertn@umich.eduvoid 7497977Shsul@eecs.umich.eduX86LiveProcess::argsInit(int pageSize, 7508013Sbinkertn@umich.edu std::vector<AuxVector<IntType> > extraAuxvs) 7518013Sbinkertn@umich.edu{ 7528013Sbinkertn@umich.edu int intSize = sizeof(IntType); 7538013Sbinkertn@umich.edu 7548013Sbinkertn@umich.edu typedef AuxVector<IntType> auxv_t; 7558013Sbinkertn@umich.edu std::vector<auxv_t> auxv = extraAuxvs; 7568013Sbinkertn@umich.edu 7578013Sbinkertn@umich.edu string filename; 7587977Shsul@eecs.umich.edu if (argv.size() < 1) 7598016Sbinkertn@umich.edu filename = ""; 7607977Shsul@eecs.umich.edu else 7617977Shsul@eecs.umich.edu filename = argv[0]; 7627977Shsul@eecs.umich.edu 7638013Sbinkertn@umich.edu //We want 16 byte alignment 7648013Sbinkertn@umich.edu uint64_t align = 16; 7658013Sbinkertn@umich.edu 7667977Shsul@eecs.umich.edu // Patch the ld_bias for dynamic executables. 7678013Sbinkertn@umich.edu updateBias(); 7687977Shsul@eecs.umich.edu 7698013Sbinkertn@umich.edu // load object file into target memory 7708013Sbinkertn@umich.edu objFile->loadSections(initVirtMem); 7717977Shsul@eecs.umich.edu 7728013Sbinkertn@umich.edu enum X86CpuFeature { 7738013Sbinkertn@umich.edu X86_OnboardFPU = 1 << 0, 7748013Sbinkertn@umich.edu X86_VirtualModeExtensions = 1 << 1, 7758013Sbinkertn@umich.edu X86_DebuggingExtensions = 1 << 2, 7768013Sbinkertn@umich.edu X86_PageSizeExtensions = 1 << 3, 7777977Shsul@eecs.umich.edu 7788013Sbinkertn@umich.edu X86_TimeStampCounter = 1 << 4, 7798013Sbinkertn@umich.edu X86_ModelSpecificRegisters = 1 << 5, 7808013Sbinkertn@umich.edu X86_PhysicalAddressExtensions = 1 << 6, 7818013Sbinkertn@umich.edu X86_MachineCheckExtensions = 1 << 7, 7828013Sbinkertn@umich.edu 7838013Sbinkertn@umich.edu X86_CMPXCHG8Instruction = 1 << 8, 7848013Sbinkertn@umich.edu X86_OnboardAPIC = 1 << 9, 7858013Sbinkertn@umich.edu X86_SYSENTER_SYSEXIT = 1 << 11, 7868013Sbinkertn@umich.edu 7878013Sbinkertn@umich.edu X86_MemoryTypeRangeRegisters = 1 << 12, 7888013Sbinkertn@umich.edu X86_PageGlobalEnable = 1 << 13, 7898013Sbinkertn@umich.edu X86_MachineCheckArchitecture = 1 << 14, 7907977Shsul@eecs.umich.edu X86_CMOVInstruction = 1 << 15, 7917977Shsul@eecs.umich.edu 7928013Sbinkertn@umich.edu X86_PageAttributeTable = 1 << 16, 7938013Sbinkertn@umich.edu X86_36BitPSEs = 1 << 17, 7948013Sbinkertn@umich.edu X86_ProcessorSerialNumber = 1 << 18, 7958013Sbinkertn@umich.edu X86_CLFLUSHInstruction = 1 << 19, 7967977Shsul@eecs.umich.edu 7978013Sbinkertn@umich.edu X86_DebugTraceStore = 1 << 21, 7988013Sbinkertn@umich.edu X86_ACPIViaMSR = 1 << 22, 7998013Sbinkertn@umich.edu X86_MultimediaExtensions = 1 << 23, 8008013Sbinkertn@umich.edu 8018013Sbinkertn@umich.edu X86_FXSAVE_FXRSTOR = 1 << 24, 8028013Sbinkertn@umich.edu X86_StreamingSIMDExtensions = 1 << 25, 8038013Sbinkertn@umich.edu X86_StreamingSIMDExtensions2 = 1 << 26, 8048013Sbinkertn@umich.edu X86_CPUSelfSnoop = 1 << 27, 8058013Sbinkertn@umich.edu 8067977Shsul@eecs.umich.edu X86_HyperThreading = 1 << 28, 8078013Sbinkertn@umich.edu X86_AutomaticClockControl = 1 << 29, 8088013Sbinkertn@umich.edu X86_IA64Processor = 1 << 30 8098013Sbinkertn@umich.edu }; 8108013Sbinkertn@umich.edu 8118013Sbinkertn@umich.edu // Setup the auxiliary vectors. These will already have endian 8128013Sbinkertn@umich.edu // conversion. Auxiliary vectors are loaded only for elf formatted 8138013Sbinkertn@umich.edu // executables; the auxv is responsible for passing information from 8147977Shsul@eecs.umich.edu // the OS to the interpreter. 8157977Shsul@eecs.umich.edu ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 8168013Sbinkertn@umich.edu if (elfObject) { 8178013Sbinkertn@umich.edu uint64_t features = 8187977Shsul@eecs.umich.edu X86_OnboardFPU | 8197977Shsul@eecs.umich.edu X86_VirtualModeExtensions | 8207977Shsul@eecs.umich.edu X86_DebuggingExtensions | 8217977Shsul@eecs.umich.edu X86_PageSizeExtensions | 8228013Sbinkertn@umich.edu X86_TimeStampCounter | 8237977Shsul@eecs.umich.edu X86_ModelSpecificRegisters | 8247977Shsul@eecs.umich.edu X86_PhysicalAddressExtensions | 8257978Sbinkertn@umich.edu X86_MachineCheckExtensions | 8267977Shsul@eecs.umich.edu X86_CMPXCHG8Instruction | 8277978Sbinkertn@umich.edu X86_OnboardAPIC | 8287978Sbinkertn@umich.edu X86_SYSENTER_SYSEXIT | 8297977Shsul@eecs.umich.edu X86_MemoryTypeRangeRegisters | 8308013Sbinkertn@umich.edu X86_PageGlobalEnable | 8317977Shsul@eecs.umich.edu X86_MachineCheckArchitecture | 8328013Sbinkertn@umich.edu X86_CMOVInstruction | 8338013Sbinkertn@umich.edu X86_PageAttributeTable | 8348013Sbinkertn@umich.edu X86_36BitPSEs | 8358013Sbinkertn@umich.edu// X86_ProcessorSerialNumber | 8368013Sbinkertn@umich.edu X86_CLFLUSHInstruction | 8378013Sbinkertn@umich.edu// X86_DebugTraceStore | 8388013Sbinkertn@umich.edu// X86_ACPIViaMSR | 8397977Shsul@eecs.umich.edu X86_MultimediaExtensions | 8408015Sbinkertn@umich.edu X86_FXSAVE_FXRSTOR | 8418015Sbinkertn@umich.edu X86_StreamingSIMDExtensions | 8428015Sbinkertn@umich.edu X86_StreamingSIMDExtensions2 | 8438015Sbinkertn@umich.edu// X86_CPUSelfSnoop | 8447977Shsul@eecs.umich.edu// X86_HyperThreading | 8457977Shsul@eecs.umich.edu// X86_AutomaticClockControl | 8468013Sbinkertn@umich.edu// X86_IA64Processor | 8478013Sbinkertn@umich.edu 0; 8488013Sbinkertn@umich.edu 8498013Sbinkertn@umich.edu //Bits which describe the system hardware capabilities 8507977Shsul@eecs.umich.edu //XXX Figure out what these should be 8517977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_HWCAP, features)); 8527977Shsul@eecs.umich.edu //The system page size 8537977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PAGESZ, X86ISA::PageBytes)); 8547977Shsul@eecs.umich.edu //Frequency at which times() increments 8557977Shsul@eecs.umich.edu //Defined to be 100 in the kernel source. 8567977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 8577977Shsul@eecs.umich.edu // This is the virtual address of the program header tables if they 8587982Ssaidi@eecs.umich.edu // appear in the executable image. 8597982Ssaidi@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 8607977Shsul@eecs.umich.edu // This is the size of a program header entry from the elf file. 8617977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 8627977Shsul@eecs.umich.edu // This is the number of program headers from the original elf file. 8637977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 8647977Shsul@eecs.umich.edu // This is the base address of the ELF interpreter; it should be 8657977Shsul@eecs.umich.edu // zero for static executables or contain the base address for 8667977Shsul@eecs.umich.edu // dynamic executables. 8677977Shsul@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_BASE, getBias())); 8687978Sbinkertn@umich.edu //XXX Figure out what this should be. 8697978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); 8707978Sbinkertn@umich.edu //The entry point to the program 8717978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 8727978Sbinkertn@umich.edu //Different user and group IDs 8737978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_UID, uid())); 8747978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_EUID, euid())); 8757978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_GID, gid())); 8767978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_EGID, egid())); 8777978Sbinkertn@umich.edu //Whether to enable "secure mode" in the executable 8787978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_SECURE, 0)); 8797978Sbinkertn@umich.edu //The address of 16 "random" bytes. 8807978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_RANDOM, 0)); 8817978Sbinkertn@umich.edu //The name of the program 8827978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_EXECFN, 0)); 8837978Sbinkertn@umich.edu //The platform string 8847978Sbinkertn@umich.edu auxv.push_back(auxv_t(M5_AT_PLATFORM, 0)); 8857978Sbinkertn@umich.edu } 8867978Sbinkertn@umich.edu 8877978Sbinkertn@umich.edu //Figure out how big the initial stack needs to be 8887978Sbinkertn@umich.edu 8897978Sbinkertn@umich.edu // A sentry NULL void pointer at the top of the stack. 8907978Sbinkertn@umich.edu int sentry_size = intSize; 8917978Sbinkertn@umich.edu 8927978Sbinkertn@umich.edu //This is the name of the file which is present on the initial stack 8937978Sbinkertn@umich.edu //It's purpose is to let the user space linker examine the original file. 8947978Sbinkertn@umich.edu int file_name_size = filename.size() + 1; 8957978Sbinkertn@umich.edu 8967978Sbinkertn@umich.edu const int numRandomBytes = 16; 8977977Shsul@eecs.umich.edu int aux_data_size = numRandomBytes; 8987978Sbinkertn@umich.edu 8997977Shsul@eecs.umich.edu string platform = "x86_64"; 9008013Sbinkertn@umich.edu aux_data_size += platform.size() + 1; 9018013Sbinkertn@umich.edu 9028013Sbinkertn@umich.edu int env_data_size = 0; 9038013Sbinkertn@umich.edu for (int i = 0; i < envp.size(); ++i) 9048013Sbinkertn@umich.edu env_data_size += envp[i].size() + 1; 9058013Sbinkertn@umich.edu int arg_data_size = 0; 9068013Sbinkertn@umich.edu for (int i = 0; i < argv.size(); ++i) 9078013Sbinkertn@umich.edu arg_data_size += argv[i].size() + 1; 9088013Sbinkertn@umich.edu 9098013Sbinkertn@umich.edu //The info_block needs to be padded so it's size is a multiple of the 9108013Sbinkertn@umich.edu //alignment mask. Also, it appears that there needs to be at least some 9118013Sbinkertn@umich.edu //padding, so if the size is already a multiple, we need to increase it 9128013Sbinkertn@umich.edu //anyway. 9138013Sbinkertn@umich.edu int base_info_block_size = 9148013Sbinkertn@umich.edu sentry_size + file_name_size + env_data_size + arg_data_size; 9158013Sbinkertn@umich.edu 9168013Sbinkertn@umich.edu int info_block_size = roundUp(base_info_block_size, align); 9178013Sbinkertn@umich.edu 9188013Sbinkertn@umich.edu int info_block_padding = info_block_size - base_info_block_size; 9198013Sbinkertn@umich.edu 9208013Sbinkertn@umich.edu //Each auxilliary vector is two 8 byte words 9218013Sbinkertn@umich.edu int aux_array_size = intSize * 2 * (auxv.size() + 1); 9228013Sbinkertn@umich.edu 9238013Sbinkertn@umich.edu int envp_array_size = intSize * (envp.size() + 1); 9248013Sbinkertn@umich.edu int argv_array_size = intSize * (argv.size() + 1); 9258013Sbinkertn@umich.edu 9268013Sbinkertn@umich.edu int argc_size = intSize; 9278013Sbinkertn@umich.edu 9288013Sbinkertn@umich.edu //Figure out the size of the contents of the actual initial frame 9297979Sbinkertn@umich.edu int frame_size = 9307979Sbinkertn@umich.edu aux_array_size + 9318013Sbinkertn@umich.edu envp_array_size + 9327979Sbinkertn@umich.edu argv_array_size + 9337979Sbinkertn@umich.edu argc_size; 9347979Sbinkertn@umich.edu 9357979Sbinkertn@umich.edu //There needs to be padding after the auxiliary vector data so that the 9367979Sbinkertn@umich.edu //very bottom of the stack is aligned properly. 9377979Sbinkertn@umich.edu int partial_size = frame_size + aux_data_size; 9387979Sbinkertn@umich.edu int aligned_partial_size = roundUp(partial_size, align); 9397979Sbinkertn@umich.edu int aux_padding = aligned_partial_size - partial_size; 9407979Sbinkertn@umich.edu 9417979Sbinkertn@umich.edu int space_needed = 9427979Sbinkertn@umich.edu info_block_size + 9437979Sbinkertn@umich.edu aux_data_size + 9447979Sbinkertn@umich.edu aux_padding + 9457979Sbinkertn@umich.edu frame_size; 9467979Sbinkertn@umich.edu 9477979Sbinkertn@umich.edu stack_min = stack_base - space_needed; 9487979Sbinkertn@umich.edu stack_min = roundDown(stack_min, align); 9497979Sbinkertn@umich.edu stack_size = roundUp(stack_base - stack_min, pageSize); 9507979Sbinkertn@umich.edu 9517979Sbinkertn@umich.edu // map memory 9527979Sbinkertn@umich.edu Addr stack_end = roundDown(stack_base - stack_size, pageSize); 9537979Sbinkertn@umich.edu 9547979Sbinkertn@umich.edu DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", stack_end, stack_size); 9557979Sbinkertn@umich.edu allocateMem(stack_end, stack_size); 9567979Sbinkertn@umich.edu 9577979Sbinkertn@umich.edu // map out initial stack contents 9587979Sbinkertn@umich.edu IntType sentry_base = stack_base - sentry_size; 9597979Sbinkertn@umich.edu IntType file_name_base = sentry_base - file_name_size; 9607979Sbinkertn@umich.edu IntType env_data_base = file_name_base - env_data_size; 9617979Sbinkertn@umich.edu IntType arg_data_base = env_data_base - arg_data_size; 9627979Sbinkertn@umich.edu IntType aux_data_base = arg_data_base - info_block_padding - aux_data_size; 9637979Sbinkertn@umich.edu IntType auxv_array_base = aux_data_base - aux_array_size - aux_padding; 9647979Sbinkertn@umich.edu IntType envp_array_base = auxv_array_base - envp_array_size; 9657979Sbinkertn@umich.edu IntType argv_array_base = envp_array_base - argv_array_size; 9667979Sbinkertn@umich.edu IntType argc_base = argv_array_base - argc_size; 9677979Sbinkertn@umich.edu 9687979Sbinkertn@umich.edu DPRINTF(Stack, "The addresses of items on the initial stack:\n"); 9697979Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - file name\n", file_name_base); 9707979Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - env data\n", env_data_base); 9717979Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); 9727979Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); 9737978Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); 9747978Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); 9757978Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); 9767977Shsul@eecs.umich.edu DPRINTF(Stack, "0x%x - argc \n", argc_base); 9778013Sbinkertn@umich.edu DPRINTF(Stack, "0x%x - stack min\n", stack_min); 9788013Sbinkertn@umich.edu 9798013Sbinkertn@umich.edu // write contents to stack 9808013Sbinkertn@umich.edu 9817978Sbinkertn@umich.edu // figure out argc 9828013Sbinkertn@umich.edu IntType argc = argv.size(); 9838013Sbinkertn@umich.edu IntType guestArgc = X86ISA::htog(argc); 9848013Sbinkertn@umich.edu 9858013Sbinkertn@umich.edu //Write out the sentry void * 9867978Sbinkertn@umich.edu IntType sentry_NULL = 0; 9878013Sbinkertn@umich.edu initVirtMem.writeBlob(sentry_base, 9888013Sbinkertn@umich.edu (uint8_t*)&sentry_NULL, sentry_size); 9898013Sbinkertn@umich.edu 9908013Sbinkertn@umich.edu //Write the file name 9918013Sbinkertn@umich.edu initVirtMem.writeString(file_name_base, filename.c_str()); 9928013Sbinkertn@umich.edu 9938013Sbinkertn@umich.edu //Fix up the aux vectors which point to data 9948013Sbinkertn@umich.edu assert(auxv[auxv.size() - 3].a_type == M5_AT_RANDOM); 9958013Sbinkertn@umich.edu auxv[auxv.size() - 3].a_val = aux_data_base; 9968013Sbinkertn@umich.edu assert(auxv[auxv.size() - 2].a_type == M5_AT_EXECFN); 9978013Sbinkertn@umich.edu auxv[auxv.size() - 2].a_val = argv_array_base; 9987978Sbinkertn@umich.edu assert(auxv[auxv.size() - 1].a_type == M5_AT_PLATFORM); 9998013Sbinkertn@umich.edu auxv[auxv.size() - 1].a_val = aux_data_base + numRandomBytes; 10008013Sbinkertn@umich.edu 10018013Sbinkertn@umich.edu //Copy the aux stuff 10027978Sbinkertn@umich.edu for (int x = 0; x < auxv.size(); x++) { 10038013Sbinkertn@umich.edu initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, 10048013Sbinkertn@umich.edu (uint8_t*)&(auxv[x].a_type), intSize); 10058013Sbinkertn@umich.edu initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 10068013Sbinkertn@umich.edu (uint8_t*)&(auxv[x].a_val), intSize); 10078013Sbinkertn@umich.edu } 10088013Sbinkertn@umich.edu //Write out the terminating zeroed auxilliary vector 10097977Shsul@eecs.umich.edu const uint64_t zero = 0; 10108013Sbinkertn@umich.edu initVirtMem.writeBlob(auxv_array_base + auxv.size() * 2 * intSize, 10118013Sbinkertn@umich.edu (uint8_t*)&zero, intSize); 10128013Sbinkertn@umich.edu initVirtMem.writeBlob(auxv_array_base + (auxv.size() * 2 + 1) * intSize, 10137979Sbinkertn@umich.edu (uint8_t*)&zero, intSize); 10148013Sbinkertn@umich.edu 10158013Sbinkertn@umich.edu initVirtMem.writeString(aux_data_base, platform.c_str()); 10167979Sbinkertn@umich.edu 10178013Sbinkertn@umich.edu copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 10188013Sbinkertn@umich.edu copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 10198013Sbinkertn@umich.edu 10208013Sbinkertn@umich.edu initVirtMem.writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 10217979Sbinkertn@umich.edu 10228013Sbinkertn@umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 10238013Sbinkertn@umich.edu //Set the stack pointer register 10248013Sbinkertn@umich.edu tc->setIntReg(StackPointerReg, stack_min); 10258013Sbinkertn@umich.edu 10268013Sbinkertn@umich.edu // There doesn't need to be any segment base added in since we're dealing 10278013Sbinkertn@umich.edu // with the flat segmentation model. 10288013Sbinkertn@umich.edu tc->pcState(getStartPC()); 10298013Sbinkertn@umich.edu 10308013Sbinkertn@umich.edu //Align the "stack_min" to a page boundary. 10318013Sbinkertn@umich.edu stack_min = roundDown(stack_min, pageSize); 10327977Shsul@eecs.umich.edu 10337977Shsul@eecs.umich.edu// num_processes++; 10348013Sbinkertn@umich.edu} 10358013Sbinkertn@umich.edu 10367977Shsul@eecs.umich.eduvoid 10378013Sbinkertn@umich.eduX86_64LiveProcess::argsInit(int intSize, int pageSize) 10388013Sbinkertn@umich.edu{ 10398013Sbinkertn@umich.edu std::vector<AuxVector<uint64_t> > extraAuxvs; 10408013Sbinkertn@umich.edu extraAuxvs.push_back(AuxVector<uint64_t>(M5_AT_SYSINFO_EHDR, 10418013Sbinkertn@umich.edu vsyscallPage.base)); 10428013Sbinkertn@umich.edu X86LiveProcess::argsInit<uint64_t>(pageSize, extraAuxvs); 10438013Sbinkertn@umich.edu} 10448013Sbinkertn@umich.edu 10458013Sbinkertn@umich.eduvoid 10468013Sbinkertn@umich.eduI386LiveProcess::argsInit(int intSize, int pageSize) 10478013Sbinkertn@umich.edu{ 10487985Ssaidi@eecs.umich.edu std::vector<AuxVector<uint32_t> > extraAuxvs; 10498013Sbinkertn@umich.edu //Tell the binary where the vsyscall part of the vsyscall page is. 10508013Sbinkertn@umich.edu extraAuxvs.push_back(AuxVector<uint32_t>(M5_AT_SYSINFO, 10517985Ssaidi@eecs.umich.edu vsyscallPage.base + vsyscallPage.vsyscallOffset)); 10528013Sbinkertn@umich.edu extraAuxvs.push_back(AuxVector<uint32_t>(M5_AT_SYSINFO_EHDR, 10538013Sbinkertn@umich.edu vsyscallPage.base)); 10547985Ssaidi@eecs.umich.edu X86LiveProcess::argsInit<uint32_t>(pageSize, extraAuxvs); 10558013Sbinkertn@umich.edu} 10568013Sbinkertn@umich.edu 10577977Shsul@eecs.umich.eduvoid 10588013Sbinkertn@umich.eduX86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn retval) 10597977Shsul@eecs.umich.edu{ 10607977Shsul@eecs.umich.edu tc->setIntReg(INTREG_RAX, retval.encodedValue()); 10618013Sbinkertn@umich.edu} 10628013Sbinkertn@umich.edu 10638013Sbinkertn@umich.eduX86ISA::IntReg 10648013Sbinkertn@umich.eduX86_64LiveProcess::getSyscallArg(ThreadContext *tc, int &i) 10657977Shsul@eecs.umich.edu{ 10668013Sbinkertn@umich.edu assert(i < NumArgumentRegs); 10678013Sbinkertn@umich.edu return tc->readIntReg(ArgumentReg[i++]); 10687977Shsul@eecs.umich.edu} 10698013Sbinkertn@umich.edu 10708013Sbinkertn@umich.eduvoid 10717977Shsul@eecs.umich.eduX86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) 10728013Sbinkertn@umich.edu{ 10738013Sbinkertn@umich.edu assert(i < NumArgumentRegs); 10748013Sbinkertn@umich.edu return tc->setIntReg(ArgumentReg[i], val); 10757977Shsul@eecs.umich.edu} 10768013Sbinkertn@umich.edu 10778013Sbinkertn@umich.eduX86ISA::IntReg 10788013Sbinkertn@umich.eduI386LiveProcess::getSyscallArg(ThreadContext *tc, int &i) 10797977Shsul@eecs.umich.edu{ 10808013Sbinkertn@umich.edu assert(i < NumArgumentRegs32); 10817977Shsul@eecs.umich.edu return tc->readIntReg(ArgumentReg32[i++]); 10827977Shsul@eecs.umich.edu} 10838013Sbinkertn@umich.edu 10848013Sbinkertn@umich.eduX86ISA::IntReg 10857977Shsul@eecs.umich.eduI386LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) 10868013Sbinkertn@umich.edu{ 10878013Sbinkertn@umich.edu assert(width == 32 || width == 64); 10888013Sbinkertn@umich.edu assert(i < NumArgumentRegs); 10897977Shsul@eecs.umich.edu uint64_t retVal = tc->readIntReg(ArgumentReg32[i++]) & mask(32); 10908013Sbinkertn@umich.edu if (width == 64) 10918013Sbinkertn@umich.edu retVal |= ((uint64_t)tc->readIntReg(ArgumentReg[i++]) << 32); 10928013Sbinkertn@umich.edu return retVal; 10938013Sbinkertn@umich.edu} 10948013Sbinkertn@umich.edu 10958004Ssaidi@eecs.umich.eduvoid 10968013Sbinkertn@umich.eduI386LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) 10978013Sbinkertn@umich.edu{ 10988013Sbinkertn@umich.edu assert(i < NumArgumentRegs); 10998013Sbinkertn@umich.edu return tc->setIntReg(ArgumentReg[i], val); 11008013Sbinkertn@umich.edu} 11017977Shsul@eecs.umich.edu