sim-se: add eventfd system call

Change-Id: I7aeb4fe808d0c8f2fb8041e3662d330d8458f09c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/12125
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ciro Santilli <ciro.santilli@arm.com>
Maintainer: Brandon Potter <Brandon.Potter@amd.com>
diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc
index 9e8997a..f19dce3 100644
--- a/src/arch/x86/linux/process.cc
+++ b/src/arch/x86/linux/process.cc
@@ -510,13 +510,13 @@
     /* 281 */ SyscallDesc("epoll_pwait", unimplementedFunc),
     /* 282 */ SyscallDesc("signalfd", unimplementedFunc),
     /* 283 */ SyscallDesc("timerfd_create", unimplementedFunc),
-    /* 284 */ SyscallDesc("eventfd", unimplementedFunc),
+    /* 284 */ SyscallDesc("eventfd", eventfdFunc<X86Linux64>),
     /* 285 */ SyscallDesc("fallocate", fallocateFunc),
     /* 286 */ SyscallDesc("timerfd_settime", unimplementedFunc),
     /* 287 */ SyscallDesc("timerfd_gettime", unimplementedFunc),
     /* 288 */ SyscallDesc("accept4", unimplementedFunc),
     /* 289 */ SyscallDesc("signalfd4", unimplementedFunc),
-    /* 290 */ SyscallDesc("eventfd2", unimplementedFunc),
+    /* 290 */ SyscallDesc("eventfd2", eventfdFunc<X86Linux64>),
     /* 291 */ SyscallDesc("epoll_create1", unimplementedFunc),
     /* 292 */ SyscallDesc("dup3", unimplementedFunc),
     /* 293 */ SyscallDesc("pipe2", unimplementedFunc),
@@ -882,7 +882,7 @@
     /* 320 */ SyscallDesc("utimensat", unimplementedFunc),
     /* 321 */ SyscallDesc("signalfd", unimplementedFunc),
     /* 322 */ SyscallDesc("timerfd", unimplementedFunc),
-    /* 323 */ SyscallDesc("eventfd", unimplementedFunc)
+    /* 323 */ SyscallDesc("eventfd", eventfdFunc<X86Linux32>)
 };
 
 I386LinuxProcess::I386LinuxProcess(ProcessParams * params, ObjectFile *objFile)
diff --git a/src/sim/fd_entry.hh b/src/sim/fd_entry.hh
index 15e174a..94c874a 100644
--- a/src/sim/fd_entry.hh
+++ b/src/sim/fd_entry.hh
@@ -80,6 +80,16 @@
         : FDEntry(close_on_exec), _flags(flags), _simFD(sim_fd)
     { }
 
+    HBFDEntry(HBFDEntry const& reg, bool close_on_exec = false)
+        : FDEntry(close_on_exec), _flags(reg._flags), _simFD(reg._simFD)
+    { }
+
+    std::shared_ptr<FDEntry>
+    clone() const override
+    {
+        return std::make_shared<HBFDEntry>(*this);
+    }
+
     int getFlags() const { return _flags; }
     int getSimFD() const { return _simFD; }
 
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index a9490fa..bfec1f5 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -57,6 +57,12 @@
 using namespace std;
 using namespace TheISA;
 
+void
+warnUnsupportedOS(std::string syscall_name)
+{
+    warn("Cannot invoke %s on host operating system.", syscall_name);
+}
+
 SyscallReturn
 unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
                   ThreadContext *tc)
@@ -1036,9 +1042,7 @@
 SyscallReturn
 fallocateFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
 {
-#if NO_FALLOCATE
-    warn("Host OS cannot support calls to fallocate. Ignoring syscall");
-#else
+#if __linux__
     int index = 0;
     int tgt_fd = p->getSyscallArg(tc, index);
     int mode = p->getSyscallArg(tc, index);
@@ -1053,8 +1057,11 @@
     int result = fallocate(sim_fd, mode, offset, len);
     if (result < 0)
         return -errno;
-#endif
     return 0;
+#else
+    warnUnsupportedOS("fallocate");
+    return -1;
+#endif
 }
 
 SyscallReturn
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 7996027..91db9ae 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -53,26 +53,18 @@
 #define NO_STAT64 0
 #endif
 
-#if (defined(__APPLE__) || defined(__OpenBSD__) ||      \
-     defined(__FreeBSD__) || defined(__NetBSD__))
-#define NO_STATFS 1
-#else
-#define NO_STATFS 0
-#endif
-
-#if (defined(__APPLE__) || defined(__OpenBSD__) ||      \
-     defined(__FreeBSD__) || defined(__NetBSD__))
-#define NO_FALLOCATE 1
-#else
-#define NO_FALLOCATE 0
-#endif
-
 ///
 /// @file syscall_emul.hh
 ///
 /// This file defines objects used to emulate syscalls from the target
 /// application on the host machine.
 
+#ifdef __linux__
+#include <sys/eventfd.h>
+#include <sys/statfs.h>
+
+#endif
+
 #ifdef __CYGWIN32__
 #include <sys/fcntl.h>
 
@@ -84,14 +76,6 @@
 #include <sys/mman.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
-
-#if (NO_STATFS == 0)
-#include <sys/statfs.h>
-
-#else
-#include <sys/mount.h>
-
-#endif
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -133,6 +117,7 @@
 //
 //////////////////////////////////////////////////////////////////////
 
+void warnUnsupportedOS(std::string syscall_name);
 
 /// Handler for unimplemented syscalls that we haven't thought about.
 SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
@@ -1530,9 +1515,7 @@
 statfsFunc(SyscallDesc *desc, int callnum, Process *process,
            ThreadContext *tc)
 {
-#if NO_STATFS
-    warn("Host OS cannot support calls to statfs. Ignoring syscall");
-#else
+#ifdef __linux__
     std::string path;
 
     int index = 0;
@@ -1552,8 +1535,11 @@
         return -errno;
 
     copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
-#endif
     return 0;
+#else
+    warnUnsupportedOS("statfs");
+    return -1;
+#endif
 }
 
 template <class OS>
@@ -2860,4 +2846,32 @@
     return p->fds->allocFD(afdp);
 }
 
+/// Target eventfd() function.
+template <class OS>
+SyscallReturn
+eventfdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+#ifdef __linux__
+    int index = 0;
+    unsigned initval = p->getSyscallArg(tc, index);
+    int in_flags = p->getSyscallArg(tc, index);
+
+    int sim_fd = eventfd(initval, in_flags);
+    if (sim_fd == -1)
+        return -errno;
+
+    bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
+
+    int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
+    flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
+
+    auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
+    int tgt_fd = p->fds->allocFD(hbfdp);
+    return tgt_fd;
+#else
+    warnUnsupportedOS("eventfd");
+    return -1;
+#endif
+}
+
 #endif // __SIM_SYSCALL_EMUL_HH__