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