X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsim%2Fprocess.cc;h=d4b1fba900df0d20e6ae6e94701ad4ecc8a7caaf;hb=df9f99567d43c9dfcecc625dce748c561699b307;hp=16037b2f42ac85eef54647358bfef0a63defd2da;hpb=71835d42df8fb488380be8cc89be4298b268902a;p=gem5.git diff --git a/src/sim/process.cc b/src/sim/process.cc index 16037b2f4..d4b1fba90 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -32,27 +32,29 @@ #include #include + +#include #include -#include "arch/remote_gdb.hh" #include "base/intmath.hh" #include "base/loader/object_file.hh" #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 "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" @@ -65,6 +67,8 @@ #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 @@ -85,12 +89,23 @@ using namespace TheISA; // current number of allocated processes int num_processes = 0; +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), checkpointRestored(false), - max_stack_size(params->max_stack_size) + : 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; @@ -111,7 +126,16 @@ Process::Process(ProcessParams * params) else stdout_fd = Process::openOutputFile(out); - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + 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) @@ -131,7 +155,7 @@ Process::Process(ProcessParams * params) fdo = &fd_map[STDERR_FILENO]; fdo->fd = stderr_fd; - fdo->filename = "STDERR"; + fdo->filename = err; fdo->flags = O_WRONLY; fdo->mode = -1; fdo->fileOffset = 0; @@ -182,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); @@ -193,33 +217,29 @@ 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); - - RemoteGDB *rgdb = new RemoteGDB(system, tc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex); - gdbl->listen(); - //gdbl->accept(); - - remoteGDB.push_back(rgdb); - - // 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); @@ -232,17 +252,6 @@ Process::startup() 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) @@ -318,6 +327,7 @@ Process::sim_fd_obj(int tgt_fd) return &fd_map[tgt_fd]; } + bool Process::checkAndAllocNextPage(Addr vaddr) { @@ -337,21 +347,23 @@ Process::checkAndAllocNextPage(Addr vaddr) if(stack_base - stack_min > 8*1024*1024) fatal("Over max stack size for one thread\n"); pTable->allocate(stack_min, TheISA::PageBytes); - warn("Increasing stack size by one page."); + inform("Increasing stack size by one page."); }; return true; } return false; } - // find all offsets for currently open files and save them +// find all offsets for currently open files and save them void -Process::fix_file_offsets() { +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; @@ -360,8 +372,8 @@ Process::fix_file_offsets() { stdin_fd = STDIN_FILENO; else if (in == "None") stdin_fd = -1; - else{ - //OPEN standard in and seek to the right location + 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); @@ -373,13 +385,25 @@ Process::fix_file_offsets() { stdout_fd = STDERR_FILENO; else if (out == "None") stdout_fd = -1; - else{ + else { stdout_fd = Process::openOutputFile(out); - if (lseek(stdin_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) - panic("Unable to seek to correct in file: %s", out); + if (lseek(stdout_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", out); } - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + 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; @@ -419,18 +443,21 @@ Process::fix_file_offsets() { //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); + panic("Unable to seek to correct location in file: %s", + fdo->filename); } } } } + void -Process::find_file_offsets(){ +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 { + } else { fdo->filename = "NULL"; fdo->fileOffset = 0; } @@ -438,7 +465,8 @@ Process::find_file_offsets(){ } void -Process::setReadPipeSource(int read_pipe_fd, int source_fd){ +Process::setReadPipeSource(int read_pipe_fd, int source_fd) +{ Process::FdMap *fdo = &fd_map[read_pipe_fd]; fdo->readPipeSource = source_fd; } @@ -468,7 +496,6 @@ Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion) void Process::serialize(std::ostream &os) { - SERIALIZE_SCALAR(initialContextLoaded); SERIALIZE_SCALAR(brk_point); SERIALIZE_SCALAR(stack_base); SERIALIZE_SCALAR(stack_size); @@ -484,13 +511,13 @@ Process::serialize(std::ostream &os) 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); @@ -503,11 +530,13 @@ Process::unserialize(Checkpoint *cp, const std::string §ion) 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(); - - checkpointRestored = true; - + 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. } @@ -544,75 +573,6 @@ LiveProcess::LiveProcess(LiveProcessParams * params, 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); - - assert(NumArgumentRegs >= 2); - threadContexts[0]->setIntReg(ArgumentReg[0], argc); - threadContexts[0]->setIntReg(ArgumentReg[1], 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) { @@ -625,6 +585,12 @@ 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(LiveProcessParams * params) { @@ -643,18 +609,17 @@ LiveProcess::create(LiveProcessParams * params) "executable as a static binary and try again.\n"); #if THE_ISA == ALPHA_ISA - if (objFile->hasTLS()) - fatal("Object file has a TLS section and single threaded TLS is not\n" - " currently supported for Alpha! Please recompile your " - "executable with \n a non-TLS toolchain.\n"); - if (objFile->getArch() != ObjectFile::Alpha) fatal("Object file architecture does not match compiled ISA (Alpha)."); + switch (objFile->getOpSys()) { case ObjectFile::Tru64: process = new AlphaTru64Process(params, objFile); break; + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: process = new AlphaLinuxProcess(params, objFile); break; @@ -663,9 +628,13 @@ LiveProcess::create(LiveProcessParams * params) fatal("Unknown/unsupported operating system."); } #elif THE_ISA == SPARC_ISA - if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32) + 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: if (objFile->getArch() == ObjectFile::SPARC64) { process = new Sparc64LinuxProcess(params, objFile); @@ -678,16 +647,26 @@ LiveProcess::create(LiveProcessParams * params) case ObjectFile::Solaris: process = new SparcSolarisProcess(params, objFile); break; + default: fatal("Unknown/unsupported operating system."); } #elif THE_ISA == X86_ISA - if (objFile->getArch() != ObjectFile::X86) + 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: - process = new X86LinuxProcess(params, objFile); + 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."); } @@ -695,6 +674,9 @@ LiveProcess::create(LiveProcessParams * params) 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; @@ -703,11 +685,31 @@ LiveProcess::create(LiveProcessParams * params) fatal("Unknown/unsupported operating system."); } #elif THE_ISA == ARM_ISA - if (objFile->getArch() != ObjectFile::Arm) + 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 ArmLinuxProcess(params, objFile); + process = new PowerLinuxProcess(params, objFile); break; default: