process.cc revision 8232:b28d06a175be
12315SN/A/*
212107SRekai.GonzalezAlberquilla@arm.com * Copyright (c) 2010 ARM Limited
39913Ssteve.reinhardt@amd.com * All rights reserved
48733Sgeoffrey.blake@arm.com *
58733Sgeoffrey.blake@arm.com * The license below extends only to copyright in the software and shall
68733Sgeoffrey.blake@arm.com * not be construed as granting a license to any other intellectual
78733Sgeoffrey.blake@arm.com * property including but not limited to intellectual property relating
88733Sgeoffrey.blake@arm.com * to a hardware implementation of the functionality of the software
98733Sgeoffrey.blake@arm.com * licensed hereunder.  You may use the software subject to the license
108733Sgeoffrey.blake@arm.com * terms below provided that you ensure that this notice is replicated
118733Sgeoffrey.blake@arm.com * unmodified and in its entirety in all distributions of the software,
128733Sgeoffrey.blake@arm.com * modified or unmodified, in source code or in binary form.
138733Sgeoffrey.blake@arm.com *
148733Sgeoffrey.blake@arm.com * Copyright (c) 2007-2008 The Florida State University
152332SN/A * All rights reserved.
162315SN/A *
172315SN/A * Redistribution and use in source and binary forms, with or without
182315SN/A * modification, are permitted provided that the following conditions are
192315SN/A * met: redistributions of source code must retain the above copyright
202315SN/A * notice, this list of conditions and the following disclaimer;
212315SN/A * redistributions in binary form must reproduce the above copyright
222315SN/A * notice, this list of conditions and the following disclaimer in the
232315SN/A * documentation and/or other materials provided with the distribution;
242315SN/A * neither the name of the copyright holders nor the names of its
252315SN/A * contributors may be used to endorse or promote products derived from
262315SN/A * this software without specific prior written permission.
272315SN/A *
282315SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292315SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302315SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312315SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322315SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342315SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352315SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362315SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372315SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382315SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392315SN/A *
402689SN/A * Authors: Stephen Hines
412689SN/A *          Ali Saidi
428733Sgeoffrey.blake@arm.com */
432315SN/A
442315SN/A#include "arch/arm/isa_traits.hh"
459944Smatt.horsnell@ARM.com#include "arch/arm/process.hh"
469944Smatt.horsnell@ARM.com#include "arch/arm/types.hh"
479944Smatt.horsnell@ARM.com#include "base/loader/elf_object.hh"
482315SN/A#include "base/loader/object_file.hh"
492315SN/A#include "base/misc.hh"
502315SN/A#include "cpu/thread_context.hh"
518888Sgeoffrey.blake@arm.com#include "debug/Stack.hh"
528793Sgblack@eecs.umich.edu#include "mem/page_table.hh"
532315SN/A#include "mem/translating_port.hh"
546658Snate@binkert.org#include "sim/byteswap.hh"
552315SN/A#include "sim/process_impl.hh"
568733Sgeoffrey.blake@arm.com#include "sim/system.hh"
579913Ssteve.reinhardt@amd.com
582683SN/Ausing namespace std;
598229Snate@binkert.orgusing namespace ArmISA;
602680SN/A
618733Sgeoffrey.blake@arm.comArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile,
628733Sgeoffrey.blake@arm.com                               ObjectFile::Arch _arch)
638793Sgblack@eecs.umich.edu    : LiveProcess(params, objFile), arch(_arch)
642315SN/A{
652315SN/A    stack_base = 0xbf000000L;
662315SN/A
672315SN/A    // Set pointer for next thread stack.  Reserve 8M for main stack.
688733Sgeoffrey.blake@arm.com    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
692315SN/A
708733Sgeoffrey.blake@arm.com    // Set up break point (Top of Heap)
712315SN/A    brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
7210379Sandreas.hansson@arm.com    brk_point = roundUp(brk_point, VMPageSize);
738733Sgeoffrey.blake@arm.com
748733Sgeoffrey.blake@arm.com    // Set up region for mmaps. For now, start at bottom of kuseg space.
758733Sgeoffrey.blake@arm.com    mmap_start = mmap_end = 0x40000000L;
768733Sgeoffrey.blake@arm.com}
779023Sgblack@eecs.umich.edu
788733Sgeoffrey.blake@arm.comvoid
798733Sgeoffrey.blake@arm.comArmLiveProcess::initState()
808733Sgeoffrey.blake@arm.com{
818733Sgeoffrey.blake@arm.com    LiveProcess::initState();
828733Sgeoffrey.blake@arm.com    argsInit(MachineBytes, VMPageSize);
838733Sgeoffrey.blake@arm.com    for (int i = 0; i < contextIds.size(); i++) {
848733Sgeoffrey.blake@arm.com        ThreadContext * tc = system->getThreadContext(contextIds[i]);
858733Sgeoffrey.blake@arm.com        CPACR cpacr = tc->readMiscReg(MISCREG_CPACR);
868733Sgeoffrey.blake@arm.com        // Enable the floating point coprocessors.
878733Sgeoffrey.blake@arm.com        cpacr.cp10 = 0x3;
888733Sgeoffrey.blake@arm.com        cpacr.cp11 = 0x3;
898733Sgeoffrey.blake@arm.com        tc->setMiscReg(MISCREG_CPACR, cpacr);
908733Sgeoffrey.blake@arm.com        // Generically enable floating point support.
918733Sgeoffrey.blake@arm.com        FPEXC fpexc = tc->readMiscReg(MISCREG_FPEXC);
928733Sgeoffrey.blake@arm.com        fpexc.en = 1;
938733Sgeoffrey.blake@arm.com        tc->setMiscReg(MISCREG_FPEXC, fpexc);
948733Sgeoffrey.blake@arm.com    }
958733Sgeoffrey.blake@arm.com}
968733Sgeoffrey.blake@arm.com
978733Sgeoffrey.blake@arm.comvoid
988733Sgeoffrey.blake@arm.comArmLiveProcess::argsInit(int intSize, int pageSize)
998733Sgeoffrey.blake@arm.com{
1008733Sgeoffrey.blake@arm.com    typedef AuxVector<uint32_t> auxv_t;
1018733Sgeoffrey.blake@arm.com    std::vector<auxv_t> auxv;
1028733Sgeoffrey.blake@arm.com
1038733Sgeoffrey.blake@arm.com    string filename;
1048733Sgeoffrey.blake@arm.com    if (argv.size() < 1)
1058733Sgeoffrey.blake@arm.com        filename = "";
1068733Sgeoffrey.blake@arm.com    else
1078733Sgeoffrey.blake@arm.com        filename = argv[0];
1088733Sgeoffrey.blake@arm.com
1098733Sgeoffrey.blake@arm.com    //We want 16 byte alignment
1108733Sgeoffrey.blake@arm.com    uint64_t align = 16;
1118733Sgeoffrey.blake@arm.com
1128733Sgeoffrey.blake@arm.com    // load object file into target memory
1138733Sgeoffrey.blake@arm.com    objFile->loadSections(initVirtMem);
1148733Sgeoffrey.blake@arm.com
1158733Sgeoffrey.blake@arm.com    enum ArmCpuFeature {
1168733Sgeoffrey.blake@arm.com        Arm_Swp = 1 << 0,
1178733Sgeoffrey.blake@arm.com        Arm_Half = 1 << 1,
1188733Sgeoffrey.blake@arm.com        Arm_Thumb = 1 << 2,
1198733Sgeoffrey.blake@arm.com        Arm_26Bit = 1 << 3,
1208733Sgeoffrey.blake@arm.com        Arm_FastMult = 1 << 4,
1219023Sgblack@eecs.umich.edu        Arm_Fpa = 1 << 5,
1228733Sgeoffrey.blake@arm.com        Arm_Vfp = 1 << 6,
1238733Sgeoffrey.blake@arm.com        Arm_Edsp = 1 << 7,
1248733Sgeoffrey.blake@arm.com        Arm_Java = 1 << 8,
1258733Sgeoffrey.blake@arm.com        Arm_Iwmmxt = 1 << 9,
1268733Sgeoffrey.blake@arm.com        Arm_Crunch = 1 << 10,
12713429Srekai.gonzalezalberquilla@arm.com        Arm_ThumbEE = 1 << 11,
1282315SN/A        Arm_Neon = 1 << 12,
1292315SN/A        Arm_Vfpv3 = 1 << 13,
1302315SN/A        Arm_Vfpv3d16 = 1 << 14
1318733Sgeoffrey.blake@arm.com    };
1328733Sgeoffrey.blake@arm.com
1338733Sgeoffrey.blake@arm.com    //Setup the auxilliary vectors. These will already have endian conversion.
1348733Sgeoffrey.blake@arm.com    //Auxilliary vectors are loaded only for elf formatted executables.
1358733Sgeoffrey.blake@arm.com    ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
1368733Sgeoffrey.blake@arm.com    if (elfObject) {
1378733Sgeoffrey.blake@arm.com        uint32_t features =
1388733Sgeoffrey.blake@arm.com            Arm_Swp |
1398733Sgeoffrey.blake@arm.com            Arm_Half |
1408733Sgeoffrey.blake@arm.com            Arm_Thumb |
1418733Sgeoffrey.blake@arm.com//            Arm_26Bit |
1428733Sgeoffrey.blake@arm.com            Arm_FastMult |
1432332SN/A//            Arm_Fpa |
1442332SN/A            Arm_Vfp |
1452332SN/A            Arm_Edsp |
1462332SN/A//            Arm_Java |
1472332SN/A//            Arm_Iwmmxt |
1482315SN/A//            Arm_Crunch |
1492315SN/A            Arm_ThumbEE |
1508733Sgeoffrey.blake@arm.com            Arm_Neon |
1518733Sgeoffrey.blake@arm.com            Arm_Vfpv3 |
1522315SN/A            Arm_Vfpv3d16 |
1532315SN/A            0;
1542315SN/A
1552315SN/A        //Bits which describe the system hardware capabilities
1562315SN/A        //XXX Figure out what these should be
1572315SN/A        auxv.push_back(auxv_t(M5_AT_HWCAP, features));
1582315SN/A        //The system page size
1592315SN/A        auxv.push_back(auxv_t(M5_AT_PAGESZ, ArmISA::VMPageSize));
1602315SN/A        //Frequency at which times() increments
1612315SN/A        auxv.push_back(auxv_t(M5_AT_CLKTCK, 0x64));
1622315SN/A        // For statically linked executables, this is the virtual address of the
1632315SN/A        // program header tables if they appear in the executable image
1642315SN/A        auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
1658733Sgeoffrey.blake@arm.com        // This is the size of a program header entry from the elf file.
1668733Sgeoffrey.blake@arm.com        auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
1672315SN/A        // This is the number of program headers from the original elf file.
1682315SN/A        auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
1692315SN/A        //This is the address of the elf "interpreter", It should be set
1702315SN/A        //to 0 for regular executables. It should be something else
1712315SN/A        //(not sure what) for dynamic libraries.
1722315SN/A        auxv.push_back(auxv_t(M5_AT_BASE, 0));
1732315SN/A
1742315SN/A        //XXX Figure out what this should be.
1752315SN/A        auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
1762315SN/A        //The entry point to the program
1772315SN/A        auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
1782315SN/A        //Different user and group IDs
1792315SN/A        auxv.push_back(auxv_t(M5_AT_UID, uid()));
1802315SN/A        auxv.push_back(auxv_t(M5_AT_EUID, euid()));
1818733Sgeoffrey.blake@arm.com        auxv.push_back(auxv_t(M5_AT_GID, gid()));
1828733Sgeoffrey.blake@arm.com        auxv.push_back(auxv_t(M5_AT_EGID, egid()));
1838733Sgeoffrey.blake@arm.com        //Whether to enable "secure mode" in the executable
1848733Sgeoffrey.blake@arm.com        auxv.push_back(auxv_t(M5_AT_SECURE, 0));
1858733Sgeoffrey.blake@arm.com
1868733Sgeoffrey.blake@arm.com        // Pointer to 16 bytes of random data
1878733Sgeoffrey.blake@arm.com        auxv.push_back(auxv_t(M5_AT_RANDOM, 0));
1882354SN/A
1898733Sgeoffrey.blake@arm.com        //The filename of the program
1902354SN/A        auxv.push_back(auxv_t(M5_AT_EXECFN, 0));
1912332SN/A        //The string "v71" -- ARM v7 architecture
1922332SN/A        auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
1932332SN/A    }
1942315SN/A
1958733Sgeoffrey.blake@arm.com    //Figure out how big the initial stack nedes to be
1968733Sgeoffrey.blake@arm.com
1978733Sgeoffrey.blake@arm.com    // A sentry NULL void pointer at the top of the stack.
1988733Sgeoffrey.blake@arm.com    int sentry_size = intSize;
1998733Sgeoffrey.blake@arm.com
2008733Sgeoffrey.blake@arm.com    string platform = "v71";
2018733Sgeoffrey.blake@arm.com    int platform_size = platform.size() + 1;
2028733Sgeoffrey.blake@arm.com
2038733Sgeoffrey.blake@arm.com    // Bytes for AT_RANDOM above, we'll just keep them 0
2042315SN/A    int aux_random_size = 16; // as per the specification
2052315SN/A
2062315SN/A    // The aux vectors are put on the stack in two groups. The first group are
2072315SN/A    // the vectors that are generated as the elf is loaded. The second group
2082315SN/A    // are the ones that were computed ahead of time and include the platform
2092683SN/A    // string.
2108888Sgeoffrey.blake@arm.com    int aux_data_size = filename.size() + 1;
21113611Sgabeblack@google.com
2128888Sgeoffrey.blake@arm.com    int env_data_size = 0;
2132315SN/A    for (int i = 0; i < envp.size(); ++i) {
2142332SN/A        env_data_size += envp[i].size() + 1;
2152332SN/A    }
2162332SN/A    int arg_data_size = 0;
2172315SN/A    for (int i = 0; i < argv.size(); ++i) {
2188733Sgeoffrey.blake@arm.com        arg_data_size += argv[i].size() + 1;
2198733Sgeoffrey.blake@arm.com    }
2202315SN/A
2218733Sgeoffrey.blake@arm.com    int info_block_size =
2222315SN/A        sentry_size + env_data_size + arg_data_size +
2232315SN/A        aux_data_size + platform_size + aux_random_size;
2242332SN/A
2258733Sgeoffrey.blake@arm.com    //Each auxilliary vector is two 4 byte words
2268733Sgeoffrey.blake@arm.com    int aux_array_size = intSize * 2 * (auxv.size() + 1);
2272732SN/A
2282315SN/A    int envp_array_size = intSize * (envp.size() + 1);
2292315SN/A    int argv_array_size = intSize * (argv.size() + 1);
2302315SN/A
2312315SN/A    int argc_size = intSize;
2322315SN/A
2332315SN/A    //Figure out the size of the contents of the actual initial frame
2342332SN/A    int frame_size =
2358733Sgeoffrey.blake@arm.com        info_block_size +
2368733Sgeoffrey.blake@arm.com        aux_array_size +
2372332SN/A        envp_array_size +
2388733Sgeoffrey.blake@arm.com        argv_array_size +
2398733Sgeoffrey.blake@arm.com        argc_size;
2408733Sgeoffrey.blake@arm.com
2412332SN/A    //There needs to be padding after the auxiliary vector data so that the
2429023Sgblack@eecs.umich.edu    //very bottom of the stack is aligned properly.
2439023Sgblack@eecs.umich.edu    int partial_size = frame_size;
2448733Sgeoffrey.blake@arm.com    int aligned_partial_size = roundUp(partial_size, align);
2458733Sgeoffrey.blake@arm.com    int aux_padding = aligned_partial_size - partial_size;
2468733Sgeoffrey.blake@arm.com
24712749Sgiacomo.travaglini@arm.com    int space_needed = frame_size + aux_padding;
24812749Sgiacomo.travaglini@arm.com
24912749Sgiacomo.travaglini@arm.com    stack_min = stack_base - space_needed;
25012749Sgiacomo.travaglini@arm.com    stack_min = roundDown(stack_min, align);
2512679SN/A    stack_size = stack_base - stack_min;
25212749Sgiacomo.travaglini@arm.com
25312749Sgiacomo.travaglini@arm.com    // map memory
25412749Sgiacomo.travaglini@arm.com    pTable->allocate(roundDown(stack_min, pageSize),
2552315SN/A                     roundUp(stack_size, pageSize));
25612749Sgiacomo.travaglini@arm.com
25712749Sgiacomo.travaglini@arm.com    // map out initial stack contents
2582315SN/A    uint32_t sentry_base = stack_base - sentry_size;
2598733Sgeoffrey.blake@arm.com    uint32_t aux_data_base = sentry_base - aux_data_size;
2608733Sgeoffrey.blake@arm.com    uint32_t env_data_base = aux_data_base - env_data_size;
2618733Sgeoffrey.blake@arm.com    uint32_t arg_data_base = env_data_base - arg_data_size;
2628733Sgeoffrey.blake@arm.com    uint32_t platform_base = arg_data_base - platform_size;
2638733Sgeoffrey.blake@arm.com    uint32_t aux_random_base = platform_base - aux_random_size;
2648733Sgeoffrey.blake@arm.com    uint32_t auxv_array_base = aux_random_base - aux_array_size - aux_padding;
2658733Sgeoffrey.blake@arm.com    uint32_t envp_array_base = auxv_array_base - envp_array_size;
2668733Sgeoffrey.blake@arm.com    uint32_t argv_array_base = envp_array_base - argv_array_size;
2678733Sgeoffrey.blake@arm.com    uint32_t argc_base = argv_array_base - argc_size;
2688733Sgeoffrey.blake@arm.com
2692315SN/A    DPRINTF(Stack, "The addresses of items on the initial stack:\n");
2708733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - aux data\n", aux_data_base);
2718733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - env data\n", env_data_base);
2722315SN/A    DPRINTF(Stack, "0x%x - arg data\n", arg_data_base);
2738733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - random data\n", aux_random_base);
2748733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - platform base\n", platform_base);
2758733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base);
2768733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
2778733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - argv array\n", argv_array_base);
2788733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - argc \n", argc_base);
2798733Sgeoffrey.blake@arm.com    DPRINTF(Stack, "0x%x - stack min\n", stack_min);
2808733Sgeoffrey.blake@arm.com
2818733Sgeoffrey.blake@arm.com    // write contents to stack
2828733Sgeoffrey.blake@arm.com
2838733Sgeoffrey.blake@arm.com    // figure out argc
28412749Sgiacomo.travaglini@arm.com    uint32_t argc = argv.size();
2858733Sgeoffrey.blake@arm.com    uint32_t guestArgc = ArmISA::htog(argc);
2868733Sgeoffrey.blake@arm.com
2878733Sgeoffrey.blake@arm.com    //Write out the sentry void *
2888733Sgeoffrey.blake@arm.com    uint32_t sentry_NULL = 0;
2898733Sgeoffrey.blake@arm.com    initVirtMem->writeBlob(sentry_base,
2908733Sgeoffrey.blake@arm.com            (uint8_t*)&sentry_NULL, sentry_size);
2918733Sgeoffrey.blake@arm.com
2928733Sgeoffrey.blake@arm.com    //Fix up the aux vectors which point to other data
2938733Sgeoffrey.blake@arm.com    for (int i = auxv.size() - 1; i >= 0; i--) {
2948733Sgeoffrey.blake@arm.com        if (auxv[i].a_type == M5_AT_PLATFORM) {
2958733Sgeoffrey.blake@arm.com            auxv[i].a_val = platform_base;
2968733Sgeoffrey.blake@arm.com            initVirtMem->writeString(platform_base, platform.c_str());
2978733Sgeoffrey.blake@arm.com        } else if (auxv[i].a_type == M5_AT_EXECFN) {
2988733Sgeoffrey.blake@arm.com            auxv[i].a_val = aux_data_base;
2998733Sgeoffrey.blake@arm.com            initVirtMem->writeString(aux_data_base, filename.c_str());
3008733Sgeoffrey.blake@arm.com        } else if (auxv[i].a_type == M5_AT_RANDOM) {
3018733Sgeoffrey.blake@arm.com            auxv[i].a_val = aux_random_base;
3028733Sgeoffrey.blake@arm.com            // Just leave the value 0, we don't want randomness
30310417Sandreas.hansson@arm.com        }
3048733Sgeoffrey.blake@arm.com    }
3058733Sgeoffrey.blake@arm.com
3068733Sgeoffrey.blake@arm.com    //Copy the aux stuff
3078733Sgeoffrey.blake@arm.com    for(int x = 0; x < auxv.size(); x++)
3089023Sgblack@eecs.umich.edu    {
3098733Sgeoffrey.blake@arm.com        initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
3108733Sgeoffrey.blake@arm.com                (uint8_t*)&(auxv[x].a_type), intSize);
3118733Sgeoffrey.blake@arm.com        initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
3128733Sgeoffrey.blake@arm.com                (uint8_t*)&(auxv[x].a_val), intSize);
3139023Sgblack@eecs.umich.edu    }
3148733Sgeoffrey.blake@arm.com    //Write out the terminating zeroed auxilliary vector
3159023Sgblack@eecs.umich.edu    const uint64_t zero = 0;
3168733Sgeoffrey.blake@arm.com    initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
3178733Sgeoffrey.blake@arm.com            (uint8_t*)&zero, 2 * intSize);
3188733Sgeoffrey.blake@arm.com
3198733Sgeoffrey.blake@arm.com    copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
3208733Sgeoffrey.blake@arm.com    copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
3218733Sgeoffrey.blake@arm.com
3228733Sgeoffrey.blake@arm.com    initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
3238733Sgeoffrey.blake@arm.com
3248733Sgeoffrey.blake@arm.com    ThreadContext *tc = system->getThreadContext(contextIds[0]);
3258733Sgeoffrey.blake@arm.com    //Set the stack pointer register
3268733Sgeoffrey.blake@arm.com    tc->setIntReg(StackPointerReg, stack_min);
3278733Sgeoffrey.blake@arm.com    //A pointer to a function to run when the program exits. We'll set this
3288733Sgeoffrey.blake@arm.com    //to zero explicitly to make sure this isn't used.
3298733Sgeoffrey.blake@arm.com    tc->setIntReg(ArgumentReg0, 0);
3308733Sgeoffrey.blake@arm.com    //Set argument regs 1 and 2 to argv[0] and envp[0] respectively
3318733Sgeoffrey.blake@arm.com    if (argv.size() > 0) {
3328733Sgeoffrey.blake@arm.com        tc->setIntReg(ArgumentReg1, arg_data_base + arg_data_size -
3338733Sgeoffrey.blake@arm.com                                    argv[argv.size() - 1].size() - 1);
3348733Sgeoffrey.blake@arm.com    } else {
3358733Sgeoffrey.blake@arm.com        tc->setIntReg(ArgumentReg1, 0);
3368733Sgeoffrey.blake@arm.com    }
3372323SN/A    if (envp.size() > 0) {
3382315SN/A        tc->setIntReg(ArgumentReg2, env_data_base + env_data_size -
3399023Sgblack@eecs.umich.edu                                    envp[envp.size() - 1].size() - 1);
3409023Sgblack@eecs.umich.edu    } else {
3412315SN/A        tc->setIntReg(ArgumentReg2, 0);
3428733Sgeoffrey.blake@arm.com    }
3438733Sgeoffrey.blake@arm.com
3448733Sgeoffrey.blake@arm.com    PCState pc;
3452323SN/A    pc.thumb(arch == ObjectFile::Thumb);
3468733Sgeoffrey.blake@arm.com    pc.nextThumb(pc.thumb());
3472679SN/A    pc.set(objFile->entryPoint() & ~mask(1));
3482323SN/A    tc->pcState(pc);
3492323SN/A
3508733Sgeoffrey.blake@arm.com    //Align the "stack_min" to a page boundary.
3512323SN/A    stack_min = roundDown(stack_min, pageSize);
3522315SN/A}
3538733Sgeoffrey.blake@arm.com
3548733Sgeoffrey.blake@arm.comArmISA::IntReg
3558733Sgeoffrey.blake@arm.comArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
3562679SN/A{
3572315SN/A    assert(i < 6);
3582315SN/A    return tc->readIntReg(ArgumentReg0 + i++);
3592315SN/A}
3602315SN/A
3618733Sgeoffrey.blake@arm.comuint64_t
3628733Sgeoffrey.blake@arm.comArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
3638733Sgeoffrey.blake@arm.com{
3648733Sgeoffrey.blake@arm.com    assert(width == 32 || width == 64);
3658733Sgeoffrey.blake@arm.com    if (width == 32)
3668733Sgeoffrey.blake@arm.com        return getSyscallArg(tc, i);
3678733Sgeoffrey.blake@arm.com
3688733Sgeoffrey.blake@arm.com    // 64 bit arguments are passed starting in an even register
3698733Sgeoffrey.blake@arm.com    if (i % 2 != 0)
3708733Sgeoffrey.blake@arm.com       i++;
3718733Sgeoffrey.blake@arm.com
3728733Sgeoffrey.blake@arm.com    // Registers r0-r6 can be used
3738733Sgeoffrey.blake@arm.com    assert(i < 5);
3742315SN/A    uint64_t val;
3758733Sgeoffrey.blake@arm.com    val = tc->readIntReg(ArgumentReg0 + i++);
3768733Sgeoffrey.blake@arm.com    val |= ((uint64_t)tc->readIntReg(ArgumentReg0 + i++) << 32);
3778733Sgeoffrey.blake@arm.com    return val;
3788733Sgeoffrey.blake@arm.com}
3792315SN/A
3808733Sgeoffrey.blake@arm.com
3818733Sgeoffrey.blake@arm.comvoid
3828733Sgeoffrey.blake@arm.comArmLiveProcess::setSyscallArg(ThreadContext *tc,
3838733Sgeoffrey.blake@arm.com        int i, ArmISA::IntReg val)
3848733Sgeoffrey.blake@arm.com{
3858733Sgeoffrey.blake@arm.com    assert(i < 4);
3868733Sgeoffrey.blake@arm.com    tc->setIntReg(ArgumentReg0 + i, val);
3878733Sgeoffrey.blake@arm.com}
3888733Sgeoffrey.blake@arm.com
3898733Sgeoffrey.blake@arm.comvoid
3908733Sgeoffrey.blake@arm.comArmLiveProcess::setSyscallReturn(ThreadContext *tc,
3912315SN/A        SyscallReturn return_value)
3922315SN/A{
3932315SN/A    tc->setIntReg(ReturnValueReg, return_value.value());
3948733Sgeoffrey.blake@arm.com}
3952315SN/A