Move Linux/Tru64 architecture independent code into kern/*
authorAli Saidi <saidi@eecs.umich.edu>
Sun, 19 Feb 2006 04:44:22 +0000 (23:44 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Sun, 19 Feb 2006 04:44:22 +0000 (23:44 -0500)
leaving dependent code making way  for solaris linux syscall emu.

SConscript:
    Add two new files for syscall emulation
    Add getDesc() function
arch/alpha/alpha_linux_process.cc:
arch/alpha/alpha_tru64_process.cc:
    move architecture independent code into kern/linux/linux.(hh|cc)
arch/alpha/alpha_linux_process.hh:
arch/alpha/alpha_tru64_process.hh:
    Add getDesc function
kern/linux/linux.hh:
    move generi linux syscall emulation code into kern/linux
kern/tru64/tru64.hh:
    move generi tru64 syscall emulation code into kern/tru64
sim/process.cc:
sim/process.hh:
    Push the function determination and calling stuff down to LiveProcess
    and out of the Linux/Tru64 classes respectively
sim/syscall_emul.cc:
sim/syscall_emul.hh:
    fnctl implementation was identical in tru64 and linux so moved to generic

--HG--
extra : convert_revision : 103293dbe6fe2f7892de4929d17dc085def77026

SConscript
arch/alpha/alpha_linux_process.cc
arch/alpha/alpha_linux_process.hh
arch/alpha/alpha_tru64_process.cc
arch/alpha/alpha_tru64_process.hh
kern/linux/linux.hh
kern/tru64/tru64.hh
sim/process.cc
sim/process.hh
sim/syscall_emul.cc
sim/syscall_emul.hh

index fc2e6ae0bf299b4921cd3c520da3c7e85e44e269..1daf68eadbaa8152110488997380ee9bfc2c3450 100644 (file)
@@ -330,6 +330,8 @@ syscall_emulation_sources = Split('''
        encumbered/eio/eio.cc
        encumbered/eio/exolex.cc
        encumbered/eio/libexo.cc
+        kern/linux/linux.cc
+        kern/tru64/tru64.cc
        sim/process.cc
        sim/syscall_emul.cc
         ''')
index fb5e32e63e9601c0b81572077fc91f37261a5c4f..6d50756f2b228ddcf385b5e2ca17cec7556e0ded 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>     // for host open() flags
-#include <string.h>    // for memset()
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "arch/alpha/alpha_linux_process.hh"
+#include "arch/alpha/isa_traits.hh"
 
-#include "cpu/base.hh"
+#include "base/trace.hh"
 #include "cpu/exec_context.hh"
+#include "kern/linux/linux.hh"
 #include "mem/functional/functional.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/host.hh"
-#include "sim/process.hh"
-#include "sim/sim_events.hh"
 
-#include "arch/alpha/isa_traits.hh"
-#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "sim/process.hh"
 #include "sim/syscall_emul.hh"
-#include "sim/root.hh" // for curTick & ticksPerSecond
-
-#include "arch/alpha/alpha_linux_process.hh"
-
-#include "base/trace.hh"
 
 using namespace std;
 
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Linux
-/// syscall interface.
-///
-class Linux {
-
-  public:
-
-    //@{
-    /// Basic Linux types.
-    typedef uint64_t size_t;
-    typedef uint64_t off_t;
-    typedef int64_t time_t;
-    typedef uint32_t uid_t;
-    typedef uint32_t gid_t;
-    //@}
-
-#if BSD_HOST
-    typedef struct stat hst_stat;
-    typedef struct stat hst_stat64;
-#else
-    typedef struct stat hst_stat ;
-    typedef struct stat64 hst_stat64;
-#endif
-
-
-    //@{
-    /// open(2) flag values.
-    static const int TGT_O_RDONLY      = 00000000;     //!< O_RDONLY
-    static const int TGT_O_WRONLY      = 00000001;     //!< O_WRONLY
-    static const int TGT_O_RDWR                = 00000002;     //!< O_RDWR
-    static const int TGT_O_NONBLOCK    = 00000004;     //!< O_NONBLOCK
-    static const int TGT_O_APPEND      = 00000010;     //!< O_APPEND
-    static const int TGT_O_CREAT       = 00001000;     //!< O_CREAT
-    static const int TGT_O_TRUNC       = 00002000;     //!< O_TRUNC
-    static const int TGT_O_EXCL                = 00004000;     //!< O_EXCL
-    static const int TGT_O_NOCTTY      = 00010000;     //!< O_NOCTTY
-    static const int TGT_O_SYNC                = 00040000;     //!< O_SYNC
-    static const int TGT_O_DRD         = 00100000;     //!< O_DRD
-    static const int TGT_O_DIRECTIO    = 00200000;     //!< O_DIRECTIO
-    static const int TGT_O_CACHE       = 00400000;     //!< O_CACHE
-    static const int TGT_O_DSYNC       = 02000000;     //!< O_DSYNC
-    static const int TGT_O_RSYNC       = 04000000;     //!< O_RSYNC
-    //@}
-
-    /// This table maps the target open() flags to the corresponding
-    /// host open() flags.
-    static OpenFlagTransTable openFlagTable[];
-
-    /// Number of entries in openFlagTable[].
-    static const int NUM_OPEN_FLAGS;
-
-    /// Stat buffer.  Note that we can't call it 'stat' since that
-    /// gets #defined to something else on some systems.
-    struct tgt_stat {
-        uint32_t       st_dev;         //!< device
-        uint32_t       st_ino;         //!< inode
-        uint32_t       st_mode;        //!< mode
-        uint32_t       st_nlink;       //!< link count
-        uint32_t       st_uid;         //!< owner's user ID
-        uint32_t       st_gid;         //!< owner's group ID
-        uint32_t       st_rdev;        //!< device number
-        int32_t                _pad1;          //!< for alignment
-        int64_t                st_size;        //!< file size in bytes
-        uint64_t       st_atimeX;      //!< time of last access
-        uint64_t       st_mtimeX;      //!< time of last modification
-        uint64_t       st_ctimeX;      //!< time of last status change
-        uint32_t       st_blksize;     //!< optimal I/O block size
-        int32_t                st_blocks;      //!< number of blocks allocated
-        uint32_t       st_flags;       //!< flags
-        uint32_t       st_gen;         //!< unknown
-    };
-
-    // same for stat64
-    struct tgt_stat64 {
-        uint64_t       st_dev;
-        uint64_t       st_ino;
-        uint64_t       st_rdev;
-        int64_t                st_size;
-        uint64_t       st_blocks;
-
-        uint32_t       st_mode;
-        uint32_t       st_uid;
-        uint32_t       st_gid;
-        uint32_t       st_blksize;
-        uint32_t       st_nlink;
-        uint32_t       __pad0;
-
-        uint64_t       tgt_st_atime;
-        uint64_t       st_atime_nsec;
-        uint64_t       tgt_st_mtime;
-        uint64_t       st_mtime_nsec;
-        uint64_t       tgt_st_ctime;
-        uint64_t       st_ctime_nsec;
-        int64_t                ___unused[3];
-    };
-
-    /// Length of strings in struct utsname (plus 1 for null char).
-    static const int _SYS_NMLN = 65;
-
-    /// Interface struct for uname().
-    struct utsname {
-        char sysname[_SYS_NMLN];       //!< System name.
-        char nodename[_SYS_NMLN];      //!< Node name.
-        char release[_SYS_NMLN];       //!< OS release.
-        char version[_SYS_NMLN];       //!< OS version.
-        char machine[_SYS_NMLN];       //!< Machine type.
-    };
-
-
-    //@{
-    /// ioctl() command codes.
-    static const unsigned TIOCGETP   = 0x40067408;
-    static const unsigned TIOCSETP   = 0x80067409;
-    static const unsigned TIOCSETN   = 0x8006740a;
-    static const unsigned TIOCSETC   = 0x80067411;
-    static const unsigned TIOCGETC   = 0x40067412;
-    static const unsigned FIONREAD   = 0x4004667f;
-    static const unsigned TIOCISATTY = 0x2000745e;
-    static const unsigned TIOCGETS   = 0x402c7413;
-    static const unsigned TIOCGETA   = 0x40127417;
-    //@}
-
-    /// Resource enumeration for getrlimit().
-    enum rlimit_resources {
-        TGT_RLIMIT_CPU = 0,
-        TGT_RLIMIT_FSIZE = 1,
-        TGT_RLIMIT_DATA = 2,
-        TGT_RLIMIT_STACK = 3,
-        TGT_RLIMIT_CORE = 4,
-        TGT_RLIMIT_RSS = 5,
-        TGT_RLIMIT_NOFILE = 6,
-        TGT_RLIMIT_AS = 7,
-        TGT_RLIMIT_VMEM = 7,
-        TGT_RLIMIT_NPROC = 8,
-        TGT_RLIMIT_MEMLOCK = 9,
-        TGT_RLIMIT_LOCKS = 10
-    };
-
-    /// Limit struct for getrlimit/setrlimit.
-    struct rlimit {
-        uint64_t  rlim_cur;    //!< soft limit
-        uint64_t  rlim_max;    //!< hard limit
-    };
-
-
-    /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
-    /// For gettimeofday().
-    struct timeval {
-        int64_t tv_sec;                //!< seconds
-        int64_t tv_usec;       //!< microseconds
-    };
-
-    // For writev/readv
-    struct tgt_iovec {
-        uint64_t iov_base; // void *
-        uint64_t iov_len;
-    };
-
-    //@{
-    /// For getrusage().
-    static const int TGT_RUSAGE_SELF = 0;
-    static const int TGT_RUSAGE_CHILDREN = -1;
-    static const int TGT_RUSAGE_BOTH = -2;
-    //@}
-
-    /// For getrusage().
-    struct rusage {
-        struct timeval ru_utime;       //!< user time used
-        struct timeval ru_stime;       //!< system time used
-        int64_t ru_maxrss;             //!< max rss
-        int64_t ru_ixrss;              //!< integral shared memory size
-        int64_t ru_idrss;              //!< integral unshared data "
-        int64_t ru_isrss;              //!< integral unshared stack "
-        int64_t ru_minflt;             //!< page reclaims - total vmfaults
-        int64_t ru_majflt;             //!< page faults
-        int64_t ru_nswap;              //!< swaps
-        int64_t ru_inblock;            //!< block input operations
-        int64_t ru_oublock;            //!< block output operations
-        int64_t ru_msgsnd;             //!< messages sent
-        int64_t ru_msgrcv;             //!< messages received
-        int64_t ru_nsignals;           //!< signals received
-        int64_t ru_nvcsw;              //!< voluntary context switches
-        int64_t ru_nivcsw;             //!< involuntary "
-    };
-
-    /// Helper function to convert a host stat buffer to a target stat
-    /// buffer.  Also copies the target buffer out to the simulated
-    /// memory space.  Used by stat(), fstat(), and lstat().
-#if !BSD_HOST
-    static void
-    copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
-    {
-        TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
-        tgt->st_dev = htog(host->st_dev);
-        tgt->st_ino = htog(host->st_ino);
-        tgt->st_mode = htog(host->st_mode);
-        tgt->st_nlink = htog(host->st_nlink);
-        tgt->st_uid = htog(host->st_uid);
-        tgt->st_gid = htog(host->st_gid);
-        tgt->st_rdev = htog(host->st_rdev);
-        tgt->st_size = htog(host->st_size);
-        tgt->st_atimeX = htog(host->st_atime);
-        tgt->st_mtimeX = htog(host->st_mtime);
-        tgt->st_ctimeX = htog(host->st_ctime);
-        tgt->st_blksize = htog(host->st_blksize);
-        tgt->st_blocks = htog(host->st_blocks);
-
-        tgt.copyOut(mem);
-    }
-#else
-    // Third version for bsd systems which no longer have any support for
-    // the old stat() call and stat() is actually a stat64()
-    static void
-    copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
-    {
-        TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
-        tgt->st_dev = htog(host->st_dev);
-        tgt->st_ino = htog(host->st_ino);
-        tgt->st_mode = htog(host->st_mode);
-        tgt->st_nlink = htog(host->st_nlink);
-        tgt->st_uid = htog(host->st_uid);
-        tgt->st_gid = htog(host->st_gid);
-        tgt->st_rdev = htog(host->st_rdev);
-        tgt->st_size = htog(host->st_size);
-        tgt->st_atimeX = htog(host->st_atime);
-        tgt->st_mtimeX = htog(host->st_mtime);
-        tgt->st_ctimeX = htog(host->st_ctime);
-        tgt->st_blksize = htog(host->st_blksize);
-        tgt->st_blocks = htog(host->st_blocks);
-
-        tgt.copyOut(mem);
-    }
-#endif
-
-
-    // Same for stat64
-    static void
-    copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
-    {
-        TypedBufferArg<Linux::tgt_stat64> tgt(addr);
-
-        // fd == 1 checks are because libc does some checks
-        // that the stdout is interactive vs. a file
-        // this makes it work on non-linux systems
-        if (fd == 1)
-            tgt->st_dev = htog((uint64_t)0xA);
-        else
-            tgt->st_dev = htog((uint64_t)host->st_dev);
-        // XXX What about STAT64_HAS_BROKEN_ST_INO ???
-        tgt->st_ino = htog((uint64_t)host->st_ino);
-        if (fd == 1)
-            tgt->st_rdev = htog((uint64_t)0x880d);
-        else
-            tgt->st_rdev = htog((uint64_t)host->st_rdev);
-        tgt->st_size = htog((int64_t)host->st_size);
-        tgt->st_blocks = htog((uint64_t)host->st_blocks);
-
-        if (fd == 1)
-            tgt->st_mode = htog((uint32_t)0x2190);
-        else
-            tgt->st_mode = htog((uint32_t)host->st_mode);
-        tgt->st_uid = htog((uint32_t)host->st_uid);
-        tgt->st_gid = htog((uint32_t)host->st_gid);
-        tgt->st_blksize = htog((uint32_t)host->st_blksize);
-        tgt->st_nlink = htog((uint32_t)host->st_nlink);
-        tgt->tgt_st_atime = htog((uint64_t)host->st_atime);
-        tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime);
-        tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime);
-#if defined(STAT_HAVE_NSEC)
-        tgt->st_atime_nsec = htog(host->st_atime_nsec);
-        tgt->st_mtime_nsec = htog(host->st_mtime_nsec);
-        tgt->st_ctime_nsec = htog(host->st_ctime_nsec);
-#else
-        tgt->st_atime_nsec = 0;
-        tgt->st_mtime_nsec = 0;
-        tgt->st_ctime_nsec = 0;
-#endif
-
-        tgt.copyOut(mem);
-    }
-
-    /// The target system's hostname.
-    static const char *hostname;
-
-    /// Target uname() handler.
-    static SyscallReturn
-    unameFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-    {
-        TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-
-        strcpy(name->sysname, "Linux");
-        strcpy(name->nodename, hostname);
-        strcpy(name->release, "2.4.20");
-        strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
-        strcpy(name->machine, "alpha");
-
-        name.copyOut(xc->mem);
-        return 0;
-    }
-
-    /// Target osf_getsysyinfo() handler.  Even though this call is
-    /// borrowed from Tru64, the subcases that get used appear to be
-    /// different in practice from those used by Tru64 processes.
-    static SyscallReturn
-    osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
-                       ExecContext *xc)
-    {
-        unsigned op = xc->getSyscallArg(0);
-        // unsigned nbytes = xc->getSyscallArg(2);
-
-        switch (op) {
-
-          case 45: { // GSI_IEEE_FP_CONTROL
-              TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
-              // I don't think this exactly matches the HW FPCR
-              *fpcr = 0;
-              fpcr.copyOut(xc->mem);
-              return 0;
-          }
-
-          default:
-            cerr << "osf_getsysinfo: unknown op " << op << endl;
-            abort();
-            break;
-        }
-
-        return 1;
-    }
-
-    /// Target osf_setsysinfo() handler.
-    static SyscallReturn
-    osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
-                       ExecContext *xc)
-    {
-        unsigned op = xc->getSyscallArg(0);
-        // unsigned nbytes = xc->getSyscallArg(2);
-
-        switch (op) {
-
-          case 14: { // SSI_IEEE_FP_CONTROL
-              TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
-              // I don't think this exactly matches the HW FPCR
-              fpcr.copyIn(xc->mem);
-              DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
-                       " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
-              return 0;
-          }
-
-          default:
-            cerr << "osf_setsysinfo: unknown op " << op << endl;
-            abort();
-            break;
-        }
-
-        return 1;
-    }
-
-    /// Target fnctl() handler.
-    static SyscallReturn
-    fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-    {
-        int fd = xc->getSyscallArg(0);
-
-        if (fd < 0 || process->sim_fd(fd) < 0)
-            return -EBADF;
-
-        int cmd = xc->getSyscallArg(1);
-        switch (cmd) {
-          case 0: // F_DUPFD
-            // if we really wanted to support this, we'd need to do it
-            // in the target fd space.
-            warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
-            return -EMFILE;
-
-          case 1: // F_GETFD (get close-on-exec flag)
-          case 2: // F_SETFD (set close-on-exec flag)
-            return 0;
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
 
-          case 3: // F_GETFL (get file flags)
-          case 4: // F_SETFL (set file flags)
-            // not sure if this is totally valid, but we'll pass it through
-            // to the underlying OS
-            warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
-            return fcntl(process->sim_fd(fd), cmd);
-            // return 0;
+    strcpy(name->sysname, "Linux");
+    strcpy(name->nodename, "m5.eecs.umich.edu");
+    strcpy(name->release, "2.4.20");
+    strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+    strcpy(name->machine, "alpha");
 
-          case 7: // F_GETLK  (get lock)
-          case 8: // F_SETLK  (set lock)
-          case 9: // F_SETLKW (set lock and wait)
-            // don't mess with file locking... just act like it's OK
-            warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
-            return 0;
+    name.copyOut(xc->mem);
+    return 0;
+}
 
-          default:
-            warn("Unknown fcntl command %d\n", cmd);
-            return 0;
-        }
+/// Target osf_getsysyinfo() handler.  Even though this call is
+/// borrowed from Tru64, the subcases that get used appear to be
+/// different in practice from those used by Tru64 processes.
+static SyscallReturn
+osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    // unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case 45: { // GSI_IEEE_FP_CONTROL
+          TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+          // I don't think this exactly matches the HW FPCR
+          *fpcr = 0;
+          fpcr.copyOut(xc->mem);
+          return 0;
+      }
+
+      default:
+        cerr << "osf_getsysinfo: unknown op " << op << endl;
+        abort();
+        break;
     }
 
-    /// Array of syscall descriptors, indexed by call number.
-    static SyscallDesc syscallDescs[];
-
-    /// Number of syscalls in syscallDescs[].
-    static const int Num_Syscall_Descs;
-
-    /// Max supported syscall number.
-    static const int Max_Syscall_Desc;
-
-    /// Do the specified syscall.  Just looks the call number up in
-    /// the table and invokes the appropriate handler.
-    static void
-    doSyscall(int callnum, Process *process, ExecContext *xc)
-    {
-        if (callnum < 0 || callnum > Max_Syscall_Desc) {
-            fatal("Syscall %d out of range", callnum);
-        }
-
-        SyscallDesc *desc = &syscallDescs[callnum];
+    return 1;
+}
 
-        desc->doSyscall(callnum, process, xc);
+/// Target osf_setsysinfo() handler.
+static SyscallReturn
+osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    // unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case 14: { // SSI_IEEE_FP_CONTROL
+          TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+          // I don't think this exactly matches the HW FPCR
+          fpcr.copyIn(xc->mem);
+          DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+                   " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+          return 0;
+      }
+
+      default:
+        cerr << "osf_setsysinfo: unknown op " << op << endl;
+        abort();
+        break;
     }
-};  // class Linux
 
+    return 1;
+}
 
-// open(2) flags translation table
-OpenFlagTransTable Linux::openFlagTable[] = {
-#ifdef _MSC_VER
-  { Linux::TGT_O_RDONLY,       _O_RDONLY },
-  { Linux::TGT_O_WRONLY,       _O_WRONLY },
-  { Linux::TGT_O_RDWR,         _O_RDWR },
-  { Linux::TGT_O_APPEND,       _O_APPEND },
-  { Linux::TGT_O_CREAT,                _O_CREAT },
-  { Linux::TGT_O_TRUNC,                _O_TRUNC },
-  { Linux::TGT_O_EXCL,         _O_EXCL },
-#ifdef _O_NONBLOCK
-  { Linux::TGT_O_NONBLOCK,     _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
-  { Linux::TGT_O_NOCTTY,       _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
-  { Linux::TGT_O_SYNC,         _O_SYNC },
-#endif
-#else /* !_MSC_VER */
-  { Linux::TGT_O_RDONLY,       O_RDONLY },
-  { Linux::TGT_O_WRONLY,       O_WRONLY },
-  { Linux::TGT_O_RDWR,         O_RDWR },
-  { Linux::TGT_O_APPEND,       O_APPEND },
-  { Linux::TGT_O_CREAT,                O_CREAT },
-  { Linux::TGT_O_TRUNC,                O_TRUNC },
-  { Linux::TGT_O_EXCL,         O_EXCL },
-  { Linux::TGT_O_NONBLOCK,     O_NONBLOCK },
-  { Linux::TGT_O_NOCTTY,       O_NOCTTY },
-#ifdef O_SYNC
-  { Linux::TGT_O_SYNC,         O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-
-const int Linux::NUM_OPEN_FLAGS =
-        (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
-
-const char *Linux::hostname = "m5.eecs.umich.edu";
 
-SyscallDesc Linux::syscallDescs[] = {
+SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
     /*  0 */ SyscallDesc("osf_syscall", unimplementedFunc),
     /*  1 */ SyscallDesc("exit", exitFunc),
     /*  2 */ SyscallDesc("fork", unimplementedFunc),
@@ -973,23 +563,6 @@ SyscallDesc Linux::syscallDescs[] = {
     /* 441 */ SyscallDesc("keyctl", unimplementedFunc)
 };
 
-const int Linux::Num_Syscall_Descs =
-        sizeof(Linux::syscallDescs) / sizeof(SyscallDesc);
-
-const int Linux::Max_Syscall_Desc = Linux::Num_Syscall_Descs - 1;
-
-
-void
-AlphaLinuxProcess::syscall(ExecContext *xc)
-{
-    num_syscalls++;
-
-    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
-    Linux::doSyscall(callnum, this, xc);
-}
-
-
 AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
                                      ObjectFile *objFile,
                                      int stdin_fd,
@@ -997,7 +570,18 @@ AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
                                      int stderr_fd,
                                      std::vector<std::string> &argv,
                                      std::vector<std::string> &envp)
-    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp)
+    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+     Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
 {
     init_regs->intRegFile[0] = 0;
 }
+
+
+
+SyscallDesc*
+AlphaLinuxProcess::getDesc(int callnum)
+{
+    if (callnum < 0 || callnum > Num_Syscall_Descs)
+        return NULL;
+    return &syscallDescs[callnum];
+}
index b4fe8e8f89241770a6c0ec1b29e93fc0bdf724d4..7de1b1ac18c66deeaf69820aa8022ec9a13c2180 100644 (file)
@@ -43,8 +43,15 @@ class AlphaLinuxProcess : public LiveProcess
                       std::vector<std::string> &argv,
                       std::vector<std::string> &envp);
 
