Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/32254 )

Change subject: wip
......................................................................

wip

Change-Id: If79ce0733a7a61274a818e39ecb9cf383cc4e8ba
---
M src/arch/arm/aapcs32.hh
M src/arch/sparc/linux/syscalls.cc
M src/arch/x86/linux/process.cc
M src/kern/linux/events.hh
M src/sim/proxy_ptr.hh
M src/sim/syscall_emul.cc
M src/sim/syscall_emul.hh
7 files changed, 373 insertions(+), 357 deletions(-)



diff --git a/src/arch/arm/aapcs32.hh b/src/arch/arm/aapcs32.hh
index 01663ff..7f40bd3 100644
--- a/src/arch/arm/aapcs32.hh
+++ b/src/arch/arm/aapcs32.hh
@@ -37,6 +37,7 @@
 #include "arch/arm/utility.hh"
 #include "base/intmath.hh"
 #include "cpu/thread_context.hh"
+#include "mem/port_proxy.hh"
 #include "sim/guest_abi.hh"
 #include "sim/proxy_ptr.hh"

diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc
index 304f2cf..32f6ef3 100644
--- a/src/arch/sparc/linux/syscalls.cc
+++ b/src/arch/sparc/linux/syscalls.cc
@@ -27,6 +27,7 @@
  */

 #include "arch/sparc/linux/process.hh"
+#include "sim/proxy_ptr.hh"
 #include "sim/syscall_desc.hh"
 #include "sim/syscall_emul.hh"

@@ -53,28 +54,19 @@

 SyscallReturn
 getresuidFunc(SyscallDesc *desc, ThreadContext *tc,
-              Addr ruid, Addr euid, Addr suid)
+ VPtr<uint64_t> ruid, VPtr<uint64_t> euid, VPtr<uint64_t> suid)
 {
     const uint64_t id = htobe(100);
     // Handle the EFAULT case
     // Set the ruid
-    if (ruid) {
-        BufferArg ruidBuff(ruid, sizeof(uint64_t));
-        memcpy(ruidBuff.bufferPtr(), &id, sizeof(uint64_t));
-        ruidBuff.copyOut(tc->getVirtProxy());
-    }
+    if (ruid)
+        *ruid = id;
     // Set the euid
-    if (euid) {
-        BufferArg euidBuff(euid, sizeof(uint64_t));
-        memcpy(euidBuff.bufferPtr(), &id, sizeof(uint64_t));
-        euidBuff.copyOut(tc->getVirtProxy());
-    }
+    if (euid)
+        *euid = id;
     // Set the suid
-    if (suid) {
-        BufferArg suidBuff(suid, sizeof(uint64_t));
-        memcpy(suidBuff.bufferPtr(), &id, sizeof(uint64_t));
-        suidBuff.copyOut(tc->getVirtProxy());
-    }
+    if (suid)
+        *suid = id;
     return 0;
 }

diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc
index 9460a4b..97fb3e3 100644
--- a/src/arch/x86/linux/process.cc
+++ b/src/arch/x86/linux/process.cc
@@ -178,12 +178,8 @@

     assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86p->gdtSize());

-    TypedBufferArg<uint64_t>
-        gdt(x86p->gdtStart() + minTLSEntry * sizeof(uint64_t),
-            numTLSEntries * sizeof(uint64_t));
-
-    if (!gdt.copyIn(tc->getVirtProxy()))
-        panic("Failed to copy in GDT for %s.\n", desc->name());
+    VBuf<uint64_t> gdt(x86p->gdtStart() + minTLSEntry * sizeof(uint64_t),
+                       numTLSEntries, tc);

     if (userDesc->entry_number == (uint32_t)(-1)) {
         // Find a free TLS entry.
@@ -234,9 +230,6 @@

     gdt[index] = (uint64_t)segDesc;

-    if (!gdt.copyOut(tc->getVirtProxy()))
-        panic("Failed to copy out GDT for %s.\n", desc->name());
-
     return 0;
 }

diff --git a/src/kern/linux/events.hh b/src/kern/linux/events.hh
index c5a297b..2ca97a4 100644
--- a/src/kern/linux/events.hh
+++ b/src/kern/linux/events.hh
@@ -48,6 +48,7 @@
 #include "debug/DebugPrintf.hh"
 #include "kern/linux/printk.hh"
 #include "kern/system_events.hh"
+#include "mem/se_translating_port_proxy.hh"
 #include "sim/guest_abi.hh"

 class ThreadContext;
diff --git a/src/sim/proxy_ptr.hh b/src/sim/proxy_ptr.hh
index a59bbff..0f481c1 100644
--- a/src/sim/proxy_ptr.hh
+++ b/src/sim/proxy_ptr.hh
@@ -85,6 +85,13 @@
     }

     void
+    discard()
+    {
+        markClean();
+        load();
+    }
+
+    void
     load()
     {
         panic_if(isDirty(), "Overwriting dirty ProxyPtr.");
@@ -265,6 +272,13 @@
         this->buffer->flush(force);
     }

+    void
+    discard()
+    {
+        if (this->buffer)
+            this->buffer->discard();
+    }
+
     template <typename A>
     typename std::enable_if<std::is_integral<A>::value, PP>::type
     operator + (A a) const
@@ -364,11 +378,158 @@
     return os;
 }

