From 6523aad25c32f2443c48b114db4dab078bfb16d1 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 22 Oct 2014 15:59:57 -0500 Subject: [PATCH 1/6] sim: revert 6709bbcf564d The identifier SYS_getdents is not available on Mac OS X. Therefore, its use results in compilation failure. It seems there is no straight forward way to implement the system call getdents using readdir() or similar C functions. Hence the commit 6709bbcf564d is being rolled back. --- src/arch/alpha/linux/process.cc | 4 ++-- src/arch/arm/linux/process.cc | 4 ++-- src/arch/mips/linux/process.cc | 4 ++-- src/arch/power/linux/process.cc | 4 ++-- src/arch/sparc/linux/syscalls.cc | 8 +++---- src/arch/x86/linux/process.cc | 4 ++-- src/sim/syscall_emul.cc | 36 -------------------------------- src/sim/syscall_emul.hh | 8 ------- 8 files changed, 14 insertions(+), 58 deletions(-) diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index fab758f47..ebe06510d 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -431,7 +431,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 302 */ SyscallDesc("mount", unimplementedFunc), /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc), /* 304 */ SyscallDesc("swapoff", unimplementedFunc), - /* 305 */ SyscallDesc("getdents", getdentsFunc), + /* 305 */ SyscallDesc("getdents", unimplementedFunc), /* 306 */ SyscallDesc("create_module", unimplementedFunc), /* 307 */ SyscallDesc("init_module", unimplementedFunc), /* 308 */ SyscallDesc("delete_module", unimplementedFunc), @@ -503,7 +503,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 374 */ SyscallDesc("pivot_root", unimplementedFunc), /* 375 */ SyscallDesc("mincore", unimplementedFunc), /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), - /* 377 */ SyscallDesc("getdents64", getdents64Func), + /* 377 */ SyscallDesc("getdents64", unimplementedFunc), /* 378 */ SyscallDesc("gettid", unimplementedFunc), /* 379 */ SyscallDesc("readahead", unimplementedFunc), /* 380 */ SyscallDesc("security", unimplementedFunc), diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 7f53eaae8..faa39fd34 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -260,7 +260,7 @@ static SyscallDesc syscallDescs32[] = { /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), /* 140 */ SyscallDesc("llseek", _llseekFunc), - /* 141 */ SyscallDesc("getdents", getdentsFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), /* 142 */ SyscallDesc("newselect", unimplementedFunc), /* 143 */ SyscallDesc("flock", unimplementedFunc), /* 144 */ SyscallDesc("msync", unimplementedFunc), @@ -336,7 +336,7 @@ static SyscallDesc syscallDescs32[] = { /* 214 */ SyscallDesc("setgid", unimplementedFunc), /* 215 */ SyscallDesc("setfsuid", unimplementedFunc), /* 216 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 217 */ SyscallDesc("getdents64", getdents64Func), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), /* 218 */ SyscallDesc("pivot_root", unimplementedFunc), /* 219 */ SyscallDesc("mincore", unimplementedFunc), /* 220 */ SyscallDesc("madvise", unimplementedFunc), diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 375288290..ef21179e5 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -277,7 +277,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), /* 140 */ SyscallDesc("llseek", unimplementedFunc), - /* 141 */ SyscallDesc("getdents", getdentsFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), /* 142 */ SyscallDesc("newselect", unimplementedFunc), /* 143 */ SyscallDesc("flock", unimplementedFunc), /* 144 */ SyscallDesc("msync", unimplementedFunc), @@ -355,7 +355,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 216 */ SyscallDesc("pivot_root", unimplementedFunc), /* 217 */ SyscallDesc("mincore", unimplementedFunc), /* 218 */ SyscallDesc("madvise", unimplementedFunc), - /* 219 */ SyscallDesc("getdents64", getdents64Func), + /* 219 */ SyscallDesc("getdents64", unimplementedFunc), /* 220 */ SyscallDesc("fcntl64", fcntl64Func), /* 221 */ SyscallDesc("reserved#221", unimplementedFunc), /* 222 */ SyscallDesc("gettid", unimplementedFunc), diff --git a/src/arch/power/linux/process.cc b/src/arch/power/linux/process.cc index eef334d01..b00e02a87 100644 --- a/src/arch/power/linux/process.cc +++ b/src/arch/power/linux/process.cc @@ -205,7 +205,7 @@ SyscallDesc PowerLinuxProcess::syscallDescs[] = { /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), /* 140 */ SyscallDesc("llseek", _llseekFunc), - /* 141 */ SyscallDesc("getdents", getdentsFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), /* 142 */ SyscallDesc("newselect", unimplementedFunc), /* 143 */ SyscallDesc("flock", unimplementedFunc), /* 144 */ SyscallDesc("msync", unimplementedFunc), @@ -281,7 +281,7 @@ SyscallDesc PowerLinuxProcess::syscallDescs[] = { /* 214 */ SyscallDesc("setgid", unimplementedFunc), /* 215 */ SyscallDesc("setfsuid", unimplementedFunc), /* 216 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 217 */ SyscallDesc("getdents64", getdents64Func), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), /* 218 */ SyscallDesc("pivot_root", unimplementedFunc), /* 219 */ SyscallDesc("mincore", unimplementedFunc), /* 220 */ SyscallDesc("madvise", unimplementedFunc), diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 232ff7140..66e8e1fe1 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -241,7 +241,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), /* 153 */ SyscallDesc("poll", unimplementedFunc), - /* 154 */ SyscallDesc("getdents64", getdents64Func), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), /* 157 */ SyscallDesc("statfs", unimplementedFunc), @@ -261,7 +261,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), // 32 bit /* 172 */ SyscallDesc("getxattr", unimplementedFunc), /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), - /* 174 */ SyscallDesc("getdents", getdentsFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), /* 175 */ SyscallDesc("setsid", unimplementedFunc), /* 176 */ SyscallDesc("fchdir", unimplementedFunc), /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), // 32 bit @@ -547,7 +547,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), /* 153 */ SyscallDesc("poll", unimplementedFunc), - /* 154 */ SyscallDesc("getdents64", getdents64Func), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), /* 157 */ SyscallDesc("statfs", unimplementedFunc), @@ -567,7 +567,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), /* 172 */ SyscallDesc("getxattr", unimplementedFunc), /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), - /* 174 */ SyscallDesc("getdents", getdentsFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), /* 175 */ SyscallDesc("setsid", unimplementedFunc), /* 176 */ SyscallDesc("fchdir", unimplementedFunc), /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 047cce351..297688323 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -296,7 +296,7 @@ static SyscallDesc syscallDescs64[] = { /* 75 */ SyscallDesc("fdatasync", unimplementedFunc), /* 76 */ SyscallDesc("truncate", truncateFunc), /* 77 */ SyscallDesc("ftruncate", ftruncateFunc), - /* 78 */ SyscallDesc("getdents", getdentsFunc), + /* 78 */ SyscallDesc("getdents", unimplementedFunc), /* 79 */ SyscallDesc("getcwd", getcwdFunc), /* 80 */ SyscallDesc("chdir", unimplementedFunc), /* 81 */ SyscallDesc("fchdir", unimplementedFunc), @@ -435,7 +435,7 @@ static SyscallDesc syscallDescs64[] = { /* 214 */ SyscallDesc("epoll_ctl_old", unimplementedFunc), /* 215 */ SyscallDesc("epoll_wait_old", unimplementedFunc), /* 216 */ SyscallDesc("remap_file_pages", unimplementedFunc), - /* 217 */ SyscallDesc("getdents64", getdents64Func), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), /* 218 */ SyscallDesc("set_tid_address", unimplementedFunc), /* 219 */ SyscallDesc("restart_syscall", unimplementedFunc), /* 220 */ SyscallDesc("semtimedop", unimplementedFunc), diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 7eeacd319..d8df891dd 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -868,41 +867,6 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } } -SyscallReturn -getdentsFunc(SyscallDesc *desc, int num, LiveProcess *p, - ThreadContext *tc) -{ - int index = 0; - int fd = p->sim_fd(p->getSyscallArg(tc, index)); - Addr bufPtr = p->getSyscallArg(tc, index); - int nbytes = p->getSyscallArg(tc, index); - BufferArg bufArg(bufPtr, nbytes); - - int bytes_read = syscall(SYS_getdents, fd, bufArg.bufferPtr(), nbytes); - - if (bytes_read != -1) - bufArg.copyOut(tc->getMemProxy()); - - return bytes_read; -} - -SyscallReturn -getdents64Func(SyscallDesc *desc, int num, LiveProcess *p, - ThreadContext *tc) -{ - int index = 0; - int fd = p->sim_fd(p->getSyscallArg(tc, index)); - Addr bufPtr = p->getSyscallArg(tc, index); - int nbytes = p->getSyscallArg(tc, index); - BufferArg bufArg(bufPtr, nbytes); - - int bytes_read = syscall(SYS_getdents64, fd, bufArg.bufferPtr(), nbytes); - - if (bytes_read != -1) - bufArg.copyOut(tc->getMemProxy()); - - return bytes_read; -} SyscallReturn accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc, int index) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index f793bc41f..dff34982d 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -439,14 +439,6 @@ futexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } -/// Target getdents() handler. -SyscallReturn getdentsFunc(SyscallDesc *desc, int num, - LiveProcess *process, ThreadContext *tc); - -/// Target getdents64() handler. -SyscallReturn getdents64Func(SyscallDesc *desc, int num, - LiveProcess *process, ThreadContext *tc); - /// Pseudo Funcs - These functions use a different return convension, /// returning a second value in a register other than the normal return register From 44ec1d212499246be3cef40ce7c96a3f65286153 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 22 Oct 2014 15:53:34 -0700 Subject: [PATCH 2/6] syscall_emul: add EmulatedDriver object Fake SE-mode device drivers can now be added by deriving from this abstract object. --- src/sim/Process.py | 8 ++++ src/sim/emul_driver.hh | 90 +++++++++++++++++++++++++++++++++++++++++ src/sim/process.cc | 19 ++++++++- src/sim/process.hh | 15 ++++++- src/sim/syscall_emul.hh | 36 +++++++++++++---- 5 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 src/sim/emul_driver.hh diff --git a/src/sim/Process.py b/src/sim/Process.py index 6f2322805..7e5f75363 100644 --- a/src/sim/Process.py +++ b/src/sim/Process.py @@ -46,6 +46,12 @@ class Process(SimObject): def export_methods(cls, code): code('bool map(Addr vaddr, Addr paddr, int size);') +class EmulatedDriver(SimObject): + type = 'EmulatedDriver' + cxx_header = "sim/emul_driver.hh" + abstract = True + filename = Param.String("device file name (under /dev)") + class LiveProcess(Process): type = 'LiveProcess' cxx_header = "sim/process.hh" @@ -60,3 +66,5 @@ class LiveProcess(Process): pid = Param.Int(100, 'process id') ppid = Param.Int(99, 'parent process id') simpoint = Param.UInt64(0, 'simulation point at which to start simulation') + drivers = VectorParam.EmulatedDriver([], 'Available emulated drivers') + diff --git a/src/sim/emul_driver.hh b/src/sim/emul_driver.hh new file mode 100644 index 000000000..778fc6461 --- /dev/null +++ b/src/sim/emul_driver.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Advanced Micro Devices, Inc. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Steve Reinhardt + */ + +#ifndef __SIM_EMUL_DRIVER_HH +#define __SIM_EMUL_DRIVER_HH + +#include + +#include "params/EmulatedDriver.hh" +#include "sim/sim_object.hh" + +class LiveProcess; +class ThreadContext; + +/** + * EmulatedDriver is an abstract base class for fake SE-mode device drivers. + * + * Specific drivers that allow applications to communicate with simulated + * hardware inside gem5 can be created by deriving from this class and + * overriding the abstract virtual methods. + * + * Currently only open() and ioctl() calls are supported, but other calls + * (e.g., read(), write(), mmap()) could be added as needed. + */ +class EmulatedDriver : public SimObject +{ + protected: + /** + * filename for opening this driver (under /dev) + */ + const std::string &filename; + + public: + EmulatedDriver(EmulatedDriverParams *p) + : SimObject(p), filename(p->filename) + { + } + + /** + * Check for a match with this driver's filename. + */ + bool match(const std::string &s) const { return (s == filename); } + + /** + * Abstract method, invoked when the user program calls open() on + * the device driver. The parameters are the same as those passed + * to openFunc() (q.v.). + * @return A newly allocated target fd, or -1 on error. + */ + virtual int open(LiveProcess *p, ThreadContext *tc, + int mode, int flags) = 0; + + /** + * Abstract method, invoked when the user program calls ioctl() on + * the file descriptor returned by a previous open(). The parameters + * are the same as those passed in to ioctlFunc() (q.v.). + * @return The return code for the ioctl, or the negation of the errno + * (see the SyscallReturn class). + */ + virtual int ioctl(LiveProcess *p, ThreadContext *tc, unsigned req) = 0; +}; + +#endif // __SIM_EMUL_DRIVER_HH diff --git a/src/sim/process.cc b/src/sim/process.cc index 913e9298d..15dc8c3e8 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -278,7 +278,7 @@ Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe) // find first free target fd for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) { Process::FdMap *fdo = &fd_map[free_fd]; - if (fdo->fd == -1) { + if (fdo->fd == -1 && fdo->driver == NULL) { fdo->fd = sim_fd; fdo->filename = filename; fdo->mode = mode; @@ -309,6 +309,7 @@ Process::free_fd(int tgt_fd) fdo->flags = 0; fdo->isPipe = false; fdo->readPipeSource = 0; + fdo->driver = NULL; } @@ -567,7 +568,8 @@ Process::map(Addr vaddr, Addr paddr, int size) LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile) : Process(params), objFile(_objFile), - argv(params->cmd), envp(params->env), cwd(params->cwd) + argv(params->cmd), envp(params->env), cwd(params->cwd), + drivers(params->drivers) { __uid = params->uid; __euid = params->euid; @@ -608,6 +610,19 @@ LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) return getSyscallArg(tc, i); } + +EmulatedDriver * +LiveProcess::findDriver(std::string filename) +{ + for (EmulatedDriver *d : drivers) { + if (d->match(filename)) + return d; + } + + return NULL; +} + + LiveProcess * LiveProcess::create(LiveProcessParams * params) { diff --git a/src/sim/process.hh b/src/sim/process.hh index 03380acf7..6e26bb8bd 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -50,6 +50,7 @@ struct LiveProcessParams; class SyscallDesc; class System; class ThreadContext; +class EmulatedDriver; template struct AuxVector @@ -139,10 +140,11 @@ class Process : public SimObject bool isPipe; int readPipeSource; uint64_t fileOffset; + EmulatedDriver *driver; FdMap() : fd(-1), filename("NULL"), mode(0), flags(0), - isPipe(false), readPipeSource(0), fileOffset(0) + isPipe(false), readPipeSource(0), fileOffset(0), driver(NULL) { } void serialize(std::ostream &os); @@ -256,6 +258,9 @@ class LiveProcess : public Process uint64_t __pid; uint64_t __ppid; + // Emulated drivers available to this process + std::vector drivers; + public: enum AuxiliaryVectorType { @@ -325,6 +330,14 @@ class LiveProcess : public Process virtual SyscallDesc *getDesc(int callnum) = 0; + /** + * Find an emulated device driver. + * + * @param filename Name of the device (under /dev) + * @return Pointer to driver object if found, else NULL + */ + EmulatedDriver *findDriver(std::string filename); + // this function is used to create the LiveProcess object, since // we can't tell which subclass of LiveProcess to use until we // open and look at the object file. diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index dff34982d..1c84e9f48 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -77,6 +77,7 @@ #include "mem/page_table.hh" #include "mem/se_translating_port_proxy.hh" #include "sim/byteswap.hh" +#include "sim/emul_driver.hh" #include "sim/process.hh" #include "sim/syscallreturn.hh" #include "sim/system.hh" @@ -604,11 +605,17 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); - if (fd < 0 || process->sim_fd(fd) < 0) { + Process::FdMap *fdObj = process->sim_fd_obj(fd); + + if (fdObj == NULL) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; } + if (fdObj->driver != NULL) { + return fdObj->driver->ioctl(process, tc, req); + } + if (OS::isTtyReq(req)) { return -ENOTTY; } @@ -629,13 +636,6 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, process->getSyscallArg(tc, index))) return -EFAULT; - if (path == "/dev/sysdev0") { - // This is a memory-mapped high-resolution timer device on Alpha. - // We don't support it, so just punt. - warn("Ignoring open(%s, ...)\n", path); - return -ENOENT; - } - int tgtFlags = process->getSyscallArg(tc, index); int mode = process->getSyscallArg(tc, index); int hostFlags = 0; @@ -661,6 +661,26 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); + if (startswith(path, "/dev/")) { + std::string filename = path.substr(strlen("/dev/")); + if (filename == "sysdev0") { + // This is a memory-mapped high-resolution timer device on Alpha. + // We don't support it, so just punt. + warn("Ignoring open(%s, ...)\n", path); + return -ENOENT; + } + + EmulatedDriver *drv = process->findDriver(filename); + if (drv != NULL) { + // the driver's open method will allocate a fd from the + // process if necessary. + return drv->open(process, tc, mode, hostFlags); + } + + // fall through here for pass through to host devices, such as + // /dev/zero + } + int fd; int local_errno; if (startswith(path, "/proc/") || startswith(path, "/system/") || From 44af2c6a6913d35a2c34bd928dbfdef3c16dcaf9 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 22 Oct 2014 15:53:34 -0700 Subject: [PATCH 3/6] syscall_emul: Put BufferArg classes in a separate header. Move the BufferArg classes that support syscall buffer args (i.e., pointers into simulated user space) out of syscall_emul.hh and into a new header syscall_emul_buf.hh so they are accessible to emulated driver implementations. Take the opportunity to add some comments as well. --- src/sim/syscall_emul.hh | 69 +-------------- src/sim/syscall_emul_buf.hh | 168 ++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+), 68 deletions(-) create mode 100644 src/sim/syscall_emul_buf.hh diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 1c84e9f48..a4f9b238e 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -75,10 +75,10 @@ #include "cpu/thread_context.hh" #include "debug/SyscallVerbose.hh" #include "mem/page_table.hh" -#include "mem/se_translating_port_proxy.hh" #include "sim/byteswap.hh" #include "sim/emul_driver.hh" #include "sim/process.hh" +#include "sim/syscall_emul_buf.hh" #include "sim/syscallreturn.hh" #include "sim/system.hh" @@ -117,73 +117,6 @@ class SyscallDesc { }; -class BaseBufferArg { - - public: - - BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) - { - bufPtr = new uint8_t[size]; - // clear out buffer: in case we only partially populate this, - // and then do a copyOut(), we want to make sure we don't - // introduce any random junk into the simulated address space - memset(bufPtr, 0, size); - } - - virtual ~BaseBufferArg() { delete [] bufPtr; } - - // - // copy data into simulator space (read from target memory) - // - virtual bool copyIn(SETranslatingPortProxy &memproxy) - { - memproxy.readBlob(addr, bufPtr, size); - return true; // no EFAULT detection for now - } - - // - // copy data out of simulator space (write to target memory) - // - virtual bool copyOut(SETranslatingPortProxy &memproxy) - { - memproxy.writeBlob(addr, bufPtr, size); - return true; // no EFAULT detection for now - } - - protected: - Addr addr; - int size; - uint8_t *bufPtr; -}; - - -class BufferArg : public BaseBufferArg -{ - public: - BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } - void *bufferPtr() { return bufPtr; } -}; - -template -class TypedBufferArg : public BaseBufferArg -{ - public: - // user can optionally specify a specific number of bytes to - // allocate to deal with those structs that have variable-size - // arrays at the end - TypedBufferArg(Addr _addr, int _size = sizeof(T)) - : BaseBufferArg(_addr, _size) - { } - - // type case - operator T*() { return (T *)bufPtr; } - - // dereference operators - T &operator*() { return *((T *)bufPtr); } - T* operator->() { return (T *)bufPtr; } - T &operator[](int i) { return ((T *)bufPtr)[i]; } -}; - ////////////////////////////////////////////////////////////////////// // // The following emulation functions are generic enough that they diff --git a/src/sim/syscall_emul_buf.hh b/src/sim/syscall_emul_buf.hh new file mode 100644 index 000000000..cbd10f2f6 --- /dev/null +++ b/src/sim/syscall_emul_buf.hh @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + */ + +#ifndef __SIM_SYSCALL_EMUL_BUF_HH__ +#define __SIM_SYSCALL_EMUL_BUF_HH__ + +/// +/// @file syscall_emul_buf.hh +/// +/// This file defines buffer classes used to handle pointer arguments +/// in emulated syscalls. + +#include + +#include "base/types.hh" +#include "mem/se_translating_port_proxy.hh" + +/** + * Base class for BufferArg and TypedBufferArg, Not intended to be + * used directly. + * + * The BufferArg classes represent buffers in target user space that + * are passed by reference to an (emulated) system call. Each + * instance provides an internal (simulator-space) buffer of the + * appropriate size and tracks the user-space address. The copyIn() + * and copyOut() methods copy the user-space buffer to and from the + * simulator-space buffer, respectively. + */ +class BaseBufferArg { + + public: + + /** + * Allocate a buffer of size 'size' representing the memory at + * target address 'addr'. + */ + BaseBufferArg(Addr _addr, int _size) + : addr(_addr), size(_size), bufPtr(new uint8_t[size]) + { + // clear out buffer: in case we only partially populate this, + // and then do a copyOut(), we want to make sure we don't + // introduce any random junk into the simulated address space + memset(bufPtr, 0, size); + } + + virtual ~BaseBufferArg() { delete [] bufPtr; } + + /** + * copy data into simulator space (read from target memory) + */ + virtual bool copyIn(SETranslatingPortProxy &memproxy) + { + memproxy.readBlob(addr, bufPtr, size); + return true; // no EFAULT detection for now + } + + /** + * copy data out of simulator space (write to target memory) + */ + virtual bool copyOut(SETranslatingPortProxy &memproxy) + { + memproxy.writeBlob(addr, bufPtr, size); + return true; // no EFAULT detection for now + } + + protected: + const Addr addr; ///< address of buffer in target address space + const int size; ///< buffer size + uint8_t * const bufPtr; ///< pointer to buffer in simulator space +}; + +/** + * BufferArg represents an untyped buffer in target user space that is + * passed by reference to an (emulated) system call. + */ +class BufferArg : public BaseBufferArg +{ + public: + /** + * Allocate a buffer of size 'size' representing the memory at + * target address 'addr'. + */ + BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } + + /** + * Return a pointer to the internal simulator-space buffer. + */ + void *bufferPtr() { return bufPtr; } +}; + +/** + * TypedBufferArg is a class template; instances of this template + * represent typed buffers in target user space that are passed by + * reference to an (emulated) system call. + * + * This template provides operator overloads for convenience, allowing + * for example the use of '->' to reference fields within a struct + * type. + */ +template +class TypedBufferArg : public BaseBufferArg +{ + public: + /** + * Allocate a buffer of type T representing the memory at target + * address 'addr'. The user can optionally specify a specific + * number of bytes to allocate to deal with structs that have + * variable-size arrays at the end. + */ + TypedBufferArg(Addr _addr, int _size = sizeof(T)) + : BaseBufferArg(_addr, _size) + { } + + /** + * Convert TypedBufferArg to a pointer to T that points to the + * internal buffer. + */ + operator T*() { return (T *)bufPtr; } + + /** + * Convert TypedBufferArg to a reference to T that references the + * internal buffer value. + */ + T &operator*() { return *((T *)bufPtr); } + + + /** + * Enable the use of '->' to reference fields where T is a struct + * type. + */ + T* operator->() { return (T *)bufPtr; } + + /** + * Enable the use of '[]' to reference fields where T is an array + * type. + */ + T &operator[](int i) { return ((T *)bufPtr)[i]; } +}; + + +#endif // __SIM_SYSCALL_EMUL_BUF_HH__ From df7f0892ed5f4522a4582aaed7e49622e3a33d9f Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 22 Oct 2014 15:53:34 -0700 Subject: [PATCH 4/6] syscall_emul: devirtualize BaseBufferArg methods Not clear why they were marked virtual to begin with, but that doesn't appear to be necessary. --- src/sim/syscall_emul_buf.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sim/syscall_emul_buf.hh b/src/sim/syscall_emul_buf.hh index cbd10f2f6..e930846be 100644 --- a/src/sim/syscall_emul_buf.hh +++ b/src/sim/syscall_emul_buf.hh @@ -70,12 +70,12 @@ class BaseBufferArg { memset(bufPtr, 0, size); } - virtual ~BaseBufferArg() { delete [] bufPtr; } + ~BaseBufferArg() { delete [] bufPtr; } /** * copy data into simulator space (read from target memory) */ - virtual bool copyIn(SETranslatingPortProxy &memproxy) + bool copyIn(SETranslatingPortProxy &memproxy) { memproxy.readBlob(addr, bufPtr, size); return true; // no EFAULT detection for now @@ -84,7 +84,7 @@ class BaseBufferArg { /** * copy data out of simulator space (write to target memory) */ - virtual bool copyOut(SETranslatingPortProxy &memproxy) + bool copyOut(SETranslatingPortProxy &memproxy) { memproxy.writeBlob(addr, bufPtr, size); return true; // no EFAULT detection for now From 9ac7f14fc021075af458404096e76225b1ea59df Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 22 Oct 2014 15:53:34 -0700 Subject: [PATCH 5/6] syscall_emul: minor style fix to LiveProcess constructor --- src/sim/process.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/sim/process.cc b/src/sim/process.cc index 15dc8c3e8..d1fb22029 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -566,17 +566,14 @@ Process::map(Addr vaddr, Addr paddr, int size) //////////////////////////////////////////////////////////////////////// -LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile) +LiveProcess::LiveProcess(LiveProcessParams *params, ObjectFile *_objFile) : Process(params), objFile(_objFile), argv(params->cmd), envp(params->env), cwd(params->cwd), + __uid(params->uid), __euid(params->euid), + __gid(params->gid), __egid(params->egid), + __pid(params->pid), __ppid(params->ppid), drivers(params->drivers) { - __uid = params->uid; - __euid = params->euid; - __gid = params->gid; - __egid = params->egid; - __pid = params->pid; - __ppid = params->ppid; // load up symbols, if any... these may be used for debugging or // profiling. From 6ab4eddb9f5fbd30db0dccbef4a60c46b7053de3 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 2 Sep 2014 16:07:50 -0500 Subject: [PATCH 6/6] syscall_emul: add retry flag to SyscallReturn This hook allows blocking emulated system calls to indicate that they would block, but return control to the simulator so that the simulation does not hang. The actual retry functionality requires additional support, to be provided in a future changeset. --- src/sim/syscall_emul.cc | 11 ++++++++--- src/sim/syscallreturn.hh | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index d8df891dd..cb592e338 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -71,10 +71,15 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); - DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", - curTick(), tc->getCpuPtr()->name(), name, retval.encodedValue()); + if (retval.needsRetry()) { + DPRINTFS(SyscallVerbose, tc->getCpuPtr(), "syscall %s needs retry\n", + name); + } else { + DPRINTFS(SyscallVerbose, tc->getCpuPtr(), "syscall %s returns %d\n", + name, retval.encodedValue()); + } - if (!(flags & SyscallDesc::SuppressReturnValue)) + if (!(flags & SyscallDesc::SuppressReturnValue) && !retval.needsRetry()) process->setSyscallReturn(tc, retval); } diff --git a/src/sim/syscallreturn.hh b/src/sim/syscallreturn.hh index 547d76610..fdd740775 100644 --- a/src/sim/syscallreturn.hh +++ b/src/sim/syscallreturn.hh @@ -64,9 +64,17 @@ class SyscallReturn /// value is expected, e.g., as the return value from a system /// call emulation function ('return 0;' or 'return -EFAULT;'). SyscallReturn(int64_t v) - : value(v) + : value(v), retryFlag(false) {} + /// Pseudo-constructor to create an instance with the retry flag set. + static SyscallReturn retry() + { + SyscallReturn s(0); + s.retryFlag = true; + return s; + } + ~SyscallReturn() {} /// Was the system call successful? @@ -75,6 +83,9 @@ class SyscallReturn return (value >= 0 || value <= -4096); } + /// Does the syscall need to be retried? + bool needsRetry() const { return retryFlag; } + /// The return value int64_t returnValue() const { @@ -98,6 +109,8 @@ class SyscallReturn private: int64_t value; + + bool retryFlag; }; #endif