-    /// Syscall emulation function.
-    virtual void syscall(ExecContext *xc);
+    virtual SyscallDesc* getDesc(int callnum);
+
+    /// The target system's hostname.
+    static const char *hostname;
+
+     /// Array of syscall descriptors, indexed by call number.
+    static SyscallDesc syscallDescs[];
+
+    const int Num_Syscall_Descs;
 };
 
 
index 5c24adad91c8e0fd9fb7a3e4af77f21b6da8d0b1..90f01637dbeea54c657c1dceb8936c5141e78b25 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>     // for host open() flags
-#include <string.h>    // for memset()
-#include <unistd.h>
-
 #include "arch/alpha/isa_traits.hh"
 #include "arch/alpha/alpha_common_syscall_emul.hh"
 #include "arch/alpha/alpha_tru64_process.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
 #include "cpu/exec_context.hh"
+#include "kern/tru64/tru64.hh"
 #include "mem/functional/functional.hh"
 #include "sim/fake_syscall.hh"
-#include "sim/host.hh"
 #include "sim/process.hh"
-#include "sim/root.hh"
 #include "sim/syscall_emul.hh"
 
 using namespace std;
 
-typedef struct stat global_stat;
-typedef struct statfs global_statfs;
-typedef struct dirent global_dirent;
-
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Tru64
-/// syscall interface.
-///
-class Tru64 {
-
-  public:
-
-    //@{
-    /// Basic Tru64 types.
-    typedef uint64_t size_t;
-    typedef uint64_t off_t;
-    typedef uint16_t nlink_t;
-    typedef int32_t  dev_t;
-    typedef uint32_t uid_t;
-    typedef uint32_t gid_t;
-    typedef uint32_t time_t;
-    typedef uint32_t mode_t;
-    typedef uint32_t ino_t;
-    typedef struct { int val[2]; } quad;
-    typedef quad fsid_t;
-    //@}
-
-    //@{
-    /// open(2) flag values.
-    static const int TGT_O_RDONLY      = 00000000;
-    static const int TGT_O_WRONLY      = 00000001;
-    static const int TGT_O_RDWR                = 00000002;
-    static const int TGT_O_NONBLOCK    = 00000004;
-    static const int TGT_O_APPEND      = 00000010;
-    static const int TGT_O_CREAT       = 00001000;
-    static const int TGT_O_TRUNC       = 00002000;
-    static const int TGT_O_EXCL                = 00004000;
-    static const int TGT_O_NOCTTY      = 00010000;
-    static const int TGT_O_SYNC                = 00040000;
-    static const int TGT_O_DRD         = 00100000;
-    static const int TGT_O_DIRECTIO    = 00200000;
-    static const int TGT_O_CACHE       = 00400000;
-    static const int TGT_O_DSYNC       = 02000000;
-    static const int TGT_O_RSYNC       = 04000000;
-    //@}
-
-    /// This table maps the target open() flags to the corresponding
-    /// host open() flags.
-    static OpenFlagTransTable openFlagTable[];
-
-    /// Number of entries in openFlagTable[].
-    static const int NUM_OPEN_FLAGS;
-
-    /// Stat buffer.  Note that Tru64 v5.0+ use a new "F64" stat
-    /// structure, and a new set of syscall numbers for stat calls.
-    /// On some hosts (notably Linux) define st_atime, st_mtime, and
-    /// st_ctime as macros, so we append an X to get around this.
-    struct F64_stat {
-        dev_t  st_dev;                 //!< st_dev
-        int32_t        st_retired1;            //!< st_retired1
-        mode_t st_mode;                //!< st_mode
-        nlink_t        st_nlink;               //!< st_nlink
-        uint16_t st_nlink_reserved;    //!< st_nlink_reserved
-        uid_t  st_uid;                 //!< st_uid
-        gid_t  st_gid;                 //!< st_gid
-        dev_t  st_rdev;                //!< st_rdev
-        dev_t  st_ldev;                //!< st_ldev
-        off_t  st_size;                //!< st_size
-        time_t st_retired2;            //!< st_retired2
-        int32_t        st_uatime;              //!< st_uatime
-        time_t st_retired3;            //!< st_retired3
-        int32_t        st_umtime;              //!< st_umtime
-        time_t st_retired4;            //!< st_retired4
-        int32_t        st_uctime;              //!< st_uctime
-        int32_t        st_retired5;            //!< st_retired5
-        int32_t        st_retired6;            //!< st_retired6
-        uint32_t       st_flags;       //!< st_flags
-        uint32_t       st_gen;         //!< st_gen
-        uint64_t       st_spare[4];    //!< st_spare[4]
-        ino_t  st_ino;                 //!< st_ino
-        int32_t        st_ino_reserved;        //!< st_ino_reserved
-        time_t st_atimeX;              //!< st_atime
-        int32_t        st_atime_reserved;      //!< st_atime_reserved
-        time_t st_mtimeX;              //!< st_mtime
-        int32_t        st_mtime_reserved;      //!< st_mtime_reserved
-        time_t st_ctimeX;              //!< st_ctime
-        int32_t        st_ctime_reserved;      //!< st_ctime_reserved
-        uint64_t       st_blksize;     //!< st_blksize
-        uint64_t       st_blocks;      //!< st_blocks
-    };
-
-
-    /// Old Tru64 v4.x stat struct.
-    /// Tru64 maintains backwards compatibility with v4.x by
-    /// implementing another set of stat functions using the old
-    /// structure definition and binding them to the old syscall
-    /// numbers.
-    struct pre_F64_stat {
-        dev_t   st_dev;
-        ino_t   st_ino;
-        mode_t  st_mode;
-        nlink_t st_nlink;
-        uid_t   st_uid;
-        gid_t   st_gid;
-        dev_t   st_rdev;
-        off_t   st_size;
-        time_t  st_atimeX;
-        int32_t st_uatime;
-        time_t  st_mtimeX;
-        int32_t st_umtime;
-        time_t  st_ctimeX;
-        int32_t st_uctime;
-        uint32_t st_blksize;
-        int32_t st_blocks;
-        uint32_t st_flags;
-        uint32_t st_gen;
-    };
-
-    /// For statfs().
-    struct F64_statfs {
-        int16_t   f_type;
-        int16_t   f_flags;
-        int32_t     f_retired1;
-        int32_t     f_retired2;
-        int32_t     f_retired3;
-        int32_t     f_retired4;
-        int32_t     f_retired5;
-        int32_t     f_retired6;
-        int32_t     f_retired7;
-        fsid_t f_fsid;
-        int32_t     f_spare[9];
-        char    f_retired8[90];
-        char    f_retired9[90];
-        uint64_t dummy[10]; // was union mount_info mount_info;
-        uint64_t  f_flags2;
-        int64_t    f_spare2[14];
-        int64_t    f_fsize;
-        int64_t    f_bsize;
-        int64_t    f_blocks;
-        int64_t    f_bfree;
-        int64_t    f_bavail;
-        int64_t    f_files;
-        int64_t    f_ffree;
-        char    f_mntonname[1024];
-        char    f_mntfromname[1024];
-    };
-
-    /// For old Tru64 v4.x statfs()
-    struct pre_F64_statfs {
-        int16_t   f_type;
-        int16_t   f_flags;
-        int32_t     f_fsize;
-        int32_t     f_bsize;
-        int32_t     f_blocks;
-        int32_t     f_bfree;
-        int32_t     f_bavail;
-        int32_t     f_files;
-        int32_t     f_ffree;
-        fsid_t  f_fsid;
-        int32_t     f_spare[9];
-        char    f_mntonname[90];
-        char    f_mntfromname[90];
-        uint64_t dummy[10]; // was union mount_info mount_info;
-    };
-
-    /// For getdirentries().
-    struct dirent
-    {
-        ino_t d_ino;           //!< file number of entry
-        uint16_t d_reclen;     //!< length of this record
-        uint16_t d_namlen;     //!< length of string in d_name
-        char d_name[256];      //!< dummy name length
-    };
-
-
-    /// Length of strings in struct utsname (plus 1 for null char).
-    static const int _SYS_NMLN = 32;
-
-    /// Interface struct for uname().
-    struct utsname {
-        char sysname[_SYS_NMLN];        //!< System name.
-        char nodename[_SYS_NMLN];       //!< Node name.
-        char release[_SYS_NMLN];        //!< OS release.
-        char version[_SYS_NMLN];        //!< OS version.
-        char machine[_SYS_NMLN];        //!< Machine type.
-    };
-
-    //@{
-    /// ioctl() command codes.
-    static const unsigned TIOCGETP   = 0x40067408;
-    static const unsigned TIOCSETP   = 0x80067409;
-    static const unsigned TIOCSETN   = 0x8006740a;
-    static const unsigned TIOCSETC   = 0x80067411;
-    static const unsigned TIOCGETC   = 0x40067412;
-    static const unsigned FIONREAD   = 0x4004667f;
-    static const unsigned TIOCISATTY = 0x2000745e;
-    // TIOCGETS not defined in tru64, so I made up a number
-    static const unsigned TIOCGETS   = 0x40000000;
-    static const unsigned TIOCGETA   = 0x402c7413;
-    //@}
-
-    /// Resource enumeration for getrlimit().
-    enum rlimit_resources {
-        TGT_RLIMIT_CPU = 0,
-        TGT_RLIMIT_FSIZE = 1,
-        TGT_RLIMIT_DATA = 2,
-        TGT_RLIMIT_STACK = 3,
-        TGT_RLIMIT_CORE = 4,
-        TGT_RLIMIT_RSS = 5,
-        TGT_RLIMIT_NOFILE = 6,
-        TGT_RLIMIT_AS = 7,
-        TGT_RLIMIT_VMEM = 7
-    };
-
-    /// Limit struct for getrlimit/setrlimit.
-    struct rlimit {
-        uint64_t  rlim_cur;    //!< soft limit
-        uint64_t  rlim_max;    //!< hard limit
-    };
-
-
-    /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
-
-    //@{
-    /// For getsysinfo().
-    static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
-    static const unsigned GSI_CPU_INFO = 59;   //!< CPU information
-    static const unsigned GSI_PROC_TYPE = 60;  //!< get proc_type
-    static const unsigned GSI_MAX_CPU = 30;   //!< max # cpu's on this machine
-    static const unsigned GSI_CPUS_IN_BOX = 55;        //!< number of CPUs in system
-    static const unsigned GSI_PHYSMEM = 19;    //!< Physical memory in KB
-    static const unsigned GSI_CLK_TCK = 42;    //!< clock freq in Hz
-    //@}
-
-    /// For getsysinfo() GSI_CPU_INFO option.
-    struct cpu_info {
-        uint32_t     current_cpu;      //!< current_cpu
-        uint32_t     cpus_in_box;      //!< cpus_in_box
-        uint32_t     cpu_type;         //!< cpu_type
-        uint32_t     ncpus;            //!< ncpus
-        uint64_t     cpus_present;     //!< cpus_present
-        uint64_t     cpus_running;     //!< cpus_running
-        uint64_t     cpu_binding;      //!< cpu_binding
-        uint64_t     cpu_ex_binding;   //!< cpu_ex_binding
-        uint32_t     mhz;              //!< mhz
-        uint32_t     unused[3];                //!< future expansion
-    };
-
-    //@{
-    /// For setsysinfo().
-    static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
-    //@}
-
-    /// For gettimeofday.
-    struct timeval {
-        uint32_t tv_sec;       //!< seconds
-        uint32_t tv_usec;      //!< microseconds
-    };
-
-    //@{
-    /// For getrusage().
-    static const int TGT_RUSAGE_THREAD = 1;
-    static const int TGT_RUSAGE_SELF = 0;
-    static const int TGT_RUSAGE_CHILDREN = -1;
-    //@}
-
-    /// For getrusage().
-    struct rusage {
-        struct timeval ru_utime;       //!< user time used
-        struct timeval ru_stime;       //!< system time used
-        uint64_t ru_maxrss;            //!< ru_maxrss
-        uint64_t ru_ixrss;             //!< integral shared memory size
-        uint64_t ru_idrss;             //!< integral unshared data "
-        uint64_t ru_isrss;             //!< integral unshared stack "
-        uint64_t ru_minflt;            //!< page reclaims - total vmfaults
-        uint64_t ru_majflt;            //!< page faults
-        uint64_t ru_nswap;             //!< swaps
-        uint64_t ru_inblock;           //!< block input operations
-        uint64_t ru_oublock;           //!< block output operations
-        uint64_t ru_msgsnd;            //!< messages sent
-        uint64_t ru_msgrcv;            //!< messages received
-        uint64_t ru_nsignals;          //!< signals received
-        uint64_t ru_nvcsw;             //!< voluntary context switches
-        uint64_t ru_nivcsw;            //!< involuntary "
-    };
-
-    /// For sigreturn().
-    struct sigcontext {
-        int64_t sc_onstack;            //!< sigstack state to restore
-        int64_t sc_mask;               //!< signal mask to restore
-        int64_t sc_pc;                 //!< pc at time of signal
-        int64_t sc_ps;                 //!< psl to retore
-        int64_t sc_regs[32];           //!< processor regs 0 to 31
-        int64_t sc_ownedfp;            //!< fp has been used
-        int64_t sc_fpregs[32];         //!< fp regs 0 to 31
-        uint64_t sc_fpcr;              //!< floating point control reg
-        uint64_t sc_fp_control;                //!< software fpcr
-        int64_t sc_reserved1;          //!< reserved for kernel
-        uint32_t sc_kreserved1;                //!< reserved for kernel
-        uint32_t sc_kreserved2;                //!< reserved for kernel
-        size_t  sc_ssize;              //!< stack size
-        caddr_t sc_sbase;              //!< stack start
-        uint64_t sc_traparg_a0;                //!< a0 argument to trap on exc
-        uint64_t sc_traparg_a1;                //!< a1 argument to trap on exc
-        uint64_t sc_traparg_a2;                //!< a2 argument to trap on exc
-        uint64_t sc_fp_trap_pc;                //!< imprecise pc
-        uint64_t sc_fp_trigger_sum;    //!< Exception summary at trigg
-        uint64_t sc_fp_trigger_inst;   //!< Instruction at trigger pc
-    };
-
-
-    /// For table().
-    static const int TBL_SYSINFO = 12;
-
-    /// For table().
-    struct tbl_sysinfo {
-        uint64_t si_user;      //!< User time
-        uint64_t si_nice;      //!< Nice time
-        uint64_t si_sys;       //!< System time
-        uint64_t si_idle;      //!< Idle time
-        uint64_t si_hz;                //!< hz
-        uint64_t si_phz;       //!< phz
-        uint64_t si_boottime;  //!< Boot time in seconds
-        uint64_t wait;         //!< Wait time
-        uint32_t  si_max_procs;        //!< rpb->rpb_numprocs
-        uint32_t  pad;         //!< padding
-    };
-
-
-    /// For stack_create.
-    struct vm_stack {
-        // was void *
-        Addr   address;        //!< address hint
-        size_t rsize;          //!< red zone size
-        size_t ysize;          //!< yellow zone size
-        size_t gsize;          //!< green zone size
-        size_t swap;           //!< amount of swap to reserve
-        size_t incr;           //!< growth increment
-        uint64_t       align;          //!< address alignment
-        uint64_t       flags;          //!< MAP_FIXED etc.
-        // was struct memalloc_attr *
-        Addr   attr;           //!< allocation policy
-        uint64_t reserved;     //!< reserved
-    };
-
-    /// Return values for nxm calls.
-    enum {
-        KERN_NOT_RECEIVER = 7,
-        KERN_NOT_IN_SET = 12
-    };
-
-    /// For nxm_task_init.
-    static const int NXM_TASK_INIT_VP = 2;     //!< initial thread is VP
-
-    /// Task attribute structure.
-    struct nxm_task_attr {
-        int64_t nxm_callback;  //!< nxm_callback
-        unsigned int nxm_version;      //!< nxm_version
-        unsigned short nxm_uniq_offset;        //!< nxm_uniq_offset
-        unsigned short flags;  //!< flags
-        int nxm_quantum;       //!< nxm_quantum
-        int pad1;              //!< pad1
-        int64_t pad2;          //!< pad2
-    };
-
-    /// Signal set.
-    typedef uint64_t   sigset_t;
-
-    /// Thread state shared between user & kernel.
-    struct ushared_state {
-        sigset_t        sigmask;        //!< thread signal mask
-        sigset_t        sig;            //!< thread pending mask
-        // struct nxm_pth_state *
-        Addr pth_id; //!< out-of-line state
-        int             flags;          //!< shared flags
-#define US_SIGSTACK     0x1             // thread called sigaltstack
-#define US_ONSTACK      0x2             // thread is running on altstack
-#define US_PROFILE      0x4             // thread called profil
-#define US_SYSCALL      0x8             // thread in syscall
-#define US_TRAP         0x10            // thread has trapped
-#define US_YELLOW       0x20            // thread has mellowed yellow
-#define US_YZONE        0x40            // thread has zoned out
-#define US_FP_OWNED     0x80            // thread used floating point
-
-        int             cancel_state;   //!< thread's cancelation state
-#define US_CANCEL         0x1           // cancel pending
-#define US_NOCANCEL       0X2           // synch cancel disabled
-#define US_SYS_NOCANCEL   0x4           // syscall cancel disabled
-#define US_ASYNC_NOCANCEL 0x8           // asynch cancel disabled
-#define US_CANCEL_BITS  (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
-#define US_CANCEL_MASK  (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
-                         US_ASYNC_NOCANCEL)
-
-        // These are semi-shared. They are always visible to
-        // the kernel but are never context-switched by the library.
-
-        int             nxm_ssig;       //!< scheduler's synchronous signals
-        int             reserved1;     //!< reserved1
-        int64_t            nxm_active;     //!< scheduler active
-        int64_t            reserved2;  //!< reserved2
-    };
-
-    struct nxm_sched_state {
-        struct          ushared_state nxm_u;    //!< state own by user thread
-        unsigned int    nxm_bits;               //!< scheduler state / slot
-        int             nxm_quantum;            //!< quantum count-down value
-        int             nxm_set_quantum;        //!< quantum reset value
-        int             nxm_sysevent;           //!< syscall state
-        // struct nxm_upcall *
-        Addr       nxm_uc_ret; //!< stack ptr of null thread
-        // void *
-        Addr nxm_tid;               //!< scheduler's thread id
-        int64_t            nxm_va;                 //!< page fault address
-        // struct nxm_pth_state *
-        Addr nxm_pthid; //!< id of null thread
-        uint64_t   nxm_bound_pcs_count;    //!< bound PCS thread count
-        int64_t            pad[2];        //!< pad
-    };
-
-    /// nxm_shared.
-    struct nxm_shared {
-        int64_t nxm_callback;              //!< address of upcall routine
-        unsigned int nxm_version;       //!< version number
-        unsigned short nxm_uniq_offset; //!< correction factor for TEB
-        unsigned short pad1;           //!< pad1
-        int64_t space[2];                  //!< future growth
-        struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
-    };
-
-    /// nxm_slot_state_t.
-    enum nxm_slot_state_t {
-        NXM_SLOT_AVAIL,
-        NXM_SLOT_BOUND,
-        NXM_SLOT_UNBOUND,
-        NXM_SLOT_EMPTY
-    };
-
-    /// nxm_config_info
-    struct nxm_config_info {
-        int nxm_nslots_per_rad;         //!< max number of VP slots per RAD
-        int nxm_nrads;                  //!< max number of RADs
-        // nxm_slot_state_t *
-        Addr nxm_slot_state; //!< per-VP slot state
-        // struct nxm_shared *
-        Addr nxm_rad[1];  //!< per-RAD shared areas
-    };
-
-    /// For nxm_thread_create.
-    enum nxm_thread_type {
-        NXM_TYPE_SCS   = 0,
-        NXM_TYPE_VP            = 1,
-        NXM_TYPE_MANAGER       = 2
-    };
-
-    /// Thread attributes.
-    struct nxm_thread_attr {
-        int version;   //!< version
-        int type;      //!< type
-        int cancel_flags;      //!< cancel_flags
-        int priority;  //!< priority
-        int policy;    //!< policy
-        int signal_type;       //!< signal_type
-        // void *
-        Addr pthid;    //!< pthid
-        sigset_t sigmask;      //!< sigmask
-        /// Initial register values.
-        struct {
-            uint64_t pc;       //!< pc
-            uint64_t sp;       //!< sp
-            uint64_t a0;       //!< a0
-        } registers;
-        uint64_t pad2[2];      //!< pad2
-    };
-
-    /// Helper function to convert a host stat buffer to a target stat
-    /// buffer.  Also copies the target buffer out to the simulated
-    /// memory space.  Used by stat(), fstat(), and lstat().
-    template <class T>
-    static void
-    copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host)
-    {
-        TypedBufferArg<T> tgt(addr);
-
-        tgt->st_dev = htog(host->st_dev);
-        tgt->st_ino = htog(host->st_ino);
-        tgt->st_mode = htog(host->st_mode);
-        tgt->st_nlink = htog(host->st_nlink);
-        tgt->st_uid = htog(host->st_uid);
-        tgt->st_gid = htog(host->st_gid);
-        tgt->st_rdev = htog(host->st_rdev);
-        tgt->st_size = htog(host->st_size);
-        tgt->st_atimeX = htog(host->st_atime);
-        tgt->st_mtimeX = htog(host->st_mtime);
-        tgt->st_ctimeX = htog(host->st_ctime);
-        tgt->st_blksize = htog(host->st_blksize);
-        tgt->st_blocks = htog(host->st_blocks);
-
-        tgt.copyOut(mem);
-    }
-
-    /// Helper function to convert a host statfs buffer to a target statfs
-    /// buffer.  Also copies the target buffer out to the simulated
-    /// memory space.  Used by statfs() and fstatfs().
-    template <class T>
-    static void
-    copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host)
-    {
-        TypedBufferArg<T> tgt(addr);
-
-#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
-        tgt->f_type = 0;
-#else
-        tgt->f_type = htog(host->f_type);
-#endif
-        tgt->f_bsize = htog(host->f_bsize);
-        tgt->f_blocks = htog(host->f_blocks);
-        tgt->f_bfree = htog(host->f_bfree);
-        tgt->f_bavail = htog(host->f_bavail);
-        tgt->f_files = htog(host->f_files);
-        tgt->f_ffree = htog(host->f_ffree);
-
-        // Is this as string normally?
-        memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
-
-        tgt.copyOut(mem);
-    }
-
-    class F64 {
-      public:
-        static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
-                                   global_stat *host)
-        {
-            Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
-        }
-
-        static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
-                                     global_statfs *host)
-        {
-            Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
-        }
-    };
-
-    class PreF64 {
-      public:
-        static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
-                                   global_stat *host)
-        {
-            Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
-        }
-
-        static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
-                                     global_statfs *host)
-        {
-            Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
-        }
-    };
-
-    /// Helper function to convert a host stat buffer to an old pre-F64
-    /// (4.x) target stat buffer.  Also copies the target buffer out to
-    /// the simulated memory space.  Used by pre_F64_stat(),
-    /// pre_F64_fstat(), and pre_F64_lstat().
-    static void
-    copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
-    {
-        TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
-
-        tgt->st_dev = htog(host->st_dev);
-        tgt->st_ino = htog(host->st_ino);
-        tgt->st_mode = htog(host->st_mode);
-        tgt->st_nlink = htog(host->st_nlink);
-        tgt->st_uid = htog(host->st_uid);
-        tgt->st_gid = htog(host->st_gid);
-        tgt->st_rdev = htog(host->st_rdev);
-        tgt->st_size = htog(host->st_size);
-        tgt->st_atimeX = htog(host->st_atime);
-        tgt->st_mtimeX = htog(host->st_mtime);
-        tgt->st_ctimeX = htog(host->st_ctime);
-        tgt->st_blksize = htog(host->st_blksize);
-        tgt->st_blocks = htog(host->st_blocks);
-
-        tgt.copyOut(mem);
-    }
-
-
-    /// The target system's hostname.
-    static const char *hostname;
-
-    /// Target uname() handler.
-    static SyscallReturn
-    unameFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-    {
-        TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
-
-        strcpy(name->sysname, "OSF1");
-        strcpy(name->nodename, hostname);
-        strcpy(name->release, "V5.1");
-        strcpy(name->version, "732");
-        strcpy(name->machine, "alpha");
-
-        name.copyOut(xc->mem);
-        return 0;
-    }
-
-
-    /// Target getsysyinfo() handler.
-    static SyscallReturn
-    getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
-                   ExecContext *xc)
-    {
-        unsigned op = xc->getSyscallArg(0);
-        unsigned nbytes = xc->getSyscallArg(2);
-
-        switch (op) {
-
-          case Tru64::GSI_MAX_CPU: {
-              TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
-              *max_cpu = htog((uint32_t)process->numCpus());
-              max_cpu.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_CPUS_IN_BOX: {
-              TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
-              *cpus_in_box = htog((uint32_t)process->numCpus());
-              cpus_in_box.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_PHYSMEM: {
-              TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
-              *physmem = htog((uint64_t)1024 * 1024);  // physical memory in KB
-              physmem.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_CPU_INFO: {
-              TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
-
-              infop->current_cpu = htog(0);
-              infop->cpus_in_box = htog(process->numCpus());
-              infop->cpu_type = htog(57);
-              infop->ncpus = htog(process->numCpus());
-              uint64_t cpumask = (1 << process->numCpus()) - 1;
-              infop->cpus_present = infop->cpus_running = htog(cpumask);
-              infop->cpu_binding = htog(0);
-              infop->cpu_ex_binding = htog(0);
-              infop->mhz = htog(667);
-
-              infop.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_PROC_TYPE: {
-              TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
-              *proc_type = htog((uint64_t)11);
-              proc_type.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_PLATFORM_NAME: {
-              BufferArg bufArg(xc->getSyscallArg(1), nbytes);
-              strncpy((char *)bufArg.bufferPtr(),
-                      "COMPAQ Professional Workstation XP1000",
-                      nbytes);
-              bufArg.copyOut(xc->mem);
-              return 1;
-          }
-
-          case Tru64::GSI_CLK_TCK: {
-              TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
-              *clk_hz = htog((uint64_t)1024);
-              clk_hz.copyOut(xc->mem);
-              return 1;
-          }
-
-          default:
-            warn("getsysinfo: unknown op %d\n", op);
-            break;
-        }
-
-        return 0;
-    }
-
-    /// Target setsysyinfo() handler.
-    static SyscallReturn
-    setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
-                   ExecContext *xc)
-    {
-        unsigned op = xc->getSyscallArg(0);
-
-        switch (op) {
-          case SSI_IEEE_FP_CONTROL:
-            warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
-                 xc->getSyscallArg(1));
-            break;
-
-          default:
-            warn("setsysinfo: unknown op %d\n", op);
-            break;
-        }
-
-        return 0;
-    }
-
-    /// Target fnctl() handler.
-    static SyscallReturn
-    fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-    {
-        int fd = xc->getSyscallArg(0);
-
-        if (fd < 0 || process->sim_fd(fd) < 0)
-            return -EBADF;
-
-        int cmd = xc->getSyscallArg(1);
-        switch (cmd) {
-          case 0: // F_DUPFD
-            // if we really wanted to support this, we'd need to do it
-            // in the target fd space.
-            warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
-            return -EMFILE;
-
-          case 1: // F_GETFD (get close-on-exec flag)
-          case 2: // F_SETFD (set close-on-exec flag)
-            return 0;
-
-          case 3: // F_GETFL (get file flags)
-          case 4: // F_SETFL (set file flags)
-            // not sure if this is totally valid, but we'll pass it through
-            // to the underlying OS
-            warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
-            return fcntl(process->sim_fd(fd), cmd);
-            // return 0;
-
-          case 7: // F_GETLK  (get lock)
-          case 8: // F_SETLK  (set lock)
-          case 9: // F_SETLKW (set lock and wait)
-            // don't mess with file locking... just act like it's OK
-            warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
-            return 0;
-
-          default:
-            warn("Unknown fcntl command %d\n", cmd);
-            return 0;
-        }
-    }
-
-
-    /// Target getdirentries() handler.
-    static SyscallReturn
-    getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
-                      ExecContext *xc)
-    {
-#ifdef __CYGWIN__
-        panic("getdirent not implemented on cygwin!");
-#else
-        int fd = process->sim_fd(xc->getSyscallArg(0));
-        Addr tgt_buf = xc->getSyscallArg(1);
-        int tgt_nbytes = xc->getSyscallArg(2);
-        Addr tgt_basep = xc->getSyscallArg(3);
-
-        char * const host_buf = new char[tgt_nbytes];
-
-        // just pass basep through uninterpreted.
-        TypedBufferArg<int64_t> basep(tgt_basep);
-        basep.copyIn(xc->mem);
-        long host_basep = (off_t)htog((int64_t)*basep);
-        int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
-
-        // check for error
-        if (host_result < 0) {
-            delete [] host_buf;
-            return -errno;
-        }
-
-        // no error: copy results back to target space
-        Addr tgt_buf_ptr = tgt_buf;
-        char *host_buf_ptr = host_buf;
-        char *host_buf_end = host_buf + host_result;
-        while (host_buf_ptr < host_buf_end) {
-            global_dirent *host_dp = (global_dirent *)host_buf_ptr;
-            int namelen = strlen(host_dp->d_name);
-
-            // Actual size includes padded string rounded up for alignment.
-            // Subtract 256 for dummy char array in Tru64::dirent definition.
-            // Add 1 to namelen for terminating null char.
-            int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
-            TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
-            tgt_dp->d_ino = host_dp->d_ino;
-            tgt_dp->d_reclen = tgt_bufsize;
-            tgt_dp->d_namlen = namelen;
-            strcpy(tgt_dp->d_name, host_dp->d_name);
-            tgt_dp.copyOut(xc->mem);
-
-            tgt_buf_ptr += tgt_bufsize;
-            host_buf_ptr += host_dp->d_reclen;
-        }
-
-        delete [] host_buf;
-
-        *basep = htog((int64_t)host_basep);
-        basep.copyOut(xc->mem);
-
-        return tgt_buf_ptr - tgt_buf;
-#endif
-    }
-
-    /// Target sigreturn() handler.
-    static SyscallReturn
-    sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-    {
-        RegFile *regs = &xc->regs;
-        TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
-
-        sc.copyIn(xc->mem);
-
-        // Restore state from sigcontext structure.
-        // Note that we'll advance PC <- NPC before the end of the cycle,
-        // so we need to restore the desired PC into NPC.
-        // The current regs->pc will get clobbered.
-        regs->npc = htog(sc->sc_pc);
-
-        for (int i = 0; i < 31; ++i) {
-            regs->intRegFile[i] = htog(sc->sc_regs[i]);
-            regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]);
-        }
-
-        regs->miscRegs.fpcr = htog(sc->sc_fpcr);
-
-        return 0;
-    }
-
-    /// Target table() handler.
-    static SyscallReturn
-    tableFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-    {
-        int id = xc->getSyscallArg(0);         // table ID
-        int index = xc->getSyscallArg(1);      // index into table
-        // arg 2 is buffer pointer; type depends on table ID
-        int nel = xc->getSyscallArg(3);                // number of elements
-        int lel = xc->getSyscallArg(4);                // expected element size
-
-        switch (id) {
-          case Tru64::TBL_SYSINFO: {
-              if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
-                  return -EINVAL;
-              TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
-
-              const int clk_hz = one_million;
-              elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
-              elp->si_nice = htog(0);
-              elp->si_sys = htog(0);
-              elp->si_idle = htog(0);
-              elp->wait = htog(0);
-              elp->si_hz = htog(clk_hz);
-              elp->si_phz = htog(clk_hz);
-              elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch?
-              elp->si_max_procs = htog(process->numCpus());
-              elp.copyOut(xc->mem);
-              return 0;
-          }
-
-          default:
-            cerr << "table(): id " << id << " unknown." << endl;
-            return -EINVAL;
-        }
-    }
-
-    /// Array of syscall descriptors, indexed by call number.
-    static SyscallDesc syscallDescs[];
-
-    /// Number of syscalls in syscallDescs[].
-    static const int Num_Syscall_Descs;
-
-    /// Max supported syscall number.
-    static const int Max_Syscall_Desc;
-
-    //
-    // Mach syscalls -- identified by negated syscall numbers
-    //
-
-    /// Create a stack region for a thread.
-    static SyscallReturn
-    stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
-                     ExecContext *xc)
-    {
-        TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
-
-        argp.copyIn(xc->mem);
-
-        // if the user chose an address, just let them have it.  Otherwise
-        // pick one for them.
-        if (htog(argp->address) == 0) {
-            argp->address = htog(process->next_thread_stack_base);
-            int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
-                    htog(argp->gsize));
-            process->next_thread_stack_base -= stack_size;
-            argp.copyOut(xc->mem);
-        }
-
-        return 0;
-    }
-
-    /// NXM library version stamp.
-    static
-    const int NXM_LIB_VERSION = 301003;
-
-    /// This call sets up the interface between the user and kernel
-    /// schedulers by creating a shared-memory region.  The shared memory
-    /// region has several structs, some global, some per-RAD, some per-VP.
-    static SyscallReturn
-    nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
-                      ExecContext *xc)
-    {
-        TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
-        TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
-
-        attrp.copyIn(xc->mem);
-
-        if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
-            cerr << "nxm_task_init: thread library version mismatch! "
-                 << "got " << attrp->nxm_version
-                 << ", expected " << NXM_LIB_VERSION << endl;
-            abort();
-        }
-
-        if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {
-            cerr << "nxm_task_init: bad flag value " << attrp->flags
-                 << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
-            abort();
-        }
-
-        const Addr base_addr = 0x12000; // was 0x3f0000000LL;
-        Addr cur_addr = base_addr; // next addresses to use
-        // first comes the config_info struct
-        Addr config_addr = cur_addr;
-        cur_addr += sizeof(Tru64::nxm_config_info);
-        // next comes the per-cpu state vector
-        Addr slot_state_addr = cur_addr;
-        int slot_state_size =
-            process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
-        cur_addr += slot_state_size;
-        // now the per-RAD state struct (we only support one RAD)
-        cur_addr = 0x14000;    // bump up addr for alignment
-        Addr rad_state_addr = cur_addr;
-        int rad_state_size =
-            (sizeof(Tru64::nxm_shared)
-             + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
-        cur_addr += rad_state_size;
-
-        // now initialize a config_info struct and copy it out to user space
-        TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
-
-        config->nxm_nslots_per_rad = htog(process->numCpus());
-        config->nxm_nrads = htog(1);   // only one RAD in our system!
-        config->nxm_slot_state = htog(slot_state_addr);
-        config->nxm_rad[0] = htog(rad_state_addr);
-
-        config.copyOut(xc->mem);
-
-        // initialize the slot_state array and copy it out
-        TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
-                                                           slot_state_size);
-        for (int i = 0; i < process->numCpus(); ++i) {
-            // CPU 0 is bound to the calling process; all others are available
-            // XXX this code should have an endian conversion, but I don't think
-            // it works anyway
-            slot_state[i] =
-                (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
-        }
-
-        slot_state.copyOut(xc->mem);
-
-        // same for the per-RAD "shared" struct.  Note that we need to
-        // allocate extra bytes for the per-VP array which is embedded at
-        // the end.
-        TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
-                                                    rad_state_size);
-
-        rad_state->nxm_callback = attrp->nxm_callback;
-        rad_state->nxm_version = attrp->nxm_version;
-        rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
-        for (int i = 0; i < process->numCpus(); ++i) {
-            Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
-            ssp->nxm_u.sigmask = htog(0);
-            ssp->nxm_u.sig = htog(0);
-            ssp->nxm_u.flags = htog(0);
-            ssp->nxm_u.cancel_state = htog(0);
-            ssp->nxm_u.nxm_ssig = 0;
-            ssp->nxm_bits = htog(0);
-            ssp->nxm_quantum = attrp->nxm_quantum;
-            ssp->nxm_set_quantum = attrp->nxm_quantum;
-            ssp->nxm_sysevent = htog(0);
-
-            if (i == 0) {
-                uint64_t uniq = xc->regs.miscRegs.uniq;
-                ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));
-                ssp->nxm_u.nxm_active = htog(uniq | 1);
-            }
-            else {
-                ssp->nxm_u.pth_id = htog(0);
-                ssp->nxm_u.nxm_active = htog(0);
-            }
-        }
-
-        rad_state.copyOut(xc->mem);
-
-        //
-        // copy pointer to shared config area out to user
-        //
-        *configptr_ptr = htog(config_addr);
-        configptr_ptr.copyOut(xc->mem);
-
-        // Register this as a valid address range with the process
-        process->nxm_start = base_addr;
-        process->nxm_end = cur_addr;
-
-        return 0;
-    }
-
-    /// Initialize execution context.
-    static void
-    init_exec_context(ExecContext *ec,
-                      Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
-    {
-        memset(&ec->regs, 0, sizeof(ec->regs));
-
-        ec->regs.intRegFile[ArgumentReg0] = gtoh(attrp->registers.a0);
-        ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc);
-        ec->regs.intRegFile[StackPointerReg] = gtoh(attrp->registers.sp);
-        ec->regs.miscRegs.uniq = uniq_val;
-
-        ec->regs.pc = gtoh(attrp->registers.pc);
-        ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(MachInst);
-
-        ec->activate();
-    }
-
-    /// Create thread.
-    static SyscallReturn
-    nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
-                          ExecContext *xc)
-    {
-        TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
-        TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
-        int thread_index = xc->getSyscallArg(2);
-
-        // get attribute args
-        attrp.copyIn(xc->mem);
-
-        if (gtoh(attrp->version) != NXM_LIB_VERSION) {
-            cerr << "nxm_thread_create: thread library version mismatch! "
-                 << "got " << attrp->version
-                 << ", expected " << NXM_LIB_VERSION << endl;
-            abort();
-        }
-
-        if (thread_index < 0 | thread_index > process->numCpus()) {
-            cerr << "nxm_thread_create: bad thread index " << thread_index
-                 << endl;
-            abort();
-        }
-
-        // On a real machine, the per-RAD shared structure is in
-        // shared memory, so both the user and kernel can get at it.
-        // We don't have that luxury, so we just copy it in and then
-        // back out again.
-        int rad_state_size =
-            (sizeof(Tru64::nxm_shared) +
-             (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
-
-        TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
-                                                    rad_state_size);
-        rad_state.copyIn(xc->mem);
-
-        uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
-
-        if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {
-            // DEC pthreads seems to always create one of these (in
-            // addition to N application threads), but we don't use it,
-            // so don't bother creating it.
-
-            // This is supposed to be a port number.  Make something up.
-            *kidp = htog(99);
-            kidp.copyOut(xc->mem);
-
-            return 0;
-        } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
-            // A real "virtual processor" kernel thread.  Need to fork
-            // this thread on another CPU.
-            Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
-
-            if (gtoh(ssp->nxm_u.nxm_active) != 0)
-                return (int) Tru64::KERN_NOT_RECEIVER;
-
-            ssp->nxm_u.pth_id = attrp->pthid;
-            ssp->nxm_u.nxm_active = htog(uniq_val | 1);
-
-            rad_state.copyOut(xc->mem);
-
-            Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
-            int slot_state_size =
-                process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
-
-            TypedBufferArg<Tru64::nxm_slot_state_t>
-                slot_state(slot_state_addr,
-                           slot_state_size);
-
-            slot_state.copyIn(xc->mem);
-
-            if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
-                cerr << "nxm_thread_createFunc: requested VP slot "
-                     << thread_index << " not available!" << endl;
-                fatal("");
-            }
-
-            // XXX This should have an endian conversion but I think this code
-            // doesn't work anyway
-            slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
-
-            slot_state.copyOut(xc->mem);
-
-            // Find a free simulator execution context.
-            for (int i = 0; i < process->numCpus(); ++i) {
-                ExecContext *xc = process->execContexts[i];
-
-                if (xc->status() == ExecContext::Unallocated) {
-                    // inactive context... grab it
-                    init_exec_context(xc, attrp, uniq_val);
-
-                    // This is supposed to be a port number, but we'll try
-                    // and get away with just sticking the thread index
-                    // here.
-                    *kidp = htog(thread_index);
-                    kidp.copyOut(xc->mem);
-
-                    return 0;
-                }
-            }
-
-            // fell out of loop... no available inactive context
-            cerr << "nxm_thread_create: no idle contexts available." << endl;
-            abort();
-        } else {
-            cerr << "nxm_thread_create: can't handle thread type "
-                 << attrp->type << endl;
-            abort();
-        }
-
-        return 0;
-    }
-
-    /// Thread idle call (like yield()).
-    static SyscallReturn
-    nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
-    {
-        return 0;
-    }
-
-    /// Block thread.
-    static SyscallReturn
-    nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
-                         ExecContext *xc)
-    {
-        uint64_t tid = xc->getSyscallArg(0);
-        uint64_t secs = xc->getSyscallArg(1);
-        uint64_t flags = xc->getSyscallArg(2);
-        uint64_t action = xc->getSyscallArg(3);
-        uint64_t usecs = xc->getSyscallArg(4);
-
-        cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
-             << " " << flags << " " << action << " " << usecs << endl;
-
-        return 0;
-    }
-
-    /// block.
-    static SyscallReturn
-    nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-    {
-        Addr uaddr = xc->getSyscallArg(0);
-        uint64_t val = xc->getSyscallArg(1);
-        uint64_t secs = xc->getSyscallArg(2);
-        uint64_t usecs = xc->getSyscallArg(3);
-        uint64_t flags = xc->getSyscallArg(4);
-
-        BaseCPU *cpu = xc->cpu;
-
-        cout << cpu->name() << ": nxm_block "
-             << hex << uaddr << dec << " " << val
-             << " " << secs << " " << usecs
-             << " " << flags << endl;
-
-        return 0;
-    }
-
-    /// Unblock thread.
-    static SyscallReturn
-    nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
-                    ExecContext *xc)
-    {
-        Addr uaddr = xc->getSyscallArg(0);
-
-        cout << xc->cpu->name() << ": nxm_unblock "
-             << hex << uaddr << dec << endl;
-
-        return 0;
-    }
-
-    /// Switch thread priority.
-    static SyscallReturn
-    swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-    {
-        // Attempts to switch to another runnable thread (if there is
-        // one).  Returns false if there are no other threads to run
-        // (i.e., the thread can reasonably spin-wait) or true if there
-        // are other threads.
-        //
-        // Since we assume at most one "kernel" thread per CPU, it's
-        // always safe to return false here.
-        return 0; //false;
-    }
-
-
-    /// Activate exec context waiting on a channel.  Just activate one
-    /// by default.
-    static int
-    activate_waiting_context(Addr uaddr, Process *process,
-                             bool activate_all = false)
-    {
-        int num_activated = 0;
-
-        list<Process::WaitRec>::iterator i = process->waitList.begin();
-        list<Process::WaitRec>::iterator end = process->waitList.end();
-
-        while (i != end && (num_activated == 0 || activate_all)) {
-            if (i->waitChan == uaddr) {
-                // found waiting process: make it active
-                ExecContext *newCtx = i->waitingContext;
-                assert(newCtx->status() == ExecContext::Suspended);
-                newCtx->activate();
-
-                // get rid of this record
-                i = process->waitList.erase(i);
-
-                ++num_activated;
-            } else {
-                ++i;
-            }
-        }
-
-        return num_activated;
-    }
-
-    /// M5 hacked-up lock acquire.
-    static void
-    m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
-    {
-        TypedBufferArg<uint64_t> lockp(uaddr);
-
-        lockp.copyIn(xc->mem);
-
-        if (gtoh(*lockp) == 0) {
-            // lock is free: grab it
-            *lockp = htog(1);
-            lockp.copyOut(xc->mem);
-        } else {
-            // lock is busy: disable until free
-            process->waitList.push_back(Process::WaitRec(uaddr, xc));
-            xc->suspend();
-        }
-    }
-
-    /// M5 unlock call.
-    static void
-    m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
-    {
-        TypedBufferArg<uint64_t> lockp(uaddr);
-
-        lockp.copyIn(xc->mem);
-        assert(*lockp != 0);
-
-        // Check for a process waiting on the lock.
-        int num_waiting = activate_waiting_context(uaddr, process);
-
-        // clear lock field if no waiting context is taking over the lock
-        if (num_waiting == 0) {
-            *lockp = 0;
-            lockp.copyOut(xc->mem);
-        }
-    }
-
-    /// Lock acquire syscall handler.
-    static SyscallReturn
-    m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
-                      ExecContext *xc)
-    {
-        Addr uaddr = xc->getSyscallArg(0);
-
-        m5_lock_mutex(uaddr, process, xc);
-
-        // Return 0 since we will always return to the user with the lock
-        // acquired.  We will just keep the context inactive until that is
-        // true.
-        return 0;
-    }
-
-    /// Try lock (non-blocking).
-    static SyscallReturn
-    m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
-                         ExecContext *xc)
-    {
-        Addr uaddr = xc->getSyscallArg(0);
-        TypedBufferArg<uint64_t> lockp(uaddr);
-
-        lockp.copyIn(xc->mem);
-
-        if (gtoh(*lockp) == 0) {
-            // lock is free: grab it
-            *lockp = htog(1);
-            lockp.copyOut(xc->mem);
-            return 0;
-        } else {
-            return 1;
-        }
-    }
-
-    /// Unlock syscall handler.
-    static SyscallReturn
-    m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
-                        ExecContext *xc)
-    {
-        Addr uaddr = xc->getSyscallArg(0);
-
-        m5_unlock_mutex(uaddr, process, xc);
-
-        return 0;
-    }
-
-    /// Signal ocndition.
-    static SyscallReturn
-    m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
-                       ExecContext *xc)
-    {
-        Addr cond_addr = xc->getSyscallArg(0);
-
-        // Wake up one process waiting on the condition variable.
-        activate_waiting_context(cond_addr, process);
-
-        return 0;
-    }
-
-    /// Wake up all processes waiting on the condition variable.
-    static SyscallReturn
-    m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
-                          ExecContext *xc)
-    {
-        Addr cond_addr = xc->getSyscallArg(0);
-
-        activate_waiting_context(cond_addr, process, true);
-
-        return 0;
-    }
-
-    /// Wait on a condition.
-    static SyscallReturn
-    m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
-                     ExecContext *xc)
-    {
-        Addr cond_addr = xc->getSyscallArg(0);
-        Addr lock_addr = xc->getSyscallArg(1);
-        TypedBufferArg<uint64_t> condp(cond_addr);
-        TypedBufferArg<uint64_t> lockp(lock_addr);
-
-        // user is supposed to acquire lock before entering
-        lockp.copyIn(xc->mem);
-        assert(gtoh(*lockp) != 0);
-
-        m5_unlock_mutex(lock_addr, process, xc);
-
-        process->waitList.push_back(Process::WaitRec(cond_addr, xc));
-        xc->suspend();
-
-        return 0;
-    }
-
-    /// Thread exit.
-    static SyscallReturn
-    m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
-                       ExecContext *xc)
-    {
-        assert(xc->status() == ExecContext::Active);
-        xc->deallocate();
-
-        return 0;
-    }
-
-    /// Array of syscall descriptors for Mach syscalls, indexed by
-    /// (negated) call number.
-    static SyscallDesc machSyscallDescs[];
-
-    /// Number of syscalls in machSyscallDescs[].
-    static const int Num_Mach_Syscall_Descs;
-
-    /// Max supported Mach syscall number.
-    static const int Max_Mach_Syscall_Desc;
-
-    /// Since negated values are used to identify Mach syscalls, the
-    /// minimum (signed) valid syscall number is the negated max Mach
-    /// syscall number.
-    static const int Min_Syscall_Desc;
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
 
