Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[gem5.git] / sim / process.cc
index 65cb8409f77f5cc2463491644561eb33c9599c9e..0a7e4608209cc0e3bcde0e554253929471cc196b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #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 "cpu/exec_context.hh"
-#include "cpu/full_cpu/smt.hh"
-#include "cpu/full_cpu/thread.hh"
-#include "eio/eio.hh"
-#include "mem/functional_mem/main_memory.hh"
+#include "cpu/smt.hh"
+#include "encumbered/cpu/full/thread.hh"
+#include "encumbered/eio/eio.hh"
+#include "encumbered/mem/functional/main.hh"
 #include "sim/builder.hh"
 #include "sim/fake_syscall.hh"
 #include "sim/process.hh"
 #include "sim/stats.hh"
+#include "sim/syscall_emul.hh"
 
 #ifdef TARGET_ALPHA
 #include "arch/alpha/alpha_tru64_process.hh"
 #endif
 
 using namespace std;
+using namespace TheISA;
 
 //
 // The purpose of this code is to fake the loader & syscall mechanism
 // when there's no OS: thus there's no resone to use it in FULL_SYSTEM
 // mode when we do have an OS
 //
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
 #error "process.cc not compatible with FULL_SYSTEM"
 #endif
 
 // current number of allocated processes
 int num_processes = 0;
 
-Process::Process(const string &name,
+Process::Process(const string &nm,
                  int stdin_fd,         // initial I/O descriptors
                  int stdout_fd,
                  int stderr_fd)
-    : SimObject(name)
+    : SimObject(nm)
 {
     // allocate memory space
-    memory = new MainMemory(name + ".MainMem");
+    memory = new MainMemory(nm + ".MainMem");
 
     // allocate initial register file
     init_regs = new RegFile;
@@ -87,8 +91,8 @@ Process::Process(const string &name,
         fd_map[i] = -1;
     }
 
-    num_syscalls = 0;
-
+    mmap_start = mmap_end = 0;
+    nxm_start = nxm_end = 0;
     // other parameters will be initialized when the program is loaded
 }
 
@@ -144,24 +148,29 @@ Process::registerExecContext(ExecContext *xc)
     execContexts.push_back(xc);
 
     if (myIndex == 0) {
-        // first exec context for this process... initialize & enable
-
         // copy process's initial regs struct
         xc->regs = *init_regs;
-
-        // mark this context as active.
-        // activate with zero delay so that we start ticking right
-        // away on cycle 0
-        xc->activate(0);
     }
 
     // return CPU number to caller and increment available CPU count
     return myIndex;
 }
 
+void
+Process::startup()
+{
+    if (execContexts.empty())
+        return;
+
+    // first exec context for this process... initialize & enable
+    ExecContext *xc = execContexts[0];
+
+    // mark this context as active so it will start ticking.
+    xc->activate(0);
+}
 
 void
-Process::replaceExecContext(int xcIndex, ExecContext *xc)
+Process::replaceExecContext(ExecContext *xc, int xcIndex)
 {
     if (xcIndex >= execContexts.size()) {
         panic("replaceExecContext: bad xcIndex, %d >= %d\n",
@@ -184,23 +193,32 @@ Process::dup_fd(int sim_fd, int tgt_fd)
 
 // generate new target fd for sim_fd
 int
-Process::open_fd(int sim_fd)
+Process::alloc_fd(int sim_fd)
 {
-    int free_fd;
-
     // in case open() returns an error, don't allocate a new fd
     if (sim_fd == -1)
         return -1;
 
     // find first free target fd
-    for (free_fd = 0; fd_map[free_fd] >= 0; ++free_fd) {
-        if (free_fd == MAX_FD)
-            panic("Process::open_fd: out of file descriptors!");
+    for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) {
+        if (fd_map[free_fd] == -1) {
+            fd_map[free_fd] = sim_fd;
+            return free_fd;
+        }
     }
 
-    fd_map[free_fd] = sim_fd;
+    panic("Process::alloc_fd: out of file descriptors!");
+}
+
 
-    return free_fd;
+// free target fd (e.g., after close)
+void
+Process::free_fd(int tgt_fd)
+{
+    if (fd_map[tgt_fd] == -1)
+        warn("Process::free_fd: request to free unused fd %d", tgt_fd);
+
+    fd_map[tgt_fd] = -1;
 }
 
 
@@ -235,8 +253,10 @@ static void
 copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
                 FunctionalMemory *memory)
 {
+    Addr data_ptr_swap;
     for (int i = 0; i < strings.size(); ++i) {
-        memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+        data_ptr_swap = htog(data_ptr);
+        memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr));
         memory->writeString(data_ptr, strings[i].c_str());
         array_ptr += sizeof(Addr);
         data_ptr += strings[i].size() + 1;
@@ -246,10 +266,10 @@ copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
     memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
 }
 
-LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
+LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
                          int stdin_fd, int stdout_fd, int stderr_fd,
                          vector<string> &argv, vector<string> &envp)