+template <typename T, typename Proxy>
+class ConstProxyBuf
+{
+  protected:
+    ProxyPtrBuffer<Proxy> buffer;
+
+    Addr _count;
+
+    void
+    boundsCheck(int i)
+    {
+        panic_if(i < 0 || i >= this->count(),
+                "Out of bounds access in ProxyBuf.");
+    }
+
+  public:
+    using Type = T;
+
+    Addr count() const { return _count; }
+    Addr addr() const { return buffer.addr(); }
+
+    template <typename ...Args,
+              typename std::enable_if<std::is_constructible<
+                  Proxy, Args&&...>::value, int>::type = 0>
+    explicit ConstProxyBuf(Addr _ptr, Addr __count, Args&&... args) :
+ buffer(std::make_shared<Proxy>(args...), _ptr, sizeof(T) * __count),
+        _count(__count)
+    {
+        panic_if(!_ptr, "ProxyBuf with zero address.");
+    }
+
+    const T &
+    operator [](int i) const
+    {
+        boundsCheck(i);
+        return *(&buffer.template asConst<T>() + i);
+    }
+
+    operator const T*() const
+    {
+        return &buffer.template asConst<T>();
+    }
+};
+
+template <typename Proxy>
+class ConstProxyBuf<void, Proxy> : public ConstProxyBuf<uint8_t, Proxy>
+{
+  public:
+    using ConstProxyBuf<uint8_t, Proxy>::ConstProxyBuf;
+
+    operator const void *() const
+    {
+        return &this->buffer.template asConst<uint8_t>();
+    }
+
+    template <typename T>
+    operator const T *() const
+    {
+        return &this->buffer.template asConst<T>();
+    }
+
+    const void *
+    operator + (Addr a) const
+    {
+        return &this->buffer.template asConst<uint8_t>() + a;
+    }
+};
+
+template <typename T, typename Proxy>
+class ProxyBuf : public ConstProxyBuf<T, Proxy>
+{
+  public:
+    void flush(bool force=false) { this->buffer.flush(force); }
+    void discard() { this->buffer.discard(); }
+
+    using CPB = ConstProxyBuf<T, Proxy>;
+    using CPB::ConstProxyBuf;
+
+    template <typename ...Args,
+              typename std::enable_if<std::is_constructible<
+                  Proxy, Args&&...>::value, int>::type = 0>
+    explicit ProxyBuf(Addr _ptr, Addr __count, Args&&... args) :
+        CPB(_ptr, __count, args...)
+    {}
+
+    using CPB::operator [];
+    T &
+    operator [](int i)
+    {
+        this->boundsCheck(i);
+        return *(&this->buffer.template as<T>() + i);
+    }
+
+    using CPB::operator const T*;
+    operator T*()
+    {
+        return &this->buffer.template as<T>();
+    }
+};
+
+template <typename Proxy>
+class ProxyBuf<void, Proxy> : public ProxyBuf<uint8_t, Proxy>
+{
+  public:
+    using ProxyBuf<uint8_t, Proxy>::ProxyBuf;
+
+    operator void *()
+    {
+        return &this->buffer.template as<uint8_t>();
+    }
+
+    template <typename T,
+ typename std::enable_if<!std::is_void<T>::value, int>::type = 0>
+    operator T *()
+    {
+        return &this->buffer.template as<T>();
+    }
+
+    void *
+    operator + (Addr a)
+    {
+        return &this->buffer.template as<uint8_t>() + a;
+    }
+
+    operator const void *() const
+    {
+        return &this->buffer.template asConst<uint8_t>();
+    }
+
+    template <typename T,
+ typename std::enable_if<!std::is_void<T>::value, int>::type = 0>
+    operator const T *() const
+    {
+        return &this->buffer.template asConst<T>();
+    }
+
+    const void *
+    operator + (Addr a) const
+    {
+        return &this->buffer.template asConst<uint8_t>() + a;
+    }
+};
+
 class SETranslatingPortProxy;

 template <typename T>
 using ConstVPtr = ConstProxyPtr<T, SETranslatingPortProxy>;
 template <typename T>
 using VPtr = ProxyPtr<T, SETranslatingPortProxy>;
+template <typename T=void>
+using ConstVBuf = ConstProxyBuf<T, SETranslatingPortProxy>;
+template <typename T=void>
+using VBuf = ProxyBuf<T, SETranslatingPortProxy>;

 #endif // __SIM_PROXY_PTR_HH__
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index b271a5f..6b229f7 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -92,17 +92,14 @@
 }

 static void
-exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
+exitFutexWake(ThreadContext *tc, VPtr<long> ctid, uint64_t tgid)
 {
     // Clear value at address pointed to by thread's childClearTID field.
-    BufferArg ctidBuf(addr, sizeof(long));
-    long *ctid = (long *)ctidBuf.bufferPtr();
     *ctid = 0;
-    ctidBuf.copyOut(tc->getVirtProxy());

     FutexMap &futex_map = tc->getSystemPtr()->futexMap;
     // Wake one of the waiting threads.
-    futex_map.wakeup(addr, tgid, 1);
+    futex_map.wakeup(ctid.addr(), tgid, 1);
 }

 static SyscallReturn
@@ -116,7 +113,7 @@
         *p->exitGroup = true;

     if (p->childClearTID)
-        exitFutexWake(tc, p->childClearTID, p->tgid());
+        exitFutexWake(tc, VPtr<long>(p->childClearTID, tc), p->tgid());

     bool last_thread = true;
     Process *parent = nullptr, *tg_lead = nullptr;
@@ -303,7 +300,7 @@
 SyscallReturn
 _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
             int tgt_fd, uint64_t offset_high, uint32_t offset_low,
-            Addr result_ptr, int whence)
+            VPtr<uint64_t> result_ptr, int whence)
 {
     auto p = tc->getProcessPtr();

@@ -320,9 +317,7 @@
     if (result == (off_t)-1)
         return -errno;
     // Assuming that the size of loff_t is 64 bits on the target platform
-    BufferArg result_buf(result_ptr, sizeof(result));
-    memcpy(result_buf.bufferPtr(), &result, sizeof(result));
-    result_buf.copyOut(tc->getVirtProxy());
+    *result_ptr = result;
     return 0;
 }

