process.cc revision 11389:1e55f16160cb
16242Sgblack@eecs.umich.edu/* 27093Sgblack@eecs.umich.edu * Copyright (c) 2003-2004 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146242Sgblack@eecs.umich.edu * this software without specific prior written permission. 156242Sgblack@eecs.umich.edu * 166242Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176242Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186242Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196242Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206242Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216242Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226242Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236242Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246242Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256242Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266242Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276242Sgblack@eecs.umich.edu * 286242Sgblack@eecs.umich.edu * Authors: Gabe Black 296242Sgblack@eecs.umich.edu * Ali Saidi 306242Sgblack@eecs.umich.edu */ 316242Sgblack@eecs.umich.edu 326242Sgblack@eecs.umich.edu#include "arch/alpha/isa_traits.hh" 336242Sgblack@eecs.umich.edu#include "arch/alpha/process.hh" 346242Sgblack@eecs.umich.edu#include "base/loader/elf_object.hh" 356242Sgblack@eecs.umich.edu#include "base/loader/object_file.hh" 366242Sgblack@eecs.umich.edu#include "base/misc.hh" 376242Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 386242Sgblack@eecs.umich.edu#include "debug/Loader.hh" 396242Sgblack@eecs.umich.edu#include "mem/page_table.hh" 406242Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 416242Sgblack@eecs.umich.edu#include "sim/process_impl.hh" 426242Sgblack@eecs.umich.edu#include "sim/system.hh" 436242Sgblack@eecs.umich.edu 446242Sgblack@eecs.umich.eduusing namespace AlphaISA; 456242Sgblack@eecs.umich.eduusing namespace std; 466242Sgblack@eecs.umich.edu 476242Sgblack@eecs.umich.eduAlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params, 486242Sgblack@eecs.umich.edu ObjectFile *objFile) 496242Sgblack@eecs.umich.edu : LiveProcess(params, objFile) 506242Sgblack@eecs.umich.edu{ 516242Sgblack@eecs.umich.edu brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); 526242Sgblack@eecs.umich.edu brk_point = roundUp(brk_point, PageBytes); 536242Sgblack@eecs.umich.edu 546242Sgblack@eecs.umich.edu // Set up stack. On Alpha, stack goes below text section. This 556242Sgblack@eecs.umich.edu // code should get moved to some architecture-specific spot. 566242Sgblack@eecs.umich.edu stack_base = objFile->textBase() - (409600+4096); 576242Sgblack@eecs.umich.edu 586242Sgblack@eecs.umich.edu // Set up region for mmaps. Tru64 seems to start just above 0 and 596242Sgblack@eecs.umich.edu // grow up from there. 606242Sgblack@eecs.umich.edu mmap_end = 0x10000; 616242Sgblack@eecs.umich.edu 626242Sgblack@eecs.umich.edu // Set pointer for next thread stack. Reserve 8M for main stack. 636242Sgblack@eecs.umich.edu next_thread_stack_base = stack_base - (8 * 1024 * 1024); 646242Sgblack@eecs.umich.edu 657111Sgblack@eecs.umich.edu} 666242Sgblack@eecs.umich.edu 676242Sgblack@eecs.umich.eduvoid 686242Sgblack@eecs.umich.eduAlphaLiveProcess::argsInit(int intSize, int pageSize) 696242Sgblack@eecs.umich.edu{ 706735Sgblack@eecs.umich.edu // Patch the ld_bias for dynamic executables. 716242Sgblack@eecs.umich.edu updateBias(); 726242Sgblack@eecs.umich.edu 736242Sgblack@eecs.umich.edu objFile->loadSections(initVirtMem); 746723Sgblack@eecs.umich.edu 756242Sgblack@eecs.umich.edu typedef AuxVector<uint64_t> auxv_t; 766242Sgblack@eecs.umich.edu std::vector<auxv_t> auxv; 776261Sgblack@eecs.umich.edu 786403Sgblack@eecs.umich.edu ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 796403Sgblack@eecs.umich.edu if (elfObject) 806403Sgblack@eecs.umich.edu { 817259Sgblack@eecs.umich.edu // modern glibc uses a bunch of auxiliary vectors to set up 827259Sgblack@eecs.umich.edu // TLS as well as do a bunch of other stuff 837259Sgblack@eecs.umich.edu // these vectors go on the bottom of the stack, below argc/argv/envp 847259Sgblack@eecs.umich.edu // pointers but above actual arg strings 857264Sgblack@eecs.umich.edu // I don't have all the ones glibc looks at here, but so far it doesn't 867267Sgblack@eecs.umich.edu // seem to be a problem. 877265Sgblack@eecs.umich.edu // check out _dl_aux_init() in glibc/elf/dl-support.c for details 887266Sgblack@eecs.umich.edu // --Lisa 897266Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PAGESZ, AlphaISA::PageBytes)); 907266Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 917259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 927259Sgblack@eecs.umich.edu DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable()); 937259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 947259Sgblack@eecs.umich.edu // This is the base address of the ELF interpreter; it should be 957259Sgblack@eecs.umich.edu // zero for static executables or contain the base address for 967259Sgblack@eecs.umich.edu // dynamic executables. 977259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_BASE, getBias())); 987259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 997259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_UID, uid())); 1007259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_EUID, euid())); 1017259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_GID, gid())); 1027259Sgblack@eecs.umich.edu auxv.push_back(auxv_t(M5_AT_EGID, egid())); 1037259Sgblack@eecs.umich.edu 1047259Sgblack@eecs.umich.edu } 1057259Sgblack@eecs.umich.edu 1067259Sgblack@eecs.umich.edu // Calculate how much space we need for arg & env & auxv arrays. 1077259Sgblack@eecs.umich.edu int argv_array_size = intSize * (argv.size() + 1); 1087259Sgblack@eecs.umich.edu int envp_array_size = intSize * (envp.size() + 1); 1097259Sgblack@eecs.umich.edu int auxv_array_size = intSize * 2 * (auxv.size() + 1); 1107259Sgblack@eecs.umich.edu 1117259Sgblack@eecs.umich.edu int arg_data_size = 0; 1127259Sgblack@eecs.umich.edu for (vector<string>::size_type i = 0; i < argv.size(); ++i) { 1137259Sgblack@eecs.umich.edu arg_data_size += argv[i].size() + 1; 1147259Sgblack@eecs.umich.edu } 1157259Sgblack@eecs.umich.edu int env_data_size = 0; 1167259Sgblack@eecs.umich.edu for (vector<string>::size_type i = 0; i < envp.size(); ++i) { 1177259Sgblack@eecs.umich.edu env_data_size += envp[i].size() + 1; 1187259Sgblack@eecs.umich.edu } 1197259Sgblack@eecs.umich.edu 1207259Sgblack@eecs.umich.edu int space_needed = 1217259Sgblack@eecs.umich.edu argv_array_size + 1227259Sgblack@eecs.umich.edu envp_array_size + 1237259Sgblack@eecs.umich.edu auxv_array_size + 1247259Sgblack@eecs.umich.edu arg_data_size + 1257259Sgblack@eecs.umich.edu env_data_size; 1267259Sgblack@eecs.umich.edu 1277259Sgblack@eecs.umich.edu if (space_needed < 32*1024) 1287259Sgblack@eecs.umich.edu space_needed = 32*1024; 1297259Sgblack@eecs.umich.edu 1307259Sgblack@eecs.umich.edu // set bottom of stack 1317259Sgblack@eecs.umich.edu stack_min = stack_base - space_needed; 1327259Sgblack@eecs.umich.edu // align it 1337259Sgblack@eecs.umich.edu stack_min = roundDown(stack_min, pageSize); 1347259Sgblack@eecs.umich.edu stack_size = stack_base - stack_min; 1357259Sgblack@eecs.umich.edu // map memory 1367259Sgblack@eecs.umich.edu allocateMem(stack_min, roundUp(stack_size, pageSize)); 1377259Sgblack@eecs.umich.edu 1387259Sgblack@eecs.umich.edu // map out initial stack contents 1397259Sgblack@eecs.umich.edu Addr argv_array_base = stack_min + intSize; // room for argc 1407259Sgblack@eecs.umich.edu Addr envp_array_base = argv_array_base + argv_array_size; 1417259Sgblack@eecs.umich.edu Addr auxv_array_base = envp_array_base + envp_array_size; 1427259Sgblack@eecs.umich.edu Addr arg_data_base = auxv_array_base + auxv_array_size; 1437259Sgblack@eecs.umich.edu Addr env_data_base = arg_data_base + arg_data_size; 1447259Sgblack@eecs.umich.edu 1457259Sgblack@eecs.umich.edu // write contents to stack 1467259Sgblack@eecs.umich.edu uint64_t argc = argv.size(); 1477259Sgblack@eecs.umich.edu if (intSize == 8) 1487259Sgblack@eecs.umich.edu argc = htog((uint64_t)argc); 1497259Sgblack@eecs.umich.edu else if (intSize == 4) 1507259Sgblack@eecs.umich.edu argc = htog((uint32_t)argc); 1516735Sgblack@eecs.umich.edu else 1526261Sgblack@eecs.umich.edu panic("Unknown int size"); 1536261Sgblack@eecs.umich.edu 1547259Sgblack@eecs.umich.edu initVirtMem.writeBlob(stack_min, (uint8_t*)&argc, intSize); 1557259Sgblack@eecs.umich.edu 1567259Sgblack@eecs.umich.edu copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 1576261Sgblack@eecs.umich.edu copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 1587259Sgblack@eecs.umich.edu 1597259Sgblack@eecs.umich.edu //Copy the aux stuff 1607259Sgblack@eecs.umich.edu for (vector<auxv_t>::size_type x = 0; x < auxv.size(); x++) { 1617267Sgblack@eecs.umich.edu initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, 1627267Sgblack@eecs.umich.edu (uint8_t*)&(auxv[x].a_type), intSize); 1637266Sgblack@eecs.umich.edu initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 1647259Sgblack@eecs.umich.edu (uint8_t*)&(auxv[x].a_val), intSize); 1657259Sgblack@eecs.umich.edu } 1667259Sgblack@eecs.umich.edu 1677259Sgblack@eecs.umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 1687259Sgblack@eecs.umich.edu 1697259Sgblack@eecs.umich.edu setSyscallArg(tc, 0, argc); 1707259Sgblack@eecs.umich.edu setSyscallArg(tc, 1, argv_array_base); 1717259Sgblack@eecs.umich.edu tc->setIntReg(StackPointerReg, stack_min); 1727267Sgblack@eecs.umich.edu 1737259Sgblack@eecs.umich.edu tc->pcState(getStartPC()); 1746242Sgblack@eecs.umich.edu} 1756242Sgblack@eecs.umich.edu 1766242Sgblack@eecs.umich.eduvoid 1776242Sgblack@eecs.umich.eduAlphaLiveProcess::setupASNReg() 1786242Sgblack@eecs.umich.edu{ 1796242Sgblack@eecs.umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 1806242Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); 1816242Sgblack@eecs.umich.edu} 1826735Sgblack@eecs.umich.edu 1836242Sgblack@eecs.umich.edu 1846242Sgblack@eecs.umich.eduvoid 1856735Sgblack@eecs.umich.eduAlphaLiveProcess::loadState(CheckpointIn &cp) 1866242Sgblack@eecs.umich.edu{ 1876242Sgblack@eecs.umich.edu LiveProcess::loadState(cp); 1886242Sgblack@eecs.umich.edu // need to set up ASN after unserialization since M5_pid value may 1896242Sgblack@eecs.umich.edu // come from checkpoint 1906242Sgblack@eecs.umich.edu setupASNReg(); 1916242Sgblack@eecs.umich.edu} 1926242Sgblack@eecs.umich.edu 1936735Sgblack@eecs.umich.edu 1946750Sgblack@eecs.umich.eduvoid 1956750Sgblack@eecs.umich.eduAlphaLiveProcess::initState() 1966750Sgblack@eecs.umich.edu{ 1976750Sgblack@eecs.umich.edu // need to set up ASN before further initialization since init 1987093Sgblack@eecs.umich.edu // will involve writing to virtual memory addresses 1997093Sgblack@eecs.umich.edu setupASNReg(); 2007093Sgblack@eecs.umich.edu 2017093Sgblack@eecs.umich.edu LiveProcess::initState(); 2027093Sgblack@eecs.umich.edu 2037093Sgblack@eecs.umich.edu argsInit(MachineBytes, PageBytes); 2047093Sgblack@eecs.umich.edu 2056735Sgblack@eecs.umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 2066735Sgblack@eecs.umich.edu tc->setIntReg(GlobalPointerReg, objFile->globalPointer()); 2076735Sgblack@eecs.umich.edu //Operate in user mode 2086735Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(IPR_ICM, mode_user << 3); 2096735Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(IPR_DTB_CM, mode_user << 3); 2106735Sgblack@eecs.umich.edu //No super page mapping 2116735Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(IPR_MCSR, 0); 2126735Sgblack@eecs.umich.edu} 2136735Sgblack@eecs.umich.edu 2146735Sgblack@eecs.umich.eduAlphaISA::IntReg 2156735Sgblack@eecs.umich.eduAlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i) 2166735Sgblack@eecs.umich.edu{ 2176735Sgblack@eecs.umich.edu assert(i < 6); 2186735Sgblack@eecs.umich.edu return tc->readIntReg(FirstArgumentReg + i++); 2196735Sgblack@eecs.umich.edu} 2206735Sgblack@eecs.umich.edu 2216735Sgblack@eecs.umich.eduvoid 2226735Sgblack@eecs.umich.eduAlphaLiveProcess::setSyscallArg(ThreadContext *tc, 2236735Sgblack@eecs.umich.edu int i, AlphaISA::IntReg val) 2246735Sgblack@eecs.umich.edu{ 2256735Sgblack@eecs.umich.edu assert(i < 6); 2266735Sgblack@eecs.umich.edu tc->setIntReg(FirstArgumentReg + i, val); 2276735Sgblack@eecs.umich.edu} 2286735Sgblack@eecs.umich.edu 2296242Sgblack@eecs.umich.eduvoid 2306242Sgblack@eecs.umich.eduAlphaLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 2316242Sgblack@eecs.umich.edu{ 232 // check for error condition. Alpha syscall convention is to 233 // indicate success/failure in reg a3 (r19) and put the 234 // return value itself in the standard return value reg (v0). 235 if (sysret.successful()) { 236 // no error 237 tc->setIntReg(SyscallSuccessReg, 0); 238 tc->setIntReg(ReturnValueReg, sysret.returnValue()); 239 } else { 240 // got an error, return details 241 tc->setIntReg(SyscallSuccessReg, (IntReg)-1); 242 tc->setIntReg(ReturnValueReg, sysret.errnoValue()); 243 } 244} 245