process.cc revision 12431
12600SN/A/* 22600SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 32600SN/A * Copyright (c) 2016 The University of Virginia 42600SN/A * All rights reserved. 52600SN/A * 62600SN/A * Redistribution and use in source and binary forms, with or without 72600SN/A * modification, are permitted provided that the following conditions are 82600SN/A * met: redistributions of source code must retain the above copyright 92600SN/A * notice, this list of conditions and the following disclaimer; 102600SN/A * redistributions in binary form must reproduce the above copyright 112600SN/A * notice, this list of conditions and the following disclaimer in the 122600SN/A * documentation and/or other materials provided with the distribution; 132600SN/A * neither the name of the copyright holders nor the names of its 142600SN/A * contributors may be used to endorse or promote products derived from 152600SN/A * this software without specific prior written permission. 162600SN/A * 172600SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182600SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192600SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202600SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212600SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222600SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232600SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242600SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252600SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262600SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272665Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292600SN/A * Authors: Gabe Black 302600SN/A * Ali Saidi 312600SN/A * Korey Sewell 322600SN/A * Alec Roelke 332600SN/A */ 342600SN/A#include "arch/riscv/process.hh" 352600SN/A 362600SN/A#include <algorithm> 372600SN/A#include <cstddef> 382600SN/A#include <iostream> 392600SN/A#include <iterator> 402600SN/A#include <map> 412600SN/A#include <string> 422600SN/A#include <vector> 432600SN/A 442600SN/A#include "arch/riscv/isa_traits.hh" 452600SN/A#include "base/loader/elf_object.hh" 462600SN/A#include "base/loader/object_file.hh" 472600SN/A#include "base/logging.hh" 482600SN/A#include "base/random.hh" 492600SN/A#include "cpu/thread_context.hh" 502600SN/A#include "debug/Stack.hh" 512600SN/A#include "mem/page_table.hh" 522600SN/A#include "params/Process.hh" 532600SN/A#include "sim/aux_vector.hh" 542600SN/A#include "sim/process.hh" 552600SN/A#include "sim/process_impl.hh" 562600SN/A#include "sim/syscall_return.hh" 572600SN/A#include "sim/system.hh" 582600SN/A 592600SN/Ausing namespace std; 602600SN/Ausing namespace RiscvISA; 612600SN/A 622600SN/ARiscvProcess::RiscvProcess(ProcessParams *params, ObjectFile *objFile) : 632600SN/A Process(params, new FuncPageTable(params->name, params->pid), objFile) 642600SN/A{ 652600SN/A fatal_if(!params->useArchPT, "Arch page tables not implemented."); 662600SN/A const Addr stack_base = 0x7FFFFFFFFFFFFFFFL; 672600SN/A const Addr max_stack_size = 8 * 1024 * 1024; 682600SN/A const Addr next_thread_stack_base = stack_base - max_stack_size; 692600SN/A const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(), 702600SN/A PageBytes); 712600SN/A const Addr mmap_end = 0x4000000000000000L; 722600SN/A memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, 732600SN/A next_thread_stack_base, mmap_end); 742600SN/A} 752600SN/A 762600SN/Avoid 772600SN/ARiscvProcess::initState() 782600SN/A{ 792600SN/A Process::initState(); 802600SN/A 812600SN/A argsInit<uint64_t>(PageBytes); 822600SN/A} 832600SN/A 842600SN/Atemplate<class IntType> void 852600SN/ARiscvProcess::argsInit(int pageSize) 862600SN/A{ 872600SN/A const int RandomBytes = 16; 882600SN/A 892600SN/A updateBias(); 902600SN/A objFile->loadSections(initVirtMem); 912600SN/A ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile); 922600SN/A memState->setStackMin(memState->getStackBase()); 932600SN/A 942600SN/A // Determine stack size and populate auxv 952600SN/A Addr stack_top = memState->getStackMin(); 962600SN/A stack_top -= RandomBytes; 972600SN/A for (const string& arg: argv) 982600SN/A stack_top -= arg.size() + 1; 992600SN/A for (const string& env: envp) 1002600SN/A stack_top -= env.size() + 1; 1012600SN/A stack_top &= -sizeof(Addr); 1022600SN/A 1032600SN/A vector<AuxVector<IntType>> auxv; 1042600SN/A if (elfObject != nullptr) { 1052600SN/A auxv.push_back({M5_AT_ENTRY, objFile->entryPoint()}); 1062600SN/A auxv.push_back({M5_AT_PHNUM, elfObject->programHeaderCount()}); 1072600SN/A auxv.push_back({M5_AT_PHENT, elfObject->programHeaderSize()}); 1082600SN/A auxv.push_back({M5_AT_PHDR, elfObject->programHeaderTable()}); 1092600SN/A auxv.push_back({M5_AT_PAGESZ, PageBytes}); 1102600SN/A auxv.push_back({M5_AT_SECURE, 0}); 1112600SN/A auxv.push_back({M5_AT_RANDOM, stack_top}); 1122600SN/A auxv.push_back({M5_AT_NULL, 0}); 1132600SN/A } 1142600SN/A stack_top -= (1 + argv.size()) * sizeof(Addr) + 1152600SN/A (1 + envp.size()) * sizeof(Addr) + 1162600SN/A sizeof(Addr) + 2 * sizeof(IntType) * auxv.size(); 1172600SN/A stack_top &= -2*sizeof(Addr); 1182600SN/A memState->setStackSize(memState->getStackBase() - stack_top); 1192600SN/A allocateMem(roundDown(stack_top, pageSize), 1202600SN/A roundUp(memState->getStackSize(), pageSize)); 1212600SN/A 1222600SN/A // Copy random bytes (for AT_RANDOM) to stack 1232600SN/A memState->setStackMin(memState->getStackMin() - RandomBytes); 1242600SN/A uint8_t at_random[RandomBytes]; 1252600SN/A generate(begin(at_random), end(at_random), 1262600SN/A [&]{ return random_mt.random(0, 0xFF); }); 1272600SN/A initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes); 1282600SN/A 1292600SN/A // Copy argv to stack 1302600SN/A vector<Addr> argPointers; 1312600SN/A for (const string& arg: argv) { 1322600SN/A memState->setStackMin(memState->getStackMin() - (arg.size() + 1)); 1332600SN/A initVirtMem.writeString(memState->getStackMin(), arg.c_str()); 1342600SN/A argPointers.push_back(memState->getStackMin()); 1352600SN/A if (DTRACE(Stack)) { 1362600SN/A string wrote; 1372600SN/A initVirtMem.readString(wrote, argPointers.back()); 1382600SN/A DPRINTFN("Wrote arg \"%s\" to address %p\n", 1392600SN/A wrote, (void*)memState->getStackMin()); 1402600SN/A } 1412600SN/A } 1422600SN/A argPointers.push_back(0); 1432600SN/A 1442600SN/A // Copy envp to stack 1452600SN/A vector<Addr> envPointers; 1462600SN/A for (const string& env: envp) { 1472600SN/A memState->setStackMin(memState->getStackMin() - (env.size() + 1)); 1482600SN/A initVirtMem.writeString(memState->getStackMin(), env.c_str()); 1492600SN/A envPointers.push_back(memState->getStackMin()); 1502600SN/A DPRINTF(Stack, "Wrote env \"%s\" to address %p\n", 1512600SN/A env, (void*)memState->getStackMin()); 1522600SN/A } 1532600SN/A envPointers.push_back(0); 1542600SN/A 1552600SN/A // Align stack 1562600SN/A memState->setStackMin(memState->getStackMin() & -sizeof(Addr)); 1572600SN/A 1582600SN/A // Calculate bottom of stack 1592600SN/A memState->setStackMin(memState->getStackMin() - 1602600SN/A ((1 + argv.size()) * sizeof(Addr) + 1612600SN/A (1 + envp.size()) * sizeof(Addr) + 1622600SN/A sizeof(Addr) + 2 * sizeof(IntType) * auxv.size())); 1632600SN/A memState->setStackMin(memState->getStackMin() & -2*sizeof(Addr)); 1642600SN/A Addr sp = memState->getStackMin(); 1652600SN/A const auto pushOntoStack = 1662600SN/A [this, &sp](const uint8_t* data, const size_t size) { 1672600SN/A initVirtMem.writeBlob(sp, data, size); 1682600SN/A sp += size; 1692600SN/A }; 1702600SN/A 1712600SN/A // Push argc and argv pointers onto stack 1722600SN/A IntType argc = htog((IntType)argv.size()); 1732600SN/A DPRINTF(Stack, "Wrote argc %d to address %p\n", 1742600SN/A argv.size(), (void*)sp); 1752600SN/A pushOntoStack((uint8_t*)&argc, sizeof(IntType)); 1762600SN/A for (const Addr& argPointer: argPointers) { 1772600SN/A DPRINTF(Stack, "Wrote argv pointer %p to address %p\n", 1782600SN/A (void*)argPointer, (void*)sp); 1792600SN/A pushOntoStack((uint8_t*)&argPointer, sizeof(Addr)); 1802600SN/A } 1812600SN/A 1822600SN/A // Push env pointers onto stack 1832600SN/A for (const Addr& envPointer: envPointers) { 1842600SN/A DPRINTF(Stack, "Wrote envp pointer %p to address %p\n", 1852600SN/A (void*)envPointer, (void*)sp); 1862600SN/A pushOntoStack((uint8_t*)&envPointer, sizeof(Addr)); 1872600SN/A } 1882600SN/A 1892600SN/A // Push aux vector onto stack 1902600SN/A std::map<IntType, string> aux_keys = { 1912600SN/A {M5_AT_ENTRY, "M5_AT_ENTRY"}, 1922600SN/A {M5_AT_PHNUM, "M5_AT_PHNUM"}, 1932600SN/A {M5_AT_PHENT, "M5_AT_PHENT"}, 1942600SN/A {M5_AT_PHDR, "M5_AT_PHDR"}, 1952600SN/A {M5_AT_PAGESZ, "M5_AT_PAGESZ"}, 1962600SN/A {M5_AT_SECURE, "M5_AT_SECURE"}, 1972600SN/A {M5_AT_RANDOM, "M5_AT_RANDOM"}, 1982600SN/A {M5_AT_NULL, "M5_AT_NULL"} 1992600SN/A }; 2002600SN/A for (const AuxVector<IntType>& aux: auxv) { 2012600SN/A DPRINTF(Stack, "Wrote aux key %s to address %p\n", 2022600SN/A aux_keys[aux.a_type], (void*)sp); 2032600SN/A pushOntoStack((uint8_t*)&aux.a_type, sizeof(IntType)); 2042600SN/A DPRINTF(Stack, "Wrote aux value %x to address %p\n", 2052600SN/A aux.a_val, (void*)sp); 2062600SN/A pushOntoStack((uint8_t*)&aux.a_val, sizeof(IntType)); 2072600SN/A } 2082600SN/A 2092600SN/A ThreadContext *tc = system->getThreadContext(contextIds[0]); 2102600SN/A tc->setIntReg(StackPointerReg, memState->getStackMin()); 2112600SN/A tc->pcState(getStartPC()); 2122600SN/A 2132600SN/A memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); 2142600SN/A} 2152600SN/A 2162600SN/ARiscvISA::IntReg 2172600SN/ARiscvProcess::getSyscallArg(ThreadContext *tc, int &i) 2182600SN/A{ 2192600SN/A // If a larger index is requested than there are syscall argument 2202600SN/A // registers, return 0 2212600SN/A RiscvISA::IntReg retval = 0; 2222600SN/A if (i < SyscallArgumentRegs.size()) 2232600SN/A retval = tc->readIntReg(SyscallArgumentRegs[i]); 2242600SN/A i++; 2252600SN/A return retval; 2262600SN/A} 2272600SN/A 2282600SN/Avoid 2292600SN/ARiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val) 2302600SN/A{ 2312600SN/A tc->setIntReg(SyscallArgumentRegs[i], val); 2322600SN/A} 2332600SN/A 2342600SN/Avoid 2352600SN/ARiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 2362600SN/A{ 2372600SN/A if (sysret.successful()) { 2382600SN/A // no error 2392600SN/A tc->setIntReg(SyscallPseudoReturnReg, sysret.returnValue()); 2402600SN/A } else { 2412600SN/A // got an error, return details 2422600SN/A tc->setIntReg(SyscallPseudoReturnReg, sysret.errnoValue()); 2432600SN/A } 2442600SN/A} 2452600SN/A