-    /// Do the specified syscall.  Just looks the call number up in
-    /// the table and invokes the appropriate handler.
-    static void
-    doSyscall(int callnum, Process *process, ExecContext *xc)
-    {
-        if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) {
-            fatal("Syscall %d out of range\n", callnum);
-        }
+    strcpy(name->sysname, "OSF1");
+    strcpy(name->nodename, "m5.eecs.umich.edu");
+    strcpy(name->release, "V5.1");
+    strcpy(name->version, "732");
+    strcpy(name->machine, "alpha");
 
-        SyscallDesc *desc =
-            (callnum < 0) ?
-            &machSyscallDescs[-callnum] : &syscallDescs[callnum];
+    name.copyOut(xc->mem);
+    return 0;
+}
 
-        desc->doSyscall(callnum, process, xc);
+/// Target getsysyinfo() handler.
+static SyscallReturn
+getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+               ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case Tru64::GSI_MAX_CPU: {
+          TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
+          *max_cpu = htog((uint32_t)process->numCpus());
+          max_cpu.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CPUS_IN_BOX: {
+          TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
+          *cpus_in_box = htog((uint32_t)process->numCpus());
+          cpus_in_box.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_PHYSMEM: {
+          TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
+          *physmem = htog((uint64_t)1024 * 1024);      // physical memory in KB
+          physmem.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CPU_INFO: {
+          TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
+
+          infop->current_cpu = htog(0);
+          infop->cpus_in_box = htog(process->numCpus());
+          infop->cpu_type = htog(57);
+          infop->ncpus = htog(process->numCpus());
+          uint64_t cpumask = (1 << process->numCpus()) - 1;
+          infop->cpus_present = infop->cpus_running = htog(cpumask);
+          infop->cpu_binding = htog(0);
+          infop->cpu_ex_binding = htog(0);
+          infop->mhz = htog(667);
+
+          infop.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_PROC_TYPE: {
+          TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
+          *proc_type = htog((uint64_t)11);
+          proc_type.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_PLATFORM_NAME: {
+          BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+          strncpy((char *)bufArg.bufferPtr(),
+                  "COMPAQ Professional Workstation XP1000",
+                  nbytes);
+          bufArg.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CLK_TCK: {
+          TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
+          *clk_hz = htog((uint64_t)1024);
+          clk_hz.copyOut(xc->mem);
+          return 1;
+      }
+
+      default:
+        warn("getsysinfo: unknown op %d\n", op);
+        break;
     }
 
-    /// Indirect syscall invocation (call #0).
-    static SyscallReturn
-    indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
-                        ExecContext *xc)
-    {
-        int new_callnum = xc->getSyscallArg(0);
+    return 0;
+}
 
-        for (int i = 0; i < 5; ++i)
-            xc->setSyscallArg(i, xc->getSyscallArg(i+1));
+/// Target setsysyinfo() handler.
+static SyscallReturn
+setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+               ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
 
-        doSyscall(new_callnum, process, xc);
+    switch (op) {
+      case Tru64::SSI_IEEE_FP_CONTROL:
+        warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
+             xc->getSyscallArg(1));
+        break;
 
-        return 0;
+      default:
+        warn("setsysinfo: unknown op %d\n", op);
+        break;
     }
 
-};  // class Tru64
-
-
-// open(2) flags translation table
-OpenFlagTransTable Tru64::openFlagTable[] = {
-#ifdef _MSC_VER
-  { Tru64::TGT_O_RDONLY,       _O_RDONLY },
-  { Tru64::TGT_O_WRONLY,       _O_WRONLY },
-  { Tru64::TGT_O_RDWR,         _O_RDWR },
-  { Tru64::TGT_O_APPEND,       _O_APPEND },
-  { Tru64::TGT_O_CREAT,                _O_CREAT },
-  { Tru64::TGT_O_TRUNC,                        _O_TRUNC },
-  { Tru64::TGT_O_EXCL,                 _O_EXCL },
-#ifdef _O_NONBLOCK
-  { Tru64::TGT_O_NONBLOCK,     _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
-  { Tru64::TGT_O_NOCTTY,       _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
-  { Tru64::TGT_O_SYNC, _O_SYNC },
-#endif
-#else /* !_MSC_VER */
-  { Tru64::TGT_O_RDONLY,       O_RDONLY },
-  { Tru64::TGT_O_WRONLY,       O_WRONLY },
-  { Tru64::TGT_O_RDWR,         O_RDWR },
-  { Tru64::TGT_O_APPEND,       O_APPEND },
-  { Tru64::TGT_O_CREAT,                O_CREAT },
-  { Tru64::TGT_O_TRUNC,                O_TRUNC },
-  { Tru64::TGT_O_EXCL,         O_EXCL },
-  { Tru64::TGT_O_NONBLOCK,     O_NONBLOCK },
-  { Tru64::TGT_O_NOCTTY,       O_NOCTTY },
-#ifdef O_SYNC
-  { Tru64::TGT_O_SYNC,         O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-
-const int Tru64::NUM_OPEN_FLAGS = (sizeof(Tru64::openFlagTable)/sizeof(Tru64::openFlagTable[0]));
+    return 0;
+}
 
-const char *Tru64::hostname = "m5.eecs.umich.edu";
 
-SyscallDesc Tru64::syscallDescs[] = {
-    /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc,
+SyscallDesc AlphaTru64Process::syscallDescs[] = {
+    /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc,
                         SyscallDesc::SuppressReturnValue),
     /* 1 */ SyscallDesc("exit", exitFunc),
     /* 2 */ SyscallDesc("fork", unimplementedFunc),
@@ -1637,7 +243,7 @@ SyscallDesc Tru64::syscallDescs[] = {
     /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
     /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
     /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
-    /* 85 */ SyscallDesc("table", tableFunc),
+    /* 85 */ SyscallDesc("table", Tru64::tableFunc),
     /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
     /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
     /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
@@ -1655,7 +261,7 @@ SyscallDesc Tru64::syscallDescs[] = {
     /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
     /* 101 */ SyscallDesc("old_send", unimplementedFunc),
     /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
-    /* 103 */ SyscallDesc("sigreturn", sigreturnFunc,
+    /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc,
                           SyscallDesc::SuppressReturnValue),
     /* 104 */ SyscallDesc("bind", unimplementedFunc),
     /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
@@ -1712,7 +318,7 @@ SyscallDesc Tru64::syscallDescs[] = {
     /* 156 */ SyscallDesc("sigaction", ignoreFunc),
     /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
     /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
-    /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc),
+    /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc),
     /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
     /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
     /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
@@ -1822,20 +428,17 @@ SyscallDesc Tru64::syscallDescs[] = {
     /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
 };
 
-const int Tru64::Num_Syscall_Descs =
-        sizeof(Tru64::syscallDescs) / sizeof(SyscallDesc);
 
-const int Tru64::Max_Syscall_Desc = Tru64::Num_Syscall_Descs - 1;
 
-SyscallDesc Tru64::machSyscallDescs[] = {
+SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
     /* 0 */  SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 1 */  SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc),
-    /* 2 */  SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc),
-    /* 3 */  SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc),
-    /* 4 */  SyscallDesc("m5_cond_signal", m5_cond_signalFunc),
-    /* 5 */  SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc),
-    /* 6 */  SyscallDesc("m5_cond_wait", m5_cond_waitFunc),
-    /* 7 */  SyscallDesc("m5_thread_exit", m5_thread_exitFunc),
+    /* 1 */  SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc),
+    /* 2 */  SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc),
+    /* 3 */  SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc),
+    /* 4 */  SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc),
+    /* 5 */  SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc),
+    /* 6 */  SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc),
+    /* 7 */  SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc),
     /* 8 */  SyscallDesc("kern_invalid", unimplementedFunc),
     /* 9 */  SyscallDesc("kern_invalid", unimplementedFunc),
     /* 10 */ SyscallDesc("task_self", unimplementedFunc),
