Brandon Potter has uploaded this change for review. ( https://gem5-review.googlesource.com/2266

Change subject: syscall-emul: Add or extend dup, dup2, and pipe
......................................................................

syscall-emul: Add or extend dup, dup2, and pipe

This changeset extends the pipe system call to work with
architectures other than Alpha (and enables the syscall for
x86). For the dup system call, it sets the clone-on-exec
flag by default. For the dup2 system call, the changeset
adds an implementation (and enables it for x86).

Change-Id: I00ddb416744ee7dd61a5cd02c4c3d97f30543878
---
M src/arch/x86/linux/process.cc
M src/sim/syscall_emul.cc
M src/sim/syscall_emul.hh
3 files changed, 95 insertions(+), 23 deletions(-)



diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc
index f90022b..aad5151 100644
--- a/src/arch/x86/linux/process.cc
+++ b/src/arch/x86/linux/process.cc
@@ -242,7 +242,7 @@
     /*  19 */ SyscallDesc("readv", unimplementedFunc),
     /*  20 */ SyscallDesc("writev", writevFunc<X86Linux64>),
     /*  21 */ SyscallDesc("access", ignoreFunc),
-    /*  22 */ SyscallDesc("pipe", unimplementedFunc),
+    /*  22 */ SyscallDesc("pipe", pipeFunc),
     /*  23 */ SyscallDesc("select", unimplementedFunc),
     /*  24 */ SyscallDesc("sched_yield", unimplementedFunc),
     /*  25 */ SyscallDesc("mremap", mremapFunc<X86Linux64>),
@@ -253,7 +253,7 @@
     /*  30 */ SyscallDesc("shmat", unimplementedFunc),
     /*  31 */ SyscallDesc("shmctl", unimplementedFunc),
     /*  32 */ SyscallDesc("dup", dupFunc),
-    /*  33 */ SyscallDesc("dup2", unimplementedFunc),
+    /*  33 */ SyscallDesc("dup2", dup2Func),
     /*  34 */ SyscallDesc("pause", unimplementedFunc),
     /*  35 */ SyscallDesc("nanosleep", ignoreFunc, SyscallDesc::WarnOnce),
     /*  36 */ SyscallDesc("getitimer", unimplementedFunc),
@@ -591,7 +591,7 @@
     /*  39 */ SyscallDesc("mkdir", unimplementedFunc),
     /*  40 */ SyscallDesc("rmdir", unimplementedFunc),
     /*  41 */ SyscallDesc("dup", dupFunc),
-    /*  42 */ SyscallDesc("pipe", unimplementedFunc),
+    /*  42 */ SyscallDesc("pipe", pipeFunc),
     /*  43 */ SyscallDesc("times", timesFunc<X86Linux32>),
     /*  44 */ SyscallDesc("prof", unimplementedFunc),
     /*  45 */ SyscallDesc("brk", brkFunc),
@@ -612,7 +612,7 @@
     /*  60 */ SyscallDesc("umask", unimplementedFunc),
     /*  61 */ SyscallDesc("chroot", unimplementedFunc),
     /*  62 */ SyscallDesc("ustat", unimplementedFunc),
-    /*  63 */ SyscallDesc("dup2", unimplementedFunc),
+    /*  63 */ SyscallDesc("dup2", dup2Func),
     /*  64 */ SyscallDesc("getppid", unimplementedFunc),
     /*  65 */ SyscallDesc("getpgrp", unimplementedFunc),
     /*  66 */ SyscallDesc("setsid", unimplementedFunc),
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index 9680193..1441592 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -626,13 +626,11 @@
     return (result == -1) ? -errno : result;
 }

-
 /**
- * TODO: there's a bit more involved here since file descriptors created with - * dup are supposed to share a file description. So, there is a problem with
- * maintaining fields like file offset or flags since an update to such a
- * field won't be reflected in the metadata for the fd entries that we
- * maintain to hold metadata for checkpoint restoration.
+ * FIXME: The file description is not shared among file descriptors created
+ * with dup. Really, it's difficult to maintain fields like file offset or
+ * flags since an update to such a field won't be reflected in the metadata
+ * for the fd entries that we maintain for checkpoint restoration.
  */
 SyscallReturn
 dupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
@@ -646,13 +644,44 @@
     int sim_fd = old_hbfdp->getSimFD();

     int result = dup(sim_fd);
-    int local_errno = errno;
+    if (result == -1)
+        return -errno;

