gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 "cpu/base.hh"
97 #include "cpu/thread_context.hh"
98 #include "kern/linux/linux.hh"
99 #include "mem/page_table.hh"
101 #include "params/Process.hh"
102 #include "sim/emul_driver.hh"
103 #include "sim/futex_map.hh"
104 #include "sim/guest_abi.hh"
105 #include "sim/process.hh"
106 #include "sim/proxy_ptr.hh"
108 #include "sim/syscall_desc.hh"
109 #include "sim/syscall_emul_buf.hh"
110 #include "sim/syscall_return.hh"
111 
112 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
113 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
114 #elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
115 #define CMSG_ALIGN(n) _ALIGN(n)
116 #endif
117 
118 namespace gem5
119 {
120 
122 //
123 // The following emulation functions are generic enough that they
124 // don't need to be recompiled for different emulated OS's. They are
125 // defined in sim/syscall_emul.cc.
126 //
128 
129 void warnUnsupportedOS(std::string syscall_name);
130 
132 SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);
133 
138 SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
140 SyscallReturn
141 ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc);
142 
144 SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status);
145 
147 SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status);
148 
150 SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc,
151  uint64_t tidPtr);
152 
154 SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc);
155 
157 SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
158 
160 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
161 
163 SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc,
164  int tgt_fd, uint64_t offs, int whence);
165 
167 SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
168  int tgt_fd, uint64_t offset_high,
169  uint32_t offset_low, VPtr<> result_ptr, int whence);
170 
172 SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
173  int tgt_fd, int how);
174 
176 SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc,
177  VPtr<> buf_ptr, int name_len);
178 
180 SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc,
181  VPtr<> buf_ptr, unsigned long size);
182 
184 SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
185  VPtr<> pathname);
186 SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc,
187  std::string path);
188 
190 SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc,
191  VPtr<> pathname, VPtr<> new_pathname);
192 
194 SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
195  VPtr<> pathname, VPtr<> new_pathname);
196 
198 SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
199  VPtr<> pathname, mode_t mode);
200 SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
201  std::string path, mode_t mode);
202 
204 SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc,
205  VPtr<> pathname, mode_t mode, dev_t dev);
206 SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc,
207  std::string path, mode_t mode, dev_t dev);
208 
210 SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
211 
212 // Target rmdir() handler.
213 SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc,
214  VPtr<> pathname);
215 SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc,
216  std::string path);
217 
219 SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc,
220  VPtr<> oldpath, VPtr<> newpath);
221 SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc,
222  std::string oldpath, std::string newpath);
223 
225 SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc,
226  VPtr<> pathname, int64_t length);
227 
229 SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc,
230  int tgt_fd, int64_t length);
231 
233 SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc);
234 
236 SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc);
237 
239 SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc,
240  VPtr<> pathname, uint32_t owner, uint32_t group);
241 SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc,
242  std::string path, uint32_t owner, uint32_t group);
243 
245 SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
246 
248 SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
249  int pid, int pgid);
250 
252 SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc,
253  int tgt_fd, uint32_t owner, uint32_t group);
254 
256 SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc,
257  int tgt_fd);
258 
260 SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc,
261  int old_tgt_fd, int new_tgt_fd);
262 
264 SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
265  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs);
266 
268 SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
269  int tgt_fd, int cmd);
270 
272 SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
273 
275 SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc,
276  VPtr<> tgt_addr, int flags);
277 
279 SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc);
280 
281 // Target getpeername() handler.
282 SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc,
283  int tgt_fd, VPtr<> sockAddrPtr,
284  VPtr<> addrlenPtr);
285 
286 // Target bind() handler.
287 SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc,
288  int tgt_fd, VPtr<> buf_ptr, int addrlen);
289 
290 // Target listen() handler.
291 SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc,
292  int tgt_fd, int backlog);
293 
294 // Target connect() handler.
295 SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc,
296  int tgt_fd, VPtr<> buf_ptr, int addrlen);
297 
298 #if defined(SYS_getdents)
299 // Target getdents() handler.
300 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
301  int tgt_fd, VPtr<> buf_ptr, unsigned count);
302 #endif
303 
304 #if defined(SYS_getdents64)
305 // Target getdents() handler.
306 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
307  int tgt_fd, VPtr<> buf_ptr, unsigned count);
308 #endif
309 
310 // Target recvmsg() handler.
311 SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
312  int tgt_fd, VPtr<> msgPtr, int flags);
313 
314 // Target sendmsg() handler.
315 SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
316  int tgt_fd, VPtr<> msgPtr, int flags);
317 
318 // Target getuid() handler.
319 SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc);
320 
322 SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc);
323 
325 SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc);
326 
328 SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
329 
331 SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc);
332 
334 SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc,
335  VPtr<> pathname, mode_t mode);
336 SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc,
337  std::string path, mode_t mode);
338 
339 // Target getsockopt() handler.
340 SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
341  int tgt_fd, int level, int optname,
342  VPtr<> valPtr, VPtr<> lenPtr);
343 
344 // Target setsockopt() handler.
345 SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
346  int tgt_fd, int level, int optname,
347  VPtr<> valPtr, socklen_t len);
348 
349 SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
350  VPtr<uint32_t> cpu, VPtr<uint32_t> node,
351  VPtr<uint32_t> tcache);
352 
353 // Target getsockname() handler.
354 SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc,
355  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
356 
357 template <class OS>
358 SyscallReturn
359 atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
360 {
361  // If pathname is absolute, then dirfd is ignored.
362  if (dirfd != OS::TGT_AT_FDCWD && !startswith(path, "/")) {
363  auto process = tc->getProcessPtr();
364 
365  std::shared_ptr<FDEntry> fdep = ((*process->fds)[dirfd]);
366  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
367  if (!ffdp)
368  return -EBADF;
369 
370  if (path.empty())
371  path = ffdp->getFileName();
372  else
373  path = ffdp->getFileName() + "/" + path;
374  }
375 
376  return 0;
377 }
378 
382 template <class OS>
383 SyscallReturn
385  VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
386 {
387  auto process = tc->getProcessPtr();
388 
389  /*
390  * Unsupported option that does not affect the correctness of the
391  * application. This is a performance optimization utilized by Linux.
392  */
393  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
394  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
395 
396  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
397 
398  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
399  // Ensure futex system call accessed atomically.
400  BufferArg buf(uaddr, sizeof(int));
402  int mem_val = *(int*)buf.bufferPtr();
403 
404  /*
405  * The value in memory at uaddr is not equal with the expected val
406  * (a different thread must have changed it before the system call was
407  * invoked). In this case, we need to throw an error.
408  */
409  if (val != mem_val)
410  return -OS::TGT_EWOULDBLOCK;
411 
412  if (OS::TGT_FUTEX_WAIT == op) {
413  futex_map.suspend(uaddr, process->tgid(), tc);
414  } else {
415  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
416  }
417 
418  return 0;
419  } else if (OS::TGT_FUTEX_WAKE == op) {
420  return futex_map.wakeup(uaddr, process->tgid(), val);
421  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
422  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
423  } else if (OS::TGT_FUTEX_REQUEUE == op ||
424  OS::TGT_FUTEX_CMP_REQUEUE == op) {
425 
426  // Ensure futex system call accessed atomically.
427  BufferArg buf(uaddr, sizeof(int));
429  int mem_val = *(int*)buf.bufferPtr();
430  /*
431  * For CMP_REQUEUE, the whole operation is only started only if
432  * val3 is still the value of the futex pointed to by uaddr.
433  */
434  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
435  return -OS::TGT_EWOULDBLOCK;
436  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
437  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
438  /*
439  * The FUTEX_WAKE_OP operation is equivalent to executing the
440  * following code atomically and totally ordered with respect to
441  * other futex operations on any of the two supplied futex words:
442  *
443  * int oldval = *(int *) addr2;
444  * *(int *) addr2 = oldval op oparg;
445  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
446  * if (oldval cmp cmparg)
447  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
448  *
449  * (op, oparg, cmp, cmparg are encoded in val3)
450  *
451  * +---+---+-----------+-----------+
452  * |op |cmp| oparg | cmparg |
453  * +---+---+-----------+-----------+
454  * 4 4 12 12 <== # of bits
455  *
456  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
457  *
458  */
459  // get value from simulated-space
460  BufferArg buf(uaddr2, sizeof(int));
462  int oldval = *(int*)buf.bufferPtr();
463  int newval = oldval;
464  // extract op, oparg, cmp, cmparg from val3
465  int wake_cmparg = val3 & 0xfff;
466  int wake_oparg = (val3 & 0xfff000) >> 12;
467  int wake_cmp = (val3 & 0xf000000) >> 24;
468  int wake_op = (val3 & 0xf0000000) >> 28;
469  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
470  wake_oparg = (1 << wake_oparg);
471  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
472  // perform operation on the value of the second futex
473  if (wake_op == OS::TGT_FUTEX_OP_SET)
474  newval = wake_oparg;
475  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
476  newval += wake_oparg;
477  else if (wake_op == OS::TGT_FUTEX_OP_OR)
478  newval |= wake_oparg;
479  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
480  newval &= ~wake_oparg;
481  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
482  newval ^= wake_oparg;
483  // copy updated value back to simulated-space
484  *(int*)buf.bufferPtr() = newval;
486  // perform the first wake-up
487  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
488  int woken2 = 0;
489  // calculate the condition of the second wake-up
490  bool is_wake2 = false;
491  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
492  is_wake2 = oldval == wake_cmparg;
493  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
494  is_wake2 = oldval != wake_cmparg;
495  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
496  is_wake2 = oldval < wake_cmparg;
497  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
498  is_wake2 = oldval <= wake_cmparg;
499  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
500  is_wake2 = oldval > wake_cmparg;
501  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
502  is_wake2 = oldval >= wake_cmparg;
503  // perform the second wake-up
504  if (is_wake2)
505  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
506 
507  return woken1 + woken2;
508  }
509  warn("futex: op %d not implemented; ignoring.", op);
510  return -ENOSYS;
511 }
512 
515 SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
516 
517 
521 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
522 
525 template <class T1, class T2>
526 void
528 {
529  static const int OneMillion = 1000 * 1000;
530 
531  uint64_t elapsed_usecs = curTick() / sim_clock::as_int::us;
532  sec = elapsed_usecs / OneMillion;
533  usec = elapsed_usecs % OneMillion;
534 }
535 
538 template <class T1, class T2>
539 void
541 {
542  static const int OneBillion = 1000 * 1000 * 1000;
543 
544  uint64_t elapsed_nsecs = curTick() / sim_clock::as_int::ns;
545  sec = elapsed_nsecs / OneBillion;
546  nsec = elapsed_nsecs % OneBillion;
547 }
548 
550 //
551 // The following emulation functions are generic, but need to be
552 // templated to account for differences in types, constants, etc.
553 //
555 
556  typedef struct statfs hst_statfs;
557 #if NO_STAT64
558  typedef struct stat hst_stat;
559  typedef struct stat hst_stat64;
560 #else
561  typedef struct stat hst_stat;
562  typedef struct stat64 hst_stat64;
563 #endif
564 
568 
569 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
570 void
571 copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
572 {
573  constexpr ByteOrder bo = OS::byteOrder;
574 
575  if (fakeTTY)
576  tgt->st_dev = 0xA;
577  else
578  tgt->st_dev = host->st_dev;
579  tgt->st_dev = htog(tgt->st_dev, bo);
580  tgt->st_ino = host->st_ino;
581  tgt->st_ino = htog(tgt->st_ino, bo);
582  tgt->st_mode = host->st_mode;
583  if (fakeTTY) {
584  // Claim to be a character device
585  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
586  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
587  }
588  tgt->st_mode = htog(tgt->st_mode, bo);
589  tgt->st_nlink = host->st_nlink;
590  tgt->st_nlink = htog(tgt->st_nlink, bo);
591  tgt->st_uid = host->st_uid;
592  tgt->st_uid = htog(tgt->st_uid, bo);
593  tgt->st_gid = host->st_gid;
594  tgt->st_gid = htog(tgt->st_gid, bo);
595  if (fakeTTY)
596  tgt->st_rdev = 0x880d;
597  else
598  tgt->st_rdev = host->st_rdev;
599  tgt->st_rdev = htog(tgt->st_rdev, bo);
600  tgt->st_size = host->st_size;
601  tgt->st_size = htog(tgt->st_size, bo);
602  tgt->st_atimeX = host->st_atime;
603  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
604  tgt->st_mtimeX = host->st_mtime;
605  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
606  tgt->st_ctimeX = host->st_ctime;
607  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
608  // Force the block size to be 8KB. This helps to ensure buffered io works
609  // consistently across different hosts.
610  tgt->st_blksize = 0x2000;
611  tgt->st_blksize = htog(tgt->st_blksize, bo);
612  tgt->st_blocks = host->st_blocks;
613  tgt->st_blocks = htog(tgt->st_blocks, bo);
614 }
615 
616 // Same for stat64
617 
618 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
619 void
620 copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host,
621  bool fakeTTY=false)
622 {
623  copyOutStatBuf<OS>(tgt, host, fakeTTY);
624 #if defined(STAT_HAVE_NSEC)
625  constexpr ByteOrder bo = OS::byteOrder;
626 
627  tgt->st_atime_nsec = host->st_atime_nsec;
628  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
629  tgt->st_mtime_nsec = host->st_mtime_nsec;
630  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
631  tgt->st_ctime_nsec = host->st_ctime_nsec;
632  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
633 #else
634  tgt->st_atime_nsec = 0;
635  tgt->st_mtime_nsec = 0;
636  tgt->st_ctime_nsec = 0;
637 #endif
638 }
639 
640 template <class OS, typename TgtStatPtr, typename HostStatPtr>
641 void
642 copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
643 {
644  constexpr ByteOrder bo = OS::byteOrder;
645 
646  tgt->f_type = htog(host->f_type, bo);
647 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
648  tgt->f_bsize = htog(host->f_iosize, bo);
649 #else
650  tgt->f_bsize = htog(host->f_bsize, bo);
651 #endif
652  tgt->f_blocks = htog(host->f_blocks, bo);
653  tgt->f_bfree = htog(host->f_bfree, bo);
654  tgt->f_bavail = htog(host->f_bavail, bo);
655  tgt->f_files = htog(host->f_files, bo);
656  tgt->f_ffree = htog(host->f_ffree, bo);
657  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
658 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
659  tgt->f_namelen = htog(host->f_namemax, bo);
660  tgt->f_frsize = htog(host->f_bsize, bo);
661 #elif defined(__APPLE__)
662  tgt->f_namelen = 0;
663  tgt->f_frsize = 0;
664 #else
665  tgt->f_namelen = htog(host->f_namelen, bo);
666  tgt->f_frsize = htog(host->f_frsize, bo);
667 #endif
668 #if defined(__linux__)
669  memcpy(&tgt->f_spare, &host->f_spare,
670  std::min(sizeof(host->f_spare), sizeof(tgt->f_spare)));
671 #else
672  /*
673  * The fields are different sizes per OS. Don't bother with
674  * f_spare or f_reserved on non-Linux for now.
675  */
676  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
677 #endif
678 }
679 
684 template <class OS>
685 SyscallReturn
687  int tgt_fd, unsigned req, VPtr<> addr)
688 {
689  auto p = tc->getProcessPtr();
690 
691  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
692 
693  if (OS::isTtyReq(req))
694  return -ENOTTY;
695 
696  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
697  if (dfdp) {
698  EmulatedDriver *emul_driver = dfdp->getDriver();
699  if (emul_driver)
700  return emul_driver->ioctl(tc, req, addr);
701  }
702 
703  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
704  if (sfdp) {
705  int status;
706 
707  switch (req) {
708  case SIOCGIFCONF: {
709  BufferArg conf_arg(addr, sizeof(ifconf));
710  conf_arg.copyIn(SETranslatingPortProxy(tc));
711 
712  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
713  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
714  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
715  ifc_buf_arg.copyIn(SETranslatingPortProxy(tc));
716 
717  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
718 
719  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
720  if (status != -1) {
721  conf->ifc_buf = (char*)ifc_buf_addr;
722  ifc_buf_arg.copyOut(SETranslatingPortProxy(tc));
723  conf_arg.copyOut(SETranslatingPortProxy(tc));
724  }
725 
726  return status;
727  }
728  case SIOCGIFFLAGS:
729 #if defined(__linux__)
730  case SIOCGIFINDEX:
731 #endif
732  case SIOCGIFNETMASK:
733  case SIOCGIFADDR:
734 #if defined(__linux__)
735  case SIOCGIFHWADDR:
736 #endif
737  case SIOCGIFMTU: {
738  BufferArg req_arg(addr, sizeof(ifreq));
739  req_arg.copyIn(SETranslatingPortProxy(tc));
740 
741  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
742  if (status != -1)
743  req_arg.copyOut(SETranslatingPortProxy(tc));
744  return status;
745  }
746  }
747  }
748 
753  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
754  tgt_fd, req, tc->pcState());
755  return -ENOTTY;
756 }
757 
759 template <class OS>
760 SyscallReturn
762  int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
763 {
764  auto p = tc->getProcessPtr();
765 
770  std::string path;
771  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
772  return -EFAULT;
773 
774 #ifdef __CYGWIN32__
775  int host_flags = O_BINARY;
776 #else
777  int host_flags = 0;
778 #endif
779 
783  for (const auto &p: OS::openFlagTable) {
784  if (tgt_flags & p.first) {
785  tgt_flags &= ~p.first;
786  host_flags |= p.second;
787  }
788  }
789  warn_if(tgt_flags, "%s: cannot decode flags %#x", desc->name(), tgt_flags);
790 
791 #ifdef __CYGWIN32__
792  host_flags |= O_BINARY;
793 #endif
794 
807  std::string redir_path = path;
808  std::string abs_path = path;
809  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
810  abs_path = p->absolutePath(path, true);
811  redir_path = p->checkPathRedirect(path);
812  } else if (!startswith(path, "/")) {
813  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
814  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
815  if (!ffdp)
816  return -EBADF;
817  abs_path = ffdp->getFileName() + path;
818  redir_path = p->checkPathRedirect(abs_path);
819  }
820 
827  if (startswith(abs_path, "/dev/")) {
828  std::string filename = abs_path.substr(strlen("/dev/"));
829  EmulatedDriver *drv = p->findDriver(filename);
830  if (drv) {
831  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
832  "driver open with path[%s]\n",
833  desc->name(), abs_path.c_str());
834  return drv->open(tc, mode, host_flags);
835  }
840  }
841 
866  int sim_fd = -1;
867  std::string used_path;
868  std::vector<std::string> special_paths =
869  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
870  "/proc/self/maps", "/dev/urandom",
871  "/sys/devices/system/cpu/online" };
872  for (auto entry : special_paths) {
873  if (startswith(path, entry)) {
874  sim_fd = OS::openSpecialFile(abs_path, p, tc);
875  used_path = abs_path;
876  }
877  }
878  if (sim_fd == -1) {
879  sim_fd = open(redir_path.c_str(), host_flags, mode);
880  used_path = redir_path;
881  }
882  if (sim_fd == -1) {
883  int local = -errno;
884  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
885  "(inferred from:%s)\n", desc->name(),
886  used_path.c_str(), path.c_str());
887  return local;
888  }
889 
898  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
899  // Record the file mode for checkpoint restoring
900  ffdp->setFileMode(mode);
901  int tgt_fd = p->fds->allocFD(ffdp);
902  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
903  "(inferred from:%s)\n", desc->name(),
904  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
905  return tgt_fd;
906 }
907 
909 template <class OS>
910 SyscallReturn
912  VPtr<> pathname, int tgt_flags, int mode)
913 {
914  return openatFunc<OS>(
915  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
916 }
917 
919 template <class OS>
920 SyscallReturn
922  int dirfd, VPtr<> pathname, int flags)
923 {
924  std::string path;
925  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
926  return -EFAULT;
927 
928  // Modifying path from the directory descriptor
929  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
930  return res;
931  }
932 
933  if (flags & OS::TGT_AT_REMOVEDIR) {
934  return rmdirImpl(desc, tc, path);
935  } else {
936  return unlinkImpl(desc, tc, path);
937  }
938 }
939 
941 template <class OS>
942 SyscallReturn
944  int dirfd, VPtr<> pathname, int mode)
945 {
946  std::string path;
947  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
948  return -EFAULT;
949 
950  // Modifying path from the directory descriptor
951  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
952  return res;
953  }
954 
955  return accessImpl(desc, tc, path, mode);
956 }
957 
959 template <class OS>
960 SyscallReturn
962  int dirfd, VPtr<> pathname, VPtr<> buf_ptr,
963  typename OS::size_t bufsiz)
964 {
965  std::string path;
966  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
967  return -EFAULT;
968 
969  // Modifying path from the directory descriptor
970  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
971  return res;
972  }
973 
974  auto p = tc->getProcessPtr();
975 
976  // Adjust path for cwd and redirection
977  path = p->checkPathRedirect(path);
978 
979  BufferArg buf(buf_ptr, bufsiz);
980 
981  int result = -1;
982  if (path != "/proc/self/exe") {
983  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
984  } else {
985  // Emulate readlink() called on '/proc/self/exe' should return the
986  // absolute path of the binary running in the simulated system (the
987  // Process' executable). It is possible that using this path in
988  // the simulated system will result in unexpected behavior if:
989  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
990  // called binary calls readlink().
991  // 2) The host's full path to the running benchmark changes from one
992  // simulation to another. This can result in different simulated
993  // performance since the simulated system will process the binary
994  // path differently, even if the binary itself does not change.
995 
996  // Get the absolute canonical path to the running application
997  char real_path[PATH_MAX];
998  char *check_real_path = realpath(p->progName(), real_path);
999  if (!check_real_path) {
1000  fatal("readlink('/proc/self/exe') unable to resolve path to "
1001  "executable: %s", p->progName());
1002  }
1003  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
1004  typename OS::size_t real_path_len = strlen(real_path);
1005  if (real_path_len > bufsiz) {
1006  // readlink will truncate the contents of the
1007  // path to ensure it is no more than bufsiz
1008  result = bufsiz;
1009  } else {
1010  result = real_path_len;
1011  }
1012 
1013  // Issue a warning about potential unexpected results
1014  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
1015  "results in various settings.\n Returning '%s'\n",
1016  (char*)buf.bufferPtr());
1017  }
1018 
1020 
1021  return (result == -1) ? -errno : result;
1022 }
1023 
1025 template <class OS>
1026 SyscallReturn
1028  VPtr<> pathname, VPtr<> buf_ptr,
1029  typename OS::size_t bufsiz)
1030 {
1031  return readlinkatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD,
1032  pathname, buf_ptr, bufsiz);
1033 }
1034 
1036 template <class OS>
1037 SyscallReturn
1039  int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
1040 {
1041  SETranslatingPortProxy proxy(tc);
1042  std::string old_name;
1043  if (!proxy.tryReadString(old_name, oldpath))
1044  return -EFAULT;
1045 
1046  std::string new_name;
1047  if (!proxy.tryReadString(new_name, newpath))
1048  return -EFAULT;
1049 
1050  // Modifying old_name from the directory descriptor
1051  if (auto res = atSyscallPath<OS>(tc, olddirfd, old_name); !res.successful()) {
1052  return res;
1053  }
1054 
1055  // Modifying new_name from the directory descriptor
1056  if (auto res = atSyscallPath<OS>(tc, newdirfd, new_name); !res.successful()) {
1057  return res;
1058  }
1059 
1060  return renameImpl(desc, tc, old_name, new_name);
1061 }
1062 
1064 template <class OS>
1065 SyscallReturn
1067  int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group,
1068  int flags)
1069 {
1070  std::string path;
1071  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1072  return -EFAULT;
1073 
1074  // Modifying path from the directory descriptor
1075  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1076  return res;
1077  }
1078 
1079  return chownImpl(desc, tc, path, owner, group);
1080 }
1081 
1083 template <class OS>
1084 SyscallReturn
1086  int dirfd, VPtr<> pathname, mode_t mode)
1087 {
1088  std::string path;
1089  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1090  return -EFAULT;
1091 
1092  // Modifying path from the directory descriptor
1093  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1094  return res;
1095  }
1096 
1097  return mkdirImpl(desc, tc, path, mode);
1098 }
1099 
1101 template <class OS>
1102 SyscallReturn
1104  int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
1105 {
1106  std::string path;
1107  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1108  return -EFAULT;
1109 
1110  // Modifying path from the directory descriptor
1111  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1112  return res;
1113  }
1114 
1115  return mknodImpl(desc, tc, path, mode, dev);
1116 }
1117 
1119 template <class OS>
1120 SyscallReturn
1123 {
1124  auto process = tc->getProcessPtr();
1125 
1126  sysinfo->uptime = seconds_since_epoch;
1127  sysinfo->totalram = process->system->memSize();
1128  sysinfo->mem_unit = 1;
1129 
1130  return 0;
1131 }
1132 
1134 template <class OS>
1135 SyscallReturn
1137  int dirfd, VPtr<> pathname, mode_t mode)
1138 {
1139  std::string path;
1140  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1141  return -EFAULT;
1142 
1143  // Modifying path from the directory descriptor
1144  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1145  return res;
1146  }
1147 
1148  mode_t hostMode = 0;
1149 
1150  // XXX translate mode flags via OS::something???
1151  hostMode = mode;
1152 
1153  auto process = tc->getProcessPtr();
1154  // Adjust path for cwd and redirection
1155  path = process->checkPathRedirect(path);
1156 
1157  // do the chmod
1158  int result = chmod(path.c_str(), hostMode);
1159  if (result < 0)
1160  return -errno;
1161 
1162  return 0;
1163 }
1164 
1166 template <class OS>
1167 SyscallReturn
1168 chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
1169 {
1170  return fchmodatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, mode);
1171 }
1172 
1173 template <class OS>
1174 SyscallReturn
1176  VPtr<> fdsPtr, int nfds, int tmout)
1177 {
1178  auto p = tc->getProcessPtr();
1179 
1180  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1181  fdsBuf.copyIn(SETranslatingPortProxy(tc));
1182 
1189  int temp_tgt_fds[nfds];
1190  for (int index = 0; index < nfds; index++) {
1191  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1192  auto tgt_fd = temp_tgt_fds[index];
1193  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1194  if (!hbfdp)
1195  return -EBADF;
1196  auto host_fd = hbfdp->getSimFD();
1197  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1198  }
1199 
1206  int status;
1207  if (tmout < 0) {
1208  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1209  if (status == 0) {
1215  System *sysh = tc->getSystemPtr();
1217  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1218  if (it->receiver == p)
1219  return -EINTR;
1220  return SyscallReturn::retry();
1221  }
1222  } else
1223  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1224 
1225  if (status == -1)
1226  return -errno;
1227 
1232  for (int index = 0; index < nfds; index++) {
1233  auto tgt_fd = temp_tgt_fds[index];
1234  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1235  }
1236 
1241  fdsBuf.copyOut(SETranslatingPortProxy(tc));
1242 
1243  return status;
1244 }
1245 
1247 template <class OS>
1248 SyscallReturn
1249 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1250 {
1251  auto p = tc->getProcessPtr();
1252 
1253  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1254  if (!ffdp)
1255  return -EBADF;
1256  int sim_fd = ffdp->getSimFD();
1257 
1258  mode_t hostMode = mode;
1259 
1260  int result = fchmod(sim_fd, hostMode);
1261 
1262  return (result < 0) ? -errno : 0;
1263 }
1264 
1266 template <class OS>
1267 SyscallReturn
1269  VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1271 {
1272  auto p = tc->getProcessPtr();
1273  Addr page_bytes = p->pTable->pageSize();
1274  uint64_t provided_address = 0;
1275  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1276 
1277  if (use_provided_address)
1278  provided_address = varargs.get<uint64_t>();
1279 
1280  if ((start % page_bytes != 0) ||
1281  (provided_address % page_bytes != 0)) {
1282  warn("mremap failing: arguments not page aligned");
1283  return -EINVAL;
1284  }
1285 
1286  new_length = roundUp(new_length, page_bytes);
1287 
1288  if (new_length > old_length) {
1289  Addr mmap_end = p->memState->getMmapEnd();
1290 
1291  if ((start + old_length) == mmap_end &&
1292  (!use_provided_address || provided_address == start)) {
1293  // This case cannot occur when growing downward, as
1294  // start is greater than or equal to mmap_end.
1295  uint64_t diff = new_length - old_length;
1296  p->memState->mapRegion(mmap_end, diff, "remapped");
1297  p->memState->setMmapEnd(mmap_end + diff);
1298  return (Addr)start;
1299  } else {
1300  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1301  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1302  return -ENOMEM;
1303  } else {
1304  uint64_t new_start = provided_address;
1305  if (!use_provided_address) {
1306  new_start = p->mmapGrowsDown() ?
1307  mmap_end - new_length : mmap_end;
1308  mmap_end = p->mmapGrowsDown() ?
1309  new_start : mmap_end + new_length;
1310  p->memState->setMmapEnd(mmap_end);
1311  }
1312 
1313  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1314  new_start, new_start + new_length,
1315  new_length - old_length);
1316 
1317  // add on the remaining unallocated pages
1318  p->allocateMem(new_start + old_length,
1319  new_length - old_length,
1320  use_provided_address /* clobber */);
1321 
1322  if (use_provided_address &&
1323  ((new_start + new_length > p->memState->getMmapEnd() &&
1324  !p->mmapGrowsDown()) ||
1325  (new_start < p->memState->getMmapEnd() &&
1326  p->mmapGrowsDown()))) {
1327  // something fishy going on here, at least notify the user
1328  // @todo: increase mmap_end?
1329  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1330  }
1331 
1332  warn("returning %08p as start\n", new_start);
1333  p->memState->remapRegion(start, new_start, old_length);
1334  return new_start;
1335  }
1336  }
1337  } else {
1338  // Shrink a region
1339  if (use_provided_address && provided_address != start)
1340  p->memState->remapRegion(start, provided_address, new_length);
1341  if (new_length != old_length)
1342  p->memState->unmapRegion(start + new_length,
1343  old_length - new_length);
1344  return use_provided_address ? provided_address : (Addr)start;
1345  }
1346 }
1347 
1349 template <class OS>
1350 SyscallReturn
1352  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1353 {
1354  std::string path;
1355  auto process = tc->getProcessPtr();
1356 
1357  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1358  return -EFAULT;
1359 
1360  // Adjust path for cwd and redirection
1361  path = process->checkPathRedirect(path);
1362 
1363  struct stat hostBuf;
1364  int result = stat(path.c_str(), &hostBuf);
1365 
1366  if (result < 0)
1367  return -errno;
1368 
1369  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1370 
1371  return 0;
1372 }
1373 
1375 template <class OS>
1376 SyscallReturn
1378  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat,
1379  int flags)
1380 {
1381  std::string path;
1382 
1383  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1384  return -EFAULT;
1385 
1386  if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1387  return -ENOENT;
1388  flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1389 
1390  warn_if(flags != 0, "newfstatat: Flag bits %#x not supported.", flags);
1391 
1392  // Modifying path from the directory descriptor
1393  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1394  return res;
1395  }
1396 
1397  auto p = tc->getProcessPtr();
1398 
1399  // Adjust path for cwd and redirection
1400  path = p->checkPathRedirect(path);
1401 
1402  struct stat host_buf;
1403  int result = stat(path.c_str(), &host_buf);
1404 
1405  if (result < 0)
1406  return -errno;
1407 
1408  copyOutStatBuf<OS>(tgt_stat, &host_buf);
1409 
1410  return 0;
1411 }
1412 
1414 template <class OS>
1415 SyscallReturn
1417  int dirfd, VPtr<> pathname,
1419 {
1420  std::string path;
1421  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1422  return -EFAULT;
1423 
1424  // Modifying path from the directory descriptor
1425  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1426  return res;
1427  }
1428 
1429  auto p = tc->getProcessPtr();
1430 
1431  // Adjust path for cwd and redirection
1432  path = p->checkPathRedirect(path);
1433 
1434 #if NO_STAT64
1435  struct stat hostBuf;
1436  int result = stat(path.c_str(), &hostBuf);
1437 #else
1438  struct stat64 hostBuf;
1439  int result = stat64(path.c_str(), &hostBuf);
1440 #endif
1441 
1442  if (result < 0)
1443  return -errno;
1444 
1445  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1446 
1447  return 0;
1448 }
1449 
1451 template <class OS>
1452 SyscallReturn
1454  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1455 {
1456  return fstatat64Func<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_stat);
1457 }
1458 
1460 template <class OS>
1461 SyscallReturn
1463  int tgt_fd, VPtr<typename OS::tgt_stat64> tgt_stat)
1464 {
1465  auto p = tc->getProcessPtr();
1466 
1467  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1468  if (!ffdp)
1469  return -EBADF;
1470  int sim_fd = ffdp->getSimFD();
1471 
1472 #if NO_STAT64
1473  struct stat hostBuf;
1474  int result = fstat(sim_fd, &hostBuf);
1475 #else
1476  struct stat64 hostBuf;
1477  int result = fstat64(sim_fd, &hostBuf);
1478 #endif
1479 
1480  if (result < 0)
1481  return -errno;
1482 
1483  copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1484 
1485  return 0;
1486 }
1487 
1488 
1490 template <class OS>
1491 SyscallReturn
1493  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1494 {
1495  std::string path;
1496  auto process = tc->getProcessPtr();
1497 
1498  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1499  return -EFAULT;
1500 
1501  // Adjust path for cwd and redirection
1502  path = process->checkPathRedirect(path);
1503 
1504  struct stat hostBuf;
1505  int result = lstat(path.c_str(), &hostBuf);
1506 
1507  if (result < 0)
1508  return -errno;
1509 
1510  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1511 
1512  return 0;
1513 }
1514 
1516 template <class OS>
1517 SyscallReturn
1519  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1520 {
1521  std::string path;
1522  auto process = tc->getProcessPtr();
1523 
1524  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1525  return -EFAULT;
1526 
1527  // Adjust path for cwd and redirection
1528  path = process->checkPathRedirect(path);
1529 
1530 #if NO_STAT64
1531  struct stat hostBuf;
1532  int result = lstat(path.c_str(), &hostBuf);
1533 #else
1534  struct stat64 hostBuf;
1535  int result = lstat64(path.c_str(), &hostBuf);
1536 #endif
1537 
1538  if (result < 0)
1539  return -errno;
1540 
1541  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1542 
1543  return 0;
1544 }
1545 
1547 template <class OS>
1548 SyscallReturn
1550  int tgt_fd, VPtr<typename OS::tgt_stat> tgt_stat)
1551 {
1552  auto p = tc->getProcessPtr();
1553 
1554  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1555 
1556  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1557  if (!ffdp)
1558  return -EBADF;
1559  int sim_fd = ffdp->getSimFD();
1560 
1561  struct stat hostBuf;
1562  int result = fstat(sim_fd, &hostBuf);
1563 
1564  if (result < 0)
1565  return -errno;
1566 
1567  copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1568 
1569  return 0;
1570 }
1571 
1573 template <class OS>
1574 SyscallReturn
1576  VPtr<> pathname, VPtr<typename OS::tgt_statfs> tgt_stat)
1577 {
1578 #if defined(__linux__)
1579  std::string path;
1580  auto process = tc->getProcessPtr();
1581 
1582  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
1583  return -EFAULT;
1584 
1585  // Adjust path for cwd and redirection
1586  path = process->checkPathRedirect(path);
1587 
1588  struct statfs hostBuf;
1589  int result = statfs(path.c_str(), &hostBuf);
1590 
1591  if (result < 0)
1592  return -errno;
1593 
1594  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1595  return 0;
1596 #else
1597  warnUnsupportedOS("statfs");
1598  return -1;
1599 #endif
1600 }
1601 
1602 template <class OS>
1603 SyscallReturn
1605  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1606 {
1607  DPRINTF(SyscallVerbose, "Doing clone. pid: %#llx, ctid: %#llx, tls: %#llx"
1608  " flags: %#llx, stack: %#llx\n",
1609  ptidPtr.addr(), ctidPtr.addr(), tlsPtr.addr(), flags, newStack);
1610  auto p = tc->getProcessPtr();
1611 
1612  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1613  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1614  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1615  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1616  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1617  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1618  return -EINVAL;
1619 
1620  ThreadContext *ctc;
1621  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1622  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1623  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1624  return -EAGAIN;
1625  }
1626 
1633  ProcessParams *pp = new ProcessParams();
1634  pp->executable.assign(*(new std::string(p->progName())));
1635  pp->cmd.push_back(*(new std::string(p->progName())));
1636  pp->system = p->system;
1637  pp->cwd.assign(p->tgtCwd);
1638  pp->input.assign("stdin");
1639  pp->output.assign("stdout");
1640  pp->errout.assign("stderr");
1641  pp->uid = p->uid();
1642  pp->euid = p->euid();
1643  pp->gid = p->gid();
1644  pp->egid = p->egid();
1645  pp->release = p->release;
1646 
1647  /* Find the first free PID that's less than the maximum */
1648  std::set<int> const& pids = p->system->PIDs;
1649  int temp_pid = *pids.begin();
1650  do {
1651  temp_pid++;
1652  } while (pids.find(temp_pid) != pids.end());
1653  if (temp_pid >= System::maxPID)
1654  fatal("temp_pid is too large: %d", temp_pid);
1655 
1656  pp->pid = temp_pid;
1657  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1658  pp->useArchPT = p->useArchPT;
1659  pp->kvmInSE = p->kvmInSE;
1660  Process *cp = pp->create();
1661  // TODO: there is no way to know when the Process SimObject is done with
1662  // the params pointer. Both the params pointer (pp) and the process
1663  // pointer (cp) are normally managed in python and are never cleaned up.
1664 
1665  Process *owner = ctc->getProcessPtr();
1666  ctc->setProcessPtr(cp);
1667  cp->assignThreadContext(ctc->contextId());
1668  owner->revokeThreadContext(ctc->contextId());
1669 
1670  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1671  BufferArg ptidBuf(ptidPtr, sizeof(long));
1672  long *ptid = (long *)ptidBuf.bufferPtr();
1673  *ptid = cp->pid();
1674  ptidBuf.copyOut(SETranslatingPortProxy(tc));
1675  }
1676 
1677  if (flags & OS::TGT_CLONE_THREAD) {
1678  cp->pTable->initState();
1679  cp->pTable->shared = true;
1680  cp->useForClone = true;
1681  }
1682 
1683  ctc->setUseForClone(true);
1684  cp->initState();
1685  p->clone(tc, ctc, cp, flags);
1686 
1687  if (flags & OS::TGT_CLONE_THREAD) {
1688  delete cp->sigchld;
1689  cp->sigchld = p->sigchld;
1690  } else if (flags & OS::TGT_SIGCHLD) {
1691  *cp->sigchld = true;
1692  }
1693 
1694  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1695  BufferArg ctidBuf(ctidPtr, sizeof(long));
1696  long *ctid = (long *)ctidBuf.bufferPtr();
1697  *ctid = cp->pid();
1698  ctidBuf.copyOut(SETranslatingPortProxy(ctc));
1699  }
1700 
1701  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1702  cp->childClearTID = (uint64_t)ctidPtr;
1703 
1704  ctc->clearArchRegs();
1705 
1706  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1707 
1708  desc->returnInto(ctc, 0);
1709 
1710  ctc->activate();
1711 
1712  if (flags & OS::TGT_CLONE_VFORK) {
1713  tc->suspend();
1714  }
1715 
1716  return cp->pid();
1717 }
1718 
1719 template <class OS>
1720 SyscallReturn
1723 {
1724  VPtr<uint64_t> ptidPtr((Addr)cl_args->parent_tid, tc);
1725  VPtr<uint64_t> ctidPtr((Addr)cl_args->child_tid, tc);
1726  VPtr<uint64_t> tlsPtr((Addr)cl_args->tls, tc);
1727  // Clone3 gives the stack as the *lowest* address, but clone/__clone2
1728  // expects the stack parameter to be the actual stack pointer
1729  uint64_t new_stack = cl_args->stack + cl_args->stack_size;
1730  uint64_t flags = cl_args->flags;
1731 
1732  return doClone<OS>(desc, tc, flags, new_stack, ptidPtr, ctidPtr, tlsPtr);
1733 }
1734 
1735 template <class OS>
1736 SyscallReturn
1738  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1739 {
1740  return doClone<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1741 }
1742 
1743 template <class OS>
1744 SyscallReturn
1746  RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1747  VPtr<> ctidPtr)
1748 {
1749  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1750 }
1751 
1753 template <class OS>
1754 SyscallReturn
1756  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1757 {
1758  auto p = tc->getProcessPtr();
1759 
1760  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1761  if (!ffdp)
1762  return -EBADF;
1763  int sim_fd = ffdp->getSimFD();
1764 
1765  struct statfs hostBuf;
1766  int result = fstatfs(sim_fd, &hostBuf);
1767 
1768  if (result < 0)
1769  return -errno;
1770 
1771  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1772 
1773  return 0;
1774 }
1775 
1777 template <class OS>
1778 SyscallReturn
1780  int tgt_fd, uint64_t tiov_base,
1781  typename OS::size_t count)
1782 {
1783  auto p = tc->getProcessPtr();
1784 
1785  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1786  if (!ffdp)
1787  return -EBADF;
1788  int sim_fd = ffdp->getSimFD();
1789 
1790  SETranslatingPortProxy prox(tc);
1791  typename OS::tgt_iovec tiov[count];
1792  struct iovec hiov[count];
1793  for (typename OS::size_t i = 0; i < count; ++i) {
1794  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1795  &tiov[i], sizeof(typename OS::tgt_iovec));
1796  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1797  hiov[i].iov_base = new char [hiov[i].iov_len];
1798  }
1799 
1800  int result = readv(sim_fd, hiov, count);
1801  int local_errno = errno;
1802 
1803  for (typename OS::size_t i = 0; i < count; ++i) {
1804  if (result != -1) {
1805  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1806  hiov[i].iov_base, hiov[i].iov_len);
1807  }
1808  delete [] (char *)hiov[i].iov_base;
1809  }
1810 
1811  return (result == -1) ? -local_errno : result;
1812 }
1813 
1815 template <class OS>
1816 SyscallReturn
1818  int tgt_fd, uint64_t tiov_base,
1819  typename OS::size_t count)
1820 {
1821  auto p = tc->getProcessPtr();
1822 
1823  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1824  if (!hbfdp)
1825  return -EBADF;
1826  int sim_fd = hbfdp->getSimFD();
1827 
1828  SETranslatingPortProxy prox(tc);
1829  struct iovec hiov[count];
1830  for (typename OS::size_t i = 0; i < count; ++i) {
1831  typename OS::tgt_iovec tiov;
1832 
1833  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1834  &tiov, sizeof(typename OS::tgt_iovec));
1835  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1836  hiov[i].iov_base = new char [hiov[i].iov_len];
1837  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1838  hiov[i].iov_len);
1839  }
1840 
1841  int result = writev(sim_fd, hiov, count);
1842 
1843  for (typename OS::size_t i = 0; i < count; ++i)
1844  delete [] (char *)hiov[i].iov_base;
1845 
1846  return (result == -1) ? -errno : result;
1847 }
1848 
1850 template <class OS>
1851 SyscallReturn
1853  VPtr<> start, typename OS::size_t length, int prot,
1854  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1855 {
1856  auto p = tc->getProcessPtr();
1857  Addr page_bytes = p->pTable->pageSize();
1858 
1859  if (start & (page_bytes - 1) ||
1860  offset & (page_bytes - 1) ||
1861  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1862  tgt_flags & OS::TGT_MAP_SHARED) ||
1863  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1864  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1865  !length) {
1866  return -EINVAL;
1867  }
1868 
1869  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1870  // With shared mmaps, there are two cases to consider:
1871  // 1) anonymous: writes should modify the mapping and this should be
1872  // visible to observers who share the mapping. Currently, it's
1873  // difficult to update the shared mapping because there's no
1874  // structure which maintains information about the which virtual
1875  // memory areas are shared. If that structure existed, it would be
1876  // possible to make the translations point to the same frames.
1877  // 2) file-backed: writes should modify the mapping and the file
1878  // which is backed by the mapping. The shared mapping problem is the
1879  // same as what was mentioned about the anonymous mappings. For
1880  // file-backed mappings, the writes to the file are difficult
1881  // because it requires syncing what the mapping holds with the file
1882  // that resides on the host system. So, any write on a real system
1883  // would cause the change to be propagated to the file mapping at
1884  // some point in the future (the inode is tracked along with the
1885  // mapping). This isn't guaranteed to always happen, but it usually
1886  // works well enough. The guarantee is provided by the msync system
1887  // call. We could force the change through with shared mappings with
1888  // a call to msync, but that again would require more information
1889  // than we currently maintain.
1890  warn_once("mmap: writing to shared mmap region is currently "
1891  "unsupported. The write succeeds on the target, but it "
1892  "will not be propagated to the host or shared mappings");
1893  }
1894 
1895  length = roundUp(length, page_bytes);
1896 
1897  int sim_fd = -1;
1898  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1899  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1900 
1901  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1902  if (dfdp) {
1903  EmulatedDriver *emul_driver = dfdp->getDriver();
1904  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1905  tgt_fd, offset);
1906  }
1907 
1908  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1909  if (!ffdp)
1910  return -EBADF;
1911  sim_fd = ffdp->getSimFD();
1912 
1921  if (p->interpImage.contains(tc->pcState().instAddr())) {
1922  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1923  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1924  auto *lib = loader::createObjectFile(p->checkPathRedirect(
1925  ffdp->getFileName()));
1926  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1927  ffdp->getFileName());
1928 
1929  if (lib) {
1930  Addr offset = lib->buildImage().minAddr() + start;
1931  loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1932  }
1933  }
1934  }
1935 
1939  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1947  if (!(start && p->memState->isUnmapped(start, length))) {
1951  start = p->memState->extendMmap(length);
1952  }
1953  }
1954 
1955  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1956  start, start + length - 1);
1957 
1963  if (tgt_flags & OS::TGT_MAP_FIXED) {
1968  p->memState->unmapRegion(start, length);
1969  }
1970 
1974  std::string region_name;
1975  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1976  region_name = "anon";
1977  } else {
1978  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1979  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1980  region_name = ffdp->getFileName();
1981  }
1982 
1987  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1988 
1989  return (Addr)start;
1990 }
1991 
1992 template <class OS>
1993 SyscallReturn
1995  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1996 {
1997  auto p = tc->getProcessPtr();
1998 
1999  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2000  if (!ffdp)
2001  return -EBADF;
2002  int sim_fd = ffdp->getSimFD();
2003 
2004  BufferArg bufArg(bufPtr, nbytes);
2005 
2006  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2007 
2008  bufArg.copyOut(SETranslatingPortProxy(tc));
2009 
2010  return (bytes_read == -1) ? -errno : bytes_read;
2011 }
2012 
2013 template <class OS>
2014 SyscallReturn
2016  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
2017 {
2018  auto p = tc->getProcessPtr();
2019 
2020  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2021  if (!ffdp)
2022  return -EBADF;
2023  int sim_fd = ffdp->getSimFD();
2024 
2025  BufferArg bufArg(bufPtr, nbytes);
2026  bufArg.copyIn(SETranslatingPortProxy(tc));
2027 
2028  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2029 
2030  return (bytes_written == -1) ? -errno : bytes_written;
2031 }
2032 
2034 template <class OS>
2035 SyscallReturn
2037  VPtr<> start, typename OS::size_t length, int prot,
2038  int tgt_flags, int tgt_fd, typename OS::off_t offset)
2039 {
2040  auto page_size = tc->getProcessPtr()->pTable->pageSize();
2041  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
2042  tgt_fd, offset * page_size);
2043 }
2044 
2046 template <class OS>
2047 SyscallReturn
2049  unsigned resource, VPtr<typename OS::rlimit> rlp)
2050 {
2051  const ByteOrder bo = OS::byteOrder;
2052  switch (resource) {
2053  case OS::TGT_RLIMIT_STACK:
2054  // max stack size in bytes: make up a number (8MiB for now)
2055  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2056  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2057  rlp->rlim_max = htog(rlp->rlim_max, bo);
2058  break;
2059 
2060  case OS::TGT_RLIMIT_DATA:
2061  // max data segment size in bytes: make up a number
2062  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2063  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2064  rlp->rlim_max = htog(rlp->rlim_max, bo);
2065  break;
2066 
2067  case OS::TGT_RLIMIT_NPROC:
2068  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
2069  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2070  rlp->rlim_max = htog(rlp->rlim_max, bo);
2071  break;
2072 
2073  default:
2074  warn("getrlimit: unimplemented resource %d", resource);
2075  return -EINVAL;
2076  break;
2077  }
2078 
2079  return 0;
2080 }
2081 
2082 template <class OS>
2083 SyscallReturn
2085  int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
2086 {
2087  if (pid != 0) {
2088  warn("prlimit: ignoring rlimits for nonzero pid");
2089  return -EPERM;
2090  }
2091  if (n)
2092  warn("prlimit: ignoring new rlimit");
2093  if (rlp) {
2094  const ByteOrder bo = OS::byteOrder;
2095  switch (resource) {
2096  case OS::TGT_RLIMIT_STACK:
2097  // max stack size in bytes: make up a number (8MiB for now)
2098  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2099  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2100  rlp->rlim_max = htog(rlp->rlim_max, bo);
2101  break;
2102  case OS::TGT_RLIMIT_DATA:
2103  // max data segment size in bytes: make up a number
2104  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2105  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2106  rlp->rlim_max = htog(rlp->rlim_max, bo);
2107  break;
2108  default:
2109  warn("prlimit: unimplemented resource %d", resource);
2110  return -EINVAL;
2111  break;
2112  }
2113  }
2114  return 0;
2115 }
2116 
2118 template <class OS>
2119 SyscallReturn
2121  int clk_id, VPtr<typename OS::timespec> tp)
2122 {
2123  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
2124  tp->tv_sec += seconds_since_epoch;
2125  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2126  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
2127 
2128  return 0;
2129 }
2130 
2132 template <class OS>
2133 SyscallReturn
2136 {
2137  // Set resolution at ns, which is what clock_gettime() returns
2138  tp->tv_sec = 0;
2139  tp->tv_nsec = 1;
2140 
2141  return 0;
2142 }
2143 
2145 template <class OS>
2146 SyscallReturn
2149 {
2150  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
2151  tp->tv_sec += seconds_since_epoch;
2152  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2153  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
2154 
2155  return 0;
2156 }
2157 
2159 template <class OS>
2160 SyscallReturn
2162  int dirfd, VPtr<> pathname, VPtr<typename OS::timeval [2]> tp)
2163 {
2164  std::string path;
2165  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
2166  return -EFAULT;
2167 
2168  // Modifying path from the directory descriptor
2169  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
2170  return res;
2171  }
2172 
2173  struct timeval hostTimeval[2];
2174  for (int i = 0; i < 2; ++i) {
2175  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
2176  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
2177  }
2178 
2179  // Adjust path for cwd and redirection
2180  auto process = tc->getProcessPtr();
2181  path = process->checkPathRedirect(path);
2182 
2183  int result = utimes(path.c_str(), hostTimeval);
2184 
2185  if (result < 0)
2186  return -errno;
2187 
2188  return 0;
2189 }
2190 
2192 template <class OS>
2193 SyscallReturn
2195  VPtr<typename OS::timeval [2]> tp)
2196 {
2197  return futimesatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tp);
2198 }
2199 
2200 template <class OS>
2201 SyscallReturn
2203  VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
2204 {
2205  auto p = tc->getProcessPtr();
2206 
2207  std::string path;
2208  SETranslatingPortProxy mem_proxy(tc);
2209  if (!mem_proxy.tryReadString(path, pathname))
2210  return -EFAULT;
2211 
2212  if (access(path.c_str(), F_OK) == -1)
2213  return -EACCES;
2214 
2215  auto read_in = [](std::vector<std::string> &vect,
2216  PortProxy &mem_proxy, VPtr<> mem_loc)
2217  {
2218  for (int inc = 0; ; inc++) {
2219  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2220  b.copyIn(mem_proxy);
2221 
2222  if (!*(Addr*)b.bufferPtr())
2223  break;
2224 
2225  vect.push_back(std::string());
2226  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2227  }
2228  };
2229 
2234  if (!p->vforkContexts.empty()) {
2235  ThreadContext *vtc = p->system->threads[p->vforkContexts.front()];
2236  assert(vtc->status() == ThreadContext::Suspended);
2237  vtc->activate();
2238  }
2239 
2246  ProcessParams *pp = new ProcessParams();
2247  pp->executable = path;
2248  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2249  read_in(pp->env, mem_proxy, envp_mem_loc);
2250  pp->uid = p->uid();
2251  pp->egid = p->egid();
2252  pp->euid = p->euid();
2253  pp->gid = p->gid();
2254  pp->ppid = p->ppid();
2255  pp->pid = p->pid();
2256  pp->input.assign("cin");
2257  pp->output.assign("cout");
2258  pp->errout.assign("cerr");
2259  pp->cwd.assign(p->tgtCwd);
2260  pp->system = p->system;
2261  pp->release = p->release;
2270  p->system->PIDs.erase(p->pid());
2271  Process *new_p = pp->create();
2272  // TODO: there is no way to know when the Process SimObject is done with
2273  // the params pointer. Both the params pointer (pp) and the process
2274  // pointer (p) are normally managed in python and are never cleaned up.
2275 
2280  new_p->fds = p->fds;
2281  for (int i = 0; i < new_p->fds->getSize(); i++) {
2282  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2283  if (fdep && fdep->getCOE())
2284  new_p->fds->closeFDEntry(i);
2285  }
2286 
2287  *new_p->sigchld = true;
2288 
2289  tc->clearArchRegs();
2290  tc->setProcessPtr(new_p);
2291  new_p->assignThreadContext(tc->contextId());
2292  new_p->init();
2293  new_p->initState();
2294  tc->activate();
2295 
2296  return SyscallReturn();
2297 }
2298 
2300 template <class OS>
2301 SyscallReturn
2303  int who /* THREAD, SELF, or CHILDREN */,
2305 {
2306  rup->ru_utime.tv_sec = 0;
2307  rup->ru_utime.tv_usec = 0;
2308  rup->ru_stime.tv_sec = 0;
2309  rup->ru_stime.tv_usec = 0;
2310  rup->ru_maxrss = 0;
2311  rup->ru_ixrss = 0;
2312  rup->ru_idrss = 0;
2313  rup->ru_isrss = 0;
2314  rup->ru_minflt = 0;
2315  rup->ru_majflt = 0;
2316  rup->ru_nswap = 0;
2317  rup->ru_inblock = 0;
2318  rup->ru_oublock = 0;
2319  rup->ru_msgsnd = 0;
2320  rup->ru_msgrcv = 0;
2321  rup->ru_nsignals = 0;
2322  rup->ru_nvcsw = 0;
2323  rup->ru_nivcsw = 0;
2324 
2325  switch (who) {
2326  case OS::TGT_RUSAGE_SELF:
2327  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2328  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2329  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2330  break;
2331 
2332  case OS::TGT_RUSAGE_CHILDREN:
2333  // do nothing. We have no child processes, so they take no time.
2334  break;
2335 
2336  default:
2337  // don't really handle THREAD or CHILDREN, but just warn and
2338  // plow ahead
2339  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2340  who);
2341  }
2342 
2343  return 0;
2344 }
2345 
2347 template <class OS>
2348 SyscallReturn
2350 {
2351  // Fill in the time structure (in clocks)
2352  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / sim_clock::as_int::s;
2353  bufp->tms_utime = clocks;
2354  bufp->tms_stime = 0;
2355  bufp->tms_cutime = 0;
2356  bufp->tms_cstime = 0;
2357 
2358  // Convert to host endianness
2359  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2360 
2361  // Return clock ticks since system boot
2362  return clocks;
2363 }
2364 
2366 template <class OS>
2367 SyscallReturn
2369 {
2370  typename OS::time_t sec, usec;
2371  getElapsedTimeMicro(sec, usec);
2372  sec += seconds_since_epoch;
2373 
2375  if (taddr != 0) {
2376  typename OS::time_t t = sec;
2377  t = htog(t, OS::byteOrder);
2378  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2379  }
2380  return sec;
2381 }
2382 
2383 template <class OS>
2384 SyscallReturn
2385 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2386 {
2402  System *sys = tc->getSystemPtr();
2403  Process *tgt_proc = nullptr;
2404  for (auto *tc: sys->threads) {
2405  Process *temp = tc->getProcessPtr();
2406  if (temp->pid() == tid) {
2407  tgt_proc = temp;
2408  break;
2409  }
2410  }
2411 
2412  if (sig != 0 || sig != OS::TGT_SIGABRT)
2413  return -EINVAL;
2414 
2415  if (tgt_proc == nullptr)
2416  return -ESRCH;
2417 
2418  if (tgid != -1 && tgt_proc->tgid() != tgid)
2419  return -ESRCH;
2420 
2421  if (sig == OS::TGT_SIGABRT)
2422  exitGroupFunc(desc, tc, 0);
2423 
2424  return 0;
2425 }
2426 
2427 template <class OS>
2428 SyscallReturn
2430  int domain, int type, int prot)
2431 {
2432  auto p = tc->getProcessPtr();
2433 
2434  int sim_fd = socket(domain, type, prot);
2435  if (sim_fd == -1)
2436  return -errno;
2437 
2438  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2439  int tgt_fd = p->fds->allocFD(sfdp);
2440 
2441  return tgt_fd;
2442 }
2443 
2444 template <class OS>
2445 SyscallReturn
2447  int domain, int type, int prot, VPtr<> svPtr)
2448 {
2449  auto p = tc->getProcessPtr();
2450 
2451  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2452  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2453  if (status == -1)
2454  return -errno;
2455 
2456  int *fds = (int *)svBuf.bufferPtr();
2457 
2458  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2459  fds[0] = p->fds->allocFD(sfdp1);
2460  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2461  fds[1] = p->fds->allocFD(sfdp2);
2462  svBuf.copyOut(SETranslatingPortProxy(tc));
2463 
2464  return status;
2465 }
2466 
2467 template <class OS>
2468 SyscallReturn
2469 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2470  VPtr<typename OS::fd_set> readfds,
2471  VPtr<typename OS::fd_set> writefds,
2472  VPtr<typename OS::fd_set> errorfds,
2474 {
2475  int retval;
2476 
2477  auto p = tc->getProcessPtr();
2478 
2484  fd_set readfds_h;
2485  FD_ZERO(&readfds_h);
2486  fd_set writefds_h;
2487  FD_ZERO(&writefds_h);
2488  fd_set errorfds_h;
2489  FD_ZERO(&errorfds_h);
2490 
2500  int nfds_h = 0;
2501  std::map<int, int> trans_map;
2502  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2503  fd_set *hst_set_entry,
2504  int iter) -> bool
2505  {
2511  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2517  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2518  if (!hbfdp)
2519  return true;
2520  auto sim_fd = hbfdp->getSimFD();
2521 
2527  trans_map[sim_fd] = iter;
2528 
2534  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2535 
2540  FD_SET(sim_fd, hst_set_entry);
2541  }
2542  return false;
2543  };
2544 
2545  for (int i = 0; i < nfds; i++) {
2546  if (readfds) {
2547  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2548  if (ebadf)
2549  return -EBADF;
2550  }
2551  if (writefds) {
2552  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2553  if (ebadf)
2554  return -EBADF;
2555  }
2556  if (errorfds) {
2557  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2558  if (ebadf)
2559  return -EBADF;
2560  }
2561  }
2562 
2563  if (timeout) {
2571  timeout->tv_sec = 0;
2572  timeout->tv_usec = 0;
2573 
2574  retval = select(nfds_h,
2575  readfds ? &readfds_h : nullptr,
2576  writefds ? &writefds_h : nullptr,
2577  errorfds ? &errorfds_h : nullptr,
2578  (timeval *)(typename OS::timeval *)timeout);
2579  } else {
2587  struct timeval tv = { 0, 0 };
2588 
2589  retval = select(nfds_h,
2590  readfds ? &readfds_h : nullptr,
2591  readfds ? &writefds_h : nullptr,
2592  readfds ? &errorfds_h : nullptr,
2593  &tv);
2594 
2595  if (retval == 0) {
2601  for (auto sig : tc->getSystemPtr()->signalList)
2602  if (sig.receiver == p)
2603  return -EINTR;
2604  return SyscallReturn::retry();
2605  }
2606  }
2607 
2608  if (retval == -1)
2609  return -errno;
2610 
2611  if (readfds) {
2612  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2613  }
2614  if (writefds) {
2615  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2616  }
2617  if (errorfds) {
2618  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2619  }
2620 
2626  for (int i = 0; i < nfds_h; i++) {
2627  if (readfds && FD_ISSET(i, &readfds_h))
2628  FD_SET(trans_map[i],
2629  reinterpret_cast<fd_set *>(
2630  (typename OS::fd_set *)readfds));
2631 
2632  if (writefds && FD_ISSET(i, &writefds_h))
2633  FD_SET(trans_map[i],
2634  reinterpret_cast<fd_set *>(
2635  (typename OS::fd_set *)writefds));
2636 
2637  if (errorfds && FD_ISSET(i, &errorfds_h))
2638  FD_SET(trans_map[i],
2639  reinterpret_cast<fd_set *>(
2640  (typename OS::fd_set *)errorfds));
2641  }
2642 
2643  return retval;
2644 }
2645 
2646 template <class OS>
2647 SyscallReturn
2649  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2650 {
2651  auto p = tc->getProcessPtr();
2652 
2653  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2654  if (!hbfdp)
2655  return -EBADF;
2656  int sim_fd = hbfdp->getSimFD();
2657 
2658  struct pollfd pfd;
2659  pfd.fd = sim_fd;
2660  pfd.events = POLLIN | POLLPRI;
2661  if ((poll(&pfd, 1, 0) == 0)
2662  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2663  return SyscallReturn::retry();
2664 
2665  BufferArg buf_arg(buf_ptr, nbytes);
2666  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2667 
2668  if (bytes_read > 0)
2669  buf_arg.copyOut(SETranslatingPortProxy(tc));
2670 
2671  return (bytes_read == -1) ? -errno : bytes_read;
2672 }
2673 
2674 template <class OS>
2675 SyscallReturn
2677  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2678 {
2679  auto p = tc->getProcessPtr();
2680 
2681  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2682  if (!hbfdp)
2683  return -EBADF;
2684  int sim_fd = hbfdp->getSimFD();
2685 
2686  BufferArg buf_arg(buf_ptr, nbytes);
2687  buf_arg.copyIn(SETranslatingPortProxy(tc));
2688 
2689  struct pollfd pfd;
2690  pfd.fd = sim_fd;
2691  pfd.events = POLLOUT;
2692 
2699  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2700  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2701  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2702  return SyscallReturn::retry();
2703  }
2704 
2705  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2706 
2707  if (bytes_written != -1)
2708  fsync(sim_fd);
2709 
2710  return (bytes_written == -1) ? -errno : bytes_written;
2711 }
2712 
2713 template <class OS>
2714 SyscallReturn
2716  pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2717 {
2718  auto p = tc->getProcessPtr();
2719 
2720  if (rusagePtr)
2721  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2722  "functionality not supported. Ignoring rusage pointer.\n",
2723  rusagePtr);
2724 
2733  System *sysh = tc->getSystemPtr();
2735  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2736  if (iter->receiver == p) {
2737  if (pid < -1) {
2738  if ((iter->sender->pgid() == -pid)
2739  && (iter->signalValue == OS::TGT_SIGCHLD))
2740  goto success;
2741  } else if (pid == -1) {
2742  if (iter->signalValue == OS::TGT_SIGCHLD)
2743  goto success;
2744  } else if (pid == 0) {
2745  if ((iter->sender->pgid() == p->pgid())
2746  && (iter->signalValue == OS::TGT_SIGCHLD))
2747  goto success;
2748  } else {
2749  if ((iter->sender->pid() == pid)
2750  && (iter->signalValue == OS::TGT_SIGCHLD))
2751  goto success;
2752  }
2753  }
2754  }
2755 
2756  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2757 
2758 success:
2759  // Set status to EXITED for WIFEXITED evaluations.
2760  const int EXITED = 0;
2761  BufferArg statusBuf(statPtr, sizeof(int));
2762  *(int *)statusBuf.bufferPtr() = EXITED;
2763  statusBuf.copyOut(SETranslatingPortProxy(tc));
2764 
2765  // Return the child PID.
2766  pid_t retval = iter->sender->pid();
2767  sysh->signalList.erase(iter);
2768  return retval;
2769 }
2770 
2771 template <class OS>
2772 SyscallReturn
2774  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2775 {
2776  struct sockaddr sa;
2777  socklen_t addrLen;
2778  int host_fd;
2779  auto p = tc->getProcessPtr();
2780 
2781  BufferArg *lenBufPtr = nullptr;
2782  BufferArg *addrBufPtr = nullptr;
2783 
2784  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2785  if (!sfdp)
2786  return -EBADF;
2787  int sim_fd = sfdp->getSimFD();
2788 
2795  struct pollfd pfd;
2796  pfd.fd = sim_fd;
2797  pfd.events = POLLIN | POLLPRI;
2798  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2799  return SyscallReturn::retry();
2800 
2801  if (lenPtr) {
2802  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2803  lenBufPtr->copyIn(SETranslatingPortProxy(tc));
2804  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2805  sizeof(socklen_t));
2806  }
2807 
2808  if (addrPtr) {
2809  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2810  addrBufPtr->copyIn(SETranslatingPortProxy(tc));
2811  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2812  sizeof(struct sockaddr));
2813  }
2814 
2815  host_fd = accept(sim_fd, &sa, &addrLen);
2816 
2817  if (host_fd == -1)
2818  return -errno;
2819 
2820  if (addrPtr) {
2821  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2822  addrBufPtr->copyOut(SETranslatingPortProxy(tc));
2823  delete(addrBufPtr);
2824  }
2825 
2826  if (lenPtr) {
2827  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2828  lenBufPtr->copyOut(SETranslatingPortProxy(tc));
2829  delete(lenBufPtr);
2830  }
2831 
2832  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2833  sfdp->_type, sfdp->_protocol);
2834  return p->fds->allocFD(afdp);
2835 }
2836 
2838 template <class OS>
2839 SyscallReturn
2841  unsigned initval, int in_flags)
2842 {
2843 #if defined(__linux__)
2844  auto p = tc->getProcessPtr();
2845 
2846  int sim_fd = eventfd(initval, in_flags);
2847  if (sim_fd == -1)
2848  return -errno;
2849 
2850  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2851 
2852  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2853  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2854 
2855  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2856  int tgt_fd = p->fds->allocFD(hbfdp);
2857  return tgt_fd;
2858 #else
2859  warnUnsupportedOS("eventfd");
2860  return -1;
2861 #endif
2862 }
2863 
2865 template <class OS>
2866 SyscallReturn
2868  pid_t pid, typename OS::size_t cpusetsize,
2869  VPtr<> cpu_set_mask)
2870 {
2871 #if defined(__linux__)
2872  if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size()))
2873  return -EINVAL;
2874 
2875  SETranslatingPortProxy proxy(tc);
2876  BufferArg maskBuf(cpu_set_mask, cpusetsize);
2877  maskBuf.copyIn(proxy);
2878  for (int i = 0; i < tc->getSystemPtr()->threads.size(); i++) {
2879  CPU_SET(i, (cpu_set_t *)maskBuf.bufferPtr());
2880  }
2881  maskBuf.copyOut(proxy);
2882  return CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size());
2883 #else
2884  warnUnsupportedOS("sched_getaffinity");
2885  return -1;
2886 #endif
2887 }
2888 
2889 // Target recvfrom() handler.
2890 template <class OS>
2891 SyscallReturn
2893  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len,
2894  int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
2895 {
2896  auto p = tc->getProcessPtr();
2897 
2898  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2899  if (!sfdp)
2900  return -EBADF;
2901  int sim_fd = sfdp->getSimFD();
2902 
2903  // Reserve buffer space.
2904  BufferArg buf(buf_ptr, buf_len);
2905 
2906  SETranslatingPortProxy proxy(tc);
2907 
2908  // Get address length.
2909  socklen_t addr_len = 0;
2910  if (addrlen_ptr != 0) {
2911  // Read address length parameter.
2912  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2913  addrlen_buf.copyIn(proxy);
2914  addr_len = *((socklen_t *)addrlen_buf.bufferPtr());
2915  }
2916 
2917  struct sockaddr sa, *sap = NULL;
2918  if (addr_len != 0) {
2919  BufferArg addr_buf(addr_ptr, addr_len);
2920  addr_buf.copyIn(proxy);
2921  memcpy(&sa, (struct sockaddr *)addr_buf.bufferPtr(),
2922  sizeof(struct sockaddr));
2923  sap = &sa;
2924  }
2925 
2926  ssize_t recvd_size = recvfrom(sim_fd,
2927  (void *)buf.bufferPtr(),
2928  buf_len, flags, sap, (socklen_t *)&addr_len);
2929 
2930  if (recvd_size == -1)
2931  return -errno;
2932 
2933  // Pass the received data out.
2934  buf.copyOut(proxy);
2935 
2936  // Copy address to addr_ptr and pass it on.
2937  if (sap != NULL) {
2938  BufferArg addr_buf(addr_ptr, addr_len);
2939  memcpy(addr_buf.bufferPtr(), sap, sizeof(sa));
2940  addr_buf.copyOut(proxy);
2941  }
2942 
2943  // Copy len to addrlen_ptr and pass it on.
2944  if (addr_len != 0) {
2945  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2946  *(socklen_t *)addrlen_buf.bufferPtr() = addr_len;
2947  addrlen_buf.copyOut(proxy);
2948  }
2949 
2950  return recvd_size;
2951 }
2952 
2953 // Target sendto() handler.
2954 template <typename OS>
2955 SyscallReturn
2957  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags,
2958  VPtr<> addr_ptr, socklen_t addr_len)
2959 {
2960  auto p = tc->getProcessPtr();
2961 
2962  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2963  if (!sfdp)
2964  return -EBADF;
2965  int sim_fd = sfdp->getSimFD();
2966 
2967  // Reserve buffer space.
2968  BufferArg buf(buf_ptr, buf_len);
2969  buf.copyIn(SETranslatingPortProxy(tc));
2970 
2971  struct sockaddr sa, *sap = nullptr;
2972  memset(&sa, 0, sizeof(sockaddr));
2973  if (addr_len != 0) {
2974  BufferArg addr_buf(addr_ptr, addr_len);
2975  addr_buf.copyIn(SETranslatingPortProxy(tc));
2976  memcpy(&sa, (sockaddr*)addr_buf.bufferPtr(), addr_len);
2977  sap = &sa;
2978  }
2979 
2980  ssize_t sent_size = sendto(sim_fd,
2981  (void *)buf.bufferPtr(),
2982  buf_len, flags, sap, (socklen_t)addr_len);
2983 
2984  return (sent_size == -1) ? -errno : sent_size;
2985 }
2986 
2988 template <typename OS>
2989 SyscallReturn
2991  typename OS::size_t length)
2992 {
2993  // Even if the system is currently not capable of recycling physical
2994  // pages, there is no reason we can't unmap them so that we trigger
2995  // appropriate seg faults when the application mistakenly tries to
2996  // access them again.
2997  auto p = tc->getProcessPtr();
2998 
2999  if (p->pTable->pageOffset(start))
3000  return -EINVAL;
3001 
3002  length = roundUp(length, p->pTable->pageSize());
3003 
3004  p->memState->unmapRegion(start, length);
3005 
3006  return 0;
3007 }
3008 
3009 // Target fallocate() handler.
3010 template <typename OS>
3011 SyscallReturn
3013  int tgt_fd, int mode, typename OS::off_t offset,
3014  typename OS::off_t len)
3015 {
3016 #if defined(__linux__)
3017  auto p = tc->getProcessPtr();
3018 
3019  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3020  if (!ffdp)
3021  return -EBADF;
3022  int sim_fd = ffdp->getSimFD();
3023 
3024  int result = fallocate(sim_fd, mode, offset, len);
3025  if (result < 0)
3026  return -errno;
3027  return 0;
3028 #else
3029  warnUnsupportedOS("fallocate");
3030  return -1;
3031 #endif
3032 }
3033 
3035 template <typename OS>
3036 SyscallReturn
3038  typename OS::off_t length)
3039 {
3040  std::string path;
3041  auto p = tc->getProcessPtr();
3042 
3043  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
3044  return -EFAULT;
3045 
3046  // Adjust path for cwd and redirection
3047  path = p->checkPathRedirect(path);
3048 
3049  int result = truncate(path.c_str(), length);
3050  return (result == -1) ? -errno : result;
3051 }
3052 
3054 template <typename OS>
3055 SyscallReturn
3056 ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd,
3057  typename OS::off_t length)
3058 {
3059  auto p = tc->getProcessPtr();
3060 
3061  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3062  if (!ffdp)
3063  return -EBADF;
3064  int sim_fd = ffdp->getSimFD();
3065 
3066  int result = ftruncate(sim_fd, length);
3067  return (result == -1) ? -errno : result;
3068 }
3069 
3070 template <typename OS>
3071 SyscallReturn
3073  VPtr<> buf_ptr, typename OS::size_t count,
3074  unsigned int flags)
3075 {
3076  SETranslatingPortProxy proxy(tc);
3077 
3078  TypedBufferArg<uint8_t> buf(buf_ptr, count);
3079  for (int i = 0; i < count; ++i) {
3080  buf[i] = gem5::random_mt.random<uint8_t>();
3081  }
3082  buf.copyOut(proxy);
3083 
3084  return count;
3085 }
3086 
3087 } // namespace gem5
3088 
3089 #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:1755
gem5::ConstProxyPtr::addr
Addr addr() const
Definition: proxy_ptr.hh:173
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:200
gem5::lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1518
gem5::Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:130
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:2349
gem5::Process::tgid
uint64_t tgid()
Definition: process.hh:90
gem5::pread64Func
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1994
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:256
gem5::System::Threads::size
int size() const
Definition: system.hh:210
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:3072
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:1852
gem5::getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:877
gem5::hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:561
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:1737
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:1377
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:260
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:1549
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:2469
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:598
gem5::ArmISA::domain
Bitfield< 7, 4 > domain
Definition: misc_types.hh:481
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:1066
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:2161
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:3037
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:776
gem5::getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:527
gem5::guest_abi::VarArgs::get
Arg get()
Definition: varargs.hh:164
gem5::startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:230
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:642
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:1492
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:357
gem5::prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:2084
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:86
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:67
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:65
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:1249
gem5::ThreadContext::setUseForClone
void setUseForClone(bool new_val)
Definition: thread_context.hh:97
gem5::Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:286
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:182
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:1121
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:911
gem5::Process::childClearTID
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:295
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:1175
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:1268
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:74
syscall_return.hh
gem5::ArmISA::b
Bitfield< 7 > b
Definition: misc_types.hh:438
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:1462
gem5::ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t length)
Target ftruncate() handler.
Definition: syscall_emul.hh:3056
gem5::System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:607
gem5::eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2840
gem5::gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:2147
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
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:761
gem5::unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags)
Target unlinkat() handler.
Definition: syscall_emul.hh:921
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:1817
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::doClone
SyscallReturn doClone(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
Definition: syscall_emul.hh:1604
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:107
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:891
gem5::X86ISA::count
count
Definition: misc.hh:710
gem5::socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2429
gem5::Process::pTable
EmulationPageTable * pTable
Definition: process.hh:184
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:1136
gem5::X86ISA::type
type
Definition: misc.hh:734
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:1575
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:1779
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:2134
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:556
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:2990
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:2015
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:384
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:540
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:1416
gem5::mkdiratFunc
SyscallReturn mkdiratFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target mkdirat() handler.
Definition: syscall_emul.hh:1085
gem5::hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:562
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:1027
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:961
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:600
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:2368
gem5::writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2676
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:620
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:2036
gem5::loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:134
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:2385
gem5::Process
Definition: process.hh:67
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
gem5::MipsISA::int_reg::T2
constexpr RegId T2
Definition: int.hh:148
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:283
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:2956
gem5::cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
Definition: syscall_emul.hh:1745
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:2120
gem5::renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
Definition: syscall_emul.hh:1038
gem5::ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
Definition: syscall_emul.hh:686
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:54
gem5::chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:1168
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:310
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:513
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:2892
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:1103
gem5::atSyscallPath
SyscallReturn atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
Definition: syscall_emul.hh:359
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:2715
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:1351
gem5::Process::sigchld
bool * sigchld
Definition: process.hh:298
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:3012
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:1453
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:521
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:2648
gem5::clone3Func
SyscallReturn clone3Func(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_clone_args > cl_args, RegVal size)
Definition: syscall_emul.hh:1721
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:2867
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::MipsISA::int_reg::T1
constexpr RegId T1
Definition: int.hh:147
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:571
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:43
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:2302
gem5::guest_abi::VarArgs
Definition: varargs.hh:149
intmath.hh
gem5::System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:121
gem5::getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:2048
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:2446
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:2194
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:2773
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:943
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:448
syscall_desc.hh
gem5::X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:587
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:480
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:2202
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:68

Generated on Sun Jul 30 2023 01:57:00 for gem5 by doxygen 1.8.17