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

Generated on Wed Dec 21 2022 10:22:40 for gem5 by doxygen 1.9.1