@@ -1852,22 +455,22 @@ SyscallDesc Tru64::machSyscallDescs[] = {
     /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
     /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
     /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc),
-    /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc),
+    /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc),
+    /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc),
     /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
     /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
     /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
     /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
     /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
     /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
-    /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc),
-    /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc),
+    /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc),
+    /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc),
     /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc),
+    /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc),
     /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
     /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
     /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
-    /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc),
+    /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc),
     /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
     /* 41 */ SyscallDesc("init_process", unimplementedFunc),
     /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
@@ -1875,7 +478,7 @@ SyscallDesc Tru64::machSyscallDescs[] = {
     /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
     /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
     /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
-    /* 47 */ SyscallDesc("stack_create", stack_createFunc),
+    /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc),
     /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
     /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
     /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
@@ -1887,7 +490,7 @@ SyscallDesc Tru64::machSyscallDescs[] = {
     /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
     /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
     /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc),
+    /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc),
     /* 60 */ SyscallDesc("swtch", unimplementedFunc),
     /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
     /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
@@ -1895,7 +498,7 @@ SyscallDesc Tru64::machSyscallDescs[] = {
     /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
     /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
     /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
-    /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc),
+    /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc),
     /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
     /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
     /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
@@ -1913,20 +516,16 @@ SyscallDesc Tru64::machSyscallDescs[] = {
     /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
 };
 
