process.cc revision 7532:3f6413fc37a2
113786Sjavier.bueno@metempsy.com/*
213786Sjavier.bueno@metempsy.com * Copyright (c) 2007-2008 The Florida State University
313786Sjavier.bueno@metempsy.com * Copyright (c) 2009 The University of Edinburgh
413786Sjavier.bueno@metempsy.com * All rights reserved.
513786Sjavier.bueno@metempsy.com *
613786Sjavier.bueno@metempsy.com * Redistribution and use in source and binary forms, with or without
713786Sjavier.bueno@metempsy.com * modification, are permitted provided that the following conditions are
813786Sjavier.bueno@metempsy.com * met: redistributions of source code must retain the above copyright
913786Sjavier.bueno@metempsy.com * notice, this list of conditions and the following disclaimer;
1013786Sjavier.bueno@metempsy.com * redistributions in binary form must reproduce the above copyright
1113786Sjavier.bueno@metempsy.com * notice, this list of conditions and the following disclaimer in the
1213786Sjavier.bueno@metempsy.com * documentation and/or other materials provided with the distribution;
1313786Sjavier.bueno@metempsy.com * neither the name of the copyright holders nor the names of its
1413786Sjavier.bueno@metempsy.com * contributors may be used to endorse or promote products derived from
1513786Sjavier.bueno@metempsy.com * this software without specific prior written permission.
1613786Sjavier.bueno@metempsy.com *
1713786Sjavier.bueno@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1813786Sjavier.bueno@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1913786Sjavier.bueno@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2013786Sjavier.bueno@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2113786Sjavier.bueno@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2213786Sjavier.bueno@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2313786Sjavier.bueno@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2413786Sjavier.bueno@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2513786Sjavier.bueno@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2613786Sjavier.bueno@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2713786Sjavier.bueno@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2813786Sjavier.bueno@metempsy.com *
2913786Sjavier.bueno@metempsy.com * Authors: Stephen Hines
3013786Sjavier.bueno@metempsy.com *          Timothy M. Jones
3113786Sjavier.bueno@metempsy.com */
3213786Sjavier.bueno@metempsy.com
3313786Sjavier.bueno@metempsy.com#include "arch/power/isa_traits.hh"
3413786Sjavier.bueno@metempsy.com#include "arch/power/process.hh"
3513786Sjavier.bueno@metempsy.com#include "arch/power/types.hh"
3613786Sjavier.bueno@metempsy.com#include "base/loader/elf_object.hh"
3713786Sjavier.bueno@metempsy.com#include "base/loader/object_file.hh"
3813786Sjavier.bueno@metempsy.com#include "base/misc.hh"
3913786Sjavier.bueno@metempsy.com#include "cpu/thread_context.hh"
4013786Sjavier.bueno@metempsy.com#include "mem/page_table.hh"
4113786Sjavier.bueno@metempsy.com#include "mem/translating_port.hh"
4213786Sjavier.bueno@metempsy.com#include "sim/process_impl.hh"
4313786Sjavier.bueno@metempsy.com#include "sim/system.hh"
4413786Sjavier.bueno@metempsy.com
4513786Sjavier.bueno@metempsy.comusing namespace std;
4613786Sjavier.bueno@metempsy.comusing namespace PowerISA;
4713786Sjavier.bueno@metempsy.com
4813963Sodanrc@yahoo.com.brPowerLiveProcess::PowerLiveProcess(LiveProcessParams *params,
4913786Sjavier.bueno@metempsy.com        ObjectFile *objFile)
5013786Sjavier.bueno@metempsy.com    : LiveProcess(params, objFile)
5113786Sjavier.bueno@metempsy.com{
5213786Sjavier.bueno@metempsy.com    stack_base = 0xbf000000L;
5313786Sjavier.bueno@metempsy.com
5413786Sjavier.bueno@metempsy.com    // Set pointer for next thread stack.  Reserve 8M for main stack.
5513786Sjavier.bueno@metempsy.com    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
5613786Sjavier.bueno@metempsy.com
5713786Sjavier.bueno@metempsy.com    // Set up break point (Top of Heap)
5813786Sjavier.bueno@metempsy.com    brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
5913786Sjavier.bueno@metempsy.com    brk_point = roundUp(brk_point, VMPageSize);
6013786Sjavier.bueno@metempsy.com
6113786Sjavier.bueno@metempsy.com    // Set up region for mmaps. For now, start at bottom of kuseg space.
6213786Sjavier.bueno@metempsy.com    mmap_start = mmap_end = 0x70000000L;
6313786Sjavier.bueno@metempsy.com}
6413786Sjavier.bueno@metempsy.com
6513786Sjavier.bueno@metempsy.comvoid
6613786Sjavier.bueno@metempsy.comPowerLiveProcess::initState()
6713786Sjavier.bueno@metempsy.com{
6813786Sjavier.bueno@metempsy.com    Process::initState();
6913786Sjavier.bueno@metempsy.com
7013786Sjavier.bueno@metempsy.com    argsInit(MachineBytes, VMPageSize);
7113786Sjavier.bueno@metempsy.com}
7213786Sjavier.bueno@metempsy.com
7313786Sjavier.bueno@metempsy.comvoid
7413786Sjavier.bueno@metempsy.comPowerLiveProcess::argsInit(int intSize, int pageSize)
7513786Sjavier.bueno@metempsy.com{
7613786Sjavier.bueno@metempsy.com    typedef AuxVector<uint32_t> auxv_t;
7713786Sjavier.bueno@metempsy.com    std::vector<auxv_t> auxv;
7813963Sodanrc@yahoo.com.br
7913786Sjavier.bueno@metempsy.com    string filename;
8013786Sjavier.bueno@metempsy.com    if (argv.size() < 1)
8113786Sjavier.bueno@metempsy.com        filename = "";
8213786Sjavier.bueno@metempsy.com    else
8313963Sodanrc@yahoo.com.br        filename = argv[0];
8413786Sjavier.bueno@metempsy.com
8513786Sjavier.bueno@metempsy.com    //We want 16 byte alignment
8613786Sjavier.bueno@metempsy.com    uint64_t align = 16;
8713786Sjavier.bueno@metempsy.com
8813786Sjavier.bueno@metempsy.com    // load object file into target memory
8913786Sjavier.bueno@metempsy.com    objFile->loadSections(initVirtMem);
9013786Sjavier.bueno@metempsy.com
9113786Sjavier.bueno@metempsy.com    //Setup the auxilliary vectors. These will already have endian conversion.
9213786Sjavier.bueno@metempsy.com    //Auxilliary vectors are loaded only for elf formatted executables.
9313786Sjavier.bueno@metempsy.com    ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
9413786Sjavier.bueno@metempsy.com    if (elfObject) {
9513786Sjavier.bueno@metempsy.com        uint32_t features = 0;
9613786Sjavier.bueno@metempsy.com
9713786Sjavier.bueno@metempsy.com        //Bits which describe the system hardware capabilities
9813786Sjavier.bueno@metempsy.com        //XXX Figure out what these should be
9913963Sodanrc@yahoo.com.br        auxv.push_back(auxv_t(M5_AT_HWCAP, features));
10013786Sjavier.bueno@metempsy.com        //The system page size
10113786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_PAGESZ, PowerISA::VMPageSize));
10213786Sjavier.bueno@metempsy.com        //Frequency at which times() increments
10313786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_CLKTCK, 0x64));
10413786Sjavier.bueno@metempsy.com        // For statically linked executables, this is the virtual address of the
10513786Sjavier.bueno@metempsy.com        // program header tables if they appear in the executable image
10613786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
10713786Sjavier.bueno@metempsy.com        // This is the size of a program header entry from the elf file.
10813786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
10913786Sjavier.bueno@metempsy.com        // This is the number of program headers from the original elf file.
11013786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
11113786Sjavier.bueno@metempsy.com        //This is the address of the elf "interpreter", It should be set
11213786Sjavier.bueno@metempsy.com        //to 0 for regular executables. It should be something else
11313786Sjavier.bueno@metempsy.com        //(not sure what) for dynamic libraries.
11413786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_BASE, 0));
11513786Sjavier.bueno@metempsy.com
11613786Sjavier.bueno@metempsy.com        //XXX Figure out what this should be.
11713786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
11813786Sjavier.bueno@metempsy.com        //The entry point to the program
11913786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
12013786Sjavier.bueno@metempsy.com        //Different user and group IDs
12113786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_UID, uid()));
12213786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_EUID, euid()));
12313786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_GID, gid()));
12413786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_EGID, egid()));
12513786Sjavier.bueno@metempsy.com        //Whether to enable "secure mode" in the executable
12613786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_SECURE, 0));
12713786Sjavier.bueno@metempsy.com        //The filename of the program
12813786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_EXECFN, 0));
12913963Sodanrc@yahoo.com.br        //The string "v51" with unknown meaning
13013786Sjavier.bueno@metempsy.com        auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
13113786Sjavier.bueno@metempsy.com    }
13213786Sjavier.bueno@metempsy.com
13313786Sjavier.bueno@metempsy.com    //Figure out how big the initial stack nedes to be
13413963Sodanrc@yahoo.com.br
13513786Sjavier.bueno@metempsy.com    // A sentry NULL void pointer at the top of the stack.
13613786Sjavier.bueno@metempsy.com    int sentry_size = intSize;
13713786Sjavier.bueno@metempsy.com
13813786Sjavier.bueno@metempsy.com    string platform = "v51";
13913786Sjavier.bueno@metempsy.com    int platform_size = platform.size() + 1;
14013786Sjavier.bueno@metempsy.com
14113786Sjavier.bueno@metempsy.com    // The aux vectors are put on the stack in two groups. The first group are
14213786Sjavier.bueno@metempsy.com    // the vectors that are generated as the elf is loaded. The second group
14313786Sjavier.bueno@metempsy.com    // are the ones that were computed ahead of time and include the platform
14413786Sjavier.bueno@metempsy.com    // string.
14513786Sjavier.bueno@metempsy.com    int aux_data_size = filename.size() + 1;
14613786Sjavier.bueno@metempsy.com
14713786Sjavier.bueno@metempsy.com    int env_data_size = 0;
14813786Sjavier.bueno@metempsy.com    for (int i = 0; i < envp.size(); ++i) {
14913786Sjavier.bueno@metempsy.com        env_data_size += envp[i].size() + 1;
15013786Sjavier.bueno@metempsy.com    }
15113786Sjavier.bueno@metempsy.com    int arg_data_size = 0;
15213786Sjavier.bueno@metempsy.com    for (int i = 0; i < argv.size(); ++i) {
15313786Sjavier.bueno@metempsy.com        arg_data_size += argv[i].size() + 1;
15413786Sjavier.bueno@metempsy.com    }
15513786Sjavier.bueno@metempsy.com
15613786Sjavier.bueno@metempsy.com    int info_block_size =
15713786Sjavier.bueno@metempsy.com        sentry_size + env_data_size + arg_data_size +
15813786Sjavier.bueno@metempsy.com        aux_data_size + platform_size;
15913786Sjavier.bueno@metempsy.com
16013786Sjavier.bueno@metempsy.com    //Each auxilliary vector is two 4 byte words
16113786Sjavier.bueno@metempsy.com    int aux_array_size = intSize * 2 * (auxv.size() + 1);
16213786Sjavier.bueno@metempsy.com
16313786Sjavier.bueno@metempsy.com    int envp_array_size = intSize * (envp.size() + 1);
16413786Sjavier.bueno@metempsy.com    int argv_array_size = intSize * (argv.size() + 1);
16513786Sjavier.bueno@metempsy.com
16613786Sjavier.bueno@metempsy.com    int argc_size = intSize;
16713786Sjavier.bueno@metempsy.com
16813786Sjavier.bueno@metempsy.com    //Figure out the size of the contents of the actual initial frame
16913786Sjavier.bueno@metempsy.com    int frame_size =
17013786Sjavier.bueno@metempsy.com        info_block_size +
17113786Sjavier.bueno@metempsy.com        aux_array_size +
17213786Sjavier.bueno@metempsy.com        envp_array_size +
17313786Sjavier.bueno@metempsy.com        argv_array_size +
17413786Sjavier.bueno@metempsy.com        argc_size;
17513786Sjavier.bueno@metempsy.com
17613786Sjavier.bueno@metempsy.com    //There needs to be padding after the auxiliary vector data so that the
17713786Sjavier.bueno@metempsy.com    //very bottom of the stack is aligned properly.
17813786Sjavier.bueno@metempsy.com    int partial_size = frame_size;
17913786Sjavier.bueno@metempsy.com    int aligned_partial_size = roundUp(partial_size, align);
18013786Sjavier.bueno@metempsy.com    int aux_padding = aligned_partial_size - partial_size;
18113786Sjavier.bueno@metempsy.com
18213786Sjavier.bueno@metempsy.com    int space_needed = frame_size + aux_padding;
18313786Sjavier.bueno@metempsy.com
18413786Sjavier.bueno@metempsy.com    stack_min = stack_base - space_needed;
18513786Sjavier.bueno@metempsy.com    stack_min = roundDown(stack_min, align);
18613786Sjavier.bueno@metempsy.com    stack_size = stack_base - stack_min;
18713786Sjavier.bueno@metempsy.com
18813786Sjavier.bueno@metempsy.com    // map memory
18913786Sjavier.bueno@metempsy.com    pTable->allocate(roundDown(stack_min, pageSize),
19013786Sjavier.bueno@metempsy.com                     roundUp(stack_size, pageSize));
19113786Sjavier.bueno@metempsy.com
19213786Sjavier.bueno@metempsy.com    // map out initial stack contents
19313786Sjavier.bueno@metempsy.com    uint32_t sentry_base = stack_base - sentry_size;
19413786Sjavier.bueno@metempsy.com    uint32_t aux_data_base = sentry_base - aux_data_size;
19513786Sjavier.bueno@metempsy.com    uint32_t env_data_base = aux_data_base - env_data_size;
19613786Sjavier.bueno@metempsy.com    uint32_t arg_data_base = env_data_base - arg_data_size;
19713786Sjavier.bueno@metempsy.com    uint32_t platform_base = arg_data_base - platform_size;
198    uint32_t auxv_array_base = platform_base - aux_array_size - aux_padding;
199    uint32_t envp_array_base = auxv_array_base - envp_array_size;
200    uint32_t argv_array_base = envp_array_base - argv_array_size;
201    uint32_t argc_base = argv_array_base - argc_size;
202
203    DPRINTF(Stack, "The addresses of items on the initial stack:\n");
204    DPRINTF(Stack, "0x%x - aux data\n", aux_data_base);
205    DPRINTF(Stack, "0x%x - env data\n", env_data_base);
206    DPRINTF(Stack, "0x%x - arg data\n", arg_data_base);
207    DPRINTF(Stack, "0x%x - platform base\n", platform_base);
208    DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base);
209    DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
210    DPRINTF(Stack, "0x%x - argv array\n", argv_array_base);
211    DPRINTF(Stack, "0x%x - argc \n", argc_base);
212    DPRINTF(Stack, "0x%x - stack min\n", stack_min);
213
214    // write contents to stack
215
216    // figure out argc
217    uint32_t argc = argv.size();
218    uint32_t guestArgc = PowerISA::htog(argc);
219
220    //Write out the sentry void *
221    uint32_t sentry_NULL = 0;
222    initVirtMem->writeBlob(sentry_base,
223            (uint8_t*)&sentry_NULL, sentry_size);
224
225    //Fix up the aux vectors which point to other data
226    for (int i = auxv.size() - 1; i >= 0; i--) {
227        if (auxv[i].a_type == M5_AT_PLATFORM) {
228            auxv[i].a_val = platform_base;
229            initVirtMem->writeString(platform_base, platform.c_str());
230        } else if (auxv[i].a_type == M5_AT_EXECFN) {
231            auxv[i].a_val = aux_data_base;
232            initVirtMem->writeString(aux_data_base, filename.c_str());
233        }
234    }
235
236    //Copy the aux stuff
237    for (int x = 0; x < auxv.size(); x++)
238    {
239        initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
240                (uint8_t*)&(auxv[x].a_type), intSize);
241        initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
242                (uint8_t*)&(auxv[x].a_val), intSize);
243    }
244    //Write out the terminating zeroed auxilliary vector
245    const uint64_t zero = 0;
246    initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
247            (uint8_t*)&zero, 2 * intSize);
248
249    copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
250    copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
251
252    initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
253
254    ThreadContext *tc = system->getThreadContext(contextIds[0]);
255
256    //Set the stack pointer register
257    tc->setIntReg(StackPointerReg, stack_min);
258
259    Addr prog_entry = objFile->entryPoint();
260    tc->setPC(prog_entry);
261    tc->setNextPC(prog_entry + sizeof(MachInst));
262
263    //Align the "stack_min" to a page boundary.
264    stack_min = roundDown(stack_min, pageSize);
265}
266
267PowerISA::IntReg
268PowerLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
269{
270    assert(i < 5);
271    return tc->readIntReg(ArgumentReg0 + i++);
272}
273
274void
275PowerLiveProcess::setSyscallArg(ThreadContext *tc,
276        int i, PowerISA::IntReg val)
277{
278    assert(i < 5);
279    tc->setIntReg(ArgumentReg0 + i, val);
280}
281
282void
283PowerLiveProcess::setSyscallReturn(ThreadContext *tc,
284        SyscallReturn return_value)
285{
286    Cr cr = tc->readIntReg(INTREG_CR);
287    if (return_value.successful()) {
288        cr.cr0.so = 0;
289    } else {
290        cr.cr0.so = 1;
291    }
292    tc->setIntReg(INTREG_CR, cr);
293    tc->setIntReg(ReturnValueReg, return_value.value());
294}
295