summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2014-10-29 23:22:26 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2014-10-29 23:22:26 -0500
commit7a0bf814b6eb2db57f37977a0cca6c442f957d68 (patch)
treedf8247c4215a69446660d6f76c5f35a3b51b12e0
parent93c0307d418e08db609818f19f5d2b02d45e7465 (diff)
parent6ab4eddb9f5fbd30db0dccbef4a60c46b7053de3 (diff)
downloadgem5-7a0bf814b6eb2db57f37977a0cca6c442f957d68.tar.xz
automated merge
-rw-r--r--src/arch/alpha/linux/process.cc4
-rw-r--r--src/arch/arm/linux/process.cc4
-rw-r--r--src/arch/mips/linux/process.cc4
-rw-r--r--src/arch/power/linux/process.cc4
-rw-r--r--src/arch/sparc/linux/syscalls.cc8
-rw-r--r--src/arch/x86/linux/process.cc4
-rw-r--r--src/sim/Process.py8
-rw-r--r--src/sim/emul_driver.hh90
-rw-r--r--src/sim/process.cc30
-rw-r--r--src/sim/process.hh15
-rw-r--r--src/sim/syscall_emul.cc47
-rw-r--r--src/sim/syscall_emul.hh113
-rw-r--r--src/sim/syscall_emul_buf.hh168
-rw-r--r--src/sim/syscallreturn.hh15
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