-const int Tru64::Num_Mach_Syscall_Descs =
-                sizeof(Tru64::machSyscallDescs) / sizeof(SyscallDesc);
-const int Tru64::Max_Mach_Syscall_Desc = Tru64::Num_Mach_Syscall_Descs - 1;
-const int Tru64::Min_Syscall_Desc = -Tru64::Max_Mach_Syscall_Desc;
-
-
-void
-AlphaTru64Process::syscall(ExecContext *xc)
+SyscallDesc*
+AlphaTru64Process::getDesc(int callnum)
 {
-    num_syscalls++;
-
-    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
+    if (callnum < Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs)
+        return NULL;
 
-    Tru64::doSyscall(callnum, this, xc);
+    if (callnum < 0)
+        return &machSyscallDescs[-callnum];
+    else
+        return &syscallDescs[callnum];
 }
 
 
@@ -1937,6 +536,8 @@ AlphaTru64Process::AlphaTru64Process(const std::string &name,
                                      int stderr_fd,
                                      std::vector<std::string> &argv,
                                      std::vector<std::string> &envp)
-    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp)
+    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+      Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
+      Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc))
 {
 }
index 49979806ca5c9b1479b5441ff64a51eaaffef66a..05176070202fa1dc38b92687b19edc8158c2fecc 100644 (file)
@@ -42,8 +42,16 @@ class AlphaTru64Process : public LiveProcess
                       std::vector<std::string> &argv,
                       std::vector<std::string> &envp);
 
-    /// Syscall emulation function.
-    virtual void syscall(ExecContext *xc);
+    /// Array of syscall descriptors, indexed by call number.
+    static SyscallDesc syscallDescs[];
+
+    /// Array of mach syscall descriptors, indexed by call number.
+    static SyscallDesc machSyscallDescs[];
+
+    const int Num_Syscall_Descs;
+    const int Num_Mach_Syscall_Descs;
+
+    virtual SyscallDesc* getDesc(int callnum);
 };
 
 
index b083b5a31eca93642cc17c0c9909ca7b3e933297..0dbccf546431c0d5cb2927cd3fed7531b2ceaf83 100644 (file)
 
 #ifndef __LINUX_HH__
 #define __LINUX_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
 
 class Linux {};
 
