gem5  v21.2.1.1
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/trace.hh"
94 #include "base/types.hh"
95 #include "config/the_isa.hh"
96 #include "cpu/base.hh"
97 #include "cpu/thread_context.hh"
98 #include "kern/linux/linux.hh"
99 #include "mem/page_table.hh"
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
527 getElapsedTimeMicro(T1 &sec, T2 &usec)
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
540 getElapsedTimeNano(T1 &sec, T2 &nsec)
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
779 
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
1604 cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
1605  VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1606 {
1607  auto p = tc->getProcessPtr();
1608 
1609  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1610  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1611  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1612  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1613  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1614  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1615  return -EINVAL;
1616 
1617  ThreadContext *ctc;
1618  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1619  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1620  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1621  return -EAGAIN;
1622  }
1623 
1630  ProcessParams *pp = new ProcessParams();
1631  pp->executable.assign(*(new std::string(p->progName())));
1632  pp->cmd.push_back(*(new std::string(p->progName())));
1633  pp->system = p->system;
1634  pp->cwd.assign(p->tgtCwd);
1635  pp->input.assign("stdin");
1636  pp->output.assign("stdout");
1637  pp->errout.assign("stderr");
1638  pp->uid = p->uid();
1639  pp->euid = p->euid();
1640  pp->gid = p->gid();
1641  pp->egid = p->egid();
1642  pp->release = p->release;
1643 
1644  /* Find the first free PID that's less than the maximum */
1645  std::set<int> const& pids = p->system->PIDs;
1646  int temp_pid = *pids.begin();
1647  do {
1648  temp_pid++;
1649  } while (pids.find(temp_pid) != pids.end());
1650  if (temp_pid >= System::maxPID)
1651  fatal("temp_pid is too large: %d", temp_pid);
1652 
1653  pp->pid = temp_pid;
1654  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1655  pp->useArchPT = p->useArchPT;
1656  pp->kvmInSE = p->kvmInSE;
1657  Process *cp = pp->create();
1658  // TODO: there is no way to know when the Process SimObject is done with
1659  // the params pointer. Both the params pointer (pp) and the process
1660  // pointer (cp) are normally managed in python and are never cleaned up.
1661 
1662  Process *owner = ctc->getProcessPtr();
1663  ctc->setProcessPtr(cp);
1664  cp->assignThreadContext(ctc->contextId());
1665  owner->revokeThreadContext(ctc->contextId());
1666 
1667  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1668  BufferArg ptidBuf(ptidPtr, sizeof(long));
1669  long *ptid = (long *)ptidBuf.bufferPtr();
1670  *ptid = cp->pid();
1671  ptidBuf.copyOut(SETranslatingPortProxy(tc));
1672  }
1673 
1674  if (flags & OS::TGT_CLONE_THREAD) {
1675  cp->pTable->shared = true;
1676  cp->useForClone = true;
1677  }
1678 
1679  ctc->setUseForClone(true);
1680  cp->initState();
1681  p->clone(tc, ctc, cp, flags);
1682 
1683  if (flags & OS::TGT_CLONE_THREAD) {
1684  delete cp->sigchld;
1685  cp->sigchld = p->sigchld;
1686  } else if (flags & OS::TGT_SIGCHLD) {
1687  *cp->sigchld = true;
1688  }
1689 
1690  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1691  BufferArg ctidBuf(ctidPtr, sizeof(long));
1692  long *ctid = (long *)ctidBuf.bufferPtr();
1693  *ctid = cp->pid();
1694  ctidBuf.copyOut(SETranslatingPortProxy(ctc));
1695  }
1696 
1697  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1698  cp->childClearTID = (uint64_t)ctidPtr;
1699 
1700  ctc->clearArchRegs();
1701 
1702  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1703 
1704  desc->returnInto(ctc, 0);
1705 
1706  ctc->activate();
1707 
1708  if (flags & OS::TGT_CLONE_VFORK) {
1709  tc->suspend();
1710  }
1711 
1712  return cp->pid();
1713 }
1714 
1715 template <class OS>
1716 SyscallReturn
1718  RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1719  VPtr<> ctidPtr)
1720 {
1721  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1722 }
1723 
1725 template <class OS>
1726 SyscallReturn
1728  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1729 {
1730  auto p = tc->getProcessPtr();
1731 
1732  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1733  if (!ffdp)
1734  return -EBADF;
1735  int sim_fd = ffdp->getSimFD();
1736 
1737  struct statfs hostBuf;
1738  int result = fstatfs(sim_fd, &hostBuf);
1739 
1740  if (result < 0)
1741  return -errno;
1742 
1743  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1744 
1745  return 0;
1746 }
1747 
1749 template <class OS>
1750 SyscallReturn
1752  int tgt_fd, uint64_t tiov_base,
1753  typename OS::size_t count)
1754 {
1755  auto p = tc->getProcessPtr();
1756 
1757  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1758  if (!ffdp)
1759  return -EBADF;
1760  int sim_fd = ffdp->getSimFD();
1761 
1762  SETranslatingPortProxy prox(tc);
1763  typename OS::tgt_iovec tiov[count];
1764  struct iovec hiov[count];
1765  for (typename OS::size_t i = 0; i < count; ++i) {
1766  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1767  &tiov[i], sizeof(typename OS::tgt_iovec));
1768  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1769  hiov[i].iov_base = new char [hiov[i].iov_len];
1770  }
1771 
1772  int result = readv(sim_fd, hiov, count);
1773  int local_errno = errno;
1774 
1775  for (typename OS::size_t i = 0; i < count; ++i) {
1776  if (result != -1) {
1777  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1778  hiov[i].iov_base, hiov[i].iov_len);
1779  }
1780  delete [] (char *)hiov[i].iov_base;
1781  }
1782 
1783  return (result == -1) ? -local_errno : result;
1784 }
1785 
1787 template <class OS>
1788 SyscallReturn
1790  int tgt_fd, uint64_t tiov_base,
1791  typename OS::size_t count)
1792 {
1793  auto p = tc->getProcessPtr();
1794 
1795  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1796  if (!hbfdp)
1797  return -EBADF;
1798  int sim_fd = hbfdp->getSimFD();
1799 
1800  SETranslatingPortProxy prox(tc);
1801  struct iovec hiov[count];
1802  for (typename OS::size_t i = 0; i < count; ++i) {
1803  typename OS::tgt_iovec tiov;
1804 
1805  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1806  &tiov, sizeof(typename OS::tgt_iovec));
1807  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1808  hiov[i].iov_base = new char [hiov[i].iov_len];
1809  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1810  hiov[i].iov_len);
1811  }
1812 
1813  int result = writev(sim_fd, hiov, count);
1814 
1815  for (typename OS::size_t i = 0; i < count; ++i)
1816  delete [] (char *)hiov[i].iov_base;
1817 
1818  return (result == -1) ? -errno : result;
1819 }
1820 
1822 template <class OS>
1823 SyscallReturn
1825  VPtr<> start, typename OS::size_t length, int prot,
1826  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1827 {
1828  auto p = tc->getProcessPtr();
1829  Addr page_bytes = p->pTable->pageSize();
1830 
1831  if (start & (page_bytes - 1) ||
1832  offset & (page_bytes - 1) ||
1833  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1834  tgt_flags & OS::TGT_MAP_SHARED) ||
1835  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1836  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1837  !length) {
1838  return -EINVAL;
1839  }
1840 
1841  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1842  // With shared mmaps, there are two cases to consider:
1843  // 1) anonymous: writes should modify the mapping and this should be
1844  // visible to observers who share the mapping. Currently, it's
1845  // difficult to update the shared mapping because there's no
1846  // structure which maintains information about the which virtual
1847  // memory areas are shared. If that structure existed, it would be
1848  // possible to make the translations point to the same frames.
1849  // 2) file-backed: writes should modify the mapping and the file
1850  // which is backed by the mapping. The shared mapping problem is the
1851  // same as what was mentioned about the anonymous mappings. For
1852  // file-backed mappings, the writes to the file are difficult
1853  // because it requires syncing what the mapping holds with the file
1854  // that resides on the host system. So, any write on a real system
1855  // would cause the change to be propagated to the file mapping at
1856  // some point in the future (the inode is tracked along with the
1857  // mapping). This isn't guaranteed to always happen, but it usually
1858  // works well enough. The guarantee is provided by the msync system
1859  // call. We could force the change through with shared mappings with
1860  // a call to msync, but that again would require more information
1861  // than we currently maintain.
1862  warn_once("mmap: writing to shared mmap region is currently "
1863  "unsupported. The write succeeds on the target, but it "
1864  "will not be propagated to the host or shared mappings");
1865  }
1866 
1867  length = roundUp(length, page_bytes);
1868 
1869  int sim_fd = -1;
1870  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1871  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1872 
1873  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1874  if (dfdp) {
1875  EmulatedDriver *emul_driver = dfdp->getDriver();
1876  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1877  tgt_fd, offset);
1878  }
1879 
1880  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1881  if (!ffdp)
1882  return -EBADF;
1883  sim_fd = ffdp->getSimFD();
1884 
1893  if (p->interpImage.contains(tc->pcState().instAddr())) {
1894  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1895  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1896  auto *lib = loader::createObjectFile(p->checkPathRedirect(
1897  ffdp->getFileName()));
1898  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1899  ffdp->getFileName());
1900 
1901  if (lib) {
1902  Addr offset = lib->buildImage().minAddr() + start;
1903  loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1904  }
1905  }
1906  }
1907 
1911  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1919  if (!(start && p->memState->isUnmapped(start, length))) {
1923  start = p->memState->extendMmap(length);
1924  }
1925  }
1926 
1927  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1928  start, start + length - 1);
1929 
1935  if (tgt_flags & OS::TGT_MAP_FIXED) {
1940  p->memState->unmapRegion(start, length);
1941  }
1942 
1946  std::string region_name;
1947  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1948  region_name = "anon";
1949  } else {
1950  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1951  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1952  region_name = ffdp->getFileName();
1953  }
1954 
1959  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1960 
1961  return (Addr)start;
1962 }
1963 
1964 template <class OS>
1965 SyscallReturn
1967  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1968 {
1969  auto p = tc->getProcessPtr();
1970 
1971  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1972  if (!ffdp)
1973  return -EBADF;
1974  int sim_fd = ffdp->getSimFD();
1975 
1976  BufferArg bufArg(bufPtr, nbytes);
1977 
1978  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1979 
1980  bufArg.copyOut(SETranslatingPortProxy(tc));
1981 
1982  return (bytes_read == -1) ? -errno : bytes_read;
1983 }
1984 
1985 template <class OS>
1986 SyscallReturn
1988  int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1989 {
1990  auto p = tc->getProcessPtr();
1991 
1992  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1993  if (!ffdp)
1994  return -EBADF;
1995  int sim_fd = ffdp->getSimFD();
1996 
1997  BufferArg bufArg(bufPtr, nbytes);
1998  bufArg.copyIn(SETranslatingPortProxy(tc));
1999 
2000  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2001 
2002  return (bytes_written == -1) ? -errno : bytes_written;
2003 }
2004 
2006 template <class OS>
2007 SyscallReturn
2009  VPtr<> start, typename OS::size_t length, int prot,
2010  int tgt_flags, int tgt_fd, typename OS::off_t offset)
2011 {
2012  auto page_size = tc->getProcessPtr()->pTable->pageSize();
2013  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
2014  tgt_fd, offset * page_size);
2015 }
2016 
2018 template <class OS>
2019 SyscallReturn
2021  unsigned resource, VPtr<typename OS::rlimit> rlp)
2022 {
2023  const ByteOrder bo = OS::byteOrder;
2024  switch (resource) {
2025  case OS::TGT_RLIMIT_STACK:
2026  // max stack size in bytes: make up a number (8MiB for now)
2027  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2028  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2029  rlp->rlim_max = htog(rlp->rlim_max, bo);
2030  break;
2031 
2032  case OS::TGT_RLIMIT_DATA:
2033  // max data segment size in bytes: make up a number
2034  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2035  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2036  rlp->rlim_max = htog(rlp->rlim_max, bo);
2037  break;
2038 
2039  case OS::TGT_RLIMIT_NPROC:
2040  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
2041  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2042  rlp->rlim_max = htog(rlp->rlim_max, bo);
2043  break;
2044 
2045  default:
2046  warn("getrlimit: unimplemented resource %d", resource);
2047  return -EINVAL;
2048  break;
2049  }
2050 
2051  return 0;
2052 }
2053 
2054 template <class OS>
2055 SyscallReturn
2057  int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
2058 {
2059  if (pid != 0) {
2060  warn("prlimit: ignoring rlimits for nonzero pid");
2061  return -EPERM;
2062  }
2063  if (n)
2064  warn("prlimit: ignoring new rlimit");
2065  if (rlp) {
2066  const ByteOrder bo = OS::byteOrder;
2067  switch (resource) {
2068  case OS::TGT_RLIMIT_STACK:
2069  // max stack size in bytes: make up a number (8MiB for now)
2070  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2071  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2072  rlp->rlim_max = htog(rlp->rlim_max, bo);
2073  break;
2074  case OS::TGT_RLIMIT_DATA:
2075  // max data segment size in bytes: make up a number
2076  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2077  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2078  rlp->rlim_max = htog(rlp->rlim_max, bo);
2079  break;
2080  default:
2081  warn("prlimit: unimplemented resource %d", resource);
2082  return -EINVAL;
2083  break;
2084  }
2085  }
2086  return 0;
2087 }
2088 
2090 template <class OS>
2091 SyscallReturn
2093  int clk_id, VPtr<typename OS::timespec> tp)
2094 {
2095  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
2096  tp->tv_sec += seconds_since_epoch;
2097  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2098  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
2099 
2100  return 0;
2101 }
2102 
2104 template <class OS>
2105 SyscallReturn
2108 {
2109  // Set resolution at ns, which is what clock_gettime() returns
2110  tp->tv_sec = 0;
2111  tp->tv_nsec = 1;
2112 
2113  return 0;
2114 }
2115 
2117 template <class OS>
2118 SyscallReturn
2121 {
2122  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
2123  tp->tv_sec += seconds_since_epoch;
2124  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2125  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
2126 
2127  return 0;
2128 }
2129 
2131 template <class OS>
2132 SyscallReturn
2134  int dirfd, VPtr<> pathname, VPtr<typename OS::timeval [2]> tp)
2135 {
2136  std::string path;
2137  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
2138  return -EFAULT;
2139 
2140  // Modifying path from the directory descriptor
2141  if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
2142  return res;
2143  }
2144 
2145  struct timeval hostTimeval[2];
2146  for (int i = 0; i < 2; ++i) {
2147  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
2148  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
2149  }
2150 
2151  // Adjust path for cwd and redirection
2152  auto process = tc->getProcessPtr();
2153  path = process->checkPathRedirect(path);
2154 
2155  int result = utimes(path.c_str(), hostTimeval);
2156 
2157  if (result < 0)
2158  return -errno;
2159 
2160  return 0;
2161 }
2162 
2164 template <class OS>
2165 SyscallReturn
2167  VPtr<typename OS::timeval [2]> tp)
2168 {
2169  return futimesatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tp);
2170 }
2171 
2172 template <class OS>
2173 SyscallReturn
2175  VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
2176 {
2177  auto p = tc->getProcessPtr();
2178 
2179  std::string path;
2180  SETranslatingPortProxy mem_proxy(tc);
2181  if (!mem_proxy.tryReadString(path, pathname))
2182  return -EFAULT;
2183 
2184  if (access(path.c_str(), F_OK) == -1)
2185  return -EACCES;
2186 
2187  auto read_in = [](std::vector<std::string> &vect,
2188  PortProxy &mem_proxy, VPtr<> mem_loc)
2189  {
2190  for (int inc = 0; ; inc++) {
2191  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2192  b.copyIn(mem_proxy);
2193 
2194  if (!*(Addr*)b.bufferPtr())
2195  break;
2196 
2197  vect.push_back(std::string());
2198  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2199  }
2200  };
2201 
2206  if (!p->vforkContexts.empty()) {
2207  ThreadContext *vtc = p->system->threads[p->vforkContexts.front()];
2208  assert(vtc->status() == ThreadContext::Suspended);
2209  vtc->activate();
2210  }
2211 
2218  ProcessParams *pp = new ProcessParams();
2219  pp->executable = path;
2220  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2221  read_in(pp->env, mem_proxy, envp_mem_loc);
2222  pp->uid = p->uid();
2223  pp->egid = p->egid();
2224  pp->euid = p->euid();
2225  pp->gid = p->gid();
2226  pp->ppid = p->ppid();
2227  pp->pid = p->pid();
2228  pp->input.assign("cin");
2229  pp->output.assign("cout");
2230  pp->errout.assign("cerr");
2231  pp->cwd.assign(p->tgtCwd);
2232  pp->system = p->system;
2233  pp->release = p->release;
2242  p->system->PIDs.erase(p->pid());
2243  Process *new_p = pp->create();
2244  // TODO: there is no way to know when the Process SimObject is done with
2245  // the params pointer. Both the params pointer (pp) and the process
2246  // pointer (p) are normally managed in python and are never cleaned up.
2247 
2252  new_p->fds = p->fds;
2253  for (int i = 0; i < new_p->fds->getSize(); i++) {
2254  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2255  if (fdep && fdep->getCOE())
2256  new_p->fds->closeFDEntry(i);
2257  }
2258 
2259  *new_p->sigchld = true;
2260 
2261  tc->clearArchRegs();
2262  tc->setProcessPtr(new_p);
2263  new_p->assignThreadContext(tc->contextId());
2264  new_p->init();
2265  new_p->initState();
2266  tc->activate();
2267 
2268  return SyscallReturn();
2269 }
2270 
2272 template <class OS>
2273 SyscallReturn
2275  int who /* THREAD, SELF, or CHILDREN */,
2277 {
2278  rup->ru_utime.tv_sec = 0;
2279  rup->ru_utime.tv_usec = 0;
2280  rup->ru_stime.tv_sec = 0;
2281  rup->ru_stime.tv_usec = 0;
2282  rup->ru_maxrss = 0;
2283  rup->ru_ixrss = 0;
2284  rup->ru_idrss = 0;
2285  rup->ru_isrss = 0;
2286  rup->ru_minflt = 0;
2287  rup->ru_majflt = 0;
2288  rup->ru_nswap = 0;
2289  rup->ru_inblock = 0;
2290  rup->ru_oublock = 0;
2291  rup->ru_msgsnd = 0;
2292  rup->ru_msgrcv = 0;
2293  rup->ru_nsignals = 0;
2294  rup->ru_nvcsw = 0;
2295  rup->ru_nivcsw = 0;
2296 
2297  switch (who) {
2298  case OS::TGT_RUSAGE_SELF:
2299  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2300  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2301  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2302  break;
2303 
2304  case OS::TGT_RUSAGE_CHILDREN:
2305  // do nothing. We have no child processes, so they take no time.
2306  break;
2307 
2308  default:
2309  // don't really handle THREAD or CHILDREN, but just warn and
2310  // plow ahead
2311  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2312  who);
2313  }
2314 
2315  return 0;
2316 }
2317 
2319 template <class OS>
2320 SyscallReturn
2322 {
2323  // Fill in the time structure (in clocks)
2324  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / sim_clock::as_int::s;
2325  bufp->tms_utime = clocks;
2326  bufp->tms_stime = 0;
2327  bufp->tms_cutime = 0;
2328  bufp->tms_cstime = 0;
2329 
2330  // Convert to host endianness
2331  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2332 
2333  // Return clock ticks since system boot
2334  return clocks;
2335 }
2336 
2338 template <class OS>
2339 SyscallReturn
2341 {
2342  typename OS::time_t sec, usec;
2343  getElapsedTimeMicro(sec, usec);
2344  sec += seconds_since_epoch;
2345 
2347  if (taddr != 0) {
2348  typename OS::time_t t = sec;
2349  t = htog(t, OS::byteOrder);
2350  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2351  }
2352  return sec;
2353 }
2354 
2355 template <class OS>
2356 SyscallReturn
2357 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2358 {
2374  System *sys = tc->getSystemPtr();
2375  Process *tgt_proc = nullptr;
2376  for (auto *tc: sys->threads) {
2377  Process *temp = tc->getProcessPtr();
2378  if (temp->pid() == tid) {
2379  tgt_proc = temp;
2380  break;
2381  }
2382  }
2383 
2384  if (sig != 0 || sig != OS::TGT_SIGABRT)
2385  return -EINVAL;
2386 
2387  if (tgt_proc == nullptr)
2388  return -ESRCH;
2389 
2390  if (tgid != -1 && tgt_proc->tgid() != tgid)
2391  return -ESRCH;
2392 
2393  if (sig == OS::TGT_SIGABRT)
2394  exitGroupFunc(desc, tc, 0);
2395 
2396  return 0;
2397 }
2398 
2399 template <class OS>
2400 SyscallReturn
2402  int domain, int type, int prot)
2403 {
2404  auto p = tc->getProcessPtr();
2405 
2406  int sim_fd = socket(domain, type, prot);
2407  if (sim_fd == -1)
2408  return -errno;
2409 
2410  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2411  int tgt_fd = p->fds->allocFD(sfdp);
2412 
2413  return tgt_fd;
2414 }
2415 
2416 template <class OS>
2417 SyscallReturn
2419  int domain, int type, int prot, VPtr<> svPtr)
2420 {
2421  auto p = tc->getProcessPtr();
2422 
2423  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2424  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2425  if (status == -1)
2426  return -errno;
2427 
2428  int *fds = (int *)svBuf.bufferPtr();
2429 
2430  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2431  fds[0] = p->fds->allocFD(sfdp1);
2432  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2433  fds[1] = p->fds->allocFD(sfdp2);
2434  svBuf.copyOut(SETranslatingPortProxy(tc));
2435 
2436  return status;
2437 }
2438 
2439 template <class OS>
2440 SyscallReturn
2441 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2442  VPtr<typename OS::fd_set> readfds,
2443  VPtr<typename OS::fd_set> writefds,
2444  VPtr<typename OS::fd_set> errorfds,
2446 {
2447  int retval;
2448 
2449  auto p = tc->getProcessPtr();
2450 
2456  fd_set readfds_h;
2457  FD_ZERO(&readfds_h);
2458  fd_set writefds_h;
2459  FD_ZERO(&writefds_h);
2460  fd_set errorfds_h;
2461  FD_ZERO(&errorfds_h);
2462 
2472  int nfds_h = 0;
2473  std::map<int, int> trans_map;
2474  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2475  fd_set *hst_set_entry,
2476  int iter) -> bool
2477  {
2483  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2489  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2490  if (!hbfdp)
2491  return true;
2492  auto sim_fd = hbfdp->getSimFD();
2493 
2499  trans_map[sim_fd] = iter;
2500 
2506  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2507 
2512  FD_SET(sim_fd, hst_set_entry);
2513  }
2514  return false;
2515  };
2516 
2517  for (int i = 0; i < nfds; i++) {
2518  if (readfds) {
2519  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2520  if (ebadf)
2521  return -EBADF;
2522  }
2523  if (writefds) {
2524  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2525  if (ebadf)
2526  return -EBADF;
2527  }
2528  if (errorfds) {
2529  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2530  if (ebadf)
2531  return -EBADF;
2532  }
2533  }
2534 
2535  if (timeout) {
2543  timeout->tv_sec = 0;
2544  timeout->tv_usec = 0;
2545 
2546  retval = select(nfds_h,
2547  readfds ? &readfds_h : nullptr,
2548  writefds ? &writefds_h : nullptr,
2549  errorfds ? &errorfds_h : nullptr,
2550  (timeval *)(typename OS::timeval *)timeout);
2551  } else {
2559  struct timeval tv = { 0, 0 };
2560 
2561  retval = select(nfds_h,
2562  readfds ? &readfds_h : nullptr,
2563  readfds ? &writefds_h : nullptr,
2564  readfds ? &errorfds_h : nullptr,
2565  &tv);
2566 
2567  if (retval == 0) {
2573  for (auto sig : tc->getSystemPtr()->signalList)
2574  if (sig.receiver == p)
2575  return -EINTR;
2576  return SyscallReturn::retry();
2577  }
2578  }
2579 
2580  if (retval == -1)
2581  return -errno;
2582 
2583  if (readfds) {
2584  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2585  }
2586  if (writefds) {
2587  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2588  }
2589  if (errorfds) {
2590  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2591  }
2592 
2598  for (int i = 0; i < nfds_h; i++) {
2599  if (readfds && FD_ISSET(i, &readfds_h))
2600  FD_SET(trans_map[i],
2601  reinterpret_cast<fd_set *>(
2602  (typename OS::fd_set *)readfds));
2603 
2604  if (writefds && FD_ISSET(i, &writefds_h))
2605  FD_SET(trans_map[i],
2606  reinterpret_cast<fd_set *>(
2607  (typename OS::fd_set *)writefds));
2608 
2609  if (errorfds && FD_ISSET(i, &errorfds_h))
2610  FD_SET(trans_map[i],
2611  reinterpret_cast<fd_set *>(
2612  (typename OS::fd_set *)errorfds));
2613  }
2614 
2615  return retval;
2616 }
2617 
2618 template <class OS>
2619 SyscallReturn
2621  int tgt_fd, VPtr<> buf_ptr, int nbytes)
2622 {
2623  auto p = tc->getProcessPtr();
2624 
2625  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2626  if (!hbfdp)
2627  return -EBADF;
2628  int sim_fd = hbfdp->getSimFD();
2629 
2630  struct pollfd pfd;
2631  pfd.fd = sim_fd;
2632  pfd.events = POLLIN | POLLPRI;
2633  if ((poll(&pfd, 1, 0) == 0)
2634  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2635  return SyscallReturn::retry();
2636 
2637  BufferArg buf_arg(buf_ptr, nbytes);
2638  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2639 
2640  if (bytes_read > 0)
2641  buf_arg.copyOut(SETranslatingPortProxy(tc));
2642 
2643  return (bytes_read == -1) ? -errno : bytes_read;
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  BufferArg buf_arg(buf_ptr, nbytes);
2659  buf_arg.copyIn(SETranslatingPortProxy(tc));
2660 
2661  struct pollfd pfd;
2662  pfd.fd = sim_fd;
2663  pfd.events = POLLOUT;
2664 
2671  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2672  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2673  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2674  return SyscallReturn::retry();
2675  }
2676 
2677  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2678 
2679  if (bytes_written != -1)
2680  fsync(sim_fd);
2681 
2682  return (bytes_written == -1) ? -errno : bytes_written;
2683 }
2684 
2685 template <class OS>
2686 SyscallReturn
2688  pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2689 {
2690  auto p = tc->getProcessPtr();
2691 
2692  if (rusagePtr)
2693  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2694  "functionality not supported. Ignoring rusage pointer.\n",
2695  rusagePtr);
2696 
2705  System *sysh = tc->getSystemPtr();
2707  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2708  if (iter->receiver == p) {
2709  if (pid < -1) {
2710  if ((iter->sender->pgid() == -pid)
2711  && (iter->signalValue == OS::TGT_SIGCHLD))
2712  goto success;
2713  } else if (pid == -1) {
2714  if (iter->signalValue == OS::TGT_SIGCHLD)
2715  goto success;
2716  } else if (pid == 0) {
2717  if ((iter->sender->pgid() == p->pgid())
2718  && (iter->signalValue == OS::TGT_SIGCHLD))
2719  goto success;
2720  } else {
2721  if ((iter->sender->pid() == pid)
2722  && (iter->signalValue == OS::TGT_SIGCHLD))
2723  goto success;
2724  }
2725  }
2726  }
2727 
2728  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2729 
2730 success:
2731  // Set status to EXITED for WIFEXITED evaluations.
2732  const int EXITED = 0;
2733  BufferArg statusBuf(statPtr, sizeof(int));
2734  *(int *)statusBuf.bufferPtr() = EXITED;
2735  statusBuf.copyOut(SETranslatingPortProxy(tc));
2736 
2737  // Return the child PID.
2738  pid_t retval = iter->sender->pid();
2739  sysh->signalList.erase(iter);
2740  return retval;
2741 }
2742 
2743 template <class OS>
2744 SyscallReturn
2746  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2747 {
2748  struct sockaddr sa;
2749  socklen_t addrLen;
2750  int host_fd;
2751  auto p = tc->getProcessPtr();
2752 
2753  BufferArg *lenBufPtr = nullptr;
2754  BufferArg *addrBufPtr = nullptr;
2755 
2756  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2757  if (!sfdp)
2758  return -EBADF;
2759  int sim_fd = sfdp->getSimFD();
2760 
2767  struct pollfd pfd;
2768  pfd.fd = sim_fd;
2769  pfd.events = POLLIN | POLLPRI;
2770  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2771  return SyscallReturn::retry();
2772 
2773  if (lenPtr) {
2774  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2775  lenBufPtr->copyIn(SETranslatingPortProxy(tc));
2776  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2777  sizeof(socklen_t));
2778  }
2779 
2780  if (addrPtr) {
2781  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2782  addrBufPtr->copyIn(SETranslatingPortProxy(tc));
2783  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2784  sizeof(struct sockaddr));
2785  }
2786 
2787  host_fd = accept(sim_fd, &sa, &addrLen);
2788 
2789  if (host_fd == -1)
2790  return -errno;
2791 
2792  if (addrPtr) {
2793  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2794  addrBufPtr->copyOut(SETranslatingPortProxy(tc));
2795  delete(addrBufPtr);
2796  }
2797 
2798  if (lenPtr) {
2799  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2800  lenBufPtr->copyOut(SETranslatingPortProxy(tc));
2801  delete(lenBufPtr);
2802  }
2803 
2804  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2805  sfdp->_type, sfdp->_protocol);
2806  return p->fds->allocFD(afdp);
2807 }
2808 
2810 template <class OS>
2811 SyscallReturn
2813  unsigned initval, int in_flags)
2814 {
2815 #if defined(__linux__)
2816  auto p = tc->getProcessPtr();
2817 
2818  int sim_fd = eventfd(initval, in_flags);
2819  if (sim_fd == -1)
2820  return -errno;
2821 
2822  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2823 
2824  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2825  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2826 
2827  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2828  int tgt_fd = p->fds->allocFD(hbfdp);
2829  return tgt_fd;
2830 #else
2831  warnUnsupportedOS("eventfd");
2832  return -1;
2833 #endif
2834 }
2835 
2837 template <class OS>
2838 SyscallReturn
2840  pid_t pid, typename OS::size_t cpusetsize,
2841  VPtr<> cpu_set_mask)
2842 {
2843 #if defined(__linux__)
2844  if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size()))
2845  return -EINVAL;
2846 
2847  SETranslatingPortProxy proxy(tc);
2848  BufferArg maskBuf(cpu_set_mask, cpusetsize);
2849  maskBuf.copyIn(proxy);
2850  for (int i = 0; i < tc->getSystemPtr()->threads.size(); i++) {
2851  CPU_SET(i, (cpu_set_t *)maskBuf.bufferPtr());
2852  }
2853  maskBuf.copyOut(proxy);
2854  return CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size());
2855 #else
2856  warnUnsupportedOS("sched_getaffinity");
2857  return -1;
2858 #endif
2859 }
2860 
2861 // Target recvfrom() handler.
2862 template <class OS>
2863 SyscallReturn
2865  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len,
2866  int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
2867 {
2868  auto p = tc->getProcessPtr();
2869 
2870  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2871  if (!sfdp)
2872  return -EBADF;
2873  int sim_fd = sfdp->getSimFD();
2874 
2875  // Reserve buffer space.
2876  BufferArg buf(buf_ptr, buf_len);
2877 
2878  SETranslatingPortProxy proxy(tc);
2879 
2880  // Get address length.
2881  socklen_t addr_len = 0;
2882  if (addrlen_ptr != 0) {
2883  // Read address length parameter.
2884  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2885  addrlen_buf.copyIn(proxy);
2886  addr_len = *((socklen_t *)addrlen_buf.bufferPtr());
2887  }
2888 
2889  struct sockaddr sa, *sap = NULL;
2890  if (addr_len != 0) {
2891  BufferArg addr_buf(addr_ptr, addr_len);
2892  addr_buf.copyIn(proxy);
2893  memcpy(&sa, (struct sockaddr *)addr_buf.bufferPtr(),
2894  sizeof(struct sockaddr));
2895  sap = &sa;
2896  }
2897 
2898  ssize_t recvd_size = recvfrom(sim_fd,
2899  (void *)buf.bufferPtr(),
2900  buf_len, flags, sap, (socklen_t *)&addr_len);
2901 
2902  if (recvd_size == -1)
2903  return -errno;
2904 
2905  // Pass the received data out.
2906  buf.copyOut(proxy);
2907 
2908  // Copy address to addr_ptr and pass it on.
2909  if (sap != NULL) {
2910  BufferArg addr_buf(addr_ptr, addr_len);
2911  memcpy(addr_buf.bufferPtr(), sap, sizeof(sa));
2912  addr_buf.copyOut(proxy);
2913  }
2914 
2915  // Copy len to addrlen_ptr and pass it on.
2916  if (addr_len != 0) {
2917  BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2918  *(socklen_t *)addrlen_buf.bufferPtr() = addr_len;
2919  addrlen_buf.copyOut(proxy);
2920  }
2921 
2922  return recvd_size;
2923 }
2924 
2925 // Target sendto() handler.
2926 template <typename OS>
2927 SyscallReturn
2929  int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags,
2930  VPtr<> addr_ptr, socklen_t addr_len)
2931 {
2932  auto p = tc->getProcessPtr();
2933 
2934  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2935  if (!sfdp)
2936  return -EBADF;
2937  int sim_fd = sfdp->getSimFD();
2938 
2939  // Reserve buffer space.
2940  BufferArg buf(buf_ptr, buf_len);
2941  buf.copyIn(SETranslatingPortProxy(tc));
2942 
2943  struct sockaddr sa, *sap = nullptr;
2944  memset(&sa, 0, sizeof(sockaddr));
2945  if (addr_len != 0) {
2946  BufferArg addr_buf(addr_ptr, addr_len);
2947  addr_buf.copyIn(SETranslatingPortProxy(tc));
2948  memcpy(&sa, (sockaddr*)addr_buf.bufferPtr(), addr_len);
2949  sap = &sa;
2950  }
2951 
2952  ssize_t sent_size = sendto(sim_fd,
2953  (void *)buf.bufferPtr(),
2954  buf_len, flags, sap, (socklen_t)addr_len);
2955 
2956  return (sent_size == -1) ? -errno : sent_size;
2957 }
2958 
2960 template <typename OS>
2961 SyscallReturn
2963  typename OS::size_t length)
2964 {
2965  // Even if the system is currently not capable of recycling physical
2966  // pages, there is no reason we can't unmap them so that we trigger
2967  // appropriate seg faults when the application mistakenly tries to
2968  // access them again.
2969  auto p = tc->getProcessPtr();
2970 
2971  if (p->pTable->pageOffset(start))
2972  return -EINVAL;
2973 
2974  length = roundUp(length, p->pTable->pageSize());
2975 
2976  p->memState->unmapRegion(start, length);
2977 
2978  return 0;
2979 }
2980 
2981 // Target fallocate() handler.
2982 template <typename OS>
2983 SyscallReturn
2985  int tgt_fd, int mode, typename OS::off_t offset,
2986  typename OS::off_t len)
2987 {
2988 #if defined(__linux__)
2989  auto p = tc->getProcessPtr();
2990 
2991  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2992  if (!ffdp)
2993  return -EBADF;
2994  int sim_fd = ffdp->getSimFD();
2995 
2996  int result = fallocate(sim_fd, mode, offset, len);
2997  if (result < 0)
2998  return -errno;
2999  return 0;
3000 #else
3001  warnUnsupportedOS("fallocate");
3002  return -1;
3003 #endif
3004 }
3005 
3007 template <typename OS>
3008 SyscallReturn
3010  typename OS::off_t length)
3011 {
3012  std::string path;
3013  auto p = tc->getProcessPtr();
3014 
3015  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
3016  return -EFAULT;
3017 
3018  // Adjust path for cwd and redirection
3019  path = p->checkPathRedirect(path);
3020 
3021  int result = truncate(path.c_str(), length);
3022  return (result == -1) ? -errno : result;
3023 }
3024 
3026 template <typename OS>
3027 SyscallReturn
3028 ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd,
3029  typename OS::off_t length)
3030 {
3031  auto p = tc->getProcessPtr();
3032 
3033  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3034  if (!ffdp)
3035  return -EBADF;
3036  int sim_fd = ffdp->getSimFD();
3037 
3038  int result = ftruncate(sim_fd, length);
3039  return (result == -1) ? -errno : result;
3040 }
3041 
3042 } // namespace gem5
3043 
3044 #endif // __SIM_SYSCALL_EMUL_HH__
gem5::fstatfsFunc
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
Definition: syscall_emul.hh:1727
gem5::chownImpl
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
Definition: syscall_emul.cc:557
gem5::X86ISA::level
Bitfield< 20 > level
Definition: intmessage.hh:51
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
gem5::lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1518
gem5::Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:131
gem5::dupFunc
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
Definition: syscall_emul.cc:599
gem5::chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
Definition: syscall_emul.cc:950
gem5::SETranslatingPortProxy
Definition: se_translating_port_proxy.hh:49
gem5::PCStateBase::instAddr
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition: pcstate.hh:107
gem5::timesFunc
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
Definition: syscall_emul.hh:2321
gem5::Process::tgid
uint64_t tgid()
Definition: process.hh:91
gem5::pread64Func
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1966
gem5::EmulationPageTable::pageSize
Addr pageSize()
Definition: page_table.hh:115
gem5::ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
gem5::EmulatedDriver::ioctl
virtual int ioctl(ThreadContext *tc, unsigned req, Addr buf)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
gem5::ArmISA::len
Bitfield< 18, 16 > len
Definition: misc_types.hh:445
warn
#define warn(...)
Definition: logging.hh:246
gem5::System::Threads::size
int size() const
Definition: system.hh:214
linux.hh
gem5::listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1112
gem5::PortProxy::writeBlob
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:192
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
gem5::PortProxy::tryReadString
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:115
gem5::mmapFunc
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
Definition: syscall_emul.hh:1824
gem5::getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:877
gem5::hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:561
gem5::getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1358
gem5::cloneFunc
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
Definition: syscall_emul.hh:1604
gem5::newfstatatFunc
SyscallReturn newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat, int flags)
Target newfstatat() handler.
Definition: syscall_emul.hh:1377
gem5::SyscallReturn
This class represents the return value from an emulated system call, including any errno setting.
Definition: syscall_return.hh:55
gem5::EmulatedDriver::mmap
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, off_t offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
Definition: emul_driver.hh:98
gem5::getpgrpFunc
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Definition: syscall_emul.cc:815
gem5::ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:150
gem5::rmdirImpl
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
Definition: syscall_emul.cc:987
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
warn_once
#define warn_once(...)
Definition: logging.hh:250
gem5::fstatFunc
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
Definition: syscall_emul.hh:1549
gem5::SyscallDesc::returnInto
virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret)=0
For use within the system call executor if new threads are created and need something returned into t...
gem5::bindFunc
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1091
gem5::accessImpl
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
Definition: syscall_emul.cc:916
gem5::selectFunc
SyscallReturn selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds, VPtr< typename OS::fd_set > readfds, VPtr< typename OS::fd_set > writefds, VPtr< typename OS::fd_set > errorfds, VPtr< typename OS::timeval > timeout)
Definition: syscall_emul.hh:2441
gem5::FutexMap::suspend
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition: futex_map.cc:53
gem5::System::futexMap
FutexMap futexMap
Definition: system.hh:600
gem5::ArmISA::domain
Bitfield< 7, 4 > domain
Definition: misc_types.hh:424
gem5::renameImpl
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
Definition: syscall_emul.cc:480
gem5::ThreadContext::pcState
virtual const PCStateBase & pcState() const =0
gem5::fchownatFunc
SyscallReturn fchownatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group, int flags)
Target fchownat() handler.
Definition: syscall_emul.hh:1066
gem5::SyscallReturn::retry
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Definition: syscall_return.hh:80
gem5::mkdirImpl
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
Definition: syscall_emul.cc:454
gem5::futimesatFunc
SyscallReturn futimesatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target futimesat() handler.
Definition: syscall_emul.hh:2133
tlb.hh
gem5::truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, typename OS::off_t length)
Target truncate() handler.
Definition: syscall_emul.hh:3009
gem5::Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:288
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:527
gem5::guest_abi::VarArgs::get
Arg get()
Definition: varargs.hh:165
gem5::startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:229
gem5::mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:444
gem5::copyOutStatfsBuf
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
Definition: syscall_emul.hh:642
futex_map.hh
gem5::lstatFunc
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
Definition: syscall_emul.hh:1492
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:365
gem5::prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:2056
gem5::getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:352
gem5::ThreadContext::activate
virtual void activate()=0
Set the status to Active.
gem5::brkFunc
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
Definition: syscall_emul.cc:258
std::vector< std::string >
gem5::Process::pid
uint64_t pid()
Definition: process.hh:87
proxy_ptr.hh
gem5::warnUnsupportedOS
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:59
gem5::sim_clock::as_int::us
Tick us
microsecond
Definition: core.cc:70
syscall_emul_buf.hh
gem5::FutexMap::requeue
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
Definition: futex_map.cc:141
gem5::sim_clock::as_int::s
Tick s
second
Definition: core.cc:68
gem5::ignoreWarnOnceFunc
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:79
gem5::fchmodFunc
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
Definition: syscall_emul.hh:1249
gem5::ThreadContext::setUseForClone
void setUseForClone(bool new_val)
Definition: thread_context.hh:103
gem5::Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:287
gem5::EmulationPageTable::shared
bool shared
Definition: page_table.hh:104
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::ThreadContext::cpuId
virtual int cpuId() const =0
gem5::closeFunc
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
Definition: syscall_emul.cc:289
gem5::Process::useForClone
bool useForClone
Definition: process.hh:183
gem5::getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1489
gem5::ThreadContext::setProcessPtr
virtual void setProcessPtr(Process *p)=0
sc_dt::inc
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:341
gem5::sysinfoFunc
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
Definition: syscall_emul.hh:1121
gem5::ThreadContext::status
virtual Status status() const =0
gem5::umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:535
gem5::unlinkImpl
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
Definition: syscall_emul.cc:392
gem5::setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:822
gem5::getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:251
gem5::openFunc
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:911
gem5::Process::childClearTID
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:296
gem5::exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:245
gem5::pollFunc
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
Definition: syscall_emul.hh:1175
gem5::mremapFunc
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags, guest_abi::VarArgs< uint64_t > varargs)
Target mremap() handler.
Definition: syscall_emul.hh:1268
gem5::getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1400
gem5::FutexMap
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:109
gem5::symlinkFunc
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
Definition: syscall_emul.cc:423
gem5::System
Definition: system.hh:75
syscall_return.hh
gem5::ArmISA::b
Bitfield< 7 > b
Definition: misc_types.hh:382
gem5::fstat64Func
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
Definition: syscall_emul.hh:1462
gem5::ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t length)
Target ftruncate() handler.
Definition: syscall_emul.hh:3028
gem5::System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:609
gem5::eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2812
gem5::gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:2119
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:94
gem5::openatFunc
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:761
gem5::unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags)
Target unlinkat() handler.
Definition: syscall_emul.hh:921
gem5::unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
Definition: syscall_emul.cc:382
gem5::writevFunc
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target writev() handler.
Definition: syscall_emul.hh:1789
gem5::_llseekFunc
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
Definition: syscall_emul.cc:313
gem5::ThreadContext::Suspended
@ Suspended
Temporarily inactive.
Definition: thread_context.hh:113
gem5::getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:891
gem5::X86ISA::count
count
Definition: misc.hh:709
gem5::socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2401
gem5::Process::pTable
EmulationPageTable * pTable
Definition: process.hh:185
gem5::PowerISA::bo
Bitfield< 25, 21 > bo
Definition: types.hh:82
DPRINTF_SYSCALL
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
Definition: syscall_debug_macros.hh:57
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::fchmodatFunc
SyscallReturn fchmodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:1136
gem5::X86ISA::type
type
Definition: misc.hh:733
gem5::FutexMap::suspend_bitset
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
Definition: futex_map.cc:89
gem5::EmulatedDriver::open
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver.
gem5::gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
process.hh
gem5::BufferArg
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Definition: syscall_emul_buf.hh:107
gem5::statfsFunc
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
Definition: syscall_emul.hh:1575
gem5::getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:898
gem5::PortProxy
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition: port_proxy.hh:86
gem5::readvFunc
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target readv() handler.
Definition: syscall_emul.hh:1751
gem5::FutexMap::wakeup
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.cc:59
gem5::clock_getresFunc
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_getres() function.
Definition: syscall_emul.hh:2106
gem5::FutexMap::wakeup_bitset
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition: futex_map.cc:108
gem5::pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:724
gem5::htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
gem5::hst_statfs
struct statfs hst_statfs
Definition: syscall_emul.hh:556
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length)
Target munmap() handler.
Definition: syscall_emul.hh:2962
gem5::truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:495
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::gettidFunc
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Definition: syscall_emul.cc:863
gem5::pwrite64Func
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1987
gem5::futexFunc
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps.
Definition: syscall_emul.hh:384
gem5::Process::checkPathRedirect
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:423
gem5::getElapsedTimeNano
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Definition: syscall_emul.hh:540
gem5::setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:280
gem5::PortProxy::readBlob
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:182
gem5::fcntlFunc
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
Definition: syscall_emul.cc:647
gem5::fstatat64Func
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstatat64() handler.
Definition: syscall_emul.hh:1416
gem5::ArmISA::t
Bitfield< 5 > t
Definition: misc_types.hh:71
gem5::mkdiratFunc
SyscallReturn mkdiratFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target mkdirat() handler.
Definition: syscall_emul.hh:1085
gem5::hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:562
gem5::connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1127
gem5::readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.hh:1027
gem5::readlinkatFunc
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlinkat() handler.
Definition: syscall_emul.hh:961
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::linkFunc
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
Definition: syscall_emul.cc:402
gem5::System::maxPID
static const int maxPID
Definition: system.hh:602
gem5::pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:730
gem5::timeFunc
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
Definition: syscall_emul.hh:2340
gem5::writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2648
gem5::accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:905
gem5::copyOutStat64Buf
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:620
gem5::sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1289
gem5::gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:342
gem5::fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:689
gem5::recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1149
gem5::mmap2Func
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
Definition: syscall_emul.hh:2008
gem5::loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:123
gem5::BaseBufferArg::copyIn
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
Definition: syscall_emul_buf.hh:81
gem5::tgkillFunc
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
Definition: syscall_emul.hh:2357
gem5::Process
Definition: process.hh:68
gem5::ThreadContext::getProcessPtr
virtual Process * getProcessPtr()=0
gem5::EmulatedDriver
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:55
gem5::exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:239
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:273
gem5::sendtoFunc
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)
Definition: syscall_emul.hh:2928
gem5::cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
Definition: syscall_emul.hh:1717
gem5::clock_gettimeFunc
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_gettime() function.
Definition: syscall_emul.hh:2092
gem5::renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
Definition: syscall_emul.hh:1038
gem5::ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
Definition: syscall_emul.hh:686
gem5::ThreadContext::suspend
virtual void suspend()=0
Set the status to Suspended.
gem5::loader::SymbolTable::insert
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition: symtab.cc:55
gem5::chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:1168
base.hh
gem5::shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1076
gem5::System::threads
Threads threads
Definition: system.hh:314
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:456
types.hh
gem5::BaseBufferArg::copyOut
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
Definition: syscall_emul_buf.hh:91
gem5::recvfromFunc
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)
Definition: syscall_emul.hh:2864
gem5::pipePseudoFunc
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
Definition: syscall_emul.cc:718
gem5::mknodatFunc
SyscallReturn mknodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknodat() handler.
Definition: syscall_emul.hh:1103
gem5::atSyscallPath
SyscallReturn atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
Definition: syscall_emul.hh:359
gem5::rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:977
guest_abi.hh
gem5::wait4Func
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
Definition: syscall_emul.hh:2687
gem5::getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:870
gem5::statFunc
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
Definition: syscall_emul.hh:1351
gem5::Process::sigchld
bool * sigchld
Definition: process.hh:299
gem5::fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, typename OS::off_t offset, typename OS::off_t len)
Definition: syscall_emul.hh:2984
gem5::roundUp
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:260
gem5::stat64Func
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
Definition: syscall_emul.hh:1453
logging.hh
emul_driver.hh
gem5::seconds_since_epoch
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
Definition: syscall_emul.hh:521
gem5::renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
Definition: syscall_emul.cc:464
gem5::Process::revokeThreadContext
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
Definition: process.cc:265
gem5::Process::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: process.cc:278
gem5::readFunc
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
Definition: syscall_emul.hh:2620
se_translating_port_proxy.hh
gem5::ThreadContext::clearArchRegs
virtual void clearArchRegs()=0
gem5::schedGetaffinityFunc
SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, pid_t pid, typename OS::size_t cpusetsize, VPtr<> cpu_set_mask)
Target sched_getaffinity.
Definition: syscall_emul.hh:2839
gem5::setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1468
gem5::ThreadContext::threadId
virtual int threadId() const =0
trace.hh
gem5::SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:69
gem5::fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:574
gem5::copyOutStatBuf
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:571
gem5::ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:72
gem5::loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
gem5::getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:856
std::list
STL list class.
Definition: stl.hh:51
gem5::getrusageFunc
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
Definition: syscall_emul.hh:2274
gem5::guest_abi::VarArgs
Definition: varargs.hh:150
intmath.hh
gem5::System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:146
gem5::getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:2020
gem5::BufferArg::bufferPtr
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Definition: syscall_emul_buf.hh:119
page_table.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: tlb.cc:60
gem5::SyscallDesc::name
std::string name() const
Definition: syscall_desc.hh:80
gem5::dup2Func
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Definition: syscall_emul.cc:619
gem5::socketpairFunc
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
Definition: syscall_emul.hh:2418
gem5::utimesFunc
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
Definition: syscall_emul.hh:2166
gem5::mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:928
object_file.hh
gem5::acceptFunc
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.hh:2745
gem5::mknodImpl
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
Definition: syscall_emul.cc:939
gem5::X86ISA::op
Bitfield< 4 > op
Definition: types.hh:83
thread_context.hh
gem5::faccessatFunc
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int mode)
Target facessat() handler.
Definition: syscall_emul.hh:943
gem5::geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:884
gem5::ArmISA::sa
Bitfield< 3 > sa
Definition: misc_types.hh:392
syscall_desc.hh
gem5::X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:588
gem5::chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:546
gem5::ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:516
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:423
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::lseekFunc
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Definition: syscall_emul.cc:296
gem5::getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1439
gem5::unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:65
gem5::execveFunc
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
Definition: syscall_emul.hh:2174
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

Generated on Wed May 4 2022 12:14:03 for gem5 by doxygen 1.8.17