-    std::shared_ptr<FDEntry> new_fdep = old_hbfdp->clone();
-    auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(new_fdep);
+ auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
     new_hbfdp->setSimFD(result);
+    new_hbfdp->setCOE(false);
+    return p->fds->allocFD(new_hbfdp);
+}

-    return (result == -1) ? -local_errno : p->fds->allocFD(new_fdep);
+SyscallReturn
+dup2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+    int index = 0;
+
+    int old_tgt_fd = p->getSyscallArg(tc, index);
+ auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
+    if (!old_hbp)
+        return -EBADF;
+    int old_sim_fd = old_hbp->getSimFD();
+
+    /**
+     * We need a valid host file descriptor number to be able to pass into
+     * the second parameter for dup2 (newfd), but we don't know what the
+     * viable numbers are; we execute the open call to retrieve one.
+     */
+    int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
+    if (res_fd == -1)
+        return -errno;
+
+    int new_tgt_fd = p->getSyscallArg(tc, index);
+ auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
+    if (new_hbp)
+        p->fds->closeFDEntry(new_tgt_fd);
+    new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
+    new_hbp->setSimFD(res_fd);
+    new_hbp->setCOE(false);
+
+    return p->fds->allocFD(new_hbp);
 }

 SyscallReturn
@@ -731,23 +760,28 @@
 }

 SyscallReturn
-pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
-               ThreadContext *tc)
+pipeImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
+         bool pseudoPipe)
 {
+    Addr tgt_addr = 0;
+    if (!pseudoPipe) {
+        int index = 0;
+        tgt_addr = p->getSyscallArg(tc, index);
+    }
+
     int sim_fds[2], tgt_fds[2];

     int pipe_retval = pipe(sim_fds);
-    if (pipe_retval < 0)
-        return pipe_retval;
+    if (pipe_retval == -1)
+        return -errno;

     auto rend = PipeFDEntry::EndType::read;
     auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
+    tgt_fds[0] = p->fds->allocFD(rpfd);

     auto wend = PipeFDEntry::EndType::write;
     auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
-
-    tgt_fds[0] = process->fds->allocFD(rpfd);
-    tgt_fds[1] = process->fds->allocFD(wpfd);
+    tgt_fds[1] = p->fds->allocFD(wpfd);

     /**
* Now patch the read object to record the target file descriptor chosen
@@ -759,8 +793,34 @@
      * Alpha Linux convention for pipe() is that fd[0] is returned as
      * the return value of the function, and fd[1] is returned in r20.
      */
-    tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
-    return sim_fds[0];
+    if (pseudoPipe) {
+        tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
+        return tgt_fds[0];
+    }
+
+    /**
+     * 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->getMemProxy());
+    return 0;
+}
+
+SyscallReturn
+pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+               ThreadContext *tc)
+{
+    return pipeImpl(desc, callnum, process, tc, true);
+}
+
+SyscallReturn
+pipeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
+{
+    return pipeImpl(desc, callnum, process, tc, false);
 }

 SyscallReturn
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index d379bbe..d75841c 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -241,6 +241,10 @@
 SyscallReturn dupFunc(SyscallDesc *desc, int num,
                       Process *process, ThreadContext *tc);

+/// Target dup2() handler.
+SyscallReturn dup2Func(SyscallDesc *desc, int num,
+                       Process *process, ThreadContext *tc);
+
 /// Target fcntl() handler.
 SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
                         Process *process, ThreadContext *tc);
@@ -253,6 +257,14 @@
 SyscallReturn setuidFunc(SyscallDesc *desc, int num,
                          Process *p, ThreadContext *tc);

+/// Target pipe() handler.
+SyscallReturn pipeFunc(SyscallDesc *desc, int num,
+                       Process *p, ThreadContext *tc);
+
+/// Internal pipe() handler.
+SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p,
+                       ThreadContext *tc, bool pseudoPipe);
+
 /// Target getpid() handler.
 SyscallReturn getpidFunc(SyscallDesc *desc, int num,
                          Process *p, ThreadContext *tc);

--
To view, visit https://gem5-review.googlesource.com/2266
To unsubscribe, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I00ddb416744ee7dd61a5cd02c4c3d97f30543878
Gerrit-Change-Number: 2266
Gerrit-PatchSet: 1
Gerrit-Owner: Brandon Potter <brandon.pot...@amd.com>
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to