From: Steve Reinhardt Date: Fri, 3 Jun 2005 20:19:34 +0000 (-0400) Subject: Additions/fixes for Tru64 syscall emulation. X-Git-Tag: m5_1.0_tutorial~39 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=22eccce34ba7d803d3f46ffeef80925a5e5ff2e3;p=gem5.git Additions/fixes for Tru64 syscall emulation. We can now run the SimpleScalar wupwise binary to completion on the test input. Didn't have time to do more testing, but I fixed a major problem w/getdirentries that should help a lot more programs run. arch/alpha/alpha_tru64_process.cc: Add truncate, ftruncate, statfs, and fstatfs. Add v4.x (pre-F64) stat, fstat, and lstat. Add setsysinfo (though all it does is provide more specific warning messages). Fix subtle but major bug in getdirentries. sim/syscall_emul.cc: sim/syscall_emul.hh: Add truncate, ftruncate, statfs, and fstatfs. --HG-- extra : convert_revision : 9037393d00dc49b0074a41603ea647587f5a9ec7 --- diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc index fe1bacc35..6fe4290e8 100644 --- a/arch/alpha/alpha_tru64_process.cc +++ b/arch/alpha/alpha_tru64_process.cc @@ -31,6 +31,7 @@ #include // for host open() flags #include #include +#include #include // for memset() #include @@ -71,6 +72,8 @@ class Tru64 { 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; //@} //@{ @@ -99,12 +102,10 @@ class Tru64 { /// 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. Backwards - /// compatibility with v4.x should be feasible by implementing - /// another set of stat functions using the old structure - /// definition and binding them to the old syscall numbers, but we - /// haven't done that yet. + /// 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 @@ -140,6 +141,79 @@ class Tru64 { }; + /// 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 { @@ -225,6 +299,11 @@ class Tru64 { 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 @@ -448,11 +527,89 @@ class Tru64 { /// 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(). + /// memory space. Used by stat(), fstat(), and lstat(). + template + static void + copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct ::stat *host) + { + TypedBufferArg 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); + } + + /// 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 + static void + copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, struct ::statfs *host) + { + TypedBufferArg tgt(addr); + + tgt->f_type = host->f_type; + tgt->f_bsize = host->f_bsize; + tgt->f_blocks = host->f_blocks; + tgt->f_bfree = host->f_bfree; + tgt->f_bavail = host->f_bavail; + tgt->f_files = host->f_files; + tgt->f_ffree = host->f_ffree; + memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid)); + + tgt.copyOut(mem); + } + + class F64 { + public: + static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + struct ::stat *host) + { + Tru64::copyOutStatBuf(mem, addr, host); + } + + static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + struct ::statfs *host) + { + Tru64::copyOutStatfsBuf(mem, addr, host); + } + }; + + class PreF64 { + public: + static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + struct ::stat *host) + { + Tru64::copyOutStatBuf(mem, addr, host); + } + + static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + struct ::statfs *host) + { + Tru64::copyOutStatfsBuf(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 - copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) + copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) { - TypedBufferArg tgt(addr); + TypedBufferArg tgt(addr); tgt->st_dev = host->st_dev; tgt->st_ino = host->st_ino; @@ -565,8 +722,28 @@ class Tru64 { } default: - cerr << "getsysinfo: unknown op " << op << endl; - abort(); + 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; } @@ -649,7 +826,7 @@ class Tru64 { char *host_buf_ptr = host_buf; char *host_buf_end = host_buf + host_result; while (host_buf_ptr < host_buf_end) { - struct dirent *host_dp = (struct dirent *)host_buf_ptr; + struct ::dirent *host_dp = (struct ::dirent *)host_buf_ptr; int namelen = strlen(host_dp->d_name); // Actual size includes padded string rounded up for alignment. @@ -1287,8 +1464,7 @@ class Tru64 { doSyscall(int callnum, Process *process, ExecContext *xc) { if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) { - cerr << "Syscall " << callnum << " out of range" << endl; - abort(); + fatal("Syscall %d out of range\n", callnum); } SyscallDesc *desc = @@ -1424,8 +1600,8 @@ SyscallDesc Tru64::syscallDescs[] = { /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), /* 65 */ SyscallDesc("mremap", unimplementedFunc), /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("pre_F64_stat", unimplementedFunc), - /* 68 */ SyscallDesc("pre_F64_lstat", unimplementedFunc), + /* 67 */ SyscallDesc("pre_F64_stat", statFunc), + /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc), /* 69 */ SyscallDesc("sbrk", unimplementedFunc), /* 70 */ SyscallDesc("sstk", unimplementedFunc), /* 71 */ SyscallDesc("mmap", mmapFunc), @@ -1448,7 +1624,7 @@ SyscallDesc Tru64::syscallDescs[] = { /* 88 */ SyscallDesc("sethostname", unimplementedFunc), /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("pre_F64_fstat", unimplementedFunc), + /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc), /* 92 */ SyscallDesc("fcntl", fcntlFunc), /* 93 */ SyscallDesc("select", unimplementedFunc), /* 94 */ SyscallDesc("poll", unimplementedFunc), @@ -1487,8 +1663,8 @@ SyscallDesc Tru64::syscallDescs[] = { /* 126 */ SyscallDesc("setreuid", unimplementedFunc), /* 127 */ SyscallDesc("setregid", unimplementedFunc), /* 128 */ SyscallDesc("rename", renameFunc), - /* 129 */ SyscallDesc("truncate", unimplementedFunc), - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 129 */ SyscallDesc("truncate", truncateFunc), + /* 130 */ SyscallDesc("ftruncate", ftruncateFunc), /* 131 */ SyscallDesc("flock", unimplementedFunc), /* 132 */ SyscallDesc("setgid", unimplementedFunc), /* 133 */ SyscallDesc("sendto", unimplementedFunc), @@ -1518,8 +1694,8 @@ SyscallDesc Tru64::syscallDescs[] = { /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc), /* 158 */ SyscallDesc("nfssvc", unimplementedFunc), /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc), - /* 160 */ SyscallDesc("pre_F64_statfs", unimplementedFunc), - /* 161 */ SyscallDesc("pre_F64_fstatfs", unimplementedFunc), + /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc), + /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc), /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), /* 163 */ SyscallDesc("async_daemon", unimplementedFunc), /* 164 */ SyscallDesc("getfh", unimplementedFunc), @@ -1582,11 +1758,11 @@ SyscallDesc Tru64::syscallDescs[] = { /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), /* 222 */ SyscallDesc("security", unimplementedFunc), /* 223 */ SyscallDesc("kloadcall", unimplementedFunc), - /* 224 */ SyscallDesc("stat", statFunc), - /* 225 */ SyscallDesc("lstat", lstatFunc), - /* 226 */ SyscallDesc("fstat", fstatFunc), - /* 227 */ SyscallDesc("statfs", unimplementedFunc), - /* 228 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 224 */ SyscallDesc("stat", statFunc), + /* 225 */ SyscallDesc("lstat", lstatFunc), + /* 226 */ SyscallDesc("fstat", fstatFunc), + /* 227 */ SyscallDesc("statfs", statfsFunc), + /* 228 */ SyscallDesc("fstatfs", fstatfsFunc), /* 229 */ SyscallDesc("getfsstat", unimplementedFunc), /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc), /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc), @@ -1615,7 +1791,7 @@ SyscallDesc Tru64::syscallDescs[] = { /* 254 */ SyscallDesc("sysfs", unimplementedFunc), /* 255 */ SyscallDesc("subsys_info", unimplementedFunc), /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc), - /* 257 */ SyscallDesc("setsysinfo", unimplementedFunc), + /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc), /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc), /* 259 */ SyscallDesc("swapctl", unimplementedFunc), /* 260 */ SyscallDesc("memcntl", unimplementedFunc), diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc index 22d62e4d1..13df2b7a2 100644 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@ -193,7 +193,7 @@ gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { - std::string path; + string path; if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) return (TheISA::IntReg)-EFAULT; @@ -205,17 +205,44 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { - std::string old_name; + string old_name; if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault) return -EFAULT; - std::string new_name; + string new_name; if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault) return -EFAULT; - int64_t result = rename(old_name.c_str(),new_name.c_str()); + int64_t result = rename(old_name.c_str(), new_name.c_str()); return (result == -1) ? -errno : result; } +SyscallReturn +truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +{ + string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + off_t length = xc->getSyscallArg(1); + + int result = truncate(path.c_str(), length); + return (result == -1) ? -errno : result; +} + +SyscallReturn +ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) +{ + int fd = process->sim_fd(xc->getSyscallArg(0)); + + if (fd < 0) + return -EBADF; + + off_t length = xc->getSyscallArg(1); + + int result = ftruncate(fd, length); + return (result == -1) ? -errno : result; +} diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index cc1692bfb..26d3b873c 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -158,46 +158,70 @@ class TypedBufferArg : public BaseBufferArg /// Handler for unimplemented syscalls that we haven't thought about. -SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Handler for unimplemented syscalls that we never intend to /// implement (signal handling, etc.) and should not affect the correct /// behavior of the program. Print a warning only if the appropriate /// trace flag is enabled. Return success to the target program. -SyscallReturn ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn ignoreFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target exit() handler: terminate simulation. -SyscallReturn exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn exitFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target getpagesize() handler. -SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target obreak() handler: set brk address. -SyscallReturn obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn obreakFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target close() handler. -SyscallReturn closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn closeFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target read() handler. -SyscallReturn readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn readFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target write() handler. -SyscallReturn writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn writeFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target lseek() handler. -SyscallReturn lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn lseekFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target munmap() handler. -SyscallReturn munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn munmapFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target gethostname() handler. -SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target unlink() handler. -SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn unlinkFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); /// Target rename() handler. -SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +SyscallReturn renameFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + + +/// Target truncate() handler. +SyscallReturn truncateFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + + +/// Target ftruncate() handler. +SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, + Process *p, 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. @@ -264,7 +288,8 @@ ioctlFunc(SyscallDesc *desc, int callnum, Process *process, return -ENOTTY; default: - fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", fd, req, xc->readPC()); + fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", + fd, req, xc->readPC()); } } @@ -282,7 +307,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, if (path == "/dev/sysdev0") { // This is a memory-mapped high-resolution timer device on Alpha. // We don't support it, so just punt. - DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << std::endl; + warn("Ignoring open(%s, ...)\n", path); return -ENOENT; } @@ -300,12 +325,14 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, // any target flags left? if (tgtFlags != 0) - std::cerr << "Syscall: open: cannot decode flags: " << tgtFlags << std::endl; + warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); #ifdef __CYGWIN32__ hostFlags |= O_BINARY; #endif + DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); + // open the file int fd = open(path.c_str(), hostFlags, mode); @@ -383,6 +410,52 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target statfs() handler. +template +SyscallReturn +statfsFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + std::string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + struct statfs hostBuf; + int result = statfs(path.c_str(), &hostBuf); + + if (result < 0) + return errno; + + OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); + + return 0; +} + + +/// Target fstatfs() handler. +template +SyscallReturn +fstatfsFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fd = process->sim_fd(xc->getSyscallArg(0)); + + if (fd < 0) + return -EBADF; + + struct statfs hostBuf; + int result = fstatfs(fd, &hostBuf); + + if (result < 0) + return errno; + + OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); + + return 0; +} + + /// Target mmap() handler. /// /// We don't really handle mmap(). If the target is mmaping an @@ -440,7 +513,8 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, break; default: - std::cerr << "getrlimitFunc: unimplemented resource " << resource << std::endl; + std::cerr << "getrlimitFunc: unimplemented resource " << resource + << std::endl; abort(); break; }