summaryrefslogtreecommitdiff
path: root/arch/alpha/alpha_linux_process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/alpha_linux_process.cc')
-rw-r--r--arch/alpha/alpha_linux_process.cc588
1 files changed, 294 insertions, 294 deletions
diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc
index 13d1f5366..d8a05849d 100644
--- a/arch/alpha/alpha_linux_process.cc
+++ b/arch/alpha/alpha_linux_process.cc
@@ -52,327 +52,326 @@
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;
-
-// open(2) flags
-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;
-
-static OpenFlagTransTable openFlagTable[];
-static const int NUM_OPEN_FLAGS;
-
-//
-// Stat buffer.
-//
-
-struct tgt_stat {
- uint32_t st_dev;
- uint32_t st_ino;
- uint32_t st_mode;
- uint32_t st_nlink;
- uint32_t st_uid;
- uint32_t st_gid;
- uint32_t st_rdev;
- int64_t st_size;
- uint64_t st_atimeX;
- uint64_t st_mtimeX;
- uint64_t st_ctimeX;
- uint32_t st_blksize;
- int32_t st_blocks;
- uint32_t st_flags;
- uint32_t st_gen;
-};
-
-
-//
-// for uname()
-//
-
-static const int _SYS_NMLN = 65;
-
-struct utsname {
- char sysname[_SYS_NMLN];
- char nodename[_SYS_NMLN];
- char release[_SYS_NMLN];
- char version[_SYS_NMLN];
- char machine[_SYS_NMLN];
-};
-
-
-//
-// for ioctl()
-//
-
-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;
-
-//
-// for getrlimit()
-//
-
-enum rlimit_resources {
- RLIMIT_CPU = 0,
- RLIMIT_FSIZE = 1,
- RLIMIT_DATA = 2,
- RLIMIT_STACK = 3,
- RLIMIT_CORE = 4,
- RLIMIT_RSS = 5,
- RLIMIT_NOFILE = 6,
- RLIMIT_AS = 7,
- RLIMIT_VMEM = 7,
- RLIMIT_NPROC = 8,
- RLIMIT_MEMLOCK = 9,
- RLIMIT_LOCKS = 10
-};
-
-struct rlimit {
- uint64_t rlim_cur; // soft limit
- uint64_t rlim_max; // hard limit
-};
-
-
-//
-// for mmap()
-//
+ 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;
+ //@}
+
+ //@{
+ /// 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
+ 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
+ };
+
+
+ /// 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;
+ //@}
+
+ /// Resource enumeration for getrlimit().
+ enum rlimit_resources {
+ RLIMIT_CPU = 0,
+ RLIMIT_FSIZE = 1,
+ RLIMIT_DATA = 2,
+ RLIMIT_STACK = 3,
+ RLIMIT_CORE = 4,
+ RLIMIT_RSS = 5,
+ RLIMIT_NOFILE = 6,
+ RLIMIT_AS = 7,
+ RLIMIT_VMEM = 7,
+ RLIMIT_NPROC = 8,
+ RLIMIT_MEMLOCK = 9,
+ 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;
- int64_t tv_usec;
-};
-
-//
-// for getrusage
-//
-
-
-static const int RUSAGE_SELF = 0;
-static const int RUSAGE_CHILDREN = -1;
-static const int RUSAGE_BOTH = -2;
-
-struct rusage {
- struct timeval ru_utime; // user time used
- struct timeval ru_stime; // system time used
- int64_t ru_maxrss;
- 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 "
-};
-
-static
-void
-copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
-{
- TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
-
- tgt.copyOut(mem);
-}
-
-
-static const char *hostname;
-
-static
-int
-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;
-}
-
-
-static
-int
-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 1;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
+ /// For gettimeofday().
+ struct timeval {
+ int64_t tv_sec; //!< seconds
+ int64_t tv_usec; //!< microseconds
+ };
+
+ //@{
+ /// For getrusage().
+ static const int RUSAGE_SELF = 0;
+ static const int RUSAGE_CHILDREN = -1;
+ static const int 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
+ /// memorty space. Used by stat(), fstat(), and lstat().
+ static void
+ copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
+ {
+ TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+ tgt->st_dev = host->st_dev;
+ tgt->st_ino = host->st_ino;
+ tgt->st_mode = host->st_mode;
+ tgt->st_nlink = host->st_nlink;
+ tgt->st_uid = host->st_uid;
+ tgt->st_gid = host->st_gid;
+ tgt->st_rdev = host->st_rdev;
+ tgt->st_size = host->st_size;
+ tgt->st_atimeX = host->st_atime;
+ tgt->st_mtimeX = host->st_mtime;
+ tgt->st_ctimeX = host->st_ctime;
+ tgt->st_blksize = host->st_blksize;
+ tgt->st_blocks = host->st_blocks;
+
+ tgt.copyOut(mem);
}
- return 0;
-}
+ /// The target system's hostname.
+ static const char *hostname;
+ /// Target uname() handler.
+ static int
+ unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-static
-int
-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", *(uint64_t*)fpcr);
- return 1;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 0;
-}
-
-
-static
-int
-fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = 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");
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
+ name.copyOut(xc->mem);
+ return 0;
+ }
- 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;
+ /// 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 int
+ 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 1;
+ }
+
+ default:
+ cerr << "osf_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
- 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;
+ /// Target osf_setsysinfo() handler.
+ static int
+ 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", *(uint64_t*)fpcr);
+ return 1;
+ }
+
+ default:
+ cerr << "osf_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
- default:
- warn("Unknown fcntl command %d\n", cmd);
return 0;
}
-}
-
-static SyscallDesc syscallDescs[];
-static const int Num_Syscall_Descs;
+ /// Target fnctl() handler.
+ static int
+ 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;
+ }
+ }
-static const int Max_Syscall_Desc;
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
-static
-void
-doSyscall(int callnum, Process *process, ExecContext *xc)
-{
- if (callnum < 0 || callnum > Max_Syscall_Desc) {
- fatal("Syscall %d out of range", callnum);
- }
+ /// Number of syscalls in syscallDescs[].
+ static const int Num_Syscall_Descs;
- SyscallDesc *desc = &syscallDescs[callnum];
+ /// Max supported syscall number.
+ static const int Max_Syscall_Desc;
- desc->doSyscall(callnum, process, xc);
-}
+ /// 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];
+ desc->doSyscall(callnum, process, xc);
+ }
}; // class Linux
// open(2) flags translation table
OpenFlagTransTable Linux::openFlagTable[] = {
- /* target flag */ /* host flag */
#ifdef _MSC_VER
{ Linux::TGT_O_RDONLY, _O_RDONLY },
{ Linux::TGT_O_WRONLY, _O_WRONLY },
@@ -406,7 +405,8 @@ OpenFlagTransTable Linux::openFlagTable[] = {
#endif /* _MSC_VER */
};
-const int Linux::NUM_OPEN_FLAGS = (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
+const int Linux::NUM_OPEN_FLAGS =
+ (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
const char *Linux::hostname = "m5.eecs.umich.edu";