gem5  v22.0.0.2
syscall_emul.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2015, 2019-2021 Arm Limited
3  * Copyright (c) 2015 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2003-2005 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #ifndef __SIM_SYSCALL_EMUL_HH__
43 #define __SIM_SYSCALL_EMUL_HH__
44 
45 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
46  defined(__FreeBSD__) || defined(__CYGWIN__) || \
47  defined(__NetBSD__))
48 #define NO_STAT64 1
49 #else
50 #define NO_STAT64 0
51 #endif
52 
58 
59 #if defined(__linux__)
60 #include <sched.h>
61 #include <sys/eventfd.h>
62 #include <sys/statfs.h>
63 
64 #else
65 #include <sys/mount.h>
66 
67 #endif
68 
69 #ifdef __CYGWIN32__
70 #include <sys/fcntl.h>
71 
72 #endif
73 #include <fcntl.h>
74 #include <net/if.h>
75 #include <poll.h>
76 #include <sys/ioctl.h>
77 #include <sys/mman.h>
78 #include <sys/socket.h>
79 #include <sys/stat.h>
80 #include <sys/time.h>
81 #include <sys/types.h>
82 #include <sys/uio.h>
83 #include <unistd.h>
84 
85 #include <cerrno>
86 #include <memory>
87 #include <string>
88 
89 #include "arch/generic/tlb.hh"
90 #include "base/intmath.hh"
92 #include "base/logging.hh"
93 #include "base/random.hh"
94 #include "base/trace.hh"
95 #include "base/types.hh"
96 #include "config/the_isa.hh"
97 #include "cpu/base.hh"
98 #include "cpu/thread_context.hh"
99 #include "kern/linux/linux.hh"
100 #include "mem/page_table.hh"
102 #include "params/Process.hh"
103 #include "sim/emul_driver.hh"
104 #include "sim/futex_map.hh"
105 #include "sim/guest_abi.hh"
106 #include "sim/process.hh"
107 #include "sim/proxy_ptr.hh"
109 #include "sim/syscall_desc.hh"
110 #include "sim/syscall_emul_buf.hh"
111 #include "sim/syscall_return.hh"
112 
113 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
114 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
115 #elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
116 #define CMSG_ALIGN(n) _ALIGN(n)
117 #endif
118 
119 namespace gem5
120 {
121 
123 //
124 // The following emulation functions are generic enough that they
125 // don't need to be recompiled for different emulated OS's. They are
126 // defined in sim/syscall_emul.cc.
127 //
129 
130 void warnUnsupportedOS(std::string syscall_name);
131 
133 SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);
134 
139 SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
141 SyscallReturn
142 ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc);
143 
145 SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status);
146 
148 SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status);
149 
151 SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc,
152  uint64_t tidPtr);
153 
155 SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc);
156 
158 SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
159 
161 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
162 
164 SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc,
165  int tgt_fd, uint64_t offs, int whence);
166 
168 SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
169  int tgt_fd, uint64_t offset_high,
170  uint32_t offset_low, VPtr<> result_ptr, int whence);
171 
173 SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
174  int tgt_fd, int how);
175 
177 SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc,
178  VPtr<> buf_ptr, int name_len);
179 
181 SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc,
182  VPtr<> buf_ptr, unsigned long size);
183 
185 SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
186  VPtr<> pathname);
187 SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc,
188  std::string path);
189 
191 SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc,
192  VPtr<> pathname, VPtr<> new_pathname);
193 
195 SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
196  VPtr<> pathname, VPtr<> new_pathname);
197 
199 SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
200  VPtr<> pathname, mode_t mode);
201 SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
202  std::string path, mode_t mode);
203 
205 SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc,
206  VPtr<> pathname, mode_t mode, dev_t dev);
207 SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc,
208  std::string path, mode_t mode, dev_t dev);
209 
211 SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
212 
213 // Target rmdir() handler.
214 SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc,
215  VPtr<> pathname);
216 SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc,
217  std::string path);
218 
220 SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc,
221  VPtr<> oldpath, VPtr<> newpath);
222 SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc,
223  std::string oldpath, std::string newpath);
224 
226 SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc,
227  VPtr<> pathname, int64_t length);
228 
230 SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc,
231  int tgt_fd, int64_t length);
232 
234 SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc);
235 
237 SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc);
238 
240 SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc,
241  VPtr<> pathname, uint32_t owner, uint32_t group);
242 SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc,
243  std::string path, uint32_t owner, uint32_t group);
244 
246 SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
247 
249 SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
250  int pid, int pgid);
251 
253 SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc,
254  int tgt_fd, uint32_t owner, uint32_t group);
255 
257 SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc,
258  int tgt_fd);
259 
261 SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc,
262  int old_tgt_fd, int new_tgt_fd);
263 
265 SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
266  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs);
267 
269 SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
270  int tgt_fd, int cmd);
271 
273 SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
274 
276 SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc,
277  VPtr<> tgt_addr, int flags);
278 
280 SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc);
281 
282 // Target getpeername() handler.
283 SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc,
284  int tgt_fd, VPtr<> sockAddrPtr,
285  VPtr<> addrlenPtr);
286 
287 // Target bind() handler.
288 SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc,
289  int tgt_fd, VPtr<> buf_ptr, int addrlen);
290 
291 // Target listen() handler.
292 SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc,
293  int tgt_fd, int backlog);
294 
295 // Target connect() handler.
296 SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc,
297  int tgt_fd, VPtr<> buf_ptr, int addrlen);
298 
299 #if defined(SYS_getdents)
300 // Target getdents() handler.
301 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
302  int tgt_fd, VPtr<> buf_ptr, unsigned count);
303 #endif
304 
305 #if defined(SYS_getdents64)
306 // Target getdents() handler.
307 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
308  int tgt_fd, VPtr<> buf_ptr, unsigned count);
309 #endif
310 
311 // Target recvmsg() handler.
312 SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
313  int tgt_fd, VPtr<> msgPtr, int flags);
314 
315 // Target sendmsg() handler.
316 SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
317  int tgt_fd, VPtr<> msgPtr, int flags);
318 
319 // Target getuid() handler.
320 SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc);
321 
323 SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc);
324 
326 SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc);
327 
329 SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
330 
332 SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc);
333 
335 SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc,
336  VPtr<> pathname, mode_t mode);
337 SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc,
338  std::string path, mode_t mode);
339 
340 // Target getsockopt() handler.
341 SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
342  int tgt_fd, int level, int optname,
343  VPtr<> valPtr, VPtr<> lenPtr);
344 
345 // Target setsockopt() handler.
346 SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
347  int tgt_fd, int level, int optname,
348  VPtr<> valPtr, socklen_t len);
349 
350 SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
351  VPtr<uint32_t> cpu, VPtr<uint32_t> node,
352  VPtr<uint32_t> tcache);
353 
354 // Target getsockname() handler.
355 SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc,
356  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
357 
358 template <class OS>
359 SyscallReturn
360 atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
361 {
362  // If pathname is absolute, then dirfd is ignored.
363  if (dirfd != OS::TGT_AT_FDCWD && !startswith(path, "/")) {
364  auto process = tc->getProcessPtr();
365 
366  std::shared_ptr<FDEntry> fdep = ((*process->fds)[dirfd]);
367  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
368  if (!ffdp)
369  return -EBADF;
370 
371  if (path.empty())
372  path = ffdp->getFileName();
373  else
374  path = ffdp->getFileName() + "/" + path;
375  }
376 
377  return 0;
378 }
379 
383 template <class OS>
384 SyscallReturn
386  VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
387 {
388  auto process = tc->getProcessPtr();
389 
390  /*
391  * Unsupported option that does not affect the correctness of the
392  * application. This is a performance optimization utilized by Linux.
393  */
394  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
395  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
396 
397  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
398 
399  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
400  // Ensure futex system call accessed atomically.
401  BufferArg buf(uaddr, sizeof(int));
403  int mem_val = *(int*)buf.bufferPtr();
404 
405  /*
406  * The value in memory at uaddr is not equal with the expected val
407  * (a different thread must have changed it before the system call was
408  * invoked). In this case, we need to throw an error.
409  */
410  if (val != mem_val)
411  return -OS::TGT_EWOULDBLOCK;
412 
413  if (OS::TGT_FUTEX_WAIT == op) {
414  futex_map.suspend(uaddr, process->tgid(), tc);
415  } else {
416  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
417  }
418 
419  return 0;
420  } else if (OS::TGT_FUTEX_WAKE == op) {
421  return futex_map.wakeup(uaddr, process->tgid(), val);
422  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
423  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
424  } else if (OS::TGT_FUTEX_REQUEUE == op ||
425  OS::TGT_FUTEX_CMP_REQUEUE == op) {
426 
427  // Ensure futex system call accessed atomically.
428  BufferArg buf(uaddr, sizeof(int));
430  int mem_val = *(int*)buf.bufferPtr();
431  /*
432  * For CMP_REQUEUE, the whole operation is only started only if
433  * val3 is still the value of the futex pointed to by uaddr.
434  */
435  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
436  return -OS::TGT_EWOULDBLOCK;
437  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
438  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
439  /*
440  * The FUTEX_WAKE_OP operation is equivalent to executing the
441  * following code atomically and totally ordered with respect to
442  * other futex operations on any of the two supplied futex words:
443  *
444  * int oldval = *(int *) addr2;
445  * *(int *) addr2 = oldval op oparg;
446  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
447  * if (oldval cmp cmparg)
448  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
449  *
450  * (op, oparg, cmp, cmparg are encoded in val3)
451  *
452  * +---+---+-----------+-----------+
453  * |op |cmp| oparg | cmparg |
454  * +---+---+-----------+-----------+
455  * 4 4 12 12 <== # of bits
456  *
457  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
458  *
459  */
460  // get value from simulated-space
461  BufferArg buf(uaddr2, sizeof(int));
463  int oldval = *(int*)buf.bufferPtr();
464  int newval = oldval;
465  // extract op, oparg, cmp, cmparg from val3
466  int wake_cmparg = val3 & 0xfff;
467  int wake_oparg = (val3 & 0xfff000) >> 12;
468  int wake_cmp = (val3 & 0xf000000) >> 24;
469  int wake_op = (val3 & 0xf0000000) >> 28;
470  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
471  wake_oparg = (1 << wake_oparg);
472  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
473  // perform operation on the value of the second futex
474  if (wake_op == OS::TGT_FUTEX_OP_SET)
475  newval = wake_oparg;
476  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
477  newval += wake_oparg;
478  else if (wake_op == OS::TGT_FUTEX_OP_OR)
479  newval |= wake_oparg;
480  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
481  newval &= ~wake_oparg;
482  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
483  newval ^= wake_oparg;
484  // copy updated value back to simulated-space
485  *(int*)buf.bufferPtr() = newval;
487  // perform the first wake-up
488  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
489  int woken2 = 0;
490  // calculate the condition of the second wake-up
491  bool is_wake2 = false;
492  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
493  is_wake2 = oldval == wake_cmparg;
494  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
495  is_wake2 = oldval != wake_cmparg;
496  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
497  is_wake2 = oldval < wake_cmparg;
498  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
499  is_wake2 = oldval <= wake_cmparg;
500  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
501  is_wake2 = oldval > wake_cmparg;
502  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
503  is_wake2 = oldval >= wake_cmparg;
504  // perform the second wake-up
505  if (is_wake2)
506  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
507 
508  return woken1 + woken2;
509  }
510  warn("futex: op %d not implemented; ignoring.", op);
511  return -ENOSYS;
512 }
513 
516 SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
517 
518 
522 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
523 
526 template <class T1, class T2>
527 void
528 getElapsedTimeMicro(T1 &sec, T2 &usec)
529 {
530  static const int OneMillion = 1000 * 1000;
531 
532  uint64_t elapsed_usecs = curTick() / sim_clock::as_int::us;
533  sec = elapsed_usecs / OneMillion;
534  usec = elapsed_usecs % OneMillion;
535 }
536 
539 template <class T1, class T2>
540 void
541 getElapsedTimeNano(T1 &sec, T2 &nsec)
542 {
543  static const int OneBillion = 1000 * 1000 * 1000;
544 
545  uint64_t elapsed_nsecs = curTick() / sim_clock::as_int::ns;
546  sec = elapsed_nsecs / OneBillion;
547  nsec = elapsed_nsecs % OneBillion;
548 }
549 
551 //
552 // The following emulation functions are generic, but need to be
553 // templated to account for differences in types, constants, etc.
554 //
556 
557  typedef struct statfs hst_statfs;
558 #if NO_STAT64
559  typedef struct stat hst_stat;
560  typedef struct stat hst_stat64;
561 #else
562  typedef struct stat hst_stat;
563  typedef struct stat64 hst_stat64;
564 #endif
565 
569 
570 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
571 void
572 copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
573 {
574  constexpr ByteOrder bo = OS::byteOrder;
575 
576  if (fakeTTY)
577  tgt->st_dev = 0xA;
578  else
579  tgt->st_dev = host->st_dev;
580  tgt->st_dev = htog(tgt->st_dev, bo);
581  tgt->st_ino = host->st_ino;
582  tgt->st_ino = htog(tgt->st_ino, bo);
583  tgt->st_mode = host->st_mode;
584  if (fakeTTY) {
585  // Claim to be a character device
586  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
587  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
588  }
589  tgt->st_mode = htog(tgt->st_mode, bo);
590  tgt->st_nlink = host->st_nlink;
591  tgt->st_nlink = htog(tgt->st_nlink, bo);
592  tgt->st_uid = host->st_uid;
593  tgt->st_uid = htog(tgt->st_uid, bo);
594  tgt->st_gid = host->st_gid;
595  tgt->st_gid = htog(tgt->st_gid, bo);
596  if (fakeTTY)
597  tgt->st_rdev = 0x880d;
598  else
599  tgt->st_rdev = host->st_rdev;
600  tgt->st_rdev = htog(tgt->st_rdev, bo);
601  tgt->st_size = host->st_size;
602  tgt->st_size = htog(tgt->st_size, bo);
603  tgt->st_atimeX = host->st_atime;
604  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
605  tgt->st_mtimeX = host->st_mtime;
606  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
607  tgt->st_ctimeX = host->st_ctime;
608  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
609  // Force the block size to be 8KB. This helps to ensure buffered io works
610  // consistently across different hosts.
611  tgt->st_blksize = 0x2000;
612  tgt->st_blksize = htog(tgt->st_blksize, bo);
613  tgt->st_blocks = host->st_blocks;
614  tgt->st_blocks = htog(tgt->st_blocks, bo);
615 }
616 
617 // Same for stat64
618 
619 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
620 void
621 copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host,
622  bool fakeTTY=false)
623 {
624  copyOutStatBuf<OS>(tgt, host, fakeTTY);
625 #if defined(STAT_HAVE_NSEC)
626  constexpr ByteOrder bo = OS::byteOrder;
627 
628  tgt->st_atime_nsec = host->st_atime_nsec;
629  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
630  tgt->st_mtime_nsec = host->st_mtime_nsec;
631  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
632  tgt->st_ctime_nsec = host->st_ctime_nsec;
633  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
634 #else
635  tgt->st_atime_nsec = 0;
636  tgt->st_mtime_nsec = 0;
637  tgt->st_ctime_nsec = 0;
638 #endif
639 }
640 
641 template <class OS, typename TgtStatPtr, typename HostStatPtr>
642 void
643 copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
644 {
645  constexpr ByteOrder bo = OS::byteOrder;
646 
647  tgt->f_type = htog(host->f_type, bo);
648 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
649  tgt->f_bsize = htog(host->f_iosize, bo);
650 #else
651  tgt->f_bsize = htog(host->f_bsize, bo);
652 #endif
653  tgt->f_blocks = htog(host->f_blocks, bo);
654  tgt->f_bfree = htog(host->f_bfree, bo);
655  tgt->f_bavail = htog(host->f_bavail, bo);
656  tgt->f_files = htog(host->f_files, bo);
657  tgt->f_ffree = htog(host->f_ffree, bo);
658  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
659 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
660  tgt->f_namelen = htog(host->f_namemax, bo);
661  tgt->f_frsize = htog(host->f_bsize, bo);
662 #elif defined(__APPLE__)
663  tgt->f_namelen = 0;
664  tgt->f_frsize = 0;
665 #else
666  tgt->f_namelen = htog(host->f_namelen, bo);
667  tgt->f_frsize = htog(host->f_frsize, bo);
668 #endif
669 #if defined(__linux__)
670  memcpy(&tgt->f_spare, &host->f_spare,
671  std::min(sizeof(host->f_spare), sizeof(tgt->f_spare)));
672 #else
673  /*
674  * The fields are different sizes per OS. Don't bother with
675  * f_spare or f_reserved on non-Linux for now.
676  */
677  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
678 #endif
679 }
680 
685 template <class OS>
686 SyscallReturn
688  int tgt_fd, unsigned req, VPtr<> addr)
689 {
690  auto p = tc->getProcessPtr();
691 
692  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
693 
694  if (OS::isTtyReq(req))
695  return -ENOTTY;
696 
697  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
698  if (dfdp) {
699  EmulatedDriver *emul_driver = dfdp->getDriver();
700  if (emul_driver)
701  return emul_driver->ioctl(tc, req, addr);
702  }
703 
704  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
705  if (sfdp) {
706  int status;
707 
708  switch (req) {
709  case SIOCGIFCONF: {
710  BufferArg conf_arg(addr, sizeof(ifconf));
711  conf_arg.copyIn(SETranslatingPortProxy(tc));
712 
713  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
714  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
715  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
716  ifc_buf_arg.copyIn(SETranslatingPortProxy(tc));
717 
718  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
719 
720  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
721  if (status != -1) {
722  conf->ifc_buf = (char*)ifc_buf_addr;
723  ifc_buf_arg.copyOut(SETranslatingPortProxy(tc));
724  conf_arg.copyOut(SETranslatingPortProxy(tc));
725  }
726 
727  return status;
728  }
729  case SIOCGIFFLAGS:
730 #if defined(__linux__)
731  case SIOCGIFINDEX:
732 #endif
733  case SIOCGIFNETMASK:
734  case SIOCGIFADDR:
735 #if defined(__linux__)
736  case SIOCGIFHWADDR:
737 #endif
738  case SIOCGIFMTU: {
739  BufferArg req_arg(addr, sizeof(ifreq));
740  req_arg.copyIn(SETranslatingPortProxy(tc));
741 
742  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
743  if (status != -1)
744  req_arg.copyOut(SETranslatingPortProxy(tc));
745  return status;
746  }
747  }
748  }
749 
754  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
755  tgt_fd, req, tc->pcState());
756  return -ENOTTY;
757 }
758 
760 template <class OS>
761 SyscallReturn
763  int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
764 {
765  auto p = tc->getProcessPtr();
766 
771  std::string path;
772  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
773  return -EFAULT;
774 
775 #ifdef __CYGWIN32__
776  int host_flags = O_BINARY;
777 #else
778  int host_flags = 0;
779 #endif
780 
784  for (const auto &p: OS::openFlagTable) {
785  if (tgt_flags & p.first) {
786  tgt_flags &= ~p.first;
787  host_flags |= p.second;
788  }
789  }
790  warn_if(tgt_flags, "%s: cannot decode flags %#x", desc->name(), tgt_flags);
791 
792 #ifdef __CYGWIN32__
793  host_flags |= O_BINARY;
794 #endif
795 
808  std::string redir_path = path;
809  std::string abs_path = path;
810  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
811  abs_path = p->absolutePath(path, true);
812  redir_path = p->checkPathRedirect(path);
813  } else if (!startswith(path, "/")) {
814  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
815  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
816  if (!ffdp)
817  return -EBADF;
818  abs_path = ffdp->getFileName() + path;
819  redir_path = p->checkPathRedirect(abs_path);
820  }
821 
828  if (startswith(abs_path, "/dev/")) {
829  std::string filename = abs_path.substr(strlen("/dev/"));
830  EmulatedDriver *drv = p->findDriver(filename);
831  if (drv) {
832  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
833  "driver open with path[%s]\n",
834  desc->name(), abs_path.c_str());
835  return drv->open(tc, mode, host_flags);
836  }
841  }
842 
867  int sim_fd = -1;
868  std::string used_path;
869  std::vector<std::string> special_paths =
870  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
871  "/proc/self/maps", "/dev/urandom",
872  "/sys/devices/system/cpu/online" };
873  for (auto entry : special_paths) {
874  if (startswith(path, entry)) {
875  sim_fd = OS::openSpecialFile(abs_path, p, tc);
876  used_path = abs_path;
877  }
878  }
879  if (sim_fd == -1) {
880  sim_fd = open(redir_path.c_str(), host_flags, mode);
881  used_path = redir_path;
882  }
883  if (sim_fd == -1) {
884  int local = -errno;
885  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
886  "(inferred from:%s)\n", desc->name(),
887  used_path.c_str(), path.c_str());
888  return local;
889  }
890 
899  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
900  // Record the file mode for checkpoint restoring
901  ffdp->setFileMode(mode);
902  int tgt_fd = p->fds->allocFD(ffdp);
903  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
904  "(inferred from:%s)\n", desc->name(),
905  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
906  return tgt_fd;
907 }
908 
910 template <class OS>
911 SyscallReturn
913  VPtr<> pathname, int tgt_flags, int mode)
914 {
915  return openatFunc<OS>(
916  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
917 }
918 
920 template <class OS>
921 SyscallReturn
923  int dirfd, VPtr<> pathname, int flags)
924 {
925  std::string path;
926  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
927  return -EFAULT;
928 
929  // Modifying path from the directory descriptor
930  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
931  return res;
932  }
933 
934  if (flags & OS::TGT_AT_REMOVEDIR) {
935  return rmdirImpl(desc, tc, path);
936  } else {
937  return unlinkImpl(desc, tc, path);
938  }
939 }
940 
942 template <class OS>
943 SyscallReturn
945  int dirfd, VPtr<> pathname, int mode)
946 {
947  std::string path;
948  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
949  return -EFAULT;
950 
951  // Modifying path from the directory descriptor
952  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
953  return res;
954  }
955 
956  return accessImpl(desc, tc, path, mode);
957 }
958 
960 template <class OS>
961 SyscallReturn
963  int dirfd, VPtr<> pathname, VPtr<> buf_ptr,
964  typename OS::size_t bufsiz)
965 {
966  std::string path;
967  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
968  return -EFAULT;
969 
970  // Modifying path from the directory descriptor
971  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
972  return res;
973  }
974 
975  auto p = tc->getProcessPtr();
976 
977  // Adjust path for cwd and redirection
978  path = p->checkPathRedirect(path);
979 
980  BufferArg buf(buf_ptr, bufsiz);
981 
982  int result = -1;
983  if (path != "/proc/self/exe") {
984  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
985  } else {
986  // Emulate readlink() called on '/proc/self/exe' should return the
987  // absolute path of the binary running in the simulated system (the
988  // Process' executable). It is possible that using this path in
989  // the simulated system will result in unexpected behavior if:
990  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
991  // called binary calls readlink().
992  // 2) The host's full path to the running benchmark changes from one
993  // simulation to another. This can result in different simulated
994  // performance since the simulated system will process the binary
995  // path differently, even if the binary itself does not change.
996 
997  // Get the absolute canonical path to the running application
998  char real_path[PATH_MAX];
999  char *check_real_path = realpath(p->progName(), real_path);
1000  if (!check_real_path) {
1001  fatal("readlink('/proc/self/exe') unable to resolve path to "
1002  "executable: %s", p->progName());
1003  }
1004  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
1005  typename OS::size_t real_path_len = strlen(real_path);
1006  if (real_path_len > bufsiz) {
1007  // readlink will truncate the contents of the
1008  // path to ensure it is no more than bufsiz
1009  result = bufsiz;
1010  } else {
1011  result = real_path_len;
1012  }
1013 
1014  // Issue a warning about potential unexpected results
1015  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
1016  "results in various settings.\n Returning '%s'\n",
1017  (char*)buf.bufferPtr());
1018  }
1019 
1021 
1022  return (result == -1) ? -errno : result;
1023 }
1024 
1026 template <class OS>
1027 SyscallReturn
1029  VPtr<> pathname, VPtr<> buf_ptr,
1030  typename OS::size_t bufsiz)
1031 {
1032  return readlinkatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD,
1033  pathname, buf_ptr, bufsiz);
1034 }
1035 
1037 template <class OS>
1038 SyscallReturn
1040  int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
1041 {
1042  SETranslatingPortProxy proxy(tc);
1043  std::string old_name;
1044  if (!proxy.tryReadString(old_name, oldpath))
1045  return -EFAULT;
1046 
1047  std::string new_name;
1048  if (!proxy.tryReadString(new_name, newpath))
1049  return -EFAULT;
1050 
1051  // Modifying old_name from the directory descriptor
1052  if (auto res = atSyscallPath<OS>(tc, olddirfd, old_name); !res.successful()) {
1053  return res;
1054  }
1055 
1056  // Modifying new_name from the directory descriptor
1057  if (auto res = atSyscallPath<OS>(tc, newdirfd, new_name); !res.successful()) {
1058  return res;
1059  }
1060 
1061  return renameImpl(desc, tc, old_name, new_name);
1062 }
1063 
1065 template <class OS>
1066 SyscallReturn
1068  int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group,
1069  int flags)
1070 {
1071  std::string path;
1072  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1073  return -EFAULT;
1074 
1075  // Modifying path from the directory descriptor
1076  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1077  return res;
1078  }
1079 
1080  return chownImpl(desc, tc, path, owner, group);
1081 }
1082 
1084 template <class OS>
1085 SyscallReturn
1087  int dirfd, VPtr<> pathname, mode_t mode)
1088 {
1089  std::string path;
1090  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1091  return -EFAULT;
1092 
1093  // Modifying path from the directory descriptor
1094  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1095  return res;
1096  }
1097 
1098  return mkdirImpl(desc, tc, path, mode);
1099 }
1100 
1102 template <class OS>
1103 SyscallReturn
1105  int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
1106 {
1107  std::string path;
1108  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1109  return -EFAULT;
1110 
1111  // Modifying path from the directory descriptor
1112  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1113  return res;
1114  }
1115 
1116  return mknodImpl(desc, tc, path, mode, dev);
1117 }
1118 
1120 template <class OS>
1121 SyscallReturn
1124 {
1125  auto process = tc->getProcessPtr();
1126 
1127  sysinfo->uptime = seconds_since_epoch;
1128  sysinfo->totalram = process->system->memSize();
1129  sysinfo->mem_unit = 1;
1130 
1131  return 0;
1132 }
1133 
1135 template <class OS>
1136 SyscallReturn
1138  int dirfd, VPtr<> pathname, mode_t mode)
1139 {
1140  std::string path;
1141  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1142  return -EFAULT;
1143 
1144  // Modifying path from the directory descriptor
1145  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1146  return res;
1147  }
1148 
1149  mode_t hostMode = 0;
1150 
1151  // XXX translate mode flags via OS::something???
1152  hostMode = mode;
1153 
1154  auto process = tc->getProcessPtr();
1155  // Adjust path for cwd and redirection
1156  path = process->checkPathRedirect(path);
1157 
1158  // do the chmod
1159  int result = chmod(path.c_str(), hostMode);
1160  if (result < 0)
1161  return -errno;
1162 
1163  return 0;
1164 }
1165 
1167 template <class OS>
1168 SyscallReturn
1169 chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
1170 {
1171  return fchmodatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, mode);
1172 }
1173 
1174 template <class OS>
1175 SyscallReturn
1177  VPtr<> fdsPtr, int nfds, int tmout)
1178 {
1179  auto p = tc->getProcessPtr();
1180 
1181  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1182  fdsBuf.copyIn(SETranslatingPortProxy(tc));
1183 
1190  int temp_tgt_fds[nfds];
1191  for (int index = 0; index < nfds; index++) {
1192  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1193  auto tgt_fd = temp_tgt_fds[index];
1194  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1195  if (!hbfdp)
1196  return -EBADF;
1197  auto host_fd = hbfdp->getSimFD();
1198  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1199  }
1200 
1207  int status;
1208  if (tmout < 0) {
1209  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1210  if (status == 0) {
1216  System *sysh = tc->getSystemPtr();
1218  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1219  if (it->receiver == p)
1220  return -EINTR;
1221  return SyscallReturn::retry();
1222  }
1223  } else
1224  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1225 
1226  if (status == -1)
1227  return -errno;
1228 
1233  for (int index = 0; index < nfds; index++) {
1234  auto tgt_fd = temp_tgt_fds[index];
1235  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1236  }
1237 
1242  fdsBuf.copyOut(SETranslatingPortProxy(tc));
1243 
1244  return status;
1245 }
1246 
1248 template <class OS>
1249 SyscallReturn
1250 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1251 {
1252  auto p = tc->getProcessPtr();
1253 
1254  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1255  if (!ffdp)
1256  return -EBADF;
1257  int sim_fd = ffdp->getSimFD();
1258 
1259  mode_t hostMode = mode;
1260 
1261  int result = fchmod(sim_fd, hostMode);
1262 
1263  return (result < 0) ? -errno : 0;
1264 }
1265 
1267 template <class OS>
1268 SyscallReturn
1270  VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1272 {
1273  auto p = tc->getProcessPtr();
1274  Addr page_bytes = p->pTable->pageSize();
1275  uint64_t provided_address = 0;
1276  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1277 
1278  if (use_provided_address)
1279  provided_address = varargs.get<uint64_t>();
1280 
1281  if ((start % page_bytes != 0) ||
1282  (provided_address % page_bytes != 0)) {
1283  warn("mremap failing: arguments not page aligned");
1284  return -EINVAL;
1285  }
1286 
1287  new_length = roundUp(new_length, page_bytes);
1288 
1289  if (new_length > old_length) {
1290  Addr mmap_end = p->memState->getMmapEnd();
1291 
1292  if ((start + old_length) == mmap_end &&
1293  (!use_provided_address || provided_address == start)) {
1294  // This case cannot occur when growing downward, as
1295  // start is greater than or equal to mmap_end.
1296  uint64_t diff = new_length - old_length;
1297  p->memState->mapRegion(mmap_end, diff, "remapped");
1298  p->memState->setMmapEnd(mmap_end + diff);
1299  return (Addr)start;
1300  } else {
1301  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1302  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1303  return -ENOMEM;
1304  } else {
1305  uint64_t new_start = provided_address;
1306  if (!use_provided_address) {
1307  new_start = p->mmapGrowsDown() ?
1308  mmap_end - new_length : mmap_end;
1309  mmap_end = p->mmapGrowsDown() ?
1310  new_start : mmap_end + new_length;
1311  p->memState->setMmapEnd(mmap_end);
1312  }
1313 
1314  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1315  new_start, new_start + new_length,
1316  new_length - old_length);
1317 
1318  // add on the remaining unallocated pages
1319  p->allocateMem(new_start + old_length,
1320  new_length - old_length,
1321  use_provided_address /* clobber */);
1322 
1323  if (use_provided_address &&
1324  ((new_start + new_length > p->memState->getMmapEnd() &&
1325  !p->mmapGrowsDown()) ||
1326  (new_start < p->memState->getMmapEnd() &&
1327  p->mmapGrowsDown()))) {
1328  // something fishy going on here, at least notify the user
1329  // @todo: increase mmap_end?
1330  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1331  }
1332 
1333  warn("returning %08p as start\n", new_start);
1334  p->memState->remapRegion(start, new_start, old_length);
1335  return new_start;
1336  }
1337  }
1338  } else {
1339  // Shrink a region
1340  if (use_provided_address && provided_address != start)
1341  p->memState->remapRegion(start, provided_address, new_length);
1342  if (new_length != old_length)
1343  p->memState->unmapRegion(start + new_length,
1344  old_length - new_length);
1345  return use_provided_address ? provided_address : (Addr)start;
1346  }
1347 }
1348 
1350 template <class OS>
1351 SyscallReturn
1353  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1354 {
1355  std::string path;
1356  auto process = tc->getProcessPtr();
1357 
1358  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1359  return -EFAULT;
1360 
1361  // Adjust path for cwd and redirection
1362  path = process->checkPathRedirect(path);
1363 
1364  struct stat hostBuf;
1365  int result = stat(path.c_str(), &hostBuf);
1366 
1367  if (result < 0)
1368  return -errno;
1369 
1370  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1371 
1372  return 0;
1373 }
1374 
1376 template <class OS>
1377 SyscallReturn
1379  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat,
1380  int flags)
1381 {
1382  std::string path;
1383 
1384  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1385  return -EFAULT;
1386 
1387  if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1388  return -ENOENT;
1389  flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1390 
1391  warn_if(flags != 0, "newfstatat: Flag bits %#x not supported.", flags);
1392 
1393  // Modifying path from the directory descriptor
1394  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1395  return res;
1396  }
1397 
1398  auto p = tc->getProcessPtr();
1399 
1400  // Adjust path for cwd and redirection
1401  path = p->checkPathRedirect(path);
1402 
1403  struct stat host_buf;
1404  int result = stat(path.c_str(), &host_buf);
1405 
1406  if (result < 0)
1407  return -errno;
1408 
1409  copyOutStatBuf<OS>(tgt_stat, &host_buf);
1410 
1411  return 0;
1412 }
1413 
1415 template <class OS>
1416 SyscallReturn
1418  int dirfd, VPtr<> pathname,
1420 {
1421  std::string path;
1422  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1423  return -EFAULT;
1424 
1425  // Modifying path from the directory descriptor
1426  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1427  return res;
1428  }
1429 
1430  auto p = tc->getProcessPtr();
1431 
1432  // Adjust path for cwd and redirection
1433  path = p->checkPathRedirect(path);
1434 
1435 #if NO_STAT64
1436  struct stat hostBuf;
1437  int result = stat(path.c_str(), &hostBuf);
1438 #else
1439  struct stat64 hostBuf;
1440  int result = stat64(path.c_str(), &hostBuf);
1441 #endif
1442 
1443  if (result < 0)
1444  return -errno;
1445 
1446  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1447 
1448  return 0;
1449 }
1450 
1452 template <class OS>
1453 SyscallReturn
1455  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1456 {
1457  return fstatat64Func<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_stat);
1458 }
1459 
1461 template <class OS>
1462 SyscallReturn
1464  int tgt_fd, VPtr<typename OS::tgt_stat64> tgt_stat)
1465 {
1466  auto p = tc->getProcessPtr();
1467 
1468  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1469  if (!ffdp)
1470  return -EBADF;
1471  int sim_fd = ffdp->getSimFD();
1472 
1473 #if NO_STAT64
1474  struct stat hostBuf;
1475  int result = fstat(sim_fd, &hostBuf);
1476 #else
1477  struct stat64 hostBuf;
1478  int result = fstat64(sim_fd, &hostBuf);
1479 #endif
1480 
1481  if (result < 0)
1482  return -errno;
1483 
1484  copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1485 
1486  return 0;
1487 }
1488 
1489 
1491 template <class OS>
1492 SyscallReturn
1494  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1495 {
1496  std::string path;
1497  auto process = tc->getProcessPtr();
1498 
1499  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1500  return -EFAULT;
1501 
1502  // Adjust path for cwd and redirection
1503  path = process->checkPathRedirect(path);
1504 
1505  struct stat hostBuf;
1506  int result = lstat(path.c_str(), &hostBuf);
1507 
1508  if (result < 0)
1509  return -errno;
1510 
1511  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1512 
1513  return 0;
1514 }
1515 
1517 template <class OS>
1518 SyscallReturn
1520  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1521 {
1522  std::string path;
1523  auto process = tc->getProcessPtr();
1524 
1525  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1526  return -EFAULT;
1527 
1528  // Adjust path for cwd and redirection
1529  path = process->checkPathRedirect(path);
1530 
1531 #if NO_STAT64
1532  struct stat hostBuf;
1533  int result = lstat(path.c_str(), &hostBuf);
1534 #else
1535  struct stat64 hostBuf;
1536  int result = lstat64(path.c_str(), &hostBuf);
1537 #endif
1538 
1539  if (result < 0)
1540  return -errno;
1541 
1542  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1543 
1544  return 0;
1545 }
1546 
1548 template <class OS>
1549 SyscallReturn
1551  int tgt_fd, VPtr<typename OS::tgt_stat> tgt_stat)
1552 {
1553  auto p = tc->getProcessPtr();
1554 
1555  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1556 
1557  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1558  if (!ffdp)
1559  return -EBADF;
1560  int sim_fd = ffdp->getSimFD();
1561 
1562  struct stat hostBuf;
1563  int result = fstat(sim_fd, &hostBuf);
1564 
1565  if (result < 0)
1566  return -errno;
1567 
1568  copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1569 
1570  return 0;
1571 }
1572 
1574 template <class OS>
1575 SyscallReturn
1577  VPtr<> pathname, VPtr<typename OS::tgt_statfs> tgt_stat)
1578 {
1579 #if defined(__linux__)
1580  std::string path;
1581  auto process = tc->getProcessPtr();
1582 
1583  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1584  return -EFAULT;
1585 
1586  // Adjust path for cwd and redirection
1587  path = process->checkPathRedirect(path);
1588 
1589  struct statfs hostBuf;
1590  int result = statfs(path.c_str(), &hostBuf);
1591 
1592  if (result < 0)
1593  return -errno;
1594 
1595  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1596  return 0;
1597 #else
1598  warnUnsupportedOS("statfs");
1599  return -1;
1600 #endif
1601 }
1602 
1603 template <class OS>
1604 SyscallReturn
1606  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1607 {
1608  auto p = tc->getProcessPtr();
1609 
1610  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1611  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1612  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1613  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1614  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1615  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1616  return -EINVAL;
1617 
1618  ThreadContext *ctc;
1619  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1620  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1621  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1622  return -EAGAIN;
1623  }
1624 
1631  ProcessParams *pp = new ProcessParams();
1632  pp->executable.assign(*(new std::string(p->progName())));
1633  pp->cmd.push_back(*(new std::string(p->progName())));
1634  pp->system = p->system;
1635  pp->cwd.assign(p->tgtCwd);
1636  pp->input.assign("stdin");
1637  pp->output.assign("stdout");
1638  pp->errout.assign("stderr");
1639  pp->uid = p->uid();
1640  pp->euid = p->euid();
1641  pp->gid = p->gid();
1642  pp->egid = p->egid();
1643  pp->release = p->release;
1644 
1645  /* Find the first free PID that's less than the maximum */
1646  std::set<int> const& pids = p->system->PIDs;
1647  int temp_pid = *pids.begin();
1648  do {
1649  temp_pid++;
1650  } while (pids.find(temp_pid) != pids.end());
1651  if (temp_pid >= System::maxPID)
1652  fatal("temp_pid is too large: %d", temp_pid);
1653 
1654  pp->pid = temp_pid;
1655  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1656  pp->useArchPT = p->useArchPT;
1657  pp->kvmInSE = p->kvmInSE;
1658  Process *cp = pp->create();
1659  // TODO: there is no way to know when the Process SimObject is done with
1660  // the params pointer. Both the params pointer (pp) and the process
1661  // pointer (cp) are normally managed in python and are never cleaned up.
1662 
1663  Process *owner = ctc->getProcessPtr();
1664  ctc->setProcessPtr(cp);
1665  cp->assignThreadContext(ctc->contextId());
1666  owner->revokeThreadContext(ctc->contextId());
1667 
1668  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1669  BufferArg ptidBuf(ptidPtr, sizeof(long));
1670  long *ptid = (long *)ptidBuf.bufferPtr();
1671  *ptid = cp->pid();
1672  ptidBuf.copyOut(SETranslatingPortProxy(tc));
1673  }
1674 
1675  if (flags & OS::TGT_CLONE_THREAD) {
1676  cp->pTable->initState();
1677  cp->pTable->shared = true;
1678  cp->useForClone = true;
1679  }
1680 
1681  ctc->setUseForClone(true);
1682  cp->initState();
1683  p->clone(tc, ctc, cp, flags);
1684 
1685  if (flags & OS::TGT_CLONE_THREAD) {
1686  delete cp->sigchld;
1687  cp->sigchld = p->sigchld;
1688  } else if (flags & OS::TGT_SIGCHLD) {
1689  *cp->sigchld = true;
1690  }
1691 
1692  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1693  BufferArg ctidBuf(ctidPtr, sizeof(long));
1694  long *ctid = (long *)ctidBuf.bufferPtr();
1695  *ctid = cp->pid();
1696  ctidBuf.copyOut(SETranslatingPortProxy(ctc));
1697  }
1698 
1699  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1700  cp->childClearTID = (uint64_t)ctidPtr;
1701 
1702  ctc->clearArchRegs();
1703 
1704  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1705 
1706  desc->returnInto(ctc, 0);
1707 
1708  ctc->activate();
1709 
1710  if (flags & OS::TGT_CLONE_VFORK) {
1711  tc->suspend();
1712  }
1713 
1714  return cp->pid();
1715 }
1716 
1717 template <class OS>
1718 SyscallReturn
1720  RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1721  VPtr<> ctidPtr)
1722 {
1723  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1724 }
1725 
1727 template <class OS>
1728 SyscallReturn
1730  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1731 {
1732  auto p = tc->getProcessPtr();
1733 
1734  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1735  if (!ffdp)
1736  return -EBADF;
1737  int sim_fd = ffdp->getSimFD();
1738 
1739  struct statfs hostBuf;
1740  int result = fstatfs(sim_fd, &hostBuf);
1741 
1742  if (result < 0)
1743  return -errno;
1744 
1745  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1746 
1747  return 0;
1748 }
1749 
1751 template <class OS>
1752 SyscallReturn
1754  int tgt_fd, uint64_t tiov_base,
1755  typename OS::size_t count)
1756 {
1757  auto p = tc->getProcessPtr();
1758 
1759  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1760  if (!ffdp)
1761  return -EBADF;
1762  int sim_fd = ffdp->getSimFD();
1763 
1764  SETranslatingPortProxy prox(tc);
1765  typename OS::tgt_iovec tiov[count];
1766  struct iovec hiov[count];
1767  for (typename OS::size_t i = 0; i < count; ++i) {
1768  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1769  &tiov[i], sizeof(typename OS::tgt_iovec));
1770  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1771  hiov[i].iov_base = new char [hiov[i].iov_len];
1772  }
1773 
1774  int result = readv(sim_fd, hiov, count);
1775  int local_errno = errno;
1776 
1777  for (typename OS::size_t i = 0; i < count; ++i) {
1778  if (result != -1) {
1779  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1780  hiov[i].iov_base, hiov[i].iov_len);
1781  }
1782  delete [] (char *)hiov[i].iov_base;
1783  }
1784 
1785  return (result == -1) ? -local_errno : result;
1786 }
1787 
1789 template <class OS>
1790 SyscallReturn
1792  int tgt_fd, uint64_t tiov_base,
1793  typename OS::size_t count)
1794 {
1795  auto p = tc->getProcessPtr();
1796 
1797  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1798  if (!hbfdp)
1799  return -EBADF;
1800  int sim_fd = hbfdp->getSimFD();
1801 
1802  SETranslatingPortProxy prox(tc);
1803  struct iovec hiov[count];
1804  for (typename OS::size_t i = 0; i < count; ++i) {
1805  typename OS::tgt_iovec tiov;
1806 
1807  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1808  &tiov, sizeof(typename OS::tgt_iovec));
1809  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1810  hiov[i].iov_base = new char [hiov[i].iov_len];
1811  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1812  hiov[i].iov_len);
1813  }
1814 
1815  int result = writev(sim_fd, hiov, count);
1816 
1817  for (typename OS::size_t i = 0; i < count; ++i)
1818  delete [] (char *)hiov[i].iov_base;
1819 
1820  return (result == -1) ? -errno : result;
1821 }
1822 
1824 template <class OS>
1825 SyscallReturn
1827  VPtr<> start, typename OS::size_t length, int prot,
1828  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1829 {
1830  auto p = tc->getProcessPtr();
1831  Addr page_bytes = p->pTable->pageSize();
1832 
1833  if (start & (page_bytes - 1) ||
1834  offset & (page_bytes - 1) ||
1835  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1836  tgt_flags & OS::TGT_MAP_SHARED) ||
1837  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1838  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1839  !length) {
1840  return -EINVAL;
1841  }
1842 
1843  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1844  // With shared mmaps, there are two cases to consider:
1845  // 1) anonymous: writes should modify the mapping and this should be
1846  // visible to observers who share the mapping. Currently, it's
1847  // difficult to update the shared mapping because there's no
1848  // structure which maintains information about the which virtual
1849  // memory areas are shared. If that structure existed, it would be
1850  // possible to make the translations point to the same frames.
1851  // 2) file-backed: writes should modify the mapping and the file
1852  // which is backed by the mapping. The shared mapping problem is the
1853  // same as what was mentioned about the anonymous mappings. For
1854  // file-backed mappings, the writes to the file are difficult
1855  // because it requires syncing what the mapping holds with the file
1856  // that resides on the host system. So, any write on a real system
1857  // would cause the change to be propagated to the file mapping at
1858  // some point in the future (the inode is tracked along with the
1859  // mapping). This isn't guaranteed to always happen, but it usually
1860  // works well enough. The guarantee is provided by the msync system
1861  // call. We could force the change through with shared mappings with
1862  // a call to msync, but that again would require more information
1863  // than we currently maintain.
1864  warn_once("mmap: writing to shared mmap region is currently "
1865  "unsupported. The write succeeds on the target, but it "
1866  "will not be propagated to the host or shared mappings");
1867  }
1868 
1869  length = roundUp(length, page_bytes);
1870 
1871  int sim_fd = -1;
1872  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1873  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1874 
1875  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1876  if (dfdp) {
1877  EmulatedDriver *emul_driver = dfdp->getDriver();
1878  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1879  tgt_fd, offset);
1880  }
1881 
1882  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1883  if (!ffdp)
1884  return -EBADF;
1885  sim_fd = ffdp->getSimFD();
1886 
1895  if (p->interpImage.contains(tc->pcState().instAddr())) {
1896  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1897  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1898  auto *lib = loader::createObjectFile(p->checkPathRedirect(
1899  ffdp->getFileName()));
1900  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1901  ffdp->getFileName());
1902 
1903  if (lib) {
1904  Addr offset = lib->buildImage().minAddr() + start;
1905  loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1906  }
1907  }
1908  }
1909 
1913  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1921  if (!(start && p->memState->isUnmapped(start, length))) {
1925  start = p->memState->extendMmap(length);
1926  }
1927  }
1928 
1929  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1930  start, start + length - 1);
1931 
1937  if (tgt_flags & OS::TGT_MAP_FIXED) {
1942  p->memState->unmapRegion(start, length);
1943  }
1944 
1948  std::string region_name;
1949  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1950  region_name = "anon";
1951  } else {
1952  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1953  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1954  region_name = ffdp->getFileName();
1955  }
1956 
1961  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1962 
1963  return (Addr)start;
1964 }
1965 
1966 template <class OS>
1967 SyscallReturn
1969  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1970 {
1971  auto p = tc->getProcessPtr();
1972 
1973  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1974  if (!ffdp)
1975  return -EBADF;
1976  int sim_fd = ffdp->getSimFD();
1977 
1978  BufferArg bufArg(bufPtr, nbytes);
1979 
1980  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1981 
1982  bufArg.copyOut(SETranslatingPortProxy(tc));
1983 
1984  return (bytes_read == -1) ? -errno : bytes_read;
1985 }
1986 
1987 template <class OS>
1988 SyscallReturn
1990  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1991 {
1992  auto p = tc->getProcessPtr();
1993 
1994  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1995  if (!ffdp)
1996  return -EBADF;
1997  int sim_fd = ffdp->getSimFD();
1998 
1999  BufferArg bufArg(bufPtr, nbytes);
2000  bufArg.copyIn(SETranslatingPortProxy(tc));
2001 
2002  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2003 
2004  return (bytes_written == -1) ? -errno : bytes_written;
2005 }
2006 
2008 template <class OS>
2009 SyscallReturn
2011  VPtr<> start, typename OS::size_t length, int prot,
2012  int tgt_flags, int tgt_fd, typename OS::off_t offset)
2013 {
2014  auto page_size = tc->getProcessPtr()->pTable->pageSize();
2015  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
2016  tgt_fd, offset * page_size);
2017 }
2018 
2020 template <class OS>
2021 SyscallReturn
2023  unsigned resource, VPtr<typename OS::rlimit> rlp)
2024 {
2025  const ByteOrder bo = OS::byteOrder;
2026  switch (resource) {
2027  case OS::TGT_RLIMIT_STACK:
2028  // max stack size in bytes: make up a number (8MiB for now)
2029  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2030  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2031  rlp->rlim_max = htog(rlp->rlim_max, bo);
2032  break;
2033 
2034  case OS::TGT_RLIMIT_DATA:
2035  // max data segment size in bytes: make up a number
2036  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2037  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2038  rlp->rlim_max = htog(rlp->rlim_max, bo);
2039  break;
2040 
2041  case OS::TGT_RLIMIT_NPROC:
2042  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
2043  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2044  rlp->rlim_max = htog(rlp->rlim_max, bo);
2045  break;
2046 
2047  default:
2048  warn("getrlimit: unimplemented resource %d", resource);
2049  return -EINVAL;
2050  break;
2051  }
2052 
2053  return 0;
2054 }
2055 
2056 template <class OS>
2057 SyscallReturn
2059  int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
2060 {
2061  if (pid != 0) {
2062  warn("prlimit: ignoring rlimits for nonzero pid");
2063  return -EPERM;
2064  }
2065  if (n)
2066  warn("prlimit: ignoring new rlimit");
2067  if (rlp) {
2068  const ByteOrder bo = OS::byteOrder;
2069  switch (resource) {
2070  case OS::TGT_RLIMIT_STACK:
2071  // max stack size in bytes: make up a number (8MiB for now)
2072  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2073  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2074  rlp->rlim_max = htog(rlp->rlim_max, bo);
2075  break;
2076  case OS::TGT_RLIMIT_DATA:
2077  // max data segment size in bytes: make up a number
2078  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2079  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2080  rlp->rlim_max = htog(rlp->rlim_max, bo);
2081  break;
2082  default:
2083  warn("prlimit: unimplemented resource %d", resource);
2084  return -EINVAL;
2085  break;
2086  }
2087  }
2088  return 0;
2089 }
2090 
2092 template <class OS>
2093 SyscallReturn
2095  int clk_id, VPtr<typename OS::timespec> tp)
2096 {
2097  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
2098  tp->tv_sec += seconds_since_epoch;
2099  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2100  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
2101 
2102  return 0;
2103 }
2104 
2106 template <class OS>
2107 SyscallReturn
2110 {
2111  // Set resolution at ns, which is what clock_gettime() returns
2112  tp->tv_sec = 0;
2113  tp->tv_nsec = 1;
2114 
2115  return 0;
2116 }
2117 
2119 template <class OS>
2120 SyscallReturn
2123 {
2124  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
2125  tp->tv_sec += seconds_since_epoch;
2126  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2127  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
2128 
2129  return 0;
2130 }
2131 
2133 template <class OS>
2134 SyscallReturn
2136  int dirfd, VPtr<> pathname, VPtr<typename OS::timeval [2]> tp)
2137 {
2138  std::string path;
2139  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
2140  return -EFAULT;
2141 
2142  // Modifying path from the directory descriptor
2143  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
2144  return res;
2145  }
2146 
2147  struct timeval hostTimeval[2];
2148  for (int i = 0; i < 2; ++i) {
2149  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
2150  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
2151  }
2152 
2153  // Adjust path for cwd and redirection
2154  auto process = tc->getProcessPtr();
2155  path = process->checkPathRedirect(path);
2156 
2157  int result = utimes(path.c_str(), hostTimeval);
2158 
2159  if (result < 0)
2160  return -errno;
2161 
2162  return 0;
2163 }
2164 
2166 template <class OS>
2167 SyscallReturn
2169  VPtr<typename OS::timeval [2]> tp)
2170 {
2171  return futimesatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tp);
2172 }
2173 
2174 template <class OS>
2175 SyscallReturn
2177  VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
2178 {
2179  auto p = tc->getProcessPtr();
2180 
2181  std::string path;
2182  SETranslatingPortProxy mem_proxy(tc);
2183  if (!mem_proxy.tryReadString(path, pathname))
2184  return -EFAULT;
2185 
2186  if (access(path.c_str(), F_OK) == -1)
2187  return -EACCES;
2188 
2189  auto read_in = [](std::vector<std::string> &vect,
2190  PortProxy &mem_proxy, VPtr<> mem_loc)
2191  {
2192  for (int inc = 0; ; inc++) {
2193  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2194  b.copyIn(mem_proxy);
2195 
2196  if (!*(Addr*)b.bufferPtr())
2197  break;
2198 
2199  vect.push_back(std::string());
2200  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2201  }
2202  };
2203 
2208  if (!p->vforkContexts.empty()) {
2209  ThreadContext *vtc = p->system->threads[p->vforkContexts.front()];
2210  assert(vtc->status() == ThreadContext::Suspended);
2211  vtc->activate();
2212  }
2213 
2220  ProcessParams *pp = new ProcessParams();
2221  pp->executable = path;
2222  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2223  read_in(pp->env, mem_proxy, envp_mem_loc);
2224  pp->uid = p->uid();
2225  pp->egid = p->egid();
2226  pp->euid = p->euid();
2227  pp->gid = p->gid();
2228  pp->ppid = p->ppid();
2229  pp->pid = p->pid();
2230  pp->input.assign("cin");
2231  pp->output.assign("cout");
2232  pp->errout.assign("cerr");
2233  pp->cwd.assign(p->tgtCwd);
2234  pp->system = p->system;
2235  pp->release = p->release;
2244  p->system->PIDs.erase(p->pid());
2245  Process *new_p = pp->create();
2246  // TODO: there is no way to know when the Process SimObject is done with
2247  // the params pointer. Both the params pointer (pp) and the process
2248  // pointer (p) are normally managed in python and are never cleaned up.
2249 
2254  new_p->fds = p->fds;
2255  for (int i = 0; i < new_p->fds->getSize(); i++) {
2256  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2257  if (fdep && fdep->getCOE())
2258  new_p->fds->closeFDEntry(i);
2259  }
2260 
2261  *new_p->sigchld = true;
2262 
2263  tc->clearArchRegs();
2264  tc->setProcessPtr(new_p);
2265  new_p->assignThreadContext(tc->contextId());
2266  new_p->init();
2267  new_p->initState();
2268  tc->activate();
2269 
2270  return SyscallReturn();
2271 }
2272 
2274 template <class OS>
2275 SyscallReturn
2277  int who /* THREAD, SELF, or CHILDREN */,
2279 {
2280  rup->ru_utime.tv_sec = 0;
2281  rup->ru_utime.tv_usec = 0;
2282  rup->ru_stime.tv_sec = 0;
2283  rup->ru_stime.tv_usec = 0;
2284  rup->ru_maxrss = 0;
2285  rup->ru_ixrss = 0;
2286  rup->ru_idrss = 0;
2287  rup->ru_isrss = 0;
2288  rup->ru_minflt = 0;
2289  rup->ru_majflt = 0;
2290  rup->ru_nswap = 0;
2291  rup->ru_inblock = 0;
2292  rup->ru_oublock = 0;
2293  rup->ru_msgsnd = 0;
2294  rup->ru_msgrcv = 0;
2295  rup->ru_nsignals = 0;
2296  rup->ru_nvcsw = 0;
2297  rup->ru_nivcsw = 0;
2298 
2299  switch (who) {
2300  case OS::TGT_RUSAGE_SELF:
2301  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2302  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2303  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2304  break;
2305 
2306  case OS::TGT_RUSAGE_CHILDREN:
2307  // do nothing. We have no child processes, so they take no time.
2308  break;
2309 
2310  default:
2311  // don't really handle THREAD or CHILDREN, but just warn and
2312  // plow ahead
2313  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2314  who);
2315  }
2316 
2317  return 0;
2318 }
2319 
2321 template <class OS>
2322 SyscallReturn
2324 {
2325  // Fill in the time structure (in clocks)
2326  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / sim_clock::as_int::s;
2327  bufp->tms_utime = clocks;
2328  bufp->tms_stime = 0;
2329  bufp->tms_cutime = 0;
2330  bufp->tms_cstime = 0;
2331 
2332  // Convert to host endianness
2333  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2334 
2335  // Return clock ticks since system boot
2336  return clocks;
2337 }
2338 
2340 template <class OS>
2341 SyscallReturn
2343 {
2344  typename OS::time_t sec, usec;
2345  getElapsedTimeMicro(sec, usec);
2346  sec += seconds_since_epoch;
2347 
2349  if (taddr != 0) {
2350  typename OS::time_t t = sec;
2351  t = htog(t, OS::byteOrder);
2352  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2353  }
2354  return sec;
2355 }
2356 
2357 template <class OS>
2358 SyscallReturn
2359 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2360 {
2376  System *sys = tc->getSystemPtr();
2377  Process *tgt_proc = nullptr;
2378  for (auto *tc: sys->threads) {
2379  Process *temp = tc->getProcessPtr();
2380  if (temp->pid() == tid) {
2381  tgt_proc = temp;
2382  break;
2383  }
2384  }
2385 
2386  if (sig != 0 || sig != OS::TGT_SIGABRT)
2387  return -EINVAL;
2388 
2389  if (tgt_proc == nullptr)
2390  return -ESRCH;
2391 
2392  if (tgid != -1 && tgt_proc->tgid() != tgid)
2393  return -ESRCH;
2394 
2395  if (sig == OS::TGT_SIGABRT)
2396  exitGroupFunc(desc, tc, 0);
2397 
2398  return 0;
2399 }
2400 
2401 template <class OS>
2402 SyscallReturn
2404  int domain, int type, int prot)
2405 {
2406  auto p = tc->getProcessPtr();
2407 
2408  int sim_fd = socket(domain, type, prot);
2409  if (sim_fd == -1)
2410  return -errno;
2411 
2412  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2413  int tgt_fd = p->fds->allocFD(sfdp);
2414 
2415  return tgt_fd;
2416 }
2417 
2418 template <class OS>
2419 SyscallReturn
2421  int domain, int type, int prot, VPtr<> svPtr)
2422 {
2423  auto p = tc->getProcessPtr();
2424 
2425  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2426  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2427  if (status == -1)
2428  return -errno;
2429 
2430  int *fds = (int *)svBuf.bufferPtr();
2431 
2432  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2433  fds[0] = p->fds->allocFD(sfdp1);
2434  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2435  fds[1] = p->fds->allocFD(sfdp2);
2436  svBuf.copyOut(SETranslatingPortProxy(tc));
2437 
2438  return status;
2439 }
2440 
2441 template <class OS>
2442 SyscallReturn
2443 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2444  VPtr<typename OS::fd_set> readfds,
2445  VPtr<typename OS::fd_set> writefds,
2446  VPtr<typename OS::fd_set> errorfds,
2448 {
2449  int retval;
2450 
2451  auto p = tc->getProcessPtr();
2452 
2458  fd_set readfds_h;
2459  FD_ZERO(&readfds_h);
2460  fd_set writefds_h;
2461  FD_ZERO(&writefds_h);
2462  fd_set errorfds_h;
2463  FD_ZERO(&errorfds_h);
2464 
2474  int nfds_h = 0;
2475  std::map<int, int> trans_map;
2476  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2477  fd_set *hst_set_entry,
2478  int iter) -> bool
2479  {
2485  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2491  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2492  if (!hbfdp)
2493  return true;
2494  auto sim_fd = hbfdp->getSimFD();
2495 
2501  trans_map[sim_fd] = iter;
2502 
2508  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2509 
2514  FD_SET(sim_fd, hst_set_entry);
2515  }
2516  return false;
2517  };
2518 
2519  for (int i = 0; i < nfds; i++) {
2520  if (readfds) {
2521  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2522  if (ebadf)
2523  return -EBADF;
2524  }
2525  if (writefds) {
2526  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2527  if (ebadf)
2528  return -EBADF;
2529  }
2530  if (errorfds) {
2531  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2532  if (ebadf)
2533  return -EBADF;
2534  }
2535  }
2536 
2537  if (timeout) {
2545  timeout->tv_sec = 0;
2546  timeout->tv_usec = 0;
2547 
2548  retval = select(nfds_h,
2549  readfds ? &readfds_h : nullptr,
2550  writefds ? &writefds_h : nullptr,
2551  errorfds ? &errorfds_h : nullptr,
2552  (timeval *)(typename OS::timeval *)timeout);
2553  } else {
2561  struct timeval tv = { 0, 0 };
2562 
2563  retval = select(nfds_h,
2564  readfds ? &readfds_h : nullptr,
2565  readfds ? &writefds_h : nullptr,
2566  readfds ? &errorfds_h : nullptr,
2567  &tv);
2568 
2569  if (retval == 0) {
2575  for (auto sig : tc->getSystemPtr()->signalList)
2576  if (sig.receiver == p)
2577  return -EINTR;
2578  return SyscallReturn::retry();
2579  }
2580  }
2581 
2582  if (retval == -1)
2583  return -errno;
2584 
2585  if (readfds) {
2586  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2587  }
2588  if (writefds) {
2589  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2590  }
2591  if (errorfds) {
2592  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2593  }
2594 
2600  for (int i = 0; i < nfds_h; i++) {
2601  if (readfds && FD_ISSET(i, &readfds_h))
2602  FD_SET(trans_map[i],
2603  reinterpret_cast<fd_set *>(
2604  (typename OS::fd_set *)readfds));
2605 
2606  if (writefds && FD_ISSET(i, &writefds_h))
2607  FD_SET(trans_map[i],
2608  reinterpret_cast<fd_set *>(
2609  (typename OS::fd_set *)writefds));
2610 
2611  if (errorfds && FD_ISSET(i, &errorfds_h))
2612  FD_SET(trans_map[i],
2613  reinterpret_cast<fd_set *>(
2614  (typename OS::fd_set *)errorfds));
2615  }
2616 
2617  return retval;
2618 }
2619 
2620 template <class OS>
2621 SyscallReturn
2623  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2624 {
2625  auto p = tc->getProcessPtr();
2626 
2627  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2628  if (!hbfdp)
2629  return -EBADF;
2630  int sim_fd = hbfdp->getSimFD();
2631 
2632  struct pollfd pfd;
2633  pfd.fd = sim_fd;
2634  pfd.events = POLLIN | POLLPRI;
2635  if ((poll(&pfd, 1, 0) == 0)
2636  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2637  return SyscallReturn::retry();
2638 
2639  BufferArg buf_arg(buf_ptr, nbytes);
2640  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2641 
2642  if (bytes_read > 0)
2643  buf_arg.copyOut(SETranslatingPortProxy(tc));
2644 
2645  return (bytes_read == -1) ? -errno : bytes_read;
2646 }
2647 
2648 template <class OS>
2649 SyscallReturn
2651  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2652 {
2653  auto p = tc->getProcessPtr();
2654 
2655  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2656  if (!hbfdp)
2657  return -EBADF;
2658  int sim_fd = hbfdp->getSimFD();
2659 
2660  BufferArg buf_arg(buf_ptr, nbytes);
2661  buf_arg.copyIn(SETranslatingPortProxy(tc));
2662 
2663  struct pollfd pfd;
2664  pfd.fd = sim_fd;
2665  pfd.events = POLLOUT;
2666 
2673  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2674  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2675  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2676  return SyscallReturn::retry();
2677  }
2678 
2679  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2680 
2681  if (bytes_written != -1)
2682  fsync(sim_fd);
2683 
2684  return (bytes_written == -1) ? -errno : bytes_written;
2685 }
2686 
2687 template <class OS>
2688 SyscallReturn
2690  pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2691 {
2692  auto p = tc->getProcessPtr();
2693 
2694  if (rusagePtr)
2695  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2696  "functionality not supported. Ignoring rusage pointer.\n",
2697  rusagePtr);
2698 
2707  System *sysh = tc->getSystemPtr();
2709  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2710  if (iter->receiver == p) {
2711  if (pid < -1) {
2712  if ((iter->sender->pgid() == -pid)
2713  && (iter->signalValue == OS::TGT_SIGCHLD))
2714  goto success;
2715  } else if (pid == -1) {
2716  if (iter->signalValue == OS::TGT_SIGCHLD)
2717  goto success;
2718  } else if (pid == 0) {
2719  if ((iter->sender->pgid() == p->pgid())
2720  && (iter->signalValue == OS::TGT_SIGCHLD))
2721  goto success;
2722  } else {
2723  if ((iter->sender->pid() == pid)
2724  && (iter->signalValue == OS::TGT_SIGCHLD))
2725  goto success;
2726  }
2727  }
2728  }
2729 
2730  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2731 
2732 success:
2733  // Set status to EXITED for WIFEXITED evaluations.
2734  const int EXITED = 0;
2735  BufferArg statusBuf(statPtr, sizeof(int));
2736  *(int *)statusBuf.bufferPtr() = EXITED;
2737  statusBuf.copyOut(SETranslatingPortProxy(tc));
2738 
2739  // Return the child PID.
2740  pid_t retval = iter->sender->pid();
2741  sysh->signalList.erase(iter);
2742  return retval;
2743 }
2744 
2745 template <class OS>
2746 SyscallReturn
2748  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2749 {
2750  struct sockaddr sa;
2751  socklen_t addrLen;
2752  int host_fd;
2753  auto p = tc->getProcessPtr();
2754 
2755  BufferArg *lenBufPtr = nullptr;
2756  BufferArg *addrBufPtr = nullptr;
2757 
2758  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2759  if (!sfdp)
2760  return -EBADF;
2761  int sim_fd = sfdp->getSimFD();
2762 
2769  struct pollfd pfd;
2770  pfd.fd = sim_fd;
2771  pfd.events = POLLIN | POLLPRI;
2772  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2773  return SyscallReturn::retry();
2774 
2775  if (lenPtr) {
2776  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2777  lenBufPtr->copyIn(SETranslatingPortProxy(tc));
2778  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2779  sizeof(socklen_t));
2780  }
2781 
2782  if (addrPtr) {
2783  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2784  addrBufPtr->copyIn(SETranslatingPortProxy(tc));
2785  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2786  sizeof(struct sockaddr));
2787  }
2788 
2789  host_fd = accept(sim_fd, &sa, &addrLen);
2790 
2791  if (host_fd == -1)
2792  return -errno;
2793 
2794  if (addrPtr) {
2795  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2796  addrBufPtr->copyOut(SETranslatingPortProxy(tc));
2797  delete(addrBufPtr);
2798  }
2799 
2800  if (lenPtr) {
2801  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2802  lenBufPtr->copyOut(SETranslatingPortProxy(tc));
2803  delete(lenBufPtr);
2804  }
2805 
2806  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2807  sfdp->_type, sfdp->_protocol);
2808  return p->fds->allocFD(afdp);
2809 }
2810 
2812 template <class OS>
2813 SyscallReturn
2815  unsigned initval, int in_flags)
2816 {
2817 #if defined(__linux__)
2818  auto p = tc->getProcessPtr();
2819 
2820  int sim_fd = eventfd(initval, in_flags);
2821  if (sim_fd == -1)
2822  return -errno;
2823 
2824  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2825 
2826  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2827  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2828 
2829  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2830  int tgt_fd = p->fds->allocFD(hbfdp);
2831  return tgt_fd;
2832 #else
2833  warnUnsupportedOS("eventfd");
2834  return -1;
2835 #endif
2836 }
2837 
2839 template <class OS>
2840 SyscallReturn
2842  pid_t pid, typename OS::size_t cpusetsize,
2843  VPtr<> cpu_set_mask)
2844 {
2845 #if defined(__linux__)
2846  if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size()))
2847  return -EINVAL;
2848 
2849  SETranslatingPortProxy proxy(tc);
2850  BufferArg maskBuf(cpu_set_mask, cpusetsize);
2851  maskBuf.copyIn(proxy);
2852  for (int i = 0; i < tc->getSystemPtr()->threads.size(); i++) {
2853  CPU_SET(i, (cpu_set_t *)maskBuf.bufferPtr());
2854  }
2855  maskBuf.copyOut(proxy);
2856  return CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size());
2857 #else
2858  warnUnsupportedOS("sched_getaffinity");
2859  return -1;
2860 #endif
2861 }
2862 
2863 // Target recvfrom() handler.
2864 template <class OS>
2865 SyscallReturn
2867  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len,
2868  int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
2869 {
2870  auto p = tc->getProcessPtr();
2871 
2872  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2873  if (!sfdp)
2874  return -EBADF;
2875  int sim_fd = sfdp->getSimFD();
2876 
2877  // Reserve buffer space.
2878  BufferArg buf(buf_ptr, buf_len);
2879 
2880  SETranslatingPortProxy proxy(tc);
2881 
2882  // Get address length.
2883  socklen_t addr_len = 0;
2884  if (addrlen_ptr != 0) {
2885  // Read address length parameter.
2886  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2887  addrlen_buf.copyIn(proxy);
2888  addr_len = *((socklen_t *)addrlen_buf.bufferPtr());
2889  }
2890 
2891  struct sockaddr sa, *sap = NULL;
2892  if (addr_len != 0) {
2893  BufferArg addr_buf(addr_ptr, addr_len);
2894  addr_buf.copyIn(proxy);
2895  memcpy(&sa, (struct sockaddr *)addr_buf.bufferPtr(),
2896  sizeof(struct sockaddr));
2897  sap = &sa;
2898  }
2899 
2900  ssize_t recvd_size = recvfrom(sim_fd,
2901  (void *)buf.bufferPtr(),
2902  buf_len, flags, sap, (socklen_t *)&addr_len);
2903 
2904  if (recvd_size == -1)
2905  return -errno;
2906 
2907  // Pass the received data out.
2908  buf.copyOut(proxy);
2909 
2910  // Copy address to addr_ptr and pass it on.
2911  if (sap != NULL) {
2912  BufferArg addr_buf(addr_ptr, addr_len);
2913  memcpy(addr_buf.bufferPtr(), sap, sizeof(sa));
2914  addr_buf.copyOut(proxy);
2915  }
2916 
2917  // Copy len to addrlen_ptr and pass it on.
2918  if (addr_len != 0) {
2919  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2920  *(socklen_t *)addrlen_buf.bufferPtr() = addr_len;
2921  addrlen_buf.copyOut(proxy);
2922  }
2923 
2924  return recvd_size;
2925 }
2926 
2927 // Target sendto() handler.
2928 template <typename OS>
2929 SyscallReturn
2931  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags,
2932  VPtr<> addr_ptr, socklen_t addr_len)
2933 {
2934  auto p = tc->getProcessPtr();
2935 
2936  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2937  if (!sfdp)
2938  return -EBADF;
2939  int sim_fd = sfdp->getSimFD();
2940 
2941  // Reserve buffer space.
2942  BufferArg buf(buf_ptr, buf_len);
2943  buf.copyIn(SETranslatingPortProxy(tc));
2944 
2945  struct sockaddr sa, *sap = nullptr;
2946  memset(&sa, 0, sizeof(sockaddr));
2947  if (addr_len != 0) {
2948  BufferArg addr_buf(addr_ptr, addr_len);
2949  addr_buf.copyIn(SETranslatingPortProxy(tc));
2950  memcpy(&sa, (sockaddr*)addr_buf.bufferPtr(), addr_len);
2951  sap = &sa;
2952  }
2953 
2954  ssize_t sent_size = sendto(sim_fd,
2955  (void *)buf.bufferPtr(),
2956  buf_len, flags, sap, (socklen_t)addr_len);
2957 
2958  return (sent_size == -1) ? -errno : sent_size;
2959 }
2960 
2962 template <typename OS>
2963 SyscallReturn
2965  typename OS::size_t length)
2966 {
2967  // Even if the system is currently not capable of recycling physical
2968  // pages, there is no reason we can't unmap them so that we trigger
2969  // appropriate seg faults when the application mistakenly tries to
2970  // access them again.
2971  auto p = tc->getProcessPtr();
2972 
2973  if (p->pTable->pageOffset(start))
2974  return -EINVAL;
2975 
2976  length = roundUp(length, p->pTable->pageSize());
2977 
2978  p->memState->unmapRegion(start, length);
2979 
2980  return 0;
2981 }
2982 
2983 // Target fallocate() handler.
2984 template <typename OS>
2985 SyscallReturn
2987  int tgt_fd, int mode, typename OS::off_t offset,
2988  typename OS::off_t len)
2989 {
2990 #if defined(__linux__)
2991  auto p = tc->getProcessPtr();
2992 
2993  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2994  if (!ffdp)
2995  return -EBADF;
2996  int sim_fd = ffdp->getSimFD();
2997 
2998  int result = fallocate(sim_fd, mode, offset, len);
2999  if (result < 0)
3000  return -errno;
3001  return 0;
3002 #else
3003  warnUnsupportedOS("fallocate");
3004  return -1;
3005 #endif
3006 }
3007 
3009 template <typename OS>
3010 SyscallReturn
3012  typename OS::off_t length)
3013 {
3014  std::string path;
3015  auto p = tc->getProcessPtr();
3016 
3017  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
3018  return -EFAULT;
3019 
3020  // Adjust path for cwd and redirection
3021  path = p->checkPathRedirect(path);
3022 
3023  int result = truncate(path.c_str(), length);
3024  return (result == -1) ? -errno : result;
3025 }
3026 
3028 template <typename OS>
3029 SyscallReturn
3030 ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd,
3031  typename OS::off_t length)
3032 {
3033  auto p = tc->getProcessPtr();
3034 
3035  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3036  if (!ffdp)
3037  return -EBADF;
3038  int sim_fd = ffdp->getSimFD();
3039 
3040  int result = ftruncate(sim_fd, length);
3041  return (result == -1) ? -errno : result;
3042 }
3043 
3044 template <typename OS>
3045 SyscallReturn
3047  VPtr<> buf_ptr, typename OS::size_t count,
3048  unsigned int flags)
3049 {
3050  SETranslatingPortProxy proxy(tc);
3051 
3052  TypedBufferArg<uint8_t> buf(buf_ptr, count);
3053  for (int i = 0; i < count; ++i) {
3054  buf[i] = gem5::random_mt.random<uint8_t>();
3055  }
3056  buf.copyOut(proxy);
3057 
3058  return count;
3059 }
3060 
3061 } // namespace gem5
3062 
3063 #endif // __SIM_SYSCALL_EMUL_HH__
gem5::fstatfsFunc
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
Definition: syscall_emul.hh:1729
gem5::chownImpl
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
Definition: syscall_emul.cc:557
gem5::X86ISA::level
Bitfield< 20 > level
Definition: intmessage.hh:51
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
gem5::lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1519
gem5::Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:131
gem5::dupFunc
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
Definition: syscall_emul.cc:599
gem5::chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
Definition: syscall_emul.cc:950
gem5::SETranslatingPortProxy
Definition: se_translating_port_proxy.hh:49
gem5::PCStateBase::instAddr
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition: pcstate.hh:107
gem5::timesFunc
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
Definition: syscall_emul.hh:2323
gem5::Process::tgid
uint64_t tgid()
Definition: process.hh:91
gem5::pread64Func
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1968
gem5::EmulationPageTable::pageSize
Addr pageSize()
Definition: page_table.hh:115
gem5::ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
gem5::EmulatedDriver::ioctl
virtual int ioctl(ThreadContext *tc, unsigned req, Addr buf)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
warn
#define warn(...)
Definition: logging.hh:246
gem5::System::Threads::size
int size() const
Definition: system.hh:214
linux.hh
gem5::listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1112
gem5::PortProxy::writeBlob
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:192
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
gem5::getrandomFunc
SyscallReturn getrandomFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, typename OS::size_t count, unsigned int flags)
Definition: syscall_emul.hh:3046
gem5::TypedBufferArg
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
Definition: syscall_emul_buf.hh:132
gem5::PortProxy::tryReadString
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:115
gem5::mmapFunc
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
Definition: syscall_emul.hh:1826
gem5::getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:877
gem5::hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:562
gem5::getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1358
gem5::cloneFunc
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
Definition: syscall_emul.hh:1605
gem5::newfstatatFunc
SyscallReturn newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat, int flags)
Target newfstatat() handler.
Definition: syscall_emul.hh:1378
gem5::SyscallReturn
This class represents the return value from an emulated system call, including any errno setting.
Definition: syscall_return.hh:55
gem5::EmulatedDriver::mmap
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, off_t offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
Definition: emul_driver.hh:98
gem5::getpgrpFunc
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Definition: syscall_emul.cc:815
gem5::ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:150
gem5::rmdirImpl
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
Definition: syscall_emul.cc:987
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
warn_once
#define warn_once(...)
Definition: logging.hh:250
gem5::fstatFunc
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
Definition: syscall_emul.hh:1550
gem5::SyscallDesc::returnInto
virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret)=0
For use within the system call executor if new threads are created and need something returned into t...
gem5::bindFunc
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1091
gem5::accessImpl
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
Definition: syscall_emul.cc:916
gem5::selectFunc
SyscallReturn selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds, VPtr< typename OS::fd_set > readfds, VPtr< typename OS::fd_set > writefds, VPtr< typename OS::fd_set > errorfds, VPtr< typename OS::timeval > timeout)
Definition: syscall_emul.hh:2443
gem5::FutexMap::suspend
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition: futex_map.cc:53
gem5::System::futexMap
FutexMap futexMap
Definition: system.hh:602
gem5::ArmISA::domain
Bitfield< 7, 4 > domain
Definition: misc_types.hh:424
gem5::renameImpl
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
Definition: syscall_emul.cc:480
gem5::ThreadContext::pcState
virtual const PCStateBase & pcState() const =0
gem5::fchownatFunc
SyscallReturn fchownatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group, int flags)
Target fchownat() handler.
Definition: syscall_emul.hh:1067
gem5::SyscallReturn::retry
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Definition: syscall_return.hh:80
gem5::mkdirImpl
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
Definition: syscall_emul.cc:454
gem5::futimesatFunc
SyscallReturn futimesatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target futimesat() handler.
Definition: syscall_emul.hh:2135
random.hh
tlb.hh
gem5::truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, typename OS::off_t length)
Target truncate() handler.
Definition: syscall_emul.hh:3011
gem5::EmulationPageTable::initState
virtual void initState()
Definition: page_table.hh:106
gem5::Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:288
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
gem5::getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:528
gem5::guest_abi::VarArgs::get
Arg get()
Definition: varargs.hh:165
gem5::startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:229
gem5::mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:444
gem5::copyOutStatfsBuf
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
Definition: syscall_emul.hh:643
futex_map.hh
gem5::lstatFunc
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
Definition: syscall_emul.hh:1493
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:370
gem5::prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:2058
gem5::getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:352
gem5::ThreadContext::activate
virtual void activate()=0
Set the status to Active.
gem5::brkFunc
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
Definition: syscall_emul.cc:258
std::vector< std::string >
gem5::Process::pid
uint64_t pid()
Definition: process.hh:87
proxy_ptr.hh
gem5::warnUnsupportedOS
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:59
gem5::sim_clock::as_int::us
Tick us
microsecond
Definition: core.cc:70
syscall_emul_buf.hh
gem5::FutexMap::requeue
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
Definition: futex_map.cc:141
gem5::sim_clock::as_int::s
Tick s
second
Definition: core.cc:68
gem5::ignoreWarnOnceFunc
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:79
gem5::fchmodFunc
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
Definition: syscall_emul.hh:1250
gem5::ThreadContext::setUseForClone
void setUseForClone(bool new_val)
Definition: thread_context.hh:103
gem5::Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:287
gem5::EmulationPageTable::shared
bool shared
Definition: page_table.hh:104
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::ThreadContext::cpuId
virtual int cpuId() const =0
gem5::closeFunc
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
Definition: syscall_emul.cc:289
gem5::Process::useForClone
bool useForClone
Definition: process.hh:183
gem5::getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1489
gem5::ThreadContext::setProcessPtr
virtual void setProcessPtr(Process *p)=0
sc_dt::inc
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:341
gem5::sysinfoFunc
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
Definition: syscall_emul.hh:1122
gem5::Random::random
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:90
gem5::ThreadContext::status
virtual Status status() const =0
gem5::umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:535
gem5::unlinkImpl
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
Definition: syscall_emul.cc:392
gem5::setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:822
gem5::getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:251
gem5::openFunc
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:912
gem5::Process::childClearTID
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:296
gem5::exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:245
gem5::pollFunc
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
Definition: syscall_emul.hh:1176
gem5::mremapFunc
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags, guest_abi::VarArgs< uint64_t > varargs)
Target mremap() handler.
Definition: syscall_emul.hh:1269
gem5::getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1400
gem5::FutexMap
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:109
gem5::symlinkFunc
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
Definition: syscall_emul.cc:423
gem5::System
Definition: system.hh:75
syscall_return.hh
gem5::ArmISA::b
Bitfield< 7 > b
Definition: misc_types.hh:382
gem5::fstat64Func
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
Definition: syscall_emul.hh:1463
gem5::ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t length)
Target ftruncate() handler.
Definition: syscall_emul.hh:3030
gem5::System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:611
gem5::eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2814
gem5::gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:2121
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:94
gem5::VegaISA::t
Bitfield< 51 > t
Definition: pagetable.hh:56
gem5::openatFunc
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:762
gem5::unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags)
Target unlinkat() handler.
Definition: syscall_emul.hh:922
gem5::unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
Definition: syscall_emul.cc:382
gem5::writevFunc
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target writev() handler.
Definition: syscall_emul.hh:1791
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::_llseekFunc
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
Definition: syscall_emul.cc:313
gem5::ThreadContext::Suspended
@ Suspended
Temporarily inactive.
Definition: thread_context.hh:113
gem5::getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:891
gem5::X86ISA::count
count
Definition: misc.hh:703
gem5::socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2403
gem5::Process::pTable
EmulationPageTable * pTable
Definition: process.hh:185
gem5::PowerISA::bo
Bitfield< 25, 21 > bo
Definition: types.hh:82
DPRINTF_SYSCALL
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
Definition: syscall_debug_macros.hh:57
gem5::fchmodatFunc
SyscallReturn fchmodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:1137
gem5::X86ISA::type
type
Definition: misc.hh:727
gem5::FutexMap::suspend_bitset
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
Definition: futex_map.cc:89
gem5::EmulatedDriver::open
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver.
gem5::gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
process.hh
gem5::BufferArg
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Definition: syscall_emul_buf.hh:107
len
uint16_t len
Definition: helpers.cc:62
gem5::statfsFunc
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
Definition: syscall_emul.hh:1576
gem5::getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:898
gem5::PortProxy
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition: port_proxy.hh:86
gem5::readvFunc
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target readv() handler.
Definition: syscall_emul.hh:1753
gem5::FutexMap::wakeup
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.cc:59
gem5::clock_getresFunc
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_getres() function.
Definition: syscall_emul.hh:2108
gem5::FutexMap::wakeup_bitset
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition: futex_map.cc:108
gem5::pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:724
gem5::htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
gem5::hst_statfs
struct statfs hst_statfs
Definition: syscall_emul.hh:557
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length)
Target munmap() handler.
Definition: syscall_emul.hh:2964
gem5::truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:495
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::gettidFunc
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Definition: syscall_emul.cc:863
flags
uint8_t flags
Definition: helpers.cc:66
gem5::pwrite64Func
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1989
gem5::futexFunc
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps.
Definition: syscall_emul.hh:385
gem5::Process::checkPathRedirect
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:424
gem5::getElapsedTimeNano
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Definition: syscall_emul.hh:541
gem5::setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:280
gem5::PortProxy::readBlob
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:182
gem5::fcntlFunc
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
Definition: syscall_emul.cc:647
gem5::fstatat64Func
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstatat64() handler.
Definition: syscall_emul.hh:1417
gem5::mkdiratFunc
SyscallReturn mkdiratFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target mkdirat() handler.
Definition: syscall_emul.hh:1086
gem5::hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:563
gem5::connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1127
gem5::readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.hh:1028
gem5::readlinkatFunc
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlinkat() handler.
Definition: syscall_emul.hh:962
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::linkFunc
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
Definition: syscall_emul.cc:402
gem5::System::maxPID
static const int maxPID
Definition: system.hh:604
gem5::pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:730
gem5::timeFunc
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
Definition: syscall_emul.hh:2342
gem5::writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2650
gem5::accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:905
gem5::copyOutStat64Buf
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:621
gem5::sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1289
gem5::gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:342
gem5::fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:689
gem5::recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1149
gem5::mmap2Func
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
Definition: syscall_emul.hh:2010
gem5::loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:135
gem5::BaseBufferArg::copyIn
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
Definition: syscall_emul_buf.hh:81
gem5::tgkillFunc
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
Definition: syscall_emul.hh:2359
gem5::Process
Definition: process.hh:68
gem5::ThreadContext::getProcessPtr
virtual Process * getProcessPtr()=0
gem5::EmulatedDriver
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:55
gem5::exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:239
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:273
gem5::sendtoFunc
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, socklen_t addr_len)
Definition: syscall_emul.hh:2930
gem5::cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
Definition: syscall_emul.hh:1719
gem5::clock_gettimeFunc
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_gettime() function.
Definition: syscall_emul.hh:2094
gem5::renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
Definition: syscall_emul.hh:1039
gem5::ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
Definition: syscall_emul.hh:687
gem5::ThreadContext::suspend
virtual void suspend()=0
Set the status to Suspended.
gem5::loader::SymbolTable::insert
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition: symtab.cc:55
gem5::chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:1169
base.hh
gem5::shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1076
gem5::System::threads
Threads threads
Definition: system.hh:314
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:456
types.hh
gem5::BaseBufferArg::copyOut
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
Definition: syscall_emul_buf.hh:91
gem5::recvfromFunc
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
Definition: syscall_emul.hh:2866
gem5::pipePseudoFunc
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
Definition: syscall_emul.cc:718
gem5::mknodatFunc
SyscallReturn mknodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknodat() handler.
Definition: syscall_emul.hh:1104
gem5::atSyscallPath
SyscallReturn atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
Definition: syscall_emul.hh:360
gem5::rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:977
guest_abi.hh
gem5::wait4Func
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
Definition: syscall_emul.hh:2689
gem5::getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:870
gem5::statFunc
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
Definition: syscall_emul.hh:1352
gem5::Process::sigchld
bool * sigchld
Definition: process.hh:299
gem5::fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, typename OS::off_t offset, typename OS::off_t len)
Definition: syscall_emul.hh:2986
gem5::roundUp
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:260
gem5::stat64Func
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
Definition: syscall_emul.hh:1454
logging.hh
emul_driver.hh
gem5::seconds_since_epoch
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
Definition: syscall_emul.hh:522
gem5::renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
Definition: syscall_emul.cc:464
gem5::Process::revokeThreadContext
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
Definition: process.cc:265
gem5::Process::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: process.cc:278
gem5::readFunc
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2622
se_translating_port_proxy.hh
gem5::ThreadContext::clearArchRegs
virtual void clearArchRegs()=0
gem5::schedGetaffinityFunc
SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, pid_t pid, typename OS::size_t cpusetsize, VPtr<> cpu_set_mask)
Target sched_getaffinity.
Definition: syscall_emul.hh:2841
gem5::setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1468
gem5::ThreadContext::threadId
virtual int threadId() const =0
trace.hh
gem5::SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:69
gem5::fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:574
gem5::copyOutStatBuf
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:572
gem5::ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:72
gem5::loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
gem5::getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:856
std::list
STL list class.
Definition: stl.hh:51
gem5::getrusageFunc
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
Definition: syscall_emul.hh:2276
gem5::guest_abi::VarArgs
Definition: varargs.hh:150
intmath.hh
gem5::System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:128
gem5::getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:2022
gem5::BufferArg::bufferPtr
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Definition: syscall_emul_buf.hh:119
page_table.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::SyscallDesc::name
std::string name() const
Definition: syscall_desc.hh:80
gem5::dup2Func
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Definition: syscall_emul.cc:619
gem5::socketpairFunc
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
Definition: syscall_emul.hh:2420
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::utimesFunc
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
Definition: syscall_emul.hh:2168
gem5::mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:928
object_file.hh
gem5::acceptFunc
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.hh:2747
gem5::mknodImpl
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
Definition: syscall_emul.cc:939
gem5::X86ISA::op
Bitfield< 4 > op
Definition: types.hh:83
thread_context.hh
gem5::faccessatFunc
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int mode)
Target facessat() handler.
Definition: syscall_emul.hh:944
gem5::geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:884
gem5::ArmISA::sa
Bitfield< 3 > sa
Definition: misc_types.hh:392
syscall_desc.hh
gem5::X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:582
gem5::chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:546
gem5::ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:516
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:423
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::lseekFunc
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Definition: syscall_emul.cc:296
gem5::getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1439
gem5::unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:65
gem5::execveFunc
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
Definition: syscall_emul.hh:2176
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

Generated on Thu Jul 28 2022 13:32:37 for gem5 by doxygen 1.8.17