@@ -354,9 +349,8 @@
 gethostnameFunc(SyscallDesc *desc, ThreadContext *tc,
                 Addr buf_ptr, int name_len)
 {
-    BufferArg name(buf_ptr, name_len);
-    strncpy((char *)name.bufferPtr(), hostname, name_len);
-    name.copyOut(tc->getVirtProxy());
+    VBuf<char> name(buf_ptr, name_len, tc);
+    strncpy(name, hostname, name_len);
     return 0;
 }

@@ -366,7 +360,7 @@
 {
     int result = 0;
     auto p = tc->getProcessPtr();
-    BufferArg buf(buf_ptr, size);
+    VBuf<char> buf(buf_ptr, size, tc);

     // Is current working directory defined?
     string cwd = p->tgtCwd;
@@ -375,18 +369,16 @@
             // Buffer too small
             return -ERANGE;
         }
-        strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
+        strncpy(buf, cwd.c_str(), size);
         result = cwd.length();
     } else {
-        if (getcwd((char *)buf.bufferPtr(), size)) {
-            result = strlen((char *)buf.bufferPtr());
+        if (getcwd(buf, size)) {
+            result = strlen(buf);
         } else {
             result = -1;
         }
     }

-    buf.copyOut(tc->getVirtProxy());
-
     return (result == -1) ? -errno : result;
 }

@@ -403,11 +395,11 @@
     // Adjust path for cwd and redirection
     path = p->checkPathRedirect(path);

-    BufferArg buf(buf_ptr, bufsiz);
+    VBuf<char> buf(buf_ptr, bufsiz, tc);

     int result = -1;
     if (path != "/proc/self/exe") {
-        result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
+        result = readlink(path.c_str(), buf, bufsiz);
     } else {
         // Emulate readlink() called on '/proc/self/exe' should return the
         // absolute path of the binary running in the simulated system (the
@@ -427,7 +419,7 @@
             fatal("readlink('/proc/self/exe') unable to resolve path to "
                   "executable: %s", p->progName());
         }
-        strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
+        strncpy(buf, real_path, bufsiz);
         size_t real_path_len = strlen(real_path);
         if (real_path_len > bufsiz) {
             // readlink will truncate the contents of the
@@ -439,12 +431,9 @@

         // Issue a warning about potential unexpected results
warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
-                  "results in various settings.\n      Returning '%s'\n",
-                  (char*)buf.bufferPtr());
+ "results in various settings.\n Returning '%s'\n", buf);
     }

-    buf.copyOut(tc->getVirtProxy());
-
     return (result == -1) ? -errno : result;
 }

@@ -837,11 +826,9 @@
      * Copy the target file descriptors into buffer space and then copy
      * the buffer space back into the target address space.
      */
-    BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
-    int *buf_ptr = (int*)tgt_handle.bufferPtr();
-    buf_ptr[0] = tgt_fds[0];
-    buf_ptr[1] = tgt_fds[1];
-    tgt_handle.copyOut(tc->getVirtProxy());
+    VBuf<int> tgt_handle(tgt_addr, 2, tc);
+    tgt_handle[0] = tgt_fds[0];
+    tgt_handle[1] = tgt_fds[1];

     if (flags) {
// pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
@@ -1080,15 +1067,15 @@
         return -EBADF;
     int sim_fd = hbfdp->getSimFD();

-    BufferArg buf_arg(buf_ptr, count);
-    auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
+    VBuf<> buf_arg(buf_ptr, count, tc);
+    auto status = syscall(SYS_NUM, sim_fd, (void *)buf_arg, count);

     if (status == -1)
         return -errno;

     unsigned traversed = 0;
     while (traversed < status) {
-        DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
+        DE *buffer = (DE *)(buf_arg + traversed);

         auto host_reclen = buffer->d_reclen;

@@ -1105,7 +1092,6 @@
         traversed += host_reclen;
     }

-    buf_arg.copyOut(tc->getVirtProxy());
     return status;
 }
 #endif
@@ -1165,17 +1151,14 @@
 {
     auto p = tc->getProcessPtr();

-    BufferArg bufSock(buf_ptr, addrlen);
-    bufSock.copyIn(tc->getVirtProxy());
+    ConstVBuf<> bufSock(buf_ptr, addrlen, tc);

auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
     if (!sfdp)
         return -EBADF;
     int sim_fd = sfdp->getSimFD();

-    int status = ::bind(sim_fd,
-                        (struct sockaddr *)bufSock.bufferPtr(),
-                        addrlen);
+    int status = ::bind(sim_fd, bufSock, addrlen);

     return (status == -1) ? -errno : status;
 }
@@ -1201,17 +1184,14 @@
 {
     auto p = tc->getProcessPtr();

-    BufferArg addr(buf_ptr, addrlen);
-    addr.copyIn(tc->getVirtProxy());
+    ConstVBuf<> addr(buf_ptr, addrlen, tc);

auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
     if (!sfdp)
         return -EBADF;
     int sim_fd = sfdp->getSimFD();

-    int status = connect(sim_fd,
-                         (struct sockaddr *)addr.bufferPtr(),
-                         (socklen_t)addrlen);
+    int status = connect(sim_fd, addr, (socklen_t)addrlen);

     return (status == -1) ? -errno : status;
 }
