gem5  v21.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
syscall_emul.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2015, 2019-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 <sys/eventfd.h>
61 #include <sys/statfs.h>
62 
63 #else
64 #include <sys/mount.h>
65 
66 #endif
67 
68 #ifdef __CYGWIN32__
69 #include <sys/fcntl.h>
70 
71 #endif
72 #include <fcntl.h>
73 #include <net/if.h>
74 #include <poll.h>
75 #include <sys/ioctl.h>
76 #include <sys/mman.h>
77 #include <sys/socket.h>
78 #include <sys/stat.h>
79 #include <sys/time.h>
80 #include <sys/types.h>
81 #include <sys/uio.h>
82 #include <unistd.h>
83 
84 #include <cerrno>
85 #include <memory>
86 #include <string>
87 
88 #include "arch/generic/tlb.hh"
89 #include "arch/utility.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 
118 //
119 // The following emulation functions are generic enough that they
120 // don't need to be recompiled for different emulated OS's. They are
121 // defined in sim/syscall_emul.cc.
122 //
124 
125 void warnUnsupportedOS(std::string syscall_name);
126 
129 
138 
139 // Target fallocateFunc() handler.
141  int tgt_fd, int mode, off_t offset, off_t len);
142 
145 
148 
151  uint64_t tidPtr);
152 
155 
158 
160 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
161 
164  int tgt_fd, uint64_t offs, int whence);
165 
168  int tgt_fd, uint64_t offset_high,
169  uint32_t offset_low, VPtr<> result_ptr, int whence);
170 
173  size_t length);
174 
177  int tgt_fd, int how);
178 
181  VPtr<> buf_ptr, int name_len);
182 
185  VPtr<> buf_ptr, unsigned long size);
186 
189  VPtr<> pathname, VPtr<> buf, size_t bufsiz);
190 
193  VPtr<> pathname);
194 
197  VPtr<> pathname, VPtr<> new_pathname);
198 
201  VPtr<> pathname, VPtr<> new_pathname);
202 
205  VPtr<> pathname, mode_t mode);
206 
209  VPtr<> pathname, mode_t mode, dev_t dev);
210 
213 
214 // Target rmdir() handler.
216 
219  VPtr<> oldpath, VPtr<> newpath);
220 
221 
224  VPtr<> pathname, off_t length);
225 
226 
229  int tgt_fd, off_t length);
230 
231 
234  VPtr<> pathname, int64_t length);
235 
238  int tgt_fd, int64_t length);
239 
242 
245 
248  VPtr<> pathname, uint32_t owner, uint32_t group);
249 
252 
255  int pid, int pgid);
256 
259  int tgt_fd, uint32_t owner, uint32_t group);
260 
263  int tgt_fd);
264 
267  int old_tgt_fd, int new_tgt_fd);
268 
271  int tgt_fd, int cmd, GuestABI::VarArgs<int> varargs);
272 
275  int tgt_fd, int cmd);
276 
279 
282  VPtr<> tgt_addr, int flags);
283 
286 
287 // Target getpeername() handler.
289  int tgt_fd, VPtr<> sockAddrPtr,
290  VPtr<> addrlenPtr);
291 
292 // Target bind() handler.
294  int tgt_fd, VPtr<> buf_ptr, int addrlen);
295 
296 // Target listen() handler.
298  int tgt_fd, int backlog);
299 
300 // Target connect() handler.
302  int tgt_fd, VPtr<> buf_ptr, int addrlen);
303 
304 #if defined(SYS_getdents)
305 // Target getdents() handler.
306 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
307  int tgt_fd, VPtr<> buf_ptr, unsigned count);
308 #endif
309 
310 #if defined(SYS_getdents64)
311 // Target getdents() handler.
312 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
313  int tgt_fd, VPtr<> buf_ptr, unsigned count);
314 #endif
315 
316 // Target sendto() handler.
318  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
319  VPtr<> addrPtr, socklen_t addrLen);
320 
321 // Target recvfrom() handler.
323  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen,
324  int flags, VPtr<> addrPtr, VPtr<> addrlenPtr);
325 
326 // Target recvmsg() handler.
328  int tgt_fd, VPtr<> msgPtr, int flags);
329 
330 // Target sendmsg() handler.
332  int tgt_fd, VPtr<> msgPtr, int flags);
333 
334 // Target getuid() handler.
336 
339 
342 
345 
348 
351  VPtr<> pathname, mode_t mode);
352 
353 // Target getsockopt() handler.
355  int tgt_fd, int level, int optname,
356  VPtr<> valPtr, VPtr<> lenPtr);
357 
358 // Target setsockopt() handler.
360  int tgt_fd, int level, int optname,
361  VPtr<> valPtr, socklen_t len);
362 
364  VPtr<uint32_t> cpu, VPtr<uint32_t> node,
365  VPtr<uint32_t> tcache);
366 
367 // Target getsockname() handler.
369  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
370 
374 template <class OS>
377  VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
378 {
379  auto process = tc->getProcessPtr();
380 
381  /*
382  * Unsupported option that does not affect the correctness of the
383  * application. This is a performance optimization utilized by Linux.
384  */
385  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
386  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
387 
388  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
389 
390  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
391  // Ensure futex system call accessed atomically.
392  BufferArg buf(uaddr, sizeof(int));
393  buf.copyIn(tc->getVirtProxy());
394  int mem_val = *(int*)buf.bufferPtr();
395 
396  /*
397  * The value in memory at uaddr is not equal with the expected val
398  * (a different thread must have changed it before the system call was
399  * invoked). In this case, we need to throw an error.
400  */
401  if (val != mem_val)
402  return -OS::TGT_EWOULDBLOCK;
403 
404  if (OS::TGT_FUTEX_WAIT == op) {
405  futex_map.suspend(uaddr, process->tgid(), tc);
406  } else {
407  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
408  }
409 
410  return 0;
411  } else if (OS::TGT_FUTEX_WAKE == op) {
412  return futex_map.wakeup(uaddr, process->tgid(), val);
413  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
414  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
415  } else if (OS::TGT_FUTEX_REQUEUE == op ||
416  OS::TGT_FUTEX_CMP_REQUEUE == op) {
417 
418  // Ensure futex system call accessed atomically.
419  BufferArg buf(uaddr, sizeof(int));
420  buf.copyIn(tc->getVirtProxy());
421  int mem_val = *(int*)buf.bufferPtr();
422  /*
423  * For CMP_REQUEUE, the whole operation is only started only if
424  * val3 is still the value of the futex pointed to by uaddr.
425  */
426  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
427  return -OS::TGT_EWOULDBLOCK;
428  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
429  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
430  /*
431  * The FUTEX_WAKE_OP operation is equivalent to executing the
432  * following code atomically and totally ordered with respect to
433  * other futex operations on any of the two supplied futex words:
434  *
435  * int oldval = *(int *) addr2;
436  * *(int *) addr2 = oldval op oparg;
437  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
438  * if (oldval cmp cmparg)
439  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
440  *
441  * (op, oparg, cmp, cmparg are encoded in val3)
442  *
443  * +---+---+-----------+-----------+
444  * |op |cmp| oparg | cmparg |
445  * +---+---+-----------+-----------+
446  * 4 4 12 12 <== # of bits
447  *
448  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
449  *
450  */
451  // get value from simulated-space
452  BufferArg buf(uaddr2, sizeof(int));
453  buf.copyIn(tc->getVirtProxy());
454  int oldval = *(int*)buf.bufferPtr();
455  int newval = oldval;
456  // extract op, oparg, cmp, cmparg from val3
457  int wake_cmparg = val3 & 0xfff;
458  int wake_oparg = (val3 & 0xfff000) >> 12;
459  int wake_cmp = (val3 & 0xf000000) >> 24;
460  int wake_op = (val3 & 0xf0000000) >> 28;
461  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
462  wake_oparg = (1 << wake_oparg);
463  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
464  // perform operation on the value of the second futex
465  if (wake_op == OS::TGT_FUTEX_OP_SET)
466  newval = wake_oparg;
467  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
468  newval += wake_oparg;
469  else if (wake_op == OS::TGT_FUTEX_OP_OR)
470  newval |= wake_oparg;
471  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
472  newval &= ~wake_oparg;
473  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
474  newval ^= wake_oparg;
475  // copy updated value back to simulated-space
476  *(int*)buf.bufferPtr() = newval;
477  buf.copyOut(tc->getVirtProxy());
478  // perform the first wake-up
479  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
480  int woken2 = 0;
481  // calculate the condition of the second wake-up
482  bool is_wake2 = false;
483  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
484  is_wake2 = oldval == wake_cmparg;
485  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
486  is_wake2 = oldval != wake_cmparg;
487  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
488  is_wake2 = oldval < wake_cmparg;
489  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
490  is_wake2 = oldval <= wake_cmparg;
491  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
492  is_wake2 = oldval > wake_cmparg;
493  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
494  is_wake2 = oldval >= wake_cmparg;
495  // perform the second wake-up
496  if (is_wake2)
497  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
498 
499  return woken1 + woken2;
500  }
501  warn("futex: op %d not implemented; ignoring.", op);
502  return -ENOSYS;
503 }
504 
508 
509 
513 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
514 
517 template <class T1, class T2>
518 void
519 getElapsedTimeMicro(T1 &sec, T2 &usec)
520 {
521  static const int OneMillion = 1000 * 1000;
522 
523  uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
524  sec = elapsed_usecs / OneMillion;
525  usec = elapsed_usecs % OneMillion;
526 }
527 
530 template <class T1, class T2>
531 void
532 getElapsedTimeNano(T1 &sec, T2 &nsec)
533 {
534  static const int OneBillion = 1000 * 1000 * 1000;
535 
536  uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
537  sec = elapsed_nsecs / OneBillion;
538  nsec = elapsed_nsecs % OneBillion;
539 }
540 
542 //
543 // The following emulation functions are generic, but need to be
544 // templated to account for differences in types, constants, etc.
545 //
547 
548  typedef struct statfs hst_statfs;
549 #if NO_STAT64
550  typedef struct stat hst_stat;
551  typedef struct stat hst_stat64;
552 #else
553  typedef struct stat hst_stat;
554  typedef struct stat64 hst_stat64;
555 #endif
556 
560 
561 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
562 void
563 copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
564 {
565  constexpr ByteOrder bo = OS::byteOrder;
566 
567  if (fakeTTY)
568  tgt->st_dev = 0xA;
569  else
570  tgt->st_dev = host->st_dev;
571  tgt->st_dev = htog(tgt->st_dev, bo);
572  tgt->st_ino = host->st_ino;
573  tgt->st_ino = htog(tgt->st_ino, bo);
574  tgt->st_mode = host->st_mode;
575  if (fakeTTY) {
576  // Claim to be a character device
577  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
578  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
579  }
580  tgt->st_mode = htog(tgt->st_mode, bo);
581  tgt->st_nlink = host->st_nlink;
582  tgt->st_nlink = htog(tgt->st_nlink, bo);
583  tgt->st_uid = host->st_uid;
584  tgt->st_uid = htog(tgt->st_uid, bo);
585  tgt->st_gid = host->st_gid;
586  tgt->st_gid = htog(tgt->st_gid, bo);
587  if (fakeTTY)
588  tgt->st_rdev = 0x880d;
589  else
590  tgt->st_rdev = host->st_rdev;
591  tgt->st_rdev = htog(tgt->st_rdev, bo);
592  tgt->st_size = host->st_size;
593  tgt->st_size = htog(tgt->st_size, bo);
594  tgt->st_atimeX = host->st_atime;
595  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
596  tgt->st_mtimeX = host->st_mtime;
597  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
598  tgt->st_ctimeX = host->st_ctime;
599  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
600  // Force the block size to be 8KB. This helps to ensure buffered io works
601  // consistently across different hosts.
602  tgt->st_blksize = 0x2000;
603  tgt->st_blksize = htog(tgt->st_blksize, bo);
604  tgt->st_blocks = host->st_blocks;
605  tgt->st_blocks = htog(tgt->st_blocks, bo);
606 }
607 
608 // Same for stat64
609 
610 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
611 void
612 copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host,
613  bool fakeTTY=false)
614 {
615  copyOutStatBuf<OS>(tgt, host, fakeTTY);
616 #if defined(STAT_HAVE_NSEC)
617  constexpr ByteOrder bo = OS::byteOrder;
618 
619  tgt->st_atime_nsec = host->st_atime_nsec;
620  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
621  tgt->st_mtime_nsec = host->st_mtime_nsec;
622  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
623  tgt->st_ctime_nsec = host->st_ctime_nsec;
624  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
625 #else
626  tgt->st_atime_nsec = 0;
627  tgt->st_mtime_nsec = 0;
628  tgt->st_ctime_nsec = 0;
629 #endif
630 }
631 
632 template <class OS, typename TgtStatPtr, typename HostStatPtr>
633 void
634 copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
635 {
636  constexpr ByteOrder bo = OS::byteOrder;
637 
638  tgt->f_type = htog(host->f_type, bo);
639 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
640  tgt->f_bsize = htog(host->f_iosize, bo);
641 #else
642  tgt->f_bsize = htog(host->f_bsize, bo);
643 #endif
644  tgt->f_blocks = htog(host->f_blocks, bo);
645  tgt->f_bfree = htog(host->f_bfree, bo);
646  tgt->f_bavail = htog(host->f_bavail, bo);
647  tgt->f_files = htog(host->f_files, bo);
648  tgt->f_ffree = htog(host->f_ffree, bo);
649  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
650 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
651  tgt->f_namelen = htog(host->f_namemax, bo);
652  tgt->f_frsize = htog(host->f_bsize, bo);
653 #elif defined(__APPLE__)
654  tgt->f_namelen = 0;
655  tgt->f_frsize = 0;
656 #else
657  tgt->f_namelen = htog(host->f_namelen, bo);
658  tgt->f_frsize = htog(host->f_frsize, bo);
659 #endif
660 #if defined(__linux__)
661  memcpy(&tgt->f_spare, &host->f_spare,
662  std::min(sizeof(host->f_spare), sizeof(tgt->f_spare)));
663 #else
664  /*
665  * The fields are different sizes per OS. Don't bother with
666  * f_spare or f_reserved on non-Linux for now.
667  */
668  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
669 #endif
670 }
671 
676 template <class OS>
679  int tgt_fd, unsigned req, VPtr<> addr)
680 {
681  auto p = tc->getProcessPtr();
682 
683  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
684 
685  if (OS::isTtyReq(req))
686  return -ENOTTY;
687 
688  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
689  if (dfdp) {
690  EmulatedDriver *emul_driver = dfdp->getDriver();
691  if (emul_driver)
692  return emul_driver->ioctl(tc, req, addr);
693  }
694 
695  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
696  if (sfdp) {
697  int status;
698 
699  switch (req) {
700  case SIOCGIFCONF: {
701  BufferArg conf_arg(addr, sizeof(ifconf));
702  conf_arg.copyIn(tc->getVirtProxy());
703 
704  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
705  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
706  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
707  ifc_buf_arg.copyIn(tc->getVirtProxy());
708 
709  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
710 
711  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
712  if (status != -1) {
713  conf->ifc_buf = (char*)ifc_buf_addr;
714  ifc_buf_arg.copyOut(tc->getVirtProxy());
715  conf_arg.copyOut(tc->getVirtProxy());
716  }
717 
718  return status;
719  }
720  case SIOCGIFFLAGS:
721 #if defined(__linux__)
722  case SIOCGIFINDEX:
723 #endif
724  case SIOCGIFNETMASK:
725  case SIOCGIFADDR:
726 #if defined(__linux__)
727  case SIOCGIFHWADDR:
728 #endif
729  case SIOCGIFMTU: {
730  BufferArg req_arg(addr, sizeof(ifreq));
731  req_arg.copyIn(tc->getVirtProxy());
732 
733  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
734  if (status != -1)
735  req_arg.copyOut(tc->getVirtProxy());
736  return status;
737  }
738  }
739  }
740 
745  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
746  tgt_fd, req, tc->pcState());
747  return -ENOTTY;
748 }
749 
751 template <class OS>
754  int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
755 {
756  auto p = tc->getProcessPtr();
757 
762  std::string path;
763  if (!tc->getVirtProxy().tryReadString(path, pathname))
764  return -EFAULT;
765 
766 #ifdef __CYGWIN32__
767  int host_flags = O_BINARY;
768 #else
769  int host_flags = 0;
770 #endif
771 
775  for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
776  if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
777  tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
778  host_flags |= OS::openFlagTable[i].hostFlag;
779  }
780  }
781  if (tgt_flags)
782  warn("%s: cannot decode flags %#x", desc->name(), tgt_flags);
783 
784 #ifdef __CYGWIN32__
785  host_flags |= O_BINARY;
786 #endif
787 
800  std::string redir_path = path;
801  std::string abs_path = path;
802  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
803  abs_path = p->absolutePath(path, true);
804  redir_path = p->checkPathRedirect(path);
805  } else if (!startswith(path, "/")) {
806  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
807  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
808  if (!ffdp)
809  return -EBADF;
810  abs_path = ffdp->getFileName() + path;
811  redir_path = p->checkPathRedirect(abs_path);
812  }
813 
820  if (startswith(abs_path, "/dev/")) {
821  std::string filename = abs_path.substr(strlen("/dev/"));
822  EmulatedDriver *drv = p->findDriver(filename);
823  if (drv) {
824  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
825  "driver open with path[%s]\n",
826  desc->name(), abs_path.c_str());
827  return drv->open(tc, mode, host_flags);
828  }
833  }
834 
859  int sim_fd = -1;
860  std::string used_path;
861  std::vector<std::string> special_paths =
862  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
863  "/proc/self/maps", "/dev/urandom",
864  "/sys/devices/system/cpu/online" };
865  for (auto entry : special_paths) {
866  if (startswith(path, entry)) {
867  sim_fd = OS::openSpecialFile(abs_path, p, tc);
868  used_path = abs_path;
869  }
870  }
871  if (sim_fd == -1) {
872  sim_fd = open(redir_path.c_str(), host_flags, mode);
873  used_path = redir_path;
874  }
875  if (sim_fd == -1) {
876  int local = -errno;
877  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
878  "(inferred from:%s)\n", desc->name(),
879  used_path.c_str(), path.c_str());
880  return local;
881  }
882 
891  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
892  int tgt_fd = p->fds->allocFD(ffdp);
893  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
894  "(inferred from:%s)\n", desc->name(),
895  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
896  return tgt_fd;
897 }
898 
900 template <class OS>
903  VPtr<> pathname, int tgt_flags, int mode)
904 {
905  return openatFunc<OS>(
906  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
907 }
908 
910 template <class OS>
912 unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname)
913 {
914  if (dirfd != OS::TGT_AT_FDCWD)
915  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
916 
917  return unlinkFunc(desc, tc, pathname);
918 }
919 
921 template <class OS>
924  int dirfd, VPtr<> pathname, int mode)
925 {
926  if (dirfd != OS::TGT_AT_FDCWD)
927  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
928  return accessFunc(desc, tc, pathname, mode);
929 }
930 
932 template <class OS>
935  int dirfd, VPtr<> pathname, VPtr<> buf, size_t bufsiz)
936 {
937  if (dirfd != OS::TGT_AT_FDCWD)
938  warn("openat: first argument not AT_FDCWD; unlikely to work");
939  return readlinkFunc(desc, tc, pathname, buf, bufsiz);
940 }
941 
943 template <class OS>
946  int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
947 {
948  if (olddirfd != OS::TGT_AT_FDCWD)
949  warn("renameat: first argument not AT_FDCWD; unlikely to work");
950 
951  if (newdirfd != OS::TGT_AT_FDCWD)
952  warn("renameat: third argument not AT_FDCWD; unlikely to work");
953 
954  return renameFunc(desc, tc, oldpath, newpath);
955 }
956 
958 template <class OS>
962 {
963  auto process = tc->getProcessPtr();
964 
965  sysinfo->uptime = seconds_since_epoch;
966  sysinfo->totalram = process->system->memSize();
967  sysinfo->mem_unit = 1;
968 
969  return 0;
970 }
971 
973 template <class OS>
975 chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
976 {
977  std::string path;
978  auto process = tc->getProcessPtr();
979 
980  if (!tc->getVirtProxy().tryReadString(path, pathname))
981  return -EFAULT;
982 
983  mode_t hostMode = 0;
984 
985  // XXX translate mode flags via OS::something???
986  hostMode = mode;
987 
988  // Adjust path for cwd and redirection
989  path = process->checkPathRedirect(path);
990 
991  // do the chmod
992  int result = chmod(path.c_str(), hostMode);
993  if (result < 0)
994  return -errno;
995 
996  return 0;
997 }
998 
999 template <class OS>
1002  VPtr<> fdsPtr, int nfds, int tmout)
1003 {
1004  auto p = tc->getProcessPtr();
1005 
1006  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1007  fdsBuf.copyIn(tc->getVirtProxy());
1008 
1015  int temp_tgt_fds[nfds];
1016  for (int index = 0; index < nfds; index++) {
1017  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1018  auto tgt_fd = temp_tgt_fds[index];
1019  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1020  if (!hbfdp)
1021  return -EBADF;
1022  auto host_fd = hbfdp->getSimFD();
1023  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1024  }
1025 
1032  int status;
1033  if (tmout < 0) {
1034  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1035  if (status == 0) {
1041  System *sysh = tc->getSystemPtr();
1043  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1044  if (it->receiver == p)
1045  return -EINTR;
1046  return SyscallReturn::retry();
1047  }
1048  } else
1049  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1050 
1051  if (status == -1)
1052  return -errno;
1053 
1058  for (int index = 0; index < nfds; index++) {
1059  auto tgt_fd = temp_tgt_fds[index];
1060  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1061  }
1062 
1067  fdsBuf.copyOut(tc->getVirtProxy());
1068 
1069  return status;
1070 }
1071 
1073 template <class OS>
1075 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1076 {
1077  auto p = tc->getProcessPtr();
1078 
1079  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1080  if (!ffdp)
1081  return -EBADF;
1082  int sim_fd = ffdp->getSimFD();
1083 
1084  mode_t hostMode = mode;
1085 
1086  int result = fchmod(sim_fd, hostMode);
1087 
1088  return (result < 0) ? -errno : 0;
1089 }
1090 
1092 template <class OS>
1095  VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1097 {
1098  auto p = tc->getProcessPtr();
1099  Addr page_bytes = p->pTable->pageSize();
1100  uint64_t provided_address = 0;
1101  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1102 
1103  if (use_provided_address)
1104  provided_address = varargs.get<uint64_t>();
1105 
1106  if ((start % page_bytes != 0) ||
1107  (provided_address % page_bytes != 0)) {
1108  warn("mremap failing: arguments not page aligned");
1109  return -EINVAL;
1110  }
1111 
1112  new_length = roundUp(new_length, page_bytes);
1113 
1114  if (new_length > old_length) {
1115  Addr mmap_end = p->memState->getMmapEnd();
1116 
1117  if ((start + old_length) == mmap_end &&
1118  (!use_provided_address || provided_address == start)) {
1119  // This case cannot occur when growing downward, as
1120  // start is greater than or equal to mmap_end.
1121  uint64_t diff = new_length - old_length;
1122  p->memState->mapRegion(mmap_end, diff, "remapped");
1123  p->memState->setMmapEnd(mmap_end + diff);
1124  return (Addr)start;
1125  } else {
1126  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1127  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1128  return -ENOMEM;
1129  } else {
1130  uint64_t new_start = provided_address;
1131  if (!use_provided_address) {
1132  new_start = p->mmapGrowsDown() ?
1133  mmap_end - new_length : mmap_end;
1134  mmap_end = p->mmapGrowsDown() ?
1135  new_start : mmap_end + new_length;
1136  p->memState->setMmapEnd(mmap_end);
1137  }
1138 
1139  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1140  new_start, new_start + new_length,
1141  new_length - old_length);
1142 
1143  // add on the remaining unallocated pages
1144  p->allocateMem(new_start + old_length,
1145  new_length - old_length,
1146  use_provided_address /* clobber */);
1147 
1148  if (use_provided_address &&
1149  ((new_start + new_length > p->memState->getMmapEnd() &&
1150  !p->mmapGrowsDown()) ||
1151  (new_start < p->memState->getMmapEnd() &&
1152  p->mmapGrowsDown()))) {
1153  // something fishy going on here, at least notify the user
1154  // @todo: increase mmap_end?
1155  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1156  }
1157 
1158  warn("returning %08p as start\n", new_start);
1159  p->memState->remapRegion(start, new_start, old_length);
1160  return new_start;
1161  }
1162  }
1163  } else {
1164  // Shrink a region
1165  if (use_provided_address && provided_address != start)
1166  p->memState->remapRegion(start, provided_address, new_length);
1167  if (new_length != old_length)
1168  p->memState->unmapRegion(start + new_length,
1169  old_length - new_length);
1170  return use_provided_address ? provided_address : (Addr)start;
1171  }
1172 }
1173 
1175 template <class OS>
1178  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1179 {
1180  std::string path;
1181  auto process = tc->getProcessPtr();
1182 
1183  if (!tc->getVirtProxy().tryReadString(path, pathname))
1184  return -EFAULT;
1185 
1186  // Adjust path for cwd and redirection
1187  path = process->checkPathRedirect(path);
1188 
1189  struct stat hostBuf;
1190  int result = stat(path.c_str(), &hostBuf);
1191 
1192  if (result < 0)
1193  return -errno;
1194 
1195  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1196 
1197  return 0;
1198 }
1199 
1200 
1202 template <class OS>
1205  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1206 {
1207  std::string path;
1208  auto process = tc->getProcessPtr();
1209 
1210  if (!tc->getVirtProxy().tryReadString(path, pathname))
1211  return -EFAULT;
1212 
1213  // Adjust path for cwd and redirection
1214  path = process->checkPathRedirect(path);
1215 
1216 #if NO_STAT64
1217  struct stat hostBuf;
1218  int result = stat(path.c_str(), &hostBuf);
1219 #else
1220  struct stat64 hostBuf;
1221  int result = stat64(path.c_str(), &hostBuf);
1222 #endif
1223 
1224  if (result < 0)
1225  return -errno;
1226 
1227  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1228 
1229  return 0;
1230 }
1231 
1232 
1234 template <class OS>
1237  int dirfd, VPtr<> pathname,
1239 {
1240  auto process = tc->getProcessPtr();
1241  if (dirfd != OS::TGT_AT_FDCWD)
1242  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1243 
1244  std::string path;
1245  if (!tc->getVirtProxy().tryReadString(path, pathname))
1246  return -EFAULT;
1247 
1248  // Adjust path for cwd and redirection
1249  path = process->checkPathRedirect(path);
1250 
1251 #if NO_STAT64
1252  struct stat hostBuf;
1253  int result = stat(path.c_str(), &hostBuf);
1254 #else
1255  struct stat64 hostBuf;
1256  int result = stat64(path.c_str(), &hostBuf);
1257 #endif
1258 
1259  if (result < 0)
1260  return -errno;
1261 
1262  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1263 
1264  return 0;
1265 }
1266 
1267 
1269 template <class OS>
1272  int tgt_fd, VPtr<typename OS::tgt_stat64> tgt_stat)
1273 {
1274  auto p = tc->getProcessPtr();
1275 
1276  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1277  if (!ffdp)
1278  return -EBADF;
1279  int sim_fd = ffdp->getSimFD();
1280 
1281 #if NO_STAT64
1282  struct stat hostBuf;
1283  int result = fstat(sim_fd, &hostBuf);
1284 #else
1285  struct stat64 hostBuf;
1286  int result = fstat64(sim_fd, &hostBuf);
1287 #endif
1288 
1289  if (result < 0)
1290  return -errno;
1291 
1292  copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1293 
1294  return 0;
1295 }
1296 
1297 
1299 template <class OS>
1302  VPtr<> pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1303 {
1304  std::string path;
1305  auto process = tc->getProcessPtr();
1306 
1307  if (!tc->getVirtProxy().tryReadString(path, pathname))
1308  return -EFAULT;
1309 
1310  // Adjust path for cwd and redirection
1311  path = process->checkPathRedirect(path);
1312 
1313  struct stat hostBuf;
1314  int result = lstat(path.c_str(), &hostBuf);
1315 
1316  if (result < 0)
1317  return -errno;
1318 
1319  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1320 
1321  return 0;
1322 }
1323 
1325 template <class OS>
1328  VPtr<> pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1329 {
1330  std::string path;
1331  auto process = tc->getProcessPtr();
1332 
1333  if (!tc->getVirtProxy().tryReadString(path, pathname))
1334  return -EFAULT;
1335 
1336  // Adjust path for cwd and redirection
1337  path = process->checkPathRedirect(path);
1338 
1339 #if NO_STAT64
1340  struct stat hostBuf;
1341  int result = lstat(path.c_str(), &hostBuf);
1342 #else
1343  struct stat64 hostBuf;
1344  int result = lstat64(path.c_str(), &hostBuf);
1345 #endif
1346 
1347  if (result < 0)
1348  return -errno;
1349 
1350  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1351 
1352  return 0;
1353 }
1354 
1356 template <class OS>
1359  int tgt_fd, VPtr<typename OS::tgt_stat> tgt_stat)
1360 {
1361  auto p = tc->getProcessPtr();
1362 
1363  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1364 
1365  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1366  if (!ffdp)
1367  return -EBADF;
1368  int sim_fd = ffdp->getSimFD();
1369 
1370  struct stat hostBuf;
1371  int result = fstat(sim_fd, &hostBuf);
1372 
1373  if (result < 0)
1374  return -errno;
1375 
1376  copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1377 
1378  return 0;
1379 }
1380 
1382 template <class OS>
1385  VPtr<> pathname, VPtr<typename OS::tgt_statfs> tgt_stat)
1386 {
1387 #if defined(__linux__)
1388  std::string path;
1389  auto process = tc->getProcessPtr();
1390 
1391  if (!tc->getVirtProxy().tryReadString(path, pathname))
1392  return -EFAULT;
1393 
1394  // Adjust path for cwd and redirection
1395  path = process->checkPathRedirect(path);
1396 
1397  struct statfs hostBuf;
1398  int result = statfs(path.c_str(), &hostBuf);
1399 
1400  if (result < 0)
1401  return -errno;
1402 
1403  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1404  return 0;
1405 #else
1406  warnUnsupportedOS("statfs");
1407  return -1;
1408 #endif
1409 }
1410 
1411 template <class OS>
1413 cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
1414  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1415 {
1416  auto p = tc->getProcessPtr();
1417 
1418  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1419  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1420  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1421  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1422  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1423  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1424  return -EINVAL;
1425 
1426  ThreadContext *ctc;
1427  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1428  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1429  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1430  return -EAGAIN;
1431  }
1432 
1439  ProcessParams *pp = new ProcessParams();
1440  pp->executable.assign(*(new std::string(p->progName())));
1441  pp->cmd.push_back(*(new std::string(p->progName())));
1442  pp->system = p->system;
1443  pp->cwd.assign(p->tgtCwd);
1444  pp->input.assign("stdin");
1445  pp->output.assign("stdout");
1446  pp->errout.assign("stderr");
1447  pp->uid = p->uid();
1448  pp->euid = p->euid();
1449  pp->gid = p->gid();
1450  pp->egid = p->egid();
1451 
1452  /* Find the first free PID that's less than the maximum */
1453  std::set<int> const& pids = p->system->PIDs;
1454  int temp_pid = *pids.begin();
1455  do {
1456  temp_pid++;
1457  } while (pids.find(temp_pid) != pids.end());
1458  if (temp_pid >= System::maxPID)
1459  fatal("temp_pid is too large: %d", temp_pid);
1460 
1461  pp->pid = temp_pid;
1462  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1463  pp->useArchPT = p->useArchPT;
1464  pp->kvmInSE = p->kvmInSE;
1465  Process *cp = pp->create();
1466  // TODO: there is no way to know when the Process SimObject is done with
1467  // the params pointer. Both the params pointer (pp) and the process
1468  // pointer (cp) are normally managed in python and are never cleaned up.
1469 
1470  Process *owner = ctc->getProcessPtr();
1471  ctc->setProcessPtr(cp);
1472  cp->assignThreadContext(ctc->contextId());
1473  owner->revokeThreadContext(ctc->contextId());
1474 
1475  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1476  BufferArg ptidBuf(ptidPtr, sizeof(long));
1477  long *ptid = (long *)ptidBuf.bufferPtr();
1478  *ptid = cp->pid();
1479  ptidBuf.copyOut(tc->getVirtProxy());
1480  }
1481 
1482  if (flags & OS::TGT_CLONE_THREAD) {
1483  cp->pTable->shared = true;
1484  cp->useForClone = true;
1485  }
1486 
1487  ctc->setUseForClone(true);
1488  cp->initState();
1489  p->clone(tc, ctc, cp, flags);
1490 
1491  if (flags & OS::TGT_CLONE_THREAD) {
1492  delete cp->sigchld;
1493  cp->sigchld = p->sigchld;
1494  } else if (flags & OS::TGT_SIGCHLD) {
1495  *cp->sigchld = true;
1496  }
1497 
1498  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1499  BufferArg ctidBuf(ctidPtr, sizeof(long));
1500  long *ctid = (long *)ctidBuf.bufferPtr();
1501  *ctid = cp->pid();
1502  ctidBuf.copyOut(ctc->getVirtProxy());
1503  }
1504 
1505  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1506  cp->childClearTID = (uint64_t)ctidPtr;
1507 
1508  ctc->clearArchRegs();
1509 
1510  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1511 
1512  desc->returnInto(ctc, 0);
1513 
1514  TheISA::PCState cpc = tc->pcState();
1515  cpc.advance();
1516  ctc->pcState(cpc);
1517  ctc->activate();
1518 
1519  return cp->pid();
1520 }
1521 
1522 template <class OS>
1525  RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1526  VPtr<> ctidPtr)
1527 {
1528  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1529 }
1530 
1532 template <class OS>
1535  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1536 {
1537  auto p = tc->getProcessPtr();
1538 
1539  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1540  if (!ffdp)
1541  return -EBADF;
1542  int sim_fd = ffdp->getSimFD();
1543 
1544  struct statfs hostBuf;
1545  int result = fstatfs(sim_fd, &hostBuf);
1546 
1547  if (result < 0)
1548  return -errno;
1549 
1550  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1551 
1552  return 0;
1553 }
1554 
1556 template <class OS>
1559  int tgt_fd, uint64_t tiov_base, size_t count)
1560 {
1561  auto p = tc->getProcessPtr();
1562 
1563  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1564  if (!ffdp)
1565  return -EBADF;
1566  int sim_fd = ffdp->getSimFD();
1567 
1568  PortProxy &prox = tc->getVirtProxy();
1569  typename OS::tgt_iovec tiov[count];
1570  struct iovec hiov[count];
1571  for (size_t i = 0; i < count; ++i) {
1572  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1573  &tiov[i], sizeof(typename OS::tgt_iovec));
1574  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1575  hiov[i].iov_base = new char [hiov[i].iov_len];
1576  }
1577 
1578  int result = readv(sim_fd, hiov, count);
1579  int local_errno = errno;
1580 
1581  for (size_t i = 0; i < count; ++i) {
1582  if (result != -1) {
1583  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1584  hiov[i].iov_base, hiov[i].iov_len);
1585  }
1586  delete [] (char *)hiov[i].iov_base;
1587  }
1588 
1589  return (result == -1) ? -local_errno : result;
1590 }
1591 
1593 template <class OS>
1596  int tgt_fd, uint64_t tiov_base, size_t count)
1597 {
1598  auto p = tc->getProcessPtr();
1599 
1600  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1601  if (!hbfdp)
1602  return -EBADF;
1603  int sim_fd = hbfdp->getSimFD();
1604 
1605  PortProxy &prox = tc->getVirtProxy();
1606  struct iovec hiov[count];
1607  for (size_t i = 0; i < count; ++i) {
1608  typename OS::tgt_iovec tiov;
1609 
1610  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1611  &tiov, sizeof(typename OS::tgt_iovec));
1612  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1613  hiov[i].iov_base = new char [hiov[i].iov_len];
1614  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1615  hiov[i].iov_len);
1616  }
1617 
1618  int result = writev(sim_fd, hiov, count);
1619 
1620  for (size_t i = 0; i < count; ++i)
1621  delete [] (char *)hiov[i].iov_base;
1622 
1623  return (result == -1) ? -errno : result;
1624 }
1625 
1627 template <class OS>
1630  VPtr<> start, typename OS::size_t length, int prot,
1631  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1632 {
1633  auto p = tc->getProcessPtr();
1634  Addr page_bytes = p->pTable->pageSize();
1635 
1636  if (start & (page_bytes - 1) ||
1637  offset & (page_bytes - 1) ||
1638  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1639  tgt_flags & OS::TGT_MAP_SHARED) ||
1640  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1641  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1642  !length) {
1643  return -EINVAL;
1644  }
1645 
1646  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1647  // With shared mmaps, there are two cases to consider:
1648  // 1) anonymous: writes should modify the mapping and this should be
1649  // visible to observers who share the mapping. Currently, it's
1650  // difficult to update the shared mapping because there's no
1651  // structure which maintains information about the which virtual
1652  // memory areas are shared. If that structure existed, it would be
1653  // possible to make the translations point to the same frames.
1654  // 2) file-backed: writes should modify the mapping and the file
1655  // which is backed by the mapping. The shared mapping problem is the
1656  // same as what was mentioned about the anonymous mappings. For
1657  // file-backed mappings, the writes to the file are difficult
1658  // because it requires syncing what the mapping holds with the file
1659  // that resides on the host system. So, any write on a real system
1660  // would cause the change to be propagated to the file mapping at
1661  // some point in the future (the inode is tracked along with the
1662  // mapping). This isn't guaranteed to always happen, but it usually
1663  // works well enough. The guarantee is provided by the msync system
1664  // call. We could force the change through with shared mappings with
1665  // a call to msync, but that again would require more information
1666  // than we currently maintain.
1667  warn_once("mmap: writing to shared mmap region is currently "
1668  "unsupported. The write succeeds on the target, but it "
1669  "will not be propagated to the host or shared mappings");
1670  }
1671 
1672  length = roundUp(length, page_bytes);
1673 
1674  int sim_fd = -1;
1675  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1676  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1677 
1678  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1679  if (dfdp) {
1680  EmulatedDriver *emul_driver = dfdp->getDriver();
1681  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1682  tgt_fd, offset);
1683  }
1684 
1685  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1686  if (!ffdp)
1687  return -EBADF;
1688  sim_fd = ffdp->getSimFD();
1689 
1698  if (p->interpImage.contains(tc->pcState().instAddr())) {
1699  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1700  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1701  auto *lib = Loader::createObjectFile(p->checkPathRedirect(
1702  ffdp->getFileName()));
1703  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1704  ffdp->getFileName());
1705 
1706  if (lib) {
1707  Addr offset = lib->buildImage().minAddr() + start;
1708  Loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1709  }
1710  }
1711  }
1712 
1716  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1724  if (!(start && p->memState->isUnmapped(start, length))) {
1728  start = p->memState->extendMmap(length);
1729  }
1730  }
1731 
1732  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1733  start, start + length - 1);
1734 
1740  if (tgt_flags & OS::TGT_MAP_FIXED) {
1745  p->memState->unmapRegion(start, length);
1746  }
1747 
1751  std::string region_name;
1752  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1753  region_name = "anon";
1754  } else {
1755  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1756  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1757  region_name = ffdp->getFileName();
1758  }
1759 
1764  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1765 
1766  return (Addr)start;
1767 }
1768 
1769 template <class OS>
1772  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1773 {
1774  auto p = tc->getProcessPtr();
1775 
1776  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1777  if (!ffdp)
1778  return -EBADF;
1779  int sim_fd = ffdp->getSimFD();
1780 
1781  BufferArg bufArg(bufPtr, nbytes);
1782 
1783  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1784 
1785  bufArg.copyOut(tc->getVirtProxy());
1786 
1787  return (bytes_read == -1) ? -errno : bytes_read;
1788 }
1789 
1790 template <class OS>
1793  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1794 {
1795  auto p = tc->getProcessPtr();
1796 
1797  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1798  if (!ffdp)
1799  return -EBADF;
1800  int sim_fd = ffdp->getSimFD();
1801 
1802  BufferArg bufArg(bufPtr, nbytes);
1803  bufArg.copyIn(tc->getVirtProxy());
1804 
1805  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1806 
1807  return (bytes_written == -1) ? -errno : bytes_written;
1808 }
1809 
1811 template <class OS>
1814  VPtr<> start, typename OS::size_t length, int prot,
1815  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1816 {
1817  auto page_size = tc->getProcessPtr()->pTable->pageSize();
1818  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
1819  tgt_fd, offset * page_size);
1820 }
1821 
1823 template <class OS>
1826  unsigned resource, VPtr<typename OS::rlimit> rlp)
1827 {
1828  const ByteOrder bo = OS::byteOrder;
1829  switch (resource) {
1830  case OS::TGT_RLIMIT_STACK:
1831  // max stack size in bytes: make up a number (8MiB for now)
1832  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1833  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1834  rlp->rlim_max = htog(rlp->rlim_max, bo);
1835  break;
1836 
1837  case OS::TGT_RLIMIT_DATA:
1838  // max data segment size in bytes: make up a number
1839  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1840  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1841  rlp->rlim_max = htog(rlp->rlim_max, bo);
1842  break;
1843 
1844  case OS::TGT_RLIMIT_NPROC:
1845  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
1846  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1847  rlp->rlim_max = htog(rlp->rlim_max, bo);
1848  break;
1849 
1850  default:
1851  warn("getrlimit: unimplemented resource %d", resource);
1852  return -EINVAL;
1853  break;
1854  }
1855 
1856  return 0;
1857 }
1858 
1859 template <class OS>
1862  int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
1863 {
1864  if (pid != 0) {
1865  warn("prlimit: ignoring rlimits for nonzero pid");
1866  return -EPERM;
1867  }
1868  if (n)
1869  warn("prlimit: ignoring new rlimit");
1870  if (rlp) {
1871  const ByteOrder bo = OS::byteOrder;
1872  switch (resource) {
1873  case OS::TGT_RLIMIT_STACK:
1874  // max stack size in bytes: make up a number (8MiB for now)
1875  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1876  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1877  rlp->rlim_max = htog(rlp->rlim_max, bo);
1878  break;
1879  case OS::TGT_RLIMIT_DATA:
1880  // max data segment size in bytes: make up a number
1881  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1882  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1883  rlp->rlim_max = htog(rlp->rlim_max, bo);
1884  break;
1885  default:
1886  warn("prlimit: unimplemented resource %d", resource);
1887  return -EINVAL;
1888  break;
1889  }
1890  }
1891  return 0;
1892 }
1893 
1895 template <class OS>
1898  int clk_id, VPtr<typename OS::timespec> tp)
1899 {
1900  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1901  tp->tv_sec += seconds_since_epoch;
1902  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1903  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
1904 
1905  return 0;
1906 }
1907 
1909 template <class OS>
1913 {
1914  // Set resolution at ns, which is what clock_gettime() returns
1915  tp->tv_sec = 0;
1916  tp->tv_nsec = 1;
1917 
1918  return 0;
1919 }
1920 
1922 template <class OS>
1926 {
1927  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1928  tp->tv_sec += seconds_since_epoch;
1929  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1930  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
1931 
1932  return 0;
1933 }
1934 
1935 
1937 template <class OS>
1940  VPtr<typename OS::timeval [2]> tp)
1941 {
1942  std::string path;
1943  auto process = tc->getProcessPtr();
1944 
1945  if (!tc->getVirtProxy().tryReadString(path, pathname))
1946  return -EFAULT;
1947 
1948  struct timeval hostTimeval[2];
1949  for (int i = 0; i < 2; ++i) {
1950  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
1951  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
1952  }
1953 
1954  // Adjust path for cwd and redirection
1955  path = process->checkPathRedirect(path);
1956 
1957  int result = utimes(path.c_str(), hostTimeval);
1958 
1959  if (result < 0)
1960  return -errno;
1961 
1962  return 0;
1963 }
1964 
1965 template <class OS>
1968  VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
1969 {
1970  auto p = tc->getProcessPtr();
1971 
1972  std::string path;
1973  PortProxy & mem_proxy = tc->getVirtProxy();
1974  if (!mem_proxy.tryReadString(path, pathname))
1975  return -EFAULT;
1976 
1977  if (access(path.c_str(), F_OK) == -1)
1978  return -EACCES;
1979 
1980  auto read_in = [](std::vector<std::string> &vect,
1981  PortProxy &mem_proxy, VPtr<> mem_loc)
1982  {
1983  for (int inc = 0; ; inc++) {
1984  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
1985  b.copyIn(mem_proxy);
1986 
1987  if (!*(Addr*)b.bufferPtr())
1988  break;
1989 
1990  vect.push_back(std::string());
1991  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
1992  }
1993  };
1994 
2001  ProcessParams *pp = new ProcessParams();
2002  pp->executable = path;
2003  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2004  read_in(pp->env, mem_proxy, envp_mem_loc);
2005  pp->uid = p->uid();
2006  pp->egid = p->egid();
2007  pp->euid = p->euid();
2008  pp->gid = p->gid();
2009  pp->ppid = p->ppid();
2010  pp->pid = p->pid();
2011  pp->input.assign("cin");
2012  pp->output.assign("cout");
2013  pp->errout.assign("cerr");
2014  pp->cwd.assign(p->tgtCwd);
2015  pp->system = p->system;
2024  p->system->PIDs.erase(p->pid());
2025  Process *new_p = pp->create();
2026  delete pp;
2027 
2032  new_p->fds = p->fds;
2033  for (int i = 0; i < new_p->fds->getSize(); i++) {
2034  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2035  if (fdep && fdep->getCOE())
2036  new_p->fds->closeFDEntry(i);
2037  }
2038 
2039  *new_p->sigchld = true;
2040 
2041  delete p;
2042  tc->clearArchRegs();
2043  tc->setProcessPtr(new_p);
2044  new_p->assignThreadContext(tc->contextId());
2045  new_p->initState();
2046  tc->activate();
2047  TheISA::PCState pcState = tc->pcState();
2048  tc->setNPC(pcState.instAddr());
2049 
2050  return SyscallReturn();
2051 }
2052 
2054 template <class OS>
2057  int who /* THREAD, SELF, or CHILDREN */,
2059 {
2060  rup->ru_utime.tv_sec = 0;
2061  rup->ru_utime.tv_usec = 0;
2062  rup->ru_stime.tv_sec = 0;
2063  rup->ru_stime.tv_usec = 0;
2064  rup->ru_maxrss = 0;
2065  rup->ru_ixrss = 0;
2066  rup->ru_idrss = 0;
2067  rup->ru_isrss = 0;
2068  rup->ru_minflt = 0;
2069  rup->ru_majflt = 0;
2070  rup->ru_nswap = 0;
2071  rup->ru_inblock = 0;
2072  rup->ru_oublock = 0;
2073  rup->ru_msgsnd = 0;
2074  rup->ru_msgrcv = 0;
2075  rup->ru_nsignals = 0;
2076  rup->ru_nvcsw = 0;
2077  rup->ru_nivcsw = 0;
2078 
2079  switch (who) {
2080  case OS::TGT_RUSAGE_SELF:
2081  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2082  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2083  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2084  break;
2085 
2086  case OS::TGT_RUSAGE_CHILDREN:
2087  // do nothing. We have no child processes, so they take no time.
2088  break;
2089 
2090  default:
2091  // don't really handle THREAD or CHILDREN, but just warn and
2092  // plow ahead
2093  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2094  who);
2095  }
2096 
2097  return 0;
2098 }
2099 
2101 template <class OS>
2104 {
2105  // Fill in the time structure (in clocks)
2106  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
2107  bufp->tms_utime = clocks;
2108  bufp->tms_stime = 0;
2109  bufp->tms_cutime = 0;
2110  bufp->tms_cstime = 0;
2111 
2112  // Convert to host endianness
2113  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2114 
2115  // Return clock ticks since system boot
2116  return clocks;
2117 }
2118 
2120 template <class OS>
2123 {
2124  typename OS::time_t sec, usec;
2125  getElapsedTimeMicro(sec, usec);
2126  sec += seconds_since_epoch;
2127 
2128  if (taddr != 0) {
2129  typename OS::time_t t = sec;
2130  t = htog(t, OS::byteOrder);
2131  PortProxy &p = tc->getVirtProxy();
2132  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2133  }
2134  return sec;
2135 }
2136 
2137 template <class OS>
2139 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2140 {
2156  System *sys = tc->getSystemPtr();
2157  Process *tgt_proc = nullptr;
2158  for (auto *tc: sys->threads) {
2159  Process *temp = tc->getProcessPtr();
2160  if (temp->pid() == tid) {
2161  tgt_proc = temp;
2162  break;
2163  }
2164  }
2165 
2166  if (sig != 0 || sig != OS::TGT_SIGABRT)
2167  return -EINVAL;
2168 
2169  if (tgt_proc == nullptr)
2170  return -ESRCH;
2171 
2172  if (tgid != -1 && tgt_proc->tgid() != tgid)
2173  return -ESRCH;
2174 
2175  if (sig == OS::TGT_SIGABRT)
2176  exitGroupFunc(desc, tc, 0);
2177 
2178  return 0;
2179 }
2180 
2181 template <class OS>
2184  int domain, int type, int prot)
2185 {
2186  auto p = tc->getProcessPtr();
2187 
2188  int sim_fd = socket(domain, type, prot);
2189  if (sim_fd == -1)
2190  return -errno;
2191 
2192  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2193  int tgt_fd = p->fds->allocFD(sfdp);
2194 
2195  return tgt_fd;
2196 }
2197 
2198 template <class OS>
2201  int domain, int type, int prot, VPtr<> svPtr)
2202 {
2203  auto p = tc->getProcessPtr();
2204 
2205  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2206  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2207  if (status == -1)
2208  return -errno;
2209 
2210  int *fds = (int *)svBuf.bufferPtr();
2211 
2212  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2213  fds[0] = p->fds->allocFD(sfdp1);
2214  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2215  fds[1] = p->fds->allocFD(sfdp2);
2216  svBuf.copyOut(tc->getVirtProxy());
2217 
2218  return status;
2219 }
2220 
2221 template <class OS>
2223 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2224  VPtr<typename OS::fd_set> readfds,
2225  VPtr<typename OS::fd_set> writefds,
2226  VPtr<typename OS::fd_set> errorfds,
2228 {
2229  int retval;
2230 
2231  auto p = tc->getProcessPtr();
2232 
2238  fd_set readfds_h;
2239  FD_ZERO(&readfds_h);
2240  fd_set writefds_h;
2241  FD_ZERO(&writefds_h);
2242  fd_set errorfds_h;
2243  FD_ZERO(&errorfds_h);
2244 
2254  int nfds_h = 0;
2255  std::map<int, int> trans_map;
2256  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2257  fd_set *hst_set_entry,
2258  int iter) -> bool
2259  {
2265  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2271  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2272  if (!hbfdp)
2273  return true;
2274  auto sim_fd = hbfdp->getSimFD();
2275 
2281  trans_map[sim_fd] = iter;
2282 
2288  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2289 
2294  FD_SET(sim_fd, hst_set_entry);
2295  }
2296  return false;
2297  };
2298 
2299  for (int i = 0; i < nfds; i++) {
2300  if (readfds) {
2301  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2302  if (ebadf)
2303  return -EBADF;
2304  }
2305  if (writefds) {
2306  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2307  if (ebadf)
2308  return -EBADF;
2309  }
2310  if (errorfds) {
2311  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2312  if (ebadf)
2313  return -EBADF;
2314  }
2315  }
2316 
2317  if (timeout) {
2325  timeout->tv_sec = 0;
2326  timeout->tv_usec = 0;
2327 
2328  retval = select(nfds_h,
2329  readfds ? &readfds_h : nullptr,
2330  writefds ? &writefds_h : nullptr,
2331  errorfds ? &errorfds_h : nullptr,
2332  (timeval *)(typename OS::timeval *)timeout);
2333  } else {
2341  struct timeval tv = { 0, 0 };
2342 
2343  retval = select(nfds_h,
2344  readfds ? &readfds_h : nullptr,
2345  readfds ? &writefds_h : nullptr,
2346  readfds ? &errorfds_h : nullptr,
2347  &tv);
2348 
2349  if (retval == 0) {
2355  for (auto sig : tc->getSystemPtr()->signalList)
2356  if (sig.receiver == p)
2357  return -EINTR;
2358  return SyscallReturn::retry();
2359  }
2360  }
2361 
2362  if (retval == -1)
2363  return -errno;
2364 
2365  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2366  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2367  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2368 
2374  for (int i = 0; i < nfds_h; i++) {
2375  if (readfds && FD_ISSET(i, &readfds_h))
2376  FD_SET(trans_map[i], readfds);
2377 
2378  if (writefds && FD_ISSET(i, &writefds_h))
2379  FD_SET(trans_map[i], writefds);
2380 
2381  if (errorfds && FD_ISSET(i, &errorfds_h))
2382  FD_SET(trans_map[i], errorfds);
2383  }
2384 
2385  return retval;
2386 }
2387 
2388 template <class OS>
2391  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2392 {
2393  auto p = tc->getProcessPtr();
2394 
2395  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2396  if (!hbfdp)
2397  return -EBADF;
2398  int sim_fd = hbfdp->getSimFD();
2399 
2400  struct pollfd pfd;
2401  pfd.fd = sim_fd;
2402  pfd.events = POLLIN | POLLPRI;
2403  if ((poll(&pfd, 1, 0) == 0)
2404  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2405  return SyscallReturn::retry();
2406 
2407  BufferArg buf_arg(buf_ptr, nbytes);
2408  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2409 
2410  if (bytes_read > 0)
2411  buf_arg.copyOut(tc->getVirtProxy());
2412 
2413  return (bytes_read == -1) ? -errno : bytes_read;
2414 }
2415 
2416 template <class OS>
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  BufferArg buf_arg(buf_ptr, nbytes);
2429  buf_arg.copyIn(tc->getVirtProxy());
2430 
2431  struct pollfd pfd;
2432  pfd.fd = sim_fd;
2433  pfd.events = POLLOUT;
2434 
2441  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2442  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2443  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2444  return SyscallReturn::retry();
2445  }
2446 
2447  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2448 
2449  if (bytes_written != -1)
2450  fsync(sim_fd);
2451 
2452  return (bytes_written == -1) ? -errno : bytes_written;
2453 }
2454 
2455 template <class OS>
2458  pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2459 {
2460  auto p = tc->getProcessPtr();
2461 
2462  if (rusagePtr)
2463  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2464  "functionality not supported. Ignoring rusage pointer.\n",
2465  rusagePtr);
2466 
2475  System *sysh = tc->getSystemPtr();
2477  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2478  if (iter->receiver == p) {
2479  if (pid < -1) {
2480  if ((iter->sender->pgid() == -pid)
2481  && (iter->signalValue == OS::TGT_SIGCHLD))
2482  goto success;
2483  } else if (pid == -1) {
2484  if (iter->signalValue == OS::TGT_SIGCHLD)
2485  goto success;
2486  } else if (pid == 0) {
2487  if ((iter->sender->pgid() == p->pgid())
2488  && (iter->signalValue == OS::TGT_SIGCHLD))
2489  goto success;
2490  } else {
2491  if ((iter->sender->pid() == pid)
2492  && (iter->signalValue == OS::TGT_SIGCHLD))
2493  goto success;
2494  }
2495  }
2496  }
2497 
2498  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2499 
2500 success:
2501  // Set status to EXITED for WIFEXITED evaluations.
2502  const int EXITED = 0;
2503  BufferArg statusBuf(statPtr, sizeof(int));
2504  *(int *)statusBuf.bufferPtr() = EXITED;
2505  statusBuf.copyOut(tc->getVirtProxy());
2506 
2507  // Return the child PID.
2508  pid_t retval = iter->sender->pid();
2509  sysh->signalList.erase(iter);
2510  return retval;
2511 }
2512 
2513 template <class OS>
2516  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2517 {
2518  struct sockaddr sa;
2519  socklen_t addrLen;
2520  int host_fd;
2521  auto p = tc->getProcessPtr();
2522 
2523  BufferArg *lenBufPtr = nullptr;
2524  BufferArg *addrBufPtr = nullptr;
2525 
2526  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2527  if (!sfdp)
2528  return -EBADF;
2529  int sim_fd = sfdp->getSimFD();
2530 
2537  struct pollfd pfd;
2538  pfd.fd = sim_fd;
2539  pfd.events = POLLIN | POLLPRI;
2540  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2541  return SyscallReturn::retry();
2542 
2543  if (lenPtr) {
2544  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2545  lenBufPtr->copyIn(tc->getVirtProxy());
2546  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2547  sizeof(socklen_t));
2548  }
2549 
2550  if (addrPtr) {
2551  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2552  addrBufPtr->copyIn(tc->getVirtProxy());
2553  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2554  sizeof(struct sockaddr));
2555  }
2556 
2557  host_fd = accept(sim_fd, &sa, &addrLen);
2558 
2559  if (host_fd == -1)
2560  return -errno;
2561 
2562  if (addrPtr) {
2563  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2564  addrBufPtr->copyOut(tc->getVirtProxy());
2565  delete(addrBufPtr);
2566  }
2567 
2568  if (lenPtr) {
2569  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2570  lenBufPtr->copyOut(tc->getVirtProxy());
2571  delete(lenBufPtr);
2572  }
2573 
2574  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2575  sfdp->_type, sfdp->_protocol);
2576  return p->fds->allocFD(afdp);
2577 }
2578 
2580 template <class OS>
2583  unsigned initval, int in_flags)
2584 {
2585 #if defined(__linux__)
2586  auto p = tc->getProcessPtr();
2587 
2588  int sim_fd = eventfd(initval, in_flags);
2589  if (sim_fd == -1)
2590  return -errno;
2591 
2592  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2593 
2594  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2595  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2596 
2597  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2598  int tgt_fd = p->fds->allocFD(hbfdp);
2599  return tgt_fd;
2600 #else
2601  warnUnsupportedOS("eventfd");
2602  return -1;
2603 #endif
2604 }
2605 
2606 #endif // __SIM_SYSCALL_EMUL_HH__
System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:614
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2418
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:62
ArmISA::status
Bitfield< 5, 0 > status
Definition: miscregs_types.hh:417
getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1591
dup2Func
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Definition: syscall_emul.cc:689
chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
Definition: syscall_emul.cc:1028
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.
SimClock::Int::ns
Tick ns
nanosecond
Definition: core.cc:62
getrusageFunc
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
Definition: syscall_emul.hh:2056
warn
#define warn(...)
Definition: logging.hh:239
linux.hh
ThreadContext::setUseForClone
void setUseForClone(bool new_val)
Definition: thread_context.hh:97
tgkillFunc
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
Definition: syscall_emul.hh:2139
ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
Definition: syscall_emul.hh:678
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:68
execveFunc
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
Definition: syscall_emul.hh:1967
readvFunc
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target readv() handler.
Definition: syscall_emul.hh:1558
ThreadContext::activate
virtual void activate()=0
Set the status to Active.
fstatfsFunc
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
Definition: syscall_emul.hh:1534
symlinkFunc
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
Definition: syscall_emul.cc:484
warnUnsupportedOS
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:57
rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:1055
MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:44
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:1278
ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:430
Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:271
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:1236
Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:117
warn_once
#define warn_once(...)
Definition: logging.hh:243
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
openatFunc
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:753
Process
Definition: process.hh:65
accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:997
ProxyPtr
Definition: proxy_ptr.hh:235
FutexMap::suspend_bitset
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
Definition: futex_map.cc:98
brkFunc
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
Definition: syscall_emul.cc:246
ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:159
stat64Func
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
Definition: syscall_emul.hh:1204
getpgrpFunc
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Definition: syscall_emul.cc:885
ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:70
tlb.hh
gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:1924
unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname)
Target unlinkat() handler.
Definition: syscall_emul.hh:912
acceptFunc
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.hh:2515
Loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:115
SimClock::Int::us
Tick us
microsecond
Definition: core.cc:61
Process::pTable
EmulationPageTable * pTable
Definition: process.hh:169
futex_map.hh
chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:975
faccessatFunc
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int mode)
Target facessat() handler.
Definition: syscall_emul.hh:923
FutexMap
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:90
PowerISA::bo
Bitfield< 25, 21 > bo
Definition: types.hh:62
System::maxPID
static const int maxPID
Definition: system.hh:607
X86ISA::op
Bitfield< 4 > op
Definition: types.hh:79
std::vector< std::string >
proxy_ptr.hh
wait4Func
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
Definition: syscall_emul.hh:2457
ThreadContext::getProcessPtr
virtual Process * getProcessPtr()=0
X86ISA::count
count
Definition: misc.hh:703
syscall_emul_buf.hh
pwrite64Func
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1792
copyOutStatBuf
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:563
pread64Func
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1771
setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:892
hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:554
_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:301
copyOutStatfsBuf
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
Definition: syscall_emul.hh:634
getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:940
ThreadContext::threadId
virtual int threadId() const =0
System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:155
sc_dt::inc
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:341
fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Definition: syscall_emul.cc:975
socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2183
pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:794
timesFunc
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
Definition: syscall_emul.hh:2103
PortProxy::writeBlob
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:187
GuestABI::VarArgs::get
Arg get()
Definition: varargs.hh:161
ArmISA::n
Bitfield< 31 > n
Definition: miscregs_types.hh:450
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:254
Process::tgid
uint64_t tgid()
Definition: process.hh:88
EmulatedDriver
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1448
utimesFunc
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
Definition: syscall_emul.hh:1939
Loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:40
cp
Definition: cprintf.cc:37
ThreadContext::clearArchRegs
virtual void clearArchRegs()=0
mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:1013
unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
Definition: syscall_emul.cc:448
getElapsedTimeNano
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Definition: syscall_emul.hh:532
ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
Definition: syscall_emul.cc:558
syscall_return.hh
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
timeFunc
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
Definition: syscall_emul.hh:2122
SyscallDesc::name
std::string name() const
Definition: syscall_desc.hh:76
socketpairFunc
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
Definition: syscall_emul.hh:2200
GuestABI::VarArgs
Definition: varargs.hh:146
System
Definition: system.hh:73
exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:233
setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1618
Process::checkPathRedirect
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:404
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:1218
lseekFunc
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Definition: syscall_emul.cc:284
getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:968
System::futexMap
FutexMap futexMap
Definition: system.hh:605
DPRINTF_SYSCALL
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
Definition: syscall_debug_macros.hh:57
exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:227
htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:156
ArmISA::sa
Bitfield< 3 > sa
Definition: miscregs_types.hh:386
linkFunc
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
Definition: syscall_emul.cc:463
listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1182
Process::sigchld
bool * sigchld
Definition: process.hh:283
readlinkatFunc
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf, size_t bufsiz)
Target readlinkat() handler.
Definition: syscall_emul.hh:934
setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:268
SimClock::Int::s
Tick s
second
Definition: core.cc:59
process.hh
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:926
openFunc
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:902
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:1813
statfsFunc
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
Definition: syscall_emul.hh:1384
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:2223
ThreadContext::cpuId
virtual int cpuId() const =0
X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:582
sysinfoFunc
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
Definition: syscall_emul.hh:960
System::Threads::size
int size() const
Definition: system.hh:204
ThreadContext::contextId
virtual ContextID contextId() const =0
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:1897
fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:644
cloneFunc
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
Definition: syscall_emul.hh:1413
getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:961
ThreadContext::setNPC
void setNPC(Addr val)
Definition: thread_context.hh:265
X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:612
ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:593
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
mremapFunc
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags, GuestABI::VarArgs< uint64_t > varargs)
Target mremap() handler.
Definition: syscall_emul.hh:1094
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:95
SyscallReturn
This class represents the return value from an emulated system call, including any errno setting.
Definition: syscall_return.hh:52
connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1197
eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2582
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:1911
BaseBufferArg::copyIn
bool copyIn(PortProxy &memproxy)
copy data into simulator space (read from target memory)
Definition: syscall_emul_buf.hh:77
munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length)
Target munmap() handler.
Definition: syscall_emul.cc:328
lstatFunc
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
Definition: syscall_emul.hh:1301
BufferArg::bufferPtr
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Definition: syscall_emul_buf.hh:115
getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:1825
ThreadContext::pcState
virtual TheISA::PCState pcState() const =0
recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1310
lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1327
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:788
X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:80
ThreadContext::getVirtProxy
virtual PortProxy & getVirtProxy()=0
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:150
X86ISA::level
Bitfield< 20 > level
Definition: intmessage.hh:47
copyOutStat64Buf
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:612
System::threads
Threads threads
Definition: system.hh:304
hst_statfs
struct statfs hst_statfs
Definition: syscall_emul.hh:548
truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:572
PortProxy
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition: port_proxy.hh:80
ArmISA::b
Bitfield< 7 > b
Definition: miscregs_types.hh:376
fcntlFunc
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, GuestABI::VarArgs< int > varargs)
Target fcntl() handler.
Definition: syscall_emul.cc:717
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...
base.hh
fstatFunc
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
Definition: syscall_emul.hh:1358
getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1639
MipsISA::PCState
GenericISA::DelaySlotPCState< MachInst > PCState
Definition: types.hh:41
types.hh
ArmISA::t
Bitfield< 5 > t
Definition: miscregs_types.hh:67
startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:239
ArmISA::domain
Bitfield< 7, 4 > domain
Definition: miscregs_types.hh:418
Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:277
roundUp
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:623
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:77
FutexMap::wakeup_bitset
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition: futex_map.cc:117
cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
Definition: syscall_emul.hh:1524
getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:239
ArmISA::len
Bitfield< 18, 16 > len
Definition: miscregs_types.hh:439
guest_abi.hh
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...
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:376
geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:954
logging.hh
statFunc
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
Definition: syscall_emul.hh:1177
getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:519
emul_driver.hh
writevFunc
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target writev() handler.
Definition: syscall_emul.hh:1595
truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, off_t length)
Target truncate() handler.
Definition: syscall_emul.cc:541
hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:553
X86ISA::type
type
Definition: misc.hh:727
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
trace.hh
gettidFunc
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Definition: syscall_emul.cc:933
gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:163
Loader::SymbolTable::insert
bool insert(const Symbol &symbol)
Definition: symtab.cc:51
getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:947
fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:759
renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
Definition: syscall_emul.cc:519
fchmodFunc
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
Definition: syscall_emul.hh:1075
SyscallReturn::retry
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Definition: syscall_return.hh:77
shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1146
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:800
std::list
STL list class.
Definition: stl.hh:51
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:1629
intmath.hh
BufferArg
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Definition: syscall_emul_buf.hh:103
closeFunc
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
Definition: syscall_emul.cc:277
fstat64Func
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
Definition: syscall_emul.hh:1271
mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:505
renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
Definition: syscall_emul.hh:945
getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1515
page_table.hh
seconds_since_epoch
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
Definition: syscall_emul.hh:513
gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:350
bindFunc
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1161
readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf, size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.cc:390
PortProxy::readBlob
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:177
EmulationPageTable::pageSize
Addr pageSize()
Definition: page_table.hh:110
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:100
object_file.hh
getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1554
getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:360
unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:63
thread_context.hh
RegVal
uint64_t RegVal
Definition: types.hh:174
readFunc
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2390
Process::pid
uint64_t pid()
Definition: process.hh:84
SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:66
prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:1861
syscall_desc.hh
pollFunc
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
Definition: syscall_emul.hh:1001
ThreadContext::setProcessPtr
virtual void setProcessPtr(Process *p)=0
ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
BaseBufferArg::copyOut
bool copyOut(PortProxy &memproxy)
copy data out of simulator space (write to target memory)
Definition: syscall_emul_buf.hh:87
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
dupFunc
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target dup() handler.
Definition: syscall_emul.cc:669

Generated on Tue Mar 23 2021 19:41:28 for gem5 by doxygen 1.8.17