sim-se: add socket-based functionality
authorBrandon Potter <brandon.potter@amd.com>
Wed, 18 Apr 2018 18:48:19 +0000 (14:48 -0400)
committerAnthony Gutierrez <anthony.gutierrez@amd.com>
Tue, 22 Jan 2019 01:56:17 +0000 (01:56 +0000)
Add socket, socketpair, bind, list, connect and shutdown
system calls.

Change-Id: I635af3fca410f96fe28f8fe497e3d457a9dbc470
Reviewed-on: https://gem5-review.googlesource.com/c/12113
Reviewed-by: Anthony Gutierrez <anthony.gutierrez@amd.com>
Maintainer: Anthony Gutierrez <anthony.gutierrez@amd.com>

src/arch/x86/linux/process.cc
src/sim/fd_entry.hh
src/sim/syscall_emul.cc
src/sim/syscall_emul.hh

index 49d3e5aa8c4095bcfec7923715d3f5093abd21e2..36845971c14a9f91a0109a0b2c2153011ed58cb4 100644 (file)
@@ -263,19 +263,19 @@ static SyscallDesc syscallDescs64[] = {
     /*  38 */ SyscallDesc("setitimer", unimplementedFunc),
     /*  39 */ SyscallDesc("getpid", getpidFunc),
     /*  40 */ SyscallDesc("sendfile", unimplementedFunc),
-    /*  41 */ SyscallDesc("socket", unimplementedFunc),
-    /*  42 */ SyscallDesc("connect", unimplementedFunc),
+    /*  41 */ SyscallDesc("socket", socketFunc<X86Linux64>),
+    /*  42 */ SyscallDesc("connect", connectFunc),
     /*  43 */ SyscallDesc("accept", unimplementedFunc),
     /*  44 */ SyscallDesc("sendto", unimplementedFunc),
     /*  45 */ SyscallDesc("recvfrom", unimplementedFunc),
     /*  46 */ SyscallDesc("sendmsg", unimplementedFunc),
     /*  47 */ SyscallDesc("recvmsg", unimplementedFunc),
-    /*  48 */ SyscallDesc("shutdown", unimplementedFunc),
-    /*  49 */ SyscallDesc("bind", unimplementedFunc),
-    /*  50 */ SyscallDesc("listen", unimplementedFunc),
+    /*  48 */ SyscallDesc("shutdown", shutdownFunc),
+    /*  49 */ SyscallDesc("bind", bindFunc),
+    /*  50 */ SyscallDesc("listen", listenFunc),
     /*  51 */ SyscallDesc("getsockname", unimplementedFunc),
     /*  52 */ SyscallDesc("getpeername", unimplementedFunc),
-    /*  53 */ SyscallDesc("socketpair", unimplementedFunc),
+    /*  53 */ SyscallDesc("socketpair", socketpairFunc<X86Linux64>),
     /*  54 */ SyscallDesc("setsockopt", unimplementedFunc),
     /*  55 */ SyscallDesc("getsockopt", unimplementedFunc),
     /*  56 */ SyscallDesc("clone", cloneFunc<X86Linux64>),
index 980011984eb5424ccbb80cab34821280dacd28a7..6b2b2daa8dd179d7699cc842c526565867d7a81f 100644 (file)
@@ -211,4 +211,30 @@ class DeviceFDEntry : public FDEntry
     std::string _fileName;
 };
 
+class SocketFDEntry: public HBFDEntry
+{
+  public:
+    SocketFDEntry(int sim_fd, int domain, int type, int protocol,
+                  bool close_on_exec = false)
+        : HBFDEntry(0, sim_fd, close_on_exec),
+          _domain(domain), _type(type), _protocol(protocol)
+    { }
+
+    SocketFDEntry(SocketFDEntry const& reg, bool close_on_exec = false)
+        : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
+          _domain(reg._domain), _type(reg._type), _protocol(reg._protocol)
+    { }
+
+    std::shared_ptr<FDEntry>
+    clone() const override
+    {
+        return std::make_shared<SocketFDEntry>(*this);
+    }
+
+  private:
+    int _domain;
+    int _type;
+    int _protocol;
+};
+
 #endif // __FD_ENTRY_HH__