+#else //!FULL_SYSTEM
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>     // for host open() flags
+#include <string.h>    // for memset()
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sim/syscall_emul.hh"
+
+///
+/// This class encapsulates the types, structures, constants,
+/// functions, and syscall-number mappings specific to the Alpha Linux
+/// syscall interface.
+///
+class Linux {
+
+  public:
+
+    //@{
+    /// Basic Linux types.
+    typedef uint64_t size_t;
+    typedef uint64_t off_t;
+    typedef int64_t time_t;
+    typedef uint32_t uid_t;
+    typedef uint32_t gid_t;
+    //@}
+
+#if BSD_HOST
+    typedef struct stat hst_stat;
+    typedef struct stat hst_stat64;
+#else
+    typedef struct stat hst_stat ;
+    typedef struct stat64 hst_stat64;
+#endif
+
+
+    //@{
+    /// open(2) flag values.
+    static const int TGT_O_RDONLY      = 00000000;     //!< O_RDONLY
+    static const int TGT_O_WRONLY      = 00000001;     //!< O_WRONLY
+    static const int TGT_O_RDWR                = 00000002;     //!< O_RDWR
+    static const int TGT_O_NONBLOCK    = 00000004;     //!< O_NONBLOCK
+    static const int TGT_O_APPEND      = 00000010;     //!< O_APPEND
+    static const int TGT_O_CREAT       = 00001000;     //!< O_CREAT
+    static const int TGT_O_TRUNC       = 00002000;     //!< O_TRUNC
+    static const int TGT_O_EXCL                = 00004000;     //!< O_EXCL
+    static const int TGT_O_NOCTTY      = 00010000;     //!< O_NOCTTY
+    static const int TGT_O_SYNC                = 00040000;     //!< O_SYNC
+    static const int TGT_O_DRD         = 00100000;     //!< O_DRD
+    static const int TGT_O_DIRECTIO    = 00200000;     //!< O_DIRECTIO
+    static const int TGT_O_CACHE       = 00400000;     //!< O_CACHE
+    static const int TGT_O_DSYNC       = 02000000;     //!< O_DSYNC
+    static const int TGT_O_RSYNC       = 04000000;     //!< O_RSYNC
+    //@}
+
+    /// This table maps the target open() flags to the corresponding
+    /// host open() flags.
+    static OpenFlagTransTable openFlagTable[];
+
+    /// Number of entries in openFlagTable[].
+    static const int NUM_OPEN_FLAGS;
+
+    /// Stat buffer.  Note that we can't call it 'stat' since that
+    /// gets #defined to something else on some systems.
+    struct tgt_stat {
+        uint32_t       st_dev;         //!< device
+        uint32_t       st_ino;         //!< inode
+        uint32_t       st_mode;        //!< mode
+        uint32_t       st_nlink;       //!< link count
+        uint32_t       st_uid;         //!< owner's user ID
+        uint32_t       st_gid;         //!< owner's group ID
+        uint32_t       st_rdev;        //!< device number
+        int32_t                _pad1;          //!< for alignment
+        int64_t                st_size;        //!< file size in bytes
+        uint64_t       st_atimeX;      //!< time of last access
+        uint64_t       st_mtimeX;      //!< time of last modification
+        uint64_t       st_ctimeX;      //!< time of last status change
+        uint32_t       st_blksize;     //!< optimal I/O block size
+        int32_t                st_blocks;      //!< number of blocks allocated
+        uint32_t       st_flags;       //!< flags
+        uint32_t       st_gen;         //!< unknown
+    };
+
+    // same for stat64
+    struct tgt_stat64 {
+        uint64_t       st_dev;
+        uint64_t       st_ino;
+        uint64_t       st_rdev;
+        int64_t                st_size;
+        uint64_t       st_blocks;
+
+        uint32_t       st_mode;
+        uint32_t       st_uid;
+        uint32_t       st_gid;
+        uint32_t       st_blksize;
+        uint32_t       st_nlink;
+        uint32_t       __pad0;
+
+        uint64_t       tgt_st_atime;
+        uint64_t       st_atime_nsec;
+        uint64_t       tgt_st_mtime;
+        uint64_t       st_mtime_nsec;
+        uint64_t       tgt_st_ctime;
+        uint64_t       st_ctime_nsec;
+        int64_t                ___unused[3];
+    };
+
+    /// Length of strings in struct utsname (plus 1 for null char).
+    static const int _SYS_NMLN = 65;
+
+    /// Interface struct for uname().
+    struct utsname {
+        char sysname[_SYS_NMLN];       //!< System name.
+        char nodename[_SYS_NMLN];      //!< Node name.
+        char release[_SYS_NMLN];       //!< OS release.
+        char version[_SYS_NMLN];       //!< OS version.
+        char machine[_SYS_NMLN];       //!< Machine type.
+    };
+
+
+    //@{
+    /// ioctl() command codes.
+    static const unsigned TIOCGETP   = 0x40067408;
+    static const unsigned TIOCSETP   = 0x80067409;
+    static const unsigned TIOCSETN   = 0x8006740a;
+    static const unsigned TIOCSETC   = 0x80067411;
+    static const unsigned TIOCGETC   = 0x40067412;
+    static const unsigned FIONREAD   = 0x4004667f;
+    static const unsigned TIOCISATTY = 0x2000745e;
+    static const unsigned TIOCGETS   = 0x402c7413;
+    static const unsigned TIOCGETA   = 0x40127417;
+    //@}
+
+    /// Resource enumeration for getrlimit().
+    enum rlimit_resources {
+        TGT_RLIMIT_CPU = 0,
+        TGT_RLIMIT_FSIZE = 1,
+        TGT_RLIMIT_DATA = 2,
+        TGT_RLIMIT_STACK = 3,
+        TGT_RLIMIT_CORE = 4,
+        TGT_RLIMIT_RSS = 5,
+        TGT_RLIMIT_NOFILE = 6,
+        TGT_RLIMIT_AS = 7,
+        TGT_RLIMIT_VMEM = 7,
+        TGT_RLIMIT_NPROC = 8,
+        TGT_RLIMIT_MEMLOCK = 9,
+        TGT_RLIMIT_LOCKS = 10
+    };
+
+    /// Limit struct for getrlimit/setrlimit.
+    struct rlimit {
+        uint64_t  rlim_cur;    //!< soft limit
+        uint64_t  rlim_max;    //!< hard limit
+    };
+
+
+    /// For mmap().
+    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+    /// For gettimeofday().
+    struct timeval {
+        int64_t tv_sec;                //!< seconds
+        int64_t tv_usec;       //!< microseconds
+    };
+
+    // For writev/readv
+    struct tgt_iovec {
+        uint64_t iov_base; // void *
+        uint64_t iov_len;
+    };
+
+    //@{
+    /// For getrusage().
+    static const int TGT_RUSAGE_SELF = 0;
+    static const int TGT_RUSAGE_CHILDREN = -1;
+    static const int TGT_RUSAGE_BOTH = -2;
+    //@}
+
+    /// For getrusage().
+    struct rusage {
+        struct timeval ru_utime;       //!< user time used
+        struct timeval ru_stime;       //!< system time used
+        int64_t ru_maxrss;             //!< max rss
+        int64_t ru_ixrss;              //!< integral shared memory size
+        int64_t ru_idrss;              //!< integral unshared data "
+        int64_t ru_isrss;              //!< integral unshared stack "
+        int64_t ru_minflt;             //!< page reclaims - total vmfaults
+        int64_t ru_majflt;             //!< page faults
+        int64_t ru_nswap;              //!< swaps
+        int64_t ru_inblock;            //!< block input operations
+        int64_t ru_oublock;            //!< block output operations
+        int64_t ru_msgsnd;             //!< messages sent
+        int64_t ru_msgrcv;             //!< messages received
+        int64_t ru_nsignals;           //!< signals received
+        int64_t ru_nvcsw;              //!< voluntary context switches
+        int64_t ru_nivcsw;             //!< involuntary "
+    };
+
+    /// Helper function to convert a host stat buffer to a target stat
+    /// buffer.  Also copies the target buffer out to the simulated
+    /// memory space.  Used by stat(), fstat(), and lstat().
+#if !BSD_HOST
+    static void
+    copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
+    {
+        TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+        tgt->st_dev = htog(host->st_dev);
+        tgt->st_ino = htog(host->st_ino);
+        tgt->st_mode = htog(host->st_mode);
+        tgt->st_nlink = htog(host->st_nlink);
+        tgt->st_uid = htog(host->st_uid);
+        tgt->st_gid = htog(host->st_gid);
+        tgt->st_rdev = htog(host->st_rdev);
+        tgt->st_size = htog(host->st_size);
+        tgt->st_atimeX = htog(host->st_atime);
+        tgt->st_mtimeX = htog(host->st_mtime);
+        tgt->st_ctimeX = htog(host->st_ctime);
+        tgt->st_blksize = htog(host->st_blksize);
+        tgt->st_blocks = htog(host->st_blocks);
+
+        tgt.copyOut(mem);
+    }
+#else
+    // Third version for bsd systems which no longer have any support for
+    // the old stat() call and stat() is actually a stat64()
+    static void
+    copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
+    {
+        TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+        tgt->st_dev = htog(host->st_dev);
+        tgt->st_ino = htog(host->st_ino);
+        tgt->st_mode = htog(host->st_mode);
+        tgt->st_nlink = htog(host->st_nlink);
+        tgt->st_uid = htog(host->st_uid);
+        tgt->st_gid = htog(host->st_gid);
+        tgt->st_rdev = htog(host->st_rdev);
+        tgt->st_size = htog(host->st_size);
+        tgt->st_atimeX = htog(host->st_atime);
+        tgt->st_mtimeX = htog(host->st_mtime);
+        tgt->st_ctimeX = htog(host->st_ctime);
+        tgt->st_blksize = htog(host->st_blksize);
+        tgt->st_blocks = htog(host->st_blocks);
+
+        tgt.copyOut(mem);
+    }
+#endif
+
+
+    // Same for stat64
+    static void
+    copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
+    {
+        TypedBufferArg<Linux::tgt_stat64> tgt(addr);
+
+        // fd == 1 checks are because libc does some checks
+        // that the stdout is interactive vs. a file
+        // this makes it work on non-linux systems
+        if (fd == 1)
+            tgt->st_dev = htog((uint64_t)0xA);
+        else
+            tgt->st_dev = htog((uint64_t)host->st_dev);
+        // XXX What about STAT64_HAS_BROKEN_ST_INO ???
+        tgt->st_ino = htog((uint64_t)host->st_ino);
+        if (fd == 1)
+            tgt->st_rdev = htog((uint64_t)0x880d);
+        else
+            tgt->st_rdev = htog((uint64_t)host->st_rdev);
+        tgt->st_size = htog((int64_t)host->st_size);
+        tgt->st_blocks = htog((uint64_t)host->st_blocks);
+
+        if (fd == 1)
+            tgt->st_mode = htog((uint32_t)0x2190);
+        else
+            tgt->st_mode = htog((uint32_t)host->st_mode);
+        tgt->st_uid = htog((uint32_t)host->st_uid);
+        tgt->st_gid = htog((uint32_t)host->st_gid);
+        tgt->st_blksize = htog((uint32_t)host->st_blksize);
+        tgt->st_nlink = htog((uint32_t)host->st_nlink);
+        tgt->tgt_st_atime = htog((uint64_t)host->st_atime);
+        tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime);
+        tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+        tgt->st_atime_nsec = htog(host->st_atime_nsec);
+        tgt->st_mtime_nsec = htog(host->st_mtime_nsec);
+        tgt->st_ctime_nsec = htog(host->st_ctime_nsec);
+#else
+        tgt->st_atime_nsec = 0;
+        tgt->st_mtime_nsec = 0;
+        tgt->st_ctime_nsec = 0;
+#endif
+
+        tgt.copyOut(mem);
+    }
+
+};  // class Linux
+
+
+#endif // FULL_SYSTEM
+
 #endif // __LINUX_HH__
index 07c0d21a7f61442c0c124f59101cf29050a09606..f3dabb0f86e6efae357f9b1c22ce69df6e5c0f44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2005 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
 
 #ifndef __TRU64_HH__
 #define __TRU64_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
 
 class Tru64 {};
 
