process.cc revision 11389
1955SN/A/* 2955SN/A * Copyright (c) 2014 Advanced Micro Devices, Inc. 31762SN/A * Copyright (c) 2012 ARM Limited 4955SN/A * All rights reserved 5955SN/A * 6955SN/A * The license below extends only to copyright in the software and shall 7955SN/A * not be construed as granting a license to any other intellectual 8955SN/A * property including but not limited to intellectual property relating 9955SN/A * to a hardware implementation of the functionality of the software 10955SN/A * licensed hereunder. You may use the software subject to the license 11955SN/A * terms below provided that you ensure that this notice is replicated 12955SN/A * unmodified and in its entirety in all distributions of the software, 13955SN/A * modified or unmodified, in source code or in binary form. 14955SN/A * 15955SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 16955SN/A * All rights reserved. 17955SN/A * 18955SN/A * Redistribution and use in source and binary forms, with or without 19955SN/A * modification, are permitted provided that the following conditions are 20955SN/A * met: redistributions of source code must retain the above copyright 21955SN/A * notice, this list of conditions and the following disclaimer; 22955SN/A * redistributions in binary form must reproduce the above copyright 23955SN/A * notice, this list of conditions and the following disclaimer in the 24955SN/A * documentation and/or other materials provided with the distribution; 25955SN/A * neither the name of the copyright holders nor the names of its 26955SN/A * contributors may be used to endorse or promote products derived from 27955SN/A * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 294762Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 315522Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 326143Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 334762Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 345522Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 365522Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 385522Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 394202Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 405742Snate@binkert.org * 41955SN/A * Authors: Nathan Binkert 424381Sbinkertn@umich.edu * Steve Reinhardt 434381Sbinkertn@umich.edu * Ali Saidi 44955SN/A */ 45955SN/A 46955SN/A#include <fcntl.h> 474202Sbinkertn@umich.edu#include <unistd.h> 48955SN/A 494382Sbinkertn@umich.edu#include <cstdio> 504382Sbinkertn@umich.edu#include <map> 514382Sbinkertn@umich.edu#include <string> 526654Snate@binkert.org 535517Snate@binkert.org#include "base/loader/object_file.hh" 547674Snate@binkert.org#include "base/loader/symtab.hh" 557674Snate@binkert.org#include "base/intmath.hh" 566143Snate@binkert.org#include "base/statistics.hh" 576143Snate@binkert.org#include "config/the_isa.hh" 586143Snate@binkert.org#include "cpu/thread_context.hh" 598233Snate@binkert.org#include "mem/page_table.hh" 608233Snate@binkert.org#include "mem/multi_level_page_table.hh" 618233Snate@binkert.org#include "mem/se_translating_port_proxy.hh" 628233Snate@binkert.org#include "params/LiveProcess.hh" 638233Snate@binkert.org#include "params/Process.hh" 648233Snate@binkert.org#include "sim/debug.hh" 658233Snate@binkert.org#include "sim/process.hh" 668233Snate@binkert.org#include "sim/process_impl.hh" 678233Snate@binkert.org#include "sim/stats.hh" 688233Snate@binkert.org#include "sim/syscall_emul.hh" 698233Snate@binkert.org#include "sim/system.hh" 708233Snate@binkert.org 718233Snate@binkert.org#if THE_ISA == ALPHA_ISA 726143Snate@binkert.org#include "arch/alpha/linux/process.hh" 738233Snate@binkert.org#include "arch/alpha/tru64/process.hh" 748233Snate@binkert.org#elif THE_ISA == SPARC_ISA 758233Snate@binkert.org#include "arch/sparc/linux/process.hh" 766143Snate@binkert.org#include "arch/sparc/solaris/process.hh" 776143Snate@binkert.org#elif THE_ISA == MIPS_ISA 786143Snate@binkert.org#include "arch/mips/linux/process.hh" 796143Snate@binkert.org#elif THE_ISA == ARM_ISA 808233Snate@binkert.org#include "arch/arm/linux/process.hh" 818233Snate@binkert.org#include "arch/arm/freebsd/process.hh" 828233Snate@binkert.org#elif THE_ISA == X86_ISA 836143Snate@binkert.org#include "arch/x86/linux/process.hh" 848233Snate@binkert.org#elif THE_ISA == POWER_ISA 858233Snate@binkert.org#include "arch/power/linux/process.hh" 868233Snate@binkert.org#else 878233Snate@binkert.org#error "THE_ISA not set" 886143Snate@binkert.org#endif 896143Snate@binkert.org 906143Snate@binkert.org 914762Snate@binkert.orgusing namespace std; 926143Snate@binkert.orgusing namespace TheISA; 938233Snate@binkert.org 948233Snate@binkert.org// current number of allocated processes 958233Snate@binkert.orgint num_processes = 0; 968233Snate@binkert.org 978233Snate@binkert.orgtemplate<class IntType> 986143Snate@binkert.org 998233Snate@binkert.orgAuxVector<IntType>::AuxVector(IntType type, IntType val) 1008233Snate@binkert.org{ 1018233Snate@binkert.org a_type = TheISA::htog(type); 1028233Snate@binkert.org a_val = TheISA::htog(val); 1036143Snate@binkert.org} 1046143Snate@binkert.org 1056143Snate@binkert.orgtemplate struct AuxVector<uint32_t>; 1066143Snate@binkert.orgtemplate struct AuxVector<uint64_t>; 1076143Snate@binkert.org 1086143Snate@binkert.orgstatic int 1096143Snate@binkert.orgopenFile(const string& filename, int flags, mode_t mode) 1106143Snate@binkert.org{ 1116143Snate@binkert.org int sim_fd = open(filename.c_str(), flags, mode); 1127065Snate@binkert.org if (sim_fd != -1) 1136143Snate@binkert.org return sim_fd; 1148233Snate@binkert.org fatal("Unable to open %s with mode %O", filename, mode); 1158233Snate@binkert.org} 1168233Snate@binkert.org 1178233Snate@binkert.orgstatic int 1188233Snate@binkert.orgopenInputFile(const string &filename) 1198233Snate@binkert.org{ 1208233Snate@binkert.org return openFile(filename, O_RDONLY, 0); 1218233Snate@binkert.org} 1228233Snate@binkert.org 1238233Snate@binkert.orgstatic int 1248233Snate@binkert.orgopenOutputFile(const string &filename) 1258233Snate@binkert.org{ 1268233Snate@binkert.org return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); 1278233Snate@binkert.org} 1288233Snate@binkert.org 1298233Snate@binkert.orgProcess::Process(ProcessParams * params) 1308233Snate@binkert.org : SimObject(params), system(params->system), 1318233Snate@binkert.org brk_point(0), stack_base(0), stack_size(0), stack_min(0), 1328233Snate@binkert.org max_stack_size(params->max_stack_size), 1338233Snate@binkert.org next_thread_stack_base(0), 1348233Snate@binkert.org M5_pid(system->allocatePID()), 1358233Snate@binkert.org useArchPT(params->useArchPT), 1368233Snate@binkert.org kvmInSE(params->kvmInSE), 1378233Snate@binkert.org pTable(useArchPT ? 1388233Snate@binkert.org static_cast<PageTableBase *>(new ArchPageTable(name(), M5_pid, system)) : 1398233Snate@binkert.org static_cast<PageTableBase *>(new FuncPageTable(name(), M5_pid)) ), 1408233Snate@binkert.org initVirtMem(system->getSystemPort(), this, 1418233Snate@binkert.org SETranslatingPortProxy::Always), 1428233Snate@binkert.org fd_array(make_shared<array<FDEntry, NUM_FDS>>()), 1438233Snate@binkert.org imap {{"", -1}, 1448233Snate@binkert.org {"cin", STDIN_FILENO}, 1456143Snate@binkert.org {"stdin", STDIN_FILENO}}, 1466143Snate@binkert.org oemap{{"", -1}, 1476143Snate@binkert.org {"cout", STDOUT_FILENO}, 1486143Snate@binkert.org {"stdout", STDOUT_FILENO}, 1496143Snate@binkert.org {"cerr", STDERR_FILENO}, 1506143Snate@binkert.org {"stderr", STDERR_FILENO}} 1516143Snate@binkert.org{ 1526143Snate@binkert.org int sim_fd; 1536143Snate@binkert.org std::map<string,int>::iterator it; 1548233Snate@binkert.org 1558233Snate@binkert.org // Search through the input options and set fd if match is found; 1568233Snate@binkert.org // otherwise, open an input file and seek to location. 1576143Snate@binkert.org FDEntry *fde_stdin = getFDEntry(STDIN_FILENO); 1586143Snate@binkert.org if ((it = imap.find(params->input)) != imap.end()) 1596143Snate@binkert.org sim_fd = it->second; 1606143Snate@binkert.org else 1616143Snate@binkert.org sim_fd = openInputFile(params->input); 1626143Snate@binkert.org fde_stdin->set(sim_fd, params->input, O_RDONLY, -1, false); 1635522Snate@binkert.org 1646143Snate@binkert.org // Search through the output/error options and set fd if match is found; 1656143Snate@binkert.org // otherwise, open an output file and seek to location. 1666143Snate@binkert.org FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO); 1676143Snate@binkert.org if ((it = oemap.find(params->output)) != oemap.end()) 1688233Snate@binkert.org sim_fd = it->second; 1698233Snate@binkert.org else 1708233Snate@binkert.org sim_fd = openOutputFile(params->output); 1716143Snate@binkert.org fde_stdout->set(sim_fd, params->output, O_WRONLY | O_CREAT | O_TRUNC, 1726143Snate@binkert.org 0664, false); 1736143Snate@binkert.org 1746143Snate@binkert.org FDEntry *fde_stderr = getFDEntry(STDERR_FILENO); 1755522Snate@binkert.org if (params->output == params->errout) 1765522Snate@binkert.org // Reuse the same file descriptor if these match. 1775522Snate@binkert.org sim_fd = fde_stdout->fd; 1785522Snate@binkert.org else if ((it = oemap.find(params->errout)) != oemap.end()) 1795604Snate@binkert.org sim_fd = it->second; 1805604Snate@binkert.org else 1816143Snate@binkert.org sim_fd = openOutputFile(params->errout); 1826143Snate@binkert.org fde_stderr->set(sim_fd, params->errout, O_WRONLY | O_CREAT | O_TRUNC, 1834762Snate@binkert.org 0664, false); 1844762Snate@binkert.org 1856143Snate@binkert.org mmap_end = 0; 1866727Ssteve.reinhardt@amd.com nxm_start = nxm_end = 0; 1876727Ssteve.reinhardt@amd.com // other parameters will be initialized when the program is loaded 1886727Ssteve.reinhardt@amd.com} 1894762Snate@binkert.org 1906143Snate@binkert.org 1916143Snate@binkert.orgvoid 1926143Snate@binkert.orgProcess::regStats() 1936143Snate@binkert.org{ 1946727Ssteve.reinhardt@amd.com using namespace Stats; 1956143Snate@binkert.org 1967674Snate@binkert.org num_syscalls 1977674Snate@binkert.org .name(name() + ".num_syscalls") 1985604Snate@binkert.org .desc("Number of system calls") 1996143Snate@binkert.org ; 2006143Snate@binkert.org} 2016143Snate@binkert.org 2024762Snate@binkert.orgvoid 2036143Snate@binkert.orgProcess::inheritFDArray(Process *p) 2044762Snate@binkert.org{ 2054762Snate@binkert.org fd_array = p->fd_array; 2064762Snate@binkert.org} 2076143Snate@binkert.org 2086143Snate@binkert.orgThreadContext * 2094762Snate@binkert.orgProcess::findFreeContext() 2108233Snate@binkert.org{ 2118233Snate@binkert.org for (int id : contextIds) { 2128233Snate@binkert.org ThreadContext *tc = system->getThreadContext(id); 2138233Snate@binkert.org if (tc->status() == ThreadContext::Halted) 2146143Snate@binkert.org return tc; 2156143Snate@binkert.org } 2164762Snate@binkert.org return NULL; 2176143Snate@binkert.org} 2184762Snate@binkert.org 2196143Snate@binkert.orgvoid 2204762Snate@binkert.orgProcess::initState() 2216143Snate@binkert.org{ 2228233Snate@binkert.org if (contextIds.empty()) 2238233Snate@binkert.org fatal("Process %s is not associated with any HW contexts!\n", name()); 2248233Snate@binkert.org 2256143Snate@binkert.org // first thread context for this process... initialize & enable 2266143Snate@binkert.org ThreadContext *tc = system->getThreadContext(contextIds[0]); 2276143Snate@binkert.org 2286143Snate@binkert.org // mark this context as active so it will start ticking. 2296143Snate@binkert.org tc->activate(); 2306143Snate@binkert.org 2316143Snate@binkert.org pTable->initState(tc); 2326143Snate@binkert.org} 2338233Snate@binkert.org 2348233Snate@binkert.orgDrainState 235955SN/AProcess::drain() 2368235Snate@binkert.org{ 2378235Snate@binkert.org findFileOffsets(); 2386143Snate@binkert.org return DrainState::Drained; 2398235Snate@binkert.org} 2408235Snate@binkert.org 2418235Snate@binkert.orgint 2428235Snate@binkert.orgProcess::allocFD(int sim_fd, const string& filename, int flags, int mode, 2438235Snate@binkert.org bool pipe) 2448235Snate@binkert.org{ 2458235Snate@binkert.org for (int free_fd = 0; free_fd < fd_array->size(); free_fd++) { 2468235Snate@binkert.org FDEntry *fde = getFDEntry(free_fd); 2478235Snate@binkert.org if (fde->isFree()) { 2488235Snate@binkert.org fde->set(sim_fd, filename, flags, mode, pipe); 2498235Snate@binkert.org return free_fd; 2508235Snate@binkert.org } 2518235Snate@binkert.org } 2528235Snate@binkert.org 2538235Snate@binkert.org fatal("Out of target file descriptors"); 2548235Snate@binkert.org} 2558235Snate@binkert.org 2565584Snate@binkert.orgvoid 2574382Sbinkertn@umich.eduProcess::resetFDEntry(int tgt_fd) 2584202Sbinkertn@umich.edu{ 2594382Sbinkertn@umich.edu FDEntry *fde = getFDEntry(tgt_fd); 2604382Sbinkertn@umich.edu assert(fde->fd > -1); 2614382Sbinkertn@umich.edu 2625584Snate@binkert.org fde->reset(); 2634382Sbinkertn@umich.edu} 2644382Sbinkertn@umich.edu 2654382Sbinkertn@umich.eduint 2668232Snate@binkert.orgProcess::getSimFD(int tgt_fd) 2675192Ssaidi@eecs.umich.edu{ 2688232Snate@binkert.org FDEntry *entry = getFDEntry(tgt_fd); 2698232Snate@binkert.org return entry ? entry->fd : -1; 2708232Snate@binkert.org} 2715192Ssaidi@eecs.umich.edu 2728232Snate@binkert.orgFDEntry * 2738232Snate@binkert.orgProcess::getFDEntry(int tgt_fd) 2745192Ssaidi@eecs.umich.edu{ 2755799Snate@binkert.org assert(0 <= tgt_fd && tgt_fd < fd_array->size()); 2768232Snate@binkert.org return &(*fd_array)[tgt_fd]; 2775192Ssaidi@eecs.umich.edu} 2785192Ssaidi@eecs.umich.edu 2795192Ssaidi@eecs.umich.eduint 2808232Snate@binkert.orgProcess::getTgtFD(int sim_fd) 2815192Ssaidi@eecs.umich.edu{ 2828232Snate@binkert.org for (int index = 0; index < fd_array->size(); index++) 2835192Ssaidi@eecs.umich.edu if ((*fd_array)[index].fd == sim_fd) 2845192Ssaidi@eecs.umich.edu return index; 2855192Ssaidi@eecs.umich.edu return -1; 2865192Ssaidi@eecs.umich.edu} 2875192Ssaidi@eecs.umich.edu 2884382Sbinkertn@umich.eduvoid 2894382Sbinkertn@umich.eduProcess::allocateMem(Addr vaddr, int64_t size, bool clobber) 2904382Sbinkertn@umich.edu{ 2912667Sstever@eecs.umich.edu int npages = divCeil(size, (int64_t)PageBytes); 2922667Sstever@eecs.umich.edu Addr paddr = system->allocPhysPages(npages); 2932667Sstever@eecs.umich.edu pTable->map(vaddr, paddr, size, 2942667Sstever@eecs.umich.edu clobber ? PageTableBase::Clobber : PageTableBase::Zero); 2952667Sstever@eecs.umich.edu} 2962667Sstever@eecs.umich.edu 2975742Snate@binkert.orgbool 2985742Snate@binkert.orgProcess::fixupStackFault(Addr vaddr) 2995742Snate@binkert.org{ 3005793Snate@binkert.org // Check if this is already on the stack and there's just no page there 3015793Snate@binkert.org // yet. 3025793Snate@binkert.org if (vaddr >= stack_min && vaddr < stack_base) { 3035793Snate@binkert.org allocateMem(roundDown(vaddr, PageBytes), PageBytes); 3045793Snate@binkert.org return true; 3054382Sbinkertn@umich.edu } 3064762Snate@binkert.org 3075344Sstever@gmail.com // We've accessed the next page of the stack, so extend it to include 3084382Sbinkertn@umich.edu // this address. 3095341Sstever@gmail.com if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) { 3105742Snate@binkert.org while (vaddr < stack_min) { 3115742Snate@binkert.org stack_min -= TheISA::PageBytes; 3125742Snate@binkert.org if (stack_base - stack_min > max_stack_size) 3135742Snate@binkert.org fatal("Maximum stack size exceeded\n"); 3145742Snate@binkert.org allocateMem(stack_min, TheISA::PageBytes); 3154762Snate@binkert.org inform("Increasing stack size by one page."); 3165742Snate@binkert.org }; 3175742Snate@binkert.org return true; 3187722Sgblack@eecs.umich.edu } 3195742Snate@binkert.org return false; 3205742Snate@binkert.org} 3215742Snate@binkert.org 3225742Snate@binkert.orgvoid 3238242Sbradley.danofsky@amd.comProcess::fixFileOffsets() 3248242Sbradley.danofsky@amd.com{ 3258242Sbradley.danofsky@amd.com auto seek = [] (FDEntry *fde) 3268242Sbradley.danofsky@amd.com { 3275341Sstever@gmail.com if (lseek(fde->fd, fde->fileOffset, SEEK_SET) < 0) 3285742Snate@binkert.org fatal("Unable to see to location in %s", fde->filename); 3297722Sgblack@eecs.umich.edu }; 3304773Snate@binkert.org 3316108Snate@binkert.org std::map<string,int>::iterator it; 3321858SN/A 3331085SN/A // Search through the input options and set fd if match is found; 3346658Snate@binkert.org // otherwise, open an input file and seek to location. 3356658Snate@binkert.org FDEntry *fde_stdin = getFDEntry(STDIN_FILENO); 3367673Snate@binkert.org if ((it = imap.find(fde_stdin->filename)) != imap.end()) { 3376658Snate@binkert.org fde_stdin->fd = it->second; 3386658Snate@binkert.org } else { 3396658Snate@binkert.org fde_stdin->fd = openInputFile(fde_stdin->filename); 3406658Snate@binkert.org seek(fde_stdin); 3416658Snate@binkert.org } 3426658Snate@binkert.org 3436658Snate@binkert.org // Search through the output/error options and set fd if match is found; 3447673Snate@binkert.org // otherwise, open an output file and seek to location. 3457673Snate@binkert.org FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO); 3467673Snate@binkert.org if ((it = oemap.find(fde_stdout->filename)) != oemap.end()) { 3477673Snate@binkert.org fde_stdout->fd = it->second; 3487673Snate@binkert.org } else { 3497673Snate@binkert.org fde_stdout->fd = openOutputFile(fde_stdout->filename); 3507673Snate@binkert.org seek(fde_stdout); 3516658Snate@binkert.org } 3527673Snate@binkert.org 3537673Snate@binkert.org FDEntry *fde_stderr = getFDEntry(STDERR_FILENO); 3547673Snate@binkert.org if (fde_stdout->filename == fde_stderr->filename) { 3557673Snate@binkert.org // Reuse the same file descriptor if these match. 3567673Snate@binkert.org fde_stderr->fd = fde_stdout->fd; 3577673Snate@binkert.org } else if ((it = oemap.find(fde_stderr->filename)) != oemap.end()) { 3587673Snate@binkert.org fde_stderr->fd = it->second; 3597673Snate@binkert.org } else { 3607673Snate@binkert.org fde_stderr->fd = openOutputFile(fde_stderr->filename); 3617673Snate@binkert.org seek(fde_stderr); 3626658Snate@binkert.org } 3637756SAli.Saidi@ARM.com 3647816Ssteve.reinhardt@amd.com for (int tgt_fd = 3; tgt_fd < fd_array->size(); tgt_fd++) { 3656658Snate@binkert.org FDEntry *fde = getFDEntry(tgt_fd); 3664382Sbinkertn@umich.edu if (fde->fd == -1) 3674382Sbinkertn@umich.edu continue; 3684762Snate@binkert.org 3694762Snate@binkert.org if (fde->isPipe) { 3704762Snate@binkert.org if (fde->filename == "PIPE-WRITE") 3716654Snate@binkert.org continue; 3726654Snate@binkert.org assert(fde->filename == "PIPE-READ"); 3735517Snate@binkert.org 3745517Snate@binkert.org int fds[2]; 3755517Snate@binkert.org if (pipe(fds) < 0) 3765517Snate@binkert.org fatal("Unable to create new pipe"); 3775517Snate@binkert.org 3785517Snate@binkert.org fde->fd = fds[0]; 3795517Snate@binkert.org 3805517Snate@binkert.org FDEntry *fde_write = getFDEntry(fde->readPipeSource); 3815517Snate@binkert.org assert(fde_write->filename == "PIPE-WRITE"); 3825517Snate@binkert.org fde_write->fd = fds[1]; 3835517Snate@binkert.org } else { 3845517Snate@binkert.org fde->fd = openFile(fde->filename.c_str(), fde->flags, fde->mode); 3855517Snate@binkert.org seek(fde); 3865517Snate@binkert.org } 3875517Snate@binkert.org } 3885517Snate@binkert.org} 3895517Snate@binkert.org 3906654Snate@binkert.orgvoid 3915517Snate@binkert.orgProcess::findFileOffsets() 3925517Snate@binkert.org{ 3935517Snate@binkert.org for (auto& fde : *fd_array) { 3945517Snate@binkert.org if (fde.fd != -1) 3955517Snate@binkert.org fde.fileOffset = lseek(fde.fd, 0, SEEK_CUR); 3965517Snate@binkert.org } 3975517Snate@binkert.org} 3985517Snate@binkert.org 3996143Snate@binkert.orgvoid 4006654Snate@binkert.orgProcess::setReadPipeSource(int read_pipe_fd, int source_fd) 4015517Snate@binkert.org{ 4025517Snate@binkert.org FDEntry *fde = getFDEntry(read_pipe_fd); 4035517Snate@binkert.org assert(source_fd >= -1); 4045517Snate@binkert.org fde->readPipeSource = source_fd; 4055517Snate@binkert.org} 4065517Snate@binkert.org 4075517Snate@binkert.orgvoid 4085517Snate@binkert.orgProcess::serialize(CheckpointOut &cp) const 4095517Snate@binkert.org{ 4105517Snate@binkert.org SERIALIZE_SCALAR(brk_point); 4115517Snate@binkert.org SERIALIZE_SCALAR(stack_base); 4125517Snate@binkert.org SERIALIZE_SCALAR(stack_size); 4135517Snate@binkert.org SERIALIZE_SCALAR(stack_min); 4145517Snate@binkert.org SERIALIZE_SCALAR(next_thread_stack_base); 4156654Snate@binkert.org SERIALIZE_SCALAR(mmap_end); 4166654Snate@binkert.org SERIALIZE_SCALAR(nxm_start); 4175517Snate@binkert.org SERIALIZE_SCALAR(nxm_end); 4185517Snate@binkert.org pTable->serialize(cp); 4196143Snate@binkert.org for (int x = 0; x < fd_array->size(); x++) { 4206143Snate@binkert.org (*fd_array)[x].serializeSection(cp, csprintf("FDEntry%d", x)); 4216143Snate@binkert.org } 4226727Ssteve.reinhardt@amd.com SERIALIZE_SCALAR(M5_pid); 4235517Snate@binkert.org 4246727Ssteve.reinhardt@amd.com} 4255517Snate@binkert.org 4265517Snate@binkert.orgvoid 4275517Snate@binkert.orgProcess::unserialize(CheckpointIn &cp) 4286654Snate@binkert.org{ 4296654Snate@binkert.org UNSERIALIZE_SCALAR(brk_point); 4307673Snate@binkert.org UNSERIALIZE_SCALAR(stack_base); 4316654Snate@binkert.org UNSERIALIZE_SCALAR(stack_size); 4326654Snate@binkert.org UNSERIALIZE_SCALAR(stack_min); 4336654Snate@binkert.org UNSERIALIZE_SCALAR(next_thread_stack_base); 4346654Snate@binkert.org UNSERIALIZE_SCALAR(mmap_end); 4355517Snate@binkert.org UNSERIALIZE_SCALAR(nxm_start); 4365517Snate@binkert.org UNSERIALIZE_SCALAR(nxm_end); 4375517Snate@binkert.org pTable->unserialize(cp); 4386143Snate@binkert.org for (int x = 0; x < fd_array->size(); x++) { 4395517Snate@binkert.org FDEntry *fde = getFDEntry(x); 4404762Snate@binkert.org fde->unserializeSection(cp, csprintf("FDEntry%d", x)); 4415517Snate@binkert.org } 4425517Snate@binkert.org fixFileOffsets(); 4436143Snate@binkert.org UNSERIALIZE_OPT_SCALAR(M5_pid); 4446143Snate@binkert.org // The above returns a bool so that you could do something if you don't 4455517Snate@binkert.org // find the param in the checkpoint if you wanted to, like set a default 4465517Snate@binkert.org // but in this case we'll just stick with the instantiated value if not 4475517Snate@binkert.org // found. 4485517Snate@binkert.org} 4495517Snate@binkert.org 4505517Snate@binkert.org 4515517Snate@binkert.orgbool 4525517Snate@binkert.orgProcess::map(Addr vaddr, Addr paddr, int size, bool cacheable) 4535517Snate@binkert.org{ 4545517Snate@binkert.org pTable->map(vaddr, paddr, size, 4556143Snate@binkert.org cacheable ? PageTableBase::Zero : PageTableBase::Uncacheable); 4565517Snate@binkert.org return true; 4576654Snate@binkert.org} 4586654Snate@binkert.org 4596654Snate@binkert.org 4606654Snate@binkert.org//////////////////////////////////////////////////////////////////////// 4616654Snate@binkert.org// 4626654Snate@binkert.org// LiveProcess member definitions 4635517Snate@binkert.org// 4645517Snate@binkert.org//////////////////////////////////////////////////////////////////////// 4655517Snate@binkert.org 4665517Snate@binkert.org 4675517Snate@binkert.orgLiveProcess::LiveProcess(LiveProcessParams *params, ObjectFile *_objFile) 4684762Snate@binkert.org : Process(params), objFile(_objFile), 4694762Snate@binkert.org argv(params->cmd), envp(params->env), cwd(params->cwd), 4704762Snate@binkert.org executable(params->executable), 4714762Snate@binkert.org __uid(params->uid), __euid(params->euid), 4724762Snate@binkert.org __gid(params->gid), __egid(params->egid), 4734762Snate@binkert.org __pid(params->pid), __ppid(params->ppid), 4747675Snate@binkert.org drivers(params->drivers) 4754762Snate@binkert.org{ 4764762Snate@binkert.org 4774762Snate@binkert.org // load up symbols, if any... these may be used for debugging or 4784762Snate@binkert.org // profiling. 4794382Sbinkertn@umich.edu if (!debugSymbolTable) { 4804382Sbinkertn@umich.edu debugSymbolTable = new SymbolTable(); 4815517Snate@binkert.org if (!objFile->loadGlobalSymbols(debugSymbolTable) || 4826654Snate@binkert.org !objFile->loadLocalSymbols(debugSymbolTable) || 4835517Snate@binkert.org !objFile->loadWeakSymbols(debugSymbolTable)) { 4848126Sgblack@eecs.umich.edu // didn't load any symbols 4856654Snate@binkert.org delete debugSymbolTable; 4867673Snate@binkert.org debugSymbolTable = NULL; 4876654Snate@binkert.org } 4886654Snate@binkert.org } 4896654Snate@binkert.org} 4906654Snate@binkert.org 4916654Snate@binkert.orgvoid 4926654Snate@binkert.orgLiveProcess::syscall(int64_t callnum, ThreadContext *tc) 4936654Snate@binkert.org{ 4946669Snate@binkert.org num_syscalls++; 4956669Snate@binkert.org 4966669Snate@binkert.org SyscallDesc *desc = getDesc(callnum); 4976669Snate@binkert.org if (desc == NULL) 4986669Snate@binkert.org fatal("Syscall %d out of range", callnum); 4996669Snate@binkert.org 5006654Snate@binkert.org desc->doSyscall(callnum, this, tc); 5017673Snate@binkert.org} 5025517Snate@binkert.org 5038126Sgblack@eecs.umich.eduIntReg 5045798Snate@binkert.orgLiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) 5057756SAli.Saidi@ARM.com{ 5067816Ssteve.reinhardt@amd.com return getSyscallArg(tc, i); 5075798Snate@binkert.org} 5085798Snate@binkert.org 5095517Snate@binkert.org 5105517Snate@binkert.orgEmulatedDriver * 5117673Snate@binkert.orgLiveProcess::findDriver(std::string filename) 5125517Snate@binkert.org{ 5135517Snate@binkert.org for (EmulatedDriver *d : drivers) { 5147673Snate@binkert.org if (d->match(filename)) 5157673Snate@binkert.org return d; 5165517Snate@binkert.org } 5175798Snate@binkert.org 5185798Snate@binkert.org return NULL; 5198333Snate@binkert.org} 5207816Ssteve.reinhardt@amd.com 5215798Snate@binkert.orgvoid 5225798Snate@binkert.orgLiveProcess::updateBias() 5234762Snate@binkert.org{ 5244762Snate@binkert.org ObjectFile *interp = objFile->getInterpreter(); 5254762Snate@binkert.org 5264762Snate@binkert.org if (!interp || !interp->relocatable()) 5274762Snate@binkert.org return; 5285517Snate@binkert.org 5295517Snate@binkert.org // Determine how large the interpreters footprint will be in the process 5305517Snate@binkert.org // address space. 5315517Snate@binkert.org Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes); 5325517Snate@binkert.org 5335517Snate@binkert.org // We are allocating the memory area; set the bias to the lowest address 5347673Snate@binkert.org // in the allocated memory region. 5357673Snate@binkert.org Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end; 5367673Snate@binkert.org 5375517Snate@binkert.org // Adjust the process mmap area to give the interpreter room; the real 5385517Snate@binkert.org // execve system call would just invoke the kernel's internal mmap 5395517Snate@binkert.org // functions to make these adjustments. 5405517Snate@binkert.org mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize; 5415517Snate@binkert.org 5425517Snate@binkert.org interp->updateBias(ld_bias); 5435517Snate@binkert.org} 5447673Snate@binkert.org 5457677Snate@binkert.org 5467673Snate@binkert.orgAddr 5477673Snate@binkert.orgLiveProcess::getBias() 5485517Snate@binkert.org{ 5495517Snate@binkert.org ObjectFile *interp = objFile->getInterpreter(); 5505517Snate@binkert.org 5515517Snate@binkert.org return interp ? interp->bias() : objFile->bias(); 5525517Snate@binkert.org} 5535517Snate@binkert.org 5545517Snate@binkert.org 5557673Snate@binkert.orgAddr 5567673Snate@binkert.orgLiveProcess::getStartPC() 5577673Snate@binkert.org{ 5585517Snate@binkert.org ObjectFile *interp = objFile->getInterpreter(); 5595517Snate@binkert.org 5605517Snate@binkert.org return interp ? interp->entryPoint() : objFile->entryPoint(); 5615517Snate@binkert.org} 5625517Snate@binkert.org 5635517Snate@binkert.org 5645517Snate@binkert.orgLiveProcess * 5657673Snate@binkert.orgLiveProcess::create(LiveProcessParams * params) 5667673Snate@binkert.org{ 5677673Snate@binkert.org LiveProcess *process = NULL; 5685517Snate@binkert.org 5697675Snate@binkert.org // If not specified, set the executable parameter equal to the 5707675Snate@binkert.org // simulated system's zeroth command line parameter 5717675Snate@binkert.org if (params->executable == "") { 5727675Snate@binkert.org params->executable = params->cmd[0]; 5737675Snate@binkert.org } 5747675Snate@binkert.org 5757675Snate@binkert.org ObjectFile *objFile = createObjectFile(params->executable); 5767675Snate@binkert.org if (objFile == NULL) { 5777677Snate@binkert.org fatal("Can't load object file %s", params->executable); 5787675Snate@binkert.org } 5797675Snate@binkert.org 5807675Snate@binkert.org#if THE_ISA == ALPHA_ISA 5817675Snate@binkert.org if (objFile->getArch() != ObjectFile::Alpha) 5827675Snate@binkert.org fatal("Object file architecture does not match compiled ISA (Alpha)."); 5837675Snate@binkert.org 5847675Snate@binkert.org switch (objFile->getOpSys()) { 5857675Snate@binkert.org case ObjectFile::Tru64: 5867675Snate@binkert.org process = new AlphaTru64Process(params, objFile); 5874762Snate@binkert.org break; 5884762Snate@binkert.org 5896143Snate@binkert.org case ObjectFile::UnknownOpSys: 5906143Snate@binkert.org warn("Unknown operating system; assuming Linux."); 5916143Snate@binkert.org // fall through 5924762Snate@binkert.org case ObjectFile::Linux: 5934762Snate@binkert.org process = new AlphaLinuxProcess(params, objFile); 5944762Snate@binkert.org break; 5957756SAli.Saidi@ARM.com 5967816Ssteve.reinhardt@amd.com default: 5974762Snate@binkert.org fatal("Unknown/unsupported operating system."); 5984762Snate@binkert.org } 5994762Snate@binkert.org#elif THE_ISA == SPARC_ISA 6005463Snate@binkert.org if (objFile->getArch() != ObjectFile::SPARC64 && 6015517Snate@binkert.org objFile->getArch() != ObjectFile::SPARC32) 6027677Snate@binkert.org fatal("Object file architecture does not match compiled ISA (SPARC)."); 6035463Snate@binkert.org switch (objFile->getOpSys()) { 6047756SAli.Saidi@ARM.com case ObjectFile::UnknownOpSys: 6057816Ssteve.reinhardt@amd.com warn("Unknown operating system; assuming Linux."); 6064762Snate@binkert.org // fall through 6077677Snate@binkert.org case ObjectFile::Linux: 6084762Snate@binkert.org if (objFile->getArch() == ObjectFile::SPARC64) { 6094762Snate@binkert.org process = new Sparc64LinuxProcess(params, objFile); 6106143Snate@binkert.org } else { 6116143Snate@binkert.org process = new Sparc32LinuxProcess(params, objFile); 6126143Snate@binkert.org } 6134762Snate@binkert.org break; 6144762Snate@binkert.org 6157756SAli.Saidi@ARM.com 6167816Ssteve.reinhardt@amd.com case ObjectFile::Solaris: 6174762Snate@binkert.org process = new SparcSolarisProcess(params, objFile); 6184762Snate@binkert.org break; 6194762Snate@binkert.org 6204762Snate@binkert.org default: 6217756SAli.Saidi@ARM.com fatal("Unknown/unsupported operating system."); 6227816Ssteve.reinhardt@amd.com } 6234762Snate@binkert.org#elif THE_ISA == X86_ISA 6244762Snate@binkert.org if (objFile->getArch() != ObjectFile::X86_64 && 6257677Snate@binkert.org objFile->getArch() != ObjectFile::I386) 6267756SAli.Saidi@ARM.com fatal("Object file architecture does not match compiled ISA (x86)."); 6277816Ssteve.reinhardt@amd.com switch (objFile->getOpSys()) { 6287675Snate@binkert.org case ObjectFile::UnknownOpSys: 6297677Snate@binkert.org warn("Unknown operating system; assuming Linux."); 6305517Snate@binkert.org // fall through 6317675Snate@binkert.org case ObjectFile::Linux: 6327675Snate@binkert.org if (objFile->getArch() == ObjectFile::X86_64) { 6337675Snate@binkert.org process = new X86_64LinuxProcess(params, objFile); 6347675Snate@binkert.org } else { 6357675Snate@binkert.org process = new I386LinuxProcess(params, objFile); 6367675Snate@binkert.org } 6377675Snate@binkert.org break; 6385517Snate@binkert.org 6397673Snate@binkert.org default: 6405517Snate@binkert.org fatal("Unknown/unsupported operating system."); 6417677Snate@binkert.org } 6427675Snate@binkert.org#elif THE_ISA == MIPS_ISA 6437673Snate@binkert.org if (objFile->getArch() != ObjectFile::Mips) 6447675Snate@binkert.org fatal("Object file architecture does not match compiled ISA (MIPS)."); 6457675Snate@binkert.org switch (objFile->getOpSys()) { 6467675Snate@binkert.org case ObjectFile::UnknownOpSys: 6477673Snate@binkert.org warn("Unknown operating system; assuming Linux."); 6487675Snate@binkert.org // fall through 6495517Snate@binkert.org case ObjectFile::Linux: 6507675Snate@binkert.org process = new MipsLinuxProcess(params, objFile); 6517675Snate@binkert.org break; 6527673Snate@binkert.org 6537675Snate@binkert.org default: 6547675Snate@binkert.org fatal("Unknown/unsupported operating system."); 6557677Snate@binkert.org } 6567675Snate@binkert.org#elif THE_ISA == ARM_ISA 6577675Snate@binkert.org ObjectFile::Arch arch = objFile->getArch(); 6587675Snate@binkert.org if (arch != ObjectFile::Arm && arch != ObjectFile::Thumb && 6595517Snate@binkert.org arch != ObjectFile::Arm64) 6607675Snate@binkert.org fatal("Object file architecture does not match compiled ISA (ARM)."); 6615517Snate@binkert.org switch (objFile->getOpSys()) { 6627673Snate@binkert.org case ObjectFile::UnknownOpSys: 6635517Snate@binkert.org warn("Unknown operating system; assuming Linux."); 6647675Snate@binkert.org // fall through 6657677Snate@binkert.org case ObjectFile::Linux: 6667756SAli.Saidi@ARM.com if (arch == ObjectFile::Arm64) { 6677816Ssteve.reinhardt@amd.com process = new ArmLinuxProcess64(params, objFile, 6687675Snate@binkert.org objFile->getArch()); 6697677Snate@binkert.org } else { 6704762Snate@binkert.org process = new ArmLinuxProcess32(params, objFile, 6717674Snate@binkert.org objFile->getArch()); 6727674Snate@binkert.org } 6737674Snate@binkert.org break; 6747674Snate@binkert.org case ObjectFile::FreeBSD: 6757674Snate@binkert.org if (arch == ObjectFile::Arm64) { 6767674Snate@binkert.org process = new ArmFreebsdProcess64(params, objFile, 6777674Snate@binkert.org objFile->getArch()); 6787674Snate@binkert.org } else { 6797674Snate@binkert.org process = new ArmFreebsdProcess32(params, objFile, 6807674Snate@binkert.org objFile->getArch()); 6817674Snate@binkert.org } 6827674Snate@binkert.org break; 6837674Snate@binkert.org case ObjectFile::LinuxArmOABI: 6847674Snate@binkert.org fatal("M5 does not support ARM OABI binaries. Please recompile with an" 6857674Snate@binkert.org " EABI compiler."); 6864762Snate@binkert.org default: 6876143Snate@binkert.org fatal("Unknown/unsupported operating system."); 6886143Snate@binkert.org } 6897756SAli.Saidi@ARM.com#elif THE_ISA == POWER_ISA 6907816Ssteve.reinhardt@amd.com if (objFile->getArch() != ObjectFile::Power) 6918235Snate@binkert.org fatal("Object file architecture does not match compiled ISA (Power)."); 6928235Snate@binkert.org switch (objFile->getOpSys()) { 6937756SAli.Saidi@ARM.com case ObjectFile::UnknownOpSys: 6947816Ssteve.reinhardt@amd.com warn("Unknown operating system; assuming Linux."); 6958235Snate@binkert.org // fall through 6964382Sbinkertn@umich.edu case ObjectFile::Linux: 6978232Snate@binkert.org process = new PowerLinuxProcess(params, objFile); 6988232Snate@binkert.org break; 6998232Snate@binkert.org 7008232Snate@binkert.org default: 7018232Snate@binkert.org fatal("Unknown/unsupported operating system."); 7026229Snate@binkert.org } 7038232Snate@binkert.org#else 7048232Snate@binkert.org#error "THE_ISA not set" 7058232Snate@binkert.org#endif 7066229Snate@binkert.org 7077673Snate@binkert.org if (process == NULL) 7085517Snate@binkert.org fatal("Unknown error creating process object."); 7095517Snate@binkert.org return process; 7107673Snate@binkert.org} 7115517Snate@binkert.org 7125517Snate@binkert.orgLiveProcess * 7135517Snate@binkert.orgLiveProcessParams::create() 7145517Snate@binkert.org{ 7158232Snate@binkert.org return LiveProcess::create(this); 7167673Snate@binkert.org} 7177673Snate@binkert.org