cpu: Fix retry bug in MinorCPU LSQ
[gem5.git] / src / sim / syscall_emul.hh
index dff34982d75f56ee2fb75aa27f4e8f5a2ad3017e..cc430b9492b1c881219f613077887e5bed856594 100644 (file)
 #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
@@ -261,6 +195,9 @@ SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
                            LiveProcess *p, ThreadContext *tc);
 
 /// Target unlink() handler.
+SyscallReturn unlinkHelper(SyscallDesc *desc, int num,
+                           LiveProcess *p, ThreadContext *tc,
+                           int index);
 SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
                          LiveProcess *p, ThreadContext *tc);
 
@@ -604,11 +541,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 +572,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 +597,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/") ||
@@ -702,6 +658,20 @@ openatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     return openFunc<OS>(desc, callnum, process, tc, 1);
 }
 
+/// Target unlinkat() handler.
+template <class OS>
+SyscallReturn
+unlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+             ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
+
+    return unlinkHelper(desc, callnum, process, tc, 1);
+}
+
 /// Target facessat() handler
 template <class OS>
 SyscallReturn
@@ -1185,7 +1155,7 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    return 0;
+    return result;
 }