process.cc revision 12394:7c5a2e374998
111828Sjason@lowepower.com/*
210107Sradhika.jagtap@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
310107Sradhika.jagtap@ARM.com * Copyright (c) 2016 The University of Virginia
410107Sradhika.jagtap@ARM.com * All rights reserved.
510107Sradhika.jagtap@ARM.com *
610107Sradhika.jagtap@ARM.com * Redistribution and use in source and binary forms, with or without
710107Sradhika.jagtap@ARM.com * modification, are permitted provided that the following conditions are
810107Sradhika.jagtap@ARM.com * met: redistributions of source code must retain the above copyright
910107Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer;
1010107Sradhika.jagtap@ARM.com * redistributions in binary form must reproduce the above copyright
1110107Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer in the
1210107Sradhika.jagtap@ARM.com * documentation and/or other materials provided with the distribution;
1310107Sradhika.jagtap@ARM.com * neither the name of the copyright holders nor the names of its
1410107Sradhika.jagtap@ARM.com * contributors may be used to endorse or promote products derived from
1510107Sradhika.jagtap@ARM.com * this software without specific prior written permission.
1610107Sradhika.jagtap@ARM.com *
1710107Sradhika.jagtap@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1810107Sradhika.jagtap@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1910107Sradhika.jagtap@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2010107Sradhika.jagtap@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2110107Sradhika.jagtap@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2210107Sradhika.jagtap@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2310107Sradhika.jagtap@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2410107Sradhika.jagtap@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2510107Sradhika.jagtap@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2610107Sradhika.jagtap@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2710107Sradhika.jagtap@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2810107Sradhika.jagtap@ARM.com *
2910107Sradhika.jagtap@ARM.com * Authors: Gabe Black
3010107Sradhika.jagtap@ARM.com *          Ali Saidi
3110107Sradhika.jagtap@ARM.com *          Korey Sewell
3210107Sradhika.jagtap@ARM.com *          Alec Roelke
3310107Sradhika.jagtap@ARM.com */
3410107Sradhika.jagtap@ARM.com#include "arch/riscv/process.hh"
3510107Sradhika.jagtap@ARM.com
3610107Sradhika.jagtap@ARM.com#include <algorithm>
3710107Sradhika.jagtap@ARM.com#include <cstddef>
3810107Sradhika.jagtap@ARM.com#include <iostream>
3910107Sradhika.jagtap@ARM.com#include <iterator>
4010107Sradhika.jagtap@ARM.com#include <map>
4110107Sradhika.jagtap@ARM.com#include <string>
4210107Sradhika.jagtap@ARM.com#include <vector>
4310107Sradhika.jagtap@ARM.com
4410107Sradhika.jagtap@ARM.com#include "arch/riscv/isa_traits.hh"
4510107Sradhika.jagtap@ARM.com#include "base/loader/elf_object.hh"
4610107Sradhika.jagtap@ARM.com#include "base/loader/object_file.hh"
4710107Sradhika.jagtap@ARM.com#include "base/logging.hh"
4810107Sradhika.jagtap@ARM.com#include "base/random.hh"
4910107Sradhika.jagtap@ARM.com#include "cpu/thread_context.hh"
5010107Sradhika.jagtap@ARM.com#include "debug/Stack.hh"
5110107Sradhika.jagtap@ARM.com#include "mem/page_table.hh"
5210107Sradhika.jagtap@ARM.com#include "params/Process.hh"
5310107Sradhika.jagtap@ARM.com#include "sim/aux_vector.hh"
5410107Sradhika.jagtap@ARM.com#include "sim/process.hh"
5510107Sradhika.jagtap@ARM.com#include "sim/process_impl.hh"
5610107Sradhika.jagtap@ARM.com#include "sim/syscall_return.hh"
5710107Sradhika.jagtap@ARM.com#include "sim/system.hh"
5810107Sradhika.jagtap@ARM.com
5910107Sradhika.jagtap@ARM.comusing namespace std;
6010107Sradhika.jagtap@ARM.comusing namespace RiscvISA;
6110107Sradhika.jagtap@ARM.com
6210107Sradhika.jagtap@ARM.comRiscvProcess::RiscvProcess(ProcessParams * params,
6310107Sradhika.jagtap@ARM.com    ObjectFile *objFile) : Process(params, objFile)
6410107Sradhika.jagtap@ARM.com{
6510107Sradhika.jagtap@ARM.com    const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
6610107Sradhika.jagtap@ARM.com    const Addr max_stack_size = 8 * 1024 * 1024;
6710107Sradhika.jagtap@ARM.com    const Addr next_thread_stack_base = stack_base - max_stack_size;
6810107Sradhika.jagtap@ARM.com    const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(),
6910107Sradhika.jagtap@ARM.com            PageBytes);
7010107Sradhika.jagtap@ARM.com    const Addr mmap_end = 0x4000000000000000L;
7110107Sradhika.jagtap@ARM.com    memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
7210107Sradhika.jagtap@ARM.com            next_thread_stack_base, mmap_end);
7310107Sradhika.jagtap@ARM.com}
7410269Sradhika.jagtap@ARM.com
7510107Sradhika.jagtap@ARM.comvoid
7610107Sradhika.jagtap@ARM.comRiscvProcess::initState()
7710269Sradhika.jagtap@ARM.com{
7810269Sradhika.jagtap@ARM.com    Process::initState();
7910269Sradhika.jagtap@ARM.com
8010269Sradhika.jagtap@ARM.com    argsInit<uint64_t>(PageBytes);
8110269Sradhika.jagtap@ARM.com}
8210269Sradhika.jagtap@ARM.com
8310269Sradhika.jagtap@ARM.comtemplate<class IntType> void
8410269Sradhika.jagtap@ARM.comRiscvProcess::argsInit(int pageSize)
8510269Sradhika.jagtap@ARM.com{
8610269Sradhika.jagtap@ARM.com    const int RandomBytes = 16;
8710269Sradhika.jagtap@ARM.com
8810269Sradhika.jagtap@ARM.com    updateBias();
8910269Sradhika.jagtap@ARM.com    objFile->loadSections(initVirtMem);
9010269Sradhika.jagtap@ARM.com    ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile);
9110269Sradhika.jagtap@ARM.com    memState->setStackMin(memState->getStackBase());
9210269Sradhika.jagtap@ARM.com
9310269Sradhika.jagtap@ARM.com    // Determine stack size and populate auxv
9410269Sradhika.jagtap@ARM.com    Addr stack_top = memState->getStackMin();
9510269Sradhika.jagtap@ARM.com    stack_top -= RandomBytes;
9610269Sradhika.jagtap@ARM.com    for (const string& arg: argv)
9710269Sradhika.jagtap@ARM.com        stack_top -= arg.size() + 1;
9810269Sradhika.jagtap@ARM.com    for (const string& env: envp)
9910269Sradhika.jagtap@ARM.com        stack_top -= env.size() + 1;
10010269Sradhika.jagtap@ARM.com    stack_top &= -sizeof(Addr);
10110107Sradhika.jagtap@ARM.com
10210107Sradhika.jagtap@ARM.com    vector<AuxVector<IntType>> auxv;
10310107Sradhika.jagtap@ARM.com    if (elfObject != nullptr) {
10410107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_ENTRY, objFile->entryPoint()});
10510107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_PHNUM, elfObject->programHeaderCount()});
10610107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_PHENT, elfObject->programHeaderSize()});
10710107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_PHDR, elfObject->programHeaderTable()});
10810107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_PAGESZ, PageBytes});
10910107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_SECURE, 0});
11010107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_RANDOM, stack_top});
11110107Sradhika.jagtap@ARM.com        auxv.push_back({M5_AT_NULL, 0});
11210107Sradhika.jagtap@ARM.com    }
11310107Sradhika.jagtap@ARM.com    stack_top -= (1 + argv.size()) * sizeof(Addr) +
11410107Sradhika.jagtap@ARM.com                   (1 + envp.size()) * sizeof(Addr) +
11510107Sradhika.jagtap@ARM.com                   sizeof(Addr) + 2 * sizeof(IntType) * auxv.size();
11610107Sradhika.jagtap@ARM.com    stack_top &= -2*sizeof(Addr);
11710107Sradhika.jagtap@ARM.com    memState->setStackSize(memState->getStackBase() - stack_top);
11810107Sradhika.jagtap@ARM.com    allocateMem(roundDown(stack_top, pageSize),
11910107Sradhika.jagtap@ARM.com            roundUp(memState->getStackSize(), pageSize));
12010107Sradhika.jagtap@ARM.com
12110107Sradhika.jagtap@ARM.com    // Copy random bytes (for AT_RANDOM) to stack
12210107Sradhika.jagtap@ARM.com    memState->setStackMin(memState->getStackMin() - RandomBytes);
12310107Sradhika.jagtap@ARM.com    uint8_t at_random[RandomBytes];
12410107Sradhika.jagtap@ARM.com    generate(begin(at_random), end(at_random),
12510107Sradhika.jagtap@ARM.com             [&]{ return random_mt.random(0, 0xFF); });
12612208Sgabeblack@google.com    initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes);
12712208Sgabeblack@google.com
12812208Sgabeblack@google.com    // Copy argv to stack
12912208Sgabeblack@google.com    vector<Addr> argPointers;
13010107Sradhika.jagtap@ARM.com    for (const string& arg: argv) {
13110107Sradhika.jagtap@ARM.com        memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
13210107Sradhika.jagtap@ARM.com        initVirtMem.writeString(memState->getStackMin(), arg.c_str());
13310107Sradhika.jagtap@ARM.com        argPointers.push_back(memState->getStackMin());
13410107Sradhika.jagtap@ARM.com        if (DTRACE(Stack)) {
13510107Sradhika.jagtap@ARM.com            string wrote;
13610107Sradhika.jagtap@ARM.com            initVirtMem.readString(wrote, argPointers.back());
13710107Sradhika.jagtap@ARM.com            DPRINTFN("Wrote arg \"%s\" to address %p\n",
13810107Sradhika.jagtap@ARM.com                    wrote, (void*)memState->getStackMin());
13910107Sradhika.jagtap@ARM.com        }
14010107Sradhika.jagtap@ARM.com    }
14110107Sradhika.jagtap@ARM.com    argPointers.push_back(0);
14210107Sradhika.jagtap@ARM.com
14310107Sradhika.jagtap@ARM.com    // Copy envp to stack
14410107Sradhika.jagtap@ARM.com    vector<Addr> envPointers;
14510107Sradhika.jagtap@ARM.com    for (const string& env: envp) {
14610107Sradhika.jagtap@ARM.com        memState->setStackMin(memState->getStackMin() - (env.size() + 1));
14710107Sradhika.jagtap@ARM.com        initVirtMem.writeString(memState->getStackMin(), env.c_str());
14810107Sradhika.jagtap@ARM.com        envPointers.push_back(memState->getStackMin());
14910107Sradhika.jagtap@ARM.com        DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
15010107Sradhika.jagtap@ARM.com                env, (void*)memState->getStackMin());
15110107Sradhika.jagtap@ARM.com    }
15210107Sradhika.jagtap@ARM.com    envPointers.push_back(0);
15310107Sradhika.jagtap@ARM.com
15410107Sradhika.jagtap@ARM.com    // Align stack
15510107Sradhika.jagtap@ARM.com    memState->setStackMin(memState->getStackMin() & -sizeof(Addr));
15610107Sradhika.jagtap@ARM.com
15710107Sradhika.jagtap@ARM.com    // Calculate bottom of stack
15810107Sradhika.jagtap@ARM.com    memState->setStackMin(memState->getStackMin() -
15910107Sradhika.jagtap@ARM.com            ((1 + argv.size()) * sizeof(Addr) +
16010107Sradhika.jagtap@ARM.com             (1 + envp.size()) * sizeof(Addr) +
16110107Sradhika.jagtap@ARM.com             sizeof(Addr) + 2 * sizeof(IntType) * auxv.size()));
16210107Sradhika.jagtap@ARM.com    memState->setStackMin(memState->getStackMin() & -2*sizeof(Addr));
16310107Sradhika.jagtap@ARM.com    Addr sp = memState->getStackMin();
16410107Sradhika.jagtap@ARM.com    const auto pushOntoStack =
16510107Sradhika.jagtap@ARM.com        [this, &sp](const uint8_t* data, const size_t size) {
16610107Sradhika.jagtap@ARM.com            initVirtMem.writeBlob(sp, data, size);
167            sp += size;
168        };
169
170    // Push argc and argv pointers onto stack
171    IntType argc = htog((IntType)argv.size());
172    DPRINTF(Stack, "Wrote argc %d to address %p\n",
173            argv.size(), (void*)sp);
174    pushOntoStack((uint8_t*)&argc, sizeof(IntType));
175    for (const Addr& argPointer: argPointers) {
176        DPRINTF(Stack, "Wrote argv pointer %p to address %p\n",
177                (void*)argPointer, (void*)sp);
178        pushOntoStack((uint8_t*)&argPointer, sizeof(Addr));
179    }
180
181    // Push env pointers onto stack
182    for (const Addr& envPointer: envPointers) {
183        DPRINTF(Stack, "Wrote envp pointer %p to address %p\n",
184                (void*)envPointer, (void*)sp);
185        pushOntoStack((uint8_t*)&envPointer, sizeof(Addr));
186    }
187
188    // Push aux vector onto stack
189    std::map<IntType, string> aux_keys = {
190        {M5_AT_ENTRY, "M5_AT_ENTRY"},
191        {M5_AT_PHNUM, "M5_AT_PHNUM"},
192        {M5_AT_PHENT, "M5_AT_PHENT"},
193        {M5_AT_PHDR, "M5_AT_PHDR"},
194        {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
195        {M5_AT_SECURE, "M5_AT_SECURE"},
196        {M5_AT_RANDOM, "M5_AT_RANDOM"},
197        {M5_AT_NULL, "M5_AT_NULL"}
198    };
199    for (const AuxVector<IntType>& aux: auxv) {
200        DPRINTF(Stack, "Wrote aux key %s to address %p\n",
201                aux_keys[aux.a_type], (void*)sp);
202        pushOntoStack((uint8_t*)&aux.a_type, sizeof(IntType));
203        DPRINTF(Stack, "Wrote aux value %x to address %p\n",
204                aux.a_val, (void*)sp);
205        pushOntoStack((uint8_t*)&aux.a_val, sizeof(IntType));
206    }
207
208    ThreadContext *tc = system->getThreadContext(contextIds[0]);
209    tc->setIntReg(StackPointerReg, memState->getStackMin());
210    tc->pcState(getStartPC());
211
212    memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
213}
214
215RiscvISA::IntReg
216RiscvProcess::getSyscallArg(ThreadContext *tc, int &i)
217{
218    // RISC-V only has four system call argument registers by convention, so
219    // if a larger index is requested return 0
220    RiscvISA::IntReg retval = 0;
221    if (i < 4)
222        retval = tc->readIntReg(SyscallArgumentRegs[i]);
223    i++;
224    return retval;
225}
226
227void
228RiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
229{
230    tc->setIntReg(SyscallArgumentRegs[i], val);
231}
232
233void
234RiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
235{
236    if (sysret.successful()) {
237        // no error
238        tc->setIntReg(SyscallPseudoReturnReg, sysret.returnValue());
239    } else {
240        // got an error, return details
241        tc->setIntReg(SyscallPseudoReturnReg, sysret.errnoValue());
242    }
243}
244