gem5  v20.0.0.3
syscall_emul.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2015, 2019 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 "mem/page_table.hh"
99 #include "params/Process.hh"
100 #include "sim/emul_driver.hh"
101 #include "sim/futex_map.hh"
102 #include "sim/guest_abi.hh"
103 #include "sim/process.hh"
105 #include "sim/syscall_desc.hh"
106 #include "sim/syscall_emul_buf.hh"
107 #include "sim/syscall_return.hh"
108 
109 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
110 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
111 #endif
112 
114 //
115 // The following emulation functions are generic enough that they
116 // don't need to be recompiled for different emulated OS's. They are
117 // defined in sim/syscall_emul.cc.
118 //
120 
121 void warnUnsupportedOS(std::string syscall_name);
122 
125 
134 
135 // Target fallocateFunc() handler.
137  int tgt_fd, int mode, off_t offset, off_t len);
138 
141 
144 
147  uint64_t tidPtr);
148 
151 
153 SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk);
154 
156 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
157 
160  int tgt_fd, uint64_t offs, int whence);
161 
164  int tgt_fd, uint64_t offset_high,
165  uint32_t offset_low, Addr result_ptr, int whence);
166 
169  size_t length);
170 
173  int tgt_fd, int how);
174 
177  Addr buf_ptr, int name_len);
178 
181  Addr buf_ptr, unsigned long size);
182 
185  Addr pathname, Addr buf, size_t bufsiz);
186 
189 
192  Addr pathname, Addr new_pathname);
193 
196  Addr pathname, Addr new_pathname);
197 
200  Addr pathname, mode_t mode);
201 
204  Addr pathname, mode_t mode, dev_t dev);
205 
208 
209 // Target rmdir() handler.
211 
214  Addr oldpath, Addr newpath);
215 
216 
219  Addr pathname, off_t length);
220 
221 
224  int tgt_fd, off_t length);
225 
226 
229  Addr pathname, int64_t length);
230 
233  int tgt_fd, int64_t length);
234 
237 
240 
243  Addr pathname, uint32_t owner, uint32_t group);
244 
247 
250  int pid, int pgid);
251 
254  int tgt_fd, uint32_t owner, uint32_t group);
255 
258  int tgt_fd);
259 
262  int old_tgt_fd, int new_tgt_fd);
263 
266  int tgt_fd, int cmd, GuestABI::VarArgs<int> varargs);
267 
270  int tgt_fd, int cmd);
271 
273 SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr);
274 
277  Addr tgt_addr, int flags);
278 
281 
282 // Target getpeername() handler.
284  int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr);
285 
286 // Target bind() handler.
288  int tgt_fd, Addr buf_ptr, int addrlen);
289 
290 // Target listen() handler.
292  int tgt_fd, int backlog);
293 
294 // Target connect() handler.
296  int tgt_fd, Addr buf_ptr, int addrlen);
297 
298 #if defined(SYS_getdents)
299 // Target getdents() handler.
300 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
301  int tgt_fd, Addr buf_ptr, unsigned count);
302 #endif
303 
304 #if defined(SYS_getdents64)
305 // Target getdents() handler.
306 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
307  int tgt_fd, Addr buf_ptr, unsigned count);
308 #endif
309 
310 // Target sendto() handler.
312  int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags,
313  Addr addrPtr, socklen_t addrLen);
314 
315 // Target recvfrom() handler.
317  int tgt_fd, Addr bufrPtr, size_t bufrLen,
318  int flags, Addr addrPtr, Addr addrlenPtr);
319 
320 // Target recvmsg() handler.
322  int tgt_fd, Addr msgPtr, int flags);
323 
324 // Target sendmsg() handler.
326  int tgt_fd, Addr msgPtr, int flags);
327 
328 // Target getuid() handler.
330 
333 
336 
339 
342 
345  Addr pathname, mode_t mode);
346 
347 // Target getsockopt() handler.
349  int tgt_fd, int level, int optname,
350  Addr valPtr, Addr lenPtr);
351 
352 // Target setsockopt() handler.
354  int tgt_fd, int level, int optname,
355  Addr valPtr, socklen_t len);
356 
357 // Target getsockname() handler.
359  int tgt_fd, Addr addrPtr, Addr lenPtr);
360 
364 template <class OS>
367  Addr uaddr, int op, int val, int timeout, Addr uaddr2, int val3)
368 {
369  using namespace std;
370 
371  auto process = tc->getProcessPtr();
372 
373  /*
374  * Unsupported option that does not affect the correctness of the
375  * application. This is a performance optimization utilized by Linux.
376  */
377  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
378  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
379 
380  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
381 
382  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
383  // Ensure futex system call accessed atomically.
384  BufferArg buf(uaddr, sizeof(int));
385  buf.copyIn(tc->getVirtProxy());
386  int mem_val = *(int*)buf.bufferPtr();
387 
388  /*
389  * The value in memory at uaddr is not equal with the expected val
390  * (a different thread must have changed it before the system call was
391  * invoked). In this case, we need to throw an error.
392  */
393  if (val != mem_val)
394  return -OS::TGT_EWOULDBLOCK;
395 
396  if (OS::TGT_FUTEX_WAIT == op) {
397  futex_map.suspend(uaddr, process->tgid(), tc);
398  } else {
399  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
400  }
401 
402  return 0;
403  } else if (OS::TGT_FUTEX_WAKE == op) {
404  return futex_map.wakeup(uaddr, process->tgid(), val);
405  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
406  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
407  } else if (OS::TGT_FUTEX_REQUEUE == op ||
408  OS::TGT_FUTEX_CMP_REQUEUE == op) {
409 
410  // Ensure futex system call accessed atomically.
411  BufferArg buf(uaddr, sizeof(int));
412  buf.copyIn(tc->getVirtProxy());
413  int mem_val = *(int*)buf.bufferPtr();
414  /*
415  * For CMP_REQUEUE, the whole operation is only started only if
416  * val3 is still the value of the futex pointed to by uaddr.
417  */
418  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
419  return -OS::TGT_EWOULDBLOCK;
420  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
421  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
422  /*
423  * The FUTEX_WAKE_OP operation is equivalent to executing the
424  * following code atomically and totally ordered with respect to
425  * other futex operations on any of the two supplied futex words:
426  *
427  * int oldval = *(int *) addr2;
428  * *(int *) addr2 = oldval op oparg;
429  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
430  * if (oldval cmp cmparg)
431  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
432  *
433  * (op, oparg, cmp, cmparg are encoded in val3)
434  *
435  * +---+---+-----------+-----------+
436  * |op |cmp| oparg | cmparg |
437  * +---+---+-----------+-----------+
438  * 4 4 12 12 <== # of bits
439  *
440  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
441  *
442  */
443  // get value from simulated-space
444  BufferArg buf(uaddr2, sizeof(int));
445  buf.copyIn(tc->getVirtProxy());
446  int oldval = *(int*)buf.bufferPtr();
447  int newval = oldval;
448  // extract op, oparg, cmp, cmparg from val3
449  int wake_cmparg = val3 & 0xfff;
450  int wake_oparg = (val3 & 0xfff000) >> 12;
451  int wake_cmp = (val3 & 0xf000000) >> 24;
452  int wake_op = (val3 & 0xf0000000) >> 28;
453  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
454  wake_oparg = (1 << wake_oparg);
455  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
456  // perform operation on the value of the second futex
457  if (wake_op == OS::TGT_FUTEX_OP_SET)
458  newval = wake_oparg;
459  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
460  newval += wake_oparg;
461  else if (wake_op == OS::TGT_FUTEX_OP_OR)
462  newval |= wake_oparg;
463  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
464  newval &= ~wake_oparg;
465  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
466  newval ^= wake_oparg;
467  // copy updated value back to simulated-space
468  *(int*)buf.bufferPtr() = newval;
469  buf.copyOut(tc->getVirtProxy());
470  // perform the first wake-up
471  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
472  int woken2 = 0;
473  // calculate the condition of the second wake-up
474  bool is_wake2 = false;
475  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
476  is_wake2 = oldval == wake_cmparg;
477  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
478  is_wake2 = oldval != wake_cmparg;
479  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
480  is_wake2 = oldval < wake_cmparg;
481  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
482  is_wake2 = oldval <= wake_cmparg;
483  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
484  is_wake2 = oldval > wake_cmparg;
485  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
486  is_wake2 = oldval >= wake_cmparg;
487  // perform the second wake-up
488  if (is_wake2)
489  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
490 
491  return woken1 + woken2;
492  }
493  warn("futex: op %d not implemented; ignoring.", op);
494  return -ENOSYS;
495 }
496 
500 
501 
505 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
506 
509 template <class T1, class T2>
510 void
511 getElapsedTimeMicro(T1 &sec, T2 &usec)
512 {
513  static const int OneMillion = 1000 * 1000;
514 
515  uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
516  sec = elapsed_usecs / OneMillion;
517  usec = elapsed_usecs % OneMillion;
518 }
519 
522 template <class T1, class T2>
523 void
524 getElapsedTimeNano(T1 &sec, T2 &nsec)
525 {
526  static const int OneBillion = 1000 * 1000 * 1000;
527 
528  uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
529  sec = elapsed_nsecs / OneBillion;
530  nsec = elapsed_nsecs % OneBillion;
531 }
532 
534 //
535 // The following emulation functions are generic, but need to be
536 // templated to account for differences in types, constants, etc.
537 //
539 
540  typedef struct statfs hst_statfs;
541 #if NO_STAT64
542  typedef struct stat hst_stat;
543  typedef struct stat hst_stat64;
544 #else
545  typedef struct stat hst_stat;
546  typedef struct stat64 hst_stat64;
547 #endif
548 
552 
553 template <typename target_stat, typename host_stat>
554 void
555 convertStatBuf(target_stat &tgt, host_stat *host,
556  ByteOrder bo, bool fakeTTY=false)
557 {
558  if (fakeTTY)
559  tgt->st_dev = 0xA;
560  else
561  tgt->st_dev = host->st_dev;
562  tgt->st_dev = htog(tgt->st_dev, bo);
563  tgt->st_ino = host->st_ino;
564  tgt->st_ino = htog(tgt->st_ino, bo);
565  tgt->st_mode = host->st_mode;
566  if (fakeTTY) {
567  // Claim to be a character device
568  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
569  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
570  }
571  tgt->st_mode = htog(tgt->st_mode, bo);
572  tgt->st_nlink = host->st_nlink;
573  tgt->st_nlink = htog(tgt->st_nlink, bo);
574  tgt->st_uid = host->st_uid;
575  tgt->st_uid = htog(tgt->st_uid, bo);
576  tgt->st_gid = host->st_gid;
577  tgt->st_gid = htog(tgt->st_gid, bo);
578  if (fakeTTY)
579  tgt->st_rdev = 0x880d;
580  else
581  tgt->st_rdev = host->st_rdev;
582  tgt->st_rdev = htog(tgt->st_rdev, bo);
583  tgt->st_size = host->st_size;
584  tgt->st_size = htog(tgt->st_size, bo);
585  tgt->st_atimeX = host->st_atime;
586  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
587  tgt->st_mtimeX = host->st_mtime;
588  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
589  tgt->st_ctimeX = host->st_ctime;
590  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
591  // Force the block size to be 8KB. This helps to ensure buffered io works
592  // consistently across different hosts.
593  tgt->st_blksize = 0x2000;
594  tgt->st_blksize = htog(tgt->st_blksize, bo);
595  tgt->st_blocks = host->st_blocks;
596  tgt->st_blocks = htog(tgt->st_blocks, bo);
597 }
598 
599 // Same for stat64
600 
601 template <typename target_stat, typename host_stat64>
602 void
603 convertStat64Buf(target_stat &tgt, host_stat64 *host,
604  ByteOrder bo, bool fakeTTY=false)
605 {
606  convertStatBuf<target_stat, host_stat64>(tgt, host, bo, fakeTTY);
607 #if defined(STAT_HAVE_NSEC)
608  tgt->st_atime_nsec = host->st_atime_nsec;
609  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
610  tgt->st_mtime_nsec = host->st_mtime_nsec;
611  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
612  tgt->st_ctime_nsec = host->st_ctime_nsec;
613  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
614 #else
615  tgt->st_atime_nsec = 0;
616  tgt->st_mtime_nsec = 0;
617  tgt->st_ctime_nsec = 0;
618 #endif
619 }
620 
621 // Here are a couple of convenience functions
622 template<class OS>
623 void
625  hst_stat *host, bool fakeTTY = false)
626 {
627  typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
628  tgt_stat_buf tgt(addr);
629  convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, OS::byteOrder, fakeTTY);
630  tgt.copyOut(mem);
631 }
632 
633 template<class OS>
634 void
636  hst_stat64 *host, bool fakeTTY = false)
637 {
638  typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
639  tgt_stat_buf tgt(addr);
640  convertStat64Buf<tgt_stat_buf, hst_stat64>(
641  tgt, host, OS::byteOrder, fakeTTY);
642  tgt.copyOut(mem);
643 }
644 
645 template <class OS>
646 void
648  hst_statfs *host)
649 {
651 
652  const ByteOrder bo = OS::byteOrder;
653 
654  tgt->f_type = htog(host->f_type, bo);
655 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
656  tgt->f_bsize = htog(host->f_iosize, bo);
657 #else
658  tgt->f_bsize = htog(host->f_bsize, bo);
659 #endif
660  tgt->f_blocks = htog(host->f_blocks, bo);
661  tgt->f_bfree = htog(host->f_bfree, bo);
662  tgt->f_bavail = htog(host->f_bavail, bo);
663  tgt->f_files = htog(host->f_files, bo);
664  tgt->f_ffree = htog(host->f_ffree, bo);
665  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
666 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
667  tgt->f_namelen = htog(host->f_namemax, bo);
668  tgt->f_frsize = htog(host->f_bsize, bo);
669 #elif defined(__APPLE__)
670  tgt->f_namelen = 0;
671  tgt->f_frsize = 0;
672 #else
673  tgt->f_namelen = htog(host->f_namelen, bo);
674  tgt->f_frsize = htog(host->f_frsize, bo);
675 #endif
676 #if defined(__linux__)
677  memcpy(&tgt->f_spare, &host->f_spare, sizeof(host->f_spare));
678 #else
679  /*
680  * The fields are different sizes per OS. Don't bother with
681  * f_spare or f_reserved on non-Linux for now.
682  */
683  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
684 #endif
685 
686  tgt.copyOut(mem);
687 }
688 
693 template <class OS>
696  int tgt_fd, unsigned req, Addr addr)
697 {
698  auto p = tc->getProcessPtr();
699 
700  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
701 
702  if (OS::isTtyReq(req))
703  return -ENOTTY;
704 
705  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
706  if (dfdp) {
707  EmulatedDriver *emul_driver = dfdp->getDriver();
708  if (emul_driver)
709  return emul_driver->ioctl(tc, req, addr);
710  }
711 
712  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
713  if (sfdp) {
714  int status;
715 
716  switch (req) {
717  case SIOCGIFCONF: {
718  BufferArg conf_arg(addr, sizeof(ifconf));
719  conf_arg.copyIn(tc->getVirtProxy());
720 
721  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
722  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
723  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
724  ifc_buf_arg.copyIn(tc->getVirtProxy());
725 
726  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
727 
728  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
729  if (status != -1) {
730  conf->ifc_buf = (char*)ifc_buf_addr;
731  ifc_buf_arg.copyOut(tc->getVirtProxy());
732  conf_arg.copyOut(tc->getVirtProxy());
733  }
734 
735  return status;
736  }
737  case SIOCGIFFLAGS:
738 #if defined(__linux__)
739  case SIOCGIFINDEX:
740 #endif
741  case SIOCGIFNETMASK:
742  case SIOCGIFADDR:
743 #if defined(__linux__)
744  case SIOCGIFHWADDR:
745 #endif
746  case SIOCGIFMTU: {
747  BufferArg req_arg(addr, sizeof(ifreq));
748  req_arg.copyIn(tc->getVirtProxy());
749 
750  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
751  if (status != -1)
752  req_arg.copyOut(tc->getVirtProxy());
753  return status;
754  }
755  }
756  }
757 
762  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
763  tgt_fd, req, tc->pcState());
764  return -ENOTTY;
765 }
766 
768 template <class OS>
771  int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
772 {
773  auto p = tc->getProcessPtr();
774 
779  std::string path;
780  if (!tc->getVirtProxy().tryReadString(path, pathname))
781  return -EFAULT;
782 
783 #ifdef __CYGWIN32__
784  int host_flags = O_BINARY;
785 #else
786  int host_flags = 0;
787 #endif
788 
792  for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
793  if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
794  tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
795  host_flags |= OS::openFlagTable[i].hostFlag;
796  }
797  }
798  if (tgt_flags)
799  warn("%s: cannot decode flags %#x", desc->name(), tgt_flags);
800 
801 #ifdef __CYGWIN32__
802  host_flags |= O_BINARY;
803 #endif
804 
817  std::string redir_path = path;
818  std::string abs_path = path;
819  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
820  abs_path = p->absolutePath(path, true);
821  redir_path = p->checkPathRedirect(path);
822  } else if (!startswith(path, "/")) {
823  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
824  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
825  if (!ffdp)
826  return -EBADF;
827  abs_path = ffdp->getFileName() + path;
828  redir_path = p->checkPathRedirect(abs_path);
829  }
830 
837  if (startswith(abs_path, "/dev/")) {
838  std::string filename = abs_path.substr(strlen("/dev/"));
839  EmulatedDriver *drv = p->findDriver(filename);
840  if (drv) {
841  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
842  "driver open with path[%s]\n",
843  desc->name(), abs_path.c_str());
844  return drv->open(tc, mode, host_flags);
845  }
850  }
851 
876  int sim_fd = -1;
877  std::string used_path;
878  std::vector<std::string> special_paths =
879  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
880  "/proc/self/maps", "/dev/urandom",
881  "/sys/devices/system/cpu/online" };
882  for (auto entry : special_paths) {
883  if (startswith(path, entry)) {
884  sim_fd = OS::openSpecialFile(abs_path, p, tc);
885  used_path = abs_path;
886  }
887  }
888  if (sim_fd == -1) {
889  sim_fd = open(redir_path.c_str(), host_flags, mode);
890  used_path = redir_path;
891  }
892  if (sim_fd == -1) {
893  int local = -errno;
894  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
895  "(inferred from:%s)\n", desc->name(),
896  used_path.c_str(), path.c_str());
897  return local;
898  }
899 
908  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
909  int tgt_fd = p->fds->allocFD(ffdp);
910  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
911  "(inferred from:%s)\n", desc->name(),
912  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
913  return tgt_fd;
914 }
915 
917 template <class OS>
920  Addr pathname, int tgt_flags, int mode)
921 {
922  return openatFunc<OS>(
923  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
924 }
925 
927 template <class OS>
929 unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname)
930 {
931  if (dirfd != OS::TGT_AT_FDCWD)
932  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
933 
934  return unlinkFunc(desc, tc, pathname);
935 }
936 
938 template <class OS>
941  int dirfd, Addr pathname, int mode)
942 {
943  if (dirfd != OS::TGT_AT_FDCWD)
944  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
945  return accessFunc(desc, tc, pathname, mode);
946 }
947 
949 template <class OS>
952  int dirfd, Addr pathname, Addr buf, size_t bufsiz)
953 {
954  if (dirfd != OS::TGT_AT_FDCWD)
955  warn("openat: first argument not AT_FDCWD; unlikely to work");
956  return readlinkFunc(desc, tc, pathname, buf, bufsiz);
957 }
958 
960 template <class OS>
963  int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
964 {
965  if (olddirfd != OS::TGT_AT_FDCWD)
966  warn("renameat: first argument not AT_FDCWD; unlikely to work");
967 
968  if (newdirfd != OS::TGT_AT_FDCWD)
969  warn("renameat: third argument not AT_FDCWD; unlikely to work");
970 
971  return renameFunc(desc, tc, oldpath, newpath);
972 }
973 
975 template <class OS>
978 {
979  auto process = tc->getProcessPtr();
980 
982 
983  sysinfo->uptime = seconds_since_epoch;
984  sysinfo->totalram = process->system->memSize();
985  sysinfo->mem_unit = 1;
986 
987  sysinfo.copyOut(tc->getVirtProxy());
988 
989  return 0;
990 }
991 
993 template <class OS>
995 chmodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
996 {
997  std::string path;
998  auto process = tc->getProcessPtr();
999 
1000  if (!tc->getVirtProxy().tryReadString(path, pathname))
1001  return -EFAULT;
1002 
1003  mode_t hostMode = 0;
1004 
1005  // XXX translate mode flags via OS::something???
1006  hostMode = mode;
1007 
1008  // Adjust path for cwd and redirection
1009  path = process->checkPathRedirect(path);
1010 
1011  // do the chmod
1012  int result = chmod(path.c_str(), hostMode);
1013  if (result < 0)
1014  return -errno;
1015 
1016  return 0;
1017 }
1018 
1019 template <class OS>
1022  Addr fdsPtr, int nfds, int tmout)
1023 {
1024  auto p = tc->getProcessPtr();
1025 
1026  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1027  fdsBuf.copyIn(tc->getVirtProxy());
1028 
1035  int temp_tgt_fds[nfds];
1036  for (int index = 0; index < nfds; index++) {
1037  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1038  auto tgt_fd = temp_tgt_fds[index];
1039  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1040  if (!hbfdp)
1041  return -EBADF;
1042  auto host_fd = hbfdp->getSimFD();
1043  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1044  }
1045 
1052  int status;
1053  if (tmout < 0) {
1054  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1055  if (status == 0) {
1061  System *sysh = tc->getSystemPtr();
1063  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1064  if (it->receiver == p)
1065  return -EINTR;
1066  return SyscallReturn::retry();
1067  }
1068  } else
1069  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1070 
1071  if (status == -1)
1072  return -errno;
1073 
1078  for (int index = 0; index < nfds; index++) {
1079  auto tgt_fd = temp_tgt_fds[index];
1080  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1081  }
1082 
1087  fdsBuf.copyOut(tc->getVirtProxy());
1088 
1089  return status;
1090 }
1091 
1093 template <class OS>
1095 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1096 {
1097  auto p = tc->getProcessPtr();
1098 
1099  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1100  if (!ffdp)
1101  return -EBADF;
1102  int sim_fd = ffdp->getSimFD();
1103 
1104  mode_t hostMode = mode;
1105 
1106  int result = fchmod(sim_fd, hostMode);
1107 
1108  return (result < 0) ? -errno : 0;
1109 }
1110 
1112 template <class OS>
1115  Addr start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1117 {
1118  auto p = tc->getProcessPtr();
1119  Addr page_bytes = tc->getSystemPtr()->getPageBytes();
1120  uint64_t provided_address = 0;
1121  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1122 
1123  if (use_provided_address)
1124  provided_address = varargs.get<uint64_t>();
1125 
1126  if ((start % page_bytes != 0) ||
1127  (provided_address % page_bytes != 0)) {
1128  warn("mremap failing: arguments not page aligned");
1129  return -EINVAL;
1130  }
1131 
1132  new_length = roundUp(new_length, page_bytes);
1133 
1134  if (new_length > old_length) {
1135  Addr mmap_end = p->memState->getMmapEnd();
1136 
1137  if ((start + old_length) == mmap_end &&
1138  (!use_provided_address || provided_address == start)) {
1139  // This case cannot occur when growing downward, as
1140  // start is greater than or equal to mmap_end.
1141  uint64_t diff = new_length - old_length;
1142  p->memState->mapRegion(mmap_end, diff, "remapped");
1143  p->memState->setMmapEnd(mmap_end + diff);
1144  return start;
1145  } else {
1146  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1147  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1148  return -ENOMEM;
1149  } else {
1150  uint64_t new_start = provided_address;
1151  if (!use_provided_address) {
1152  new_start = p->mmapGrowsDown() ?
1153  mmap_end - new_length : mmap_end;
1154  mmap_end = p->mmapGrowsDown() ?
1155  new_start : mmap_end + new_length;
1156  p->memState->setMmapEnd(mmap_end);
1157  }
1158 
1159  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1160  new_start, new_start + new_length,
1161  new_length - old_length);
1162 
1163  // add on the remaining unallocated pages
1164  p->allocateMem(new_start + old_length,
1165  new_length - old_length,
1166  use_provided_address /* clobber */);
1167 
1168  if (use_provided_address &&
1169  ((new_start + new_length > p->memState->getMmapEnd() &&
1170  !p->mmapGrowsDown()) ||
1171  (new_start < p->memState->getMmapEnd() &&
1172  p->mmapGrowsDown()))) {
1173  // something fishy going on here, at least notify the user
1174  // @todo: increase mmap_end?
1175  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1176  }
1177 
1178  warn("returning %08p as start\n", new_start);
1179  p->memState->remapRegion(start, new_start, old_length);
1180  return new_start;
1181  }
1182  }
1183  } else {
1184  // Shrink a region
1185  if (use_provided_address && provided_address != start)
1186  p->memState->remapRegion(start, provided_address, new_length);
1187  if (new_length != old_length)
1188  p->memState->unmapRegion(start + new_length,
1189  old_length - new_length);
1190  return use_provided_address ? provided_address : start;
1191  }
1192 }
1193 
1195 template <class OS>
1197 statFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
1198 {
1199  std::string path;
1200  auto process = tc->getProcessPtr();
1201 
1202  if (!tc->getVirtProxy().tryReadString(path, pathname))
1203  return -EFAULT;
1204 
1205  // Adjust path for cwd and redirection
1206  path = process->checkPathRedirect(path);
1207 
1208  struct stat hostBuf;
1209  int result = stat(path.c_str(), &hostBuf);
1210 
1211  if (result < 0)
1212  return -errno;
1213 
1214  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1215 
1216  return 0;
1217 }
1218 
1219 
1221 template <class OS>
1223 stat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
1224 {
1225  std::string path;
1226  auto process = tc->getProcessPtr();
1227 
1228  if (!tc->getVirtProxy().tryReadString(path, pathname))
1229  return -EFAULT;
1230 
1231  // Adjust path for cwd and redirection
1232  path = process->checkPathRedirect(path);
1233 
1234 #if NO_STAT64
1235  struct stat hostBuf;
1236  int result = stat(path.c_str(), &hostBuf);
1237 #else
1238  struct stat64 hostBuf;
1239  int result = stat64(path.c_str(), &hostBuf);
1240 #endif
1241 
1242  if (result < 0)
1243  return -errno;
1244 
1245  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1246 
1247  return 0;
1248 }
1249 
1250 
1252 template <class OS>
1255  int dirfd, Addr pathname, Addr bufPtr)
1256 {
1257  auto process = tc->getProcessPtr();
1258  if (dirfd != OS::TGT_AT_FDCWD)
1259  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1260 
1261  std::string path;
1262  if (!tc->getVirtProxy().tryReadString(path, pathname))
1263  return -EFAULT;
1264 
1265  // Adjust path for cwd and redirection
1266  path = process->checkPathRedirect(path);
1267 
1268 #if NO_STAT64
1269  struct stat hostBuf;
1270  int result = stat(path.c_str(), &hostBuf);
1271 #else
1272  struct stat64 hostBuf;
1273  int result = stat64(path.c_str(), &hostBuf);
1274 #endif
1275 
1276  if (result < 0)
1277  return -errno;
1278 
1279  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1280 
1281  return 0;
1282 }
1283 
1284 
1286 template <class OS>
1288 fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
1289 {
1290  auto p = tc->getProcessPtr();
1291 
1292  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1293  if (!ffdp)
1294  return -EBADF;
1295  int sim_fd = ffdp->getSimFD();
1296 
1297 #if NO_STAT64
1298  struct stat hostBuf;
1299  int result = fstat(sim_fd, &hostBuf);
1300 #else
1301  struct stat64 hostBuf;
1302  int result = fstat64(sim_fd, &hostBuf);
1303 #endif
1304 
1305  if (result < 0)
1306  return -errno;
1307 
1308  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1309 
1310  return 0;
1311 }
1312 
1313 
1315 template <class OS>
1317 lstatFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
1318 {
1319  std::string path;
1320  auto process = tc->getProcessPtr();
1321 
1322  if (!tc->getVirtProxy().tryReadString(path, pathname))
1323  return -EFAULT;
1324 
1325  // Adjust path for cwd and redirection
1326  path = process->checkPathRedirect(path);
1327 
1328  struct stat hostBuf;
1329  int result = lstat(path.c_str(), &hostBuf);
1330 
1331  if (result < 0)
1332  return -errno;
1333 
1334  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1335 
1336  return 0;
1337 }
1338 
1340 template <class OS>
1342 lstat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
1343 {
1344  std::string path;
1345  auto process = tc->getProcessPtr();
1346 
1347  if (!tc->getVirtProxy().tryReadString(path, pathname))
1348  return -EFAULT;
1349 
1350  // Adjust path for cwd and redirection
1351  path = process->checkPathRedirect(path);
1352 
1353 #if NO_STAT64
1354  struct stat hostBuf;
1355  int result = lstat(path.c_str(), &hostBuf);
1356 #else
1357  struct stat64 hostBuf;
1358  int result = lstat64(path.c_str(), &hostBuf);
1359 #endif
1360 
1361  if (result < 0)
1362  return -errno;
1363 
1364  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1365 
1366  return 0;
1367 }
1368 
1370 template <class OS>
1372 fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
1373 {
1374  auto p = tc->getProcessPtr();
1375 
1376  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1377 
1378  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1379  if (!ffdp)
1380  return -EBADF;
1381  int sim_fd = ffdp->getSimFD();
1382 
1383  struct stat hostBuf;
1384  int result = fstat(sim_fd, &hostBuf);
1385 
1386  if (result < 0)
1387  return -errno;
1388 
1389  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1390 
1391  return 0;
1392 }
1393 
1395 template <class OS>
1397 statfsFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
1398 {
1399 #if defined(__linux__)
1400  std::string path;
1401  auto process = tc->getProcessPtr();
1402 
1403  if (!tc->getVirtProxy().tryReadString(path, pathname))
1404  return -EFAULT;
1405 
1406  // Adjust path for cwd and redirection
1407  path = process->checkPathRedirect(path);
1408 
1409  struct statfs hostBuf;
1410  int result = statfs(path.c_str(), &hostBuf);
1411 
1412  if (result < 0)
1413  return -errno;
1414 
1415  copyOutStatfsBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1416  return 0;
1417 #else
1418  warnUnsupportedOS("statfs");
1419  return -1;
1420 #endif
1421 }
1422 
1423 template <class OS>
1425 cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
1426  Addr ptidPtr, Addr ctidPtr, Addr tlsPtr)
1427 {
1428  auto p = tc->getProcessPtr();
1429 
1430  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1431  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1432  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1433  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1434  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1435  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1436  return -EINVAL;
1437 
1438  ThreadContext *ctc;
1439  if (!(ctc = tc->getSystemPtr()->findFreeContext())) {
1440  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1441  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1442  return -EAGAIN;
1443  }
1444 
1451  ProcessParams *pp = new ProcessParams();
1452  pp->executable.assign(*(new std::string(p->progName())));
1453  pp->cmd.push_back(*(new std::string(p->progName())));
1454  pp->system = p->system;
1455  pp->cwd.assign(p->tgtCwd);
1456  pp->input.assign("stdin");
1457  pp->output.assign("stdout");
1458  pp->errout.assign("stderr");
1459  pp->uid = p->uid();
1460  pp->euid = p->euid();
1461  pp->gid = p->gid();
1462  pp->egid = p->egid();
1463 
1464  /* Find the first free PID that's less than the maximum */
1465  std::set<int> const& pids = p->system->PIDs;
1466  int temp_pid = *pids.begin();
1467  do {
1468  temp_pid++;
1469  } while (pids.find(temp_pid) != pids.end());
1470  if (temp_pid >= System::maxPID)
1471  fatal("temp_pid is too large: %d", temp_pid);
1472 
1473  pp->pid = temp_pid;
1474  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1475  pp->useArchPT = p->useArchPT;
1476  pp->kvmInSE = p->kvmInSE;
1477  Process *cp = pp->create();
1478  // TODO: there is no way to know when the Process SimObject is done with
1479  // the params pointer. Both the params pointer (pp) and the process
1480  // pointer (cp) are normally managed in python and are never cleaned up.
1481 
1482  Process *owner = ctc->getProcessPtr();
1483  ctc->setProcessPtr(cp);
1484  cp->assignThreadContext(ctc->contextId());
1485  owner->revokeThreadContext(ctc->contextId());
1486 
1487  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1488  BufferArg ptidBuf(ptidPtr, sizeof(long));
1489  long *ptid = (long *)ptidBuf.bufferPtr();
1490  *ptid = cp->pid();
1491  ptidBuf.copyOut(tc->getVirtProxy());
1492  }
1493 
1494  if (flags & OS::TGT_CLONE_THREAD) {
1495  cp->pTable->shared = true;
1496  cp->useForClone = true;
1497  }
1498  cp->initState();
1499  p->clone(tc, ctc, cp, flags);
1500 
1501  if (flags & OS::TGT_CLONE_THREAD) {
1502  delete cp->sigchld;
1503  cp->sigchld = p->sigchld;
1504  } else if (flags & OS::TGT_SIGCHLD) {
1505  *cp->sigchld = true;
1506  }
1507 
1508  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1509  BufferArg ctidBuf(ctidPtr, sizeof(long));
1510  long *ctid = (long *)ctidBuf.bufferPtr();
1511  *ctid = cp->pid();
1512  ctidBuf.copyOut(ctc->getVirtProxy());
1513  }
1514 
1515  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1516  cp->childClearTID = (uint64_t)ctidPtr;
1517 
1518  ctc->clearArchRegs();
1519 
1520  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1521 
1522  desc->returnInto(ctc, 0);
1523 
1524 #if THE_ISA == SPARC_ISA
1527 #endif
1528 
1529  TheISA::PCState cpc = tc->pcState();
1530  if (!p->kvmInSE)
1531  cpc.advance();
1532  ctc->pcState(cpc);
1533  ctc->activate();
1534 
1535  return cp->pid();
1536 }
1537 
1538 template <class OS>
1541  RegVal newStack, Addr ptidPtr, Addr tlsPtr, Addr ctidPtr)
1542 {
1543  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1544 }
1545 
1547 template <class OS>
1549 fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
1550 {
1551  auto p = tc->getProcessPtr();
1552 
1553  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1554  if (!ffdp)
1555  return -EBADF;
1556  int sim_fd = ffdp->getSimFD();
1557 
1558  struct statfs hostBuf;
1559  int result = fstatfs(sim_fd, &hostBuf);
1560 
1561  if (result < 0)
1562  return -errno;
1563 
1564  copyOutStatfsBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1565 
1566  return 0;
1567 }
1568 
1570 template <class OS>
1573  int tgt_fd, uint64_t tiov_base, size_t count)
1574 {
1575  auto p = tc->getProcessPtr();
1576 
1577  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1578  if (!ffdp)
1579  return -EBADF;
1580  int sim_fd = ffdp->getSimFD();
1581 
1582  PortProxy &prox = tc->getVirtProxy();
1583  typename OS::tgt_iovec tiov[count];
1584  struct iovec hiov[count];
1585  for (size_t i = 0; i < count; ++i) {
1586  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1587  &tiov[i], sizeof(typename OS::tgt_iovec));
1588  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1589  hiov[i].iov_base = new char [hiov[i].iov_len];
1590  }
1591 
1592  int result = readv(sim_fd, hiov, count);
1593  int local_errno = errno;
1594 
1595  for (size_t i = 0; i < count; ++i) {
1596  if (result != -1) {
1597  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1598  hiov[i].iov_base, hiov[i].iov_len);
1599  }
1600  delete [] (char *)hiov[i].iov_base;
1601  }
1602 
1603  return (result == -1) ? -local_errno : result;
1604 }
1605 
1607 template <class OS>
1610  int tgt_fd, uint64_t tiov_base, size_t count)
1611 {
1612  auto p = tc->getProcessPtr();
1613 
1614  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1615  if (!hbfdp)
1616  return -EBADF;
1617  int sim_fd = hbfdp->getSimFD();
1618 
1619  PortProxy &prox = tc->getVirtProxy();
1620  struct iovec hiov[count];
1621  for (size_t i = 0; i < count; ++i) {
1622  typename OS::tgt_iovec tiov;
1623 
1624  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1625  &tiov, sizeof(typename OS::tgt_iovec));
1626  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1627  hiov[i].iov_base = new char [hiov[i].iov_len];
1628  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1629  hiov[i].iov_len);
1630  }
1631 
1632  int result = writev(sim_fd, hiov, count);
1633 
1634  for (size_t i = 0; i < count; ++i)
1635  delete [] (char *)hiov[i].iov_base;
1636 
1637  return (result == -1) ? -errno : result;
1638 }
1639 
1641 template <class OS>
1644  Addr start, typename OS::size_t length, int prot,
1645  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1646 {
1647  auto p = tc->getProcessPtr();
1648  Addr page_bytes = tc->getSystemPtr()->getPageBytes();
1649 
1650  if (start & (page_bytes - 1) ||
1651  offset & (page_bytes - 1) ||
1652  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1653  tgt_flags & OS::TGT_MAP_SHARED) ||
1654  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1655  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1656  !length) {
1657  return -EINVAL;
1658  }
1659 
1660  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1661  // With shared mmaps, there are two cases to consider:
1662  // 1) anonymous: writes should modify the mapping and this should be
1663  // visible to observers who share the mapping. Currently, it's
1664  // difficult to update the shared mapping because there's no
1665  // structure which maintains information about the which virtual
1666  // memory areas are shared. If that structure existed, it would be
1667  // possible to make the translations point to the same frames.
1668  // 2) file-backed: writes should modify the mapping and the file
1669  // which is backed by the mapping. The shared mapping problem is the
1670  // same as what was mentioned about the anonymous mappings. For
1671  // file-backed mappings, the writes to the file are difficult
1672  // because it requires syncing what the mapping holds with the file
1673  // that resides on the host system. So, any write on a real system
1674  // would cause the change to be propagated to the file mapping at
1675  // some point in the future (the inode is tracked along with the
1676  // mapping). This isn't guaranteed to always happen, but it usually
1677  // works well enough. The guarantee is provided by the msync system
1678  // call. We could force the change through with shared mappings with
1679  // a call to msync, but that again would require more information
1680  // than we currently maintain.
1681  warn_once("mmap: writing to shared mmap region is currently "
1682  "unsupported. The write succeeds on the target, but it "
1683  "will not be propagated to the host or shared mappings");
1684  }
1685 
1686  length = roundUp(length, page_bytes);
1687 
1688  int sim_fd = -1;
1689  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1690  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1691 
1692  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1693  if (dfdp) {
1694  EmulatedDriver *emul_driver = dfdp->getDriver();
1695  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1696  tgt_fd, offset);
1697  }
1698 
1699  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1700  if (!ffdp)
1701  return -EBADF;
1702  sim_fd = ffdp->getSimFD();
1703 
1712  if (p->interpImage.contains(tc->pcState().instAddr())) {
1713  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1714  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1715  auto *lib = Loader::createObjectFile(p->checkPathRedirect(
1716  ffdp->getFileName()));
1717  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1718  ffdp->getFileName());
1719 
1720  if (lib) {
1721  lib->loadAllSymbols(Loader::debugSymbolTable,
1722  lib->buildImage().minAddr(), start);
1723  }
1724  }
1725  }
1726 
1730  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1738  if (!(start && p->memState->isUnmapped(start, length))) {
1742  start = p->memState->extendMmap(length);
1743  }
1744  }
1745 
1746  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1747  start, start + length - 1);
1748 
1754  if (tgt_flags & OS::TGT_MAP_FIXED) {
1759  p->memState->unmapRegion(start, length);
1760  }
1761 
1765  std::string region_name;
1766  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1767  region_name = "anon";
1768  } else {
1769  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1770  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1771  region_name = ffdp->getFileName();
1772  }
1773 
1778  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1779 
1780  return start;
1781 }
1782 
1783 template <class OS>
1786  int tgt_fd, Addr bufPtr, int nbytes, int offset)
1787 {
1788  auto p = tc->getProcessPtr();
1789 
1790  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1791  if (!ffdp)
1792  return -EBADF;
1793  int sim_fd = ffdp->getSimFD();
1794 
1795  BufferArg bufArg(bufPtr, nbytes);
1796 
1797  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1798 
1799  bufArg.copyOut(tc->getVirtProxy());
1800 
1801  return (bytes_read == -1) ? -errno : bytes_read;
1802 }
1803 
1804 template <class OS>
1807  int tgt_fd, Addr bufPtr, int nbytes, int offset)
1808 {
1809  auto p = tc->getProcessPtr();
1810 
1811  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1812  if (!ffdp)
1813  return -EBADF;
1814  int sim_fd = ffdp->getSimFD();
1815 
1816  BufferArg bufArg(bufPtr, nbytes);
1817  bufArg.copyIn(tc->getVirtProxy());
1818 
1819  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1820 
1821  return (bytes_written == -1) ? -errno : bytes_written;
1822 }
1823 
1825 template <class OS>
1828  Addr start, typename OS::size_t length, int prot,
1829  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1830 {
1831  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
1832  tgt_fd, offset * tc->getSystemPtr()->getPageBytes());
1833 }
1834 
1836 template <class OS>
1839  unsigned resource, Addr rlim)
1840 {
1842 
1843  const ByteOrder bo = OS::byteOrder;
1844  switch (resource) {
1845  case OS::TGT_RLIMIT_STACK:
1846  // max stack size in bytes: make up a number (8MB for now)
1847  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1848  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1849  rlp->rlim_max = htog(rlp->rlim_max, bo);
1850  break;
1851 
1852  case OS::TGT_RLIMIT_DATA:
1853  // max data segment size in bytes: make up a number
1854  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1855  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1856  rlp->rlim_max = htog(rlp->rlim_max, bo);
1857  break;
1858 
1859  case OS::TGT_RLIMIT_NPROC:
1860  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->numContexts();
1861  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1862  rlp->rlim_max = htog(rlp->rlim_max, bo);
1863  break;
1864 
1865  default:
1866  warn("getrlimit: unimplemented resource %d", resource);
1867  return -EINVAL;
1868  break;
1869  }
1870 
1871  rlp.copyOut(tc->getVirtProxy());
1872  return 0;
1873 }
1874 
1875 template <class OS>
1878  int pid, int resource, Addr n, Addr o)
1879 {
1880  if (pid != 0) {
1881  warn("prlimit: ignoring rlimits for nonzero pid");
1882  return -EPERM;
1883  }
1884  if (n != 0)
1885  warn("prlimit: ignoring new rlimit");
1886  if (o != 0) {
1887  const ByteOrder bo = OS::byteOrder;
1889  switch (resource) {
1890  case OS::TGT_RLIMIT_STACK:
1891  // max stack size in bytes: make up a number (8MB for now)
1892  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1893  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1894  rlp->rlim_max = htog(rlp->rlim_max, bo);
1895  break;
1896  case OS::TGT_RLIMIT_DATA:
1897  // max data segment size in bytes: make up a number
1898  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1899  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1900  rlp->rlim_max = htog(rlp->rlim_max, bo);
1901  break;
1902  default:
1903  warn("prlimit: unimplemented resource %d", resource);
1904  return -EINVAL;
1905  break;
1906  }
1907  rlp.copyOut(tc->getVirtProxy());
1908  }
1909  return 0;
1910 }
1911 
1913 template <class OS>
1916  int clk_id, Addr tp_ptr)
1917 {
1919 
1920  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1921  tp->tv_sec += seconds_since_epoch;
1922  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1923  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
1924 
1925  tp.copyOut(tc->getVirtProxy());
1926 
1927  return 0;
1928 }
1929 
1931 template <class OS>
1933 clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, Addr tp_ptr)
1934 {
1936 
1937  // Set resolution at ns, which is what clock_gettime() returns
1938  tp->tv_sec = 0;
1939  tp->tv_nsec = 1;
1940 
1941  tp.copyOut(tc->getVirtProxy());
1942 
1943  return 0;
1944 }
1945 
1947 template <class OS>
1950  Addr tv_ptr, Addr tz_ptr)
1951 {
1953 
1954  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1955  tp->tv_sec += seconds_since_epoch;
1956  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1957  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
1958 
1959  tp.copyOut(tc->getVirtProxy());
1960 
1961  return 0;
1962 }
1963 
1964 
1966 template <class OS>
1968 utimesFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr times)
1969 {
1970  std::string path;
1971  auto process = tc->getProcessPtr();
1972 
1973  if (!tc->getVirtProxy().tryReadString(path, pathname))
1974  return -EFAULT;
1975 
1977  tp.copyIn(tc->getVirtProxy());
1978 
1979  struct timeval hostTimeval[2];
1980  for (int i = 0; i < 2; ++i) {
1981  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
1982  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
1983  }
1984 
1985  // Adjust path for cwd and redirection
1986  path = process->checkPathRedirect(path);
1987 
1988  int result = utimes(path.c_str(), hostTimeval);
1989 
1990  if (result < 0)
1991  return -errno;
1992 
1993  return 0;
1994 }
1995 
1996 template <class OS>
1999  Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
2000 {
2001  auto p = tc->getProcessPtr();
2002 
2003  std::string path;
2004  PortProxy & mem_proxy = tc->getVirtProxy();
2005  if (!mem_proxy.tryReadString(path, pathname))
2006  return -EFAULT;
2007 
2008  if (access(path.c_str(), F_OK) == -1)
2009  return -EACCES;
2010 
2011  auto read_in = [](std::vector<std::string> &vect,
2012  PortProxy &mem_proxy, Addr mem_loc)
2013  {
2014  for (int inc = 0; ; inc++) {
2015  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2016  b.copyIn(mem_proxy);
2017 
2018  if (!*(Addr*)b.bufferPtr())
2019  break;
2020 
2021  vect.push_back(std::string());
2022  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2023  }
2024  };
2025 
2032  ProcessParams *pp = new ProcessParams();
2033  pp->executable = path;
2034  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2035  read_in(pp->env, mem_proxy, envp_mem_loc);
2036  pp->uid = p->uid();
2037  pp->egid = p->egid();
2038  pp->euid = p->euid();
2039  pp->gid = p->gid();
2040  pp->ppid = p->ppid();
2041  pp->pid = p->pid();
2042  pp->input.assign("cin");
2043  pp->output.assign("cout");
2044  pp->errout.assign("cerr");
2045  pp->cwd.assign(p->tgtCwd);
2046  pp->system = p->system;
2055  p->system->PIDs.erase(p->pid());
2056  Process *new_p = pp->create();
2057  delete pp;
2058 
2063  new_p->fds = p->fds;
2064  for (int i = 0; i < new_p->fds->getSize(); i++) {
2065  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2066  if (fdep && fdep->getCOE())
2067  new_p->fds->closeFDEntry(i);
2068  }
2069 
2070  *new_p->sigchld = true;
2071 
2072  delete p;
2073  tc->clearArchRegs();
2074  tc->setProcessPtr(new_p);
2075  new_p->assignThreadContext(tc->contextId());
2076  new_p->initState();
2077  tc->activate();
2078  TheISA::PCState pcState = tc->pcState();
2079  tc->setNPC(pcState.instAddr());
2080 
2081  return SyscallReturn();
2082 }
2083 
2085 template <class OS>
2088  int who /* THREAD, SELF, or CHILDREN */, Addr usage)
2089 {
2091 
2092  rup->ru_utime.tv_sec = 0;
2093  rup->ru_utime.tv_usec = 0;
2094  rup->ru_stime.tv_sec = 0;
2095  rup->ru_stime.tv_usec = 0;
2096  rup->ru_maxrss = 0;
2097  rup->ru_ixrss = 0;
2098  rup->ru_idrss = 0;
2099  rup->ru_isrss = 0;
2100  rup->ru_minflt = 0;
2101  rup->ru_majflt = 0;
2102  rup->ru_nswap = 0;
2103  rup->ru_inblock = 0;
2104  rup->ru_oublock = 0;
2105  rup->ru_msgsnd = 0;
2106  rup->ru_msgrcv = 0;
2107  rup->ru_nsignals = 0;
2108  rup->ru_nvcsw = 0;
2109  rup->ru_nivcsw = 0;
2110 
2111  switch (who) {
2112  case OS::TGT_RUSAGE_SELF:
2113  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2114  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2115  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2116  break;
2117 
2118  case OS::TGT_RUSAGE_CHILDREN:
2119  // do nothing. We have no child processes, so they take no time.
2120  break;
2121 
2122  default:
2123  // don't really handle THREAD or CHILDREN, but just warn and
2124  // plow ahead
2125  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2126  who);
2127  }
2128 
2129  rup.copyOut(tc->getVirtProxy());
2130 
2131  return 0;
2132 }
2133 
2135 template <class OS>
2138 {
2139  TypedBufferArg<typename OS::tms> bufp(bufPtr);
2140 
2141  // Fill in the time structure (in clocks)
2142  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
2143  bufp->tms_utime = clocks;
2144  bufp->tms_stime = 0;
2145  bufp->tms_cutime = 0;
2146  bufp->tms_cstime = 0;
2147 
2148  // Convert to host endianness
2149  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2150 
2151  // Write back
2152  bufp.copyOut(tc->getVirtProxy());
2153 
2154  // Return clock ticks since system boot
2155  return clocks;
2156 }
2157 
2159 template <class OS>
2162 {
2163  typename OS::time_t sec, usec;
2164  getElapsedTimeMicro(sec, usec);
2165  sec += seconds_since_epoch;
2166 
2167  if (taddr != 0) {
2168  typename OS::time_t t = sec;
2169  t = htog(t, OS::byteOrder);
2170  PortProxy &p = tc->getVirtProxy();
2171  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2172  }
2173  return sec;
2174 }
2175 
2176 template <class OS>
2178 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2179 {
2195  System *sys = tc->getSystemPtr();
2196  Process *tgt_proc = nullptr;
2197  for (int i = 0; i < sys->numContexts(); i++) {
2198  Process *temp = sys->threadContexts[i]->getProcessPtr();
2199  if (temp->pid() == tid) {
2200  tgt_proc = temp;
2201  break;
2202  }
2203  }
2204 
2205  if (sig != 0 || sig != OS::TGT_SIGABRT)
2206  return -EINVAL;
2207 
2208  if (tgt_proc == nullptr)
2209  return -ESRCH;
2210 
2211  if (tgid != -1 && tgt_proc->tgid() != tgid)
2212  return -ESRCH;
2213 
2214  if (sig == OS::TGT_SIGABRT)
2215  exitGroupFunc(desc, tc, 0);
2216 
2217  return 0;
2218 }
2219 
2220 template <class OS>
2223  int domain, int type, int prot)
2224 {
2225  auto p = tc->getProcessPtr();
2226 
2227  int sim_fd = socket(domain, type, prot);
2228  if (sim_fd == -1)
2229  return -errno;
2230 
2231  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2232  int tgt_fd = p->fds->allocFD(sfdp);
2233 
2234  return tgt_fd;
2235 }
2236 
2237 template <class OS>
2240  int domain, int type, int prot, Addr svPtr)
2241 {
2242  auto p = tc->getProcessPtr();
2243 
2244  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2245  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2246  if (status == -1)
2247  return -errno;
2248 
2249  int *fds = (int *)svBuf.bufferPtr();
2250 
2251  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2252  fds[0] = p->fds->allocFD(sfdp1);
2253  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2254  fds[1] = p->fds->allocFD(sfdp2);
2255  svBuf.copyOut(tc->getVirtProxy());
2256 
2257  return status;
2258 }
2259 
2260 template <class OS>
2263  int nfds_t, Addr fds_read_ptr, Addr fds_writ_ptr,
2264  Addr fds_excp_ptr, Addr time_val_ptr)
2265 {
2266  int retval;
2267 
2268  auto p = tc->getProcessPtr();
2269 
2270  TypedBufferArg<typename OS::fd_set> rd_t(fds_read_ptr);
2271  TypedBufferArg<typename OS::fd_set> wr_t(fds_writ_ptr);
2272  TypedBufferArg<typename OS::fd_set> ex_t(fds_excp_ptr);
2273  TypedBufferArg<typename OS::timeval> tp(time_val_ptr);
2274 
2280  fd_set rd_h;
2281  FD_ZERO(&rd_h);
2282  fd_set wr_h;
2283  FD_ZERO(&wr_h);
2284  fd_set ex_h;
2285  FD_ZERO(&ex_h);
2286 
2290  if (fds_read_ptr)
2291  rd_t.copyIn(tc->getVirtProxy());
2292  if (fds_writ_ptr)
2293  wr_t.copyIn(tc->getVirtProxy());
2294  if (fds_excp_ptr)
2295  ex_t.copyIn(tc->getVirtProxy());
2296 
2306  int nfds_h = 0;
2307  std::map<int, int> trans_map;
2308  auto try_add_host_set = [&](fd_set *tgt_set_entry,
2309  fd_set *hst_set_entry,
2310  int iter) -> bool
2311  {
2317  if (FD_ISSET(iter, tgt_set_entry)) {
2323  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2324  if (!hbfdp)
2325  return true;
2326  auto sim_fd = hbfdp->getSimFD();
2327 
2333  trans_map[sim_fd] = iter;
2334 
2340  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2341 
2346  FD_SET(sim_fd, hst_set_entry);
2347  }
2348  return false;
2349  };
2350 
2351  for (int i = 0; i < nfds_t; i++) {
2352  if (fds_read_ptr) {
2353  bool ebadf = try_add_host_set((fd_set*)&*rd_t, &rd_h, i);
2354  if (ebadf) return -EBADF;
2355  }
2356  if (fds_writ_ptr) {
2357  bool ebadf = try_add_host_set((fd_set*)&*wr_t, &wr_h, i);
2358  if (ebadf) return -EBADF;
2359  }
2360  if (fds_excp_ptr) {
2361  bool ebadf = try_add_host_set((fd_set*)&*ex_t, &ex_h, i);
2362  if (ebadf) return -EBADF;
2363  }
2364  }
2365 
2366  if (time_val_ptr) {
2374  tp->tv_sec = 0;
2375  tp->tv_usec = 0;
2376 
2377  retval = select(nfds_h,
2378  fds_read_ptr ? &rd_h : nullptr,
2379  fds_writ_ptr ? &wr_h : nullptr,
2380  fds_excp_ptr ? &ex_h : nullptr,
2381  (timeval*)&*tp);
2382  } else {
2390  struct timeval tv = { 0, 0 };
2391 
2392  retval = select(nfds_h,
2393  fds_read_ptr ? &rd_h : nullptr,
2394  fds_writ_ptr ? &wr_h : nullptr,
2395  fds_excp_ptr ? &ex_h : nullptr,
2396  &tv);
2397 
2398  if (retval == 0) {
2404  for (auto sig : tc->getSystemPtr()->signalList)
2405  if (sig.receiver == p)
2406  return -EINTR;
2407  return SyscallReturn::retry();
2408  }
2409  }
2410 
2411  if (retval == -1)
2412  return -errno;
2413 
2414  FD_ZERO((fd_set*)&*rd_t);
2415  FD_ZERO((fd_set*)&*wr_t);
2416  FD_ZERO((fd_set*)&*ex_t);
2417 
2423  for (int i = 0; i < nfds_h; i++) {
2424  if (fds_read_ptr) {
2425  if (FD_ISSET(i, &rd_h))
2426  FD_SET(trans_map[i], (fd_set*)&*rd_t);
2427  }
2428 
2429  if (fds_writ_ptr) {
2430  if (FD_ISSET(i, &wr_h))
2431  FD_SET(trans_map[i], (fd_set*)&*wr_t);
2432  }
2433 
2434  if (fds_excp_ptr) {
2435  if (FD_ISSET(i, &ex_h))
2436  FD_SET(trans_map[i], (fd_set*)&*ex_t);
2437  }
2438  }
2439 
2440  if (fds_read_ptr)
2441  rd_t.copyOut(tc->getVirtProxy());
2442  if (fds_writ_ptr)
2443  wr_t.copyOut(tc->getVirtProxy());
2444  if (fds_excp_ptr)
2445  ex_t.copyOut(tc->getVirtProxy());
2446  if (time_val_ptr)
2447  tp.copyOut(tc->getVirtProxy());
2448 
2449  return retval;
2450 }
2451 
2452 template <class OS>
2455  int tgt_fd, Addr buf_ptr, int nbytes)
2456 {
2457  auto p = tc->getProcessPtr();
2458 
2459  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2460  if (!hbfdp)
2461  return -EBADF;
2462  int sim_fd = hbfdp->getSimFD();
2463 
2464  struct pollfd pfd;
2465  pfd.fd = sim_fd;
2466  pfd.events = POLLIN | POLLPRI;
2467  if ((poll(&pfd, 1, 0) == 0)
2468  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2469  return SyscallReturn::retry();
2470 
2471  BufferArg buf_arg(buf_ptr, nbytes);
2472  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2473 
2474  if (bytes_read > 0)
2475  buf_arg.copyOut(tc->getVirtProxy());
2476 
2477  return (bytes_read == -1) ? -errno : bytes_read;
2478 }
2479 
2480 template <class OS>
2483  int tgt_fd, Addr buf_ptr, int nbytes)
2484 {
2485  auto p = tc->getProcessPtr();
2486 
2487  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2488  if (!hbfdp)
2489  return -EBADF;
2490  int sim_fd = hbfdp->getSimFD();
2491 
2492  BufferArg buf_arg(buf_ptr, nbytes);
2493  buf_arg.copyIn(tc->getVirtProxy());
2494 
2495  struct pollfd pfd;
2496  pfd.fd = sim_fd;
2497  pfd.events = POLLOUT;
2498 
2505  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2506  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2507  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2508  return SyscallReturn::retry();
2509  }
2510 
2511  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2512 
2513  if (bytes_written != -1)
2514  fsync(sim_fd);
2515 
2516  return (bytes_written == -1) ? -errno : bytes_written;
2517 }
2518 
2519 template <class OS>
2522  pid_t pid, Addr statPtr, int options, Addr rusagePtr)
2523 {
2524  auto p = tc->getProcessPtr();
2525 
2526  if (rusagePtr)
2527  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2528  "functionality not supported. Ignoring rusage pointer.\n",
2529  rusagePtr);
2530 
2539  System *sysh = tc->getSystemPtr();
2541  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2542  if (iter->receiver == p) {
2543  if (pid < -1) {
2544  if ((iter->sender->pgid() == -pid)
2545  && (iter->signalValue == OS::TGT_SIGCHLD))
2546  goto success;
2547  } else if (pid == -1) {
2548  if (iter->signalValue == OS::TGT_SIGCHLD)
2549  goto success;
2550  } else if (pid == 0) {
2551  if ((iter->sender->pgid() == p->pgid())
2552  && (iter->signalValue == OS::TGT_SIGCHLD))
2553  goto success;
2554  } else {
2555  if ((iter->sender->pid() == pid)
2556  && (iter->signalValue == OS::TGT_SIGCHLD))
2557  goto success;
2558  }
2559  }
2560  }
2561 
2562  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2563 
2564 success:
2565  // Set status to EXITED for WIFEXITED evaluations.
2566  const int EXITED = 0;
2567  BufferArg statusBuf(statPtr, sizeof(int));
2568  *(int *)statusBuf.bufferPtr() = EXITED;
2569  statusBuf.copyOut(tc->getVirtProxy());
2570 
2571  // Return the child PID.
2572  pid_t retval = iter->sender->pid();
2573  sysh->signalList.erase(iter);
2574  return retval;
2575 }
2576 
2577 template <class OS>
2580  int tgt_fd, Addr addrPtr, Addr lenPtr)
2581 {
2582  struct sockaddr sa;
2583  socklen_t addrLen;
2584  int host_fd;
2585  auto p = tc->getProcessPtr();
2586 
2587  BufferArg *lenBufPtr = nullptr;
2588  BufferArg *addrBufPtr = nullptr;
2589 
2590  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2591  if (!sfdp)
2592  return -EBADF;
2593  int sim_fd = sfdp->getSimFD();
2594 
2601  struct pollfd pfd;
2602  pfd.fd = sim_fd;
2603  pfd.events = POLLIN | POLLPRI;
2604  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2605  return SyscallReturn::retry();
2606 
2607  if (lenPtr) {
2608  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2609  lenBufPtr->copyIn(tc->getVirtProxy());
2610  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2611  sizeof(socklen_t));
2612  }
2613 
2614  if (addrPtr) {
2615  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2616  addrBufPtr->copyIn(tc->getVirtProxy());
2617  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2618  sizeof(struct sockaddr));
2619  }
2620 
2621  host_fd = accept(sim_fd, &sa, &addrLen);
2622 
2623  if (host_fd == -1)
2624  return -errno;
2625 
2626  if (addrPtr) {
2627  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2628  addrBufPtr->copyOut(tc->getVirtProxy());
2629  delete(addrBufPtr);
2630  }
2631 
2632  if (lenPtr) {
2633  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2634  lenBufPtr->copyOut(tc->getVirtProxy());
2635  delete(lenBufPtr);
2636  }
2637 
2638  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2639  sfdp->_type, sfdp->_protocol);
2640  return p->fds->allocFD(afdp);
2641 }
2642 
2644 template <class OS>
2647  unsigned initval, int in_flags)
2648 {
2649 #if defined(__linux__)
2650  auto p = tc->getProcessPtr();
2651 
2652  int sim_fd = eventfd(initval, in_flags);
2653  if (sim_fd == -1)
2654  return -errno;
2655 
2656  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2657 
2658  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2659  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2660 
2661  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2662  int tgt_fd = p->fds->allocFD(hbfdp);
2663  return tgt_fd;
2664 #else
2665  warnUnsupportedOS("eventfd");
2666  return -1;
2667 #endif
2668 }
2669 
2670 #endif // __SIM_SYSCALL_EMUL_HH__
count
Definition: misc.hh:703
FutexMap futexMap
Definition: system.hh:495
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, int name_len)
Target gethostname() handler.
This file defines buffer classes used to handle pointer arguments in emulated syscalls.
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target writev() handler.
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, int offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
Definition: emul_driver.hh:95
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstat() handler.
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, uint64_t old_length, uint64_t new_length, uint64_t flags, GuestABI::VarArgs< uint64_t > varargs)
Target mremap() handler.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
virtual System * getSystemPtr()=0
Bitfield< 30, 0 > index
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, Addr ptidPtr, Addr ctidPtr, Addr tlsPtr)
Tick us
microsecond
Definition: core.cc:64
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:61
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target symlink() handler.
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr)
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, Addr uaddr, int op, int val, int timeout, Addr uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf&#39;s in multi-threaded apps...
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext...
Definition: process.cc:274
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target lstat() handler.
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:285
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:162
Bitfield< 7 > i
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target unlink() handler.
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
void copyOutStatfsBuf(PortProxy &mem, Addr addr, hst_statfs *host)
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, Addr info)
Target sysinfo() handler.
virtual TheISA::PCState pcState() const =0
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, off_t length)
Target truncate() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
bool copyIn(PortProxy &memproxy)
copy data into simulator space (read from target memory)
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, Addr svPtr)
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, Addr ptidPtr, Addr tlsPtr, Addr ctidPtr)
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, Addr rlim)
Target getrlimit() handler.
bool * sigchld
Definition: process.hh:288
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, socklen_t addrLen)
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target chmod() handler.
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
ip6_addr_t addr
Definition: inet.hh:330
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, Addr result_ptr, int whence)
Target _llseek() handler.
virtual PortProxy & getVirtProxy()=0
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, Addr fdsPtr, int nfds, int tmout)
virtual Process * getProcessPtr()=0
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling, etc.) and should not affect the correct behavior of the program.
Definition: syscall_emul.cc:72
uint64_t RegVal
Definition: types.hh:166
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:110
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
Definition: system.hh:72
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Bitfield< 23, 0 > offset
Definition: types.hh:152
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
struct statfs hst_statfs
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:297
Definition: cprintf.cc:40
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, Addr buf, size_t bufsiz)
Target readlinkat() handler.
Bitfield< 4, 0 > mode
Bitfield< 7 > prot
Definition: misc.hh:582
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:114
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
Target open() handler.
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
ThreadContext is the external interface to all thread state for anything outside of the CPU...
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.hh:239
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, uint32_t owner, uint32_t group)
Target chown() handler.
void usage(const char *progname)
Definition: symtest.cc:39
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, Addr lenPtr)
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, GuestABI::VarArgs< int > varargs)
Target fcntl() handler.
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target lstat64() handler.
Bitfield< 63 > val
Definition: misc.hh:769
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Bitfield< 31 > n
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target link() handler.
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
Bitfield< 5, 0 > status
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk)
Target brk() handler: set brk address.
Bitfield< 7 > b
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
int getSimFD() const
Definition: fd_entry.hh:92
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
uint8_t type
Definition: inet.hh:328
void copyOutStat64Buf(PortProxy &mem, Addr addr, hst_stat64 *host, bool fakeTTY=false)
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Tick curTick()
The current simulated tick.
Definition: core.hh:44
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...
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, unsigned long size)
Target getcwd() handler.
void assignThreadContext(ContextID context_id)
Definition: process.hh:120
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
static const int maxPID
Definition: system.hh:497
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:309
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:155
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
virtual int cpuId() const =0
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target mkdir() handler.
virtual void setProcessPtr(Process *p)=0
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:187
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.hh:140
uint64_t pid()
Definition: process.hh:84
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, Addr usage)
Target getrusage() function.
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, Addr taddr)
Target time() function.
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, Addr statPtr, int options, Addr rusagePtr)
ByteOrder
Definition: types.hh:245
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Bitfield< 3 > sa
std::vector< ThreadContext * > threadContexts
Definition: system.hh:182
Bitfield< 18, 16 > len
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:74
unsigned numContexts() const
Definition: system.hh:198
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, Addr oldpath, Addr newpath)
Target rename() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, Addr bufPtr)
Target times() function.
void setNPC(Addr val)
std::string const & getFileName() const
Definition: fd_entry.hh:130
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
ThreadContext * findFreeContext()
Definition: system.cc:245
STL list class.
Definition: stl.hh:51
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:59
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, int64_t length)
Target truncate64() handler.
SyscallReturn selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds_t, Addr fds_read_ptr, Addr fds_writ_ptr, Addr fds_excp_ptr, Addr time_val_ptr)
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, Addr tp_ptr)
Target clock_getres() function.
virtual void activate()=0
Set the status to Active.
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver. ...
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, Addr addr)
Target ioctl() handler.
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstatfs() handler.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target dup() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
std::string name() const
Definition: syscall_desc.hh:76
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstat64() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target readv() handler.
#define warn_once(...)
Definition: logging.hh:212
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven&#39;t thought about.
Definition: syscall_emul.cc:65
std::list< BasicSignal > signalList
Definition: system.hh:504
bool startswith(const char *s, const char *prefix)
Return true if &#39;s&#39; starts with the prefix string &#39;prefix&#39;.
Definition: str.hh:224
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:177
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target statfs() handler.
struct stat64 hst_stat64
void copyOutStatBuf(PortProxy &mem, Addr addr, hst_stat *host, bool fakeTTY=false)
Bitfield< 20 > level
Definition: intmessage.hh:47
Tick s
second
Definition: core.cc:62
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:66
This object is a proxy for a port or other object which implements the functional response protocol...
Definition: port_proxy.hh:80
EmulationPageTable * pTable
Definition: process.hh:174
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Bitfield< 25, 21 > bo
Definition: types.hh:62
Declarations of a non-full system Page Table.
const int SyscallPseudoReturnReg
Definition: registers.hh:131
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
inserts a futex into the map with one waiting TC associates the waiter with a given bitmask ...
Definition: futex_map.hh:175
Bitfield< 7, 4 > domain
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Wakes up all waiters waiting on the addr and associated with the given bitset.
Definition: futex_map.hh:197
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr, int flags)
Target pipe() handler.
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, Addr n, Addr o)
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr buf, size_t bufsiz)
Target readlink() handler.
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition: futex_map.hh:122
virtual int threadId() const =0
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:410
bool copyOut(PortProxy &memproxy)
copy data out of simulator space (write to target memory)
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target chdir() handler.
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr, int nbytes, int offset)
bool useForClone
Definition: process.hh:172
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target access() handler.
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:117
virtual ContextID contextId() const =0
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, socklen_t len)
void convertStat64Buf(target_stat &tgt, host_stat64 *host, ByteOrder bo, bool fakeTTY=false)
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr times)
Target utimes() handler.
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target stat() handler.
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Tick ns
nanosecond
Definition: core.cc:65
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:46
virtual void clearArchRegs()=0
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
uint8_t length
Definition: inet.hh:329
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, Addr tp_ptr)
Target clock_gettime() function.
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Holds file descriptors needed to simulate devices opened with pseudo files (commonly with calls to io...
Definition: fd_entry.hh:192
#define warn(...)
Definition: logging.hh:208
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr, int nbytes, int offset)
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr)
Target pipe() handler.
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, Addr start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it&#39;s used with.
Definition: syscall_emul.cc:79
Bitfield< 5 > t
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, int tgt_flags, int mode)
Target open() handler.
Bitfield< 4 > op
Definition: types.hh:78
This class represents the return value from an emulated system call, including any errno setting...
bool_vector8 mem[]
Definition: reset_stim.h:43
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, Addr bufPtr)
Target fstatat64() handler.
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, Addr addrlenPtr)
uint64_t tgid()
Definition: process.hh:88
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target stat64() handler.
void convertStatBuf(target_stat &tgt, host_stat *host, ByteOrder bo, bool fakeTTY=false)
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, size_t length)
Target munmap() handler.
Bitfield< 14, 12 > fd
Definition: types.hh:158
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
GenericISA::DelaySlotPCState< MachInst > PCState
Definition: types.hh:41
Bitfield< 0 > p
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
Target renameat() handler.
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...
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname)
Target unlinkat() handler.
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, int mode)
Target facessat() handler.
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
struct stat hst_stat
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, Addr tv_ptr, Addr tz_ptr)
Target gettimeofday() handler.
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Addr getPageBytes() const
Get the page bytes for the ISA.
Definition: system.hh:266
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode, dev_t dev)
Target mknod() handler.
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:437
std::shared_ptr< FDArray > fds
Definition: process.hh:276
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.

Generated on Fri Jul 3 2020 15:53:05 for gem5 by doxygen 1.8.13