@@ -1219,7 +1199,7 @@
 SyscallReturn
 recvfromFunc(SyscallDesc *desc, ThreadContext *tc,
              int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags,
-             Addr addrPtr, Addr addrlenPtr)
+             Addr addrPtr, VPtr<socklen_t> addrlenPtr)
 {
     auto p = tc->getProcessPtr();

@@ -1229,49 +1209,39 @@
     int sim_fd = sfdp->getSimFD();

     // Reserve buffer space.
-    BufferArg bufrBuf(bufrPtr, bufrLen);
+    VBuf<> bufrBuf(bufrPtr, bufrLen, tc);

     // Get address length.
-    socklen_t addrLen = 0;
-    if (addrlenPtr != 0) {
-        // Read address length parameter.
-        BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
-        addrlenBuf.copyIn(tc->getVirtProxy());
-        addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
-    }
+    socklen_t addrLen = addrlenPtr ? *addrlenPtr : 0;

-    struct sockaddr sa, *sap = NULL;
-    if (addrLen != 0) {
-        BufferArg addrBuf(addrPtr, addrLen);
-        addrBuf.copyIn(tc->getVirtProxy());
-        memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
-               sizeof(struct sockaddr));
+    struct sockaddr sa;
+    struct sockaddr *sap = nullptr;
+    if (addrPtr) {
+        VBuf<> addrBuf(addrPtr, addrLen, tc);
+        memcpy(&sa, addrBuf,
+               std::min<size_t>(sizeof(struct sockaddr), addrLen));
         sap = &sa;
     }

-    ssize_t recvd_size = recvfrom(sim_fd,
-                                  (void *)bufrBuf.bufferPtr(),
- bufrLen, flags, sap, (socklen_t *)&addrLen);
+    ssize_t recvd_size = recvfrom(sim_fd, bufrBuf, bufrLen,
+                                  flags, sap, &addrLen);

-    if (recvd_size == -1)
+    if (recvd_size == -1) {
+        addrlenPtr.discard();
+        bufrBuf.discard();
         return -errno;
-
-    // Pass the received data out.
-    bufrBuf.copyOut(tc->getVirtProxy());
+    }

     // Copy address to addrPtr and pass it on.
-    if (sap != NULL) {
-        BufferArg addrBuf(addrPtr, addrLen);
-        memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
-        addrBuf.copyOut(tc->getVirtProxy());
+    if (sap) {
+        VBuf<> addrBuf(addrPtr, addrLen, tc);
+        memcpy(addrBuf, sap,
+                std::min<size_t>(sizeof(struct sockaddr), addrLen));
     }

     // Copy len to addrlenPtr and pass it on.
-    if (addrLen != 0) {
-        BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
-        *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
-        addrlenBuf.copyOut(tc->getVirtProxy());
-    }
+    if (addrlenPtr)
+        *addrlenPtr = addrLen;

     return recvd_size;
 }
@@ -1289,28 +1259,25 @@
     int sim_fd = sfdp->getSimFD();

     // Reserve buffer space.
-    BufferArg bufrBuf(bufrPtr, bufrLen);
-    bufrBuf.copyIn(tc->getVirtProxy());
+    VBuf<> bufrBuf(bufrPtr, bufrLen, tc);

     struct sockaddr sa, *sap = nullptr;
     memset(&sa, 0, sizeof(sockaddr));
-    if (addrLen != 0) {
-        BufferArg addrBuf(addrPtr, addrLen);
-        addrBuf.copyIn(tc->getVirtProxy());
-        memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
+    if (addrPtr) {
+        VBuf<> addrBuf(addrPtr, addrLen, tc);
+        memcpy(&sa, addrBuf, addrLen);
         sap = &sa;
     }

-    ssize_t sent_size = sendto(sim_fd,
-                               (void *)bufrBuf.bufferPtr(),
-                               bufrLen, flags, sap, (socklen_t)addrLen);
+    ssize_t sent_size = sendto(sim_fd, bufrBuf, bufrLen,
+                               flags, sap, (socklen_t)addrLen);

     return (sent_size == -1) ? -errno : sent_size;
 }

 SyscallReturn
 recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
-            int tgt_fd, Addr msgPtr, int flags)
+            int tgt_fd, VPtr<struct msghdr> msgHdr, int flags)
 {
     auto p = tc->getProcessPtr();

@@ -1337,118 +1304,93 @@
       *  };
       */

-    /**
- * The plan with this system call is to replace all of the pointers in the - * structure and the substructure with BufferArg class pointers. We will
-     * copy every field from the structures into our BufferArg classes.
+    /*
+     * Create a local version of msg_name and point the header at it.
      */
-    BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
-    msgBuf.copyIn(tc->getVirtProxy());
-    struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
-
-    /**
-     * We will use these address place holders to retain the pointers which
- * we are going to replace with our own buffers in our simulator address
-     * space.
-     */
-    Addr msg_name_phold = 0;
-    Addr msg_iov_phold = 0;
-    Addr iovec_base_phold[msgHdr->msg_iovlen];
-    Addr msg_control_phold = 0;
-
-    /**
-     * Record msg_name pointer then replace with buffer pointer.
-     */
-    BufferArg *nameBuf = NULL;
+    std::unique_ptr<VBuf<>> nameBuf;
     if (msgHdr->msg_name) {
-        /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
-        /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
-        /*3*/nameBuf->copyIn(tc->getVirtProxy());
-        /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
+        nameBuf.reset(new VBuf<>(
+                    (Addr)msgHdr->msg_name, msgHdr->msg_namelen, tc));
+        msgHdr->msg_name = *nameBuf;
     }

-    /**
-     * Record msg_iov pointer then replace with buffer pointer. Also, setup
-     * an array of buffer pointers for the iovec structs record and replace
-     * their pointers with buffer pointers.
+    /*
+     * Create local versions of msg_iov and the buffers it points to, and
+     * record them in the header.
      */
