diff options
author | Brandon Potter <brandon.potter@amd.com> | 2018-04-18 14:48:19 -0400 |
---|---|---|
committer | Anthony Gutierrez <anthony.gutierrez@amd.com> | 2019-01-22 01:56:17 +0000 |
commit | a2ed7d5575fb7e847314bb87b92c73459149f2d0 (patch) | |
tree | b632738c83cf8fb429d54706bb5c16e5c45c9643 | |
parent | 2c9f7ebca51eaf8fafd1f854ec0475cb18e9e20c (diff) | |
download | gem5-a2ed7d5575fb7e847314bb87b92c73459149f2d0.tar.xz |
sim-se: add socket-based functionality
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>
-rw-r--r-- | src/arch/x86/linux/process.cc | 12 | ||||
-rw-r--r-- | src/sim/fd_entry.hh | 26 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 80 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 61 |
4 files changed, 173 insertions, 6 deletions
diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 49d3e5aa8..36845971c 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -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>), diff --git a/src/sim/fd_entry.hh b/src/sim/fd_entry.hh index 980011984..6b2b2daa8 100644 --- a/src/sim/fd_entry.hh +++ b/src/sim/fd_entry.hh @@ -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__ diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index e79e79c62..3b35d34e9 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -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; +} diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 3f06869aa..9329f7a5b 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -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__ |