summaryrefslogtreecommitdiff
path: root/src/sim/syscall_emul.cc
diff options
context:
space:
mode:
authorBrandon Potter <brandon.potter@amd.com>2018-04-18 14:45:37 -0400
committerAnthony Gutierrez <anthony.gutierrez@amd.com>2018-09-19 20:54:04 +0000
commitf2abc6bb9edbcb23c7e314873b26ca6303a9c1b7 (patch)
tree89bba644fd3934779e9330f45703e59cbdce9512 /src/sim/syscall_emul.cc
parentbed9460aaa6ade07383642e14e5076ce5e456fea (diff)
downloadgem5-f2abc6bb9edbcb23c7e314873b26ca6303a9c1b7.tar.xz
syscall_emul: implement dir-related syscalls
Add getdents, rmdir, chdir, and mknod to SE mode for x86. Change-Id: I387ea3066869e8999bc0064f74070f4e47c1e9a1 Reviewed-on: https://gem5-review.googlesource.com/12112 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Anthony Gutierrez <anthony.gutierrez@amd.com>
Diffstat (limited to 'src/sim/syscall_emul.cc')
-rw-r--r--src/sim/syscall_emul.cc96
1 files changed, 95 insertions, 1 deletions
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index dd2323eaa..794b0bc2c 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -32,10 +32,12 @@
#include "sim/syscall_emul.hh"
#include <fcntl.h>
+#include <syscall.h>
#include <unistd.h>
#include <csignal>
#include <iostream>
+#include <mutex>
#include <string>
#include "arch/utility.hh"
@@ -45,6 +47,7 @@
#include "cpu/thread_context.hh"
#include "dev/net/dist_iface.hh"
#include "mem/page_table.hh"
+#include "sim/byteswap.hh"
#include "sim/process.hh"
#include "sim/sim_exit.hh"
#include "sim/syscall_debug_macros.hh"
@@ -512,7 +515,6 @@ unlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
path = p->fullPath(path);
int result = unlink(path.c_str());
@@ -1105,3 +1107,95 @@ accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
return accessFunc(desc, callnum, p, tc, 0);
}
+SyscallReturn
+mknodFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+ int index = 0;
+ std::string path;
+ if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
+ return -EFAULT;
+
+ path = p->fullPath(path);
+ mode_t mode = p->getSyscallArg(tc, index);
+ dev_t dev = p->getSyscallArg(tc, index);
+
+ auto result = mknod(path.c_str(), mode, dev);
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+chdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+ int index = 0;
+ std::string path;
+ if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
+ return -EFAULT;
+
+ path = p->fullPath(path);
+
+ auto result = chdir(path.c_str());
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+rmdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
+{
+ int index = 0;
+ std::string path;
+ if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
+ return -EFAULT;
+
+ path = p->fullPath(path);
+
+ auto result = rmdir(path.c_str());
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+getdentsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
+{
+ int index = 0;
+ int tgt_fd = p->getSyscallArg(tc, index);
+ Addr buf_ptr = p->getSyscallArg(tc, index);
+ unsigned count = p->getSyscallArg(tc, index);
+
+ auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
+ if (!hbfdp)
+ return -EBADF;
+ int sim_fd = hbfdp->getSimFD();
+
+ BufferArg buf_arg(buf_ptr, count);
+ auto status = syscall(SYS_getdents, sim_fd, buf_arg.bufferPtr(), count);
+
+ if (status == -1)
+ return -errno;
+
+ typedef struct linux_dirent {
+ unsigned long d_ino;
+ unsigned long d_off;
+ unsigned short d_reclen;
+ char dname[];
+ } LinDent;
+
+ unsigned traversed = 0;
+ while (traversed < status) {
+ LinDent *buffer = (LinDent*)((Addr)buf_arg.bufferPtr() + traversed);
+
+ auto host_reclen = buffer->d_reclen;
+
+ /**
+ * Convert the byte ordering from the host to the target before
+ * passing the data back into the target's address space to preserve
+ * endianness.
+ */
+ buffer->d_ino = htog(buffer->d_ino);
+ buffer->d_off = htog(buffer->d_off);
+ buffer->d_reclen = htog(buffer->d_reclen);
+
+ traversed += host_reclen;
+ }
+
+ buf_arg.copyOut(tc->getMemProxy());
+ return status;
+}
+