gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
syscall_emul.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2015 ARM Limited
3  * Copyright (c) 2015 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2003-2005 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Authors: Steve Reinhardt
42  * Kevin Lim
43  */
44 
45 #ifndef __SIM_SYSCALL_EMUL_HH__
46 #define __SIM_SYSCALL_EMUL_HH__
47 
48 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
49  defined(__FreeBSD__) || defined(__CYGWIN__) || \
50  defined(__NetBSD__))
51 #define NO_STAT64 1
52 #else
53 #define NO_STAT64 0
54 #endif
55 
56 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
57  defined(__FreeBSD__) || defined(__NetBSD__))
58 #define NO_STATFS 1
59 #else
60 #define NO_STATFS 0
61 #endif
62 
63 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
64  defined(__FreeBSD__) || defined(__NetBSD__))
65 #define NO_FALLOCATE 1
66 #else
67 #define NO_FALLOCATE 0
68 #endif
69 
75 
76 #ifdef __CYGWIN32__
77 #include <sys/fcntl.h>
78 
79 #endif
80 #include <fcntl.h>
81 #include <sys/mman.h>
82 #include <sys/stat.h>
83 #if (NO_STATFS == 0)
84 #include <sys/statfs.h>
85 #else
86 #include <sys/mount.h>
87 #endif
88 #include <sys/time.h>
89 #include <sys/uio.h>
90 #include <unistd.h>
91 
92 #include <cerrno>
93 #include <memory>
94 #include <string>
95 
96 #include "arch/utility.hh"
97 #include "base/intmath.hh"
99 #include "base/misc.hh"
100 #include "base/trace.hh"
101 #include "base/types.hh"
102 #include "config/the_isa.hh"
103 #include "cpu/base.hh"
104 #include "cpu/thread_context.hh"
105 #include "mem/page_table.hh"
106 #include "params/Process.hh"
107 #include "sim/emul_driver.hh"
108 #include "sim/futex_map.hh"
109 #include "sim/process.hh"
111 #include "sim/syscall_desc.hh"
112 #include "sim/syscall_emul_buf.hh"
113 #include "sim/syscall_return.hh"
114 
116 //
117 // The following emulation functions are generic enough that they
118 // don't need to be recompiled for different emulated OS's. They are
119 // defined in sim/syscall_emul.cc.
120 //
122 
123 
126  Process *p, ThreadContext *tc);
127 
132 SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
133  Process *p, ThreadContext *tc);
134 
135 // Target fallocateFunc() handler.
137  Process *p, ThreadContext *tc);
138 
140 SyscallReturn exitFunc(SyscallDesc *desc, int num,
141  Process *p, ThreadContext *tc);
142 
145  Process *p, ThreadContext *tc);
146 
149  Process *p, ThreadContext *tc);
150 
153  Process *p, ThreadContext *tc);
154 
156 SyscallReturn brkFunc(SyscallDesc *desc, int num,
157  Process *p, ThreadContext *tc);
158 
160 SyscallReturn closeFunc(SyscallDesc *desc, int num,
161  Process *p, ThreadContext *tc);
162 
163 // Target read() handler.
164 SyscallReturn readFunc(SyscallDesc *desc, int num,
165  Process *p, ThreadContext *tc);
166 
168 SyscallReturn writeFunc(SyscallDesc *desc, int num,
169  Process *p, ThreadContext *tc);
170 
172 SyscallReturn lseekFunc(SyscallDesc *desc, int num,
173  Process *p, ThreadContext *tc);
174 
176 SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
177  Process *p, ThreadContext *tc);
178 
180 SyscallReturn munmapFunc(SyscallDesc *desc, int num,
181  Process *p, ThreadContext *tc);
182 
185  Process *p, ThreadContext *tc);
186 
188 SyscallReturn getcwdFunc(SyscallDesc *desc, int num,
189  Process *p, ThreadContext *tc);
190 
192 SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
193  Process *p, ThreadContext *tc,
194  int index = 0);
195 SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
196  Process *p, ThreadContext *tc);
197 
199 SyscallReturn unlinkHelper(SyscallDesc *desc, int num,
200  Process *p, ThreadContext *tc,
201  int index);
202 SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
203  Process *p, ThreadContext *tc);
204 
206 SyscallReturn mkdirFunc(SyscallDesc *desc, int num,
207  Process *p, ThreadContext *tc);
208 
210 SyscallReturn renameFunc(SyscallDesc *desc, int num,
211  Process *p, ThreadContext *tc);
212 
213 
215 SyscallReturn truncateFunc(SyscallDesc *desc, int num,
216  Process *p, ThreadContext *tc);
217 
218 
221  Process *p, ThreadContext *tc);
222 
223 
226  Process *p, ThreadContext *tc);
227 
230  Process *p, ThreadContext *tc);
231 
232 
234 SyscallReturn umaskFunc(SyscallDesc *desc, int num,
235  Process *p, ThreadContext *tc);
236 
238 SyscallReturn gettidFunc(SyscallDesc *desc, int num,
239  Process *p, ThreadContext *tc);
240 
242 SyscallReturn chownFunc(SyscallDesc *desc, int num,
243  Process *p, ThreadContext *tc);
244 
246 SyscallReturn setpgidFunc(SyscallDesc *desc, int num,
247  Process *p, ThreadContext *tc);
248 
250 SyscallReturn fchownFunc(SyscallDesc *desc, int num,
251  Process *p, ThreadContext *tc);
252 
254 SyscallReturn dupFunc(SyscallDesc *desc, int num,
255  Process *process, ThreadContext *tc);
256 
258 SyscallReturn dup2Func(SyscallDesc *desc, int num,
259  Process *process, ThreadContext *tc);
260 
262 SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
263  Process *process, ThreadContext *tc);
264 
266 SyscallReturn fcntl64Func(SyscallDesc *desc, int num,
267  Process *process, ThreadContext *tc);
268 
270 SyscallReturn setuidFunc(SyscallDesc *desc, int num,
271  Process *p, ThreadContext *tc);
272 
274 SyscallReturn pipeFunc(SyscallDesc *desc, int num,
275  Process *p, ThreadContext *tc);
276 
278 SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p,
279  ThreadContext *tc, bool pseudoPipe);
280 
282 SyscallReturn getpidFunc(SyscallDesc *desc, int num,
283  Process *p, ThreadContext *tc);
284 
286 SyscallReturn getuidFunc(SyscallDesc *desc, int num,
287  Process *p, ThreadContext *tc);
288 
290 SyscallReturn getgidFunc(SyscallDesc *desc, int num,
291  Process *p, ThreadContext *tc);
292 
294 SyscallReturn getppidFunc(SyscallDesc *desc, int num,
295  Process *p, ThreadContext *tc);
296 
298 SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
299  Process *p, ThreadContext *tc);
300 
302 SyscallReturn getegidFunc(SyscallDesc *desc, int num,
303  Process *p, ThreadContext *tc);
304 
306 SyscallReturn accessFunc(SyscallDesc *desc, int num,
307  Process *p, ThreadContext *tc);
308 SyscallReturn accessFunc(SyscallDesc *desc, int num,
309  Process *p, ThreadContext *tc,
310  int index);
311 
315 template <class OS>
317 futexFunc(SyscallDesc *desc, int callnum, Process *process,
318  ThreadContext *tc)
319 {
320  using namespace std;
321 
322  int index = 0;
323  Addr uaddr = process->getSyscallArg(tc, index);
324  int op = process->getSyscallArg(tc, index);
325  int val = process->getSyscallArg(tc, index);
326 
327  /*
328  * Unsupported option that does not affect the correctness of the
329  * application. This is a performance optimization utilized by Linux.
330  */
331  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
332 
333  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
334 
335  if (OS::TGT_FUTEX_WAIT == op) {
336  // Ensure futex system call accessed atomically.
337  BufferArg buf(uaddr, sizeof(int));
338  buf.copyIn(tc->getMemProxy());
339  int mem_val = *(int*)buf.bufferPtr();
340 
341  /*
342  * The value in memory at uaddr is not equal with the expected val
343  * (a different thread must have changed it before the system call was
344  * invoked). In this case, we need to throw an error.
345  */
346  if (val != mem_val)
347  return -OS::TGT_EWOULDBLOCK;
348 
349  futex_map.suspend(uaddr, process->tgid(), tc);
350 
351  return 0;
352  } else if (OS::TGT_FUTEX_WAKE == op) {
353  return futex_map.wakeup(uaddr, process->tgid(), val);
354  }
355 
356  warn("futex: op %d not implemented; ignoring.", op);
357  return -ENOSYS;
358 }
359 
360 
364  Process *process, ThreadContext *tc);
365 
368  Process *p, ThreadContext *tc);
369 
372  Process *p, ThreadContext *tc);
373 
376  Process *p, ThreadContext *tc);
377 
378 
380 const int one_million = 1000000;
382 const int one_billion = 1000000000;
383 
387 const unsigned seconds_since_epoch = 1000000000;
388 
391 template <class T1, class T2>
392 void
393 getElapsedTimeMicro(T1 &sec, T2 &usec)
394 {
395  uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
396  sec = elapsed_usecs / one_million;
397  usec = elapsed_usecs % one_million;
398 }
399 
402 template <class T1, class T2>
403 void
404 getElapsedTimeNano(T1 &sec, T2 &nsec)
405 {
406  uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
407  sec = elapsed_nsecs / one_billion;
408  nsec = elapsed_nsecs % one_billion;
409 }
410 
412 //
413 // The following emulation functions are generic, but need to be
414 // templated to account for differences in types, constants, etc.
415 //
417 
418  typedef struct statfs hst_statfs;
419 #if NO_STAT64
420  typedef struct stat hst_stat;
421  typedef struct stat hst_stat64;
422 #else
423  typedef struct stat hst_stat;
424  typedef struct stat64 hst_stat64;
425 #endif
426 
430 
431 template <typename target_stat, typename host_stat>
432 void
433 convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
434 {
435  using namespace TheISA;
436 
437  if (fakeTTY)
438  tgt->st_dev = 0xA;
439  else
440  tgt->st_dev = host->st_dev;
441  tgt->st_dev = TheISA::htog(tgt->st_dev);
442  tgt->st_ino = host->st_ino;
443  tgt->st_ino = TheISA::htog(tgt->st_ino);
444  tgt->st_mode = host->st_mode;
445  if (fakeTTY) {
446  // Claim to be a character device
447  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
448  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
449  }
450  tgt->st_mode = TheISA::htog(tgt->st_mode);
451  tgt->st_nlink = host->st_nlink;
452  tgt->st_nlink = TheISA::htog(tgt->st_nlink);
453  tgt->st_uid = host->st_uid;
454  tgt->st_uid = TheISA::htog(tgt->st_uid);
455  tgt->st_gid = host->st_gid;
456  tgt->st_gid = TheISA::htog(tgt->st_gid);
457  if (fakeTTY)
458  tgt->st_rdev = 0x880d;
459  else
460  tgt->st_rdev = host->st_rdev;
461  tgt->st_rdev = TheISA::htog(tgt->st_rdev);
462  tgt->st_size = host->st_size;
463  tgt->st_size = TheISA::htog(tgt->st_size);
464  tgt->st_atimeX = host->st_atime;
465  tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
466  tgt->st_mtimeX = host->st_mtime;
467  tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
468  tgt->st_ctimeX = host->st_ctime;
469  tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
470  // Force the block size to be 8KB. This helps to ensure buffered io works
471  // consistently across different hosts.
472  tgt->st_blksize = 0x2000;
473  tgt->st_blksize = TheISA::htog(tgt->st_blksize);
474  tgt->st_blocks = host->st_blocks;
475  tgt->st_blocks = TheISA::htog(tgt->st_blocks);
476 }
477 
478 // Same for stat64
479 
480 template <typename target_stat, typename host_stat64>
481 void
482 convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
483 {
484  using namespace TheISA;
485 
486  convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
487 #if defined(STAT_HAVE_NSEC)
488  tgt->st_atime_nsec = host->st_atime_nsec;
489  tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
490  tgt->st_mtime_nsec = host->st_mtime_nsec;
491  tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
492  tgt->st_ctime_nsec = host->st_ctime_nsec;
493  tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
494 #else
495  tgt->st_atime_nsec = 0;
496  tgt->st_mtime_nsec = 0;
497  tgt->st_ctime_nsec = 0;
498 #endif
499 }
500 
501 // Here are a couple of convenience functions
502 template<class OS>
503 void
505  hst_stat *host, bool fakeTTY = false)
506 {
507  typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
508  tgt_stat_buf tgt(addr);
509  convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
510  tgt.copyOut(mem);
511 }
512 
513 template<class OS>
514 void
516  hst_stat64 *host, bool fakeTTY = false)
517 {
518  typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
519  tgt_stat_buf tgt(addr);
520  convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
521  tgt.copyOut(mem);
522 }
523 
524 template <class OS>
525 void
527  hst_statfs *host)
528 {
530 
531  tgt->f_type = TheISA::htog(host->f_type);
532 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
533  tgt->f_bsize = TheISA::htog(host->f_iosize);
534 #else
535  tgt->f_bsize = TheISA::htog(host->f_bsize);
536 #endif
537  tgt->f_blocks = TheISA::htog(host->f_blocks);
538  tgt->f_bfree = TheISA::htog(host->f_bfree);
539  tgt->f_bavail = TheISA::htog(host->f_bavail);
540  tgt->f_files = TheISA::htog(host->f_files);
541  tgt->f_ffree = TheISA::htog(host->f_ffree);
542  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
543 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
544  tgt->f_namelen = TheISA::htog(host->f_namemax);
545  tgt->f_frsize = TheISA::htog(host->f_bsize);
546 #elif defined(__APPLE__)
547  tgt->f_namelen = 0;
548  tgt->f_frsize = 0;
549 #else
550  tgt->f_namelen = TheISA::htog(host->f_namelen);
551  tgt->f_frsize = TheISA::htog(host->f_frsize);
552 #endif
553 #if defined(__linux__)
554  memcpy(&tgt->f_spare, &host->f_spare, sizeof(host->f_spare));
555 #else
556  /*
557  * The fields are different sizes per OS. Don't bother with
558  * f_spare or f_reserved on non-Linux for now.
559  */
560  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
561 #endif
562 
563  tgt.copyOut(mem);
564 }
565 
570 template <class OS>
572 ioctlFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
573 {
574  int index = 0;
575  int tgt_fd = p->getSyscallArg(tc, index);
576  unsigned req = p->getSyscallArg(tc, index);
577 
578  DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
579 
580  if (OS::isTtyReq(req))
581  return -ENOTTY;
582 
583  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
584  if (!dfdp)
585  return -EBADF;
586 
592  EmulatedDriver *emul_driver = dfdp->getDriver();
593  if (emul_driver)
594  return emul_driver->ioctl(p, tc, req);
595 
600  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
601  tgt_fd, req, tc->pcState());
602  return -ENOTTY;
603 }
604 
605 template <class OS>
607 openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
608  bool isopenat)
609 {
610  int index = 0;
611  int tgt_dirfd = -1;
612 
617  if (isopenat)
618  tgt_dirfd = p->getSyscallArg(tc, index);
619 
624  std::string path;
625  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
626  return -EFAULT;
627 
628 #ifdef __CYGWIN32__
629  int host_flags = O_BINARY;
630 #else
631  int host_flags = 0;
632 #endif
633 
637  int tgt_flags = p->getSyscallArg(tc, index);
638  for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
639  if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
640  tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
641  host_flags |= OS::openFlagTable[i].hostFlag;
642  }
643  }
644  if (tgt_flags) {
645  warn("open%s: cannot decode flags 0x%x",
646  isopenat ? "at" : "", tgt_flags);
647  }
648 #ifdef __CYGWIN32__
649  host_flags |= O_BINARY;
650 #endif
651 
652  int mode = p->getSyscallArg(tc, index);
653 
666  if (!isopenat || (isopenat && tgt_dirfd == OS::TGT_AT_FDCWD)) {
667  path = p->fullPath(path);
668  } else if (!startswith(path, "/")) {
669  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
670  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
671  if (!ffdp)
672  return -EBADF;
673  path.insert(0, ffdp->getFileName());
674  }
675 
682  if (startswith(path, "/dev/")) {
683  std::string filename = path.substr(strlen("/dev/"));
684  EmulatedDriver *drv = p->findDriver(filename);
685  if (drv) {
686  DPRINTF_SYSCALL(Verbose, "open%s: passing call to "
687  "driver open with path[%s]\n",
688  isopenat ? "at" : "", path.c_str());
689  return drv->open(p, tc, mode, host_flags);
690  }
695  }
696 
706  int sim_fd = -1;
707  std::vector<std::string> special_paths =
708  { "/proc/", "/system/", "/sys/", "/platform/", "/etc/passwd" };
709  for (auto entry : special_paths) {
710  if (startswith(path, entry))
711  sim_fd = OS::openSpecialFile(path, p, tc);
712  }
713  if (sim_fd == -1) {
714  sim_fd = open(path.c_str(), host_flags, mode);
715  }
716  if (sim_fd == -1) {
717  int local = -errno;
718  DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n",
719  isopenat ? "at" : "", path.c_str());
720  return local;
721  }
722 
731  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
732  int tgt_fd = p->fds->allocFD(ffdp);
733  DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n",
734  isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str());
735  return tgt_fd;
736 }
737 
739 template <class OS>
741 openFunc(SyscallDesc *desc, int callnum, Process *process,
742  ThreadContext *tc)
743 {
744  return openImpl<OS>(desc, callnum, process, tc, false);
745 }
746 
748 template <class OS>
750 openatFunc(SyscallDesc *desc, int callnum, Process *process,
751  ThreadContext *tc)
752 {
753  return openImpl<OS>(desc, callnum, process, tc, true);
754 }
755 
757 template <class OS>
759 unlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
760  ThreadContext *tc)
761 {
762  int index = 0;
763  int dirfd = process->getSyscallArg(tc, index);
764  if (dirfd != OS::TGT_AT_FDCWD)
765  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
766 
767  return unlinkHelper(desc, callnum, process, tc, 1);
768 }
769 
771 template <class OS>
773 faccessatFunc(SyscallDesc *desc, int callnum, Process *process,
774  ThreadContext *tc)
775 {
776  int index = 0;
777  int dirfd = process->getSyscallArg(tc, index);
778  if (dirfd != OS::TGT_AT_FDCWD)
779  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
780  return accessFunc(desc, callnum, process, tc, 1);
781 }
782 
784 template <class OS>
786 readlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
787  ThreadContext *tc)
788 {
789  int index = 0;
790  int dirfd = process->getSyscallArg(tc, index);
791  if (dirfd != OS::TGT_AT_FDCWD)
792  warn("openat: first argument not AT_FDCWD; unlikely to work");
793  return readlinkFunc(desc, callnum, process, tc, 1);
794 }
795 
797 template <class OS>
799 renameatFunc(SyscallDesc *desc, int callnum, Process *process,
800  ThreadContext *tc)
801 {
802  int index = 0;
803 
804  int olddirfd = process->getSyscallArg(tc, index);
805  if (olddirfd != OS::TGT_AT_FDCWD)
806  warn("renameat: first argument not AT_FDCWD; unlikely to work");
807 
808  std::string old_name;
809 
810  if (!tc->getMemProxy().tryReadString(old_name,
811  process->getSyscallArg(tc, index)))
812  return -EFAULT;
813 
814  int newdirfd = process->getSyscallArg(tc, index);
815  if (newdirfd != OS::TGT_AT_FDCWD)
816  warn("renameat: third argument not AT_FDCWD; unlikely to work");
817 
818  std::string new_name;
819 
820  if (!tc->getMemProxy().tryReadString(new_name,
821  process->getSyscallArg(tc, index)))
822  return -EFAULT;
823 
824  // Adjust path for current working directory
825  old_name = process->fullPath(old_name);
826  new_name = process->fullPath(new_name);
827 
828  int result = rename(old_name.c_str(), new_name.c_str());
829  return (result == -1) ? -errno : result;
830 }
831 
833 template <class OS>
835 sysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
836  ThreadContext *tc)
837 {
838 
839  int index = 0;
841  sysinfo(process->getSyscallArg(tc, index));
842 
843  sysinfo->uptime = seconds_since_epoch;
844  sysinfo->totalram = process->system->memSize();
845  sysinfo->mem_unit = 1;
846 
847  sysinfo.copyOut(tc->getMemProxy());
848 
849  return 0;
850 }
851 
853 template <class OS>
855 chmodFunc(SyscallDesc *desc, int callnum, Process *process,
856  ThreadContext *tc)
857 {
858  std::string path;
859 
860  int index = 0;
861  if (!tc->getMemProxy().tryReadString(path,
862  process->getSyscallArg(tc, index))) {
863  return -EFAULT;
864  }
865 
866  uint32_t mode = process->getSyscallArg(tc, index);
867  mode_t hostMode = 0;
868 
869  // XXX translate mode flags via OS::something???
870  hostMode = mode;
871 
872  // Adjust path for current working directory
873  path = process->fullPath(path);
874 
875  // do the chmod
876  int result = chmod(path.c_str(), hostMode);
877  if (result < 0)
878  return -errno;
879 
880  return 0;
881 }
882 
883 
885 template <class OS>
887 fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
888 {
889  int index = 0;
890  int tgt_fd = p->getSyscallArg(tc, index);
891  uint32_t mode = p->getSyscallArg(tc, index);
892 
893  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
894  if (!ffdp)
895  return -EBADF;
896  int sim_fd = ffdp->getSimFD();
897 
898  mode_t hostMode = mode;
899 
900  int result = fchmod(sim_fd, hostMode);
901 
902  return (result < 0) ? -errno : 0;
903 }
904 
906 template <class OS>
908 mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
909 {
910  int index = 0;
911  Addr start = process->getSyscallArg(tc, index);
912  uint64_t old_length = process->getSyscallArg(tc, index);
913  uint64_t new_length = process->getSyscallArg(tc, index);
914  uint64_t flags = process->getSyscallArg(tc, index);
915  uint64_t provided_address = 0;
916  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
917 
918  if (use_provided_address)
919  provided_address = process->getSyscallArg(tc, index);
920 
921  if ((start % TheISA::PageBytes != 0) ||
922  (provided_address % TheISA::PageBytes != 0)) {
923  warn("mremap failing: arguments not page aligned");
924  return -EINVAL;
925  }
926 
927  new_length = roundUp(new_length, TheISA::PageBytes);
928 
929  if (new_length > old_length) {
930  std::shared_ptr<MemState> mem_state = process->memState;
931  Addr mmap_end = mem_state->getMmapEnd();
932 
933  if ((start + old_length) == mmap_end &&
934  (!use_provided_address || provided_address == start)) {
935  uint64_t diff = new_length - old_length;
936  process->allocateMem(mmap_end, diff);
937  mem_state->setMmapEnd(mmap_end + diff);
938  return start;
939  } else {
940  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
941  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
942  return -ENOMEM;
943  } else {
944  uint64_t new_start = use_provided_address ?
945  provided_address : mmap_end;
946  process->pTable->remap(start, old_length, new_start);
947  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
948  new_start, new_start + new_length,
949  new_length - old_length);
950  // add on the remaining unallocated pages
951  process->allocateMem(new_start + old_length,
952  new_length - old_length,
953  use_provided_address /* clobber */);
954  if (!use_provided_address)
955  mem_state->setMmapEnd(mmap_end + new_length);
956  if (use_provided_address &&
957  new_start + new_length > mem_state->getMmapEnd()) {
958  // something fishy going on here, at least notify the user
959  // @todo: increase mmap_end?
960  warn("mmap region limit exceeded with MREMAP_FIXED\n");
961  }
962  warn("returning %08p as start\n", new_start);
963  return new_start;
964  }
965  }
966  } else {
967  if (use_provided_address && provided_address != start)
968  process->pTable->remap(start, new_length, provided_address);
969  process->pTable->unmap(start + new_length, old_length - new_length);
970  return use_provided_address ? provided_address : start;
971  }
972 }
973 
975 template <class OS>
977 statFunc(SyscallDesc *desc, int callnum, Process *process,
978  ThreadContext *tc)
979 {
980  std::string path;
981 
982  int index = 0;
983  if (!tc->getMemProxy().tryReadString(path,
984  process->getSyscallArg(tc, index))) {
985  return -EFAULT;
986  }
987  Addr bufPtr = process->getSyscallArg(tc, index);
988 
989  // Adjust path for current working directory
990  path = process->fullPath(path);
991 
992  struct stat hostBuf;
993  int result = stat(path.c_str(), &hostBuf);
994 
995  if (result < 0)
996  return -errno;
997 
998  copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
999 
1000  return 0;
1001 }
1002 
1003 
1005 template <class OS>
1007 stat64Func(SyscallDesc *desc, int callnum, Process *process,
1008  ThreadContext *tc)
1009 {
1010  std::string path;
1011 
1012  int index = 0;
1013  if (!tc->getMemProxy().tryReadString(path,
1014  process->getSyscallArg(tc, index)))
1015  return -EFAULT;
1016  Addr bufPtr = process->getSyscallArg(tc, index);
1017 
1018  // Adjust path for current working directory
1019  path = process->fullPath(path);
1020 
1021 #if NO_STAT64
1022  struct stat hostBuf;
1023  int result = stat(path.c_str(), &hostBuf);
1024 #else
1025  struct stat64 hostBuf;
1026  int result = stat64(path.c_str(), &hostBuf);
1027 #endif
1028 
1029  if (result < 0)
1030  return -errno;
1031 
1032  copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1033 
1034  return 0;
1035 }
1036 
1037 
1039 template <class OS>
1041 fstatat64Func(SyscallDesc *desc, int callnum, Process *process,
1042  ThreadContext *tc)
1043 {
1044  int index = 0;
1045  int dirfd = process->getSyscallArg(tc, index);
1046  if (dirfd != OS::TGT_AT_FDCWD)
1047  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1048 
1049  std::string path;
1050  if (!tc->getMemProxy().tryReadString(path,
1051  process->getSyscallArg(tc, index)))
1052  return -EFAULT;
1053  Addr bufPtr = process->getSyscallArg(tc, index);
1054 
1055  // Adjust path for current working directory
1056  path = process->fullPath(path);
1057 
1058 #if NO_STAT64
1059  struct stat hostBuf;
1060  int result = stat(path.c_str(), &hostBuf);
1061 #else
1062  struct stat64 hostBuf;
1063  int result = stat64(path.c_str(), &hostBuf);
1064 #endif
1065 
1066  if (result < 0)
1067  return -errno;
1068 
1069  copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1070 
1071  return 0;
1072 }
1073 
1074 
1076 template <class OS>
1078 fstat64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1079 {
1080  int index = 0;
1081  int tgt_fd = p->getSyscallArg(tc, index);
1082  Addr bufPtr = p->getSyscallArg(tc, index);
1083 
1084  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1085  if (!ffdp)
1086  return -EBADF;
1087  int sim_fd = ffdp->getSimFD();
1088 
1089 #if NO_STAT64
1090  struct stat hostBuf;
1091  int result = fstat(sim_fd, &hostBuf);
1092 #else
1093  struct stat64 hostBuf;
1094  int result = fstat64(sim_fd, &hostBuf);
1095 #endif
1096 
1097  if (result < 0)
1098  return -errno;
1099 
1100  copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1101 
1102  return 0;
1103 }
1104 
1105 
1107 template <class OS>
1109 lstatFunc(SyscallDesc *desc, int callnum, Process *process,
1110  ThreadContext *tc)
1111 {
1112  std::string path;
1113 
1114  int index = 0;
1115  if (!tc->getMemProxy().tryReadString(path,
1116  process->getSyscallArg(tc, index))) {
1117  return -EFAULT;
1118  }
1119  Addr bufPtr = process->getSyscallArg(tc, index);
1120 
1121  // Adjust path for current working directory
1122  path = process->fullPath(path);
1123 
1124  struct stat hostBuf;
1125  int result = lstat(path.c_str(), &hostBuf);
1126 
1127  if (result < 0)
1128  return -errno;
1129 
1130  copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1131 
1132  return 0;
1133 }
1134 
1136 template <class OS>
1138 lstat64Func(SyscallDesc *desc, int callnum, Process *process,
1139  ThreadContext *tc)
1140 {
1141  std::string path;
1142 
1143  int index = 0;
1144  if (!tc->getMemProxy().tryReadString(path,
1145  process->getSyscallArg(tc, index))) {
1146  return -EFAULT;
1147  }
1148  Addr bufPtr = process->getSyscallArg(tc, index);
1149 
1150  // Adjust path for current working directory
1151  path = process->fullPath(path);
1152 
1153 #if NO_STAT64
1154  struct stat hostBuf;
1155  int result = lstat(path.c_str(), &hostBuf);
1156 #else
1157  struct stat64 hostBuf;
1158  int result = lstat64(path.c_str(), &hostBuf);
1159 #endif
1160 
1161  if (result < 0)
1162  return -errno;
1163 
1164  copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1165 
1166  return 0;
1167 }
1168 
1170 template <class OS>
1172 fstatFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1173 {
1174  int index = 0;
1175  int tgt_fd = p->getSyscallArg(tc, index);
1176  Addr bufPtr = p->getSyscallArg(tc, index);
1177 
1178  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1179 
1180  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1181  if (!ffdp)
1182  return -EBADF;
1183  int sim_fd = ffdp->getSimFD();
1184 
1185  struct stat hostBuf;
1186  int result = fstat(sim_fd, &hostBuf);
1187 
1188  if (result < 0)
1189  return -errno;
1190 
1191  copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1192 
1193  return 0;
1194 }
1195 
1196 
1198 template <class OS>
1200 statfsFunc(SyscallDesc *desc, int callnum, Process *process,
1201  ThreadContext *tc)
1202 {
1203 #if NO_STATFS
1204  warn("Host OS cannot support calls to statfs. Ignoring syscall");
1205 #else
1206  std::string path;
1207 
1208  int index = 0;
1209  if (!tc->getMemProxy().tryReadString(path,
1210  process->getSyscallArg(tc, index))) {
1211  return -EFAULT;
1212  }
1213  Addr bufPtr = process->getSyscallArg(tc, index);
1214 
1215  // Adjust path for current working directory
1216  path = process->fullPath(path);
1217 
1218  struct statfs hostBuf;
1219  int result = statfs(path.c_str(), &hostBuf);
1220 
1221  if (result < 0)
1222  return -errno;
1223 
1224  copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1225 #endif
1226  return 0;
1227 }
1228 
1229 template <class OS>
1231 cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1232 {
1233  int index = 0;
1234  TheISA::IntReg flags = p->getSyscallArg(tc, index);
1235  TheISA::IntReg newStack = p->getSyscallArg(tc, index);
1236  Addr ptidPtr = p->getSyscallArg(tc, index);
1237  Addr ctidPtr = p->getSyscallArg(tc, index);
1238  Addr tlsPtr M5_VAR_USED = p->getSyscallArg(tc, index);
1239 
1240  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1241  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1242  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1243  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1244  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1245  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1246  return -EINVAL;
1247 
1248  ThreadContext *ctc;
1249  if (!(ctc = p->findFreeContext()))
1250  fatal("clone: no spare thread context in system");
1251 
1258  ProcessParams *pp = new ProcessParams();
1259  pp->executable.assign(*(new std::string(p->progName())));
1260  pp->cmd.push_back(*(new std::string(p->progName())));
1261  pp->system = p->system;
1262  pp->cwd.assign(p->getcwd());
1263  pp->input.assign("stdin");
1264  pp->output.assign("stdout");
1265  pp->errout.assign("stderr");
1266  pp->uid = p->uid();
1267  pp->euid = p->euid();
1268  pp->gid = p->gid();
1269  pp->egid = p->egid();
1270 
1271  /* Find the first free PID that's less than the maximum */
1272  std::set<int> const& pids = p->system->PIDs;
1273  int temp_pid = *pids.begin();
1274  do {
1275  temp_pid++;
1276  } while (pids.find(temp_pid) != pids.end());
1277  if (temp_pid >= System::maxPID)
1278  fatal("temp_pid is too large: %d", temp_pid);
1279 
1280  pp->pid = temp_pid;
1281  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1282  Process *cp = pp->create();
1283  delete pp;
1284 
1285  Process *owner = ctc->getProcessPtr();
1286  ctc->setProcessPtr(cp);
1287  cp->assignThreadContext(ctc->contextId());
1288  owner->revokeThreadContext(ctc->contextId());
1289 
1290  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1291  BufferArg ptidBuf(ptidPtr, sizeof(long));
1292  long *ptid = (long *)ptidBuf.bufferPtr();
1293  *ptid = cp->pid();
1294  ptidBuf.copyOut(tc->getMemProxy());
1295  }
1296 
1297  cp->initState();
1298  p->clone(tc, ctc, cp, flags);
1299 
1300  if (flags & OS::TGT_CLONE_THREAD) {
1301  delete cp->sigchld;
1302  cp->sigchld = p->sigchld;
1303  } else if (flags & OS::TGT_SIGCHLD) {
1304  *cp->sigchld = true;
1305  }
1306 
1307  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1308  BufferArg ctidBuf(ctidPtr, sizeof(long));
1309  long *ctid = (long *)ctidBuf.bufferPtr();
1310  *ctid = cp->pid();
1311  ctidBuf.copyOut(ctc->getMemProxy());
1312  }
1313 
1314  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1315  cp->childClearTID = (uint64_t)ctidPtr;
1316 
1317  ctc->clearArchRegs();
1318 
1319 #if THE_ISA == ALPHA_ISA
1320  TheISA::copyMiscRegs(tc, ctc);
1321 #elif THE_ISA == SPARC_ISA
1322  TheISA::copyRegs(tc, ctc);
1323  ctc->setIntReg(TheISA::NumIntArchRegs + 6, 0);
1324  ctc->setIntReg(TheISA::NumIntArchRegs + 4, 0);
1328  ctc->setIntReg(TheISA::NumIntArchRegs + 7, 0);
1331  for (int y = 8; y < 32; y++)
1332  ctc->setIntReg(y, tc->readIntReg(y));
1333 #elif THE_ISA == ARM_ISA or THE_ISA == X86_ISA
1334  TheISA::copyRegs(tc, ctc);
1335 #endif
1336 
1337 #if THE_ISA == X86_ISA
1338  if (flags & OS::TGT_CLONE_SETTLS) {
1341  }
1342 #endif
1343 
1344  if (newStack)
1345  ctc->setIntReg(TheISA::StackPointerReg, newStack);
1346 
1347  cp->setSyscallReturn(ctc, 0);
1348 
1349 #if THE_ISA == ALPHA_ISA
1351 #elif THE_ISA == SPARC_ISA
1354 #endif
1355 
1356  ctc->pcState(tc->nextInstAddr());
1357  ctc->activate();
1358 
1359  return cp->pid();
1360 }
1361 
1363 template <class OS>
1365 fstatfsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1366 {
1367  int index = 0;
1368  int tgt_fd = p->getSyscallArg(tc, index);
1369  Addr bufPtr = p->getSyscallArg(tc, index);
1370 
1371  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1372  if (!ffdp)
1373  return -EBADF;
1374  int sim_fd = ffdp->getSimFD();
1375 
1376  struct statfs hostBuf;
1377  int result = fstatfs(sim_fd, &hostBuf);
1378 
1379  if (result < 0)
1380  return -errno;
1381 
1382  copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1383 
1384  return 0;
1385 }
1386 
1387 
1389 template <class OS>
1391 writevFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1392 {
1393  int index = 0;
1394  int tgt_fd = p->getSyscallArg(tc, index);
1395 
1396  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1397  if (!hbfdp)
1398  return -EBADF;
1399  int sim_fd = hbfdp->getSimFD();
1400 
1401  SETranslatingPortProxy &prox = tc->getMemProxy();
1402  uint64_t tiov_base = p->getSyscallArg(tc, index);
1403  size_t count = p->getSyscallArg(tc, index);
1404  struct iovec hiov[count];
1405  for (size_t i = 0; i < count; ++i) {
1406  typename OS::tgt_iovec tiov;
1407 
1408  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1409  (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
1410  hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
1411  hiov[i].iov_base = new char [hiov[i].iov_len];
1412  prox.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
1413  hiov[i].iov_len);
1414  }
1415 
1416  int result = writev(sim_fd, hiov, count);
1417 
1418  for (size_t i = 0; i < count; ++i)
1419  delete [] (char *)hiov[i].iov_base;
1420 
1421  if (result < 0)
1422  return -errno;
1423 
1424  return result;
1425 }
1426 
1428 template <class OS>
1431  bool is_mmap2)
1432 {
1433  int index = 0;
1434  Addr start = p->getSyscallArg(tc, index);
1435  uint64_t length = p->getSyscallArg(tc, index);
1436  int prot = p->getSyscallArg(tc, index);
1437  int tgt_flags = p->getSyscallArg(tc, index);
1438  int tgt_fd = p->getSyscallArg(tc, index);
1439  int offset = p->getSyscallArg(tc, index);
1440 
1441  if (is_mmap2)
1442  offset *= TheISA::PageBytes;
1443 
1444  if (start & (TheISA::PageBytes - 1) ||
1445  offset & (TheISA::PageBytes - 1) ||
1446  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1447  tgt_flags & OS::TGT_MAP_SHARED) ||
1448  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1449  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1450  !length) {
1451  return -EINVAL;
1452  }
1453 
1454  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1455  // With shared mmaps, there are two cases to consider:
1456  // 1) anonymous: writes should modify the mapping and this should be
1457  // visible to observers who share the mapping. Currently, it's
1458  // difficult to update the shared mapping because there's no
1459  // structure which maintains information about the which virtual
1460  // memory areas are shared. If that structure existed, it would be
1461  // possible to make the translations point to the same frames.
1462  // 2) file-backed: writes should modify the mapping and the file
1463  // which is backed by the mapping. The shared mapping problem is the
1464  // same as what was mentioned about the anonymous mappings. For
1465  // file-backed mappings, the writes to the file are difficult
1466  // because it requires syncing what the mapping holds with the file
1467  // that resides on the host system. So, any write on a real system
1468  // would cause the change to be propagated to the file mapping at
1469  // some point in the future (the inode is tracked along with the
1470  // mapping). This isn't guaranteed to always happen, but it usually
1471  // works well enough. The guarantee is provided by the msync system
1472  // call. We could force the change through with shared mappings with
1473  // a call to msync, but that again would require more information
1474  // than we currently maintain.
1475  warn("mmap: writing to shared mmap region is currently "
1476  "unsupported. The write succeeds on the target, but it "
1477  "will not be propagated to the host or shared mappings");
1478  }
1479 
1480  length = roundUp(length, TheISA::PageBytes);
1481 
1482  int sim_fd = -1;
1483  uint8_t *pmap = nullptr;
1484  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1485  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1486 
1487  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1488  if (dfdp) {
1489  EmulatedDriver *emul_driver = dfdp->getDriver();
1490  return emul_driver->mmap(p, tc, start, length, prot,
1491  tgt_flags, tgt_fd, offset);
1492  }
1493 
1494  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1495  if (!ffdp)
1496  return -EBADF;
1497  sim_fd = ffdp->getSimFD();
1498 
1499  pmap = (decltype(pmap))mmap(nullptr, length, PROT_READ, MAP_PRIVATE,
1500  sim_fd, offset);
1501 
1502  if (pmap == (decltype(pmap))-1) {
1503  warn("mmap: failed to map file into host address space");
1504  return -errno;
1505  }
1506  }
1507 
1508  // Extend global mmap region if necessary. Note that we ignore the
1509  // start address unless MAP_FIXED is specified.
1510  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1511  std::shared_ptr<MemState> mem_state = p->memState;
1512  Addr mmap_end = mem_state->getMmapEnd();
1513 
1514  start = p->mmapGrowsDown() ? mmap_end - length : mmap_end;
1515  mmap_end = p->mmapGrowsDown() ? start : mmap_end + length;
1516 
1517  mem_state->setMmapEnd(mmap_end);
1518  }
1519 
1520  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1521  start, start + length - 1);
1522 
1523  // We only allow mappings to overwrite existing mappings if
1524  // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem
1525  // because we ignore the start hint if TGT_MAP_FIXED is not set.
1526  int clobber = tgt_flags & OS::TGT_MAP_FIXED;
1527  if (clobber) {
1528  for (auto tc : p->system->threadContexts) {
1529  // If we might be overwriting old mappings, we need to
1530  // invalidate potentially stale mappings out of the TLBs.
1531  tc->getDTBPtr()->flushAll();
1532  tc->getITBPtr()->flushAll();
1533  }
1534  }
1535 
1536  // Allocate physical memory and map it in. If the page table is already
1537  // mapped and clobber is not set, the simulator will issue throw a
1538  // fatal and bail out of the simulation.
1539  p->allocateMem(start, length, clobber);
1540 
1541  // Transfer content into target address space.
1542  SETranslatingPortProxy &tp = tc->getMemProxy();
1543  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1544  // In general, we should zero the mapped area for anonymous mappings,
1545  // with something like:
1546  // tp.memsetBlob(start, 0, length);
1547  // However, given that we don't support sparse mappings, and
1548  // some applications can map a couple of gigabytes of space
1549  // (intending sparse usage), that can get painfully expensive.
1550  // Fortunately, since we don't properly implement munmap either,
1551  // there's no danger of remapping used memory, so for now all
1552  // newly mapped memory should already be zeroed so we can skip it.
1553  } else {
1554  // It is possible to mmap an area larger than a file, however
1555  // accessing unmapped portions the system triggers a "Bus error"
1556  // on the host. We must know when to stop copying the file from
1557  // the host into the target address space.
1558  struct stat file_stat;
1559  if (fstat(sim_fd, &file_stat) > 0)
1560  fatal("mmap: cannot stat file");
1561 
1562  // Copy the portion of the file that is resident. This requires
1563  // checking both the mmap size and the filesize that we are
1564  // trying to mmap into this space; the mmap size also depends
1565  // on the specified offset into the file.
1566  uint64_t size = std::min((uint64_t)file_stat.st_size - offset,
1567  length);
1568  tp.writeBlob(start, pmap, size);
1569 
1570  // Cleanup the mmap region before exiting this function.
1571  munmap(pmap, length);
1572 
1573  // Maintain the symbol table for dynamic executables.
1574  // The loader will call mmap to map the images into its address
1575  // space and we intercept that here. We can verify that we are
1576  // executing inside the loader by checking the program counter value.
1577  // XXX: with multiprogrammed workloads or multi-node configurations,
1578  // this will not work since there is a single global symbol table.
1579  ObjectFile *interpreter = p->getInterpreter();
1580  if (interpreter) {
1581  Addr text_start = interpreter->textBase();
1582  Addr text_end = text_start + interpreter->textSize();
1583 
1584  Addr pc = tc->pcState().pc();
1585 
1586  if (pc >= text_start && pc < text_end) {
1587  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1588  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1589  ObjectFile *lib = createObjectFile(ffdp->getFileName());
1590 
1591  if (lib) {
1593  lib->textBase(), start);
1594  }
1595  }
1596  }
1597 
1598  // Note that we do not zero out the remainder of the mapping. This
1599  // is done by a real system, but it probably will not affect
1600  // execution (hopefully).
1601  }
1602 
1603  return start;
1604 }
1605 
1606 template <class OS>
1609 {
1610  int index = 0;
1611  int tgt_fd = p->getSyscallArg(tc, index);
1612  Addr bufPtr = p->getSyscallArg(tc, index);
1613  int nbytes = p->getSyscallArg(tc, index);
1614  int offset = p->getSyscallArg(tc, index);
1615 
1616  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1617  if (!ffdp)
1618  return -EBADF;
1619  int sim_fd = ffdp->getSimFD();
1620 
1621  BufferArg bufArg(bufPtr, nbytes);
1622  bufArg.copyIn(tc->getMemProxy());
1623 
1624  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1625 
1626  return (bytes_written == -1) ? -errno : bytes_written;
1627 }
1628 
1630 template <class OS>
1633 {
1634  return mmapImpl<OS>(desc, num, p, tc, false);
1635 }
1636 
1638 template <class OS>
1641 {
1642  return mmapImpl<OS>(desc, num, p, tc, true);
1643 }
1644 
1646 template <class OS>
1648 getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
1649  ThreadContext *tc)
1650 {
1651  int index = 0;
1652  unsigned resource = process->getSyscallArg(tc, index);
1653  TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
1654 
1655  switch (resource) {
1656  case OS::TGT_RLIMIT_STACK:
1657  // max stack size in bytes: make up a number (8MB for now)
1658  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1659  rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1660  rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1661  break;
1662 
1663  case OS::TGT_RLIMIT_DATA:
1664  // max data segment size in bytes: make up a number
1665  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1666  rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1667  rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1668  break;
1669 
1670  default:
1671  warn("getrlimit: unimplemented resource %d", resource);
1672  return -EINVAL;
1673  break;
1674  }
1675 
1676  rlp.copyOut(tc->getMemProxy());
1677  return 0;
1678 }
1679 
1681 template <class OS>
1684 {
1685  int index = 1;
1686  //int clk_id = p->getSyscallArg(tc, index);
1688 
1689  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1690  tp->tv_sec += seconds_since_epoch;
1691  tp->tv_sec = TheISA::htog(tp->tv_sec);
1692  tp->tv_nsec = TheISA::htog(tp->tv_nsec);
1693 
1694  tp.copyOut(tc->getMemProxy());
1695 
1696  return 0;
1697 }
1698 
1700 template <class OS>
1703 {
1704  int index = 1;
1706 
1707  // Set resolution at ns, which is what clock_gettime() returns
1708  tp->tv_sec = 0;
1709  tp->tv_nsec = 1;
1710 
1711  tp.copyOut(tc->getMemProxy());
1712 
1713  return 0;
1714 }
1715 
1717 template <class OS>
1719 gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
1720  ThreadContext *tc)
1721 {
1722  int index = 0;
1723  TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
1724 
1725  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1726  tp->tv_sec += seconds_since_epoch;
1727  tp->tv_sec = TheISA::htog(tp->tv_sec);
1728  tp->tv_usec = TheISA::htog(tp->tv_usec);
1729 
1730  tp.copyOut(tc->getMemProxy());
1731 
1732  return 0;
1733 }
1734 
1735 
1737 template <class OS>
1739 utimesFunc(SyscallDesc *desc, int callnum, Process *process,
1740  ThreadContext *tc)
1741 {
1742  std::string path;
1743 
1744  int index = 0;
1745  if (!tc->getMemProxy().tryReadString(path,
1746  process->getSyscallArg(tc, index))) {
1747  return -EFAULT;
1748  }
1749 
1751  tp(process->getSyscallArg(tc, index));
1752  tp.copyIn(tc->getMemProxy());
1753 
1754  struct timeval hostTimeval[2];
1755  for (int i = 0; i < 2; ++i) {
1756  hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
1757  hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
1758  }
1759 
1760  // Adjust path for current working directory
1761  path = process->fullPath(path);
1762 
1763  int result = utimes(path.c_str(), hostTimeval);
1764 
1765  if (result < 0)
1766  return -errno;
1767 
1768  return 0;
1769 }
1770 
1771 template <class OS>
1773 execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1774 {
1775  desc->setFlags(0);
1776 
1777  int index = 0;
1778  std::string path;
1779  SETranslatingPortProxy & mem_proxy = tc->getMemProxy();
1780  if (!mem_proxy.tryReadString(path, p->getSyscallArg(tc, index)))
1781  return -EFAULT;
1782 
1783  if (access(path.c_str(), F_OK) == -1)
1784  return -EACCES;
1785 
1786  auto read_in = [](std::vector<std::string> & vect,
1787  SETranslatingPortProxy & mem_proxy,
1788  Addr mem_loc)
1789  {
1790  for (int inc = 0; ; inc++) {
1791  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
1792  b.copyIn(mem_proxy);
1793 
1794  if (!*(Addr*)b.bufferPtr())
1795  break;
1796 
1797  vect.push_back(std::string());
1798  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
1799  }
1800  };
1801 
1808  ProcessParams *pp = new ProcessParams();
1809  pp->executable = path;
1810  Addr argv_mem_loc = p->getSyscallArg(tc, index);
1811  read_in(pp->cmd, mem_proxy, argv_mem_loc);
1812  Addr envp_mem_loc = p->getSyscallArg(tc, index);
1813  read_in(pp->env, mem_proxy, envp_mem_loc);
1814  pp->uid = p->uid();
1815  pp->egid = p->egid();
1816  pp->euid = p->euid();
1817  pp->gid = p->gid();
1818  pp->ppid = p->ppid();
1819  pp->pid = p->pid();
1820  pp->input.assign("cin");
1821  pp->output.assign("cout");
1822  pp->errout.assign("cerr");
1823  pp->cwd.assign(p->getcwd());
1824  pp->system = p->system;
1833  p->system->PIDs.erase(p->pid());
1834  Process *new_p = pp->create();
1835  delete pp;
1836 
1841  new_p->fds = p->fds;
1842  for (int i = 0; i < new_p->fds->getSize(); i++) {
1843  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
1844  if (fdep && fdep->getCOE())
1845  new_p->fds->closeFDEntry(i);
1846  }
1847 
1848  *new_p->sigchld = true;
1849 
1850  delete p;
1851  tc->clearArchRegs();
1852  tc->setProcessPtr(new_p);
1853  new_p->assignThreadContext(tc->contextId());
1854  new_p->initState();
1855  tc->activate();
1856  TheISA::PCState pcState = tc->pcState();
1857  tc->setNPC(pcState.instAddr());
1858 
1860  return 0;
1861 }
1862 
1864 template <class OS>
1866 getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
1867  ThreadContext *tc)
1868 {
1869  int index = 0;
1870  int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
1871  TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
1872 
1873  rup->ru_utime.tv_sec = 0;
1874  rup->ru_utime.tv_usec = 0;
1875  rup->ru_stime.tv_sec = 0;
1876  rup->ru_stime.tv_usec = 0;
1877  rup->ru_maxrss = 0;
1878  rup->ru_ixrss = 0;
1879  rup->ru_idrss = 0;
1880  rup->ru_isrss = 0;
1881  rup->ru_minflt = 0;
1882  rup->ru_majflt = 0;
1883  rup->ru_nswap = 0;
1884  rup->ru_inblock = 0;
1885  rup->ru_oublock = 0;
1886  rup->ru_msgsnd = 0;
1887  rup->ru_msgrcv = 0;
1888  rup->ru_nsignals = 0;
1889  rup->ru_nvcsw = 0;
1890  rup->ru_nivcsw = 0;
1891 
1892  switch (who) {
1893  case OS::TGT_RUSAGE_SELF:
1894  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
1895  rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
1896  rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
1897  break;
1898 
1899  case OS::TGT_RUSAGE_CHILDREN:
1900  // do nothing. We have no child processes, so they take no time.
1901  break;
1902 
1903  default:
1904  // don't really handle THREAD or CHILDREN, but just warn and
1905  // plow ahead
1906  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
1907  who);
1908  }
1909 
1910  rup.copyOut(tc->getMemProxy());
1911 
1912  return 0;
1913 }
1914 
1916 template <class OS>
1918 timesFunc(SyscallDesc *desc, int callnum, Process *process,
1919  ThreadContext *tc)
1920 {
1921  int index = 0;
1922  TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
1923 
1924  // Fill in the time structure (in clocks)
1925  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
1926  bufp->tms_utime = clocks;
1927  bufp->tms_stime = 0;
1928  bufp->tms_cutime = 0;
1929  bufp->tms_cstime = 0;
1930 
1931  // Convert to host endianness
1932  bufp->tms_utime = TheISA::htog(bufp->tms_utime);
1933 
1934  // Write back
1935  bufp.copyOut(tc->getMemProxy());
1936 
1937  // Return clock ticks since system boot
1938  return clocks;
1939 }
1940 
1942 template <class OS>
1944 timeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
1945 {
1946  typename OS::time_t sec, usec;
1947  getElapsedTimeMicro(sec, usec);
1948  sec += seconds_since_epoch;
1949 
1950  int index = 0;
1951  Addr taddr = (Addr)process->getSyscallArg(tc, index);
1952  if (taddr != 0) {
1953  typename OS::time_t t = sec;
1954  t = TheISA::htog(t);
1956  p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
1957  }
1958  return sec;
1959 }
1960 
1961 template <class OS>
1963 tgkillFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
1964 {
1965  int index = 0;
1966  int tgid = process->getSyscallArg(tc, index);
1967  int tid = process->getSyscallArg(tc, index);
1968  int sig = process->getSyscallArg(tc, index);
1969 
1985  System *sys = tc->getSystemPtr();
1986  Process *tgt_proc = nullptr;
1987  for (int i = 0; i < sys->numContexts(); i++) {
1988  Process *temp = sys->threadContexts[i]->getProcessPtr();
1989  if (temp->pid() == tid) {
1990  tgt_proc = temp;
1991  break;
1992  }
1993  }
1994 
1995  if (sig != 0 || sig != OS::TGT_SIGABRT)
1996  return -EINVAL;
1997 
1998  if (tgt_proc == nullptr)
1999  return -ESRCH;
2000 
2001  if (tgid != -1 && tgt_proc->tgid() != tgid)
2002  return -ESRCH;
2003 
2004  if (sig == OS::TGT_SIGABRT)
2005  exitGroupFunc(desc, 252, process, tc);
2006 
2007  return 0;
2008 }
2009 
2010 
2011 #endif // __SIM_SYSCALL_EMUL_HH__
count
Definition: misc.hh:704
SyscallReturn closeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target close() handler.
SyscallReturn setpgidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target setpgid() handler.
#define DPRINTF(x,...)
Definition: trace.hh:212
FutexMap futexMap
Definition: system.hh:555
SyscallReturn accessFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target access() handler.
This file defines buffer classes used to handle pointer arguments in emulated syscalls.
SyscallReturn _llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target _llseek() handler.
SyscallReturn writevFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target writev() handler.
SyscallReturn mmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target mmap() handler.
SyscallReturn clock_getresFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target clock_getres() function.
virtual System * getSystemPtr()=0
Bitfield< 30, 0 > index
T htog(T value)
Definition: byteswap.hh:177
SyscallReturn gettidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target gettid() handler.
Tick us
microsecond
Definition: core.cc:65
SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getgidPseudo() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getuid() handler.
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext...
Definition: process.cc:275
size_t textSize() const
Definition: object_file.hh:142
virtual void unmap(Addr vaddr, int64_t size)=0
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:212
SyscallReturn openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, bool isopenat)
Bitfield< 7 > i
Definition: miscregs.hh:1378
const int one_million
A readable name for 1,000,000, for converting microseconds to seconds.
SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target rename() handler.
SyscallReturn getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getrlimit() handler.
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target gettimeofday() handler.
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition: process.cc:310
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd? Most platforms grow downward, but a few (such as Alpha) grow upward instead, so they can override this method to return false.
Definition: process.hh:144
bool * sigchld
Definition: process.hh:215
SyscallReturn truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target truncate() handler.
bool copyIn(SETranslatingPortProxy &memproxy)
copy data into simulator space (read from target memory)
SyscallReturn sysinfoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target sysinfo() handler.
ip6_addr_t addr
Definition: inet.hh:335
uint64_t uid()
Definition: process.hh:83
const int one_billion
A readable name for 1,000,000,000, for converting nanoseconds to seconds.
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
virtual Process * getProcessPtr()=0
virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i)=0
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:102
virtual void readBlob(Addr addr, uint8_t *p, int size) const
Read size bytes memory at address and store in p.
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:45
Definition: system.hh:83
int getSimFD() const
Definition: fd_entry.hh:84
virtual void setIntReg(int reg_idx, uint64_t val)=0
Bitfield< 23, 0 > offset
Definition: types.hh:149
struct statfs hst_statfs
ObjectFile * getInterpreter()
Definition: process.cc:468
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:288
SyscallReturn unlinkatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target unlinkat() handler.
virtual TheISA::PCState pcState()=0
Bitfield< 4, 0 > mode
Definition: miscregs.hh:1385
Bitfield< 7 > prot
Definition: misc.hh:583
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
T roundUp(const T &val, const U &align)
Definition: intmath.hh:205
SyscallReturn pwrite64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
std::shared_ptr< MemState > memState
Definition: process.hh:206
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
SyscallReturn mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, bool is_mmap2)
Real mmap handler.
SyscallReturn fstatFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target fstat() handler.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
SyscallReturn cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
SyscallReturn lstat64Func(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target lstat64() handler.
T gtoh(T value)
Definition: byteswap.hh:179
SyscallReturn timeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target time() function.
virtual int ioctl(Process *p, ThreadContext *tc, unsigned req)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
Bitfield< 63 > val
Definition: misc.hh:770
SyscallReturn exitFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target exit() handler: terminate current context.
SyscallReturn getpidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getpid() handler.
SyscallReturn timesFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target times() function.
SyscallReturn execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
void copyOutStatfsBuf(SETranslatingPortProxy &mem, Addr addr, hst_statfs *host)
SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target ftruncate64() handler.
#define warn(...)
Definition: misc.hh:219
Bitfield< 7 > b
Definition: miscregs.hh:1564
SyscallReturn ioctlFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target ioctl() handler.
bool copyOut(SETranslatingPortProxy &memproxy)
copy data out of simulator space (write to target memory)
SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target gethostname() handler.
Tick curTick()
The current simulated tick.
Definition: core.hh:47
virtual uint64_t readIntReg(int reg_idx)=0
SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target ftruncate() handler.
SyscallReturn utimesFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target utimes() handler.
void assignThreadContext(ContextID context_id)
Definition: process.hh:125
SyscallReturn faccessatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target facessat() handler.
virtual void remap(Addr vaddr, int64_t size, Addr new_vaddr)=0
SyscallReturn chmodFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target chmod() handler.
static const int maxPID
Definition: system.hh:557
bool tryReadString(std::string &str, Addr addr) const
SyscallReturn writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target write() handler.
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target clock_gettime() function.
void copyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, hst_stat64 *host, bool fakeTTY=false)
Addr textBase() const
Definition: object_file.hh:138
uint64_t ppid()
Definition: process.hh:88
virtual void setProcessPtr(Process *p)=0
SyscallReturn chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target chown() handler.
virtual int open(Process *p, ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver. ...
uint64_t pid()
Definition: process.hh:87
virtual TheISA::TLB * getDTBPtr()=0
std::set< int > PIDs
Process set to track which PIDs have already been allocated.
Definition: system.hh:560
SyscallReturn mmap2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target mmap2() handler.
SyscallReturn ignoreFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling, etc.) and should not affect the correct behavior of the program.
Definition: syscall_emul.cc:67
SyscallReturn mkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target mkdir() handler.
uint64_t euid()
Definition: process.hh:84
const char * progName() const
Definition: process.hh:93
SyscallReturn fcntl64Func(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target fcntl64() handler.
virtual Addr nextInstAddr()=0
std::vector< ThreadContext * > threadContexts
Definition: system.hh:199
ThreadContext * findFreeContext()
Definition: process.cc:265
#define fatal(...)
Definition: misc.hh:163
void copyMiscRegs(ThreadContext *src, ThreadContext *dest)
Definition: utility.cc:86
SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getpagesize() handler.
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:76
SyscallReturn setuidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target setuid() handler.
SyscallReturn readlinkatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target readlinkat() handler.
SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
SyscallReturn umaskFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target umask() handler.
System * system
Definition: process.hh:171
SyscallReturn getegidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getegid() handler.
void setNPC(Addr val)
const RegIndex StackPointerReg
Definition: registers.hh:79
const RegIndex SyscallPseudoReturnReg
Definition: registers.hh:88
SyscallReturn renameatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target renameat() handler.
virtual SETranslatingPortProxy & getMemProxy()=0
SyscallReturn lseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target lseek() handler.
SyscallReturn fstatfsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target fstatfs() handler.
virtual void activate()=0
Set the status to Active.
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
std::string getcwd() const
Definition: process.hh:95
EmulatedDriver * findDriver(std::string filename)
Find an emulated device driver.
Definition: process.cc:431
SyscallReturn dupFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target dup() handler.
SyscallReturn readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getpidPseudo() handler.
SyscallReturn mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target mremap() handler.
int numContexts()
Definition: system.hh:208
SyscallReturn tgkillFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:205
const Addr PageBytes
Definition: isa_traits.hh:52
PageTableBase * pTable
Definition: process.hh:178
Ancillary State Registers.
Definition: miscregs.hh:45
SyscallReturn fstatat64Func(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target fstatat64() handler.
std::string fullPath(const std::string &filename)
Definition: process.cc:646
SyscallReturn unlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, int index)
Target unlink() handler.
void convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY=false)
SyscallReturn futexFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps...
struct stat64 hst_stat64
SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:57
uint64_t IntReg
Definition: registers.hh:47
Tick s
second
Definition: core.cc:63
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:63
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:83
Addr memSize() const
Amount of physical memory that exists.
Definition: system.cc:359
SyscallReturn fchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target fchown() handler.
SyscallReturn statFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target stat() handler.
const int NumIntArchRegs
Definition: registers.hh:91
SyscallReturn fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target fchmod() handler.
int size()
Definition: pagetable.hh:146
SyscallReturn getcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getcwd() handler.
Declarations of a non-full system Page Table.
SyscallReturn truncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target truncate64() handler.
SyscallReturn openatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target openat() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, bool pseudoPipe)
Internal pipe() handler.
SyscallReturn stat64Func(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target stat64() handler.
SyscallReturn brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target brk() handler: set brk address.
virtual bool loadAllSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=maxAddr)=0
ObjectFile * createObjectFile(const string &fname, bool raw)
Definition: object_file.cc:157
SyscallReturn exitGroupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target exit_group() handler: terminate simulation. (exit all threads)
GenericISA::SimplePCState< MachInst > PCState
Definition: types.hh:43
SyscallReturn fcntlFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target fcntl() handler.
const int NWindows
Definition: sparc_traits.hh:43
virtual int contextId() const =0
SyscallReturn pipeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target pipe() handler.
SyscallReturn readlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, int index=0)
Target readlink() handler.
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:87
SyscallReturn openFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target open() handler.
SyscallReturn getrusageFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getrusage() function.
SyscallReturn munmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target munmap() handler.
uint64_t gid()
Definition: process.hh:85
SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
void copyRegs(ThreadContext *src, ThreadContext *dest)
Definition: utility.cc:65
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Tick ns
nanosecond
Definition: core.cc:66
virtual void clearArchRegs()=0
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
IntReg pc
Definition: remote_gdb.hh:91
Do not set return registers according to executor return value.
Definition: syscall_desc.hh:81
SyscallReturn lstatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target lstat() handler.
SyscallReturn dup2Func(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target dup2() handler.
uint8_t length
Definition: inet.hh:334
void copyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, hst_stat *host, bool fakeTTY=false)
Holds file descriptors needed to simulate devices opened with pseudo files (commonly with calls to io...
Definition: fd_entry.hh:184
virtual void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value)=0
SyscallReturn getgidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getgid() handler.
SyscallReturn statfsFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target statfs() handler.
SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getuidPseudo() handler.
Bitfield< 5 > t
Definition: miscregs.hh:1382
Bitfield< 4 > op
Definition: types.hh:80
This class represents the return value from an emulated system call, including any errno setting...
uint64_t tgid()
Definition: process.hh:90
void convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY=false)
void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *new_p, TheISA::IntReg flags)
Definition: process.cc:160
virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val)=0
SyscallReturn getppidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getppid() handler.
Bitfield< 0 > p
const RegIndex SyscallSuccessReg
Definition: registers.hh:89
SyscallReturn fallocateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
virtual Addr mmap(Process *p, ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, int offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
Definition: emul_driver.hh:96
struct stat hst_stat
virtual TheISA::TLB * getITBPtr()=0
void setFlags(int flags)
uint64_t egid()
Definition: process.hh:86
SyscallReturn setTidAddressFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target set_tid_address() handler.
SyscallReturn fstat64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target fstat64() handler.
virtual void writeBlob(Addr addr, const uint8_t *p, int size) const
Write size bytes from p to address.
std::shared_ptr< FDArray > fds
Definition: process.hh:203

Generated on Fri Jun 9 2017 13:03:51 for gem5 by doxygen 1.8.6