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