-    BufferArg *iovBuf = NULL;
-    BufferArg *iovecBuf[msgHdr->msg_iovlen];
-    for (int i = 0; i < msgHdr->msg_iovlen; i++) {
-        iovec_base_phold[i] = 0;
-        iovecBuf[i] = NULL;
-    }
+    std::vector<std::unique_ptr<VBuf<>>> iovecs;
+    std::unique_ptr<VBuf<struct iovec>> iov;

     if (msgHdr->msg_iov) {
-        /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
-        /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
-                                    sizeof(struct iovec));
-        /*3*/iovBuf->copyIn(tc->getVirtProxy());
-        for (int i = 0; i < msgHdr->msg_iovlen; i++) {
-            if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
-                /*1*/iovec_base_phold[i] =
- (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
-                /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
-                     ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
-                /*3*/iovecBuf[i]->copyIn(tc->getVirtProxy());
-                /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
-                     iovecBuf[i]->bufferPtr();
+        // Get the guest msg_iov array.
+        iov.reset(new VBuf<struct iovec>(
+                    (Addr)msgHdr->msg_iov, msgHdr->msg_iovlen, tc));
+
+        // For each element in the array...
+        for (int i = 0; i < iov->count(); i++) {
+            auto vec = (*iov)[i];
+            // If it points to anything...
+            if (vec.iov_base) {
+                // Create a local version of it.
+                iovecs[i].reset(
+                        new VBuf<>((Addr)vec.iov_base, vec.iov_len, tc));
+                vec.iov_base = *iovecs[i];
             }
         }
-        /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
+        // Install the host version of msg_iov in msgHdr.
+        msgHdr->msg_iov = *iov;
     }

-    /**
-     * Record msg_control pointer then replace with buffer pointer.
+    /*
+     * Create a local version of msg_control and point the header at it.
      */
-    BufferArg *controlBuf = NULL;
+    std::unique_ptr<VBuf<>> controlBuf;
     if (msgHdr->msg_control) {
-        /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
-        /*2*/controlBuf = new BufferArg(msg_control_phold,
- CMSG_ALIGN(msgHdr->msg_controllen));
-        /*3*/controlBuf->copyIn(tc->getVirtProxy());
-        /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
+        controlBuf.reset(new VBuf<>((Addr)msgHdr->msg_control,
+ CMSG_ALIGN(msgHdr->msg_controllen), tc));
+        msgHdr->msg_control = *controlBuf;
     }

     ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);

-    if (recvd_size < 0)
+    if (recvd_size < 0) {
+        // If something bad happened, throw away all our modifications.
+        msgHdr.discard();
+        if (iov)
+            iov->discard();
+        if (nameBuf)
+            nameBuf->discard();
+        for (auto &iovec: iovecs)
+            if (iovec)
+                iovec->discard();
+        if (controlBuf)
+            controlBuf->discard();
         return -errno;
-
-    if (msgHdr->msg_name) {
-        nameBuf->copyOut(tc->getVirtProxy());
-        delete(nameBuf);
-        msgHdr->msg_name = (void *)msg_name_phold;
     }

-    if (msgHdr->msg_iov) {
-        for (int i = 0; i< msgHdr->msg_iovlen; i++) {
-            if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
-                iovecBuf[i]->copyOut(tc->getVirtProxy());
-                delete iovecBuf[i];
-                ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
-                (void *)iovec_base_phold[i];
-            }
-        }
-        iovBuf->copyOut(tc->getVirtProxy());
-        delete iovBuf;
-        msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
+    /*
+     * Point the msgHdr back to the guest versions of things. The data
+     * buffers will write themselves back out.
+     */
+    if (controlBuf)
+        msgHdr->msg_control = (void *)controlBuf->addr();
+
+    if (iov) {
+        msgHdr->msg_iov = (struct iovec *)iov->addr();
+        for (int i = 0; i < iovecs.size(); i++)
+            if (iovecs[i])
+                (*iov)[i].iov_base = (void *)iovecs[i]->addr();
     }

-    if (msgHdr->msg_control) {
-        controlBuf->copyOut(tc->getVirtProxy());
-        delete(controlBuf);
-        msgHdr->msg_control = (void *)msg_control_phold;
-    }
-
-    msgBuf.copyOut(tc->getVirtProxy());
+    if (nameBuf)
+        msgHdr->msg_name = (void *)nameBuf->addr();

     return recvd_size;
 }

 SyscallReturn
 sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
-            int tgt_fd, Addr msgPtr, int flags)
+            int tgt_fd, VPtr<struct msghdr> msgHdr, int flags)
 {
     auto p = tc->getProcessPtr();

@@ -1458,57 +1400,46 @@
     int sim_fd = sfdp->getSimFD();

     /**
-     * Reserve buffer space.
-     */
-    BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
-    msgBuf.copyIn(tc->getVirtProxy());
-    struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
-
-    /**
      * Assuming msgHdr.msg_iovlen >= 1, then there is no point calling
      * recvmsg without a buffer.
      */
-    struct iovec *iovPtr = msgHdr.msg_iov;
- BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
+    BufferArg iovBuf((Addr)msgHdr->msg_iov,
+            sizeof(struct iovec) * msgHdr->msg_iovlen);
     iovBuf.copyIn(tc->getVirtProxy());
-    struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
-    msgHdr.msg_iov = iov;
+    struct iovec *iovs = (struct iovec *)iovBuf.bufferPtr();
+    msgHdr->msg_iov = iovs;

     /**
      * Cannot instantiate buffers till inside the loop.
      * Create array to hold buffer addresses, to be used during copyIn of
      * send data.
      */
-    BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
-                                                   * sizeof(BufferArg *));
+    std::vector<BufferArg *> bufferArray(msgHdr->msg_iovlen);

     /**
      * Iterate through the iovec structures:
* Get the base buffer addreses, reserve iov_len amount of space for each.
      * Put the buf address into the bufferArray for later retrieval.
      */
-    for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
-        Addr basePtr = (Addr) iov[iovIndex].iov_base;
- bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
-        bufferArray[iovIndex]->copyIn(tc->getVirtProxy());
-        iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
+    for (int idx = 0; idx < msgHdr->msg_iovlen; idx++) {
+        auto &buf = bufferArray[idx];
+        auto &iov = iovs[idx];
+        Addr basePtr = (Addr)iov.iov_base;
+        buf = new BufferArg(basePtr, iov.iov_len);
+        buf->copyIn(tc->getVirtProxy());
+        iov.iov_base = buf->bufferPtr();
     }

