X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsim%2Fprocess.cc;h=d4b1fba900df0d20e6ae6e94701ad4ecc8a7caaf;hb=df9f99567d43c9dfcecc625dce748c561699b307;hp=63ff33969e28b65bcd102ef155abd951f088e949;hpb=fd8a4ff5a8a9ea65e227f0b4000dfcda06d4764f;p=gem5.git diff --git a/src/sim/process.cc b/src/sim/process.cc index 63ff33969..d4b1fba90 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include "base/intmath.hh" @@ -40,17 +41,20 @@ #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/physical.hh" #include "mem/translating_port.hh" -#include "sim/builder.hh" +#include "params/Process.hh" +#include "params/LiveProcess.hh" +#include "sim/debug.hh" #include "sim/process.hh" +#include "sim/process_impl.hh" #include "sim/stats.hh" #include "sim/syscall_emul.hh" #include "sim/system.hh" -#include "arch/isa_specific.hh" #if THE_ISA == ALPHA_ISA #include "arch/alpha/linux/process.hh" #include "arch/alpha/tru64/process.hh" @@ -59,6 +63,12 @@ #include "arch/sparc/solaris/process.hh" #elif THE_ISA == MIPS_ISA #include "arch/mips/linux/process.hh" +#elif THE_ISA == ARM_ISA +#include "arch/arm/linux/process.hh" +#elif THE_ISA == X86_ISA +#include "arch/x86/linux/process.hh" +#elif THE_ISA == POWER_ISA +#include "arch/power/linux/process.hh" #else #error "THE_ISA not set" #endif @@ -79,26 +89,87 @@ using namespace TheISA; // current number of allocated processes int num_processes = 0; -Process::Process(const string &nm, - System *_system, - int stdin_fd, // initial I/O descriptors - int stdout_fd, - int stderr_fd) - : SimObject(nm), system(_system) +template +AuxVector::AuxVector(IntType type, IntType val) { + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} + +template class AuxVector; +template class AuxVector; + +Process::Process(ProcessParams * params) + : SimObject(params), system(params->system), + max_stack_size(params->max_stack_size) +{ + string in = params->input; + string out = params->output; + string err = params->errout; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else if (in == "None") + stdin_fd = -1; + else + stdin_fd = Process::openInputFile(in); + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else if (out == "None") + stdout_fd = -1; + else + stdout_fd = Process::openOutputFile(out); + + if (err == "stdout" || err == "cout") + stderr_fd = STDOUT_FILENO; + else if (err == "stderr" || err == "cerr") + stderr_fd = STDERR_FILENO; + else if (err == "None") + stderr_fd = -1; + else if (err == out) + stderr_fd = stdout_fd; + else + stderr_fd = Process::openOutputFile(err); + + M5_pid = system->allocatePID(); // initialize first 3 fds (stdin, stdout, stderr) - fd_map[STDIN_FILENO] = stdin_fd; - fd_map[STDOUT_FILENO] = stdout_fd; - fd_map[STDERR_FILENO] = stderr_fd; + Process::FdMap *fdo = &fd_map[STDIN_FILENO]; + fdo->fd = stdin_fd; + fdo->filename = in; + fdo->flags = O_RDONLY; + fdo->mode = -1; + fdo->fileOffset = 0; + + fdo = &fd_map[STDOUT_FILENO]; + fdo->fd = stdout_fd; + fdo->filename = out; + fdo->flags = O_WRONLY | O_CREAT | O_TRUNC; + fdo->mode = 0774; + fdo->fileOffset = 0; + + fdo = &fd_map[STDERR_FILENO]; + fdo->fd = stderr_fd; + fdo->filename = err; + fdo->flags = O_WRONLY; + fdo->mode = -1; + fdo->fileOffset = 0; + // mark remaining fds as free for (int i = 3; i <= MAX_FD; ++i) { - fd_map[i] = -1; + Process::FdMap *fdo = &fd_map[i]; + fdo->fd = -1; } mmap_start = mmap_end = 0; nxm_start = nxm_end = 0; - pTable = new PageTable(system); + pTable = new PageTable(this); // other parameters will be initialized when the program is loaded } @@ -135,7 +206,7 @@ Process::openInputFile(const string &filename) int Process::openOutputFile(const string &filename) { - int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774); + int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd == -1) { perror(NULL); @@ -146,48 +217,41 @@ Process::openOutputFile(const string &filename) return fd; } - -int -Process::registerThreadContext(ThreadContext *tc) +ThreadContext * +Process::findFreeContext() { - // add to list - int myIndex = threadContexts.size(); - threadContexts.push_back(tc); - - // return CPU number to caller - return myIndex; + int size = contextIds.size(); + ThreadContext *tc; + for (int i = 0; i < size; ++i) { + tc = system->getThreadContext(contextIds[i]); + if (tc->status() == ThreadContext::Halted) { + // inactive context, free to use + return tc; + } + } + return NULL; } void -Process::startup() +Process::initState() { - if (threadContexts.empty()) - fatal("Process %s is not associated with any CPUs!\n", name()); + if (contextIds.empty()) + fatal("Process %s is not associated with any HW contexts!\n", name()); // first thread context for this process... initialize & enable - ThreadContext *tc = threadContexts[0]; + ThreadContext *tc = system->getThreadContext(contextIds[0]); // mark this context as active so it will start ticking. tc->activate(0); Port *mem_port; mem_port = system->physmem->getPort("functional"); - initVirtMem = new TranslatingPort("process init port", pTable, true); + initVirtMem = new TranslatingPort("process init port", this, + TranslatingPort::Always); mem_port->setPeer(initVirtMem); initVirtMem->setPeer(mem_port); } -void -Process::replaceThreadContext(ThreadContext *tc, int tcIndex) -{ - if (tcIndex >= threadContexts.size()) { - panic("replaceThreadContext: bad tcIndex, %d >= %d\n", - tcIndex, threadContexts.size()); - } - - threadContexts[tcIndex] = tc; -} - // map simulator fd sim_fd to target fd tgt_fd void Process::dup_fd(int sim_fd, int tgt_fd) @@ -195,22 +259,30 @@ Process::dup_fd(int sim_fd, int tgt_fd) if (tgt_fd < 0 || tgt_fd > MAX_FD) panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd); - fd_map[tgt_fd] = sim_fd; + Process::FdMap *fdo = &fd_map[tgt_fd]; + fdo->fd = sim_fd; } // generate new target fd for sim_fd int -Process::alloc_fd(int sim_fd) +Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe) { // in case open() returns an error, don't allocate a new fd if (sim_fd == -1) return -1; // find first free target fd - for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) { - if (fd_map[free_fd] == -1) { - fd_map[free_fd] = sim_fd; + for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) { + Process::FdMap *fdo = &fd_map[free_fd]; + if (fdo->fd == -1) { + fdo->fd = sim_fd; + fdo->filename = filename; + fdo->mode = mode; + fdo->fileOffset = 0; + fdo->flags = flags; + fdo->isPipe = pipe; + fdo->readPipeSource = 0; return free_fd; } } @@ -223,10 +295,17 @@ Process::alloc_fd(int sim_fd) void Process::free_fd(int tgt_fd) { - if (fd_map[tgt_fd] == -1) + Process::FdMap *fdo = &fd_map[tgt_fd]; + if (fdo->fd == -1) warn("Process::free_fd: request to free unused fd %d", tgt_fd); - fd_map[tgt_fd] = -1; + fdo->fd = -1; + fdo->filename = "NULL"; + fdo->mode = 0; + fdo->fileOffset = 0; + fdo->flags = 0; + fdo->isPipe = false; + fdo->readPipeSource = 0; } @@ -237,13 +316,186 @@ Process::sim_fd(int tgt_fd) if (tgt_fd > MAX_FD) return -1; - return fd_map[tgt_fd]; + return fd_map[tgt_fd].fd; +} + +Process::FdMap * +Process::sim_fd_obj(int tgt_fd) +{ + if (tgt_fd > MAX_FD) + panic("sim_fd_obj called in fd out of range."); + + return &fd_map[tgt_fd]; +} + +bool +Process::checkAndAllocNextPage(Addr vaddr) +{ + // if this is an initial write we might not have + if (vaddr >= stack_min && vaddr < stack_base) { + pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize); + return true; + } + + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) { + while (vaddr < stack_min) { + stack_min -= TheISA::PageBytes; + if(stack_base - stack_min > max_stack_size) + fatal("Maximum stack size exceeded\n"); + if(stack_base - stack_min > 8*1024*1024) + fatal("Over max stack size for one thread\n"); + pTable->allocate(stack_min, TheISA::PageBytes); + inform("Increasing stack size by one page."); + }; + return true; + } + return false; +} + +// find all offsets for currently open files and save them +void +Process::fix_file_offsets() +{ + Process::FdMap *fdo_stdin = &fd_map[STDIN_FILENO]; + Process::FdMap *fdo_stdout = &fd_map[STDOUT_FILENO]; + Process::FdMap *fdo_stderr = &fd_map[STDERR_FILENO]; + string in = fdo_stdin->filename; + string out = fdo_stdout->filename; + string err = fdo_stderr->filename; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else if (in == "None") + stdin_fd = -1; + else { + // open standard in and seek to the right location + stdin_fd = Process::openInputFile(in); + if (lseek(stdin_fd, fdo_stdin->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", in); + } + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else if (out == "None") + stdout_fd = -1; + else { + stdout_fd = Process::openOutputFile(out); + if (lseek(stdout_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", out); + } + + if (err == "stdout" || err == "cout") + stderr_fd = STDOUT_FILENO; + else if (err == "stderr" || err == "cerr") + stderr_fd = STDERR_FILENO; + else if (err == "None") + stderr_fd = -1; + else if (err == out) + stderr_fd = stdout_fd; + else { + stderr_fd = Process::openOutputFile(err); + if (lseek(stderr_fd, fdo_stderr->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", err); + } + + fdo_stdin->fd = stdin_fd; + fdo_stdout->fd = stdout_fd; + fdo_stderr->fd = stderr_fd; + + + for (int free_fd = 3; free_fd <= MAX_FD; ++free_fd) { + Process::FdMap *fdo = &fd_map[free_fd]; + if (fdo->fd != -1) { + if (fdo->isPipe){ + if (fdo->filename == "PIPE-WRITE") + continue; + else { + assert (fdo->filename == "PIPE-READ"); + //create a new pipe + int fds[2]; + int pipe_retval = pipe(fds); + + if (pipe_retval < 0) { + // error + panic("Unable to create new pipe."); + } + fdo->fd = fds[0]; //set read pipe + Process::FdMap *fdo_write = &fd_map[fdo->readPipeSource]; + if (fdo_write->filename != "PIPE-WRITE") + panic ("Couldn't find write end of the pipe"); + + fdo_write->fd = fds[1];//set write pipe + } + } else { + //Open file + int fd = open(fdo->filename.c_str(), fdo->flags, fdo->mode); + + if (fd == -1) + panic("Unable to open file: %s", fdo->filename); + fdo->fd = fd; + + //Seek to correct location before checkpoint + if (lseek(fd,fdo->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", + fdo->filename); + } + } + } +} + +void +Process::find_file_offsets() +{ + for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) { + Process::FdMap *fdo = &fd_map[free_fd]; + if (fdo->fd != -1) { + fdo->fileOffset = lseek(fdo->fd, 0, SEEK_CUR); + } else { + fdo->filename = "NULL"; + fdo->fileOffset = 0; + } + } +} + +void +Process::setReadPipeSource(int read_pipe_fd, int source_fd) +{ + Process::FdMap *fdo = &fd_map[read_pipe_fd]; + fdo->readPipeSource = source_fd; +} + +void +Process::FdMap::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(fd); + SERIALIZE_SCALAR(isPipe); + SERIALIZE_SCALAR(filename); + SERIALIZE_SCALAR(flags); + SERIALIZE_SCALAR(readPipeSource); + SERIALIZE_SCALAR(fileOffset); +} + +void +Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(fd); + UNSERIALIZE_SCALAR(isPipe); + UNSERIALIZE_SCALAR(filename); + UNSERIALIZE_SCALAR(flags); + UNSERIALIZE_SCALAR(readPipeSource); + UNSERIALIZE_SCALAR(fileOffset); } void Process::serialize(std::ostream &os) { - SERIALIZE_SCALAR(initialContextLoaded); SERIALIZE_SCALAR(brk_point); SERIALIZE_SCALAR(stack_base); SERIALIZE_SCALAR(stack_size); @@ -253,15 +505,19 @@ Process::serialize(std::ostream &os) SERIALIZE_SCALAR(mmap_end); SERIALIZE_SCALAR(nxm_start); SERIALIZE_SCALAR(nxm_end); - SERIALIZE_ARRAY(fd_map, MAX_FD); - + find_file_offsets(); pTable->serialize(os); + for (int x = 0; x <= MAX_FD; x++) { + nameOut(os, csprintf("%s.FdMap%d", name(), x)); + fd_map[x].serialize(os); + } + SERIALIZE_SCALAR(M5_pid); + } void Process::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_SCALAR(initialContextLoaded); UNSERIALIZE_SCALAR(brk_point); UNSERIALIZE_SCALAR(stack_base); UNSERIALIZE_SCALAR(stack_size); @@ -271,20 +527,19 @@ Process::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(mmap_end); UNSERIALIZE_SCALAR(nxm_start); UNSERIALIZE_SCALAR(nxm_end); - UNSERIALIZE_ARRAY(fd_map, MAX_FD); - pTable->unserialize(cp, section); + for (int x = 0; x <= MAX_FD; x++) { + fd_map[x].unserialize(cp, csprintf("%s.FdMap%d", section, x)); + } + fix_file_offsets(); + UNSERIALIZE_OPT_SCALAR(M5_pid); + // The above returns a bool so that you could do something if you don't + // find the param in the checkpoint if you wanted to, like set a default + // but in this case we'll just stick with the instantianted value if not + // found. } -// -// need to declare these here since there is no concrete Process type -// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call, -// which is where these get declared for concrete types). -// -DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) - - //////////////////////////////////////////////////////////////////////// // // LiveProcess member definitions @@ -292,43 +547,18 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) //////////////////////////////////////////////////////////////////////// -void -copyStringArray(vector &strings, Addr array_ptr, Addr data_ptr, - TranslatingPort* memPort) -{ - Addr data_ptr_swap; - for (int i = 0; i < strings.size(); ++i) { - data_ptr_swap = htog(data_ptr); - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); - memPort->writeString(data_ptr, strings[i].c_str()); - array_ptr += sizeof(Addr); - data_ptr += strings[i].size() + 1; - } - // add NULL terminator - data_ptr = 0; - - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); -} - -LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, - System *_system, - int stdin_fd, int stdout_fd, int stderr_fd, - vector &_argv, vector &_envp, - const string &_cwd, - uint64_t _uid, uint64_t _euid, - uint64_t _gid, uint64_t _egid, - uint64_t _pid, uint64_t _ppid) - : Process(nm, _system, stdin_fd, stdout_fd, stderr_fd), - objFile(_objFile), argv(_argv), envp(_envp), cwd(_cwd) +LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile) + : Process(params), objFile(_objFile), + argv(params->cmd), envp(params->env), cwd(params->cwd) { - __uid = _uid; - __euid = _euid; - __gid = _gid; - __egid = _egid; - __pid = _pid; - __ppid = _ppid; + __uid = params->uid; + __euid = params->euid; + __gid = params->gid; + __egid = params->egid; + __pid = params->pid; + __ppid = params->ppid; - prog_fname = argv[0]; + prog_fname = params->cmd[0]; // load up symbols, if any... these may be used for debugging or // profiling. @@ -343,74 +573,6 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, } } -void -LiveProcess::argsInit(int intSize, int pageSize) -{ - Process::startup(); - - // load object file into target memory - objFile->loadSections(initVirtMem); - - // Calculate how much space we need for arg & env arrays. - int argv_array_size = intSize * (argv.size() + 1); - int envp_array_size = intSize * (envp.size() + 1); - int arg_data_size = 0; - for (int i = 0; i < argv.size(); ++i) { - arg_data_size += argv[i].size() + 1; - } - int env_data_size = 0; - for (int i = 0; i < envp.size(); ++i) { - env_data_size += envp[i].size() + 1; - } - - int space_needed = - argv_array_size + envp_array_size + arg_data_size + env_data_size; - if (space_needed < 32*1024) - space_needed = 32*1024; - - // set bottom of stack - stack_min = stack_base - space_needed; - // align it - stack_min = roundDown(stack_min, pageSize); - stack_size = stack_base - stack_min; - // map memory - pTable->allocate(stack_min, roundUp(stack_size, pageSize)); - - // map out initial stack contents - Addr argv_array_base = stack_min + intSize; // room for argc - Addr envp_array_base = argv_array_base + argv_array_size; - Addr arg_data_base = envp_array_base + envp_array_size; - Addr env_data_base = arg_data_base + arg_data_size; - - // write contents to stack - uint64_t argc = argv.size(); - if (intSize == 8) - argc = htog((uint64_t)argc); - else if (intSize == 4) - argc = htog((uint32_t)argc); - else - panic("Unknown int size"); - - initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); - - copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); - copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); - - threadContexts[0]->setIntReg(ArgumentReg0, argc); - threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); - threadContexts[0]->setIntReg(StackPointerReg, stack_min); - - Addr prog_entry = objFile->entryPoint(); - threadContexts[0]->setPC(prog_entry); - threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); - -#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc - threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); -#endif - - num_processes++; -} - void LiveProcess::syscall(int64_t callnum, ThreadContext *tc) { @@ -423,18 +585,19 @@ LiveProcess::syscall(int64_t callnum, ThreadContext *tc) desc->doSyscall(callnum, this, tc); } +IntReg +LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) +{ + return getSyscallArg(tc, i); +} + LiveProcess * -LiveProcess::create(const std::string &nm, System *system, int stdin_fd, - int stdout_fd, int stderr_fd, std::string executable, - std::vector &argv, - std::vector &envp, - const std::string &cwd, - uint64_t _uid, uint64_t _euid, - uint64_t _gid, uint64_t _egid, - uint64_t _pid, uint64_t _ppid) +LiveProcess::create(LiveProcessParams * params) { LiveProcess *process = NULL; + string executable = + params->executable == "" ? params->cmd[0] : params->executable; ObjectFile *objFile = createObjectFile(executable); if (objFile == NULL) { fatal("Can't load object file %s", executable); @@ -442,48 +605,68 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, if (objFile->isDynamic()) fatal("Object file is a dynamic executable however only static " - "executables are supported!\n Please recompile your " + "executables are supported!\n Please recompile your " "executable as a static binary and try again.\n"); #if THE_ISA == ALPHA_ISA if (objFile->getArch() != ObjectFile::Alpha) fatal("Object file architecture does not match compiled ISA (Alpha)."); + switch (objFile->getOpSys()) { case ObjectFile::Tru64: - process = new AlphaTru64Process(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + process = new AlphaTru64Process(params, objFile); break; + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: - process = new AlphaLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + process = new AlphaLinuxProcess(params, objFile); break; default: fatal("Unknown/unsupported operating system."); } #elif THE_ISA == SPARC_ISA - if (objFile->getArch() != ObjectFile::SPARC) + if (objFile->getArch() != ObjectFile::SPARC64 && + objFile->getArch() != ObjectFile::SPARC32) fatal("Object file architecture does not match compiled ISA (SPARC)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: - process = new SparcLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + if (objFile->getArch() == ObjectFile::SPARC64) { + process = new Sparc64LinuxProcess(params, objFile); + } else { + process = new Sparc32LinuxProcess(params, objFile); + } break; case ObjectFile::Solaris: - process = new SparcSolarisProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + process = new SparcSolarisProcess(params, objFile); + break; + + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == X86_ISA + if (objFile->getArch() != ObjectFile::X86_64 && + objFile->getArch() != ObjectFile::I386) + fatal("Object file architecture does not match compiled ISA (x86)."); + switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through + case ObjectFile::Linux: + if (objFile->getArch() == ObjectFile::X86_64) { + process = new X86_64LinuxProcess(params, objFile); + } else { + process = new I386LinuxProcess(params, objFile); + } break; + default: fatal("Unknown/unsupported operating system."); } @@ -491,11 +674,42 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, if (objFile->getArch() != ObjectFile::Mips) fatal("Object file architecture does not match compiled ISA (MIPS)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through + case ObjectFile::Linux: + process = new MipsLinuxProcess(params, objFile); + break; + + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == ARM_ISA + if (objFile->getArch() != ObjectFile::Arm && + objFile->getArch() != ObjectFile::Thumb) + fatal("Object file architecture does not match compiled ISA (ARM)."); + switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through + case ObjectFile::Linux: + process = new ArmLinuxProcess(params, objFile, objFile->getArch()); + break; + case ObjectFile::LinuxArmOABI: + fatal("M5 does not support ARM OABI binaries. Please recompile with an" + " EABI compiler."); + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == POWER_ISA + if (objFile->getArch() != ObjectFile::Power) + fatal("Object file architecture does not match compiled ISA (Power)."); + switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: - process = new MipsLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + process = new PowerLinuxProcess(params, objFile); break; default: @@ -511,73 +725,8 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, return process; } - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) - - VectorParam cmd; - Param executable; - Param input; - Param output; - VectorParam env; - Param cwd; - SimObjectParam system; - Param uid; - Param euid; - Param gid; - Param egid; - Param pid; - Param ppid; - -END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess) - - INIT_PARAM(cmd, "command line (executable plus arguments)"), - INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), - INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), - INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), - INIT_PARAM(env, "environment settings"), - INIT_PARAM(cwd, "current working directory"), - INIT_PARAM(system, "system"), - INIT_PARAM(uid, "user id"), - INIT_PARAM(euid, "effective user id"), - INIT_PARAM(gid, "group id"), - INIT_PARAM(egid, "effective group id"), - INIT_PARAM(pid, "process id"), - INIT_PARAM(ppid, "parent process id") - -END_INIT_SIM_OBJECT_PARAMS(LiveProcess) - - -CREATE_SIM_OBJECT(LiveProcess) +LiveProcess * +LiveProcessParams::create() { - string in = input; - string out = output; - - // initialize file descriptors to default: same as simulator - int stdin_fd, stdout_fd, stderr_fd; - - if (in == "stdin" || in == "cin") - stdin_fd = STDIN_FILENO; - else - stdin_fd = Process::openInputFile(input); - - if (out == "stdout" || out == "cout") - stdout_fd = STDOUT_FILENO; - else if (out == "stderr" || out == "cerr") - stdout_fd = STDERR_FILENO; - else - stdout_fd = Process::openOutputFile(out); - - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; - - return LiveProcess::create(getInstanceName(), system, - stdin_fd, stdout_fd, stderr_fd, - (string)executable == "" ? cmd[0] : executable, - cmd, env, cwd, - uid, euid, gid, egid, pid, ppid); + return LiveProcess::create(this); } - - -REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)