gem5  v19.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 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  * Authors: Steve Reinhardt
42  * Kevin Lim
43  */
44 
45 #ifndef __SIM_SYSCALL_EMUL_HH__
46 #define __SIM_SYSCALL_EMUL_HH__
47 
48 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
49  defined(__FreeBSD__) || defined(__CYGWIN__) || \
50  defined(__NetBSD__))
51 #define NO_STAT64 1
52 #else
53 #define NO_STAT64 0
54 #endif
55 
61 
62 #if defined(__linux__)
63 #include <sys/eventfd.h>
64 #include <sys/statfs.h>
65 
66 #else
67 #include <sys/mount.h>
68 
69 #endif
70 
71 #ifdef __CYGWIN32__
72 #include <sys/fcntl.h>
73 
74 #endif
75 #include <fcntl.h>
76 #include <net/if.h>
77 #include <poll.h>
78 #include <sys/ioctl.h>
79 #include <sys/mman.h>
80 #include <sys/socket.h>
81 #include <sys/stat.h>
82 #include <sys/time.h>
83 #include <sys/types.h>
84 #include <sys/uio.h>
85 #include <unistd.h>
86 
87 #include <cerrno>
88 #include <memory>
89 #include <string>
90 
91 #include "arch/generic/tlb.hh"
92 #include "arch/utility.hh"
93 #include "base/intmath.hh"
95 #include "base/logging.hh"
96 #include "base/trace.hh"
97 #include "base/types.hh"
98 #include "config/the_isa.hh"
99 #include "cpu/base.hh"
100 #include "cpu/thread_context.hh"
101 #include "mem/page_table.hh"
102 #include "params/Process.hh"
103 #include "sim/emul_driver.hh"
104 #include "sim/futex_map.hh"
105 #include "sim/process.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 #endif
114 
116 //
117 // The following emulation functions are generic enough that they
118 // don't need to be recompiled for different emulated OS's. They are
119 // defined in sim/syscall_emul.cc.
120 //
122 
123 void warnUnsupportedOS(std::string syscall_name);
124 
127 
135 ignoreWarnOnceFunc(SyscallDesc *desc, int num, ThreadContext *tc);
136 
137 // Target fallocateFunc() handler.
139  int tgt_fd, int mode, off_t offset, off_t len);
140 
142 SyscallReturn exitFunc(SyscallDesc *desc, int num, ThreadContext *tc,
143  int status);
144 
147  int status);
148 
151  uint64_t tidPtr);
152 
155 
157 SyscallReturn brkFunc(SyscallDesc *desc, int num, ThreadContext *tc,
158  Addr new_brk);
159 
162  int tgt_fd);
163 
166  int tgt_fd, uint64_t offs, int whence);
167 
170  int tgt_fd, uint64_t offset_high,
171  uint32_t offset_low, Addr result_ptr, int whence);
172 
175 
178  int tgt_fd, int how);
179 
182  Addr buf_ptr, int name_len);
183 
186  Addr buf_ptr, unsigned long size);
187 
190  Addr pathname, Addr buf, size_t bufsiz);
191 
194  Addr pathname);
195 
197 SyscallReturn linkFunc(SyscallDesc *desc, int num, ThreadContext *tc,
198  Addr pathname, Addr new_pathname);
199 
202  Addr pathname, Addr new_pathname);
203 
206  Addr pathname, mode_t mode);
207 
210  Addr pathname, mode_t mode, dev_t dev);
211 
214  Addr pathname);
215 
216 // Target rmdir() handler.
218  Addr pathname);
219 
222  Addr oldpath, Addr newpath);
223 
224 
227  Addr pathname, off_t length);
228 
229 
232  int tgt_fd, off_t length);
233 
234 
237  Addr pathname, int64_t length);
238 
241 
242 
244 SyscallReturn umaskFunc(SyscallDesc *desc, int num, ThreadContext *tc);
245 
248 
251  Addr pathname, uint32_t owner, uint32_t group);
252 
255 
258  int pid, int pgid);
259 
262  int tgt_fd, uint32_t owner, uint32_t group);
263 
265 SyscallReturn dupFunc(SyscallDesc *desc, int num, ThreadContext *tc,
266  int tgt_fd);
267 
269 SyscallReturn dup2Func(SyscallDesc *desc, int num, ThreadContext *tc,
270  int old_tgt_fd, int new_tgt_fd);
271 
273 SyscallReturn fcntlFunc(SyscallDesc *desc, int num, ThreadContext *tc);
274 
277 
279 SyscallReturn pipeFunc(SyscallDesc *desc, int num, ThreadContext *tc);
280 
282 SyscallReturn pipeImpl(SyscallDesc *desc, int num, ThreadContext *tc,
283  bool pseudo_pipe, bool is_pipe2=false);
284 
286 SyscallReturn pipe2Func(SyscallDesc *desc, int num, ThreadContext *tc);
287 
290 
291 // Target getpeername() handler.
293  int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr);
294 
295 // Target bind() handler.
296 SyscallReturn bindFunc(SyscallDesc *desc, int num, ThreadContext *tc,
297  int tgt_fd, Addr buf_ptr, int addrlen);
298 
299 // Target listen() handler.
301  int tgt_fd, int backlog);
302 
303 // Target connect() handler.
305  int tgt_fd, Addr buf_ptr, int addrlen);
306 
307 #if defined(SYS_getdents)
308 // Target getdents() handler.
309 SyscallReturn getdentsFunc(SyscallDesc *desc, int num, ThreadContext *tc,
310  int tgt_fd, Addr buf_ptr, unsigned count);
311 #endif
312 
313 #if defined(SYS_getdents64)
314 // Target getdents() handler.
315 SyscallReturn getdents64Func(SyscallDesc *desc, int num, ThreadContext *tc,
316  int tgt_fd, Addr buf_ptr, unsigned count);
317 #endif
318 
319 // Target sendto() handler.
321  int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags,
322  Addr addrPtr, socklen_t addrLen);
323 
324 // Target recvfrom() handler.
326  int tgt_fd, Addr bufrPtr, size_t bufrLen,
327  int flags, Addr addrPtr, Addr addrlenPtr);
328 
329 // Target recvmsg() handler.
331  int tgt_fd, Addr msgPtr, int flags);
332 
333 // Target sendmsg() handler.
335  int tgt_fd, Addr msgPtr, int flags);
336 
337 // Target getuid() handler.
339 
342 
345 
348 
351 
354  Addr pathname, mode_t mode);
355 
356 // Target getsockopt() handler.
358  int tgt_fd, int level, int optname,
359  Addr valPtr, Addr lenPtr);
360 
361 // Target setsockopt() handler.
363  int tgt_fd, int level, int optname,
364  Addr valPtr, socklen_t len);
365 
366 // Target getsockname() handler.
368  int tgt_fd, Addr addrPtr, Addr lenPtr);
369 
373 template <class OS>
375 futexFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
376  Addr uaddr, int op, int val, int timeout, Addr uaddr2, int val3)
377 {
378  using namespace std;
379 
380  auto process = tc->getProcessPtr();
381 
382  /*
383  * Unsupported option that does not affect the correctness of the
384  * application. This is a performance optimization utilized by Linux.
385  */
386  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
387  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
388 
389  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
390 
391  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
392  // Ensure futex system call accessed atomically.
393  BufferArg buf(uaddr, sizeof(int));
394  buf.copyIn(tc->getVirtProxy());
395  int mem_val = *(int*)buf.bufferPtr();
396 
397  /*
398  * The value in memory at uaddr is not equal with the expected val
399  * (a different thread must have changed it before the system call was
400  * invoked). In this case, we need to throw an error.
401  */
402  if (val != mem_val)
403  return -OS::TGT_EWOULDBLOCK;
404 
405  if (OS::TGT_FUTEX_WAIT == op) {
406  futex_map.suspend(uaddr, process->tgid(), tc);
407  } else {
408  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
409  }
410 
411  return 0;
412  } else if (OS::TGT_FUTEX_WAKE == op) {
413  return futex_map.wakeup(uaddr, process->tgid(), val);
414  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
415  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
416  } else if (OS::TGT_FUTEX_REQUEUE == op ||
417  OS::TGT_FUTEX_CMP_REQUEUE == op) {
418 
419  // Ensure futex system call accessed atomically.
420  BufferArg buf(uaddr, sizeof(int));
421  buf.copyIn(tc->getVirtProxy());
422  int mem_val = *(int*)buf.bufferPtr();
423  /*
424  * For CMP_REQUEUE, the whole operation is only started only if
425  * val3 is still the value of the futex pointed to by uaddr.
426  */
427  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
428  return -OS::TGT_EWOULDBLOCK;
429  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
430  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
431  /*
432  * The FUTEX_WAKE_OP operation is equivalent to executing the
433  * following code atomically and totally ordered with respect to
434  * other futex operations on any of the two supplied futex words:
435  *
436  * int oldval = *(int *) addr2;
437  * *(int *) addr2 = oldval op oparg;
438  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
439  * if (oldval cmp cmparg)
440  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
441  *
442  * (op, oparg, cmp, cmparg are encoded in val3)
443  *
444  * +---+---+-----------+-----------+
445  * |op |cmp| oparg | cmparg |
446  * +---+---+-----------+-----------+
447  * 4 4 12 12 <== # of bits
448  *
449  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
450  *
451  */
452  // get value from simulated-space
453  BufferArg buf(uaddr2, sizeof(int));
454  buf.copyIn(tc->getVirtProxy());
455  int oldval = *(int*)buf.bufferPtr();
456  int newval = oldval;
457  // extract op, oparg, cmp, cmparg from val3
458  int wake_cmparg = val3 & 0xfff;
459  int wake_oparg = (val3 & 0xfff000) >> 12;
460  int wake_cmp = (val3 & 0xf000000) >> 24;
461  int wake_op = (val3 & 0xf0000000) >> 28;
462  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
463  wake_oparg = (1 << wake_oparg);
464  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
465  // perform operation on the value of the second futex
466  if (wake_op == OS::TGT_FUTEX_OP_SET)
467  newval = wake_oparg;
468  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
469  newval += wake_oparg;
470  else if (wake_op == OS::TGT_FUTEX_OP_OR)
471  newval |= wake_oparg;
472  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
473  newval &= ~wake_oparg;
474  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
475  newval ^= wake_oparg;
476  // copy updated value back to simulated-space
477  *(int*)buf.bufferPtr() = newval;
478  buf.copyOut(tc->getVirtProxy());
479  // perform the first wake-up
480  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
481  int woken2 = 0;
482  // calculate the condition of the second wake-up
483  bool is_wake2 = false;
484  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
485  is_wake2 = oldval == wake_cmparg;
486  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
487  is_wake2 = oldval != wake_cmparg;
488  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
489  is_wake2 = oldval < wake_cmparg;
490  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
491  is_wake2 = oldval <= wake_cmparg;
492  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
493  is_wake2 = oldval > wake_cmparg;
494  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
495  is_wake2 = oldval >= wake_cmparg;
496  // perform the second wake-up
497  if (is_wake2)
498  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
499 
500  return woken1 + woken2;
501  }
502  warn("futex: op %d not implemented; ignoring.", op);
503  return -ENOSYS;
504 }
505 
506 
510 
513 
516 
519 
520 
522 const int one_million = 1000000;
524 const int one_billion = 1000000000;
525 
529 const unsigned seconds_since_epoch = 1000000000;
530 
533 template <class T1, class T2>
534 void
535 getElapsedTimeMicro(T1 &sec, T2 &usec)
536 {
537  uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
538  sec = elapsed_usecs / one_million;
539  usec = elapsed_usecs % one_million;
540 }
541 
544 template <class T1, class T2>
545 void
546 getElapsedTimeNano(T1 &sec, T2 &nsec)
547 {
548  uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
549  sec = elapsed_nsecs / one_billion;
550  nsec = elapsed_nsecs % one_billion;
551 }
552 
554 //
555 // The following emulation functions are generic, but need to be
556 // templated to account for differences in types, constants, etc.
557 //
559 
560  typedef struct statfs hst_statfs;
561 #if NO_STAT64
562  typedef struct stat hst_stat;
563  typedef struct stat hst_stat64;
564 #else
565  typedef struct stat hst_stat;
566  typedef struct stat64 hst_stat64;
567 #endif
568 
572 
573 template <typename target_stat, typename host_stat>
574 void
575 convertStatBuf(target_stat &tgt, host_stat *host,
576  ByteOrder bo, bool fakeTTY=false)
577 {
578  if (fakeTTY)
579  tgt->st_dev = 0xA;
580  else
581  tgt->st_dev = host->st_dev;
582  tgt->st_dev = htog(tgt->st_dev, bo);
583  tgt->st_ino = host->st_ino;
584  tgt->st_ino = htog(tgt->st_ino, bo);
585  tgt->st_mode = host->st_mode;
586  if (fakeTTY) {
587  // Claim to be a character device
588  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
589  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
590  }
591  tgt->st_mode = htog(tgt->st_mode, bo);
592  tgt->st_nlink = host->st_nlink;
593  tgt->st_nlink = htog(tgt->st_nlink, bo);
594  tgt->st_uid = host->st_uid;
595  tgt->st_uid = htog(tgt->st_uid, bo);
596  tgt->st_gid = host->st_gid;
597  tgt->st_gid = htog(tgt->st_gid, bo);
598  if (fakeTTY)
599  tgt->st_rdev = 0x880d;
600  else
601  tgt->st_rdev = host->st_rdev;
602  tgt->st_rdev = htog(tgt->st_rdev, bo);
603  tgt->st_size = host->st_size;
604  tgt->st_size = htog(tgt->st_size, bo);
605  tgt->st_atimeX = host->st_atime;
606  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
607  tgt->st_mtimeX = host->st_mtime;
608  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
609  tgt->st_ctimeX = host->st_ctime;
610  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
611  // Force the block size to be 8KB. This helps to ensure buffered io works
612  // consistently across different hosts.
613  tgt->st_blksize = 0x2000;
614  tgt->st_blksize = htog(tgt->st_blksize, bo);
615  tgt->st_blocks = host->st_blocks;
616  tgt->st_blocks = htog(tgt->st_blocks, bo);
617 }
618 
619 // Same for stat64
620 
621 template <typename target_stat, typename host_stat64>
622 void
623 convertStat64Buf(target_stat &tgt, host_stat64 *host,
624  ByteOrder bo, bool fakeTTY=false)
625 {
626  convertStatBuf<target_stat, host_stat64>(tgt, host, bo, fakeTTY);
627 #if defined(STAT_HAVE_NSEC)
628  tgt->st_atime_nsec = host->st_atime_nsec;
629  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
630  tgt->st_mtime_nsec = host->st_mtime_nsec;
631  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
632  tgt->st_ctime_nsec = host->st_ctime_nsec;
633  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
634 #else
635  tgt->st_atime_nsec = 0;
636  tgt->st_mtime_nsec = 0;
637  tgt->st_ctime_nsec = 0;
638 #endif
639 }
640 
641 // Here are a couple of convenience functions
642 template<class OS>
643 void
645  hst_stat *host, bool fakeTTY = false)
646 {
647  typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
648  tgt_stat_buf tgt(addr);
649  convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, OS::byteOrder, fakeTTY);
650  tgt.copyOut(mem);
651 }
652 
653 template<class OS>
654 void
656  hst_stat64 *host, bool fakeTTY = false)
657 {
658  typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
659  tgt_stat_buf tgt(addr);
660  convertStat64Buf<tgt_stat_buf, hst_stat64>(
661  tgt, host, OS::byteOrder, fakeTTY);
662  tgt.copyOut(mem);
663 }
664 
665 template <class OS>
666 void
668  hst_statfs *host)
669 {
671 
672  const ByteOrder bo = OS::byteOrder;
673 
674  tgt->f_type = htog(host->f_type, bo);
675 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
676  tgt->f_bsize = htog(host->f_iosize, bo);
677 #else
678  tgt->f_bsize = htog(host->f_bsize, bo);
679 #endif
680  tgt->f_blocks = htog(host->f_blocks, bo);
681  tgt->f_bfree = htog(host->f_bfree, bo);
682  tgt->f_bavail = htog(host->f_bavail, bo);
683  tgt->f_files = htog(host->f_files, bo);
684  tgt->f_ffree = htog(host->f_ffree, bo);
685  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
686 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
687  tgt->f_namelen = htog(host->f_namemax, bo);
688  tgt->f_frsize = htog(host->f_bsize, bo);
689 #elif defined(__APPLE__)
690  tgt->f_namelen = 0;
691  tgt->f_frsize = 0;
692 #else
693  tgt->f_namelen = htog(host->f_namelen, bo);
694  tgt->f_frsize = htog(host->f_frsize, bo);
695 #endif
696 #if defined(__linux__)
697  memcpy(&tgt->f_spare, &host->f_spare, sizeof(host->f_spare));
698 #else
699  /*
700  * The fields are different sizes per OS. Don't bother with
701  * f_spare or f_reserved on non-Linux for now.
702  */
703  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
704 #endif
705 
706  tgt.copyOut(mem);
707 }
708 
713 template <class OS>
715 ioctlFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
716 {
717  int index = 0;
718  auto p = tc->getProcessPtr();
719 
720  int tgt_fd = p->getSyscallArg(tc, index);
721  unsigned req = p->getSyscallArg(tc, index);
722 
723  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
724 
725  if (OS::isTtyReq(req))
726  return -ENOTTY;
727 
728  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
729  if (dfdp) {
730  EmulatedDriver *emul_driver = dfdp->getDriver();
731  if (emul_driver)
732  return emul_driver->ioctl(tc, req);
733  }
734 
735  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
736  if (sfdp) {
737  int status;
738 
739  switch (req) {
740  case SIOCGIFCONF: {
741  Addr conf_addr = p->getSyscallArg(tc, index);
742  BufferArg conf_arg(conf_addr, sizeof(ifconf));
743  conf_arg.copyIn(tc->getVirtProxy());
744 
745  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
746  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
747  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
748  ifc_buf_arg.copyIn(tc->getVirtProxy());
749 
750  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
751 
752  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
753  if (status != -1) {
754  conf->ifc_buf = (char*)ifc_buf_addr;
755  ifc_buf_arg.copyOut(tc->getVirtProxy());
756  conf_arg.copyOut(tc->getVirtProxy());
757  }
758 
759  return status;
760  }
761  case SIOCGIFFLAGS:
762 #if defined(__linux__)
763  case SIOCGIFINDEX:
764 #endif
765  case SIOCGIFNETMASK:
766  case SIOCGIFADDR:
767 #if defined(__linux__)
768  case SIOCGIFHWADDR:
769 #endif
770  case SIOCGIFMTU: {
771  Addr req_addr = p->getSyscallArg(tc, index);
772  BufferArg req_arg(req_addr, sizeof(ifreq));
773  req_arg.copyIn(tc->getVirtProxy());
774 
775  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
776  if (status != -1)
777  req_arg.copyOut(tc->getVirtProxy());
778  return status;
779  }
780  }
781  }
782 
787  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
788  tgt_fd, req, tc->pcState());
789  return -ENOTTY;
790 }
791 
793 template <class OS>
795 openatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
796  int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
797 {
798  auto p = tc->getProcessPtr();
799 
804  std::string path;
805  if (!tc->getVirtProxy().tryReadString(path, pathname))
806  return -EFAULT;
807 
808 #ifdef __CYGWIN32__
809  int host_flags = O_BINARY;
810 #else
811  int host_flags = 0;
812 #endif
813 
817  for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
818  if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
819  tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
820  host_flags |= OS::openFlagTable[i].hostFlag;
821  }
822  }
823  if (tgt_flags)
824  warn("%s: cannot decode flags %#x", desc->name(), tgt_flags);
825 
826 #ifdef __CYGWIN32__
827  host_flags |= O_BINARY;
828 #endif
829 
842  std::string redir_path = path;
843  std::string abs_path = path;
844  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
845  abs_path = p->absolutePath(path, true);
846  redir_path = p->checkPathRedirect(path);
847  } else if (!startswith(path, "/")) {
848  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
849  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
850  if (!ffdp)
851  return -EBADF;
852  abs_path = ffdp->getFileName() + path;
853  redir_path = p->checkPathRedirect(abs_path);
854  }
855 
862  if (startswith(abs_path, "/dev/")) {
863  std::string filename = abs_path.substr(strlen("/dev/"));
864  EmulatedDriver *drv = p->findDriver(filename);
865  if (drv) {
866  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
867  "driver open with path[%s]\n",
868  desc->name(), abs_path.c_str());
869  return drv->open(tc, mode, host_flags);
870  }
875  }
876 
901  int sim_fd = -1;
902  std::string used_path;
903  std::vector<std::string> special_paths =
904  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd" };
905  for (auto entry : special_paths) {
906  if (startswith(path, entry)) {
907  sim_fd = OS::openSpecialFile(abs_path, p, tc);
908  used_path = abs_path;
909  }
910  }
911  if (sim_fd == -1) {
912  sim_fd = open(redir_path.c_str(), host_flags, mode);
913  used_path = redir_path;
914  }
915  if (sim_fd == -1) {
916  int local = -errno;
917  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
918  "(inferred from:%s)\n", desc->name(),
919  used_path.c_str(), path.c_str());
920  return local;
921  }
922 
931  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
932  int tgt_fd = p->fds->allocFD(ffdp);
933  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
934  "(inferred from:%s)\n", desc->name(),
935  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
936  return tgt_fd;
937 }
938 
940 template <class OS>
942 openFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
943  Addr pathname, int tgt_flags, int mode)
944 {
945  return openatFunc<OS>(desc, callnum, tc, OS::TGT_AT_FDCWD,
946  pathname, tgt_flags, mode);
947 }
948 
950 template <class OS>
952 unlinkatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
953  int dirfd, Addr pathname)
954 {
955  if (dirfd != OS::TGT_AT_FDCWD)
956  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
957 
958  return unlinkFunc(desc, callnum, tc, pathname);
959 }
960 
962 template <class OS>
964 faccessatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
965  int dirfd, Addr pathname, int mode)
966 {
967  if (dirfd != OS::TGT_AT_FDCWD)
968  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
969  return accessFunc(desc, callnum, tc, pathname, mode);
970 }
971 
973 template <class OS>
975 readlinkatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
976  int dirfd, Addr pathname, Addr buf, size_t bufsiz)
977 {
978  if (dirfd != OS::TGT_AT_FDCWD)
979  warn("openat: first argument not AT_FDCWD; unlikely to work");
980  return readlinkFunc(desc, callnum, tc, pathname, buf, bufsiz);
981 }
982 
984 template <class OS>
986 renameatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
987  int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
988 {
989  if (olddirfd != OS::TGT_AT_FDCWD)
990  warn("renameat: first argument not AT_FDCWD; unlikely to work");
991 
992  if (newdirfd != OS::TGT_AT_FDCWD)
993  warn("renameat: third argument not AT_FDCWD; unlikely to work");
994 
995  return renameFunc(desc, callnum, tc, oldpath, newpath);
996 }
997 
999 template <class OS>
1001 sysinfoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr info)
1002 {
1003  auto process = tc->getProcessPtr();
1004 
1006 
1007  sysinfo->uptime = seconds_since_epoch;
1008  sysinfo->totalram = process->system->memSize();
1009  sysinfo->mem_unit = 1;
1010 
1011  sysinfo.copyOut(tc->getVirtProxy());
1012 
1013  return 0;
1014 }
1015 
1017 template <class OS>
1019 chmodFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1020  Addr pathname, mode_t mode)
1021 {
1022  std::string path;
1023  auto process = tc->getProcessPtr();
1024 
1025  if (!tc->getVirtProxy().tryReadString(path, pathname))
1026  return -EFAULT;
1027 
1028  mode_t hostMode = 0;
1029 
1030  // XXX translate mode flags via OS::something???
1031  hostMode = mode;
1032 
1033  // Adjust path for cwd and redirection
1034  path = process->checkPathRedirect(path);
1035 
1036  // do the chmod
1037  int result = chmod(path.c_str(), hostMode);
1038  if (result < 0)
1039  return -errno;
1040 
1041  return 0;
1042 }
1043 
1044 template <class OS>
1046 pollFunc(SyscallDesc *desc, int num, ThreadContext *tc,
1047  Addr fdsPtr, int nfds, int tmout)
1048 {
1049  auto p = tc->getProcessPtr();
1050 
1051  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1052  fdsBuf.copyIn(tc->getVirtProxy());
1053 
1060  int temp_tgt_fds[nfds];
1061  for (int index = 0; index < nfds; index++) {
1062  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1063  auto tgt_fd = temp_tgt_fds[index];
1064  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1065  if (!hbfdp)
1066  return -EBADF;
1067  auto host_fd = hbfdp->getSimFD();
1068  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1069  }
1070 
1077  int status;
1078  if (tmout < 0) {
1079  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1080  if (status == 0) {
1086  System *sysh = tc->getSystemPtr();
1088  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1089  if (it->receiver == p)
1090  return -EINTR;
1091  return SyscallReturn::retry();
1092  }
1093  } else
1094  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1095 
1096  if (status == -1)
1097  return -errno;
1098 
1103  for (int index = 0; index < nfds; index++) {
1104  auto tgt_fd = temp_tgt_fds[index];
1105  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1106  }
1107 
1112  fdsBuf.copyOut(tc->getVirtProxy());
1113 
1114  return status;
1115 }
1116 
1118 template <class OS>
1120 fchmodFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1121  int tgt_fd, uint32_t mode)
1122 {
1123  auto p = tc->getProcessPtr();
1124 
1125  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1126  if (!ffdp)
1127  return -EBADF;
1128  int sim_fd = ffdp->getSimFD();
1129 
1130  mode_t hostMode = mode;
1131 
1132  int result = fchmod(sim_fd, hostMode);
1133 
1134  return (result < 0) ? -errno : 0;
1135 }
1136 
1138 template <class OS>
1140 mremapFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
1141 {
1142  int index = 0;
1143  auto process = tc->getProcessPtr();
1144  Addr start = process->getSyscallArg(tc, index);
1145  uint64_t old_length = process->getSyscallArg(tc, index);
1146  uint64_t new_length = process->getSyscallArg(tc, index);
1147  uint64_t flags = process->getSyscallArg(tc, index);
1148  uint64_t provided_address = 0;
1149  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1150 
1151  if (use_provided_address)
1152  provided_address = process->getSyscallArg(tc, index);
1153 
1154  if ((start % TheISA::PageBytes != 0) ||
1155  (provided_address % TheISA::PageBytes != 0)) {
1156  warn("mremap failing: arguments not page aligned");
1157  return -EINVAL;
1158  }
1159 
1160  new_length = roundUp(new_length, TheISA::PageBytes);
1161 
1162  if (new_length > old_length) {
1163  std::shared_ptr<MemState> mem_state = process->memState;
1164  Addr mmap_end = mem_state->getMmapEnd();
1165 
1166  if ((start + old_length) == mmap_end &&
1167  (!use_provided_address || provided_address == start)) {
1168  // This case cannot occur when growing downward, as
1169  // start is greater than or equal to mmap_end.
1170  uint64_t diff = new_length - old_length;
1171  process->allocateMem(mmap_end, diff);
1172  mem_state->setMmapEnd(mmap_end + diff);
1173  return start;
1174  } else {
1175  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1176  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1177  return -ENOMEM;
1178  } else {
1179  uint64_t new_start = provided_address;
1180  if (!use_provided_address) {
1181  new_start = process->mmapGrowsDown() ?
1182  mmap_end - new_length : mmap_end;
1183  mmap_end = process->mmapGrowsDown() ?
1184  new_start : mmap_end + new_length;
1185  mem_state->setMmapEnd(mmap_end);
1186  }
1187 
1188  process->pTable->remap(start, old_length, new_start);
1189  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1190  new_start, new_start + new_length,
1191  new_length - old_length);
1192  // add on the remaining unallocated pages
1193  process->allocateMem(new_start + old_length,
1194  new_length - old_length,
1195  use_provided_address /* clobber */);
1196  if (use_provided_address &&
1197  ((new_start + new_length > mem_state->getMmapEnd() &&
1198  !process->mmapGrowsDown()) ||
1199  (new_start < mem_state->getMmapEnd() &&
1200  process->mmapGrowsDown()))) {
1201  // something fishy going on here, at least notify the user
1202  // @todo: increase mmap_end?
1203  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1204  }
1205  warn("returning %08p as start\n", new_start);
1206  return new_start;
1207  }
1208  }
1209  } else {
1210  if (use_provided_address && provided_address != start)
1211  process->pTable->remap(start, new_length, provided_address);
1212  process->pTable->unmap(start + new_length, old_length - new_length);
1213  return use_provided_address ? provided_address : start;
1214  }
1215 }
1216 
1218 template <class OS>
1220 statFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1221  Addr pathname, Addr bufPtr)
1222 {
1223  std::string path;
1224  auto process = tc->getProcessPtr();
1225 
1226  if (!tc->getVirtProxy().tryReadString(path, pathname))
1227  return -EFAULT;
1228 
1229  // Adjust path for cwd and redirection
1230  path = process->checkPathRedirect(path);
1231 
1232  struct stat hostBuf;
1233  int result = stat(path.c_str(), &hostBuf);
1234 
1235  if (result < 0)
1236  return -errno;
1237 
1238  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1239 
1240  return 0;
1241 }
1242 
1243 
1245 template <class OS>
1247 stat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc,
1248  Addr pathname, Addr bufPtr)
1249 {
1250  std::string path;
1251  auto process = tc->getProcessPtr();
1252 
1253  if (!tc->getVirtProxy().tryReadString(path, pathname))
1254  return -EFAULT;
1255 
1256  // Adjust path for cwd and redirection
1257  path = process->checkPathRedirect(path);
1258 
1259 #if NO_STAT64
1260  struct stat hostBuf;
1261  int result = stat(path.c_str(), &hostBuf);
1262 #else
1263  struct stat64 hostBuf;
1264  int result = stat64(path.c_str(), &hostBuf);
1265 #endif
1266 
1267  if (result < 0)
1268  return -errno;
1269 
1270  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1271 
1272  return 0;
1273 }
1274 
1275 
1277 template <class OS>
1279 fstatat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc,
1280  int dirfd, Addr pathname, Addr bufPtr)
1281 {
1282  auto process = tc->getProcessPtr();
1283  if (dirfd != OS::TGT_AT_FDCWD)
1284  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1285 
1286  std::string path;
1287  if (!tc->getVirtProxy().tryReadString(path, pathname))
1288  return -EFAULT;
1289 
1290  // Adjust path for cwd and redirection
1291  path = process->checkPathRedirect(path);
1292 
1293 #if NO_STAT64
1294  struct stat hostBuf;
1295  int result = stat(path.c_str(), &hostBuf);
1296 #else
1297  struct stat64 hostBuf;
1298  int result = stat64(path.c_str(), &hostBuf);
1299 #endif
1300 
1301  if (result < 0)
1302  return -errno;
1303 
1304  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1305 
1306  return 0;
1307 }
1308 
1309 
1311 template <class OS>
1313 fstat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc,
1314  int tgt_fd, Addr bufPtr)
1315 {
1316  auto p = tc->getProcessPtr();
1317 
1318  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1319  if (!ffdp)
1320  return -EBADF;
1321  int sim_fd = ffdp->getSimFD();
1322 
1323 #if NO_STAT64
1324  struct stat hostBuf;
1325  int result = fstat(sim_fd, &hostBuf);
1326 #else
1327  struct stat64 hostBuf;
1328  int result = fstat64(sim_fd, &hostBuf);
1329 #endif
1330 
1331  if (result < 0)
1332  return -errno;
1333 
1334  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1335 
1336  return 0;
1337 }
1338 
1339 
1341 template <class OS>
1343 lstatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1344  Addr pathname, Addr bufPtr)
1345 {
1346  std::string path;
1347  auto process = tc->getProcessPtr();
1348 
1349  if (!tc->getVirtProxy().tryReadString(path, pathname))
1350  return -EFAULT;
1351 
1352  // Adjust path for cwd and redirection
1353  path = process->checkPathRedirect(path);
1354 
1355  struct stat hostBuf;
1356  int result = lstat(path.c_str(), &hostBuf);
1357 
1358  if (result < 0)
1359  return -errno;
1360 
1361  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1362 
1363  return 0;
1364 }
1365 
1367 template <class OS>
1369 lstat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc,
1370  Addr pathname, Addr bufPtr)
1371 {
1372  std::string path;
1373  auto process = tc->getProcessPtr();
1374 
1375  if (!tc->getVirtProxy().tryReadString(path, pathname))
1376  return -EFAULT;
1377 
1378  // Adjust path for cwd and redirection
1379  path = process->checkPathRedirect(path);
1380 
1381 #if NO_STAT64
1382  struct stat hostBuf;
1383  int result = lstat(path.c_str(), &hostBuf);
1384 #else
1385  struct stat64 hostBuf;
1386  int result = lstat64(path.c_str(), &hostBuf);
1387 #endif
1388 
1389  if (result < 0)
1390  return -errno;
1391 
1392  copyOutStat64Buf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1393 
1394  return 0;
1395 }
1396 
1398 template <class OS>
1400 fstatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1401  int tgt_fd, Addr bufPtr)
1402 {
1403  auto p = tc->getProcessPtr();
1404 
1405  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1406 
1407  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1408  if (!ffdp)
1409  return -EBADF;
1410  int sim_fd = ffdp->getSimFD();
1411 
1412  struct stat hostBuf;
1413  int result = fstat(sim_fd, &hostBuf);
1414 
1415  if (result < 0)
1416  return -errno;
1417 
1418  copyOutStatBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1419 
1420  return 0;
1421 }
1422 
1424 template <class OS>
1426 statfsFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1427  Addr pathname, Addr bufPtr)
1428 {
1429 #if defined(__linux__)
1430  std::string path;
1431  auto process = tc->getProcessPtr();
1432 
1433  if (!tc->getVirtProxy().tryReadString(path, pathname))
1434  return -EFAULT;
1435 
1436  // Adjust path for cwd and redirection
1437  path = process->checkPathRedirect(path);
1438 
1439  struct statfs hostBuf;
1440  int result = statfs(path.c_str(), &hostBuf);
1441 
1442  if (result < 0)
1443  return -errno;
1444 
1445  copyOutStatfsBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1446  return 0;
1447 #else
1448  warnUnsupportedOS("statfs");
1449  return -1;
1450 #endif
1451 }
1452 
1453 template <class OS>
1455 cloneFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
1456 {
1457  int index = 0;
1458 
1459  auto p = tc->getProcessPtr();
1460  RegVal flags = p->getSyscallArg(tc, index);
1461  RegVal newStack = p->getSyscallArg(tc, index);
1462  Addr ptidPtr = p->getSyscallArg(tc, index);
1463 
1464 #if THE_ISA == RISCV_ISA or THE_ISA == ARM_ISA
1465 
1470  Addr tlsPtr = p->getSyscallArg(tc, index);
1471  Addr ctidPtr = p->getSyscallArg(tc, index);
1472 #else
1473  Addr ctidPtr = p->getSyscallArg(tc, index);
1474  Addr tlsPtr = p->getSyscallArg(tc, index);
1475 #endif
1476 
1477  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1478  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1479  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1480  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1481  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1482  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1483  return -EINVAL;
1484 
1485  ThreadContext *ctc;
1486  if (!(ctc = tc->getSystemPtr()->findFreeContext())) {
1487  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1488  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1489  return -EAGAIN;
1490  }
1491 
1498  ProcessParams *pp = new ProcessParams();
1499  pp->executable.assign(*(new std::string(p->progName())));
1500  pp->cmd.push_back(*(new std::string(p->progName())));
1501  pp->system = p->system;
1502  pp->cwd.assign(p->tgtCwd);
1503  pp->input.assign("stdin");
1504  pp->output.assign("stdout");
1505  pp->errout.assign("stderr");
1506  pp->uid = p->uid();
1507  pp->euid = p->euid();
1508  pp->gid = p->gid();
1509  pp->egid = p->egid();
1510 
1511  /* Find the first free PID that's less than the maximum */
1512  std::set<int> const& pids = p->system->PIDs;
1513  int temp_pid = *pids.begin();
1514  do {
1515  temp_pid++;
1516  } while (pids.find(temp_pid) != pids.end());
1517  if (temp_pid >= System::maxPID)
1518  fatal("temp_pid is too large: %d", temp_pid);
1519 
1520  pp->pid = temp_pid;
1521  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1522  pp->useArchPT = p->useArchPT;
1523  pp->kvmInSE = p->kvmInSE;
1524  Process *cp = pp->create();
1525  // TODO: there is no way to know when the Process SimObject is done with
1526  // the params pointer. Both the params pointer (pp) and the process
1527  // pointer (cp) are normally managed in python and are never cleaned up.
1528 
1529  Process *owner = ctc->getProcessPtr();
1530  ctc->setProcessPtr(cp);
1531  cp->assignThreadContext(ctc->contextId());
1532  owner->revokeThreadContext(ctc->contextId());
1533 
1534  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1535  BufferArg ptidBuf(ptidPtr, sizeof(long));
1536  long *ptid = (long *)ptidBuf.bufferPtr();
1537  *ptid = cp->pid();
1538  ptidBuf.copyOut(tc->getVirtProxy());
1539  }
1540 
1541  if (flags & OS::TGT_CLONE_THREAD) {
1542  cp->pTable->shared = true;
1543  cp->useForClone = true;
1544  }
1545  cp->initState();
1546  p->clone(tc, ctc, cp, flags);
1547 
1548  if (flags & OS::TGT_CLONE_THREAD) {
1549  delete cp->sigchld;
1550  cp->sigchld = p->sigchld;
1551  } else if (flags & OS::TGT_SIGCHLD) {
1552  *cp->sigchld = true;
1553  }
1554 
1555  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1556  BufferArg ctidBuf(ctidPtr, sizeof(long));
1557  long *ctid = (long *)ctidBuf.bufferPtr();
1558  *ctid = cp->pid();
1559  ctidBuf.copyOut(ctc->getVirtProxy());
1560  }
1561 
1562  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1563  cp->childClearTID = (uint64_t)ctidPtr;
1564 
1565  ctc->clearArchRegs();
1566 
1567  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1568 
1569  cp->setSyscallReturn(ctc, 0);
1570 
1571 #if THE_ISA == ALPHA_ISA
1573 #elif THE_ISA == SPARC_ISA
1576 #endif
1577 
1578  if (p->kvmInSE) {
1579 #if THE_ISA == X86_ISA
1580  ctc->pcState(tc->readIntReg(TheISA::INTREG_RCX));
1581 #else
1582  panic("KVM CPU model is not supported for this ISA");
1583 #endif
1584  } else {
1585  TheISA::PCState cpc = tc->pcState();
1586  cpc.advance();
1587  ctc->pcState(cpc);
1588  }
1589  ctc->activate();
1590 
1591  return cp->pid();
1592 }
1593 
1595 template <class OS>
1597 fstatfsFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1598  int tgt_fd, Addr bufPtr)
1599 {
1600  auto p = tc->getProcessPtr();
1601 
1602  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1603  if (!ffdp)
1604  return -EBADF;
1605  int sim_fd = ffdp->getSimFD();
1606 
1607  struct statfs hostBuf;
1608  int result = fstatfs(sim_fd, &hostBuf);
1609 
1610  if (result < 0)
1611  return -errno;
1612 
1613  copyOutStatfsBuf<OS>(tc->getVirtProxy(), bufPtr, &hostBuf);
1614 
1615  return 0;
1616 }
1617 
1619 template <class OS>
1621 readvFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1622  int tgt_fd, uint64_t tiov_base, size_t count)
1623 {
1624  auto p = tc->getProcessPtr();
1625 
1626  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1627  if (!ffdp)
1628  return -EBADF;
1629  int sim_fd = ffdp->getSimFD();
1630 
1631  PortProxy &prox = tc->getVirtProxy();
1632  typename OS::tgt_iovec tiov[count];
1633  struct iovec hiov[count];
1634  for (size_t i = 0; i < count; ++i) {
1635  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1636  &tiov[i], sizeof(typename OS::tgt_iovec));
1637  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1638  hiov[i].iov_base = new char [hiov[i].iov_len];
1639  }
1640 
1641  int result = readv(sim_fd, hiov, count);
1642  int local_errno = errno;
1643 
1644  for (size_t i = 0; i < count; ++i) {
1645  if (result != -1) {
1646  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1647  hiov[i].iov_base, hiov[i].iov_len);
1648  }
1649  delete [] (char *)hiov[i].iov_base;
1650  }
1651 
1652  return (result == -1) ? -local_errno : result;
1653 }
1654 
1656 template <class OS>
1658 writevFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1659  int tgt_fd, uint64_t tiov_base, size_t count)
1660 {
1661  auto p = tc->getProcessPtr();
1662 
1663  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1664  if (!hbfdp)
1665  return -EBADF;
1666  int sim_fd = hbfdp->getSimFD();
1667 
1668  PortProxy &prox = tc->getVirtProxy();
1669  struct iovec hiov[count];
1670  for (size_t i = 0; i < count; ++i) {
1671  typename OS::tgt_iovec tiov;
1672 
1673  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1674  &tiov, sizeof(typename OS::tgt_iovec));
1675  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1676  hiov[i].iov_base = new char [hiov[i].iov_len];
1677  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1678  hiov[i].iov_len);
1679  }
1680 
1681  int result = writev(sim_fd, hiov, count);
1682 
1683  for (size_t i = 0; i < count; ++i)
1684  delete [] (char *)hiov[i].iov_base;
1685 
1686  return (result == -1) ? -errno : result;
1687 }
1688 
1690 template <class OS>
1692 mmapFunc(SyscallDesc *desc, int num, ThreadContext *tc,
1693  Addr start, uint64_t length, int prot, int tgt_flags,
1694  int tgt_fd, int offset)
1695 {
1696  auto p = tc->getProcessPtr();
1697 
1698  if (start & (TheISA::PageBytes - 1) ||
1699  offset & (TheISA::PageBytes - 1) ||
1700  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1701  tgt_flags & OS::TGT_MAP_SHARED) ||
1702  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1703  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1704  !length) {
1705  return -EINVAL;
1706  }
1707 
1708  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1709  // With shared mmaps, there are two cases to consider:
1710  // 1) anonymous: writes should modify the mapping and this should be
1711  // visible to observers who share the mapping. Currently, it's
1712  // difficult to update the shared mapping because there's no
1713  // structure which maintains information about the which virtual
1714  // memory areas are shared. If that structure existed, it would be
1715  // possible to make the translations point to the same frames.
1716  // 2) file-backed: writes should modify the mapping and the file
1717  // which is backed by the mapping. The shared mapping problem is the
1718  // same as what was mentioned about the anonymous mappings. For
1719  // file-backed mappings, the writes to the file are difficult
1720  // because it requires syncing what the mapping holds with the file
1721  // that resides on the host system. So, any write on a real system
1722  // would cause the change to be propagated to the file mapping at
1723  // some point in the future (the inode is tracked along with the
1724  // mapping). This isn't guaranteed to always happen, but it usually
1725  // works well enough. The guarantee is provided by the msync system
1726  // call. We could force the change through with shared mappings with
1727  // a call to msync, but that again would require more information
1728  // than we currently maintain.
1729  warn("mmap: writing to shared mmap region is currently "
1730  "unsupported. The write succeeds on the target, but it "
1731  "will not be propagated to the host or shared mappings");
1732  }
1733 
1734  length = roundUp(length, TheISA::PageBytes);
1735 
1736  int sim_fd = -1;
1737  uint8_t *pmap = nullptr;
1738  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1739  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1740 
1741  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1742  if (dfdp) {
1743  EmulatedDriver *emul_driver = dfdp->getDriver();
1744  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1745  tgt_fd, offset);
1746  }
1747 
1748  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1749  if (!ffdp)
1750  return -EBADF;
1751  sim_fd = ffdp->getSimFD();
1752 
1753  pmap = (decltype(pmap))mmap(nullptr, length, PROT_READ, MAP_PRIVATE,
1754  sim_fd, offset);
1755 
1756  if (pmap == (decltype(pmap))-1) {
1757  warn("mmap: failed to map file into host address space");
1758  return -errno;
1759  }
1760  }
1761 
1762  // Extend global mmap region if necessary. Note that we ignore the
1763  // start address unless MAP_FIXED is specified.
1764  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1765  std::shared_ptr<MemState> mem_state = p->memState;
1766  Addr mmap_end = mem_state->getMmapEnd();
1767 
1768  start = p->mmapGrowsDown() ? mmap_end - length : mmap_end;
1769  mmap_end = p->mmapGrowsDown() ? start : mmap_end + length;
1770 
1771  mem_state->setMmapEnd(mmap_end);
1772  }
1773 
1774  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1775  start, start + length - 1);
1776 
1777  // We only allow mappings to overwrite existing mappings if
1778  // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem
1779  // because we ignore the start hint if TGT_MAP_FIXED is not set.
1780  int clobber = tgt_flags & OS::TGT_MAP_FIXED;
1781  if (clobber) {
1782  for (auto tc : p->system->threadContexts) {
1783  // If we might be overwriting old mappings, we need to
1784  // invalidate potentially stale mappings out of the TLBs.
1785  tc->getDTBPtr()->flushAll();
1786  tc->getITBPtr()->flushAll();
1787  }
1788  }
1789 
1790  // Allocate physical memory and map it in. If the page table is already
1791  // mapped and clobber is not set, the simulator will issue throw a
1792  // fatal and bail out of the simulation.
1793  p->allocateMem(start, length, clobber);
1794 
1795  // Transfer content into target address space.
1796  PortProxy &tp = tc->getVirtProxy();
1797  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1798  // In general, we should zero the mapped area for anonymous mappings,
1799  // with something like:
1800  // tp.memsetBlob(start, 0, length);
1801  // However, given that we don't support sparse mappings, and
1802  // some applications can map a couple of gigabytes of space
1803  // (intending sparse usage), that can get painfully expensive.
1804  // Fortunately, since we don't properly implement munmap either,
1805  // there's no danger of remapping used memory, so for now all
1806  // newly mapped memory should already be zeroed so we can skip it.
1807  } else {
1808  // It is possible to mmap an area larger than a file, however
1809  // accessing unmapped portions the system triggers a "Bus error"
1810  // on the host. We must know when to stop copying the file from
1811  // the host into the target address space.
1812  struct stat file_stat;
1813  if (fstat(sim_fd, &file_stat) > 0)
1814  fatal("mmap: cannot stat file");
1815 
1816  // Copy the portion of the file that is resident. This requires
1817  // checking both the mmap size and the filesize that we are
1818  // trying to mmap into this space; the mmap size also depends
1819  // on the specified offset into the file.
1820  uint64_t size = std::min((uint64_t)file_stat.st_size - offset,
1821  length);
1822  tp.writeBlob(start, pmap, size);
1823 
1824  // Cleanup the mmap region before exiting this function.
1825  munmap(pmap, length);
1826 
1827  // Maintain the symbol table for dynamic executables.
1828  // The loader will call mmap to map the images into its address
1829  // space and we intercept that here. We can verify that we are
1830  // executing inside the loader by checking the program counter value.
1831  // XXX: with multiprogrammed workloads or multi-node configurations,
1832  // this will not work since there is a single global symbol table.
1833  if (p->interpImage.contains(tc->pcState().instAddr())) {
1834  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1835  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1836  auto process = tc->getProcessPtr();
1838  process->checkPathRedirect(
1839  ffdp->getFileName()));
1840 
1841  if (lib) {
1843  lib->buildImage().minAddr(), start);
1844  }
1845  }
1846 
1847  // Note that we do not zero out the remainder of the mapping. This
1848  // is done by a real system, but it probably will not affect
1849  // execution (hopefully).
1850  }
1851 
1852  return start;
1853 }
1854 
1855 template <class OS>
1858  int tgt_fd, Addr bufPtr, int nbytes, int offset)
1859 {
1860  auto p = tc->getProcessPtr();
1861 
1862  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1863  if (!ffdp)
1864  return -EBADF;
1865  int sim_fd = ffdp->getSimFD();
1866 
1867  BufferArg bufArg(bufPtr, nbytes);
1868  bufArg.copyIn(tc->getVirtProxy());
1869 
1870  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1871 
1872  return (bytes_written == -1) ? -errno : bytes_written;
1873 }
1874 
1876 template <class OS>
1879  Addr start, uint64_t length, int prot, int tgt_flags,
1880  int tgt_fd, int offset)
1881 {
1882  return mmapFunc<OS>(desc, num, tc, start, length, prot, tgt_flags,
1883  tgt_fd, offset * tc->getSystemPtr()->getPageBytes());
1884 }
1885 
1887 template <class OS>
1889 getrlimitFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1890  unsigned resource, Addr rlim)
1891 {
1893 
1894  const ByteOrder bo = OS::byteOrder;
1895  switch (resource) {
1896  case OS::TGT_RLIMIT_STACK:
1897  // max stack size in bytes: make up a number (8MB for now)
1898  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1899  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1900  rlp->rlim_max = htog(rlp->rlim_max, bo);
1901  break;
1902 
1903  case OS::TGT_RLIMIT_DATA:
1904  // max data segment size in bytes: make up a number
1905  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1906  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1907  rlp->rlim_max = htog(rlp->rlim_max, bo);
1908  break;
1909 
1910  case OS::TGT_RLIMIT_NPROC:
1911  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->numContexts();
1912  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1913  rlp->rlim_max = htog(rlp->rlim_max, bo);
1914  break;
1915 
1916  default:
1917  warn("getrlimit: unimplemented resource %d", resource);
1918  return -EINVAL;
1919  break;
1920  }
1921 
1922  rlp.copyOut(tc->getVirtProxy());
1923  return 0;
1924 }
1925 
1926 template <class OS>
1928 prlimitFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
1929  int pid, int resource, Addr n, Addr o)
1930 {
1931  if (pid != 0) {
1932  warn("prlimit: ignoring rlimits for nonzero pid");
1933  return -EPERM;
1934  }
1935  if (n != 0)
1936  warn("prlimit: ignoring new rlimit");
1937  if (o != 0) {
1938  const ByteOrder bo = OS::byteOrder;
1940  switch (resource) {
1941  case OS::TGT_RLIMIT_STACK:
1942  // max stack size in bytes: make up a number (8MB for now)
1943  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1944  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1945  rlp->rlim_max = htog(rlp->rlim_max, bo);
1946  break;
1947  case OS::TGT_RLIMIT_DATA:
1948  // max data segment size in bytes: make up a number
1949  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1950  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1951  rlp->rlim_max = htog(rlp->rlim_max, bo);
1952  break;
1953  default:
1954  warn("prlimit: unimplemented resource %d", resource);
1955  return -EINVAL;
1956  break;
1957  }
1958  rlp.copyOut(tc->getVirtProxy());
1959  }
1960  return 0;
1961 }
1962 
1964 template <class OS>
1967  int clk_id, Addr tp_ptr)
1968 {
1970 
1971  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1972  tp->tv_sec += seconds_since_epoch;
1973  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1974  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
1975 
1976  tp.copyOut(tc->getVirtProxy());
1977 
1978  return 0;
1979 }
1980 
1982 template <class OS>
1985  int clk_id, Addr tp_ptr)
1986 {
1988 
1989  // Set resolution at ns, which is what clock_gettime() returns
1990  tp->tv_sec = 0;
1991  tp->tv_nsec = 1;
1992 
1993  tp.copyOut(tc->getVirtProxy());
1994 
1995  return 0;
1996 }
1997 
1999 template <class OS>
2002  Addr tv_ptr, Addr tz_ptr)
2003 {
2005 
2006  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
2007  tp->tv_sec += seconds_since_epoch;
2008  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2009  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
2010 
2011  tp.copyOut(tc->getVirtProxy());
2012 
2013  return 0;
2014 }
2015 
2016 
2018 template <class OS>
2020 utimesFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
2021  Addr pathname, Addr times)
2022 {
2023  std::string path;
2024  auto process = tc->getProcessPtr();
2025 
2026  if (!tc->getVirtProxy().tryReadString(path, pathname))
2027  return -EFAULT;
2028 
2030  tp.copyIn(tc->getVirtProxy());
2031 
2032  struct timeval hostTimeval[2];
2033  for (int i = 0; i < 2; ++i) {
2034  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
2035  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
2036  }
2037 
2038  // Adjust path for cwd and redirection
2039  path = process->checkPathRedirect(path);
2040 
2041  int result = utimes(path.c_str(), hostTimeval);
2042 
2043  if (result < 0)
2044  return -errno;
2045 
2046  return 0;
2047 }
2048 
2049 template <class OS>
2051 execveFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
2052  Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
2053 {
2054  auto p = tc->getProcessPtr();
2055 
2056  std::string path;
2057  PortProxy & mem_proxy = tc->getVirtProxy();
2058  if (!mem_proxy.tryReadString(path, pathname))
2059  return -EFAULT;
2060 
2061  if (access(path.c_str(), F_OK) == -1)
2062  return -EACCES;
2063 
2064  auto read_in = [](std::vector<std::string> &vect,
2065  PortProxy &mem_proxy, Addr mem_loc)
2066  {
2067  for (int inc = 0; ; inc++) {
2068  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2069  b.copyIn(mem_proxy);
2070 
2071  if (!*(Addr*)b.bufferPtr())
2072  break;
2073 
2074  vect.push_back(std::string());
2075  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2076  }
2077  };
2078 
2085  ProcessParams *pp = new ProcessParams();
2086  pp->executable = path;
2087  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2088  read_in(pp->env, mem_proxy, envp_mem_loc);
2089  pp->uid = p->uid();
2090  pp->egid = p->egid();
2091  pp->euid = p->euid();
2092  pp->gid = p->gid();
2093  pp->ppid = p->ppid();
2094  pp->pid = p->pid();
2095  pp->input.assign("cin");
2096  pp->output.assign("cout");
2097  pp->errout.assign("cerr");
2098  pp->cwd.assign(p->tgtCwd);
2099  pp->system = p->system;
2108  p->system->PIDs.erase(p->pid());
2109  Process *new_p = pp->create();
2110  delete pp;
2111 
2116  new_p->fds = p->fds;
2117  for (int i = 0; i < new_p->fds->getSize(); i++) {
2118  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2119  if (fdep && fdep->getCOE())
2120  new_p->fds->closeFDEntry(i);
2121  }
2122 
2123  *new_p->sigchld = true;
2124 
2125  delete p;
2126  tc->clearArchRegs();
2127  tc->setProcessPtr(new_p);
2128  new_p->assignThreadContext(tc->contextId());
2129  new_p->initState();
2130  tc->activate();
2131  TheISA::PCState pcState = tc->pcState();
2132  tc->setNPC(pcState.instAddr());
2133 
2134  return SyscallReturn();
2135 }
2136 
2138 template <class OS>
2140 getrusageFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
2141  int who /* THREAD, SELF, or CHILDREN */, Addr usage)
2142 {
2144 
2145  rup->ru_utime.tv_sec = 0;
2146  rup->ru_utime.tv_usec = 0;
2147  rup->ru_stime.tv_sec = 0;
2148  rup->ru_stime.tv_usec = 0;
2149  rup->ru_maxrss = 0;
2150  rup->ru_ixrss = 0;
2151  rup->ru_idrss = 0;
2152  rup->ru_isrss = 0;
2153  rup->ru_minflt = 0;
2154  rup->ru_majflt = 0;
2155  rup->ru_nswap = 0;
2156  rup->ru_inblock = 0;
2157  rup->ru_oublock = 0;
2158  rup->ru_msgsnd = 0;
2159  rup->ru_msgrcv = 0;
2160  rup->ru_nsignals = 0;
2161  rup->ru_nvcsw = 0;
2162  rup->ru_nivcsw = 0;
2163 
2164  switch (who) {
2165  case OS::TGT_RUSAGE_SELF:
2166  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2167  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2168  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2169  break;
2170 
2171  case OS::TGT_RUSAGE_CHILDREN:
2172  // do nothing. We have no child processes, so they take no time.
2173  break;
2174 
2175  default:
2176  // don't really handle THREAD or CHILDREN, but just warn and
2177  // plow ahead
2178  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2179  who);
2180  }
2181 
2182  rup.copyOut(tc->getVirtProxy());
2183 
2184  return 0;
2185 }
2186 
2188 template <class OS>
2190 timesFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr bufPtr)
2191 {
2192  TypedBufferArg<typename OS::tms> bufp(bufPtr);
2193 
2194  // Fill in the time structure (in clocks)
2195  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
2196  bufp->tms_utime = clocks;
2197  bufp->tms_stime = 0;
2198  bufp->tms_cutime = 0;
2199  bufp->tms_cstime = 0;
2200 
2201  // Convert to host endianness
2202  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2203 
2204  // Write back
2205  bufp.copyOut(tc->getVirtProxy());
2206 
2207  // Return clock ticks since system boot
2208  return clocks;
2209 }
2210 
2212 template <class OS>
2214 timeFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr taddr)
2215 {
2216  typename OS::time_t sec, usec;
2217  getElapsedTimeMicro(sec, usec);
2218  sec += seconds_since_epoch;
2219 
2220  if (taddr != 0) {
2221  typename OS::time_t t = sec;
2222  t = htog(t, OS::byteOrder);
2223  PortProxy &p = tc->getVirtProxy();
2224  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2225  }
2226  return sec;
2227 }
2228 
2229 template <class OS>
2232  int tgid, int tid, int sig)
2233 {
2249  System *sys = tc->getSystemPtr();
2250  Process *tgt_proc = nullptr;
2251  for (int i = 0; i < sys->numContexts(); i++) {
2252  Process *temp = sys->threadContexts[i]->getProcessPtr();
2253  if (temp->pid() == tid) {
2254  tgt_proc = temp;
2255  break;
2256  }
2257  }
2258 
2259  if (sig != 0 || sig != OS::TGT_SIGABRT)
2260  return -EINVAL;
2261 
2262  if (tgt_proc == nullptr)
2263  return -ESRCH;
2264 
2265  if (tgid != -1 && tgt_proc->tgid() != tgid)
2266  return -ESRCH;
2267 
2268  if (sig == OS::TGT_SIGABRT)
2269  exitGroupFunc(desc, num, tc, 0);
2270 
2271  return 0;
2272 }
2273 
2274 template <class OS>
2277  int domain, int type, int prot)
2278 {
2279  auto p = tc->getProcessPtr();
2280 
2281  int sim_fd = socket(domain, type, prot);
2282  if (sim_fd == -1)
2283  return -errno;
2284 
2285  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2286  int tgt_fd = p->fds->allocFD(sfdp);
2287 
2288  return tgt_fd;
2289 }
2290 
2291 template <class OS>
2294  int domain, int type, int prot, Addr svPtr)
2295 {
2296  auto p = tc->getProcessPtr();
2297 
2298  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2299  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2300  if (status == -1)
2301  return -errno;
2302 
2303  int *fds = (int *)svBuf.bufferPtr();
2304 
2305  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2306  fds[0] = p->fds->allocFD(sfdp1);
2307  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2308  fds[1] = p->fds->allocFD(sfdp2);
2309  svBuf.copyOut(tc->getVirtProxy());
2310 
2311  return status;
2312 }
2313 
2314 template <class OS>
2316 selectFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
2317  int nfds_t, Addr fds_read_ptr, Addr fds_writ_ptr,
2318  Addr fds_excp_ptr, Addr time_val_ptr)
2319 {
2320  int retval;
2321 
2322  auto p = tc->getProcessPtr();
2323 
2324  TypedBufferArg<typename OS::fd_set> rd_t(fds_read_ptr);
2325  TypedBufferArg<typename OS::fd_set> wr_t(fds_writ_ptr);
2326  TypedBufferArg<typename OS::fd_set> ex_t(fds_excp_ptr);
2327  TypedBufferArg<typename OS::timeval> tp(time_val_ptr);
2328 
2334  fd_set rd_h;
2335  FD_ZERO(&rd_h);
2336  fd_set wr_h;
2337  FD_ZERO(&wr_h);
2338  fd_set ex_h;
2339  FD_ZERO(&ex_h);
2340 
2344  if (fds_read_ptr)
2345  rd_t.copyIn(tc->getVirtProxy());
2346  if (fds_writ_ptr)
2347  wr_t.copyIn(tc->getVirtProxy());
2348  if (fds_excp_ptr)
2349  ex_t.copyIn(tc->getVirtProxy());
2350 
2360  int nfds_h = 0;
2361  std::map<int, int> trans_map;
2362  auto try_add_host_set = [&](fd_set *tgt_set_entry,
2363  fd_set *hst_set_entry,
2364  int iter) -> bool
2365  {
2371  if (FD_ISSET(iter, tgt_set_entry)) {
2377  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2378  if (!hbfdp)
2379  return true;
2380  auto sim_fd = hbfdp->getSimFD();
2381 
2387  trans_map[sim_fd] = iter;
2388 
2394  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2395 
2400  FD_SET(sim_fd, hst_set_entry);
2401  }
2402  return false;
2403  };
2404 
2405  for (int i = 0; i < nfds_t; i++) {
2406  if (fds_read_ptr) {
2407  bool ebadf = try_add_host_set((fd_set*)&*rd_t, &rd_h, i);
2408  if (ebadf) return -EBADF;
2409  }
2410  if (fds_writ_ptr) {
2411  bool ebadf = try_add_host_set((fd_set*)&*wr_t, &wr_h, i);
2412  if (ebadf) return -EBADF;
2413  }
2414  if (fds_excp_ptr) {
2415  bool ebadf = try_add_host_set((fd_set*)&*ex_t, &ex_h, i);
2416  if (ebadf) return -EBADF;
2417  }
2418  }
2419 
2420  if (time_val_ptr) {
2428  tp->tv_sec = 0;
2429  tp->tv_usec = 0;
2430 
2431  retval = select(nfds_h,
2432  fds_read_ptr ? &rd_h : nullptr,
2433  fds_writ_ptr ? &wr_h : nullptr,
2434  fds_excp_ptr ? &ex_h : nullptr,
2435  (timeval*)&*tp);
2436  } else {
2444  struct timeval tv = { 0, 0 };
2445 
2446  retval = select(nfds_h,
2447  fds_read_ptr ? &rd_h : nullptr,
2448  fds_writ_ptr ? &wr_h : nullptr,
2449  fds_excp_ptr ? &ex_h : nullptr,
2450  &tv);
2451 
2452  if (retval == 0) {
2458  for (auto sig : tc->getSystemPtr()->signalList)
2459  if (sig.receiver == p)
2460  return -EINTR;
2461  return SyscallReturn::retry();
2462  }
2463  }
2464 
2465  if (retval == -1)
2466  return -errno;
2467 
2468  FD_ZERO((fd_set*)&*rd_t);
2469  FD_ZERO((fd_set*)&*wr_t);
2470  FD_ZERO((fd_set*)&*ex_t);
2471 
2477  for (int i = 0; i < nfds_h; i++) {
2478  if (fds_read_ptr) {
2479  if (FD_ISSET(i, &rd_h))
2480  FD_SET(trans_map[i], (fd_set*)&*rd_t);
2481  }
2482 
2483  if (fds_writ_ptr) {
2484  if (FD_ISSET(i, &wr_h))
2485  FD_SET(trans_map[i], (fd_set*)&*wr_t);
2486  }
2487 
2488  if (fds_excp_ptr) {
2489  if (FD_ISSET(i, &ex_h))
2490  FD_SET(trans_map[i], (fd_set*)&*ex_t);
2491  }
2492  }
2493 
2494  if (fds_read_ptr)
2495  rd_t.copyOut(tc->getVirtProxy());
2496  if (fds_writ_ptr)
2497  wr_t.copyOut(tc->getVirtProxy());
2498  if (fds_excp_ptr)
2499  ex_t.copyOut(tc->getVirtProxy());
2500  if (time_val_ptr)
2501  tp.copyOut(tc->getVirtProxy());
2502 
2503  return retval;
2504 }
2505 
2506 template <class OS>
2508 readFunc(SyscallDesc *desc, int num, ThreadContext *tc,
2509  int tgt_fd, Addr buf_ptr, int nbytes)
2510 {
2511  auto p = tc->getProcessPtr();
2512 
2513  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2514  if (!hbfdp)
2515  return -EBADF;
2516  int sim_fd = hbfdp->getSimFD();
2517 
2518  struct pollfd pfd;
2519  pfd.fd = sim_fd;
2520  pfd.events = POLLIN | POLLPRI;
2521  if ((poll(&pfd, 1, 0) == 0)
2522  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2523  return SyscallReturn::retry();
2524 
2525  BufferArg buf_arg(buf_ptr, nbytes);
2526  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2527 
2528  if (bytes_read > 0)
2529  buf_arg.copyOut(tc->getVirtProxy());
2530 
2531  return (bytes_read == -1) ? -errno : bytes_read;
2532 }
2533 
2534 template <class OS>
2537  int tgt_fd, Addr buf_ptr, int nbytes)
2538 {
2539  auto p = tc->getProcessPtr();
2540 
2541  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2542  if (!hbfdp)
2543  return -EBADF;
2544  int sim_fd = hbfdp->getSimFD();
2545 
2546  BufferArg buf_arg(buf_ptr, nbytes);
2547  buf_arg.copyIn(tc->getVirtProxy());
2548 
2549  struct pollfd pfd;
2550  pfd.fd = sim_fd;
2551  pfd.events = POLLOUT;
2552 
2559  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2560  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2561  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2562  return SyscallReturn::retry();
2563  }
2564 
2565  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2566 
2567  if (bytes_written != -1)
2568  fsync(sim_fd);
2569 
2570  return (bytes_written == -1) ? -errno : bytes_written;
2571 }
2572 
2573 template <class OS>
2576  pid_t pid, Addr statPtr, int options, Addr rusagePtr)
2577 {
2578  auto p = tc->getProcessPtr();
2579 
2580  if (rusagePtr)
2581  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2582  "functionality not supported. Ignoring rusage pointer.\n",
2583  rusagePtr);
2584 
2593  System *sysh = tc->getSystemPtr();
2595  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2596  if (iter->receiver == p) {
2597  if (pid < -1) {
2598  if ((iter->sender->pgid() == -pid)
2599  && (iter->signalValue == OS::TGT_SIGCHLD))
2600  goto success;
2601  } else if (pid == -1) {
2602  if (iter->signalValue == OS::TGT_SIGCHLD)
2603  goto success;
2604  } else if (pid == 0) {
2605  if ((iter->sender->pgid() == p->pgid())
2606  && (iter->signalValue == OS::TGT_SIGCHLD))
2607  goto success;
2608  } else {
2609  if ((iter->sender->pid() == pid)
2610  && (iter->signalValue == OS::TGT_SIGCHLD))
2611  goto success;
2612  }
2613  }
2614  }
2615 
2616  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2617 
2618 success:
2619  // Set status to EXITED for WIFEXITED evaluations.
2620  const int EXITED = 0;
2621  BufferArg statusBuf(statPtr, sizeof(int));
2622  *(int *)statusBuf.bufferPtr() = EXITED;
2623  statusBuf.copyOut(tc->getVirtProxy());
2624 
2625  // Return the child PID.
2626  pid_t retval = iter->sender->pid();
2627  sysh->signalList.erase(iter);
2628  return retval;
2629 }
2630 
2631 template <class OS>
2634  int tgt_fd, Addr addrPtr, Addr lenPtr)
2635 {
2636  struct sockaddr sa;
2637  socklen_t addrLen;
2638  int host_fd;
2639  auto p = tc->getProcessPtr();
2640 
2641  BufferArg *lenBufPtr = nullptr;
2642  BufferArg *addrBufPtr = nullptr;
2643 
2644  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2645  if (!sfdp)
2646  return -EBADF;
2647  int sim_fd = sfdp->getSimFD();
2648 
2655  struct pollfd pfd;
2656  pfd.fd = sim_fd;
2657  pfd.events = POLLIN | POLLPRI;
2658  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2659  return SyscallReturn::retry();
2660 
2661  if (lenPtr) {
2662  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2663  lenBufPtr->copyIn(tc->getVirtProxy());
2664  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2665  sizeof(socklen_t));
2666  }
2667 
2668  if (addrPtr) {
2669  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2670  addrBufPtr->copyIn(tc->getVirtProxy());
2671  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2672  sizeof(struct sockaddr));
2673  }
2674 
2675  host_fd = accept(sim_fd, &sa, &addrLen);
2676 
2677  if (host_fd == -1)
2678  return -errno;
2679 
2680  if (addrPtr) {
2681  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2682  addrBufPtr->copyOut(tc->getVirtProxy());
2683  delete(addrBufPtr);
2684  }
2685 
2686  if (lenPtr) {
2687  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2688  lenBufPtr->copyOut(tc->getVirtProxy());
2689  delete(lenBufPtr);
2690  }
2691 
2692  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2693  sfdp->_type, sfdp->_protocol);
2694  return p->fds->allocFD(afdp);
2695 }
2696 
2698 template <class OS>
2701  unsigned initval, int in_flags)
2702 {
2703 #if defined(__linux__)
2704  auto p = tc->getProcessPtr();
2705 
2706  int sim_fd = eventfd(initval, in_flags);
2707  if (sim_fd == -1)
2708  return -errno;
2709 
2710  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2711 
2712  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2713  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2714 
2715  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2716  int tgt_fd = p->fds->allocFD(hbfdp);
2717  return tgt_fd;
2718 #else
2719  warnUnsupportedOS("eventfd");
2720  return -1;
2721 #endif
2722 }
2723 
2724 #endif // __SIM_SYSCALL_EMUL_HH__
count
Definition: misc.hh:705
SyscallReturn pwrite64Func(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr bufPtr, int nbytes, int offset)
SyscallReturn statFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target stat() handler.
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
SyscallReturn fchmodFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
SyscallReturn writevFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target writev() handler.
FutexMap futexMap
Definition: system.hh:642
SyscallReturn exitFunc(SyscallDesc *desc, int num, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn setTidAddressFunc(SyscallDesc *desc, int num, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
This file defines buffer classes used to handle pointer arguments in emulated syscalls.
SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Handler for unimplemented syscalls that we haven&#39;t thought about.
Definition: syscall_emul.cc:68
SyscallReturn lstatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target lstat() handler.
virtual void flushAll()=0
Remove all entries from the TLB.
SyscallReturn linkFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target link() handler.
SyscallReturn sysinfoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr info)
Target sysinfo() 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
virtual int ioctl(ThreadContext *tc, unsigned req)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
virtual System * getSystemPtr()=0
Bitfield< 30, 0 > index
SyscallReturn _llseekFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, Addr result_ptr, int whence)
Target _llseek() handler.
Tick us
microsecond
Definition: core.cc:67
SyscallReturn truncate64Func(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, int64_t length)
Target truncate64() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn chmodFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, mode_t mode)
Target chmod() handler.
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext...
Definition: process.cc:284
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:289
SyscallReturn getsockoptFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, Addr lenPtr)
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:166
SyscallReturn prlimitFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int pid, int resource, Addr n, Addr o)
SyscallReturn fcntl64Func(SyscallDesc *desc, int num, ThreadContext *tc)
Target fcntl64() handler.
Bitfield< 7 > i
const int one_million
A readable name for 1,000,000, for converting microseconds to seconds.
virtual BaseTLB * getDTBPtr()=0
void copyOutStatfsBuf(PortProxy &mem, Addr addr, hst_statfs *host)
virtual TheISA::PCState pcState() const =0
virtual RegVal readIntReg(RegIndex reg_idx) const =0
SyscallReturn chownFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, uint32_t owner, uint32_t group)
Target chown() handler.
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:64
SyscallReturn accessFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, mode_t mode)
Target access() handler.
bool copyIn(PortProxy &memproxy)
copy data into simulator space (read from target memory)
SyscallReturn statfsFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target statfs() handler.
SyscallReturn brkFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr new_brk)
Target brk() handler: set brk address.
bool * sigchld
Definition: process.hh:292
SyscallReturn pipeFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target pipe() handler.
SyscallReturn openatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
Target open() handler.
SyscallReturn fstatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstat() handler.
ip6_addr_t addr
Definition: inet.hh:335
SyscallReturn recvfromFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, Addr addrlenPtr)
const int one_billion
A readable name for 1,000,000,000, for converting nanoseconds to seconds.
SyscallReturn getegidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getegid() handler.
virtual PortProxy & getVirtProxy()=0
SyscallReturn renameatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
Target renameat() handler.
std::string name()
Definition: syscall_desc.hh:88
virtual Process * getProcessPtr()=0
uint64_t RegVal
Definition: types.hh:168
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:112
SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:45
Definition: system.hh:77
SyscallReturn clock_getresFunc(SyscallDesc *desc, int num, ThreadContext *tc, int clk_id, Addr tp_ptr)
Target clock_getres() function.
Bitfield< 23, 0 > offset
Definition: types.hh:154
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
SyscallReturn shutdownFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
struct statfs hst_statfs
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:307
SyscallReturn socketFunc(SyscallDesc *desc, int num, ThreadContext *tc, int domain, int type, int prot)
SyscallReturn ignoreFunc(SyscallDesc *desc, int num, 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:77
SyscallReturn getcwdFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: cprintf.cc:42
Bitfield< 4, 0 > mode
SyscallReturn fallocateFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Bitfield< 7 > prot
Definition: misc.hh:584
SyscallReturn lseekFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getgid() handler.
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
SyscallReturn utimesFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr times)
Target utimes() handler.
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:168
SyscallReturn unlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname)
Target unlink() handler.
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
SyscallReturn timeFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr taddr)
Target time() function.
SyscallReturn timesFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr bufPtr)
Target times() function.
SyscallReturn faccessatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int dirfd, Addr pathname, int mode)
Target facessat() handler.
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:243
void usage(const char *progname)
Definition: symtest.cc:41
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
SyscallReturn lstat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target lstat64() handler.
SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn socketpairFunc(SyscallDesc *desc, int num, ThreadContext *tc, int domain, int type, int prot, Addr svPtr)
Bitfield< 63 > val
Definition: misc.hh:771
Bitfield< 31 > n
SyscallReturn readFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
SyscallReturn bindFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
SyscallReturn truncateFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, off_t length)
Target truncate() handler.
SyscallReturn ioctlFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
Target ioctl() handler.
SyscallReturn closeFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd)
Target close() handler.
Bitfield< 5, 0 > status
SyscallReturn getpgrpFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getpgrpFunc() handler.
Bitfield< 7 > b
Addr minAddr() const
SyscallReturn tgkillFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgid, int tid, int sig)
SyscallReturn fstat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstat64() handler.
SyscallReturn readvFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target readv() handler.
SyscallReturn renameFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr oldpath, Addr newpath)
Target rename() handler.
int getSimFD() const
Definition: fd_entry.hh:94
virtual MemoryImage buildImage() const =0
uint8_t type
Definition: inet.hh:333
void copyOutStat64Buf(PortProxy &mem, Addr addr, hst_stat64 *host, bool fakeTTY=false)
Tick curTick()
The current simulated tick.
Definition: core.hh:47
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr tv_ptr, Addr tz_ptr)
Target gettimeofday() handler.
SyscallReturn chdirFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname)
Target chdir() handler.
void assignThreadContext(ContextID context_id)
Definition: process.hh:127
static const int maxPID
Definition: system.hh:644
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:309
ByteOrder byteOrder(ThreadContext *tc)
Definition: utility.hh:374
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:159
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, int num, ThreadContext *tc, int clk_id, Addr tp_ptr)
Target clock_gettime() function.
virtual int cpuId() const =0
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:189
SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr buf_ptr, int name_len)
Target gethostname() handler.
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.hh:144
uint64_t pid()
Definition: process.hh:91
SyscallReturn getrusageFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int who, Addr usage)
Target getrusage() function.
ByteOrder
Definition: types.hh:247
SyscallReturn umaskFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target umask() handler.
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
SyscallReturn getuidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Bitfield< 3 > sa
SyscallReturn selectFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int nfds_t, Addr fds_read_ptr, Addr fds_writ_ptr, Addr fds_excp_ptr, Addr time_val_ptr)
virtual RegVal getSyscallArg(ThreadContext *tc, int &i)=0
std::vector< ThreadContext * > threadContexts
Definition: system.hh:190
Bitfield< 18, 16 > len
SyscallReturn stat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr bufPtr)
Target stat64() handler.
SyscallReturn readlinkatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int dirfd, Addr pathname, Addr buf, size_t bufsiz)
Target readlinkat() handler.
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:76
virtual BaseTLB * getITBPtr()=0
unsigned numContexts() const
Definition: system.hh:206
SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getpidPseudo() handler.
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
void setNPC(Addr val)
SyscallReturn mknodFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, mode_t mode, dev_t dev)
Target mknod() handler.
std::string const & getFileName() const
Definition: fd_entry.hh:132
ThreadContext * findFreeContext()
Definition: system.cc:306
const RegIndex SyscallPseudoReturnReg
Definition: registers.hh:86
STL list class.
Definition: stl.hh:54
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:62
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.
SyscallReturn gettidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target gettid() handler.
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
SyscallReturn recvmsgFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
SyscallReturn pipeImpl(SyscallDesc *desc, int num, ThreadContext *tc, bool pseudo_pipe, bool is_pipe2=false)
Internal pipe() handler.
std::list< BasicSignal > signalList
Definition: system.hh:651
SyscallReturn execveFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
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:227
const Addr PageBytes
Definition: isa_traits.hh:47
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:179
SyscallReturn dupFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd)
Target dup() handler.
SyscallReturn writeFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
SyscallReturn setsockoptFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, socklen_t len)
SyscallReturn setpgidFunc(SyscallDesc *desc, int num, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn cloneFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
SyscallReturn getrlimitFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, unsigned resource, Addr rlim)
Target getrlimit() handler.
struct stat64 hst_stat64
void copyOutStatBuf(PortProxy &mem, Addr addr, hst_stat *host, bool fakeTTY=false)
SyscallReturn sendmsgFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
SyscallReturn pollFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr fdsPtr, int nfds, int tmout)
Bitfield< 20 > level
Definition: intmessage.hh:49
Tick s
second
Definition: core.cc:65
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:69
SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
SyscallReturn mkdirFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, mode_t mode)
Target mkdir() handler.
This object is a proxy for a port or other object which implements the functional response protocol...
Definition: port_proxy.hh:82
SyscallReturn acceptFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
SyscallReturn getppidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getppid() handler.
SyscallReturn eventfdFunc(SyscallDesc *desc, int num, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
EmulationPageTable * pTable
Definition: process.hh:181
Bitfield< 25, 21 > bo
Definition: types.hh:64
Declarations of a non-full system Page Table.
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:179
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:201
SyscallReturn rmdirFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname)
SyscallReturn fcntlFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target fcntl() handler.
SyscallReturn wait4Func(SyscallDesc *desc, int num, ThreadContext *tc, pid_t pid, Addr statPtr, int options, Addr rusagePtr)
SyscallReturn readlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, Addr buf, size_t bufsiz)
Target readlink() handler.
SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, ThreadContext *tc)
Target ftruncate64() handler.
SyscallReturn mmap2Func(SyscallDesc *desc, int num, ThreadContext *tc, Addr start, uint64_t length, int prot, int tgt_flags, int tgt_fd, int offset)
Target mmap2() handler.
GenericISA::SimplePCState< MachInst > PCState
Definition: types.hh:43
SyscallReturn fchownFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition: futex_map.hh:126
virtual int threadId() const =0
SyscallReturn symlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target symlink() handler.
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:459
bool copyOut(PortProxy &memproxy)
copy data out of simulator space (write to target memory)
bool useForClone
Definition: process.hh:179
SyscallReturn mremapFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
Target mremap() handler.
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:121
virtual ContextID contextId() const =0
SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getuidPseudo() handler.
void convertStat64Buf(target_stat &tgt, host_stat64 *host, ByteOrder bo, bool fakeTTY=false)
SyscallReturn connectFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Tick ns
nanosecond
Definition: core.cc:68
virtual void clearArchRegs()=0
SyscallReturn openFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr pathname, int tgt_flags, int mode)
Target open() handler.
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
uint8_t length
Definition: inet.hh:334
SyscallReturn pipe2Func(SyscallDesc *desc, int num, ThreadContext *tc)
Target pipe() handler.
SyscallReturn getsocknameFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
Holds file descriptors needed to simulate devices opened with pseudo files (commonly with calls to io...
Definition: fd_entry.hh:194
#define warn(...)
Definition: logging.hh:212
virtual void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value)=0
Bitfield< 5 > t
Bitfield< 4 > op
Definition: types.hh:80
This class represents the return value from an emulated system call, including any errno setting...
bool_vector8 mem[]
Definition: reset_stim.h:43
uint64_t tgid()
Definition: process.hh:95
void convertStatBuf(target_stat &tgt, host_stat *host, ByteOrder bo, bool fakeTTY=false)
SyscallReturn dup2Func(SyscallDesc *desc, int num, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Bitfield< 14, 12 > fd
Definition: types.hh:160
SyscallReturn sendtoFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, socklen_t addrLen)
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:102
SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getgidPseudo() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it&#39;s used with.
Definition: syscall_emul.cc:84
SyscallReturn fstatat64Func(SyscallDesc *desc, int callnum, ThreadContext *tc, int dirfd, Addr pathname, Addr bufPtr)
Target fstatat64() handler.
Bitfield< 0 > p
SyscallReturn getpeernameFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr)
const RegIndex SyscallSuccessReg
Definition: registers.hh:87
SyscallReturn mmapFunc(SyscallDesc *desc, int num, ThreadContext *tc, Addr start, uint64_t length, int prot, int tgt_flags, int tgt_fd, int offset)
Target mmap() handler.
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
struct stat hst_stat
virtual bool loadAllSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=MaxAddr)
Definition: object_file.hh:84
SyscallReturn futexFunc(SyscallDesc *desc, int callnum, 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...
SyscallReturn listenFunc(SyscallDesc *desc, int num, ThreadContext *tc, int tgt_fd, int backlog)
SyscallReturn munmapFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target munmap() handler.
SyscallReturn unlinkatFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int dirfd, Addr pathname)
Target unlinkat() handler.
SyscallReturn fstatfsFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int tgt_fd, Addr bufPtr)
Target fstatfs() handler.
SyscallReturn exitGroupFunc(SyscallDesc *desc, int num, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn getpidFunc(SyscallDesc *desc, int num, ThreadContext *tc)
Target getpid() handler.
std::shared_ptr< FDArray > fds
Definition: process.hh:280

Generated on Fri Feb 28 2020 16:27:03 for gem5 by doxygen 1.8.13