+#else //!FULL_SYSTEM
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>    // for memset()
+#include <unistd.h>
+
+#include "cpu/base.hh"
+#include "sim/root.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+
+typedef struct stat global_stat;
+typedef struct statfs global_statfs;
+typedef struct dirent global_dirent;
+
+///
+/// This class encapsulates the types, structures, constants,
+/// functions, and syscall-number mappings specific to the Alpha Tru64
+/// syscall interface.
+///
+class Tru64 {
+
+  public:
+
+    //@{
+    /// Basic Tru64 types.
+    typedef uint64_t size_t;
+    typedef uint64_t off_t;
+    typedef uint16_t nlink_t;
+    typedef int32_t  dev_t;
+    typedef uint32_t uid_t;
+    typedef uint32_t gid_t;
+    typedef uint32_t time_t;
+    typedef uint32_t mode_t;
+    typedef uint32_t ino_t;
+    typedef struct { int val[2]; } quad;
+    typedef quad fsid_t;
+    //@}
+
+    //@{
+    /// open(2) flag values.
+    static const int TGT_O_RDONLY      = 00000000;
+    static const int TGT_O_WRONLY      = 00000001;
+    static const int TGT_O_RDWR                = 00000002;
+    static const int TGT_O_NONBLOCK    = 00000004;
+    static const int TGT_O_APPEND      = 00000010;
+    static const int TGT_O_CREAT       = 00001000;
+    static const int TGT_O_TRUNC       = 00002000;
+    static const int TGT_O_EXCL                = 00004000;
+    static const int TGT_O_NOCTTY      = 00010000;
+    static const int TGT_O_SYNC                = 00040000;
+    static const int TGT_O_DRD         = 00100000;
+    static const int TGT_O_DIRECTIO    = 00200000;
+    static const int TGT_O_CACHE       = 00400000;
+    static const int TGT_O_DSYNC       = 02000000;
+    static const int TGT_O_RSYNC       = 04000000;
+    //@}
+
+    /// This table maps the target open() flags to the corresponding
+    /// host open() flags.
+    static OpenFlagTransTable openFlagTable[];
+
+    /// Number of entries in openFlagTable[].
+    static const int NUM_OPEN_FLAGS;
+
+    /// Stat buffer.  Note that Tru64 v5.0+ use a new "F64" stat
+    /// structure, and a new set of syscall numbers for stat calls.
+    /// On some hosts (notably Linux) define st_atime, st_mtime, and
+    /// st_ctime as macros, so we append an X to get around this.
+    struct F64_stat {
+        dev_t  st_dev;                 //!< st_dev
+        int32_t        st_retired1;            //!< st_retired1
+        mode_t st_mode;                //!< st_mode
+        nlink_t        st_nlink;               //!< st_nlink
+        uint16_t st_nlink_reserved;    //!< st_nlink_reserved
+        uid_t  st_uid;                 //!< st_uid
+        gid_t  st_gid;                 //!< st_gid
+        dev_t  st_rdev;                //!< st_rdev
+        dev_t  st_ldev;                //!< st_ldev
+        off_t  st_size;                //!< st_size
+        time_t st_retired2;            //!< st_retired2
+        int32_t        st_uatime;              //!< st_uatime
+        time_t st_retired3;            //!< st_retired3
+        int32_t        st_umtime;              //!< st_umtime
+        time_t st_retired4;            //!< st_retired4
+        int32_t        st_uctime;              //!< st_uctime
+        int32_t        st_retired5;            //!< st_retired5
+        int32_t        st_retired6;            //!< st_retired6
+        uint32_t       st_flags;       //!< st_flags
+        uint32_t       st_gen;         //!< st_gen
+        uint64_t       st_spare[4];    //!< st_spare[4]
+        ino_t  st_ino;                 //!< st_ino
+        int32_t        st_ino_reserved;        //!< st_ino_reserved
+        time_t st_atimeX;              //!< st_atime
+        int32_t        st_atime_reserved;      //!< st_atime_reserved
+        time_t st_mtimeX;              //!< st_mtime
+        int32_t        st_mtime_reserved;      //!< st_mtime_reserved
+        time_t st_ctimeX;              //!< st_ctime
+        int32_t        st_ctime_reserved;      //!< st_ctime_reserved
+        uint64_t       st_blksize;     //!< st_blksize
+        uint64_t       st_blocks;      //!< st_blocks
+    };
+
+
+    /// Old Tru64 v4.x stat struct.
+    /// Tru64 maintains backwards compatibility with v4.x by
+    /// implementing another set of stat functions using the old
+    /// structure definition and binding them to the old syscall
+    /// numbers.
+    struct pre_F64_stat {
+        dev_t   st_dev;
+        ino_t   st_ino;
+        mode_t  st_mode;
+        nlink_t st_nlink;
+        uid_t   st_uid;
+        gid_t   st_gid;
+        dev_t   st_rdev;
+        off_t   st_size;
+        time_t  st_atimeX;
+        int32_t st_uatime;
+        time_t  st_mtimeX;
+        int32_t st_umtime;
+        time_t  st_ctimeX;
+        int32_t st_uctime;
+        uint32_t st_blksize;
+        int32_t st_blocks;
+        uint32_t st_flags;
+        uint32_t st_gen;
+    };
+
+    /// For statfs().
+    struct F64_statfs {
+        int16_t   f_type;
+        int16_t   f_flags;
+        int32_t     f_retired1;
+        int32_t     f_retired2;
+        int32_t     f_retired3;
+        int32_t     f_retired4;
+        int32_t     f_retired5;
+        int32_t     f_retired6;
+        int32_t     f_retired7;
+        fsid_t f_fsid;
+        int32_t     f_spare[9];
+        char    f_retired8[90];
+        char    f_retired9[90];
+        uint64_t dummy[10]; // was union mount_info mount_info;
+        uint64_t  f_flags2;
+        int64_t    f_spare2[14];
+        int64_t    f_fsize;
+        int64_t    f_bsize;
+        int64_t    f_blocks;
+        int64_t    f_bfree;
+        int64_t    f_bavail;
+        int64_t    f_files;
+        int64_t    f_ffree;
+        char    f_mntonname[1024];
+        char    f_mntfromname[1024];
+    };
+
+    /// For old Tru64 v4.x statfs()
+    struct pre_F64_statfs {
+        int16_t   f_type;
+        int16_t   f_flags;
+        int32_t     f_fsize;
+        int32_t     f_bsize;
+        int32_t     f_blocks;
+        int32_t     f_bfree;
+        int32_t     f_bavail;
+        int32_t     f_files;
+        int32_t     f_ffree;
+        fsid_t  f_fsid;
+        int32_t     f_spare[9];
+        char    f_mntonname[90];
+        char    f_mntfromname[90];
+        uint64_t dummy[10]; // was union mount_info mount_info;
+    };
+
+    /// For getdirentries().
+    struct dirent
+    {
+        ino_t d_ino;           //!< file number of entry
+        uint16_t d_reclen;     //!< length of this record
+        uint16_t d_namlen;     //!< length of string in d_name
+        char d_name[256];      //!< dummy name length
+    };
+
+
+    /// Length of strings in struct utsname (plus 1 for null char).
+    static const int _SYS_NMLN = 32;
+
+    /// Interface struct for uname().
+    struct utsname {
+        char sysname[_SYS_NMLN];        //!< System name.
+        char nodename[_SYS_NMLN];       //!< Node name.
+        char release[_SYS_NMLN];        //!< OS release.
+        char version[_SYS_NMLN];        //!< OS version.
+        char machine[_SYS_NMLN];        //!< Machine type.
+    };
+
+    //@{
+    /// ioctl() command codes.
+    static const unsigned TIOCGETP   = 0x40067408;
+    static const unsigned TIOCSETP   = 0x80067409;
+    static const unsigned TIOCSETN   = 0x8006740a;
+    static const unsigned TIOCSETC   = 0x80067411;
+    static const unsigned TIOCGETC   = 0x40067412;
+    static const unsigned FIONREAD   = 0x4004667f;
+    static const unsigned TIOCISATTY = 0x2000745e;
+    // TIOCGETS not defined in tru64, so I made up a number
+    static const unsigned TIOCGETS   = 0x40000000;
+    static const unsigned TIOCGETA   = 0x402c7413;
+    //@}
+
+    /// Resource enumeration for getrlimit().
+    enum rlimit_resources {
+        TGT_RLIMIT_CPU = 0,
+        TGT_RLIMIT_FSIZE = 1,
+        TGT_RLIMIT_DATA = 2,
+        TGT_RLIMIT_STACK = 3,
+        TGT_RLIMIT_CORE = 4,
+        TGT_RLIMIT_RSS = 5,
+        TGT_RLIMIT_NOFILE = 6,
+        TGT_RLIMIT_AS = 7,
+        TGT_RLIMIT_VMEM = 7
+    };
+
+    /// Limit struct for getrlimit/setrlimit.
+    struct rlimit {
+        uint64_t  rlim_cur;    //!< soft limit
+        uint64_t  rlim_max;    //!< hard limit
+    };
+
+
+    /// For mmap().
+    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+
+    //@{
+    /// For getsysinfo().
+    static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
+    static const unsigned GSI_CPU_INFO = 59;   //!< CPU information
+    static const unsigned GSI_PROC_TYPE = 60;  //!< get proc_type
+    static const unsigned GSI_MAX_CPU = 30;   //!< max # cpu's on this machine
+    static const unsigned GSI_CPUS_IN_BOX = 55;        //!< number of CPUs in system
+    static const unsigned GSI_PHYSMEM = 19;    //!< Physical memory in KB
+    static const unsigned GSI_CLK_TCK = 42;    //!< clock freq in Hz
+    //@}
+
+    /// For getsysinfo() GSI_CPU_INFO option.
+    struct cpu_info {
+        uint32_t     current_cpu;      //!< current_cpu
+        uint32_t     cpus_in_box;      //!< cpus_in_box
+        uint32_t     cpu_type;         //!< cpu_type
+        uint32_t     ncpus;            //!< ncpus
+        uint64_t     cpus_present;     //!< cpus_present
+        uint64_t     cpus_running;     //!< cpus_running
+        uint64_t     cpu_binding;      //!< cpu_binding
+        uint64_t     cpu_ex_binding;   //!< cpu_ex_binding
+        uint32_t     mhz;              //!< mhz
+        uint32_t     unused[3];                //!< future expansion
+    };
+
+    //@{
+    /// For setsysinfo().
+    static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
+    //@}
+
+    /// For gettimeofday.
+    struct timeval {
+        uint32_t tv_sec;       //!< seconds
+        uint32_t tv_usec;      //!< microseconds
+    };
+
+    //@{
+    /// For getrusage().
+    static const int TGT_RUSAGE_THREAD = 1;
+    static const int TGT_RUSAGE_SELF = 0;
+    static const int TGT_RUSAGE_CHILDREN = -1;
+    //@}
+
+    /// For getrusage().
+    struct rusage {
+        struct timeval ru_utime;       //!< user time used
+        struct timeval ru_stime;       //!< system time used
+        uint64_t ru_maxrss;            //!< ru_maxrss
+        uint64_t ru_ixrss;             //!< integral shared memory size
+        uint64_t ru_idrss;             //!< integral unshared data "
+        uint64_t ru_isrss;             //!< integral unshared stack "
+        uint64_t ru_minflt;            //!< page reclaims - total vmfaults
+        uint64_t ru_majflt;            //!< page faults
+        uint64_t ru_nswap;             //!< swaps
+        uint64_t ru_inblock;           //!< block input operations
+        uint64_t ru_oublock;           //!< block output operations
+        uint64_t ru_msgsnd;            //!< messages sent
+        uint64_t ru_msgrcv;            //!< messages received
+        uint64_t ru_nsignals;          //!< signals received
+        uint64_t ru_nvcsw;             //!< voluntary context switches
+        uint64_t ru_nivcsw;            //!< involuntary "
+    };
+
+    /// For sigreturn().
+    struct sigcontext {
+        int64_t sc_onstack;            //!< sigstack state to restore
+        int64_t sc_mask;               //!< signal mask to restore
+        int64_t sc_pc;                 //!< pc at time of signal
+        int64_t sc_ps;                 //!< psl to retore
+        int64_t sc_regs[32];           //!< processor regs 0 to 31
+        int64_t sc_ownedfp;            //!< fp has been used
+        int64_t sc_fpregs[32];         //!< fp regs 0 to 31
+        uint64_t sc_fpcr;              //!< floating point control reg
+        uint64_t sc_fp_control;                //!< software fpcr
+        int64_t sc_reserved1;          //!< reserved for kernel
+        uint32_t sc_kreserved1;                //!< reserved for kernel
+        uint32_t sc_kreserved2;                //!< reserved for kernel
+        size_t  sc_ssize;              //!< stack size
+        caddr_t sc_sbase;              //!< stack start
+        uint64_t sc_traparg_a0;                //!< a0 argument to trap on exc
+        uint64_t sc_traparg_a1;                //!< a1 argument to trap on exc
+        uint64_t sc_traparg_a2;                //!< a2 argument to trap on exc
+        uint64_t sc_fp_trap_pc;                //!< imprecise pc
+        uint64_t sc_fp_trigger_sum;    //!< Exception summary at trigg
+        uint64_t sc_fp_trigger_inst;   //!< Instruction at trigger pc
+    };
+
+
+    /// For table().
+    static const int TBL_SYSINFO = 12;
+
+    /// For table().
+    struct tbl_sysinfo {
+        uint64_t si_user;      //!< User time
+        uint64_t si_nice;      //!< Nice time
+        uint64_t si_sys;       //!< System time
+        uint64_t si_idle;      //!< Idle time
+        uint64_t si_hz;                //!< hz
+        uint64_t si_phz;       //!< phz
+        uint64_t si_boottime;  //!< Boot time in seconds
+        uint64_t wait;         //!< Wait time
+        uint32_t  si_max_procs;        //!< rpb->rpb_numprocs
+        uint32_t  pad;         //!< padding
+    };
+
+
+    /// For stack_create.
+    struct vm_stack {
+        // was void *
+        Addr   address;        //!< address hint
+        size_t rsize;          //!< red zone size
+        size_t ysize;          //!< yellow zone size
+        size_t gsize;          //!< green zone size
+        size_t swap;           //!< amount of swap to reserve
+        size_t incr;           //!< growth increment
+        uint64_t       align;          //!< address alignment
+        uint64_t       flags;          //!< MAP_FIXED etc.
+        // was struct memalloc_attr *
+        Addr   attr;           //!< allocation policy
+        uint64_t reserved;     //!< reserved
+    };
+
+    /// Return values for nxm calls.
+    enum {
+        KERN_NOT_RECEIVER = 7,
+        KERN_NOT_IN_SET = 12
+    };
+
+    /// For nxm_task_init.
+    static const int NXM_TASK_INIT_VP = 2;     //!< initial thread is VP
+
+    /// Task attribute structure.
+    struct nxm_task_attr {
+        int64_t nxm_callback;  //!< nxm_callback
+        unsigned int nxm_version;      //!< nxm_version
+        unsigned short nxm_uniq_offset;        //!< nxm_uniq_offset
+        unsigned short flags;  //!< flags
+        int nxm_quantum;       //!< nxm_quantum
+        int pad1;              //!< pad1
+        int64_t pad2;          //!< pad2
+    };
+
+    /// Signal set.
+    typedef uint64_t   sigset_t;
+
+    /// Thread state shared between user & kernel.
+    struct ushared_state {
+        sigset_t        sigmask;        //!< thread signal mask
+        sigset_t        sig;            //!< thread pending mask
+        // struct nxm_pth_state *
+        Addr pth_id; //!< out-of-line state
+        int             flags;          //!< shared flags
+#define US_SIGSTACK     0x1             // thread called sigaltstack
+#define US_ONSTACK      0x2             // thread is running on altstack
+#define US_PROFILE      0x4             // thread called profil
+#define US_SYSCALL      0x8             // thread in syscall
+#define US_TRAP         0x10            // thread has trapped
+#define US_YELLOW       0x20            // thread has mellowed yellow
+#define US_YZONE        0x40            // thread has zoned out
+#define US_FP_OWNED     0x80            // thread used floating point
+
+        int             cancel_state;   //!< thread's cancelation state
+#define US_CANCEL         0x1           // cancel pending
+#define US_NOCANCEL       0X2           // synch cancel disabled
+#define US_SYS_NOCANCEL   0x4           // syscall cancel disabled
+#define US_ASYNC_NOCANCEL 0x8           // asynch cancel disabled
+#define US_CANCEL_BITS  (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
+#define US_CANCEL_MASK  (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
+                         US_ASYNC_NOCANCEL)
+
+        // These are semi-shared. They are always visible to
+        // the kernel but are never context-switched by the library.
+
+        int             nxm_ssig;       //!< scheduler's synchronous signals
+        int             reserved1;     //!< reserved1
+        int64_t            nxm_active;     //!< scheduler active
+        int64_t            reserved2;  //!< reserved2
+    };
+
+    struct nxm_sched_state {
+        struct          ushared_state nxm_u;    //!< state own by user thread
+        unsigned int    nxm_bits;               //!< scheduler state / slot
+        int             nxm_quantum;            //!< quantum count-down value
+        int             nxm_set_quantum;        //!< quantum reset value
+        int             nxm_sysevent;           //!< syscall state
+        // struct nxm_upcall *
+        Addr       nxm_uc_ret; //!< stack ptr of null thread
+        // void *
+        Addr nxm_tid;               //!< scheduler's thread id
+        int64_t            nxm_va;                 //!< page fault address
+        // struct nxm_pth_state *
+        Addr nxm_pthid; //!< id of null thread
+        uint64_t   nxm_bound_pcs_count;    //!< bound PCS thread count
+        int64_t            pad[2];        //!< pad
+    };
+
+    /// nxm_shared.
+    struct nxm_shared {
+        int64_t nxm_callback;              //!< address of upcall routine
+        unsigned int nxm_version;       //!< version number
+        unsigned short nxm_uniq_offset; //!< correction factor for TEB
+        unsigned short pad1;           //!< pad1
+        int64_t space[2];                  //!< future growth
+        struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
+    };
+
+    /// nxm_slot_state_t.
+    enum nxm_slot_state_t {
+        NXM_SLOT_AVAIL,
+        NXM_SLOT_BOUND,
+        NXM_SLOT_UNBOUND,
+        NXM_SLOT_EMPTY
+    };
+
+    /// nxm_config_info
+    struct nxm_config_info {
+        int nxm_nslots_per_rad;         //!< max number of VP slots per RAD
+        int nxm_nrads;                  //!< max number of RADs
+        // nxm_slot_state_t *
+        Addr nxm_slot_state; //!< per-VP slot state
+        // struct nxm_shared *
+        Addr nxm_rad[1];  //!< per-RAD shared areas
+    };
+
+    /// For nxm_thread_create.
+    enum nxm_thread_type {
+        NXM_TYPE_SCS   = 0,
+        NXM_TYPE_VP            = 1,
+        NXM_TYPE_MANAGER       = 2
+    };
+
+    /// Thread attributes.
+    struct nxm_thread_attr {
+        int version;   //!< version
+        int type;      //!< type
+        int cancel_flags;      //!< cancel_flags
+        int priority;  //!< priority
+        int policy;    //!< policy
+        int signal_type;       //!< signal_type
+        // void *
+        Addr pthid;    //!< pthid
+        sigset_t sigmask;      //!< sigmask
+        /// Initial register values.
+        struct {
+            uint64_t pc;       //!< pc
+            uint64_t sp;       //!< sp
+            uint64_t a0;       //!< a0
+        } registers;
+        uint64_t pad2[2];      //!< pad2
+    };
+
+    /// Helper function to convert a host stat buffer to a target stat
+    /// buffer.  Also copies the target buffer out to the simulated
+    /// memory space.  Used by stat(), fstat(), and lstat().
+    template <class T>
+    static void
+    copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host)
+    {
+        TypedBufferArg<T> tgt(addr);
+
+        tgt->st_dev = htog(host->st_dev);
+        tgt->st_ino = htog(host->st_ino);
+        tgt->st_mode = htog(host->st_mode);
+        tgt->st_nlink = htog(host->st_nlink);
+        tgt->st_uid = htog(host->st_uid);
+        tgt->st_gid = htog(host->st_gid);
+        tgt->st_rdev = htog(host->st_rdev);
+        tgt->st_size = htog(host->st_size);
+        tgt->st_atimeX = htog(host->st_atime);
+        tgt->st_mtimeX = htog(host->st_mtime);
+        tgt->st_ctimeX = htog(host->st_ctime);
+        tgt->st_blksize = htog(host->st_blksize);
+        tgt->st_blocks = htog(host->st_blocks);
+
+        tgt.copyOut(mem);
+    }
+
+    /// Helper function to convert a host statfs buffer to a target statfs
+    /// buffer.  Also copies the target buffer out to the simulated
+    /// memory space.  Used by statfs() and fstatfs().
+    template <class T>
+    static void
+    copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host)
+    {
+        TypedBufferArg<T> tgt(addr);
+
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+        tgt->f_type = 0;
+#else
+        tgt->f_type = htog(host->f_type);
+#endif
+        tgt->f_bsize = htog(host->f_bsize);
+        tgt->f_blocks = htog(host->f_blocks);
+        tgt->f_bfree = htog(host->f_bfree);
+        tgt->f_bavail = htog(host->f_bavail);
+        tgt->f_files = htog(host->f_files);
+        tgt->f_ffree = htog(host->f_ffree);
+
+        // Is this as string normally?
+        memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
+
+        tgt.copyOut(mem);
+    }
+
+    class F64 {
+      public:
+        static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+                                   global_stat *host)
+        {
+            Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
+        }
+
+        static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+                                     global_statfs *host)
+        {
+            Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
+        }
+    };
+
+    class PreF64 {
+      public:
+        static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+                                   global_stat *host)
+        {
+            Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
+        }
+
+        static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+                                     global_statfs *host)
+        {
+            Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
+        }
+    };
+
+    /// Helper function to convert a host stat buffer to an old pre-F64
+    /// (4.x) target stat buffer.  Also copies the target buffer out to
+    /// the simulated memory space.  Used by pre_F64_stat(),
+    /// pre_F64_fstat(), and pre_F64_lstat().
+    static void
+    copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
+    {
+        TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
+
+        tgt->st_dev = htog(host->st_dev);
+        tgt->st_ino = htog(host->st_ino);
+        tgt->st_mode = htog(host->st_mode);
+        tgt->st_nlink = htog(host->st_nlink);
+        tgt->st_uid = htog(host->st_uid);
+        tgt->st_gid = htog(host->st_gid);
+        tgt->st_rdev = htog(host->st_rdev);
+        tgt->st_size = htog(host->st_size);
+        tgt->st_atimeX = htog(host->st_atime);
+        tgt->st_mtimeX = htog(host->st_mtime);
+        tgt->st_ctimeX = htog(host->st_ctime);
+        tgt->st_blksize = htog(host->st_blksize);
+        tgt->st_blocks = htog(host->st_blocks);
+
+        tgt.copyOut(mem);
+    }
+
+
+    /// The target system's hostname.
+    static const char *hostname;
+
+
+    /// Target getdirentries() handler.
+    static SyscallReturn
+    getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
+                      ExecContext *xc)
+    {
+#ifdef __CYGWIN__
+        panic("getdirent not implemented on cygwin!");
+#else
+        int fd = process->sim_fd(xc->getSyscallArg(0));
+        Addr tgt_buf = xc->getSyscallArg(1);
+        int tgt_nbytes = xc->getSyscallArg(2);
+        Addr tgt_basep = xc->getSyscallArg(3);
+
+        char * const host_buf = new char[tgt_nbytes];
+
+        // just pass basep through uninterpreted.
+        TypedBufferArg<int64_t> basep(tgt_basep);
+        basep.copyIn(xc->mem);
+        long host_basep = (off_t)htog((int64_t)*basep);
+        int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
+
+        // check for error
+        if (host_result < 0) {
+            delete [] host_buf;
+            return -errno;
+        }
+
+        // no error: copy results back to target space
+        Addr tgt_buf_ptr = tgt_buf;
+        char *host_buf_ptr = host_buf;
+        char *host_buf_end = host_buf + host_result;
+        while (host_buf_ptr < host_buf_end) {
+            global_dirent *host_dp = (global_dirent *)host_buf_ptr;
+            int namelen = strlen(host_dp->d_name);
+
+            // Actual size includes padded string rounded up for alignment.
+            // Subtract 256 for dummy char array in Tru64::dirent definition.
+            // Add 1 to namelen for terminating null char.
+            int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
+            TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
+            tgt_dp->d_ino = host_dp->d_ino;
+            tgt_dp->d_reclen = tgt_bufsize;
+            tgt_dp->d_namlen = namelen;
+            strcpy(tgt_dp->d_name, host_dp->d_name);
+            tgt_dp.copyOut(xc->mem);
+
+            tgt_buf_ptr += tgt_bufsize;
+            host_buf_ptr += host_dp->d_reclen;
+        }
+
+        delete [] host_buf;
+
+        *basep = htog((int64_t)host_basep);
+        basep.copyOut(xc->mem);
+
+        return tgt_buf_ptr - tgt_buf;
+#endif
+    }
+
+    /// Target sigreturn() handler.
+    static SyscallReturn
+    sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+    {
+        RegFile *regs = &xc->regs;
+        TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
+
+        sc.copyIn(xc->mem);
+
+        // Restore state from sigcontext structure.
+        // Note that we'll advance PC <- NPC before the end of the cycle,
+        // so we need to restore the desired PC into NPC.
+        // The current regs->pc will get clobbered.
+        regs->npc = htog(sc->sc_pc);
+
+        for (int i = 0; i < 31; ++i) {
+            regs->intRegFile[i] = htog(sc->sc_regs[i]);
+            regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]);
+        }
+
+        regs->miscRegs.fpcr = htog(sc->sc_fpcr);
+
+        return 0;
+    }
+
+    /// Target table() handler.
+    static SyscallReturn
+    tableFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+    {
+        int id = xc->getSyscallArg(0);         // table ID
+        int index = xc->getSyscallArg(1);      // index into table
+        // arg 2 is buffer pointer; type depends on table ID
+        int nel = xc->getSyscallArg(3);                // number of elements
+        int lel = xc->getSyscallArg(4);                // expected element size
+
+        switch (id) {
+          case Tru64::TBL_SYSINFO: {
+              if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
+                  return -EINVAL;
+              TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
+
+              const int clk_hz = one_million;
+              elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
+              elp->si_nice = htog(0);
+              elp->si_sys = htog(0);
+              elp->si_idle = htog(0);
+              elp->wait = htog(0);
+              elp->si_hz = htog(clk_hz);
+              elp->si_phz = htog(clk_hz);
+              elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch?
+              elp->si_max_procs = htog(process->numCpus());
+              elp.copyOut(xc->mem);
+              return 0;
+          }
+
+          default:
+            cerr << "table(): id " << id << " unknown." << endl;
+            return -EINVAL;
+        }
+    }
+
+    //
+    // Mach syscalls -- identified by negated syscall numbers
+    //
+
+    /// Create a stack region for a thread.
+    static SyscallReturn
+    stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
+                     ExecContext *xc)
+    {
+        TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
+
+        argp.copyIn(xc->mem);
+
+        // if the user chose an address, just let them have it.  Otherwise
+        // pick one for them.
+        if (htog(argp->address) == 0) {
+            argp->address = htog(process->next_thread_stack_base);
+            int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
+                    htog(argp->gsize));
+            process->next_thread_stack_base -= stack_size;
+            argp.copyOut(xc->mem);
+        }
+
+        return 0;
+    }
+
+    /// NXM library version stamp.
+    static
+    const int NXM_LIB_VERSION = 301003;
+
+    /// This call sets up the interface between the user and kernel
+    /// schedulers by creating a shared-memory region.  The shared memory
+    /// region has several structs, some global, some per-RAD, some per-VP.
+    static SyscallReturn
+    nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
+                      ExecContext *xc)
+    {
+        TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
+        TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
+
+        attrp.copyIn(xc->mem);
+
+        if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
+            cerr << "nxm_task_init: thread library version mismatch! "
+                 << "got " << attrp->nxm_version
+                 << ", expected " << NXM_LIB_VERSION << endl;
+            abort();
+        }
+
+        if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {
+            cerr << "nxm_task_init: bad flag value " << attrp->flags
+                 << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
+            abort();
+        }
+
+        const Addr base_addr = 0x12000; // was 0x3f0000000LL;
+        Addr cur_addr = base_addr; // next addresses to use
+        // first comes the config_info struct
+        Addr config_addr = cur_addr;
+        cur_addr += sizeof(Tru64::nxm_config_info);
+        // next comes the per-cpu state vector
+        Addr slot_state_addr = cur_addr;
+        int slot_state_size =
+            process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+        cur_addr += slot_state_size;
+        // now the per-RAD state struct (we only support one RAD)
+        cur_addr = 0x14000;    // bump up addr for alignment
+        Addr rad_state_addr = cur_addr;
+        int rad_state_size =
+            (sizeof(Tru64::nxm_shared)
+             + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+        cur_addr += rad_state_size;
+
+        // now initialize a config_info struct and copy it out to user space
+        TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
+
+        config->nxm_nslots_per_rad = htog(process->numCpus());
+        config->nxm_nrads = htog(1);   // only one RAD in our system!
+        config->nxm_slot_state = htog(slot_state_addr);
+        config->nxm_rad[0] = htog(rad_state_addr);
+
+        config.copyOut(xc->mem);
+
+        // initialize the slot_state array and copy it out
+        TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
+                                                           slot_state_size);
+        for (int i = 0; i < process->numCpus(); ++i) {
+            // CPU 0 is bound to the calling process; all others are available
+            // XXX this code should have an endian conversion, but I don't think
+            // it works anyway
+            slot_state[i] =
+                (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
+        }
+
+        slot_state.copyOut(xc->mem);
+
+        // same for the per-RAD "shared" struct.  Note that we need to
+        // allocate extra bytes for the per-VP array which is embedded at
+        // the end.
+        TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
+                                                    rad_state_size);
+
+        rad_state->nxm_callback = attrp->nxm_callback;
+        rad_state->nxm_version = attrp->nxm_version;
+        rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
+        for (int i = 0; i < process->numCpus(); ++i) {
+            Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
+            ssp->nxm_u.sigmask = htog(0);
+            ssp->nxm_u.sig = htog(0);
+            ssp->nxm_u.flags = htog(0);
+            ssp->nxm_u.cancel_state = htog(0);
+            ssp->nxm_u.nxm_ssig = 0;
+            ssp->nxm_bits = htog(0);
+            ssp->nxm_quantum = attrp->nxm_quantum;
+            ssp->nxm_set_quantum = attrp->nxm_quantum;
+            ssp->nxm_sysevent = htog(0);
+
+            if (i == 0) {
+                uint64_t uniq = xc->regs.miscRegs.uniq;
+                ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));
+                ssp->nxm_u.nxm_active = htog(uniq | 1);
+            }
+            else {
+                ssp->nxm_u.pth_id = htog(0);
+                ssp->nxm_u.nxm_active = htog(0);
+            }
+        }
+
+        rad_state.copyOut(xc->mem);
+
+        //
+        // copy pointer to shared config area out to user
+        //
+        *configptr_ptr = htog(config_addr);
+        configptr_ptr.copyOut(xc->mem);
+
+        // Register this as a valid address range with the process
+        process->nxm_start = base_addr;
+        process->nxm_end = cur_addr;
+
+        return 0;
+    }
+
+    /// Initialize execution context.
+    static void
+    init_exec_context(ExecContext *ec,
+                      Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
+    {
+        memset(&ec->regs, 0, sizeof(ec->regs));
+
+        ec->regs.intRegFile[ArgumentReg0] = gtoh(attrp->registers.a0);
+        ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc);
+        ec->regs.intRegFile[StackPointerReg] = gtoh(attrp->registers.sp);
+        ec->regs.miscRegs.uniq = uniq_val;
+
+        ec->regs.pc = gtoh(attrp->registers.pc);
+        ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(MachInst);
+
+        ec->activate();
+    }
+
+    /// Create thread.
+    static SyscallReturn
+    nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
+                          ExecContext *xc)
+    {
+        TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
+        TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
+        int thread_index = xc->getSyscallArg(2);
+
+        // get attribute args
+        attrp.copyIn(xc->mem);
+
+        if (gtoh(attrp->version) != NXM_LIB_VERSION) {
+            cerr << "nxm_thread_create: thread library version mismatch! "
+                 << "got " << attrp->version
+                 << ", expected " << NXM_LIB_VERSION << endl;
+            abort();
+        }
+
+        if (thread_index < 0 | thread_index > process->numCpus()) {
+            cerr << "nxm_thread_create: bad thread index " << thread_index
+                 << endl;
+            abort();
+        }
+
+        // On a real machine, the per-RAD shared structure is in
+        // shared memory, so both the user and kernel can get at it.
+        // We don't have that luxury, so we just copy it in and then
+        // back out again.
+        int rad_state_size =
+            (sizeof(Tru64::nxm_shared) +
+             (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+
+        TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
+                                                    rad_state_size);
+        rad_state.copyIn(xc->mem);
+
+        uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
+
+        if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {
+            // DEC pthreads seems to always create one of these (in
+            // addition to N application threads), but we don't use it,
+            // so don't bother creating it.
+
+            // This is supposed to be a port number.  Make something up.
+            *kidp = htog(99);
+            kidp.copyOut(xc->mem);
+
+            return 0;
+        } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
+            // A real "virtual processor" kernel thread.  Need to fork
+            // this thread on another CPU.
+            Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
+
+            if (gtoh(ssp->nxm_u.nxm_active) != 0)
+                return (int) Tru64::KERN_NOT_RECEIVER;
+
+            ssp->nxm_u.pth_id = attrp->pthid;
+            ssp->nxm_u.nxm_active = htog(uniq_val | 1);
+
+            rad_state.copyOut(xc->mem);
+
+            Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
+            int slot_state_size =
+                process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+
+            TypedBufferArg<Tru64::nxm_slot_state_t>
+                slot_state(slot_state_addr,
+                           slot_state_size);
+
+            slot_state.copyIn(xc->mem);
+
+            if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
+                cerr << "nxm_thread_createFunc: requested VP slot "
+                     << thread_index << " not available!" << endl;
+                fatal("");
+            }
+
+            // XXX This should have an endian conversion but I think this code
+            // doesn't work anyway
+            slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
+
+            slot_state.copyOut(xc->mem);
+
+            // Find a free simulator execution context.
+            for (int i = 0; i < process->numCpus(); ++i) {
+                ExecContext *xc = process->execContexts[i];
+
+                if (xc->status() == ExecContext::Unallocated) {
+                    // inactive context... grab it
+                    init_exec_context(xc, attrp, uniq_val);
+
+                    // This is supposed to be a port number, but we'll try
+                    // and get away with just sticking the thread index
+                    // here.
+                    *kidp = htog(thread_index);
+                    kidp.copyOut(xc->mem);
+
+                    return 0;
+                }
+            }
+
+            // fell out of loop... no available inactive context
+            cerr << "nxm_thread_create: no idle contexts available." << endl;
+            abort();
+        } else {
+            cerr << "nxm_thread_create: can't handle thread type "
+                 << attrp->type << endl;
+            abort();
+        }
+
+        return 0;
+    }
+
+    /// Thread idle call (like yield()).
+    static SyscallReturn
+    nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
+                 ExecContext *xc)
+    {
+        return 0;
+    }
+
+    /// Block thread.
+    static SyscallReturn
+    nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+                         ExecContext *xc)
+    {
+        uint64_t tid = xc->getSyscallArg(0);
+        uint64_t secs = xc->getSyscallArg(1);
+        uint64_t flags = xc->getSyscallArg(2);
+        uint64_t action = xc->getSyscallArg(3);
+        uint64_t usecs = xc->getSyscallArg(4);
+
+        cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
+             << " " << flags << " " << action << " " << usecs << endl;
+
+        return 0;
+    }
+
+    /// block.
+    static SyscallReturn
+    nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+    {
+        Addr uaddr = xc->getSyscallArg(0);
+        uint64_t val = xc->getSyscallArg(1);
+        uint64_t secs = xc->getSyscallArg(2);
+        uint64_t usecs = xc->getSyscallArg(3);
+        uint64_t flags = xc->getSyscallArg(4);
+
+        BaseCPU *cpu = xc->cpu;
+
+        cout << cpu->name() << ": nxm_block "
+             << hex << uaddr << dec << " " << val
+             << " " << secs << " " << usecs
+             << " " << flags << endl;
+
+        return 0;
+    }
+
+    /// Unblock thread.
+    static SyscallReturn
+    nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
+                    ExecContext *xc)
+    {
+        Addr uaddr = xc->getSyscallArg(0);
+
+        cout << xc->cpu->name() << ": nxm_unblock "
+             << hex << uaddr << dec << endl;
+
+        return 0;
+    }
+
+    /// Switch thread priority.
+    static SyscallReturn
+    swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+    {
+        // Attempts to switch to another runnable thread (if there is
+        // one).  Returns false if there are no other threads to run
+        // (i.e., the thread can reasonably spin-wait) or true if there
+        // are other threads.
+        //
+        // Since we assume at most one "kernel" thread per CPU, it's
+        // always safe to return false here.
+        return 0; //false;
+    }
+
+
+    /// Activate exec context waiting on a channel.  Just activate one
+    /// by default.
+    static int
+    activate_waiting_context(Addr uaddr, Process *process,
+                             bool activate_all = false)
+    {
+        int num_activated = 0;
+
+        list<Process::WaitRec>::iterator i = process->waitList.begin();
+        list<Process::WaitRec>::iterator end = process->waitList.end();
+
+        while (i != end && (num_activated == 0 || activate_all)) {
+            if (i->waitChan == uaddr) {
+                // found waiting process: make it active
+                ExecContext *newCtx = i->waitingContext;
+                assert(newCtx->status() == ExecContext::Suspended);
+                newCtx->activate();
+
+                // get rid of this record
+                i = process->waitList.erase(i);
+
+                ++num_activated;
+            } else {
+                ++i;
+            }
+        }
+
+        return num_activated;
+    }
+
+    /// M5 hacked-up lock acquire.
+    static void
+    m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+    {
+        TypedBufferArg<uint64_t> lockp(uaddr);
+
+        lockp.copyIn(xc->mem);
+
+        if (gtoh(*lockp) == 0) {
+            // lock is free: grab it
+            *lockp = htog(1);
+            lockp.copyOut(xc->mem);
+        } else {
+            // lock is busy: disable until free
+            process->waitList.push_back(Process::WaitRec(uaddr, xc));
+            xc->suspend();
+        }
+    }
+
+    /// M5 unlock call.
+    static void
+    m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+    {
+        TypedBufferArg<uint64_t> lockp(uaddr);
+
+        lockp.copyIn(xc->mem);
+        assert(*lockp != 0);
+
+        // Check for a process waiting on the lock.
+        int num_waiting = activate_waiting_context(uaddr, process);
+
+        // clear lock field if no waiting context is taking over the lock
+        if (num_waiting == 0) {
+            *lockp = 0;
+            lockp.copyOut(xc->mem);
+        }
+    }
+
+    /// Lock acquire syscall handler.
+    static SyscallReturn
+    m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
+                      ExecContext *xc)
+    {
+        Addr uaddr = xc->getSyscallArg(0);
+
+        m5_lock_mutex(uaddr, process, xc);
+
+        // Return 0 since we will always return to the user with the lock
+        // acquired.  We will just keep the context inactive until that is
+        // true.
+        return 0;
+    }
+
+    /// Try lock (non-blocking).
+    static SyscallReturn
+    m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
+                         ExecContext *xc)
+    {
+        Addr uaddr = xc->getSyscallArg(0);
+        TypedBufferArg<uint64_t> lockp(uaddr);
+
+        lockp.copyIn(xc->mem);
+
+        if (gtoh(*lockp) == 0) {
+            // lock is free: grab it
+            *lockp = htog(1);
+            lockp.copyOut(xc->mem);
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    /// Unlock syscall handler.
+    static SyscallReturn
+    m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
+                        ExecContext *xc)
+    {
+        Addr uaddr = xc->getSyscallArg(0);
+
+        m5_unlock_mutex(uaddr, process, xc);
+
+        return 0;
+    }
+
+    /// Signal ocndition.
+    static SyscallReturn
+    m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
+                       ExecContext *xc)
+    {
+        Addr cond_addr = xc->getSyscallArg(0);
+
+        // Wake up one process waiting on the condition variable.
+        activate_waiting_context(cond_addr, process);
+
+        return 0;
+    }
+
+    /// Wake up all processes waiting on the condition variable.
+    static SyscallReturn
+    m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
+                          ExecContext *xc)
+    {
+        Addr cond_addr = xc->getSyscallArg(0);
+
+        activate_waiting_context(cond_addr, process, true);
+
+        return 0;
+    }
+
+    /// Wait on a condition.
+    static SyscallReturn
+    m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
+                     ExecContext *xc)
+    {
+        Addr cond_addr = xc->getSyscallArg(0);
+        Addr lock_addr = xc->getSyscallArg(1);
+        TypedBufferArg<uint64_t> condp(cond_addr);
+        TypedBufferArg<uint64_t> lockp(lock_addr);
+
+        // user is supposed to acquire lock before entering
+        lockp.copyIn(xc->mem);
+        assert(gtoh(*lockp) != 0);
+
+        m5_unlock_mutex(lock_addr, process, xc);
+
+        process->waitList.push_back(Process::WaitRec(cond_addr, xc));
+        xc->suspend();
+
+        return 0;
+    }
+
+    /// Thread exit.
+    static SyscallReturn
+    m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
+                       ExecContext *xc)
+    {
+        assert(xc->status() == ExecContext::Active);
+        xc->deallocate();
+
+        return 0;
+    }
+
+    /// Indirect syscall invocation (call #0).
+    static SyscallReturn
+    indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
+                        ExecContext *xc)
+    {
+        int new_callnum = xc->getSyscallArg(0);
+        LiveProcess *lp = dynamic_cast<LiveProcess*>(process);
+        assert(lp);
+
+        for (int i = 0; i < 5; ++i)
+            xc->setSyscallArg(i, xc->getSyscallArg(i+1));
+
+
+        SyscallDesc *new_desc = lp->getDesc(new_callnum);
+        if (desc == NULL)
+            fatal("Syscall %d out of range", callnum);
+
+        new_desc->doSyscall(new_callnum, process, xc);
+
+        return 0;
+    }
+
+};  // class Tru64
+
+
+#endif // FULL_SYSTEM
+
 #endif // __TRU64_HH__