-    : Process(name, stdin_fd, stdout_fd, stderr_fd)
+    : Process(nm, stdin_fd, stdout_fd, stderr_fd)
 {
     prog_fname = argv[0];
 
@@ -258,18 +278,30 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
     text_size = objFile->textSize();
     data_base = objFile->dataBase();
     data_size = objFile->dataSize() + objFile->bssSize();
-    brk_point = RoundUp<uint64_t>(data_base + data_size, VMPageSize);
+    brk_point = roundUp(data_base + data_size, VMPageSize);
 
     // load object file into target memory
     objFile->loadSections(memory);
 
+    // load up symbols, if any... these may be used for debugging or
+    // profiling.
+    if (!debugSymbolTable) {
+        debugSymbolTable = new SymbolTable();
+        if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
+            !objFile->loadLocalSymbols(debugSymbolTable)) {
+            // didn't load any symbols
+            delete debugSymbolTable;
+            debugSymbolTable = NULL;
+        }
+    }
+
     // Set up stack.  On Alpha, stack goes below text section.  This
     // code should get moved to some architecture-specific spot.
     stack_base = text_base - (409600+4096);
 
     // Set up region for mmaps.  Tru64 seems to start just above 0 and
     // grow up from there.
-    mmap_base = 0x10000;
+    mmap_start = mmap_end = 0x10000;
 
     // Set pointer for next thread stack.  Reserve 8M for main stack.
     next_thread_stack_base = stack_base - (8 * 1024 * 1024);
@@ -306,6 +338,7 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
 
     // write contents to stack
     uint64_t argc = argv.size();
+    argc = htog(argc);
     memory->access(Write, stack_min, &argc, sizeof(uint64_t));
 
     copyStringArray(argv, argv_array_base, arg_data_base, memory);
@@ -319,29 +352,43 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
     init_regs->npc = prog_entry + sizeof(MachInst);
 }
 
+void
+LiveProcess::syscall(ExecContext *xc)
+{
+    num_syscalls++;
+
+    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
+
+    SyscallDesc *desc = getDesc(callnum);
+    if (desc == NULL)
+        fatal("Syscall %d out of range", callnum);
+
+    desc->doSyscall(callnum, this, xc);
+}
 
 LiveProcess *
-LiveProcess::create(const string &name,
+LiveProcess::create(const string &nm,
                     int stdin_fd, int stdout_fd, int stderr_fd,
+                    string executable,
                     vector<string> &argv, vector<string> &envp)
 {
     LiveProcess *process = NULL;
-    ObjectFile *objFile = createObjectFile(argv[0]);
+    ObjectFile *objFile = createObjectFile(executable);
     if (objFile == NULL) {
-        fatal("Can't load object file %s", argv[0]);
+        fatal("Can't load object file %s", executable);
     }
 
     // check object type & set up syscall emulation pointer
     if (objFile->getArch() == ObjectFile::Alpha) {
         switch (objFile->getOpSys()) {
           case ObjectFile::Tru64:
-            process = new AlphaTru64Process(name, objFile,
+            process = new AlphaTru64Process(nm, objFile,
                                             stdin_fd, stdout_fd, stderr_fd,
                                             argv, envp);
             break;
 
           case ObjectFile::Linux:
-            process = new AlphaLinuxProcess(name, objFile,
+            process = new AlphaLinuxProcess(nm, objFile,
                                             stdin_fd, stdout_fd, stderr_fd,
                                             argv, envp);
             break;
@@ -362,9 +409,11 @@ LiveProcess::create(const string &name,
 }
 
 
+
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
 
     VectorParam<string> cmd;
+    Param<string> executable;
     Param<string> input;
     Param<string> output;
     VectorParam<string> env;
@@ -375,6 +424,7 @@ 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")
@@ -384,23 +434,30 @@ END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
 
 CREATE_SIM_OBJECT(LiveProcess)
 {
-    // initialize file descriptors to default: same as simulator
-    int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
-    int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
-    int stderr_fd = output.isValid() ? stdout_fd : 2;
+    string in = input;
+    string out = output;
 
-    // dummy for default env
-    vector<string> null_vec;
-
-    //  We do this with "temp" because of the bogus compiler warning
-    //  you get with g++ 2.95 -O if you just "return new LiveProcess(..."
-    LiveProcess *temp = LiveProcess::create(getInstanceName(),
-                                            stdin_fd, stdout_fd, stderr_fd,
-                                            cmd,
-                                            env.isValid() ? env : null_vec);
-
-    return temp;
+    // 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(),
+                               stdin_fd, stdout_fd, stderr_fd,
+                               (string)executable == "" ? cmd[0] : executable,
+                               cmd, env);
 }
 
-
 REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)