process.cc revision 14139
12623SN/A/* 29608Sandreas.hansson@arm.com * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. 39442SAndreas.Sandberg@ARM.com * Copyright (c) 2012 ARM Limited 49442SAndreas.Sandberg@ARM.com * All rights reserved 59442SAndreas.Sandberg@ARM.com * 69442SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 79442SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 89442SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 99442SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 109442SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 119442SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 129442SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 139442SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 142623SN/A * 152623SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 162623SN/A * All rights reserved. 172623SN/A * 182623SN/A * Redistribution and use in source and binary forms, with or without 192623SN/A * modification, are permitted provided that the following conditions are 202623SN/A * met: redistributions of source code must retain the above copyright 212623SN/A * notice, this list of conditions and the following disclaimer; 222623SN/A * redistributions in binary form must reproduce the above copyright 232623SN/A * notice, this list of conditions and the following disclaimer in the 242623SN/A * documentation and/or other materials provided with the distribution; 252623SN/A * neither the name of the copyright holders nor the names of its 262623SN/A * contributors may be used to endorse or promote products derived from 272623SN/A * this software without specific prior written permission. 282623SN/A * 292623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392665Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402665Ssaidi@eecs.umich.edu * 412623SN/A * Authors: Nathan Binkert 422623SN/A * Steve Reinhardt 432623SN/A * Ali Saidi 442623SN/A * Brandon Potter 452623SN/A */ 462623SN/A 476973Stjones1@inf.ed.ac.uk#include "sim/process.hh" 485529Snate@binkert.org 495529Snate@binkert.org#include <fcntl.h> 502623SN/A#include <unistd.h> 512623SN/A 522623SN/A#include <array> 532623SN/A#include <climits> 545529Snate@binkert.org#include <csignal> 552623SN/A#include <map> 562623SN/A#include <string> 572623SN/A#include <vector> 582623SN/A 592623SN/A#include "base/intmath.hh" 602623SN/A#include "base/loader/object_file.hh" 615728Sgblack@eecs.umich.edu#include "base/loader/symtab.hh" 625728Sgblack@eecs.umich.edu#include "base/statistics.hh" 635728Sgblack@eecs.umich.edu#include "config/the_isa.hh" 645728Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 655728Sgblack@eecs.umich.edu#include "mem/page_table.hh" 665728Sgblack@eecs.umich.edu#include "mem/se_translating_port_proxy.hh" 675728Sgblack@eecs.umich.edu#include "params/Process.hh" 685728Sgblack@eecs.umich.edu#include "sim/emul_driver.hh" 695728Sgblack@eecs.umich.edu#include "sim/fd_array.hh" 705728Sgblack@eecs.umich.edu#include "sim/fd_entry.hh" 715728Sgblack@eecs.umich.edu#include "sim/redirect_path.hh" 725728Sgblack@eecs.umich.edu#include "sim/syscall_desc.hh" 735728Sgblack@eecs.umich.edu#include "sim/system.hh" 745728Sgblack@eecs.umich.edu 755728Sgblack@eecs.umich.eduusing namespace std; 765728Sgblack@eecs.umich.eduusing namespace TheISA; 775728Sgblack@eecs.umich.edu 785728Sgblack@eecs.umich.edustatic std::string 795728Sgblack@eecs.umich.edunormalize(std::string& directory) 805728Sgblack@eecs.umich.edu{ 815728Sgblack@eecs.umich.edu if (directory.back() != '/') 825728Sgblack@eecs.umich.edu directory += '/'; 835728Sgblack@eecs.umich.edu return directory; 845728Sgblack@eecs.umich.edu} 855728Sgblack@eecs.umich.edu 865728Sgblack@eecs.umich.eduProcess::Process(ProcessParams *params, EmulationPageTable *pTable, 875728Sgblack@eecs.umich.edu ObjectFile *obj_file) 885728Sgblack@eecs.umich.edu : SimObject(params), system(params->system), 895728Sgblack@eecs.umich.edu useArchPT(params->useArchPT), 905728Sgblack@eecs.umich.edu kvmInSE(params->kvmInSE), 915728Sgblack@eecs.umich.edu useForClone(false), 925728Sgblack@eecs.umich.edu pTable(pTable), 935728Sgblack@eecs.umich.edu initVirtMem(system->getSystemPort(), this, 945728Sgblack@eecs.umich.edu SETranslatingPortProxy::Always), 955728Sgblack@eecs.umich.edu objFile(obj_file), 965728Sgblack@eecs.umich.edu argv(params->cmd), envp(params->env), 975728Sgblack@eecs.umich.edu executable(params->executable), 985728Sgblack@eecs.umich.edu tgtCwd(normalize(params->cwd)), 995728Sgblack@eecs.umich.edu hostCwd(checkPathRedirect(tgtCwd)), 1005728Sgblack@eecs.umich.edu release(params->release), 1015728Sgblack@eecs.umich.edu _uid(params->uid), _euid(params->euid), 1025728Sgblack@eecs.umich.edu _gid(params->gid), _egid(params->egid), 1035728Sgblack@eecs.umich.edu _pid(params->pid), _ppid(params->ppid), 1045728Sgblack@eecs.umich.edu _pgid(params->pgid), drivers(params->drivers), 1055728Sgblack@eecs.umich.edu fds(make_shared<FDArray>(params->input, params->output, params->errout)), 1065728Sgblack@eecs.umich.edu childClearTID(0) 1075728Sgblack@eecs.umich.edu{ 1085894Sgblack@eecs.umich.edu if (_pid >= System::maxPID) 1095894Sgblack@eecs.umich.edu fatal("_pid is too large: %d", _pid); 1105894Sgblack@eecs.umich.edu 1115894Sgblack@eecs.umich.edu auto ret_pair = system->PIDs.emplace(_pid); 1125894Sgblack@eecs.umich.edu if (!ret_pair.second) 1135894Sgblack@eecs.umich.edu fatal("_pid %d is already used", _pid); 1146023Snate@binkert.org 1156023Snate@binkert.org /** 1165894Sgblack@eecs.umich.edu * Linux bundles together processes into this concept called a thread 1175894Sgblack@eecs.umich.edu * group. The thread group is responsible for recording which processes 1186023Snate@binkert.org * behave as threads within a process context. The thread group leader 1197944SGiacomo.Gabrielli@arm.com * is the process who's tgid is equal to its pid. Other processes which 1207945SAli.Saidi@ARM.com * belong to the thread group, but do not lead the thread group, are 1219342SAndreas.Sandberg@arm.com * treated as child threads. These threads are created by the clone system 1227945SAli.Saidi@ARM.com * call with options specified to create threads (differing from the 1237945SAli.Saidi@ARM.com * options used to implement a fork). By default, set up the tgid/pid 1247944SGiacomo.Gabrielli@arm.com * with a new, equivalent value. If CLONE_THREAD is specified, patch 1257944SGiacomo.Gabrielli@arm.com * the tgid value with the old process' value. 12610379Sandreas.hansson@arm.com */ 1276023Snate@binkert.org _tgid = params->pid; 1285894Sgblack@eecs.umich.edu 1295894Sgblack@eecs.umich.edu exitGroup = new bool(); 1305894Sgblack@eecs.umich.edu sigchld = new bool(); 1315894Sgblack@eecs.umich.edu 1325894Sgblack@eecs.umich.edu if (!debugSymbolTable) { 1335894Sgblack@eecs.umich.edu debugSymbolTable = new SymbolTable(); 1346973Stjones1@inf.ed.ac.uk if (!objFile->loadGlobalSymbols(debugSymbolTable) || 1356973Stjones1@inf.ed.ac.uk !objFile->loadLocalSymbols(debugSymbolTable) || 1366973Stjones1@inf.ed.ac.uk !objFile->loadWeakSymbols(debugSymbolTable)) { 1375894Sgblack@eecs.umich.edu delete debugSymbolTable; 13810379Sandreas.hansson@arm.com debugSymbolTable = nullptr; 1395894Sgblack@eecs.umich.edu } 14010653Sandreas.hansson@arm.com } 1415894Sgblack@eecs.umich.edu} 1425894Sgblack@eecs.umich.edu 1435894Sgblack@eecs.umich.eduvoid 1445744Sgblack@eecs.umich.eduProcess::clone(ThreadContext *otc, ThreadContext *ntc, 1455728Sgblack@eecs.umich.edu Process *np, RegVal flags) 1465728Sgblack@eecs.umich.edu{ 1475728Sgblack@eecs.umich.edu#ifndef CLONE_VM 1485728Sgblack@eecs.umich.edu#define CLONE_VM 0 1498707Sandreas.hansson@arm.com#endif 1508707Sandreas.hansson@arm.com#ifndef CLONE_FILES 1518707Sandreas.hansson@arm.com#define CLONE_FILES 0 1528707Sandreas.hansson@arm.com#endif 1538707Sandreas.hansson@arm.com#ifndef CLONE_THREAD 1548707Sandreas.hansson@arm.com#define CLONE_THREAD 0 1559608Sandreas.hansson@arm.com#endif 1562623SN/A if (CLONE_VM & flags) { 1572623SN/A /** 1582623SN/A * Share the process memory address space between the new process 1598707Sandreas.hansson@arm.com * and the old process. Changes in one will be visible in the other 1609608Sandreas.hansson@arm.com * due to the pointer use. 1612623SN/A */ 1622623SN/A delete np->pTable; 1632623SN/A np->pTable = pTable; 1642623SN/A auto &proxy = dynamic_cast<SETranslatingPortProxy &>( 1658948Sandreas.hansson@arm.com ntc->getVirtProxy()); 1668948Sandreas.hansson@arm.com proxy.setPageTable(np->pTable); 1678948Sandreas.hansson@arm.com 16810030SAli.Saidi@ARM.com np->memState = memState; 1698948Sandreas.hansson@arm.com } else { 1708707Sandreas.hansson@arm.com /** 1712948Ssaidi@eecs.umich.edu * Duplicate the process memory address space. The state needs to be 1722948Ssaidi@eecs.umich.edu * copied over (rather than using pointers to share everything). 1732948Ssaidi@eecs.umich.edu */ 1743349Sbinkertn@umich.edu typedef std::vector<pair<Addr,Addr>> MapVec; 1752948Ssaidi@eecs.umich.edu MapVec mappings; 1762948Ssaidi@eecs.umich.edu pTable->getMappings(&mappings); 1778707Sandreas.hansson@arm.com 1785336Shines@cs.fsu.edu for (auto map : mappings) { 1793349Sbinkertn@umich.edu Addr paddr, vaddr = map.first; 1802948Ssaidi@eecs.umich.edu bool alloc_page = !(np->pTable->translate(vaddr, paddr)); 1812948Ssaidi@eecs.umich.edu np->replicatePage(vaddr, paddr, otc, ntc, alloc_page); 1829087Sandreas.hansson@arm.com } 1832623SN/A 1842623SN/A *np->memState = *memState; 1858707Sandreas.hansson@arm.com } 1862623SN/A 1872623SN/A if (CLONE_FILES & flags) { 1882623SN/A /** 1898707Sandreas.hansson@arm.com * The parent and child file descriptors are shared because the 1909095Sandreas.hansson@arm.com * two FDArray pointers are pointing to the same FDArray. Opening 1918707Sandreas.hansson@arm.com * and closing file descriptors will be visible to both processes. 1922623SN/A */ 1932623SN/A np->fds = fds; 1942623SN/A } else { 1952623SN/A /** 1968975Sandreas.hansson@arm.com * Copy the file descriptors from the old process into the new 1972623SN/A * child process. The file descriptors entry can be opened and 1982657Ssaidi@eecs.umich.edu * closed independently of the other process being considered. The 1992948Ssaidi@eecs.umich.edu * host file descriptors are also dup'd so that the flags for the 2002948Ssaidi@eecs.umich.edu * host file descriptor is independent of the other process. 2012948Ssaidi@eecs.umich.edu */ 2022948Ssaidi@eecs.umich.edu std::shared_ptr<FDArray> nfds = np->fds; 2032948Ssaidi@eecs.umich.edu for (int tgt_fd = 0; tgt_fd < fds->getSize(); tgt_fd++) { 2042948Ssaidi@eecs.umich.edu std::shared_ptr<FDEntry> this_fde = (*fds)[tgt_fd]; 2052948Ssaidi@eecs.umich.edu if (!this_fde) { 2065336Shines@cs.fsu.edu nfds->setFDEntry(tgt_fd, nullptr); 2072948Ssaidi@eecs.umich.edu continue; 2082948Ssaidi@eecs.umich.edu } 2092948Ssaidi@eecs.umich.edu nfds->setFDEntry(tgt_fd, this_fde->clone()); 2102948Ssaidi@eecs.umich.edu 2112623SN/A auto this_hbfd = std::dynamic_pointer_cast<HBFDEntry>(this_fde); 2122623SN/A if (!this_hbfd) 2138707Sandreas.hansson@arm.com continue; 2142623SN/A 2152623SN/A int this_sim_fd = this_hbfd->getSimFD(); 2162623SN/A if (this_sim_fd <= 2) 2178707Sandreas.hansson@arm.com continue; 2189095Sandreas.hansson@arm.com 2199095Sandreas.hansson@arm.com int np_sim_fd = dup(this_sim_fd); 22010030SAli.Saidi@ARM.com assert(np_sim_fd != -1); 22110030SAli.Saidi@ARM.com 22210030SAli.Saidi@ARM.com auto nhbfd = std::dynamic_pointer_cast<HBFDEntry>((*nfds)[tgt_fd]); 2232623SN/A nhbfd->setSimFD(np_sim_fd); 22410030SAli.Saidi@ARM.com } 2252623SN/A } 2262623SN/A 22710030SAli.Saidi@ARM.com if (CLONE_THREAD & flags) { 22810030SAli.Saidi@ARM.com np->_tgid = _tgid; 22910030SAli.Saidi@ARM.com delete np->exitGroup; 23010030SAli.Saidi@ARM.com np->exitGroup = exitGroup; 23110529Smorr@cs.wisc.edu } 23210030SAli.Saidi@ARM.com 2338975Sandreas.hansson@arm.com np->argv.insert(np->argv.end(), argv.begin(), argv.end()); 2342623SN/A np->envp.insert(np->envp.end(), envp.begin(), envp.end()); 2352657Ssaidi@eecs.umich.edu} 2362948Ssaidi@eecs.umich.edu 23710529Smorr@cs.wisc.eduvoid 23810529Smorr@cs.wisc.eduProcess::regStats() 23910529Smorr@cs.wisc.edu{ 24010529Smorr@cs.wisc.edu SimObject::regStats(); 2412948Ssaidi@eecs.umich.edu 2422948Ssaidi@eecs.umich.edu using namespace Stats; 2432948Ssaidi@eecs.umich.edu 2442948Ssaidi@eecs.umich.edu numSyscalls 2452948Ssaidi@eecs.umich.edu .name(name() + ".numSyscalls") 2465336Shines@cs.fsu.edu .desc("Number of system calls") 2472948Ssaidi@eecs.umich.edu ; 2482948Ssaidi@eecs.umich.edu} 2492948Ssaidi@eecs.umich.edu 2502948Ssaidi@eecs.umich.eduThreadContext * 2512623SN/AProcess::findFreeContext() 2522623SN/A{ 25310464SAndreas.Sandberg@ARM.com for (auto &it : system->threadContexts) { 25410464SAndreas.Sandberg@ARM.com if (ThreadContext::Halted == it->status()) 2552623SN/A return it; 2562623SN/A } 2572623SN/A return nullptr; 2583349Sbinkertn@umich.edu} 2593349Sbinkertn@umich.edu 2602623SN/Avoid 26110464SAndreas.Sandberg@ARM.comProcess::revokeThreadContext(int context_id) 2623170Sstever@eecs.umich.edu{ 2638850Sandreas.hansson@arm.com std::vector<ContextID>::iterator it; 2648850Sandreas.hansson@arm.com for (it = contextIds.begin(); it != contextIds.end(); it++) { 2658850Sandreas.hansson@arm.com if (*it == context_id) { 2669608Sandreas.hansson@arm.com contextIds.erase(it); 2678850Sandreas.hansson@arm.com return; 2688850Sandreas.hansson@arm.com } 2699608Sandreas.hansson@arm.com } 2708850Sandreas.hansson@arm.com warn("Unable to find thread context to revoke"); 2712623SN/A} 2722623SN/A 2739342SAndreas.Sandberg@arm.comvoid 2749342SAndreas.Sandberg@arm.comProcess::initState() 2752798Sktlim@umich.edu{ 2762798Sktlim@umich.edu if (contextIds.empty()) 2772623SN/A fatal("Process %s is not associated with any HW contexts!\n", name()); 2782623SN/A 2799523SAndreas.Sandberg@ARM.com // first thread context for this process... initialize & enable 2809523SAndreas.Sandberg@ARM.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 28110407Smitch.hayenga@arm.com 2828737Skoansin.tan@gmail.com // mark this context as active so it will start ticking. 2832623SN/A tc->activate(); 2848444Sgblack@eecs.umich.edu 2857520Sgblack@eecs.umich.edu pTable->initState(); 2868444Sgblack@eecs.umich.edu} 2878444Sgblack@eecs.umich.edu 2887520Sgblack@eecs.umich.eduDrainState 2892623SN/AProcess::drain() 29010379Sandreas.hansson@arm.com{ 2913349Sbinkertn@umich.edu fds->updateFileOffsets(); 2925894Sgblack@eecs.umich.edu return DrainState::Drained; 29310379Sandreas.hansson@arm.com} 2944471Sstever@eecs.umich.edu 2959258SAli.Saidi@ARM.comvoid 2969258SAli.Saidi@ARM.comProcess::allocateMem(Addr vaddr, int64_t size, bool clobber) 2979258SAli.Saidi@ARM.com{ 2989258SAli.Saidi@ARM.com int npages = divCeil(size, (int64_t)PageBytes); 2999258SAli.Saidi@ARM.com Addr paddr = system->allocPhysPages(npages); 3009258SAli.Saidi@ARM.com pTable->map(vaddr, paddr, size, 3019258SAli.Saidi@ARM.com clobber ? EmulationPageTable::Clobber : 3029258SAli.Saidi@ARM.com EmulationPageTable::MappingFlags(0)); 3035315Sstever@gmail.com} 3045315Sstever@gmail.com 3055315Sstever@gmail.comvoid 3065315Sstever@gmail.comProcess::replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, 3075315Sstever@gmail.com ThreadContext *new_tc, bool allocate_page) 3085315Sstever@gmail.com{ 3096973Stjones1@inf.ed.ac.uk if (allocate_page) 3106973Stjones1@inf.ed.ac.uk new_paddr = system->allocPhysPages(1); 3116973Stjones1@inf.ed.ac.uk 3126973Stjones1@inf.ed.ac.uk // Read from old physical page. 3136973Stjones1@inf.ed.ac.uk uint8_t *buf_p = new uint8_t[PageBytes]; 3146973Stjones1@inf.ed.ac.uk old_tc->getVirtProxy().readBlob(vaddr, buf_p, PageBytes); 3152798Sktlim@umich.edu 3164471Sstever@eecs.umich.edu // Create new mapping in process address space by clobbering existing 3174471Sstever@eecs.umich.edu // mapping (if any existed) and then write to the new physical page. 3185710Scws3k@cs.virginia.edu bool clobber = true; 3194471Sstever@eecs.umich.edu pTable->map(vaddr, new_paddr, PageBytes, clobber); 3205103Ssaidi@eecs.umich.edu new_tc->getVirtProxy().writeBlob(vaddr, buf_p, PageBytes); 3215103Ssaidi@eecs.umich.edu delete[] buf_p; 3225103Ssaidi@eecs.umich.edu} 3235103Ssaidi@eecs.umich.edu 3245103Ssaidi@eecs.umich.edubool 3255336Shines@cs.fsu.eduProcess::fixupStackFault(Addr vaddr) 3265103Ssaidi@eecs.umich.edu{ 3275103Ssaidi@eecs.umich.edu Addr stack_min = memState->getStackMin(); 3289442SAndreas.Sandberg@ARM.com Addr stack_base = memState->getStackBase(); 3299442SAndreas.Sandberg@ARM.com Addr max_stack_size = memState->getMaxStackSize(); 3309442SAndreas.Sandberg@ARM.com 3319442SAndreas.Sandberg@ARM.com // Check if this is already on the stack and there's just no page there 3329442SAndreas.Sandberg@ARM.com // yet. 3339442SAndreas.Sandberg@ARM.com if (vaddr >= stack_min && vaddr < stack_base) { 3349442SAndreas.Sandberg@ARM.com allocateMem(roundDown(vaddr, PageBytes), PageBytes); 3359442SAndreas.Sandberg@ARM.com return true; 3369442SAndreas.Sandberg@ARM.com } 3379442SAndreas.Sandberg@ARM.com 3389830Sandreas.hansson@arm.com // We've accessed the next page of the stack, so extend it to include 3399830Sandreas.hansson@arm.com // this address. 3409840Sandreas.hansson@arm.com if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) { 3419840Sandreas.hansson@arm.com while (vaddr < stack_min) { 3429442SAndreas.Sandberg@ARM.com stack_min -= TheISA::PageBytes; 3439442SAndreas.Sandberg@ARM.com if (stack_base - stack_min > max_stack_size) 3449442SAndreas.Sandberg@ARM.com fatal("Maximum stack size exceeded\n"); 3459830Sandreas.hansson@arm.com allocateMem(stack_min, TheISA::PageBytes); 3469442SAndreas.Sandberg@ARM.com inform("Increasing stack size by one page."); 3479442SAndreas.Sandberg@ARM.com } 3489442SAndreas.Sandberg@ARM.com memState->setStackMin(stack_min); 3499442SAndreas.Sandberg@ARM.com return true; 3509442SAndreas.Sandberg@ARM.com } 3519442SAndreas.Sandberg@ARM.com return false; 3529442SAndreas.Sandberg@ARM.com} 3539442SAndreas.Sandberg@ARM.com 3549442SAndreas.Sandberg@ARM.comvoid 3559442SAndreas.Sandberg@ARM.comProcess::serialize(CheckpointOut &cp) const 3569442SAndreas.Sandberg@ARM.com{ 3579442SAndreas.Sandberg@ARM.com memState->serialize(cp); 3589442SAndreas.Sandberg@ARM.com pTable->serialize(cp); 3599442SAndreas.Sandberg@ARM.com /** 3609442SAndreas.Sandberg@ARM.com * Checkpoints for file descriptors currently do not work. Need to 3612623SN/A * come back and fix them at a later date. 3622623SN/A */ 3632623SN/A 364 warn("Checkpoints for file descriptors currently do not work."); 365} 366 367void 368Process::unserialize(CheckpointIn &cp) 369{ 370 memState->unserialize(cp); 371 pTable->unserialize(cp); 372 /** 373 * Checkpoints for file descriptors currently do not work. Need to 374 * come back and fix them at a later date. 375 */ 376 warn("Checkpoints for file descriptors currently do not work."); 377 // The above returns a bool so that you could do something if you don't 378 // find the param in the checkpoint if you wanted to, like set a default 379 // but in this case we'll just stick with the instantiated value if not 380 // found. 381} 382 383bool 384Process::map(Addr vaddr, Addr paddr, int size, bool cacheable) 385{ 386 pTable->map(vaddr, paddr, size, 387 cacheable ? EmulationPageTable::MappingFlags(0) : 388 EmulationPageTable::Uncacheable); 389 return true; 390} 391 392void 393Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault) 394{ 395 numSyscalls++; 396 397 SyscallDesc *desc = getDesc(callnum); 398 if (desc == nullptr) 399 fatal("Syscall %d out of range", callnum); 400 401 desc->doSyscall(callnum, tc, fault); 402} 403 404RegVal 405Process::getSyscallArg(ThreadContext *tc, int &i, int width) 406{ 407 return getSyscallArg(tc, i); 408} 409 410EmulatedDriver * 411Process::findDriver(std::string filename) 412{ 413 for (EmulatedDriver *d : drivers) { 414 if (d->match(filename)) 415 return d; 416 } 417 418 return nullptr; 419} 420 421std::string 422Process::checkPathRedirect(const std::string &filename) 423{ 424 // If the input parameter contains a relative path, convert it. 425 // The target version of the current working directory is fine since 426 // we immediately convert it using redirect paths into a host version. 427 auto abs_path = absolutePath(filename, false); 428 429 for (auto path : system->redirectPaths) { 430 // Search through the redirect paths to see if a starting substring of 431 // our path falls into any buckets which need to redirected. 432 if (startswith(abs_path, path->appPath())) { 433 std::string tail = abs_path.substr(path->appPath().size()); 434 435 // If this path needs to be redirected, search through a list 436 // of targets to see if we can match a valid file (or directory). 437 for (auto host_path : path->hostPaths()) { 438 if (access((host_path + tail).c_str(), R_OK) == 0) { 439 // Return the valid match. 440 return host_path + tail; 441 } 442 } 443 // The path needs to be redirected, but the file or directory 444 // does not exist on the host filesystem. Return the first 445 // host path as a default. 446 return path->hostPaths()[0] + tail; 447 } 448 } 449 450 // The path does not need to be redirected. 451 return abs_path; 452} 453 454void 455Process::updateBias() 456{ 457 ObjectFile *interp = objFile->getInterpreter(); 458 459 if (!interp || !interp->relocatable()) 460 return; 461 462 // Determine how large the interpreters footprint will be in the process 463 // address space. 464 Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes); 465 466 // We are allocating the memory area; set the bias to the lowest address 467 // in the allocated memory region. 468 Addr mmap_end = memState->getMmapEnd(); 469 Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end; 470 471 // Adjust the process mmap area to give the interpreter room; the real 472 // execve system call would just invoke the kernel's internal mmap 473 // functions to make these adjustments. 474 mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize; 475 memState->setMmapEnd(mmap_end); 476 477 interp->updateBias(ld_bias); 478} 479 480ObjectFile * 481Process::getInterpreter() 482{ 483 return objFile->getInterpreter(); 484} 485 486Addr 487Process::getBias() 488{ 489 ObjectFile *interp = getInterpreter(); 490 491 return interp ? interp->bias() : objFile->bias(); 492} 493 494Addr 495Process::getStartPC() 496{ 497 ObjectFile *interp = getInterpreter(); 498 499 return interp ? interp->entryPoint() : objFile->entryPoint(); 500} 501 502std::string 503Process::absolutePath(const std::string &filename, bool host_filesystem) 504{ 505 if (filename.empty() || startswith(filename, "/")) 506 return filename; 507 508 // Construct the absolute path given the current working directory for 509 // either the host filesystem or target filesystem. The distinction only 510 // matters if filesystem redirection is utilized in the simulation. 511 auto path_base = std::string(); 512 if (host_filesystem) { 513 path_base = hostCwd; 514 assert(!hostCwd.empty()); 515 } else { 516 path_base = tgtCwd; 517 assert(!tgtCwd.empty()); 518 } 519 520 // Add a trailing '/' if the current working directory did not have one. 521 normalize(path_base); 522 523 // Append the filename onto the current working path. 524 auto absolute_path = path_base + filename; 525 526 return absolute_path; 527} 528 529Process * 530ProcessParams::create() 531{ 532 // If not specified, set the executable parameter equal to the 533 // simulated system's zeroth command line parameter 534 if (executable == "") { 535 executable = cmd[0]; 536 } 537 538 ObjectFile *obj_file = createObjectFile(executable); 539 fatal_if(!obj_file, "Cannot load object file %s.", executable); 540 541 Process *process = ObjectFile::tryLoaders(this, obj_file); 542 fatal_if(!process, "Unknown error creating process object."); 543 544 return process; 545} 546