gem5  v21.1.0.2
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-2020 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/trace.hh"
94 #include "base/types.hh"
95 #include "config/the_isa.hh"
96 #include "cpu/base.hh"
97 #include "cpu/thread_context.hh"
98 #include "kern/linux/linux.hh"
99 #include "mem/page_table.hh"
100 #include "params/Process.hh"
101 #include "sim/emul_driver.hh"
102 #include "sim/futex_map.hh"
103 #include "sim/guest_abi.hh"
104 #include "sim/process.hh"
105 #include "sim/proxy_ptr.hh"
107 #include "sim/syscall_desc.hh"
108 #include "sim/syscall_emul_buf.hh"
109 #include "sim/syscall_return.hh"
110 
111 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
112 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
113 #elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
114 #define CMSG_ALIGN(n) _ALIGN(n)
115 #endif
116 
117 namespace gem5
118 {
119 
121 //
122 // The following emulation functions are generic enough that they
123 // don't need to be recompiled for different emulated OS's. They are
124 // defined in sim/syscall_emul.cc.
125 //
127 
128 void warnUnsupportedOS(std::string syscall_name);
129 
131 SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);
132 
137 SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
139 SyscallReturn
140 ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc);
141 
142 // Target fallocateFunc() handler.
143 SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc,
144  int tgt_fd, int mode, off_t offset, off_t len);
145 
147 SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status);
148 
150 SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status);
151 
153 SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc,
154  uint64_t tidPtr);
155 
157 SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc);
158 
160 SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
161 
163 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
164 
166 SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc,
167  int tgt_fd, uint64_t offs, int whence);
168 
170 SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
171  int tgt_fd, uint64_t offset_high,
172  uint32_t offset_low, VPtr<> result_ptr, int whence);
173 
175 SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start,
176  size_t length);
177 
179 SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
180  int tgt_fd, int how);
181 
183 SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc,
184  VPtr<> buf_ptr, int name_len);
185 
187 SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc,
188  VPtr<> buf_ptr, unsigned long size);
189 
191 SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc,
192  VPtr<> pathname, VPtr<> buf, size_t bufsiz);
193 
195 SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
196  VPtr<> pathname);
197 
199 SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc,
200  VPtr<> pathname, VPtr<> new_pathname);
201 
203 SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
204  VPtr<> pathname, VPtr<> new_pathname);
205 
207 SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
208  VPtr<> pathname, mode_t mode);
209 
211 SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc,
212  VPtr<> pathname, mode_t mode, dev_t dev);
213 
215 SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
216 
217 // Target rmdir() handler.
218 SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
219 
221 SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc,
222  VPtr<> oldpath, VPtr<> newpath);
223 
224 
226 SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc,
227  VPtr<> pathname, off_t length);
228 
229 
231 SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc,
232  int tgt_fd, off_t length);
233 
234 
236 SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc,
237  VPtr<> pathname, int64_t length);
238 
240 SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc,
241  int tgt_fd, int64_t length);
242 
244 SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc);
245 
247 SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc);
248 
250 SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc,
251  VPtr<> pathname, uint32_t owner, uint32_t group);
252 
254 SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
255 
257 SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
258  int pid, int pgid);
259 
261 SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc,
262  int tgt_fd, uint32_t owner, uint32_t group);
263 
265 SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc,
266  int tgt_fd);
267 
269 SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc,
270  int old_tgt_fd, int new_tgt_fd);
271 
273 SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
274  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs);
275 
277 SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
278  int tgt_fd, int cmd);
279 
281 SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
282 
284 SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc,
285  VPtr<> tgt_addr, int flags);
286 
288 SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc);
289 
290 // Target getpeername() handler.
291 SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc,
292  int tgt_fd, VPtr<> sockAddrPtr,
293  VPtr<> addrlenPtr);
294 
295 // Target bind() handler.
296 SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc,
297  int tgt_fd, VPtr<> buf_ptr, int addrlen);
298 
299 // Target listen() handler.
300 SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc,
301  int tgt_fd, int backlog);
302 
303 // Target connect() handler.
304 SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc,
305  int tgt_fd, VPtr<> buf_ptr, int addrlen);
306 
307 #if defined(SYS_getdents)
308 // Target getdents() handler.
309 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
310  int tgt_fd, VPtr<> buf_ptr, unsigned count);
311 #endif
312 
313 #if defined(SYS_getdents64)
314 // Target getdents() handler.
315 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
316  int tgt_fd, VPtr<> buf_ptr, unsigned count);
317 #endif
318 
319 // Target sendto() handler.
320 SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc,
321  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
322  VPtr<> addrPtr, socklen_t addrLen);
323 
324 // Target recvfrom() handler.
325 SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc,
326  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen,
327  int flags, VPtr<> addrPtr, VPtr<> addrlenPtr);
328 
329 // Target recvmsg() handler.
330 SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
331  int tgt_fd, VPtr<> msgPtr, int flags);
332 
333 // Target sendmsg() handler.
334 SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
335  int tgt_fd, VPtr<> msgPtr, int flags);
336 
337 // Target getuid() handler.
338 SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc);
339 
341 SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc);
342 
344 SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc);
345 
347 SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
348 
350 SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc);
351 
353 SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc,
354  VPtr<> pathname, mode_t mode);
355 
356 // Target getsockopt() handler.
357 SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
358  int tgt_fd, int level, int optname,
359  VPtr<> valPtr, VPtr<> lenPtr);
360 
361 // Target setsockopt() handler.
362 SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
363  int tgt_fd, int level, int optname,
364  VPtr<> valPtr, socklen_t len);
365 
366 SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
367  VPtr<uint32_t> cpu, VPtr<uint32_t> node,
368  VPtr<uint32_t> tcache);
369 
370 // Target getsockname() handler.
371 SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc,
372  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
373 
377 template <class OS>
378 SyscallReturn
380  VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
381 {
382  auto process = tc->getProcessPtr();
383 
384  /*
385  * Unsupported option that does not affect the correctness of the
386  * application. This is a performance optimization utilized by Linux.
387  */
388  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
389  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
390 
391  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
392 
393  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
394  // Ensure futex system call accessed atomically.
395  BufferArg buf(uaddr, sizeof(int));
396  buf.copyIn(tc->getVirtProxy());
397  int mem_val = *(int*)buf.bufferPtr();
398 
399  /*
400  * The value in memory at uaddr is not equal with the expected val
401  * (a different thread must have changed it before the system call was
402  * invoked). In this case, we need to throw an error.
403  */
404  if (val != mem_val)
405  return -OS::TGT_EWOULDBLOCK;
406 
407  if (OS::TGT_FUTEX_WAIT == op) {
408  futex_map.suspend(uaddr, process->tgid(), tc);
409  } else {
410  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
411  }
412 
413  return 0;
414  } else if (OS::TGT_FUTEX_WAKE == op) {
415  return futex_map.wakeup(uaddr, process->tgid(), val);
416  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
417  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
418  } else if (OS::TGT_FUTEX_REQUEUE == op ||
419  OS::TGT_FUTEX_CMP_REQUEUE == op) {
420 
421  // Ensure futex system call accessed atomically.
422  BufferArg buf(uaddr, sizeof(int));
423  buf.copyIn(tc->getVirtProxy());
424  int mem_val = *(int*)buf.bufferPtr();
425  /*
426  * For CMP_REQUEUE, the whole operation is only started only if
427  * val3 is still the value of the futex pointed to by uaddr.
428  */
429  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
430  return -OS::TGT_EWOULDBLOCK;
431  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
432  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
433  /*
434  * The FUTEX_WAKE_OP operation is equivalent to executing the
435  * following code atomically and totally ordered with respect to
436  * other futex operations on any of the two supplied futex words:
437  *
438  * int oldval = *(int *) addr2;
439  * *(int *) addr2 = oldval op oparg;
440  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
441  * if (oldval cmp cmparg)
442  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
443  *
444  * (op, oparg, cmp, cmparg are encoded in val3)
445  *
446  * +---+---+-----------+-----------+
447  * |op |cmp| oparg | cmparg |
448  * +---+---+-----------+-----------+
449  * 4 4 12 12 <== # of bits
450  *
451  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
452  *
453  */
454  // get value from simulated-space
455  BufferArg buf(uaddr2, sizeof(int));
456  buf.copyIn(tc->getVirtProxy());
457  int oldval = *(int*)buf.bufferPtr();
458  int newval = oldval;
459  // extract op, oparg, cmp, cmparg from val3
460  int wake_cmparg = val3 & 0xfff;
461  int wake_oparg = (val3 & 0xfff000) >> 12;
462  int wake_cmp = (val3 & 0xf000000) >> 24;
463  int wake_op = (val3 & 0xf0000000) >> 28;
464  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
465  wake_oparg = (1 << wake_oparg);
466  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
467  // perform operation on the value of the second futex
468  if (wake_op == OS::TGT_FUTEX_OP_SET)
469  newval = wake_oparg;
470  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
471  newval += wake_oparg;
472  else if (wake_op == OS::TGT_FUTEX_OP_OR)
473  newval |= wake_oparg;
474  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
475  newval &= ~wake_oparg;
476  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
477  newval ^= wake_oparg;
478  // copy updated value back to simulated-space
479  *(int*)buf.bufferPtr() = newval;
480  buf.copyOut(tc->getVirtProxy());
481  // perform the first wake-up
482  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
483  int woken2 = 0;
484  // calculate the condition of the second wake-up
485  bool is_wake2 = false;
486  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
487  is_wake2 = oldval == wake_cmparg;
488  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
489  is_wake2 = oldval != wake_cmparg;
490  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
491  is_wake2 = oldval < wake_cmparg;
492  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
493  is_wake2 = oldval <= wake_cmparg;
494  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
495  is_wake2 = oldval > wake_cmparg;
496  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
497  is_wake2 = oldval >= wake_cmparg;
498  // perform the second wake-up
499  if (is_wake2)
500  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
501 
502  return woken1 + woken2;
503  }
504  warn("futex: op %d not implemented; ignoring.", op);
505  return -ENOSYS;
506 }
507 
510 SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
511 
512 
516 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
517 
520 template <class T1, class T2>
521 void
522 getElapsedTimeMicro(T1 &sec, T2 &usec)
523 {
524  static const int OneMillion = 1000 * 1000;
525 
526  uint64_t elapsed_usecs = curTick() / sim_clock::as_int::us;
527  sec = elapsed_usecs / OneMillion;
528  usec = elapsed_usecs % OneMillion;
529 }
530 
533 template <class T1, class T2>
534 void
535 getElapsedTimeNano(T1 &sec, T2 &nsec)
536 {
537  static const int OneBillion = 1000 * 1000 * 1000;
538 
539  uint64_t elapsed_nsecs = curTick() / sim_clock::as_int::ns;
540  sec = elapsed_nsecs / OneBillion;
541  nsec = elapsed_nsecs % OneBillion;
542 }
543 
545 //
546 // The following emulation functions are generic, but need to be
547 // templated to account for differences in types, constants, etc.
548 //
550 
551  typedef struct statfs hst_statfs;
552 #if NO_STAT64
553  typedef struct stat hst_stat;
554  typedef struct stat hst_stat64;
555 #else
556  typedef struct stat hst_stat;
557  typedef struct stat64 hst_stat64;
558 #endif
559 
563 
564 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
565 void
566 copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
567 {
568  constexpr ByteOrder bo = OS::byteOrder;
569 
570  if (fakeTTY)
571  tgt->st_dev = 0xA;
572  else
573  tgt->st_dev = host->st_dev;
574  tgt->st_dev = htog(tgt->st_dev, bo);
575  tgt->st_ino = host->st_ino;
576  tgt->st_ino = htog(tgt->st_ino, bo);
577  tgt->st_mode = host->st_mode;
578  if (fakeTTY) {
579  // Claim to be a character device
580  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
581  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
582  }
583  tgt->st_mode = htog(tgt->st_mode, bo);
584  tgt->st_nlink = host->st_nlink;
585  tgt->st_nlink = htog(tgt->st_nlink, bo);
586  tgt->st_uid = host->st_uid;
587  tgt->st_uid = htog(tgt->st_uid, bo);
588  tgt->st_gid = host->st_gid;
589  tgt->st_gid = htog(tgt->st_gid, bo);
590  if (fakeTTY)
591  tgt->st_rdev = 0x880d;
592  else
593  tgt->st_rdev = host->st_rdev;
594  tgt->st_rdev = htog(tgt->st_rdev, bo);
595  tgt->st_size = host->st_size;
596  tgt->st_size = htog(tgt->st_size, bo);
597  tgt->st_atimeX = host->st_atime;
598  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
599  tgt->st_mtimeX = host->st_mtime;
600  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
601  tgt->st_ctimeX = host->st_ctime;
602  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
603  // Force the block size to be 8KB. This helps to ensure buffered io works
604  // consistently across different hosts.
605  tgt->st_blksize = 0x2000;
606  tgt->st_blksize = htog(tgt->st_blksize, bo);
607  tgt->st_blocks = host->st_blocks;
608  tgt->st_blocks = htog(tgt->st_blocks, bo);
609 }
610 
611 // Same for stat64
612 
613 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
614 void
615 copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host,
616  bool fakeTTY=false)
617 {
618  copyOutStatBuf<OS>(tgt, host, fakeTTY);
619 #if defined(STAT_HAVE_NSEC)
620  constexpr ByteOrder bo = OS::byteOrder;
621 
622  tgt->st_atime_nsec = host->st_atime_nsec;
623  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
624  tgt->st_mtime_nsec = host->st_mtime_nsec;
625  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
626  tgt->st_ctime_nsec = host->st_ctime_nsec;
627  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
628 #else
629  tgt->st_atime_nsec = 0;
630  tgt->st_mtime_nsec = 0;
631  tgt->st_ctime_nsec = 0;
632 #endif
633 }
634 
635 template <class OS, typename TgtStatPtr, typename HostStatPtr>
636 void
637 copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
638 {
639  constexpr ByteOrder bo = OS::byteOrder;
640 
641  tgt->f_type = htog(host->f_type, bo);
642 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
643  tgt->f_bsize = htog(host->f_iosize, bo);
644 #else
645  tgt->f_bsize = htog(host->f_bsize, bo);
646 #endif
647  tgt->f_blocks = htog(host->f_blocks, bo);
648  tgt->f_bfree = htog(host->f_bfree, bo);
649  tgt->f_bavail = htog(host->f_bavail, bo);
650  tgt->f_files = htog(host->f_files, bo);
651  tgt->f_ffree = htog(host->f_ffree, bo);
652  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
653 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
654  tgt->f_namelen = htog(host->f_namemax, bo);
655  tgt->f_frsize = htog(host->f_bsize, bo);
656 #elif defined(__APPLE__)
657  tgt->f_namelen = 0;
658  tgt->f_frsize = 0;
659 #else
660  tgt->f_namelen = htog(host->f_namelen, bo);
661  tgt->f_frsize = htog(host->f_frsize, bo);
662 #endif
663 #if defined(__linux__)
664  memcpy(&tgt->f_spare, &host->f_spare,
665  std::min(sizeof(host->f_spare), sizeof(tgt->f_spare)));
666 #else
667  /*
668  * The fields are different sizes per OS. Don't bother with
669  * f_spare or f_reserved on non-Linux for now.
670  */
671  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
672 #endif
673 }
674 
679 template <class OS>
680 SyscallReturn
682  int tgt_fd, unsigned req, VPtr<> addr)
683 {
684  auto p = tc->getProcessPtr();
685 
686  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
687 
688  if (OS::isTtyReq(req))
689  return -ENOTTY;
690 
691  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
692  if (dfdp) {
693  EmulatedDriver *emul_driver = dfdp->getDriver();
694  if (emul_driver)
695  return emul_driver->ioctl(tc, req, addr);
696  }
697 
698  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
699  if (sfdp) {
700  int status;
701 
702  switch (req) {
703  case SIOCGIFCONF: {
704  BufferArg conf_arg(addr, sizeof(ifconf));
705  conf_arg.copyIn(tc->getVirtProxy());
706 
707  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
708  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
709  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
710  ifc_buf_arg.copyIn(tc->getVirtProxy());
711 
712  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
713 
714  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
715  if (status != -1) {
716  conf->ifc_buf = (char*)ifc_buf_addr;
717  ifc_buf_arg.copyOut(tc->getVirtProxy());
718  conf_arg.copyOut(tc->getVirtProxy());
719  }
720 
721  return status;
722  }
723  case SIOCGIFFLAGS:
724 #if defined(__linux__)
725  case SIOCGIFINDEX:
726 #endif
727  case SIOCGIFNETMASK:
728  case SIOCGIFADDR:
729 #if defined(__linux__)
730  case SIOCGIFHWADDR:
731 #endif
732  case SIOCGIFMTU: {
733  BufferArg req_arg(addr, sizeof(ifreq));
734  req_arg.copyIn(tc->getVirtProxy());
735 
736  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
737  if (status != -1)
738  req_arg.copyOut(tc->getVirtProxy());
739  return status;
740  }
741  }
742  }
743 
748  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
749  tgt_fd, req, tc->pcState());
750  return -ENOTTY;
751 }
752 
754 template <class OS>
755 SyscallReturn
757  int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
758 {
759  auto p = tc->getProcessPtr();
760 
765  std::string path;
766  if (!tc->getVirtProxy().tryReadString(path, pathname))
767  return -EFAULT;
768 
769 #ifdef __CYGWIN32__
770  int host_flags = O_BINARY;
771 #else
772  int host_flags = 0;
773 #endif
774 
778  for (const auto &p: OS::openFlagTable) {
779  if (tgt_flags & p.first) {
780  tgt_flags &= ~p.first;
781  host_flags |= p.second;
782  }
783  }
784  warn_if(tgt_flags, "%s: cannot decode flags %#x", desc->name(), tgt_flags);
785 
786 #ifdef __CYGWIN32__
787  host_flags |= O_BINARY;
788 #endif
789 
802  std::string redir_path = path;
803  std::string abs_path = path;
804  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
805  abs_path = p->absolutePath(path, true);
806  redir_path = p->checkPathRedirect(path);
807  } else if (!startswith(path, "/")) {
808  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
809  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
810  if (!ffdp)
811  return -EBADF;
812  abs_path = ffdp->getFileName() + path;
813  redir_path = p->checkPathRedirect(abs_path);
814  }
815 
822  if (startswith(abs_path, "/dev/")) {
823  std::string filename = abs_path.substr(strlen("/dev/"));
824  EmulatedDriver *drv = p->findDriver(filename);
825  if (drv) {
826  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
827  "driver open with path[%s]\n",
828  desc->name(), abs_path.c_str());
829  return drv->open(tc, mode, host_flags);
830  }
835  }
836 
861  int sim_fd = -1;
862  std::string used_path;
863  std::vector<std::string> special_paths =
864  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
865  "/proc/self/maps", "/dev/urandom",
866  "/sys/devices/system/cpu/online" };
867  for (auto entry : special_paths) {
868  if (startswith(path, entry)) {
869  sim_fd = OS::openSpecialFile(abs_path, p, tc);
870  used_path = abs_path;
871  }
872  }
873  if (sim_fd == -1) {
874  sim_fd = open(redir_path.c_str(), host_flags, mode);
875  used_path = redir_path;
876  }
877  if (sim_fd == -1) {
878  int local = -errno;
879  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
880  "(inferred from:%s)\n", desc->name(),
881  used_path.c_str(), path.c_str());
882  return local;
883  }
884 
893  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
894  // Record the file mode for checkpoint restoring
895  ffdp->setFileMode(mode);
896  int tgt_fd = p->fds->allocFD(ffdp);
897  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
898  "(inferred from:%s)\n", desc->name(),
899  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
900  return tgt_fd;
901 }
902 
904 template <class OS>
905 SyscallReturn
907  VPtr<> pathname, int tgt_flags, int mode)
908 {
909  return openatFunc<OS>(
910  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
911 }
912 
914 template <class OS>
915 SyscallReturn
916 unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname)
917 {
918  if (dirfd != OS::TGT_AT_FDCWD)
919  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
920 
921  return unlinkFunc(desc, tc, pathname);
922 }
923 
925 template <class OS>
926 SyscallReturn
928  int dirfd, VPtr<> pathname, int mode)
929 {
930  if (dirfd != OS::TGT_AT_FDCWD)
931  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
932  return accessFunc(desc, tc, pathname, mode);
933 }
934 
936 template <class OS>
937 SyscallReturn
939  int dirfd, VPtr<> pathname, VPtr<> buf, size_t bufsiz)
940 {
941  if (dirfd != OS::TGT_AT_FDCWD)
942  warn("openat: first argument not AT_FDCWD; unlikely to work");
943  return readlinkFunc(desc, tc, pathname, buf, bufsiz);
944 }
945 
947 template <class OS>
948 SyscallReturn
950  int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
951 {
952  if (olddirfd != OS::TGT_AT_FDCWD)
953  warn("renameat: first argument not AT_FDCWD; unlikely to work");
954 
955  if (newdirfd != OS::TGT_AT_FDCWD)
956  warn("renameat: third argument not AT_FDCWD; unlikely to work");
957 
958  return renameFunc(desc, tc, oldpath, newpath);
959 }
960 
962 template <class OS>
963 SyscallReturn
966 {
967  auto process = tc->getProcessPtr();
968 
969  sysinfo->uptime = seconds_since_epoch;
970  sysinfo->totalram = process->system->memSize();
971  sysinfo->mem_unit = 1;
972 
973  return 0;
974 }
975 
977 template <class OS>
978 SyscallReturn
979 chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
980 {
981  std::string path;
982  auto process = tc->getProcessPtr();
983 
984  if (!tc->getVirtProxy().tryReadString(path, pathname))
985  return -EFAULT;
986 
987  mode_t hostMode = 0;
988 
989  // XXX translate mode flags via OS::something???
990  hostMode = mode;
991 
992  // Adjust path for cwd and redirection
993  path = process->checkPathRedirect(path);
994 
995  // do the chmod
996  int result = chmod(path.c_str(), hostMode);
997  if (result < 0)
998  return -errno;
999 
1000  return 0;
1001 }
1002 
1003 template <class OS>
1004 SyscallReturn
1006  VPtr<> fdsPtr, int nfds, int tmout)
1007 {
1008  auto p = tc->getProcessPtr();
1009 
1010  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1011  fdsBuf.copyIn(tc->getVirtProxy());
1012 
1019  int temp_tgt_fds[nfds];
1020  for (int index = 0; index < nfds; index++) {
1021  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1022  auto tgt_fd = temp_tgt_fds[index];
1023  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1024  if (!hbfdp)
1025  return -EBADF;
1026  auto host_fd = hbfdp->getSimFD();
1027  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1028  }
1029 
1036  int status;
1037  if (tmout < 0) {
1038  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1039  if (status == 0) {
1045  System *sysh = tc->getSystemPtr();
1047  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1048  if (it->receiver == p)
1049  return -EINTR;
1050  return SyscallReturn::retry();
1051  }
1052  } else
1053  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1054 
1055  if (status == -1)
1056  return -errno;
1057 
1062  for (int index = 0; index < nfds; index++) {
1063  auto tgt_fd = temp_tgt_fds[index];
1064  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1065  }
1066 
1071  fdsBuf.copyOut(tc->getVirtProxy());
1072 
1073  return status;
1074 }
1075 
1077 template <class OS>
1078 SyscallReturn
1079 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1080 {
1081  auto p = tc->getProcessPtr();
1082 
1083  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1084  if (!ffdp)
1085  return -EBADF;
1086  int sim_fd = ffdp->getSimFD();
1087 
1088  mode_t hostMode = mode;
1089 
1090  int result = fchmod(sim_fd, hostMode);
1091 
1092  return (result < 0) ? -errno : 0;
1093 }
1094 
1096 template <class OS>
1097 SyscallReturn
1099  VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1101 {
1102  auto p = tc->getProcessPtr();
1103  Addr page_bytes = p->pTable->pageSize();
1104  uint64_t provided_address = 0;
1105  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1106 
1107  if (use_provided_address)
1108  provided_address = varargs.get<uint64_t>();
1109 
1110  if ((start % page_bytes != 0) ||
1111  (provided_address % page_bytes != 0)) {
1112  warn("mremap failing: arguments not page aligned");
1113  return -EINVAL;
1114  }
1115 
1116  new_length = roundUp(new_length, page_bytes);
1117 
1118  if (new_length > old_length) {
1119  Addr mmap_end = p->memState->getMmapEnd();
1120 
1121  if ((start + old_length) == mmap_end &&
1122  (!use_provided_address || provided_address == start)) {
1123  // This case cannot occur when growing downward, as
1124  // start is greater than or equal to mmap_end.
1125  uint64_t diff = new_length - old_length;
1126  p->memState->mapRegion(mmap_end, diff, "remapped");
1127  p->memState->setMmapEnd(mmap_end + diff);
1128  return (Addr)start;
1129  } else {
1130  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1131  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1132  return -ENOMEM;
1133  } else {
1134  uint64_t new_start = provided_address;
1135  if (!use_provided_address) {
1136  new_start = p->mmapGrowsDown() ?
1137  mmap_end - new_length : mmap_end;
1138  mmap_end = p->mmapGrowsDown() ?
1139  new_start : mmap_end + new_length;
1140  p->memState->setMmapEnd(mmap_end);
1141  }
1142 
1143  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1144  new_start, new_start + new_length,
1145  new_length - old_length);
1146 
1147  // add on the remaining unallocated pages
1148  p->allocateMem(new_start + old_length,
1149  new_length - old_length,
1150  use_provided_address /* clobber */);
1151 
1152  if (use_provided_address &&
1153  ((new_start + new_length > p->memState->getMmapEnd() &&
1154  !p->mmapGrowsDown()) ||
1155  (new_start < p->memState->getMmapEnd() &&
1156  p->mmapGrowsDown()))) {
1157  // something fishy going on here, at least notify the user
1158  // @todo: increase mmap_end?
1159  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1160  }
1161 
1162  warn("returning %08p as start\n", new_start);
1163  p->memState->remapRegion(start, new_start, old_length);
1164  return new_start;
1165  }
1166  }
1167  } else {
1168  // Shrink a region
1169  if (use_provided_address && provided_address != start)
1170  p->memState->remapRegion(start, provided_address, new_length);
1171  if (new_length != old_length)
1172  p->memState->unmapRegion(start + new_length,
1173  old_length - new_length);
1174  return use_provided_address ? provided_address : (Addr)start;
1175  }
1176 }
1177 
1179 template <class OS>
1180 SyscallReturn
1182  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1183 {
1184  std::string path;
1185  auto process = tc->getProcessPtr();
1186 
1187  if (!tc->getVirtProxy().tryReadString(path, pathname))
1188  return -EFAULT;
1189 
1190  // Adjust path for cwd and redirection
1191  path = process->checkPathRedirect(path);
1192 
1193  struct stat hostBuf;
1194  int result = stat(path.c_str(), &hostBuf);
1195 
1196  if (result < 0)
1197  return -errno;
1198 
1199  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1200 
1201  return 0;
1202 }
1203 
1204 
1206 template <class OS>
1207 SyscallReturn
1209  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1210 {
1211  std::string path;
1212  auto process = tc->getProcessPtr();
1213 
1214  if (!tc->getVirtProxy().tryReadString(path, pathname))
1215  return -EFAULT;
1216 
1217  // Adjust path for cwd and redirection
1218  path = process->checkPathRedirect(path);
1219 
1220 #if NO_STAT64
1221  struct stat hostBuf;
1222  int result = stat(path.c_str(), &hostBuf);
1223 #else
1224  struct stat64 hostBuf;
1225  int result = stat64(path.c_str(), &hostBuf);
1226 #endif
1227 
1228  if (result < 0)
1229  return -errno;
1230 
1231  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1232 
1233  return 0;
1234 }
1235 
1236 
1238 template <class OS>
1239 SyscallReturn
1241  int dirfd, VPtr<> pathname,
1243 {
1244  auto process = tc->getProcessPtr();
1245  if (dirfd != OS::TGT_AT_FDCWD)
1246  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1247 
1248  std::string path;
1249  if (!tc->getVirtProxy().tryReadString(path, pathname))
1250  return -EFAULT;
1251 
1252  // Adjust path for cwd and redirection
1253  path = process->checkPathRedirect(path);
1254 
1255 #if NO_STAT64
1256  struct stat hostBuf;
1257  int result = stat(path.c_str(), &hostBuf);
1258 #else
1259  struct stat64 hostBuf;
1260  int result = stat64(path.c_str(), &hostBuf);
1261 #endif
1262 
1263  if (result < 0)
1264  return -errno;
1265 
1266  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1267 
1268  return 0;
1269 }
1270 
1271 
1273 template <class OS>
1274 SyscallReturn
1276  int tgt_fd, VPtr<typename OS::tgt_stat64> tgt_stat)
1277 {
1278  auto p = tc->getProcessPtr();
1279 
1280  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1281  if (!ffdp)
1282  return -EBADF;
1283  int sim_fd = ffdp->getSimFD();
1284 
1285 #if NO_STAT64
1286  struct stat hostBuf;
1287  int result = fstat(sim_fd, &hostBuf);
1288 #else
1289  struct stat64 hostBuf;
1290  int result = fstat64(sim_fd, &hostBuf);
1291 #endif
1292 
1293  if (result < 0)
1294  return -errno;
1295 
1296  copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1297 
1298  return 0;
1299 }
1300 
1301 
1303 template <class OS>
1304 SyscallReturn
1306  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1307 {
1308  std::string path;
1309  auto process = tc->getProcessPtr();
1310 
1311  if (!tc->getVirtProxy().tryReadString(path, pathname))
1312  return -EFAULT;
1313 
1314  // Adjust path for cwd and redirection
1315  path = process->checkPathRedirect(path);
1316 
1317  struct stat hostBuf;
1318  int result = lstat(path.c_str(), &hostBuf);
1319 
1320  if (result < 0)
1321  return -errno;
1322 
1323  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1324 
1325  return 0;
1326 }
1327 
1329 template <class OS>
1330 SyscallReturn
1332  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1333 {
1334  std::string path;
1335  auto process = tc->getProcessPtr();
1336 
1337  if (!tc->getVirtProxy().tryReadString(path, pathname))
1338  return -EFAULT;
1339 
1340  // Adjust path for cwd and redirection
1341  path = process->checkPathRedirect(path);
1342 
1343 #if NO_STAT64
1344  struct stat hostBuf;
1345  int result = lstat(path.c_str(), &hostBuf);
1346 #else
1347  struct stat64 hostBuf;
1348  int result = lstat64(path.c_str(), &hostBuf);
1349 #endif
1350 
1351  if (result < 0)
1352  return -errno;
1353 
1354  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1355 
1356  return 0;
1357 }
1358 
1360 template <class OS>
1361 SyscallReturn
1363  int tgt_fd, VPtr<typename OS::tgt_stat> tgt_stat)
1364 {
1365  auto p = tc->getProcessPtr();
1366 
1367  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1368 
1369  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1370  if (!ffdp)
1371  return -EBADF;
1372  int sim_fd = ffdp->getSimFD();
1373 
1374  struct stat hostBuf;
1375  int result = fstat(sim_fd, &hostBuf);
1376 
1377  if (result < 0)
1378  return -errno;
1379 
1380  copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1381 
1382  return 0;
1383 }
1384 
1386 template <class OS>
1387 SyscallReturn
1389  VPtr<> pathname, VPtr<typename OS::tgt_statfs> tgt_stat)
1390 {
1391 #if defined(__linux__)
1392  std::string path;
1393  auto process = tc->getProcessPtr();
1394 
1395  if (!tc->getVirtProxy().tryReadString(path, pathname))
1396  return -EFAULT;
1397 
1398  // Adjust path for cwd and redirection
1399  path = process->checkPathRedirect(path);
1400 
1401  struct statfs hostBuf;
1402  int result = statfs(path.c_str(), &hostBuf);
1403 
1404  if (result < 0)
1405  return -errno;
1406 
1407  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1408  return 0;
1409 #else
1410  warnUnsupportedOS("statfs");
1411  return -1;
1412 #endif
1413 }
1414 
1415 template <class OS>
1416 SyscallReturn
1417 cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
1418  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1419 {
1420  auto p = tc->getProcessPtr();
1421 
1422  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1423  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1424  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1425  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1426  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1427  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1428  return -EINVAL;
1429 
1430  ThreadContext *ctc;
1431  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1432  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1433  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1434  return -EAGAIN;
1435  }
1436 
1443  ProcessParams *pp = new ProcessParams();
1444  pp->executable.assign(*(new std::string(p->progName())));
1445  pp->cmd.push_back(*(new std::string(p->progName())));
1446  pp->system = p->system;
1447  pp->cwd.assign(p->tgtCwd);
1448  pp->input.assign("stdin");
1449  pp->output.assign("stdout");
1450  pp->errout.assign("stderr");
1451  pp->uid = p->uid();
1452  pp->euid = p->euid();
1453  pp->gid = p->gid();
1454  pp->egid = p->egid();
1455  pp->release = p->release;
1456 
1457  /* Find the first free PID that's less than the maximum */
1458  std::set<int> const& pids = p->system->PIDs;
1459  int temp_pid = *pids.begin();
1460  do {
1461  temp_pid++;
1462  } while (pids.find(temp_pid) != pids.end());
1463  if (temp_pid >= System::maxPID)
1464  fatal("temp_pid is too large: %d", temp_pid);
1465 
1466  pp->pid = temp_pid;
1467  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1468  pp->useArchPT = p->useArchPT;
1469  pp->kvmInSE = p->kvmInSE;
1470  Process *cp = pp->create();
1471  // TODO: there is no way to know when the Process SimObject is done with
1472  // the params pointer. Both the params pointer (pp) and the process
1473  // pointer (cp) are normally managed in python and are never cleaned up.
1474 
1475  Process *owner = ctc->getProcessPtr();
1476  ctc->setProcessPtr(cp);
1477  cp->assignThreadContext(ctc->contextId());
1478  owner->revokeThreadContext(ctc->contextId());
1479 
1480  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1481  BufferArg ptidBuf(ptidPtr, sizeof(long));
1482  long *ptid = (long *)ptidBuf.bufferPtr();
1483  *ptid = cp->pid();
1484  ptidBuf.copyOut(tc->getVirtProxy());
1485  }
1486 
1487  if (flags & OS::TGT_CLONE_THREAD) {
1488  cp->pTable->shared = true;
1489  cp->useForClone = true;
1490  }
1491 
1492  ctc->setUseForClone(true);
1493  cp->initState();
1494  p->clone(tc, ctc, cp, flags);
1495 
1496  if (flags & OS::TGT_CLONE_THREAD) {
1497  delete cp->sigchld;
1498  cp->sigchld = p->sigchld;
1499  } else if (flags & OS::TGT_SIGCHLD) {
1500  *cp->sigchld = true;
1501  }
1502 
1503  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1504  BufferArg ctidBuf(ctidPtr, sizeof(long));
1505  long *ctid = (long *)ctidBuf.bufferPtr();
1506  *ctid = cp->pid();
1507  ctidBuf.copyOut(ctc->getVirtProxy());
1508  }
1509 
1510  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1511  cp->childClearTID = (uint64_t)ctidPtr;
1512 
1513  ctc->clearArchRegs();
1514 
1515  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1516 
1517  desc->returnInto(ctc, 0);
1518 
1519  TheISA::PCState cpc = tc->pcState();
1520  cpc.advance();
1521  ctc->pcState(cpc);
1522  ctc->activate();
1523 
1524  if (flags & OS::TGT_CLONE_VFORK) {
1525  tc->suspend();
1526  }
1527 
1528  return cp->pid();
1529 }
1530 
1531 template <class OS>
1532 SyscallReturn
1534  RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1535  VPtr<> ctidPtr)
1536 {
1537  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1538 }
1539 
1541 template <class OS>
1542 SyscallReturn
1544  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1545 {
1546  auto p = tc->getProcessPtr();
1547 
1548  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1549  if (!ffdp)
1550  return -EBADF;
1551  int sim_fd = ffdp->getSimFD();
1552 
1553  struct statfs hostBuf;
1554  int result = fstatfs(sim_fd, &hostBuf);
1555 
1556  if (result < 0)
1557  return -errno;
1558 
1559  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1560 
1561  return 0;
1562 }
1563 
1565 template <class OS>
1566 SyscallReturn
1568  int tgt_fd, uint64_t tiov_base, size_t count)
1569 {
1570  auto p = tc->getProcessPtr();
1571 
1572  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1573  if (!ffdp)
1574  return -EBADF;
1575  int sim_fd = ffdp->getSimFD();
1576 
1577  PortProxy &prox = tc->getVirtProxy();
1578  typename OS::tgt_iovec tiov[count];
1579  struct iovec hiov[count];
1580  for (size_t i = 0; i < count; ++i) {
1581  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1582  &tiov[i], sizeof(typename OS::tgt_iovec));
1583  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1584  hiov[i].iov_base = new char [hiov[i].iov_len];
1585  }
1586 
1587  int result = readv(sim_fd, hiov, count);
1588  int local_errno = errno;
1589 
1590  for (size_t i = 0; i < count; ++i) {
1591  if (result != -1) {
1592  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1593  hiov[i].iov_base, hiov[i].iov_len);
1594  }
1595  delete [] (char *)hiov[i].iov_base;
1596  }
1597 
1598  return (result == -1) ? -local_errno : result;
1599 }
1600 
1602 template <class OS>
1603 SyscallReturn
1605  int tgt_fd, uint64_t tiov_base, size_t count)
1606 {
1607  auto p = tc->getProcessPtr();
1608 
1609  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1610  if (!hbfdp)
1611  return -EBADF;
1612  int sim_fd = hbfdp->getSimFD();
1613 
1614  PortProxy &prox = tc->getVirtProxy();
1615  struct iovec hiov[count];
1616  for (size_t i = 0; i < count; ++i) {
1617  typename OS::tgt_iovec tiov;
1618 
1619  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1620  &tiov, sizeof(typename OS::tgt_iovec));
1621  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1622  hiov[i].iov_base = new char [hiov[i].iov_len];
1623  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1624  hiov[i].iov_len);
1625  }
1626 
1627  int result = writev(sim_fd, hiov, count);
1628 
1629  for (size_t i = 0; i < count; ++i)
1630  delete [] (char *)hiov[i].iov_base;
1631 
1632  return (result == -1) ? -errno : result;
1633 }
1634 
1636 template <class OS>
1637 SyscallReturn
1639  VPtr<> start, typename OS::size_t length, int prot,
1640  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1641 {
1642  auto p = tc->getProcessPtr();
1643  Addr page_bytes = p->pTable->pageSize();
1644 
1645  if (start & (page_bytes - 1) ||
1646  offset & (page_bytes - 1) ||
1647  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1648  tgt_flags & OS::TGT_MAP_SHARED) ||
1649  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1650  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1651  !length) {
1652  return -EINVAL;
1653  }
1654 
1655  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1656  // With shared mmaps, there are two cases to consider:
1657  // 1) anonymous: writes should modify the mapping and this should be
1658  // visible to observers who share the mapping. Currently, it's
1659  // difficult to update the shared mapping because there's no
1660  // structure which maintains information about the which virtual
1661  // memory areas are shared. If that structure existed, it would be
1662  // possible to make the translations point to the same frames.
1663  // 2) file-backed: writes should modify the mapping and the file
1664  // which is backed by the mapping. The shared mapping problem is the
1665  // same as what was mentioned about the anonymous mappings. For
1666  // file-backed mappings, the writes to the file are difficult
1667  // because it requires syncing what the mapping holds with the file
1668  // that resides on the host system. So, any write on a real system
1669  // would cause the change to be propagated to the file mapping at
1670  // some point in the future (the inode is tracked along with the
1671  // mapping). This isn't guaranteed to always happen, but it usually
1672  // works well enough. The guarantee is provided by the msync system
1673  // call. We could force the change through with shared mappings with
1674  // a call to msync, but that again would require more information
1675  // than we currently maintain.
1676  warn_once("mmap: writing to shared mmap region is currently "
1677  "unsupported. The write succeeds on the target, but it "
1678  "will not be propagated to the host or shared mappings");
1679  }
1680 
1681  length = roundUp(length, page_bytes);
1682 
1683  int sim_fd = -1;
1684  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1685  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1686 
1687  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1688  if (dfdp) {
1689  EmulatedDriver *emul_driver = dfdp->getDriver();
1690  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1691  tgt_fd, offset);
1692  }
1693 
1694  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1695  if (!ffdp)
1696  return -EBADF;
1697  sim_fd = ffdp->getSimFD();
1698 
1707  if (p->interpImage.contains(tc->pcState().instAddr())) {
1708  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1709  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1710  auto *lib = loader::createObjectFile(p->checkPathRedirect(
1711  ffdp->getFileName()));
1712  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1713  ffdp->getFileName());
1714 
1715  if (lib) {
1716  Addr offset = lib->buildImage().minAddr() + start;
1717  loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1718  }
1719  }
1720  }
1721 
1725  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1733  if (!(start && p->memState->isUnmapped(start, length))) {
1737  start = p->memState->extendMmap(length);
1738  }
1739  }
1740 
1741  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1742  start, start + length - 1);
1743 
1749  if (tgt_flags & OS::TGT_MAP_FIXED) {
1754  p->memState->unmapRegion(start, length);
1755  }
1756 
1760  std::string region_name;
1761  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1762  region_name = "anon";
1763  } else {
1764  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1765  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1766  region_name = ffdp->getFileName();
1767  }
1768 
1773  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1774 
1775  return (Addr)start;
1776 }
1777 
1778 template <class OS>
1779 SyscallReturn
1781  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
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  BufferArg bufArg(bufPtr, nbytes);
1791 
1792  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1793 
1794  bufArg.copyOut(tc->getVirtProxy());
1795 
1796  return (bytes_read == -1) ? -errno : bytes_read;
1797 }
1798 
1799 template <class OS>
1800 SyscallReturn
1802  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1803 {
1804  auto p = tc->getProcessPtr();
1805 
1806  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1807  if (!ffdp)
1808  return -EBADF;
1809  int sim_fd = ffdp->getSimFD();
1810 
1811  BufferArg bufArg(bufPtr, nbytes);
1812  bufArg.copyIn(tc->getVirtProxy());
1813 
1814  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1815 
1816  return (bytes_written == -1) ? -errno : bytes_written;
1817 }
1818 
1820 template <class OS>
1821 SyscallReturn
1823  VPtr<> start, typename OS::size_t length, int prot,
1824  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1825 {
1826  auto page_size = tc->getProcessPtr()->pTable->pageSize();
1827  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
1828  tgt_fd, offset * page_size);
1829 }
1830 
1832 template <class OS>
1833 SyscallReturn
1835  unsigned resource, VPtr<typename OS::rlimit> rlp)
1836 {
1837  const ByteOrder bo = OS::byteOrder;
1838  switch (resource) {
1839  case OS::TGT_RLIMIT_STACK:
1840  // max stack size in bytes: make up a number (8MiB for now)
1841  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1842  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1843  rlp->rlim_max = htog(rlp->rlim_max, bo);
1844  break;
1845 
1846  case OS::TGT_RLIMIT_DATA:
1847  // max data segment size in bytes: make up a number
1848  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1849  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1850  rlp->rlim_max = htog(rlp->rlim_max, bo);
1851  break;
1852 
1853  case OS::TGT_RLIMIT_NPROC:
1854  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
1855  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1856  rlp->rlim_max = htog(rlp->rlim_max, bo);
1857  break;
1858 
1859  default:
1860  warn("getrlimit: unimplemented resource %d", resource);
1861  return -EINVAL;
1862  break;
1863  }
1864 
1865  return 0;
1866 }
1867 
1868 template <class OS>
1869 SyscallReturn
1871  int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
1872 {
1873  if (pid != 0) {
1874  warn("prlimit: ignoring rlimits for nonzero pid");
1875  return -EPERM;
1876  }
1877  if (n)
1878  warn("prlimit: ignoring new rlimit");
1879  if (rlp) {
1880  const ByteOrder bo = OS::byteOrder;
1881  switch (resource) {
1882  case OS::TGT_RLIMIT_STACK:
1883  // max stack size in bytes: make up a number (8MiB for now)
1884  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1885  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1886  rlp->rlim_max = htog(rlp->rlim_max, bo);
1887  break;
1888  case OS::TGT_RLIMIT_DATA:
1889  // max data segment size in bytes: make up a number
1890  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1891  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1892  rlp->rlim_max = htog(rlp->rlim_max, bo);
1893  break;
1894  default:
1895  warn("prlimit: unimplemented resource %d", resource);
1896  return -EINVAL;
1897  break;
1898  }
1899  }
1900  return 0;
1901 }
1902 
1904 template <class OS>
1905 SyscallReturn
1907  int clk_id, VPtr<typename OS::timespec> tp)
1908 {
1909  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1910  tp->tv_sec += seconds_since_epoch;
1911  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1912  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
1913 
1914  return 0;
1915 }
1916 
1918 template <class OS>
1919 SyscallReturn
1922 {
1923  // Set resolution at ns, which is what clock_gettime() returns
1924  tp->tv_sec = 0;
1925  tp->tv_nsec = 1;
1926 
1927  return 0;
1928 }
1929 
1931 template <class OS>
1932 SyscallReturn
1935 {
1936  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1937  tp->tv_sec += seconds_since_epoch;
1938  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1939  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
1940 
1941  return 0;
1942 }
1943 
1944 
1946 template <class OS>
1947 SyscallReturn
1949  VPtr<typename OS::timeval [2]> tp)
1950 {
1951  std::string path;
1952  auto process = tc->getProcessPtr();
1953 
1954  if (!tc->getVirtProxy().tryReadString(path, pathname))
1955  return -EFAULT;
1956 
1957  struct timeval hostTimeval[2];
1958  for (int i = 0; i < 2; ++i) {
1959  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
1960  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
1961  }
1962 
1963  // Adjust path for cwd and redirection
1964  path = process->checkPathRedirect(path);
1965 
1966  int result = utimes(path.c_str(), hostTimeval);
1967 
1968  if (result < 0)
1969  return -errno;
1970 
1971  return 0;
1972 }
1973 
1974 template <class OS>
1975 SyscallReturn
1977  VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
1978 {
1979  auto p = tc->getProcessPtr();
1980 
1981  std::string path;
1982  PortProxy & mem_proxy = tc->getVirtProxy();
1983  if (!mem_proxy.tryReadString(path, pathname))
1984  return -EFAULT;
1985 
1986  if (access(path.c_str(), F_OK) == -1)
1987  return -EACCES;
1988 
1989  auto read_in = [](std::vector<std::string> &vect,
1990  PortProxy &mem_proxy, VPtr<> mem_loc)
1991  {
1992  for (int inc = 0; ; inc++) {
1993  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
1994  b.copyIn(mem_proxy);
1995 
1996  if (!*(Addr*)b.bufferPtr())
1997  break;
1998 
1999  vect.push_back(std::string());
2000  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2001  }
2002  };
2003 
2008  if (!p->vforkContexts.empty()) {
2009  ThreadContext *vtc = p->system->threads[p->vforkContexts.front()];
2010  assert(vtc->status() == ThreadContext::Suspended);
2011  vtc->activate();
2012  }
2013 
2020  ProcessParams *pp = new ProcessParams();
2021  pp->executable = path;
2022  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2023  read_in(pp->env, mem_proxy, envp_mem_loc);
2024  pp->uid = p->uid();
2025  pp->egid = p->egid();
2026  pp->euid = p->euid();
2027  pp->gid = p->gid();
2028  pp->ppid = p->ppid();
2029  pp->pid = p->pid();
2030  pp->input.assign("cin");
2031  pp->output.assign("cout");
2032  pp->errout.assign("cerr");
2033  pp->cwd.assign(p->tgtCwd);
2034  pp->system = p->system;
2035  pp->release = p->release;
2044  p->system->PIDs.erase(p->pid());
2045  Process *new_p = pp->create();
2046  // TODO: there is no way to know when the Process SimObject is done with
2047  // the params pointer. Both the params pointer (pp) and the process
2048  // pointer (p) are normally managed in python and are never cleaned up.
2049 
2054  new_p->fds = p->fds;
2055  for (int i = 0; i < new_p->fds->getSize(); i++) {
2056  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2057  if (fdep && fdep->getCOE())
2058  new_p->fds->closeFDEntry(i);
2059  }
2060 
2061  *new_p->sigchld = true;
2062 
2063  tc->clearArchRegs();
2064  tc->setProcessPtr(new_p);
2065  new_p->assignThreadContext(tc->contextId());
2066  new_p->init();
2067  new_p->initState();
2068  tc->activate();
2069  TheISA::PCState pcState = tc->pcState();
2070  tc->setNPC(pcState.instAddr());
2071 
2072  return SyscallReturn();
2073 }
2074 
2076 template <class OS>
2077 SyscallReturn
2079  int who /* THREAD, SELF, or CHILDREN */,
2081 {
2082  rup->ru_utime.tv_sec = 0;
2083  rup->ru_utime.tv_usec = 0;
2084  rup->ru_stime.tv_sec = 0;
2085  rup->ru_stime.tv_usec = 0;
2086  rup->ru_maxrss = 0;
2087  rup->ru_ixrss = 0;
2088  rup->ru_idrss = 0;
2089  rup->ru_isrss = 0;
2090  rup->ru_minflt = 0;
2091  rup->ru_majflt = 0;
2092  rup->ru_nswap = 0;
2093  rup->ru_inblock = 0;
2094  rup->ru_oublock = 0;
2095  rup->ru_msgsnd = 0;
2096  rup->ru_msgrcv = 0;
2097  rup->ru_nsignals = 0;
2098  rup->ru_nvcsw = 0;
2099  rup->ru_nivcsw = 0;
2100 
2101  switch (who) {
2102  case OS::TGT_RUSAGE_SELF:
2103  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2104  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2105  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2106  break;
2107 
2108  case OS::TGT_RUSAGE_CHILDREN:
2109  // do nothing. We have no child processes, so they take no time.
2110  break;
2111 
2112  default:
2113  // don't really handle THREAD or CHILDREN, but just warn and
2114  // plow ahead
2115  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2116  who);
2117  }
2118 
2119  return 0;
2120 }
2121 
2123 template <class OS>
2124 SyscallReturn
2126 {
2127  // Fill in the time structure (in clocks)
2128  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / sim_clock::as_int::s;
2129  bufp->tms_utime = clocks;
2130  bufp->tms_stime = 0;
2131  bufp->tms_cutime = 0;
2132  bufp->tms_cstime = 0;
2133 
2134  // Convert to host endianness
2135  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2136 
2137  // Return clock ticks since system boot
2138  return clocks;
2139 }
2140 
2142 template <class OS>
2143 SyscallReturn
2145 {
2146  typename OS::time_t sec, usec;
2147  getElapsedTimeMicro(sec, usec);
2148  sec += seconds_since_epoch;
2149 
2150  if (taddr != 0) {
2151  typename OS::time_t t = sec;
2152  t = htog(t, OS::byteOrder);
2153  PortProxy &p = tc->getVirtProxy();
2154  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2155  }
2156  return sec;
2157 }
2158 
2159 template <class OS>
2160 SyscallReturn
2161 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2162 {
2178  System *sys = tc->getSystemPtr();
2179  Process *tgt_proc = nullptr;
2180  for (auto *tc: sys->threads) {
2181  Process *temp = tc->getProcessPtr();
2182  if (temp->pid() == tid) {
2183  tgt_proc = temp;
2184  break;
2185  }
2186  }
2187 
2188  if (sig != 0 || sig != OS::TGT_SIGABRT)
2189  return -EINVAL;
2190 
2191  if (tgt_proc == nullptr)
2192  return -ESRCH;
2193 
2194  if (tgid != -1 && tgt_proc->tgid() != tgid)
2195  return -ESRCH;
2196 
2197  if (sig == OS::TGT_SIGABRT)
2198  exitGroupFunc(desc, tc, 0);
2199 
2200  return 0;
2201 }
2202 
2203 template <class OS>
2204 SyscallReturn
2206  int domain, int type, int prot)
2207 {
2208  auto p = tc->getProcessPtr();
2209 
2210  int sim_fd = socket(domain, type, prot);
2211  if (sim_fd == -1)
2212  return -errno;
2213 
2214  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2215  int tgt_fd = p->fds->allocFD(sfdp);
2216 
2217  return tgt_fd;
2218 }
2219 
2220 template <class OS>
2221 SyscallReturn
2223  int domain, int type, int prot, VPtr<> svPtr)
2224 {
2225  auto p = tc->getProcessPtr();
2226 
2227  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2228  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2229  if (status == -1)
2230  return -errno;
2231 
2232  int *fds = (int *)svBuf.bufferPtr();
2233 
2234  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2235  fds[0] = p->fds->allocFD(sfdp1);
2236  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2237  fds[1] = p->fds->allocFD(sfdp2);
2238  svBuf.copyOut(tc->getVirtProxy());
2239 
2240  return status;
2241 }
2242 
2243 template <class OS>
2244 SyscallReturn
2245 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2246  VPtr<typename OS::fd_set> readfds,
2247  VPtr<typename OS::fd_set> writefds,
2248  VPtr<typename OS::fd_set> errorfds,
2250 {
2251  int retval;
2252 
2253  auto p = tc->getProcessPtr();
2254 
2260  fd_set readfds_h;
2261  FD_ZERO(&readfds_h);
2262  fd_set writefds_h;
2263  FD_ZERO(&writefds_h);
2264  fd_set errorfds_h;
2265  FD_ZERO(&errorfds_h);
2266 
2276  int nfds_h = 0;
2277  std::map<int, int> trans_map;
2278  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2279  fd_set *hst_set_entry,
2280  int iter) -> bool
2281  {
2287  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2293  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2294  if (!hbfdp)
2295  return true;
2296  auto sim_fd = hbfdp->getSimFD();
2297 
2303  trans_map[sim_fd] = iter;
2304 
2310  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2311 
2316  FD_SET(sim_fd, hst_set_entry);
2317  }
2318  return false;
2319  };
2320 
2321  for (int i = 0; i < nfds; i++) {
2322  if (readfds) {
2323  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2324  if (ebadf)
2325  return -EBADF;
2326  }
2327  if (writefds) {
2328  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2329  if (ebadf)
2330  return -EBADF;
2331  }
2332  if (errorfds) {
2333  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2334  if (ebadf)
2335  return -EBADF;
2336  }
2337  }
2338 
2339  if (timeout) {
2347  timeout->tv_sec = 0;
2348  timeout->tv_usec = 0;
2349 
2350  retval = select(nfds_h,
2351  readfds ? &readfds_h : nullptr,
2352  writefds ? &writefds_h : nullptr,
2353  errorfds ? &errorfds_h : nullptr,
2354  (timeval *)(typename OS::timeval *)timeout);
2355  } else {
2363  struct timeval tv = { 0, 0 };
2364 
2365  retval = select(nfds_h,
2366  readfds ? &readfds_h : nullptr,
2367  readfds ? &writefds_h : nullptr,
2368  readfds ? &errorfds_h : nullptr,
2369  &tv);
2370 
2371  if (retval == 0) {
2377  for (auto sig : tc->getSystemPtr()->signalList)
2378  if (sig.receiver == p)
2379  return -EINTR;
2380  return SyscallReturn::retry();
2381  }
2382  }
2383 
2384  if (retval == -1)
2385  return -errno;
2386 
2387  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2388  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2389  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2390 
2396  for (int i = 0; i < nfds_h; i++) {
2397  if (readfds && FD_ISSET(i, &readfds_h))
2398  FD_SET(trans_map[i],
2399  reinterpret_cast<fd_set *>(
2400  (typename OS::fd_set *)readfds));
2401 
2402  if (writefds && FD_ISSET(i, &writefds_h))
2403  FD_SET(trans_map[i],
2404  reinterpret_cast<fd_set *>(
2405  (typename OS::fd_set *)writefds));
2406 
2407  if (errorfds && FD_ISSET(i, &errorfds_h))
2408  FD_SET(trans_map[i],
2409  reinterpret_cast<fd_set *>(
2410  (typename OS::fd_set *)errorfds));
2411  }
2412 
2413  return retval;
2414 }
2415 
2416 template <class OS>
2417 SyscallReturn
2419  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2420 {
2421  auto p = tc->getProcessPtr();
2422 
2423  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2424  if (!hbfdp)
2425  return -EBADF;
2426  int sim_fd = hbfdp->getSimFD();
2427 
2428  struct pollfd pfd;
2429  pfd.fd = sim_fd;
2430  pfd.events = POLLIN | POLLPRI;
2431  if ((poll(&pfd, 1, 0) == 0)
2432  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2433  return SyscallReturn::retry();
2434 
2435  BufferArg buf_arg(buf_ptr, nbytes);
2436  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2437 
2438  if (bytes_read > 0)
2439  buf_arg.copyOut(tc->getVirtProxy());
2440 
2441  return (bytes_read == -1) ? -errno : bytes_read;
2442 }
2443 
2444 template <class OS>
2445 SyscallReturn
2447  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2448 {
2449  auto p = tc->getProcessPtr();
2450 
2451  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2452  if (!hbfdp)
2453  return -EBADF;
2454  int sim_fd = hbfdp->getSimFD();
2455 
2456  BufferArg buf_arg(buf_ptr, nbytes);
2457  buf_arg.copyIn(tc->getVirtProxy());
2458 
2459  struct pollfd pfd;
2460  pfd.fd = sim_fd;
2461  pfd.events = POLLOUT;
2462 
2469  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2470  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2471  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2472  return SyscallReturn::retry();
2473  }
2474 
2475  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2476 
2477  if (bytes_written != -1)
2478  fsync(sim_fd);
2479 
2480  return (bytes_written == -1) ? -errno : bytes_written;
2481 }
2482 
2483 template <class OS>
2484 SyscallReturn
2486  pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2487 {
2488  auto p = tc->getProcessPtr();
2489 
2490  if (rusagePtr)
2491  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2492  "functionality not supported. Ignoring rusage pointer.\n",
2493  rusagePtr);
2494 
2503  System *sysh = tc->getSystemPtr();
2505  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2506  if (iter->receiver == p) {
2507  if (pid < -1) {
2508  if ((iter->sender->pgid() == -pid)
2509  && (iter->signalValue == OS::TGT_SIGCHLD))
2510  goto success;
2511  } else if (pid == -1) {
2512  if (iter->signalValue == OS::TGT_SIGCHLD)
2513  goto success;
2514  } else if (pid == 0) {
2515  if ((iter->sender->pgid() == p->pgid())
2516  && (iter->signalValue == OS::TGT_SIGCHLD))
2517  goto success;
2518  } else {
2519  if ((iter->sender->pid() == pid)
2520  && (iter->signalValue == OS::TGT_SIGCHLD))
2521  goto success;
2522  }
2523  }
2524  }
2525 
2526  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2527 
2528 success:
2529  // Set status to EXITED for WIFEXITED evaluations.
2530  const int EXITED = 0;
2531  BufferArg statusBuf(statPtr, sizeof(int));
2532  *(int *)statusBuf.bufferPtr() = EXITED;
2533  statusBuf.copyOut(tc->getVirtProxy());
2534 
2535  // Return the child PID.
2536  pid_t retval = iter->sender->pid();
2537  sysh->signalList.erase(iter);
2538  return retval;
2539 }
2540 
2541 template <class OS>
2542 SyscallReturn
2544  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2545 {
2546  struct sockaddr sa;
2547  socklen_t addrLen;
2548  int host_fd;
2549  auto p = tc->getProcessPtr();
2550 
2551  BufferArg *lenBufPtr = nullptr;
2552  BufferArg *addrBufPtr = nullptr;
2553 
2554  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2555  if (!sfdp)
2556  return -EBADF;
2557  int sim_fd = sfdp->getSimFD();
2558 
2565  struct pollfd pfd;
2566  pfd.fd = sim_fd;
2567  pfd.events = POLLIN | POLLPRI;
2568  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2569  return SyscallReturn::retry();
2570 
2571  if (lenPtr) {
2572  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2573  lenBufPtr->copyIn(tc->getVirtProxy());
2574  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2575  sizeof(socklen_t));
2576  }
2577 
2578  if (addrPtr) {
2579  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2580  addrBufPtr->copyIn(tc->getVirtProxy());
2581  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2582  sizeof(struct sockaddr));
2583  }
2584 
2585  host_fd = accept(sim_fd, &sa, &addrLen);
2586 
2587  if (host_fd == -1)
2588  return -errno;
2589 
2590  if (addrPtr) {
2591  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2592  addrBufPtr->copyOut(tc->getVirtProxy());
2593  delete(addrBufPtr);
2594  }
2595 
2596  if (lenPtr) {
2597  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2598  lenBufPtr->copyOut(tc->getVirtProxy());
2599  delete(lenBufPtr);
2600  }
2601 
2602  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2603  sfdp->_type, sfdp->_protocol);
2604  return p->fds->allocFD(afdp);
2605 }
2606 
2608 template <class OS>
2609 SyscallReturn
2611  unsigned initval, int in_flags)
2612 {
2613 #if defined(__linux__)
2614  auto p = tc->getProcessPtr();
2615 
2616  int sim_fd = eventfd(initval, in_flags);
2617  if (sim_fd == -1)
2618  return -errno;
2619 
2620  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2621 
2622  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2623  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2624 
2625  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2626  int tgt_fd = p->fds->allocFD(hbfdp);
2627  return tgt_fd;
2628 #else
2629  warnUnsupportedOS("eventfd");
2630  return -1;
2631 #endif
2632 }
2633 
2635 template <class OS>
2636 SyscallReturn
2638  pid_t pid, size_t cpusetsize, VPtr<> cpu_set_mask)
2639 {
2640 #if defined(__linux__)
2641  if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size()))
2642  return -EINVAL;
2643 
2644  BufferArg maskBuf(cpu_set_mask, cpusetsize);
2645  maskBuf.copyIn(tc->getVirtProxy());
2646  for (int i = 0; i < tc->getSystemPtr()->threads.size(); i++) {
2647  CPU_SET(i, (cpu_set_t *)maskBuf.bufferPtr());
2648  }
2649  maskBuf.copyOut(tc->getVirtProxy());
2650  return CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size());
2651 #else
2652  warnUnsupportedOS("sched_getaffinity");
2653  return -1;
2654 #endif
2655 }
2656 
2657 } // namespace gem5
2658 
2659 #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:1543
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:189
gem5::lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1331
gem5::Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:119
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:680
gem5::chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
Definition: syscall_emul.cc:1039
gem5::timesFunc
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
Definition: syscall_emul.hh:2125
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:1780
gem5::EmulationPageTable::pageSize
Addr pageSize()
Definition: page_table.hh:114
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...
gem5::ArmISA::len
Bitfield< 18, 16 > len
Definition: misc_types.hh:444
warn
#define warn(...)
Definition: logging.hh:245
gem5::System::Threads::size
int size() const
Definition: system.hh:216
linux.hh
gem5::listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1195
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::schedGetaffinityFunc
SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, pid_t pid, size_t cpusetsize, VPtr<> cpu_set_mask)
Target sched_getaffinity.
Definition: syscall_emul.hh:2637
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
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:1638
gem5::getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:958
gem5::hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:556
gem5::getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1528
gem5::cloneFunc
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
Definition: syscall_emul.hh:1417
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:896
gem5::ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:150
gem5::readvFunc
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target readv() handler.
Definition: syscall_emul.hh:1567
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
warn_once
#define warn_once(...)
Definition: logging.hh:249
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:1362
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:1174
gem5::fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Definition: syscall_emul.cc:986
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:2245
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:626
gem5::ArmISA::domain
Bitfield< 7, 4 > domain
Definition: misc_types.hh:423
gem5::SyscallReturn::retry
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Definition: syscall_return.hh:80
tlb.hh
gem5::Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:287
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:522
gem5::readlinkatFunc
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf, size_t bufsiz)
Target readlinkat() handler.
Definition: syscall_emul.hh:938
gem5::guest_abi::VarArgs::get
Arg get()
Definition: varargs.hh:165
gem5::startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:242
gem5::mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:516
gem5::copyOutStatfsBuf
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
Definition: syscall_emul.hh:637
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:1305
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:412
gem5::prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:1870
gem5::getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:371
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:257
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:58
gem5::sim_clock::as_int::us
Tick us
microsecond
Definition: core.cc:70
syscall_emul_buf.hh
gem5::FutexMap::requeue
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
Definition: futex_map.cc:141
gem5::sim_clock::as_int::s
Tick s
second
Definition: core.cc:68
gem5::ignoreWarnOnceFunc
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:78
gem5::fchmodFunc
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
Definition: syscall_emul.hh:1079
gem5::writevFunc
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target writev() handler.
Definition: syscall_emul.hh:1604
gem5::ThreadContext::setUseForClone
void setUseForClone(bool new_val)
Definition: thread_context.hh:102
gem5::Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:273
gem5::EmulationPageTable::shared
bool shared
Definition: page_table.hh:103
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
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:288
gem5::Process::useForClone
bool useForClone
Definition: process.hh:169
gem5::getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1653
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:964
gem5::ThreadContext::status
virtual Status status() const =0
gem5::umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:623
gem5::setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:903
gem5::getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:250
gem5::openFunc
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:906
gem5::Process::childClearTID
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:282
gem5::exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:244
gem5::pollFunc
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
Definition: syscall_emul.hh:1005
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:1098
gem5::getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1568
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:495
gem5::System
Definition: system.hh:77
syscall_return.hh
gem5::ArmISA::b
Bitfield< 7 > b
Definition: misc_types.hh:381
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:1275
gem5::System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:635
gem5::eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2610
gem5::gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:1933
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:93
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:756
gem5::unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
Definition: syscall_emul.cc:459
gem5::ThreadContext::getVirtProxy
virtual PortProxy & getVirtProxy()=0
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:312
gem5::ThreadContext::Suspended
@ Suspended
Temporarily inactive.
Definition: thread_context.hh:112
gem5::getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:972
gem5::X86ISA::count
count
Definition: misc.hh:709
gem5::socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2205
gem5::Process::pTable
EmulationPageTable * pTable
Definition: process.hh:171
gem5::ThreadContext::setNPC
void setNPC(Addr val)
Definition: thread_context.hh:241
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::truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, off_t length)
Target truncate() handler.
Definition: syscall_emul.cc:552
gem5::MipsISA::PCState
GenericISA::DelaySlotPCState< 4 > PCState
Definition: pcstate.hh:40
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::X86ISA::type
type
Definition: misc.hh:733
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
gem5::statfsFunc
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
Definition: syscall_emul.hh:1388
gem5::getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:979
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::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:1920
gem5::FutexMap::wakeup_bitset
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition: futex_map.cc:108
gem5::munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length)
Target munmap() handler.
Definition: syscall_emul.cc:339
gem5::pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:805
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:551
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:583
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:944
gem5::pwrite64Func
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1801
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:379
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:417
gem5::getElapsedTimeNano
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Definition: syscall_emul.hh:535
gem5::setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:279
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::ThreadContext::pcState
virtual TheISA::PCState pcState() const =0
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:728
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:1240
gem5::ArmISA::t
Bitfield< 5 > t
Definition: misc_types.hh:70
gem5::readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.cc:401
gem5::hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:557
gem5::connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1210
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:474
gem5::System::maxPID
static const int maxPID
Definition: system.hh:628
gem5::pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:811
gem5::timeFunc
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
Definition: syscall_emul.hh:2144
gem5::writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2446
gem5::accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:1008
gem5::copyOutStat64Buf
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:615
gem5::sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1461
gem5::gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:361
gem5::fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:770
gem5::recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1323
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:1822
gem5::loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:123
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:2161
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::ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
Definition: syscall_emul.cc:569
gem5::exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:238
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:272
gem5::cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
Definition: syscall_emul.hh:1533
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:1906
gem5::renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
Definition: syscall_emul.hh:949
gem5::ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
Definition: syscall_emul.hh:681
gem5::ThreadContext::suspend
virtual void suspend()=0
Set the status to Suspended.
gem5::loader::SymbolTable::insert
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition: symtab.cc:55
gem5::chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:979
base.hh
gem5::shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1159
gem5::System::threads
Threads threads
Definition: system.hh:316
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:455
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::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:799
gem5::rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:1066
guest_abi.hh
gem5::recvfromFunc
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, VPtr<> addrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1231
gem5::wait4Func
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
Definition: syscall_emul.hh:2485
gem5::getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:951
gem5::statFunc
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
Definition: syscall_emul.hh:1181
gem5::Process::sigchld
bool * sigchld
Definition: process.hh:285
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:1208
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:516
gem5::renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
Definition: syscall_emul.cc:530
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:264
gem5::Process::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: process.cc:277
gem5::readFunc
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2418
gem5::ThreadContext::clearArchRegs
virtual void clearArchRegs()=0
gem5::setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1632
gem5::ThreadContext::threadId
virtual int threadId() const =0
trace.hh
gem5::SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:69
gem5::fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:655
gem5::copyOutStatBuf
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:566
gem5::ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:71
gem5::loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
gem5::getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:937
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:2078
gem5::guest_abi::VarArgs
Definition: varargs.hh:150
intmath.hh
gem5::System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:147
gem5::getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:1834
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: decoder.cc:40
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:700
gem5::socketpairFunc
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
Definition: syscall_emul.hh:2222
gem5::utimesFunc
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
Definition: syscall_emul.hh:1948
gem5::mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:1024
object_file.hh
gem5::acceptFunc
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.hh:2543
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:927
gem5::geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:965
gem5::ArmISA::sa
Bitfield< 3 > sa
Definition: misc_types.hh:391
syscall_desc.hh
gem5::X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:588
gem5::chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:634
gem5::ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:604
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:422
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:73
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:295
gem5::getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1605
gem5::sendtoFunc
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, VPtr<> addrPtr, socklen_t addrLen)
Definition: syscall_emul.cc:1291
gem5::unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:64
gem5::unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname)
Target unlinkat() handler.
Definition: syscall_emul.hh:916
gem5::execveFunc
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
Definition: syscall_emul.hh:1976
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

Generated on Tue Sep 21 2021 12:25:48 for gem5 by doxygen 1.8.17