-    ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
+    ssize_t sent_size = sendmsg(sim_fd, msgHdr, flags);
     int local_errno = errno;

     /**
      * Free dynamically allocated memory.
      */
-    for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
-        BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
-        delete(baseBuf);
-    }
+    for (auto &ptr: bufferArray)
+        delete ptr;

-    /**
-     * Malloced above.
-     */
-    free(bufferArray);
+    msgHdr.discard();

     return (sent_size < 0) ? -local_errno : sent_size;
 }
@@ -1639,8 +1570,6 @@
 getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
            VPtr<uint32_t> cpu, VPtr<uint32_t> node, VPtr<uint32_t> tcache)
 {
-    bool error = false;
-
     // unsigned is the same size (4) on all Linux supported ISAs.
     if (cpu)
*cpu = htog(tc->contextId(), tc->getSystemPtr()->getGuestByteOrder());
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 31c1d4c..27d8278 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -163,7 +163,8 @@
 /// Target _llseek() handler.
 SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
                           int tgt_fd, uint64_t offset_high,
- uint32_t offset_low, Addr result_ptr, int whence);
+                          uint32_t offset_low, VPtr<uint64_t> result_ptr,
+                          int whence);

 /// Target munmap() handler.
 SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start,
@@ -316,15 +317,16 @@
 // Target recvfrom() handler.
 SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc,
                            int tgt_fd, Addr bufrPtr, size_t bufrLen,
-                           int flags, Addr addrPtr, Addr addrlenPtr);
+                           int flags, Addr addrPtr,
+                           VPtr<socklen_t> addrlenPtr);

 // Target recvmsg() handler.
 SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
-                          int tgt_fd, Addr msgPtr, int flags);
+ int tgt_fd, VPtr<struct msghdr> msgHdr, int flags);

 // Target sendmsg() handler.
 SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
-                          int tgt_fd, Addr msgPtr, int flags);
+ int tgt_fd, VPtr<struct msghdr> msgHdr, int flags);

 // Target getuid() handler.
 SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc);
@@ -356,7 +358,8 @@
                              Addr valPtr, socklen_t len);

 SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
-                         Addr cpu_ptr, Addr node_ptr, Addr tcache_ptr);
+                         VPtr<uint32_t> cpu, VPtr<uint32_t> node,
+                         VPtr<uint32_t> tcache);

 // Target getsockname() handler.
 SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc,
@@ -385,16 +388,14 @@

     if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
         // Ensure futex system call accessed atomically.
-        BufferArg buf(uaddr, sizeof(int));
-        buf.copyIn(tc->getVirtProxy());
-        int mem_val = *(int*)buf.bufferPtr();
+        VPtr<int> buf(uaddr, tc);

         /*
          * The value in memory at uaddr is not equal with the expected val
* (a different thread must have changed it before the system call was
          * invoked). In this case, we need to throw an error.
          */
-        if (val != mem_val)
+        if (val != *buf)
             return -OS::TGT_EWOULDBLOCK;

         if (OS::TGT_FUTEX_WAIT == op) {
@@ -412,14 +413,12 @@
                OS::TGT_FUTEX_CMP_REQUEUE == op) {

         // Ensure futex system call accessed atomically.
-        BufferArg buf(uaddr, sizeof(int));
-        buf.copyIn(tc->getVirtProxy());
-        int mem_val = *(int*)buf.bufferPtr();
+        VPtr<int> buf(uaddr, tc);
         /*
          * For CMP_REQUEUE, the whole operation is only started only if
          * val3 is still the value of the futex pointed to by uaddr.
          */
-        if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
+        if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != *buf)
             return -OS::TGT_EWOULDBLOCK;
