process.cc revision 11813
16313Sgblack@eecs.umich.edu/*
26313Sgblack@eecs.umich.edu * Copyright (c) 2014 Advanced Micro Devices, Inc.
36313Sgblack@eecs.umich.edu * Copyright (c) 2012 ARM Limited
46313Sgblack@eecs.umich.edu * All rights reserved
56313Sgblack@eecs.umich.edu *
66313Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
76313Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
86313Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
96313Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
106313Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
116313Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
126313Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
136313Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
146313Sgblack@eecs.umich.edu *
156313Sgblack@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan
166313Sgblack@eecs.umich.edu * All rights reserved.
176313Sgblack@eecs.umich.edu *
186313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
196313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
206313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
216313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
226313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
236313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
246313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
256313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
266313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
276313Sgblack@eecs.umich.edu * this software without specific prior written permission.
286313Sgblack@eecs.umich.edu *
296313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
306313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
316313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
326313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
336313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
346359Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
356336Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
366336Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
376336Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
386336Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
396336Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
406336Sgblack@eecs.umich.edu *
416313Sgblack@eecs.umich.edu * Authors: Nathan Binkert
426313Sgblack@eecs.umich.edu *          Steve Reinhardt
436313Sgblack@eecs.umich.edu *          Ali Saidi
446336Sgblack@eecs.umich.edu */
456313Sgblack@eecs.umich.edu
466313Sgblack@eecs.umich.edu#include "sim/process.hh"
476313Sgblack@eecs.umich.edu
486313Sgblack@eecs.umich.edu#include <fcntl.h>
496313Sgblack@eecs.umich.edu#include <unistd.h>
506313Sgblack@eecs.umich.edu
516336Sgblack@eecs.umich.edu#include <array>
526336Sgblack@eecs.umich.edu#include <map>
536336Sgblack@eecs.umich.edu#include <string>
546313Sgblack@eecs.umich.edu#include <vector>
556313Sgblack@eecs.umich.edu
566313Sgblack@eecs.umich.edu#include "base/intmath.hh"
576313Sgblack@eecs.umich.edu#include "base/loader/object_file.hh"
586336Sgblack@eecs.umich.edu#include "base/loader/symtab.hh"
596336Sgblack@eecs.umich.edu#include "base/statistics.hh"
606336Sgblack@eecs.umich.edu#include "config/the_isa.hh"
616336Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
626336Sgblack@eecs.umich.edu#include "mem/page_table.hh"
636313Sgblack@eecs.umich.edu#include "mem/se_translating_port_proxy.hh"
646313Sgblack@eecs.umich.edu#include "params/LiveProcess.hh"
656313Sgblack@eecs.umich.edu#include "params/Process.hh"
666336Sgblack@eecs.umich.edu#include "sim/emul_driver.hh"
676336Sgblack@eecs.umich.edu#include "sim/syscall_desc.hh"
686313Sgblack@eecs.umich.edu#include "sim/system.hh"
696359Sgblack@eecs.umich.edu
706359Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA
716359Sgblack@eecs.umich.edu#include "arch/alpha/linux/process.hh"
726359Sgblack@eecs.umich.edu#elif THE_ISA == SPARC_ISA
736359Sgblack@eecs.umich.edu#include "arch/sparc/linux/process.hh"
746359Sgblack@eecs.umich.edu#include "arch/sparc/solaris/process.hh"
756359Sgblack@eecs.umich.edu#elif THE_ISA == MIPS_ISA
766359Sgblack@eecs.umich.edu#include "arch/mips/linux/process.hh"
776359Sgblack@eecs.umich.edu#elif THE_ISA == ARM_ISA
786359Sgblack@eecs.umich.edu#include "arch/arm/linux/process.hh"
796359Sgblack@eecs.umich.edu#include "arch/arm/freebsd/process.hh"
806359Sgblack@eecs.umich.edu#elif THE_ISA == X86_ISA
816359Sgblack@eecs.umich.edu#include "arch/x86/linux/process.hh"
826359Sgblack@eecs.umich.edu#elif THE_ISA == POWER_ISA
836359Sgblack@eecs.umich.edu#include "arch/power/linux/process.hh"
846313Sgblack@eecs.umich.edu#elif THE_ISA == RISCV_ISA
856313Sgblack@eecs.umich.edu#include "arch/riscv/linux/process.hh"
866313Sgblack@eecs.umich.edu#else
876313Sgblack@eecs.umich.edu#error "THE_ISA not set"
886313Sgblack@eecs.umich.edu#endif
896313Sgblack@eecs.umich.edu
906313Sgblack@eecs.umich.edu
916313Sgblack@eecs.umich.eduusing namespace std;
92using namespace TheISA;
93
94// current number of allocated processes
95int num_processes = 0;
96
97template<class IntType>
98
99AuxVector<IntType>::AuxVector(IntType type, IntType val)
100{
101    a_type = TheISA::htog(type);
102    a_val = TheISA::htog(val);
103}
104
105template struct AuxVector<uint32_t>;
106template struct AuxVector<uint64_t>;
107
108static int
109openFile(const string& filename, int flags, mode_t mode)
110{
111    int sim_fd = open(filename.c_str(), flags, mode);
112    if (sim_fd != -1)
113        return sim_fd;
114    fatal("Unable to open %s with mode %O", filename, mode);
115}
116
117static int
118openInputFile(const string &filename)
119{
120    return openFile(filename, O_RDONLY, 0);
121}
122
123static int
124openOutputFile(const string &filename)
125{
126    return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
127}
128
129Process::Process(ProcessParams * params)
130    : SimObject(params), system(params->system),
131      brk_point(0), stack_base(0), stack_size(0), stack_min(0),
132      max_stack_size(params->max_stack_size),
133      next_thread_stack_base(0),
134      useArchPT(params->useArchPT),
135      kvmInSE(params->kvmInSE),
136      pTable(useArchPT ?
137        static_cast<PageTableBase *>(new ArchPageTable(name(), params->pid,
138            system)) :
139        static_cast<PageTableBase *>(new FuncPageTable(name(), params->pid))),
140      initVirtMem(system->getSystemPort(), this,
141                  SETranslatingPortProxy::Always),
142      fd_array(make_shared<array<FDEntry, NUM_FDS>>()),
143      imap {{"",       -1},
144            {"cin",    STDIN_FILENO},
145            {"stdin",  STDIN_FILENO}},
146      oemap{{"",       -1},
147            {"cout",   STDOUT_FILENO},
148            {"stdout", STDOUT_FILENO},
149            {"cerr",   STDERR_FILENO},
150            {"stderr", STDERR_FILENO}},
151      _uid(params->uid), _euid(params->euid),
152      _gid(params->gid), _egid(params->egid),
153      _pid(params->pid), _ppid(params->ppid)
154{
155    int sim_fd;
156    std::map<string,int>::iterator it;
157
158    // Search through the input options and set fd if match is found;
159    // otherwise, open an input file and seek to location.
160    FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
161    if ((it = imap.find(params->input)) != imap.end())
162        sim_fd = it->second;
163    else
164        sim_fd = openInputFile(params->input);
165    fde_stdin->set(sim_fd, params->input, O_RDONLY, -1, false);
166
167    // Search through the output/error options and set fd if match is found;
168    // otherwise, open an output file and seek to location.
169    FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
170    if ((it = oemap.find(params->output)) != oemap.end())
171        sim_fd = it->second;
172    else
173        sim_fd = openOutputFile(params->output);
174    fde_stdout->set(sim_fd, params->output, O_WRONLY | O_CREAT | O_TRUNC,
175                    0664, false);
176
177    FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
178    if (params->output == params->errout)
179        // Reuse the same file descriptor if these match.
180        sim_fd = fde_stdout->fd;
181    else if ((it = oemap.find(params->errout)) != oemap.end())
182        sim_fd = it->second;
183    else
184        sim_fd = openOutputFile(params->errout);
185    fde_stderr->set(sim_fd, params->errout, O_WRONLY | O_CREAT | O_TRUNC,
186                    0664, false);
187
188    mmap_end = 0;
189    nxm_start = nxm_end = 0;
190    // other parameters will be initialized when the program is loaded
191}
192
193
194void
195Process::regStats()
196{
197    SimObject::regStats();
198
199    using namespace Stats;
200
201    num_syscalls
202        .name(name() + ".num_syscalls")
203        .desc("Number of system calls")
204        ;
205}
206
207void
208Process::inheritFDArray(Process *p)
209{
210    fd_array = p->fd_array;
211}
212
213ThreadContext *
214Process::findFreeContext()
215{
216    for (int id : contextIds) {
217        ThreadContext *tc = system->getThreadContext(id);
218        if (tc->status() == ThreadContext::Halted)
219            return tc;
220    }
221    return NULL;
222}
223
224void
225Process::initState()
226{
227    if (contextIds.empty())
228        fatal("Process %s is not associated with any HW contexts!\n", name());
229
230    // first thread context for this process... initialize & enable
231    ThreadContext *tc = system->getThreadContext(contextIds[0]);
232
233    // mark this context as active so it will start ticking.
234    tc->activate();
235
236    pTable->initState(tc);
237}
238
239DrainState
240Process::drain()
241{
242    findFileOffsets();
243    return DrainState::Drained;
244}
245
246int
247Process::allocFD(int sim_fd, const string& filename, int flags, int mode,
248                 bool pipe)
249{
250    for (int free_fd = 0; free_fd < fd_array->size(); free_fd++) {
251        FDEntry *fde = getFDEntry(free_fd);
252        if (fde->isFree()) {
253            fde->set(sim_fd, filename, flags, mode, pipe);
254            return free_fd;
255        }
256    }
257
258    fatal("Out of target file descriptors");
259}
260
261void
262Process::resetFDEntry(int tgt_fd)
263{
264    FDEntry *fde = getFDEntry(tgt_fd);
265    assert(fde->fd > -1);
266
267    fde->reset();
268}
269
270int
271Process::getSimFD(int tgt_fd)
272{
273    FDEntry *entry = getFDEntry(tgt_fd);
274    return entry ? entry->fd : -1;
275}
276
277FDEntry *
278Process::getFDEntry(int tgt_fd)
279{
280    assert(0 <= tgt_fd && tgt_fd < fd_array->size());
281    return &(*fd_array)[tgt_fd];
282}
283
284int
285Process::getTgtFD(int sim_fd)
286{
287    for (int index = 0; index < fd_array->size(); index++)
288        if ((*fd_array)[index].fd == sim_fd)
289            return index;
290    return -1;
291}
292
293void
294Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
295{
296    int npages = divCeil(size, (int64_t)PageBytes);
297    Addr paddr = system->allocPhysPages(npages);
298    pTable->map(vaddr, paddr, size,
299                clobber ? PageTableBase::Clobber : PageTableBase::Zero);
300}
301
302bool
303Process::fixupStackFault(Addr vaddr)
304{
305    // Check if this is already on the stack and there's just no page there
306    // yet.
307    if (vaddr >= stack_min && vaddr < stack_base) {
308        allocateMem(roundDown(vaddr, PageBytes), PageBytes);
309        return true;
310    }
311
312    // We've accessed the next page of the stack, so extend it to include
313    // this address.
314    if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
315        while (vaddr < stack_min) {
316            stack_min -= TheISA::PageBytes;
317            if (stack_base - stack_min > max_stack_size)
318                fatal("Maximum stack size exceeded\n");
319            allocateMem(stack_min, TheISA::PageBytes);
320            inform("Increasing stack size by one page.");
321        };
322        return true;
323    }
324    return false;
325}
326
327void
328Process::fixFileOffsets()
329{
330    auto seek = [] (FDEntry *fde)
331    {
332        if (lseek(fde->fd, fde->fileOffset, SEEK_SET) < 0)
333            fatal("Unable to see to location in %s", fde->filename);
334    };
335
336    std::map<string,int>::iterator it;
337
338    // Search through the input options and set fd if match is found;
339    // otherwise, open an input file and seek to location.
340    FDEntry *fde_stdin = getFDEntry(STDIN_FILENO);
341
342    // Check if user has specified a different input file, and if so, use it
343    // instead of the file specified in the checkpoint. This also resets the
344    // file offset from the checkpointed value
345    string new_in = ((ProcessParams*)params())->input;
346    if (new_in != fde_stdin->filename) {
347        warn("Using new input file (%s) rather than checkpointed (%s)\n",
348             new_in, fde_stdin->filename);
349        fde_stdin->filename = new_in;
350        fde_stdin->fileOffset = 0;
351    }
352
353    if ((it = imap.find(fde_stdin->filename)) != imap.end()) {
354        fde_stdin->fd = it->second;
355    } else {
356        fde_stdin->fd = openInputFile(fde_stdin->filename);
357        seek(fde_stdin);
358    }
359
360    // Search through the output/error options and set fd if match is found;
361    // otherwise, open an output file and seek to location.
362    FDEntry *fde_stdout = getFDEntry(STDOUT_FILENO);
363
364    // Check if user has specified a different output file, and if so, use it
365    // instead of the file specified in the checkpoint. This also resets the
366    // file offset from the checkpointed value
367    string new_out = ((ProcessParams*)params())->output;
368    if (new_out != fde_stdout->filename) {
369        warn("Using new output file (%s) rather than checkpointed (%s)\n",
370             new_out, fde_stdout->filename);
371        fde_stdout->filename = new_out;
372        fde_stdout->fileOffset = 0;
373    }
374
375    if ((it = oemap.find(fde_stdout->filename)) != oemap.end()) {
376        fde_stdout->fd = it->second;
377    } else {
378        fde_stdout->fd = openOutputFile(fde_stdout->filename);
379        seek(fde_stdout);
380    }
381
382    FDEntry *fde_stderr = getFDEntry(STDERR_FILENO);
383
384    // Check if user has specified a different error file, and if so, use it
385    // instead of the file specified in the checkpoint. This also resets the
386    // file offset from the checkpointed value
387    string new_err = ((ProcessParams*)params())->errout;
388    if (new_err != fde_stderr->filename) {
389        warn("Using new error file (%s) rather than checkpointed (%s)\n",
390             new_err, fde_stderr->filename);
391        fde_stderr->filename = new_err;
392        fde_stderr->fileOffset = 0;
393    }
394
395    if (fde_stdout->filename == fde_stderr->filename) {
396        // Reuse the same file descriptor if these match.
397        fde_stderr->fd = fde_stdout->fd;
398    } else if ((it = oemap.find(fde_stderr->filename)) != oemap.end()) {
399        fde_stderr->fd = it->second;
400    } else {
401        fde_stderr->fd = openOutputFile(fde_stderr->filename);
402        seek(fde_stderr);
403    }
404
405    for (int tgt_fd = 3; tgt_fd < fd_array->size(); tgt_fd++) {
406        FDEntry *fde = getFDEntry(tgt_fd);
407        if (fde->fd == -1)
408            continue;
409
410        if (fde->isPipe) {
411            if (fde->filename == "PIPE-WRITE")
412                continue;
413            assert(fde->filename == "PIPE-READ");
414
415            int fds[2];
416            if (pipe(fds) < 0)
417                fatal("Unable to create new pipe");
418
419            fde->fd = fds[0];
420
421            FDEntry *fde_write = getFDEntry(fde->readPipeSource);
422            assert(fde_write->filename == "PIPE-WRITE");
423            fde_write->fd = fds[1];
424        } else {
425            fde->fd = openFile(fde->filename.c_str(), fde->flags, fde->mode);
426            seek(fde);
427        }
428    }
429}
430
431void
432Process::findFileOffsets()
433{
434    for (auto& fde : *fd_array) {
435        if (fde.fd != -1)
436            fde.fileOffset = lseek(fde.fd, 0, SEEK_CUR);
437    }
438}
439
440void
441Process::setReadPipeSource(int read_pipe_fd, int source_fd)
442{
443    FDEntry *fde = getFDEntry(read_pipe_fd);
444    assert(source_fd >= -1);
445    fde->readPipeSource = source_fd;
446}
447
448void
449Process::serialize(CheckpointOut &cp) const
450{
451    SERIALIZE_SCALAR(brk_point);
452    SERIALIZE_SCALAR(stack_base);
453    SERIALIZE_SCALAR(stack_size);
454    SERIALIZE_SCALAR(stack_min);
455    SERIALIZE_SCALAR(next_thread_stack_base);
456    SERIALIZE_SCALAR(mmap_end);
457    SERIALIZE_SCALAR(nxm_start);
458    SERIALIZE_SCALAR(nxm_end);
459    pTable->serialize(cp);
460    for (int x = 0; x < fd_array->size(); x++) {
461        (*fd_array)[x].serializeSection(cp, csprintf("FDEntry%d", x));
462    }
463
464}
465
466void
467Process::unserialize(CheckpointIn &cp)
468{
469    UNSERIALIZE_SCALAR(brk_point);
470    UNSERIALIZE_SCALAR(stack_base);
471    UNSERIALIZE_SCALAR(stack_size);
472    UNSERIALIZE_SCALAR(stack_min);
473    UNSERIALIZE_SCALAR(next_thread_stack_base);
474    UNSERIALIZE_SCALAR(mmap_end);
475    UNSERIALIZE_SCALAR(nxm_start);
476    UNSERIALIZE_SCALAR(nxm_end);
477    pTable->unserialize(cp);
478    for (int x = 0; x < fd_array->size(); x++) {
479        FDEntry *fde = getFDEntry(x);
480        fde->unserializeSection(cp, csprintf("FDEntry%d", x));
481    }
482    fixFileOffsets();
483    // The above returns a bool so that you could do something if you don't
484    // find the param in the checkpoint if you wanted to, like set a default
485    // but in this case we'll just stick with the instantiated value if not
486    // found.
487}
488
489
490bool
491Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
492{
493    pTable->map(vaddr, paddr, size,
494                cacheable ? PageTableBase::Zero : PageTableBase::Uncacheable);
495    return true;
496}
497
498
499////////////////////////////////////////////////////////////////////////
500//
501// LiveProcess member definitions
502//
503////////////////////////////////////////////////////////////////////////
504
505
506LiveProcess::LiveProcess(LiveProcessParams *params, ObjectFile *_objFile)
507    : Process(params), objFile(_objFile),
508      argv(params->cmd), envp(params->env), cwd(params->cwd),
509      executable(params->executable),
510      drivers(params->drivers)
511{
512
513    // load up symbols, if any... these may be used for debugging or
514    // profiling.
515    if (!debugSymbolTable) {
516        debugSymbolTable = new SymbolTable();
517        if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
518            !objFile->loadLocalSymbols(debugSymbolTable) ||
519            !objFile->loadWeakSymbols(debugSymbolTable)) {
520            // didn't load any symbols
521            delete debugSymbolTable;
522            debugSymbolTable = NULL;
523        }
524    }
525}
526
527void
528LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
529{
530    num_syscalls++;
531
532    SyscallDesc *desc = getDesc(callnum);
533    if (desc == NULL)
534        fatal("Syscall %d out of range", callnum);
535
536    desc->doSyscall(callnum, this, tc);
537}
538
539IntReg
540LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
541{
542    return getSyscallArg(tc, i);
543}
544
545
546EmulatedDriver *
547LiveProcess::findDriver(std::string filename)
548{
549    for (EmulatedDriver *d : drivers) {
550        if (d->match(filename))
551            return d;
552    }
553
554    return NULL;
555}
556
557void
558LiveProcess::updateBias()
559{
560    ObjectFile *interp = objFile->getInterpreter();
561
562    if (!interp || !interp->relocatable())
563        return;
564
565    // Determine how large the interpreters footprint will be in the process
566    // address space.
567    Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
568
569    // We are allocating the memory area; set the bias to the lowest address
570    // in the allocated memory region.
571    Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
572
573    // Adjust the process mmap area to give the interpreter room; the real
574    // execve system call would just invoke the kernel's internal mmap
575    // functions to make these adjustments.
576    mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
577
578    interp->updateBias(ld_bias);
579}
580
581
582ObjectFile *
583LiveProcess::getInterpreter()
584{
585    return objFile->getInterpreter();
586}
587
588
589Addr
590LiveProcess::getBias()
591{
592    ObjectFile *interp = getInterpreter();
593
594    return interp ? interp->bias() : objFile->bias();
595}
596
597
598Addr
599LiveProcess::getStartPC()
600{
601    ObjectFile *interp = getInterpreter();
602
603    return interp ? interp->entryPoint() : objFile->entryPoint();
604}
605
606
607LiveProcess *
608LiveProcess::create(LiveProcessParams * params)
609{
610    LiveProcess *process = NULL;
611
612    // If not specified, set the executable parameter equal to the
613    // simulated system's zeroth command line parameter
614    if (params->executable == "") {
615        params->executable = params->cmd[0];
616    }
617
618    ObjectFile *objFile = createObjectFile(params->executable);
619    if (objFile == NULL) {
620        fatal("Can't load object file %s", params->executable);
621    }
622
623#if THE_ISA == ALPHA_ISA
624    if (objFile->getArch() != ObjectFile::Alpha)
625        fatal("Object file architecture does not match compiled ISA (Alpha).");
626
627    switch (objFile->getOpSys()) {
628      case ObjectFile::UnknownOpSys:
629        warn("Unknown operating system; assuming Linux.");
630        // fall through
631      case ObjectFile::Linux:
632        process = new AlphaLinuxProcess(params, objFile);
633        break;
634
635      default:
636        fatal("Unknown/unsupported operating system.");
637    }
638#elif THE_ISA == SPARC_ISA
639    if (objFile->getArch() != ObjectFile::SPARC64 &&
640        objFile->getArch() != ObjectFile::SPARC32)
641        fatal("Object file architecture does not match compiled ISA (SPARC).");
642    switch (objFile->getOpSys()) {
643      case ObjectFile::UnknownOpSys:
644        warn("Unknown operating system; assuming Linux.");
645        // fall through
646      case ObjectFile::Linux:
647        if (objFile->getArch() == ObjectFile::SPARC64) {
648            process = new Sparc64LinuxProcess(params, objFile);
649        } else {
650            process = new Sparc32LinuxProcess(params, objFile);
651        }
652        break;
653
654
655      case ObjectFile::Solaris:
656        process = new SparcSolarisProcess(params, objFile);
657        break;
658
659      default:
660        fatal("Unknown/unsupported operating system.");
661    }
662#elif THE_ISA == X86_ISA
663    if (objFile->getArch() != ObjectFile::X86_64 &&
664        objFile->getArch() != ObjectFile::I386)
665        fatal("Object file architecture does not match compiled ISA (x86).");
666    switch (objFile->getOpSys()) {
667      case ObjectFile::UnknownOpSys:
668        warn("Unknown operating system; assuming Linux.");
669        // fall through
670      case ObjectFile::Linux:
671        if (objFile->getArch() == ObjectFile::X86_64) {
672            process = new X86_64LinuxProcess(params, objFile);
673        } else {
674            process = new I386LinuxProcess(params, objFile);
675        }
676        break;
677
678      default:
679        fatal("Unknown/unsupported operating system.");
680    }
681#elif THE_ISA == MIPS_ISA
682    if (objFile->getArch() != ObjectFile::Mips)
683        fatal("Object file architecture does not match compiled ISA (MIPS).");
684    switch (objFile->getOpSys()) {
685      case ObjectFile::UnknownOpSys:
686        warn("Unknown operating system; assuming Linux.");
687        // fall through
688      case ObjectFile::Linux:
689        process = new MipsLinuxProcess(params, objFile);
690        break;
691
692      default:
693        fatal("Unknown/unsupported operating system.");
694    }
695#elif THE_ISA == ARM_ISA
696    ObjectFile::Arch arch = objFile->getArch();
697    if (arch != ObjectFile::Arm && arch != ObjectFile::Thumb &&
698        arch != ObjectFile::Arm64)
699        fatal("Object file architecture does not match compiled ISA (ARM).");
700    switch (objFile->getOpSys()) {
701      case ObjectFile::UnknownOpSys:
702        warn("Unknown operating system; assuming Linux.");
703        // fall through
704      case ObjectFile::Linux:
705        if (arch == ObjectFile::Arm64) {
706            process = new ArmLinuxProcess64(params, objFile,
707                                            objFile->getArch());
708        } else {
709            process = new ArmLinuxProcess32(params, objFile,
710                                            objFile->getArch());
711        }
712        break;
713      case ObjectFile::FreeBSD:
714        if (arch == ObjectFile::Arm64) {
715            process = new ArmFreebsdProcess64(params, objFile,
716                                              objFile->getArch());
717        } else {
718            process = new ArmFreebsdProcess32(params, objFile,
719                                              objFile->getArch());
720        }
721        break;
722      case ObjectFile::LinuxArmOABI:
723        fatal("M5 does not support ARM OABI binaries. Please recompile with an"
724              " EABI compiler.");
725      default:
726        fatal("Unknown/unsupported operating system.");
727    }
728#elif THE_ISA == POWER_ISA
729    if (objFile->getArch() != ObjectFile::Power)
730        fatal("Object file architecture does not match compiled ISA (Power).");
731    switch (objFile->getOpSys()) {
732      case ObjectFile::UnknownOpSys:
733        warn("Unknown operating system; assuming Linux.");
734        // fall through
735      case ObjectFile::Linux:
736        process = new PowerLinuxProcess(params, objFile);
737        break;
738
739      default:
740        fatal("Unknown/unsupported operating system.");
741    }
742#elif THE_ISA == RISCV_ISA
743    if (objFile->getArch() != ObjectFile::Riscv)
744        fatal("Object file architecture does not match compiled ISA (RISCV).");
745    switch (objFile->getOpSys()) {
746      case ObjectFile::UnknownOpSys:
747        warn("Unknown operating system; assuming Linux.");
748        // fall through
749      case ObjectFile::Linux:
750        process = new RiscvLinuxProcess(params, objFile);
751        break;
752      default:
753        fatal("Unknown/unsupported operating system.");
754    }
755#else
756#error "THE_ISA not set"
757#endif
758
759    if (process == NULL)
760        fatal("Unknown error creating process object.");
761    return process;
762}
763
764LiveProcess *
765LiveProcessParams::create()
766{
767    return LiveProcess::create(this);
768}
769