index e79e79c6281cd163c6863d8a2d143e8e2c18c2c6..3b35d34e9bf1c4a2589c4a23a676d90a401f524a 100644 (file)
@@ -1224,3 +1224,83 @@ getdents64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
     return getdentsImpl<LinDent64, SYS_getdents64>(desc, callnum, p, tc);
 }
 #endif
+
+SyscallReturn
+shutdownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int tgt_fd = p->getSyscallArg(tc, index);
+    int how = p->getSyscallArg(tc, index);
+
+    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
+    if (!sfdp)
+        return -EBADF;
+    int sim_fd = sfdp->getSimFD();
+
+    int retval = shutdown(sim_fd, how);
+
+    return (retval == -1) ? -errno : retval;
+}
+
+SyscallReturn
+bindFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int tgt_fd = p->getSyscallArg(tc, index);
+    Addr buf_ptr = p->getSyscallArg(tc, index);
+    int addrlen = p->getSyscallArg(tc, index);
+
+    BufferArg bufSock(buf_ptr, addrlen);
+    bufSock.copyIn(tc->getMemProxy());
+
+    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);
+
+    return (status == -1) ? -errno : status;
+}
+
+SyscallReturn
+listenFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int tgt_fd = p->getSyscallArg(tc, index);
+    int backlog = p->getSyscallArg(tc, index);
+
+    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
+    if (!sfdp)
+        return -EBADF;
+    int sim_fd = sfdp->getSimFD();
+
+    int status = listen(sim_fd, backlog);
+
+    return (status == -1) ? -errno : status;
+}
+
+SyscallReturn
+connectFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int tgt_fd = p->getSyscallArg(tc, index);
+    Addr buf_ptr = p->getSyscallArg(tc, index);
+    int addrlen = p->getSyscallArg(tc, index);
+
+    BufferArg addr(buf_ptr, addrlen);
+    addr.copyIn(tc->getMemProxy());
+
+    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);
+
+    return (status == -1) ? -errno : status;
+}
index 3f06869aac114c86231d1cf1a7ec4c92a3981bce..9329f7a5b402ab577936487c10ab04ab2ed0f235 100644 (file)
@@ -79,6 +79,7 @@
 #endif
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #if (NO_STATFS == 0)
 #include <sys/statfs.h>
@@ -181,6 +182,10 @@ SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
 SyscallReturn munmapFunc(SyscallDesc *desc, int num,
                          Process *p, ThreadContext *tc);
 
+/// Target shutdown() handler.
+SyscallReturn shutdownFunc(SyscallDesc *desc, int num,
+                           Process *p, ThreadContext *tc);
+
 /// Target gethostname() handler.
 SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
                               Process *p, ThreadContext *tc);
@@ -303,6 +308,18 @@ SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p,
 SyscallReturn getpidFunc(SyscallDesc *desc, int num,
                          Process *p, ThreadContext *tc);
 
+// Target bind() handler.
+SyscallReturn bindFunc(SyscallDesc *desc, int num,
+                       Process *p, ThreadContext *tc);
+
+// Target listen() handler.
+SyscallReturn listenFunc(SyscallDesc *desc, int num,
+                         Process *p, ThreadContext *tc);
+
+// Target connect() handler.
+SyscallReturn connectFunc(SyscallDesc *desc, int num,
+                          Process *p, ThreadContext *tc);
+
 #if defined(SYS_getdents)
 // Target getdents() handler.
 SyscallReturn getdentsFunc(SyscallDesc *desc, int num,
@@ -2080,5 +2097,49 @@ tgkillFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
     return 0;
 }
 
+template <class OS>
+SyscallReturn
+socketFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int domain = p->getSyscallArg(tc, index);
+    int type = p->getSyscallArg(tc, index);
+    int prot = p->getSyscallArg(tc, index);
+
+    int sim_fd = socket(domain, type, prot);
+    if (sim_fd == -1)
+        return -errno;
+
+    auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
+    int tgt_fd = p->fds->allocFD(sfdp);
+
+    return tgt_fd;
+}
+
+template <class OS>
+SyscallReturn
+socketpairFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+    int domain = p->getSyscallArg(tc, index);
+    int type = p->getSyscallArg(tc, index);
+    int prot = p->getSyscallArg(tc, index);
+    Addr svPtr = p->getSyscallArg(tc, index);
+
+    BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
+    int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
+    if (status == -1)
+        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->getMemProxy());
+
+    return status;
+}
 
 #endif // __SIM_SYSCALL_EMUL_HH__