index 59d122b48f0f010172e91488ce39347968b48df1..3ae3abb52b6d6fe5be47ad745d8947fcd56f82f0 100644 (file)
@@ -46,6 +46,7 @@
 #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"
@@ -350,6 +351,19 @@ LiveProcess::LiveProcess(const string &nm, 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 &nm,
@@ -394,6 +408,7 @@ LiveProcess::create(const string &nm,
 }
 
 
+
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
 
     VectorParam<string> cmd;
index 43fafd9d7b4d29914eb05326ef08766da8e0f202..40143ea046e79ce874a084b1d9cbd66f3a1bfd6b 100644 (file)
@@ -48,6 +48,7 @@
 
 class ExecContext;
 class FunctionalMemory;
+class SyscallDesc;
 class Process : public SimObject
 {
   public:
@@ -200,6 +201,11 @@ class LiveProcess : public Process
                                std::string executable,
                                std::vector<std::string> &argv,
                                std::vector<std::string> &envp);
+
+    virtual void syscall(ExecContext *xc);
+
+    virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); }
+
 };
 
 
index 4b6388a41a143fbd6c66a881f01dc8238353fce6..a46e991b91d1763983c99f01b4e15bc89f08bb35 100644 (file)
@@ -26,6 +26,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <fcntl.h>
 #include <unistd.h>
 
 #include <string>
@@ -278,3 +279,48 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
     int result = fchown(fd, hostOwner, hostGroup);
     return (result == -1) ? -errno : result;
 }
+
+
+SyscallReturn
+fcntlFunc(SyscallDesc *desc, int num, Process *process,
+          ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+
+    if (fd < 0 || process->sim_fd(fd) < 0)
+        return -EBADF;
+
+    int cmd = xc->getSyscallArg(1);
+    switch (cmd) {
+      case 0: // F_DUPFD
+        // if we really wanted to support this, we'd need to do it
+        // in the target fd space.
+        warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
+        return -EMFILE;
+
+      case 1: // F_GETFD (get close-on-exec flag)
+      case 2: // F_SETFD (set close-on-exec flag)
+        return 0;
+
+      case 3: // F_GETFL (get file flags)
+      case 4: // F_SETFL (set file flags)
+        // not sure if this is totally valid, but we'll pass it through
+        // to the underlying OS
+        warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
+        return fcntl(process->sim_fd(fd), cmd);
+        // return 0;
+
+      case 7: // F_GETLK  (get lock)
+      case 8: // F_SETLK  (set lock)
+      case 9: // F_SETLKW (set lock and wait)
+        // don't mess with file locking... just act like it's OK
+        warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
+        return 0;
+
+      default:
+        warn("Unknown fcntl command %d\n", cmd);
+        return 0;
+    }
+}
+
+
index d8029ddb0b30c40378a4515035bd3c440a1faa33..fd5c7b6e6b114aa9995f33889b4843985a930b18 100644 (file)
@@ -239,6 +239,10 @@ SyscallReturn chownFunc(SyscallDesc *desc, int num,
 SyscallReturn fchownFunc(SyscallDesc *desc, int num,
                          Process *p, ExecContext *xc);
 
+/// Target fnctl() handler.
+SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
+                        Process *process, ExecContext *xc);
+
 /// This struct is used to build an target-OS-dependent table that
 /// maps the target's open() flags to the host open() flags.
 struct OpenFlagTransTable {