process.cc revision 11392:5967db4cff04
11689SN/A/*
29783Sandreas.hansson@arm.com * Copyright (c) 2014 Advanced Micro Devices, Inc.
37598Sminkyu.jeong@arm.com * Copyright (c) 2012 ARM Limited
47598Sminkyu.jeong@arm.com * All rights reserved
57598Sminkyu.jeong@arm.com *
67598Sminkyu.jeong@arm.com * The license below extends only to copyright in the software and shall
77598Sminkyu.jeong@arm.com * not be construed as granting a license to any other intellectual
87598Sminkyu.jeong@arm.com * property including but not limited to intellectual property relating
97598Sminkyu.jeong@arm.com * to a hardware implementation of the functionality of the software
107598Sminkyu.jeong@arm.com * licensed hereunder.  You may use the software subject to the license
117598Sminkyu.jeong@arm.com * terms below provided that you ensure that this notice is replicated
127598Sminkyu.jeong@arm.com * unmodified and in its entirety in all distributions of the software,
137598Sminkyu.jeong@arm.com * modified or unmodified, in source code or in binary form.
142326SN/A *
151689SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
161689SN/A * All rights reserved.
171689SN/A *
181689SN/A * Redistribution and use in source and binary forms, with or without
191689SN/A * modification, are permitted provided that the following conditions are
201689SN/A * met: redistributions of source code must retain the above copyright
211689SN/A * notice, this list of conditions and the following disclaimer;
221689SN/A * redistributions in binary form must reproduce the above copyright
231689SN/A * notice, this list of conditions and the following disclaimer in the
241689SN/A * documentation and/or other materials provided with the distribution;
251689SN/A * neither the name of the copyright holders nor the names of its
261689SN/A * contributors may be used to endorse or promote products derived from
271689SN/A * this software without specific prior written permission.
281689SN/A *
291689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
321689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
331689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
341689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
351689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
361689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
371689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381689SN/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 *
411689SN/A * Authors: Nathan Binkert
421689SN/A *          Steve Reinhardt
439944Smatt.horsnell@ARM.com *          Ali Saidi
449944Smatt.horsnell@ARM.com */
459944Smatt.horsnell@ARM.com
461060SN/A#include <fcntl.h>
471060SN/A#include <unistd.h>
481689SN/A
491060SN/A#include <cstdio>
501060SN/A#include <map>
511060SN/A#include <string>
528230Snate@binkert.org
536658Snate@binkert.org#include "base/loader/object_file.hh"
548887Sgeoffrey.blake@arm.com#include "base/loader/symtab.hh"
552292SN/A#include "base/intmath.hh"
561717SN/A#include "base/statistics.hh"
578229Snate@binkert.org#include "config/the_isa.hh"
588232Snate@binkert.org#include "cpu/thread_context.hh"
599444SAndreas.Sandberg@ARM.com#include "mem/page_table.hh"
608232Snate@binkert.org#include "mem/multi_level_page_table.hh"
619527SMatt.Horsnell@arm.com#include "mem/se_translating_port_proxy.hh"
625529Snate@binkert.org#include "params/LiveProcess.hh"
631060SN/A#include "params/Process.hh"
646221Snate@binkert.org#include "sim/debug.hh"
656221Snate@binkert.org#include "sim/process.hh"
661681SN/A#include "sim/process_impl.hh"
675529Snate@binkert.org#include "sim/stats.hh"
682873Sktlim@umich.edu#include "sim/syscall_emul.hh"
694329Sktlim@umich.edu#include "sim/system.hh"
704329Sktlim@umich.edu
714329Sktlim@umich.edu#if THE_ISA == ALPHA_ISA
722292SN/A#include "arch/alpha/linux/process.hh"
732292SN/A#include "arch/alpha/tru64/process.hh"
742292SN/A#elif THE_ISA == SPARC_ISA
752292SN/A#include "arch/sparc/linux/process.hh"
762820Sktlim@umich.edu#include "arch/sparc/solaris/process.hh"
772292SN/A#elif THE_ISA == MIPS_ISA
782820Sktlim@umich.edu#include "arch/mips/linux/process.hh"
792820Sktlim@umich.edu#elif THE_ISA == ARM_ISA
809444SAndreas.Sandberg@ARM.com#include "arch/arm/linux/process.hh"
811060SN/A#include "arch/arm/freebsd/process.hh"
8210172Sdam.sunwoo@arm.com#elif THE_ISA == X86_ISA
8310172Sdam.sunwoo@arm.com#include "arch/x86/linux/process.hh"
8410172Sdam.sunwoo@arm.com#elif THE_ISA == POWER_ISA
8510172Sdam.sunwoo@arm.com#include "arch/power/linux/process.hh"
8610172Sdam.sunwoo@arm.com#else
8710172Sdam.sunwoo@arm.com#error "THE_ISA not set"
8810172Sdam.sunwoo@arm.com#endif
8910172Sdam.sunwoo@arm.com
9010172Sdam.sunwoo@arm.com
9110172Sdam.sunwoo@arm.comusing namespace std;
9210172Sdam.sunwoo@arm.comusing namespace TheISA;
9310172Sdam.sunwoo@arm.com
9410172Sdam.sunwoo@arm.com// current number of allocated processes
952292SN/Aint num_processes = 0;
962292SN/A
972292SN/Atemplate<class IntType>
981060SN/A
991060SN/AAuxVector<IntType>::AuxVector(IntType type, IntType val)
1001060SN/A{
1011060SN/A    a_type = TheISA::htog(type);
1021060SN/A    a_val = TheISA::htog(val);
1031060SN/A}
1041681SN/A
1056221Snate@binkert.orgtemplate struct AuxVector<uint32_t>;
1066221Snate@binkert.orgtemplate struct AuxVector<uint64_t>;
1076221Snate@binkert.org
1086221Snate@binkert.orgstatic int
1092292SN/AopenFile(const string& filename, int flags, mode_t mode)
1102292SN/A{
1112820Sktlim@umich.edu    int sim_fd = open(filename.c_str(), flags, mode);
1122820Sktlim@umich.edu    if (sim_fd != -1)
1132292SN/A        return sim_fd;
1142292SN/A    fatal("Unable to open %s with mode %O", filename, mode);
1152820Sktlim@umich.edu}
1162820Sktlim@umich.edu
1172292SN/Astatic int
1182292SN/AopenInputFile(const string &filename)
1192292SN/A{
1202292SN/A    return openFile(filename, O_RDONLY, 0);
1212292SN/A}
1222292SN/A
1232292SN/Astatic int
1242292SN/AopenOutputFile(const string &filename)
1251060SN/A{
1261060SN/A    return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
1271681SN/A}
1281062SN/A
12910023Smatt.horsnell@ARM.comProcess::Process(ProcessParams * params)
13010023Smatt.horsnell@ARM.com    : SimObject(params), system(params->system),
13110023Smatt.horsnell@ARM.com      brk_point(0), stack_base(0), stack_size(0), stack_min(0),
13210023Smatt.horsnell@ARM.com      max_stack_size(params->max_stack_size),
13310023Smatt.horsnell@ARM.com      next_thread_stack_base(0),
13410023Smatt.horsnell@ARM.com      M5_pid(system->allocatePID()),
13510023Smatt.horsnell@ARM.com      useArchPT(params->useArchPT),
13610023Smatt.horsnell@ARM.com      kvmInSE(params->kvmInSE),
1372292SN/A      pTable(useArchPT ?
1381062SN/A        static_cast<PageTableBase *>(new ArchPageTable(name(), M5_pid, system)) :
1392301SN/A        static_cast<PageTableBase *>(new FuncPageTable(name(), M5_pid)) ),
1402301SN/A      initVirtMem(system->getSystemPort(), this,
1411062SN/A                  SETranslatingPortProxy::Always),
1422727Sktlim@umich.edu      fd_array(make_shared<array<FDEntry, NUM_FDS>>()),
1431062SN/A      imap {{"",       -1},
1441062SN/A            {"cin",    STDIN_FILENO},
1451062SN/A            {"stdin",  STDIN_FILENO}},
1461062SN/A      oemap{{"",       -1},
1471062SN/A            {"cout",   STDOUT_FILENO},
1481062SN/A            {"stdout", STDOUT_FILENO},
1491062SN/A            {"cerr",   STDERR_FILENO},
1501062SN/A            {"stderr", STDERR_FILENO}}
1511062SN/A{
1521062SN/A    int sim_fd;
1531062SN/A    std::map<string,int>::iterator it;
1541062SN/A
1551062SN/A    // Search through the input options and set fd if match is found;
1561062SN/A    // otherwise, open an input file and seek to location.
1571062SN/A    FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
1581062SN/A    if ((it = imap.find(params->input)) != imap.end())
1591062SN/A        sim_fd = it->second;
1601062SN/A    else
1611062SN/A        sim_fd = openInputFile(params->input);
1621062SN/A    fde_stdin->set(sim_fd, params->input, O_RDONLY, -1, false);
1631062SN/A
1641062SN/A    // Search through the output/error options and set fd if match is found;
1651062SN/A    // otherwise, open an output file and seek to location.
1661062SN/A    FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
1671062SN/A    if ((it = oemap.find(params->output)) != oemap.end())
1681062SN/A        sim_fd = it->second;
1691062SN/A    else
1701062SN/A        sim_fd = openOutputFile(params->output);
1711062SN/A    fde_stdout->set(sim_fd, params->output, O_WRONLY | O_CREAT | O_TRUNC,
1721062SN/A                    0664, false);
1731062SN/A
1741062SN/A    FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
1751062SN/A    if (params->output == params->errout)
1761062SN/A        // Reuse the same file descriptor if these match.
1771062SN/A        sim_fd = fde_stdout->fd;
1781062SN/A    else if ((it = oemap.find(params->errout)) != oemap.end())
1791062SN/A        sim_fd = it->second;
1801062SN/A    else
1811062SN/A        sim_fd = openOutputFile(params->errout);
1821062SN/A    fde_stderr->set(sim_fd, params->errout, O_WRONLY | O_CREAT | O_TRUNC,
1831062SN/A                    0664, false);
1842292SN/A
1852292SN/A    mmap_end = 0;
1862292SN/A    nxm_start = nxm_end = 0;
1872292SN/A    // other parameters will be initialized when the program is loaded
1881062SN/A}
1891062SN/A
1901062SN/A
1911062SN/Avoid
1921062SN/AProcess::regStats()
1931062SN/A{
1941062SN/A    using namespace Stats;
1952292SN/A
1962292SN/A    num_syscalls
1972292SN/A        .name(name() + ".num_syscalls")
1982292SN/A        .desc("Number of system calls")
1992292SN/A        ;
2002292SN/A}
2012292SN/A
2022292SN/Avoid
2032292SN/AProcess::inheritFDArray(Process *p)
2042292SN/A{
2052301SN/A    fd_array = p->fd_array;
2062727Sktlim@umich.edu}
2072353SN/A
2082727Sktlim@umich.eduThreadContext *
2092727Sktlim@umich.eduProcess::findFreeContext()
2102727Sktlim@umich.edu{
2116221Snate@binkert.org    for (int id : contextIds) {
2122353SN/A        ThreadContext *tc = system->getThreadContext(id);
2132727Sktlim@umich.edu        if (tc->status() == ThreadContext::Halted)
2142727Sktlim@umich.edu            return tc;
2152727Sktlim@umich.edu    }
2162727Sktlim@umich.edu    return NULL;
2172353SN/A}
2182727Sktlim@umich.edu
2192727Sktlim@umich.eduvoid
2202727Sktlim@umich.eduProcess::initState()
2216221Snate@binkert.org{
2228240Snate@binkert.org    if (contextIds.empty())
2232301SN/A        fatal("Process %s is not associated with any HW contexts!\n", name());
2242727Sktlim@umich.edu
2252301SN/A    // first thread context for this process... initialize & enable
2262727Sktlim@umich.edu    ThreadContext *tc = system->getThreadContext(contextIds[0]);
2276221Snate@binkert.org
2288240Snate@binkert.org    // mark this context as active so it will start ticking.
2292301SN/A    tc->activate();
2302727Sktlim@umich.edu
2312301SN/A    pTable->initState(tc);
2322727Sktlim@umich.edu}
2336221Snate@binkert.org
2348240Snate@binkert.orgDrainState
2352301SN/AProcess::drain()
2362727Sktlim@umich.edu{
2372301SN/A    findFileOffsets();
2382727Sktlim@umich.edu    return DrainState::Drained;
2396221Snate@binkert.org}
2408240Snate@binkert.org
2412301SN/Aint
2422727Sktlim@umich.eduProcess::allocFD(int sim_fd, const string& filename, int flags, int mode,
2432301SN/A                 bool pipe)
2442301SN/A{
2458240Snate@binkert.org    for (int free_fd = 0; free_fd < fd_array->size(); free_fd++) {
2462301SN/A        FDEntry *fde = getFDEntry(free_fd);
2472727Sktlim@umich.edu        if (fde->isFree()) {
2482727Sktlim@umich.edu            fde->set(sim_fd, filename, flags, mode, pipe);
2492727Sktlim@umich.edu            return free_fd;
2502727Sktlim@umich.edu        }
2518240Snate@binkert.org    }
2522727Sktlim@umich.edu
2532727Sktlim@umich.edu    fatal("Out of target file descriptors");
2542727Sktlim@umich.edu}
2552727Sktlim@umich.edu
2562301SN/Avoid
2572301SN/AProcess::resetFDEntry(int tgt_fd)
2586221Snate@binkert.org{
2598240Snate@binkert.org    FDEntry *fde = getFDEntry(tgt_fd);
2602301SN/A    assert(fde->fd > -1);
2612727Sktlim@umich.edu
2622301SN/A    fde->reset();
2632326SN/A}
2646221Snate@binkert.org
2658240Snate@binkert.orgint
2662301SN/AProcess::getSimFD(int tgt_fd)
2672727Sktlim@umich.edu{
2682301SN/A    FDEntry *entry = getFDEntry(tgt_fd);
2692326SN/A    return entry ? entry->fd : -1;
2706221Snate@binkert.org}
2718240Snate@binkert.org
2722301SN/AFDEntry *
2732727Sktlim@umich.eduProcess::getFDEntry(int tgt_fd)
2742301SN/A{
2752326SN/A    assert(0 <= tgt_fd && tgt_fd < fd_array->size());
2766221Snate@binkert.org    return &(*fd_array)[tgt_fd];
2778240Snate@binkert.org}
2782301SN/A
2792727Sktlim@umich.eduint
2802301SN/AProcess::getTgtFD(int sim_fd)
2812326SN/A{
2826221Snate@binkert.org    for (int index = 0; index < fd_array->size(); index++)
2838240Snate@binkert.org        if ((*fd_array)[index].fd == sim_fd)
2842301SN/A            return index;
2852727Sktlim@umich.edu    return -1;
2862301SN/A}
2872326SN/A
2888240Snate@binkert.orgvoid
2892301SN/AProcess::allocateMem(Addr vaddr, int64_t size, bool clobber)
2902727Sktlim@umich.edu{
2912301SN/A    int npages = divCeil(size, (int64_t)PageBytes);
2922326SN/A    Addr paddr = system->allocPhysPages(npages);
2932301SN/A    pTable->map(vaddr, paddr, size,
2942326SN/A                clobber ? PageTableBase::Clobber : PageTableBase::Zero);
2958240Snate@binkert.org}
2962301SN/A
2972727Sktlim@umich.edubool
2982301SN/AProcess::fixupStackFault(Addr vaddr)
2992326SN/A{
3002301SN/A    // Check if this is already on the stack and there's just no page there
3012326SN/A    // yet.
3028240Snate@binkert.org    if (vaddr >= stack_min && vaddr < stack_base) {
3032301SN/A        allocateMem(roundDown(vaddr, PageBytes), PageBytes);
3042727Sktlim@umich.edu        return true;
3052326SN/A    }
3061062SN/A
3071062SN/A    // We've accessed the next page of the stack, so extend it to include
3081681SN/A    // this address.
3091060SN/A    if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
3109427SAndreas.Sandberg@ARM.com        while (vaddr < stack_min) {
3111060SN/A            stack_min -= TheISA::PageBytes;
3126221Snate@binkert.org            if (stack_base - stack_min > max_stack_size)
3132292SN/A                fatal("Maximum stack size exceeded\n");
3142292SN/A            allocateMem(stack_min, TheISA::PageBytes);
3152292SN/A            inform("Increasing stack size by one page.");
3162292SN/A        };
3172292SN/A        return true;
3182292SN/A    }
3192292SN/A    return false;
3202292SN/A}
3212292SN/A
3228887Sgeoffrey.blake@arm.comvoid
3238733Sgeoffrey.blake@arm.comProcess::fixFileOffsets()
3248850Sandreas.hansson@arm.com{
3258887Sgeoffrey.blake@arm.com    auto seek = [] (FDEntry *fde)
3268733Sgeoffrey.blake@arm.com    {
3272733Sktlim@umich.edu        if (lseek(fde->fd, fde->fileOffset, SEEK_SET) < 0)
3281060SN/A            fatal("Unable to see to location in %s", fde->filename);
3291060SN/A    };
3301681SN/A
3311060SN/A    std::map<string,int>::iterator it;
3322292SN/A
3331060SN/A    // Search through the input options and set fd if match is found;
3341060SN/A    // otherwise, open an input file and seek to location.
3351060SN/A    FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
3361060SN/A    if ((it = imap.find(fde_stdin->filename)) != imap.end()) {
3371060SN/A        fde_stdin->fd = it->second;
3381060SN/A    } else {
3391060SN/A        fde_stdin->fd = openInputFile(fde_stdin->filename);
3401060SN/A        seek(fde_stdin);
3411060SN/A    }
3422292SN/A
3432292SN/A    // Search through the output/error options and set fd if match is found;
3441060SN/A    // otherwise, open an output file and seek to location.
3451060SN/A    FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
3461060SN/A    if ((it = oemap.find(fde_stdout->filename)) != oemap.end()) {
3471060SN/A        fde_stdout->fd = it->second;
3481681SN/A    } else {
3491060SN/A        fde_stdout->fd = openOutputFile(fde_stdout->filename);
3502292SN/A        seek(fde_stdout);
3511060SN/A    }
3521060SN/A
3531060SN/A    FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
3541060SN/A    if (fde_stdout->filename == fde_stderr->filename) {
3551060SN/A        // Reuse the same file descriptor if these match.
3561060SN/A        fde_stderr->fd = fde_stdout->fd;
3571060SN/A    } else if ((it = oemap.find(fde_stderr->filename)) != oemap.end()) {
3581681SN/A        fde_stderr->fd = it->second;
3591060SN/A    } else {
3602292SN/A        fde_stderr->fd = openOutputFile(fde_stderr->filename);
3611060SN/A        seek(fde_stderr);
3621060SN/A    }
3631060SN/A
3641060SN/A    for (int tgt_fd = 3; tgt_fd < fd_array->size(); tgt_fd++) {
3651060SN/A        FDEntry *fde = getFDEntry(tgt_fd);
3661060SN/A        if (fde->fd == -1)
3671060SN/A            continue;
3681681SN/A
3691060SN/A        if (fde->isPipe) {
3706221Snate@binkert.org            if (fde->filename == "PIPE-WRITE")
3711060SN/A                continue;
3722292SN/A            assert(fde->filename == "PIPE-READ");
3732292SN/A
3742292SN/A            int fds[2];
3752292SN/A            if (pipe(fds) < 0)
3761060SN/A                fatal("Unable to create new pipe");
3771060SN/A
3781681SN/A            fde->fd = fds[0];
3791060SN/A
3802292SN/A            FDEntry *fde_write = getFDEntry(fde->readPipeSource);
3811060SN/A            assert(fde_write->filename == "PIPE-WRITE");
3822292SN/A            fde_write->fd = fds[1];
3831060SN/A        } else {
3841060SN/A            fde->fd = openFile(fde->filename.c_str(), fde->flags, fde->mode);
3852307SN/A            seek(fde);
3862863Sktlim@umich.edu        }
3879444SAndreas.Sandberg@ARM.com    }
3882307SN/A}
3899444SAndreas.Sandberg@ARM.com
3909444SAndreas.Sandberg@ARM.comvoid
3919444SAndreas.Sandberg@ARM.comProcess::findFileOffsets()
3929444SAndreas.Sandberg@ARM.com{
3939444SAndreas.Sandberg@ARM.com    for (auto& fde : *fd_array) {
3949444SAndreas.Sandberg@ARM.com        if (fde.fd != -1)
3959444SAndreas.Sandberg@ARM.com            fde.fileOffset = lseek(fde.fd, 0, SEEK_CUR);
3969444SAndreas.Sandberg@ARM.com    }
3979444SAndreas.Sandberg@ARM.com}
3989444SAndreas.Sandberg@ARM.com
3999444SAndreas.Sandberg@ARM.comvoid
4009444SAndreas.Sandberg@ARM.comProcess::setReadPipeSource(int read_pipe_fd, int source_fd)
4019444SAndreas.Sandberg@ARM.com{
4029783Sandreas.hansson@arm.com    FDEntry *fde = getFDEntry(read_pipe_fd);
4039783Sandreas.hansson@arm.com    assert(source_fd >= -1);
4049783Sandreas.hansson@arm.com    fde->readPipeSource = source_fd;
4059783Sandreas.hansson@arm.com}
4069783Sandreas.hansson@arm.com
4079783Sandreas.hansson@arm.comvoid
4089783Sandreas.hansson@arm.comProcess::serialize(CheckpointOut &cp) const
4099783Sandreas.hansson@arm.com{
4109444SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(brk_point);
4111681SN/A    SERIALIZE_SCALAR(stack_base);
4121681SN/A    SERIALIZE_SCALAR(stack_size);
4132316SN/A    SERIALIZE_SCALAR(stack_min);
4141681SN/A    SERIALIZE_SCALAR(next_thread_stack_base);
4159444SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(mmap_end);
4162843Sktlim@umich.edu    SERIALIZE_SCALAR(nxm_start);
4179444SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(nxm_end);
4182843Sktlim@umich.edu    pTable->serialize(cp);
4199444SAndreas.Sandberg@ARM.com    for (int x = 0; x < fd_array->size(); x++) {
4209444SAndreas.Sandberg@ARM.com        (*fd_array)[x].serializeSection(cp, csprintf("FDEntry%d", x));
4211681SN/A    }
4221681SN/A    SERIALIZE_SCALAR(M5_pid);
4232307SN/A
4241681SN/A}
4252307SN/A
4261060SN/Avoid
4272348SN/AProcess::unserialize(CheckpointIn &cp)
4282307SN/A{
4292307SN/A    UNSERIALIZE_SCALAR(brk_point);
4302307SN/A    UNSERIALIZE_SCALAR(stack_base);
4311060SN/A    UNSERIALIZE_SCALAR(stack_size);
4322307SN/A    UNSERIALIZE_SCALAR(stack_min);
4332307SN/A    UNSERIALIZE_SCALAR(next_thread_stack_base);
4349444SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(mmap_end);
4351060SN/A    UNSERIALIZE_SCALAR(nxm_start);
4369427SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(nxm_end);
4372307SN/A    pTable->unserialize(cp);
4381060SN/A    for (int x = 0; x < fd_array->size(); x++) {
4396221Snate@binkert.org        FDEntry *fde = getFDEntry(x);
4406221Snate@binkert.org        fde->unserializeSection(cp, csprintf("FDEntry%d", x));
4416221Snate@binkert.org    }
4426221Snate@binkert.org    fixFileOffsets();
4432307SN/A    UNSERIALIZE_OPT_SCALAR(M5_pid);
4441060SN/A    // The above returns a bool so that you could do something if you don't
4452307SN/A    // find the param in the checkpoint if you wanted to, like set a default
4462307SN/A    // but in this case we'll just stick with the instantiated value if not
4472873Sktlim@umich.edu    // found.
4482307SN/A}
4491060SN/A
4501060SN/A
4511060SN/Abool
4521681SN/AProcess::map(Addr vaddr, Addr paddr, int size, bool cacheable)
4531060SN/A{
4546221Snate@binkert.org    pTable->map(vaddr, paddr, size,
4552107SN/A                cacheable ? PageTableBase::Zero : PageTableBase::Uncacheable);
4566221Snate@binkert.org    return true;
4572107SN/A}
4582292SN/A
4592292SN/A
4602107SN/A////////////////////////////////////////////////////////////////////////
4612292SN/A//
4622326SN/A// LiveProcess member definitions
4632292SN/A//
4642107SN/A////////////////////////////////////////////////////////////////////////
4652292SN/A
4662935Sksewell@umich.edu
4674632Sgblack@eecs.umich.eduLiveProcess::LiveProcess(LiveProcessParams *params, ObjectFile *_objFile)
4682935Sksewell@umich.edu    : Process(params), objFile(_objFile),
4692292SN/A      argv(params->cmd), envp(params->env), cwd(params->cwd),
4702292SN/A      executable(params->executable),
4712292SN/A      __uid(params->uid), __euid(params->euid),
4722292SN/A      __gid(params->gid), __egid(params->egid),
4732292SN/A      __pid(params->pid), __ppid(params->ppid),
4742107SN/A      drivers(params->drivers)
4752292SN/A{
4762107SN/A
4772292SN/A    // load up symbols, if any... these may be used for debugging or
4782292SN/A    // profiling.
4792107SN/A    if (!debugSymbolTable) {
4802702Sktlim@umich.edu        debugSymbolTable = new SymbolTable();
4812107SN/A        if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
4822107SN/A            !objFile->loadLocalSymbols(debugSymbolTable) ||
4832107SN/A            !objFile->loadWeakSymbols(debugSymbolTable)) {
4842107SN/A            // didn't load any symbols
4856221Snate@binkert.org            delete debugSymbolTable;
4862292SN/A            debugSymbolTable = NULL;
4877720Sgblack@eecs.umich.edu        }
4887720Sgblack@eecs.umich.edu    }
4892292SN/A}
49010231Ssteve.reinhardt@amd.com
4917852SMatt.Horsnell@arm.comvoid
4927852SMatt.Horsnell@arm.comLiveProcess::syscall(int64_t callnum, ThreadContext *tc)
4937852SMatt.Horsnell@arm.com{
4947852SMatt.Horsnell@arm.com    num_syscalls++;
4952935Sksewell@umich.edu
4967852SMatt.Horsnell@arm.com    SyscallDesc *desc = getDesc(callnum);
4977852SMatt.Horsnell@arm.com    if (desc == NULL)
4982292SN/A        fatal("Syscall %d out of range", callnum);
4997852SMatt.Horsnell@arm.com
5007852SMatt.Horsnell@arm.com    desc->doSyscall(callnum, this, tc);
5017852SMatt.Horsnell@arm.com}
5022292SN/A
5037852SMatt.Horsnell@arm.comIntReg
5047852SMatt.Horsnell@arm.comLiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
5057852SMatt.Horsnell@arm.com{
5062292SN/A    return getSyscallArg(tc, i);
5072292SN/A}
5082292SN/A
5092292SN/A
5106221Snate@binkert.orgEmulatedDriver *
5112292SN/ALiveProcess::findDriver(std::string filename)
5128513SGiacomo.Gabrielli@arm.com{
5138513SGiacomo.Gabrielli@arm.com    for (EmulatedDriver *d : drivers) {
5148513SGiacomo.Gabrielli@arm.com        if (d->match(filename))
5158513SGiacomo.Gabrielli@arm.com            return d;
5168513SGiacomo.Gabrielli@arm.com    }
5178513SGiacomo.Gabrielli@arm.com
5188513SGiacomo.Gabrielli@arm.com    return NULL;
5198513SGiacomo.Gabrielli@arm.com}
52010231Ssteve.reinhardt@amd.com
5218513SGiacomo.Gabrielli@arm.comvoid
5228513SGiacomo.Gabrielli@arm.comLiveProcess::updateBias()
5232292SN/A{
5247852SMatt.Horsnell@arm.com    ObjectFile *interp = objFile->getInterpreter();
5258513SGiacomo.Gabrielli@arm.com
5268137SAli.Saidi@ARM.com    if (!interp || !interp->relocatable())
5272292SN/A        return;
5288513SGiacomo.Gabrielli@arm.com
5298513SGiacomo.Gabrielli@arm.com    // Determine how large the interpreters footprint will be in the process
5302292SN/A    // address space.
5317852SMatt.Horsnell@arm.com    Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
5327852SMatt.Horsnell@arm.com
5332292SN/A    // We are allocating the memory area; set the bias to the lowest address
5342292SN/A    // in the allocated memory region.
5352292SN/A    Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
5362292SN/A
5376221Snate@binkert.org    // Adjust the process mmap area to give the interpreter room; the real
5382292SN/A    // execve system call would just invoke the kernel's internal mmap
5392292SN/A    // functions to make these adjustments.
5407720Sgblack@eecs.umich.edu    mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
54110231Ssteve.reinhardt@amd.com
5427852SMatt.Horsnell@arm.com    interp->updateBias(ld_bias);
5437852SMatt.Horsnell@arm.com}
5442292SN/A
5457852SMatt.Horsnell@arm.com
5467852SMatt.Horsnell@arm.comObjectFile *
5478137SAli.Saidi@ARM.comLiveProcess::getInterpreter()
5482292SN/A{
5497852SMatt.Horsnell@arm.com    return objFile->getInterpreter();
5507852SMatt.Horsnell@arm.com}
5512292SN/A
5527852SMatt.Horsnell@arm.com
5532292SN/AAddr
5547852SMatt.Horsnell@arm.comLiveProcess::getBias()
5557852SMatt.Horsnell@arm.com{
5562292SN/A    ObjectFile *interp = getInterpreter();
5572292SN/A
5582292SN/A    return interp ? interp->bias() : objFile->bias();
5592292SN/A}
5606221Snate@binkert.org
5612292SN/A
5622292SN/AAddr
5632292SN/ALiveProcess::getStartPC()
5642292SN/A{
5652292SN/A    ObjectFile *interp = getInterpreter();
5662292SN/A
5672292SN/A    return interp ? interp->entryPoint() : objFile->entryPoint();
5682292SN/A}
5692292SN/A
5702292SN/A
5712292SN/ALiveProcess *
5722292SN/ALiveProcess::create(LiveProcessParams * params)
5732292SN/A{
5742292SN/A    LiveProcess *process = NULL;
5752292SN/A
5762292SN/A    // If not specified, set the executable parameter equal to the
5772292SN/A    // simulated system's zeroth command line parameter
5782292SN/A    if (params->executable == "") {
5796221Snate@binkert.org        params->executable = params->cmd[0];
5802292SN/A    }
5812292SN/A
5822292SN/A    ObjectFile *objFile = createObjectFile(params->executable);
5832292SN/A    if (objFile == NULL) {
5842292SN/A        fatal("Can't load object file %s", params->executable);
5852292SN/A    }
5862292SN/A
5872292SN/A#if THE_ISA == ALPHA_ISA
5882292SN/A    if (objFile->getArch() != ObjectFile::Alpha)
5892292SN/A        fatal("Object file architecture does not match compiled ISA (Alpha).");
5902292SN/A
5912292SN/A    switch (objFile->getOpSys()) {
5922292SN/A      case ObjectFile::Tru64:
5932292SN/A        process = new AlphaTru64Process(params, objFile);
5942292SN/A        break;
5952292SN/A
5962292SN/A      case ObjectFile::UnknownOpSys:
5971060SN/A        warn("Unknown operating system; assuming Linux.");
5981681SN/A        // fall through
5991060SN/A      case ObjectFile::Linux:
6001060SN/A        process = new AlphaLinuxProcess(params, objFile);
6012292SN/A        break;
6022292SN/A
6032292SN/A      default:
6042292SN/A        fatal("Unknown/unsupported operating system.");
6052292SN/A    }
6062292SN/A#elif THE_ISA == SPARC_ISA
6071681SN/A    if (objFile->getArch() != ObjectFile::SPARC64 &&
6081681SN/A        objFile->getArch() != ObjectFile::SPARC32)
6091060SN/A        fatal("Object file architecture does not match compiled ISA (SPARC).");
6102292SN/A    switch (objFile->getOpSys()) {
6111060SN/A      case ObjectFile::UnknownOpSys:
6122292SN/A        warn("Unknown operating system; assuming Linux.");
6132292SN/A        // fall through
6141060SN/A      case ObjectFile::Linux:
6152292SN/A        if (objFile->getArch() == ObjectFile::SPARC64) {
6162292SN/A            process = new Sparc64LinuxProcess(params, objFile);
6172292SN/A        } else {
6182292SN/A            process = new Sparc32LinuxProcess(params, objFile);
6193221Sktlim@umich.edu        }
6203221Sktlim@umich.edu        break;
6213221Sktlim@umich.edu
6223221Sktlim@umich.edu
6233221Sktlim@umich.edu      case ObjectFile::Solaris:
6242292SN/A        process = new SparcSolarisProcess(params, objFile);
6252292SN/A        break;
6262292SN/A
6272292SN/A      default:
6282326SN/A        fatal("Unknown/unsupported operating system.");
6292292SN/A    }
6302292SN/A#elif THE_ISA == X86_ISA
6312820Sktlim@umich.edu    if (objFile->getArch() != ObjectFile::X86_64 &&
6322292SN/A        objFile->getArch() != ObjectFile::I386)
6332292SN/A        fatal("Object file architecture does not match compiled ISA (x86).");
6342292SN/A    switch (objFile->getOpSys()) {
6352292SN/A      case ObjectFile::UnknownOpSys:
6362353SN/A        warn("Unknown operating system; assuming Linux.");
6372292SN/A        // fall through
6382292SN/A      case ObjectFile::Linux:
6392353SN/A        if (objFile->getArch() == ObjectFile::X86_64) {
6402353SN/A            process = new X86_64LinuxProcess(params, objFile);
6412292SN/A        } else {
6422292SN/A            process = new I386LinuxProcess(params, objFile);
6432292SN/A        }
6442292SN/A        break;
6452292SN/A
6462292SN/A      default:
6472292SN/A        fatal("Unknown/unsupported operating system.");
6482292SN/A    }
6492292SN/A#elif THE_ISA == MIPS_ISA
6502292SN/A    if (objFile->getArch() != ObjectFile::Mips)
6512292SN/A        fatal("Object file architecture does not match compiled ISA (MIPS).");
6522292SN/A    switch (objFile->getOpSys()) {
6532731Sktlim@umich.edu      case ObjectFile::UnknownOpSys:
6542292SN/A        warn("Unknown operating system; assuming Linux.");
6552292SN/A        // fall through
6562292SN/A      case ObjectFile::Linux:
6572292SN/A        process = new MipsLinuxProcess(params, objFile);
6582292SN/A        break;
6592292SN/A
6602292SN/A      default:
6612292SN/A        fatal("Unknown/unsupported operating system.");
6626221Snate@binkert.org    }
6632292SN/A#elif THE_ISA == ARM_ISA
6642292SN/A    ObjectFile::Arch arch = objFile->getArch();
6652292SN/A    if (arch != ObjectFile::Arm && arch != ObjectFile::Thumb &&
6662292SN/A        arch != ObjectFile::Arm64)
6672292SN/A        fatal("Object file architecture does not match compiled ISA (ARM).");
6682292SN/A    switch (objFile->getOpSys()) {
6692292SN/A      case ObjectFile::UnknownOpSys:
6702292SN/A        warn("Unknown operating system; assuming Linux.");
6719937SFaissal.Sleiman@arm.com        // fall through
6722292SN/A      case ObjectFile::Linux:
6737720Sgblack@eecs.umich.edu        if (arch == ObjectFile::Arm64) {
6742292SN/A            process = new ArmLinuxProcess64(params, objFile,
6752292SN/A                                            objFile->getArch());
6762292SN/A        } else {
6772292SN/A            process = new ArmLinuxProcess32(params, objFile,
6782292SN/A                                            objFile->getArch());
6792292SN/A        }
6802292SN/A        break;
6812292SN/A      case ObjectFile::FreeBSD:
6822292SN/A        if (arch == ObjectFile::Arm64) {
6832292SN/A            process = new ArmFreebsdProcess64(params, objFile,
6842292SN/A                                              objFile->getArch());
6852292SN/A        } else {
6862292SN/A            process = new ArmFreebsdProcess32(params, objFile,
6872292SN/A                                              objFile->getArch());
6886221Snate@binkert.org        }
6896221Snate@binkert.org        break;
6902292SN/A      case ObjectFile::LinuxArmOABI:
6913867Sbinkertn@umich.edu        fatal("M5 does not support ARM OABI binaries. Please recompile with an"
6926221Snate@binkert.org              " EABI compiler.");
6933867Sbinkertn@umich.edu      default:
6942292SN/A        fatal("Unknown/unsupported operating system.");
6952292SN/A    }
6962292SN/A#elif THE_ISA == POWER_ISA
6972292SN/A    if (objFile->getArch() != ObjectFile::Power)
6982292SN/A        fatal("Object file architecture does not match compiled ISA (Power).");
6992292SN/A    switch (objFile->getOpSys()) {
7002292SN/A      case ObjectFile::UnknownOpSys:
7012292SN/A        warn("Unknown operating system; assuming Linux.");
7022292SN/A        // fall through
7032292SN/A      case ObjectFile::Linux:
7042292SN/A        process = new PowerLinuxProcess(params, objFile);
7056221Snate@binkert.org        break;
7066221Snate@binkert.org
7072292SN/A      default:
7083867Sbinkertn@umich.edu        fatal("Unknown/unsupported operating system.");
7096221Snate@binkert.org    }
7103867Sbinkertn@umich.edu#else
7113867Sbinkertn@umich.edu#error "THE_ISA not set"
7122292SN/A#endif
7132292SN/A
7142292SN/A    if (process == NULL)
7152292SN/A        fatal("Unknown error creating process object.");
7161062SN/A    return process;
7171062SN/A}
7181681SN/A
7191062SN/ALiveProcess *
7202292SN/ALiveProcessParams::create()
7211062SN/A{
7222292SN/A    return LiveProcess::create(this);
7231062SN/A}
7246221Snate@binkert.org