return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
     } else if (OS::TGT_FUTEX_WAKE_OP == op) {
@@ -445,9 +444,8 @@
          *
          */
         // get value from simulated-space
-        BufferArg buf(uaddr2, sizeof(int));
-        buf.copyIn(tc->getVirtProxy());
-        int oldval = *(int*)buf.bufferPtr();
+        VPtr<int> buf(uaddr2, tc);
+        int oldval = *buf;
         int newval = oldval;
         // extract op, oparg, cmp, cmparg from val3
         int wake_cmparg =  val3 & 0xfff;
@@ -469,8 +467,7 @@
         else if (wake_op == OS::TGT_FUTEX_OP_XOR)
             newval ^= wake_oparg;
         // copy updated value back to simulated-space
-        *(int*)buf.bufferPtr() = newval;
-        buf.copyOut(tc->getVirtProxy());
+        *buf = newval;
         // perform the first wake-up
         int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
         int woken2 = 0;
@@ -694,22 +691,18 @@

         switch (req) {
           case SIOCGIFCONF: {
-            BufferArg conf_arg(addr, sizeof(ifconf));
-            conf_arg.copyIn(tc->getVirtProxy());
+            VPtr<ifconf> conf(addr, tc);

-            ifconf *conf = (ifconf*)conf_arg.bufferPtr();
             Addr ifc_buf_addr = (Addr)conf->ifc_buf;
-            BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
-            ifc_buf_arg.copyIn(tc->getVirtProxy());
+            VBuf<char> ifc_buf_arg(ifc_buf_addr, conf->ifc_len, tc);

-            conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
+            conf->ifc_buf = (char *)ifc_buf_arg;

-            status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
-            if (status != -1) {
-                conf->ifc_buf = (char*)ifc_buf_addr;
-                ifc_buf_arg.copyOut(tc->getVirtProxy());
-                conf_arg.copyOut(tc->getVirtProxy());
-            }
+            status = ioctl(sfdp->getSimFD(), req, conf);
+            if (status != -1)
+                conf->ifc_buf = (char *)ifc_buf_addr;
+            else
+                conf.discard();

             return status;
           }
@@ -723,12 +716,11 @@
           case SIOCGIFHWADDR:
 #endif
           case SIOCGIFMTU: {
-            BufferArg req_arg(addr, sizeof(ifreq));
-            req_arg.copyIn(tc->getVirtProxy());
+            VPtr<ifreq> arg(addr, tc);

-            status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
-            if (status != -1)
-                req_arg.copyOut(tc->getVirtProxy());
+            status = ioctl(sfdp->getSimFD(), req, arg);
+            if (status == -1)
+                arg.discard();
             return status;
           }
         }
@@ -999,8 +991,7 @@
 {
     auto p = tc->getProcessPtr();

-    BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
-    fdsBuf.copyIn(tc->getVirtProxy());
+    VBuf<struct pollfd> fdsBuf(fdsPtr, nfds, tc);

     /**
      * Record the target file descriptors in a local variable. We need to
@@ -1010,13 +1001,13 @@
      */
     int temp_tgt_fds[nfds];
     for (int index = 0; index < nfds; index++) {
- temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
+        temp_tgt_fds[index] = fdsBuf[index].fd;
         auto tgt_fd = temp_tgt_fds[index];
auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
         if (!hbfdp)
             return -EBADF;
         auto host_fd = hbfdp->getSimFD();
-        ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
+        fdsBuf[index].fd = host_fd;
     }

     /**
@@ -1027,7 +1018,7 @@
      */
     int status;
     if (tmout < 0) {
-        status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
+        status = poll(fdsBuf, nfds, 0);
         if (status == 0) {
             /**
              * If blocking indefinitely, check the signal list to see if a
@@ -1042,7 +1033,7 @@
             return SyscallReturn::retry();
         }
     } else
-        status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
+        status = poll(fdsBuf, nfds, 0);

     if (status == -1)
         return -errno;
@@ -1053,15 +1044,9 @@
      */
     for (int index = 0; index < nfds; index++) {
         auto tgt_fd = temp_tgt_fds[index];
-        ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
+        fdsBuf[index].fd = tgt_fd;
     }

-    /**
-     * Copy out the pollfd struct because the host may have updated fields
-     * in the structure.
-     */
-    fdsBuf.copyOut(tc->getVirtProxy());
-
     return status;
 }

@@ -1406,7 +1391,7 @@
 template <class OS>
 SyscallReturn
cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
-          Addr ptidPtr, Addr ctidPtr, Addr tlsPtr)
+          VPtr<long> ptid, VPtr<long> ctid, Addr tlsPtr)
 {
     auto p = tc->getProcessPtr();

@@ -1467,12 +1452,8 @@
     cp->assignThreadContext(ctc->contextId());
     owner->revokeThreadContext(ctc->contextId());

-    if (flags & OS::TGT_CLONE_PARENT_SETTID) {
-        BufferArg ptidBuf(ptidPtr, sizeof(long));
-        long *ptid = (long *)ptidBuf.bufferPtr();
+    if (flags & OS::TGT_CLONE_PARENT_SETTID)
         *ptid = cp->pid();
-        ptidBuf.copyOut(tc->getVirtProxy());
-    }

     if (flags & OS::TGT_CLONE_THREAD) {
         cp->pTable->shared = true;
@@ -1488,15 +1469,11 @@
         *cp->sigchld = true;
     }

-    if (flags & OS::TGT_CLONE_CHILD_SETTID) {
-        BufferArg ctidBuf(ctidPtr, sizeof(long));
-        long *ctid = (long *)ctidBuf.bufferPtr();
+    if (flags & OS::TGT_CLONE_CHILD_SETTID)
         *ctid = cp->pid();
-        ctidBuf.copyOut(ctc->getVirtProxy());
-    }

     if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
-        cp->childClearTID = (uint64_t)ctidPtr;
+        cp->childClearTID = *ctid;

     ctc->clearArchRegs();

@@ -1521,9 +1498,10 @@
 template <class OS>
 SyscallReturn
 cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags,
- RegVal newStack, Addr ptidPtr, Addr tlsPtr, Addr ctidPtr)
+                   RegVal newStack, VPtr<long> ptid,
+                   Addr tlsPtr, VPtr<long> ctid)
 {
- return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
+    return cloneFunc<OS>(desc, tc, flags, newStack, ptid, ctid, tlsPtr);
 }

 /// Target fstatfs() handler.
@@ -1776,11 +1754,9 @@
         return -EBADF;
     int sim_fd = ffdp->getSimFD();

-    BufferArg bufArg(bufPtr, nbytes);
+    VBuf<> bufArg(bufPtr, nbytes, tc);

-    int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
-
-    bufArg.copyOut(tc->getVirtProxy());
+    int bytes_read = pread(sim_fd, bufArg, nbytes, offset);

     return (bytes_read == -1) ? -errno : bytes_read;
 }
@@ -1797,10 +1773,9 @@
         return -EBADF;
     int sim_fd = ffdp->getSimFD();

-    BufferArg bufArg(bufPtr, nbytes);
-    bufArg.copyIn(tc->getVirtProxy());
+    VBuf<> bufArg(bufPtr, nbytes, tc);

-    int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
+    int bytes_written = pwrite(sim_fd, bufArg, nbytes, offset);

     return (bytes_written == -1) ? -errno : bytes_written;
 }
@@ -1967,25 +1942,21 @@
     auto p = tc->getProcessPtr();

     std::string path;
-    PortProxy & mem_proxy = tc->getVirtProxy();
+    PortProxy &mem_proxy = tc->getVirtProxy();
     if (!mem_proxy.tryReadString(path, pathname))
         return -EFAULT;

     if (access(path.c_str(), F_OK) == -1)
         return -EACCES;

