diff options
-rw-r--r-- | src/arch/alpha/linux/process.cc | 4 | ||||
-rw-r--r-- | src/arch/arm/linux/process.cc | 4 | ||||
-rw-r--r-- | src/arch/mips/linux/process.cc | 4 | ||||
-rw-r--r-- | src/arch/power/linux/process.cc | 4 | ||||
-rw-r--r-- | src/arch/sparc/linux/syscalls.cc | 8 | ||||
-rw-r--r-- | src/arch/x86/linux/process.cc | 4 | ||||
-rw-r--r-- | src/sim/Process.py | 8 | ||||
-rw-r--r-- | src/sim/emul_driver.hh | 90 | ||||
-rw-r--r-- | src/sim/process.cc | 30 | ||||
-rw-r--r-- | src/sim/process.hh | 15 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 47 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 113 | ||||
-rw-r--r-- | src/sim/syscall_emul_buf.hh | 168 | ||||
-rw-r--r-- | src/sim/syscallreturn.hh | 15 |
14 files changed, 366 insertions, 148 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/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 <string> + +#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..d1fb22029 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; } @@ -565,16 +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) + 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. @@ -608,6 +607,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<class IntType> 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<EmulatedDriver *> 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.cc b/src/sim/syscall_emul.cc index 7eeacd319..cb592e338 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -31,7 +31,6 @@ #include <fcntl.h> #include <unistd.h> -#include <sys/syscall.h> #include <cstdio> #include <iostream> @@ -72,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); } @@ -869,41 +873,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..a4f9b238e 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -75,9 +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" @@ -116,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 T> -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 @@ -439,14 +373,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 @@ -612,11 +538,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; } @@ -637,13 +569,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; @@ -669,6 +594,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/") || diff --git a/src/sim/syscall_emul_buf.hh b/src/sim/syscall_emul_buf.hh new file mode 100644 index 000000000..e930846be --- /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 <cstring> + +#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); + } + + ~BaseBufferArg() { delete [] bufPtr; } + + /** + * copy data into simulator space (read from target memory) + */ + 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) + */ + 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 T> +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<T> to a pointer to T that points to the + * internal buffer. + */ + operator T*() { return (T *)bufPtr; } + + /** + * Convert TypedBufferArg<T> 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__ 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 |