-    auto read_in = [](std::vector<std::string> &vect,
-                      PortProxy &mem_proxy, Addr mem_loc)
+    auto read_in = [mem_proxy, tc](
+            std::vector<std::string> &vect, Addr mem_loc)
     {
-        for (int inc = 0; ; inc++) {
-            BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
-            b.copyIn(mem_proxy);
-
-            if (!*(Addr*)b.bufferPtr())
-                break;
-
-            vect.push_back(std::string());
-            mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
+        // This shouldn't assume all pointers are the size of Addr.
+        for (ConstVPtr<Addr> b(mem_loc, tc); *b; b = b + 1) {
+            std::string str;
+            mem_proxy.tryReadString(str, *b);
+            vect.push_back(str);
         }
     };

@@ -1997,8 +1968,8 @@
      */
     ProcessParams *pp = new ProcessParams();
     pp->executable = path;
-    read_in(pp->cmd, mem_proxy, argv_mem_loc);
-    read_in(pp->env, mem_proxy, envp_mem_loc);
+    read_in(pp->cmd, argv_mem_loc);
+    read_in(pp->env, envp_mem_loc);
     pp->uid = p->uid();
     pp->egid = p->egid();
     pp->euid = p->euid();
@@ -2199,18 +2170,17 @@
 {
     auto p = tc->getProcessPtr();

-    BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
-    int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
-    if (status == -1)
+    VBuf<int> fds(svPtr, 2, tc);
+    int status = socketpair(domain, type, prot, fds);
+    if (status == -1) {
+        fds.discard();
         return -errno;
-
-    int *fds = (int *)svBuf.bufferPtr();
+    }

auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
     fds[0] = p->fds->allocFD(sfdp1);
auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
     fds[1] = p->fds->allocFD(sfdp2);
-    svBuf.copyOut(tc->getVirtProxy());

     return status;
 }
@@ -2401,11 +2371,11 @@
         && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
         return SyscallReturn::retry();

-    BufferArg buf_arg(buf_ptr, nbytes);
-    int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
+    VBuf<> buf_arg(buf_ptr, nbytes, tc);
+    int bytes_read = read(sim_fd, buf_arg, nbytes);

-    if (bytes_read > 0)
-        buf_arg.copyOut(tc->getVirtProxy());
+    if (bytes_read <= 0)
+        buf_arg.discard();

     return (bytes_read == -1) ? -errno : bytes_read;
 }
@@ -2422,8 +2392,7 @@
         return -EBADF;
     int sim_fd = hbfdp->getSimFD();

-    BufferArg buf_arg(buf_ptr, nbytes);
-    buf_arg.copyIn(tc->getVirtProxy());
+    VBuf<> buf_arg(buf_ptr, nbytes, tc);

     struct pollfd pfd;
     pfd.fd = sim_fd;
@@ -2441,7 +2410,7 @@
             return SyscallReturn::retry();
     }

-    int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
+    int bytes_written = write(sim_fd, buf_arg, nbytes);

     if (bytes_written != -1)
         fsync(sim_fd);
@@ -2452,7 +2421,7 @@
 template <class OS>
 SyscallReturn
 wait4Func(SyscallDesc *desc, ThreadContext *tc,
-          pid_t pid, Addr statPtr, int options, Addr rusagePtr)
+          pid_t pid, VPtr<int> status, int options, Addr rusagePtr)
 {
     auto p = tc->getProcessPtr();

@@ -2497,9 +2466,7 @@
 success:
     // Set status to EXITED for WIFEXITED evaluations.
     const int EXITED = 0;
-    BufferArg statusBuf(statPtr, sizeof(int));
-    *(int *)statusBuf.bufferPtr() = EXITED;
-    statusBuf.copyOut(tc->getVirtProxy());
+    *status = EXITED;

     // Return the child PID.
     pid_t retval = iter->sender->pid();
@@ -2510,16 +2477,11 @@
 template <class OS>
 SyscallReturn
 acceptFunc(SyscallDesc *desc, ThreadContext *tc,
-           int tgt_fd, Addr addrPtr, Addr lenPtr)
+ int tgt_fd, VPtr<struct sockaddr> addrPtr, VPtr<socklen_t> lenPtr)
 {
-    struct sockaddr sa;
-    socklen_t addrLen;
     int host_fd;
     auto p = tc->getProcessPtr();

-    BufferArg *lenBufPtr = nullptr;
-    BufferArg *addrBufPtr = nullptr;
-
auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
     if (!sfdp)
         return -EBADF;
@@ -2537,35 +2499,12 @@
if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
         return SyscallReturn::retry();

-    if (lenPtr) {
-        lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
-        lenBufPtr->copyIn(tc->getVirtProxy());
-        memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
-               sizeof(socklen_t));
-    }
+    host_fd = accept(sim_fd, addrPtr, lenPtr);

-    if (addrPtr) {
-        addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
-        addrBufPtr->copyIn(tc->getVirtProxy());
-        memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
-               sizeof(struct sockaddr));
-    }
-
-    host_fd = accept(sim_fd, &sa, &addrLen);
-
-    if (host_fd == -1)
+    if (host_fd == -1) {
+        addrPtr.discard();
+        lenPtr.discard();
         return -errno;
-
-    if (addrPtr) {
-        memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
-        addrBufPtr->copyOut(tc->getVirtProxy());
-        delete(addrBufPtr);
-    }
-
-    if (lenPtr) {
-        *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
-        lenBufPtr->copyOut(tc->getVirtProxy());
-        delete(lenBufPtr);
     }

     auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/32254
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: If79ce0733a7a61274a818e39ecb9cf383cc4e8ba
Gerrit-Change-Number: 32254
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to