gem5 v23.0.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
syscall_emul.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2013, 2015, 2019-2021 Arm Limited
3 * Copyright (c) 2015 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2003-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#ifndef __SIM_SYSCALL_EMUL_HH__
43#define __SIM_SYSCALL_EMUL_HH__
44
45#if (defined(__APPLE__) || defined(__OpenBSD__) || \
46 defined(__FreeBSD__) || defined(__CYGWIN__) || \
47 defined(__NetBSD__))
48#define NO_STAT64 1
49#else
50#define NO_STAT64 0
51#endif
52
58
59#if defined(__linux__)
60#include <sched.h>
61#include <sys/eventfd.h>
62#include <sys/statfs.h>
63
64#else
65#include <sys/mount.h>
66
67#endif
68
69#ifdef __CYGWIN32__
70#include <sys/fcntl.h>
71
72#endif
73#include <fcntl.h>
74#include <net/if.h>
75#include <poll.h>
76#include <sys/ioctl.h>
77#include <sys/mman.h>
78#include <sys/socket.h>
79#include <sys/stat.h>
80#include <sys/time.h>
81#include <sys/types.h>
82#include <sys/uio.h>
83#include <unistd.h>
84
85#include <cerrno>
86#include <memory>
87#include <string>
88
89#include "arch/generic/tlb.hh"
90#include "base/intmath.hh"
92#include "base/logging.hh"
93#include "base/random.hh"
94#include "base/trace.hh"
95#include "base/types.hh"
96#include "cpu/base.hh"
97#include "cpu/thread_context.hh"
98#include "kern/linux/linux.hh"
99#include "mem/page_table.hh"
101#include "params/Process.hh"
102#include "sim/emul_driver.hh"
103#include "sim/futex_map.hh"
104#include "sim/guest_abi.hh"
105#include "sim/process.hh"
106#include "sim/proxy_ptr.hh"
108#include "sim/syscall_desc.hh"
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
118namespace 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
129void warnUnsupportedOS(std::string syscall_name);
130
132SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);
133
138SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
140SyscallReturn
141ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc);
142
144SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status);
145
147SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status);
148
150SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc,
151 uint64_t tidPtr);
152
154SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc);
155
157SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
158
160SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
161
163SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc,
164 int tgt_fd, uint64_t offs, int whence);
165
167SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc,
168 int tgt_fd, uint64_t offset_high,
169 uint32_t offset_low, VPtr<> result_ptr, int whence);
170
172SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
173 int tgt_fd, int how);
174
176SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc,
177 VPtr<> buf_ptr, int name_len);
178
180SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc,
181 VPtr<> buf_ptr, unsigned long size);
182
184SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
185 VPtr<> pathname);
186SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc,
187 std::string path);
188
190SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc,
191 VPtr<> pathname, VPtr<> new_pathname);
192
194SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
195 VPtr<> pathname, VPtr<> new_pathname);
196
198SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
199 VPtr<> pathname, mode_t mode);
200SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
201 std::string path, mode_t mode);
202
204SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc,
205 VPtr<> pathname, mode_t mode, dev_t dev);
206SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc,
207 std::string path, mode_t mode, dev_t dev);
208
210SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
211
212// Target rmdir() handler.
213SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc,
214 VPtr<> pathname);
215SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc,
216 std::string path);
217
219SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc,
220 VPtr<> oldpath, VPtr<> newpath);
221SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc,
222 std::string oldpath, std::string newpath);
223
225SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc,
226 VPtr<> pathname, int64_t length);
227
229SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc,
230 int tgt_fd, int64_t length);
231
233SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc);
234
236SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc);
237
239SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc,
240 VPtr<> pathname, uint32_t owner, uint32_t group);
241SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc,
242 std::string path, uint32_t owner, uint32_t group);
243
245SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
246
248SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
249 int pid, int pgid);
250
252SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc,
253 int tgt_fd, uint32_t owner, uint32_t group);
254
256SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc,
257 int tgt_fd);
258
260SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc,
261 int old_tgt_fd, int new_tgt_fd);
262
264SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
265 int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs);
266
268SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
269 int tgt_fd, int cmd);
270
272SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
273
275SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc,
276 VPtr<> tgt_addr, int flags);
277
279SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc);
280
281// Target getpeername() handler.
282SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc,
283 int tgt_fd, VPtr<> sockAddrPtr,
284 VPtr<> addrlenPtr);
285
286// Target bind() handler.
287SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc,
288 int tgt_fd, VPtr<> buf_ptr, int addrlen);
289
290// Target listen() handler.
291SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc,
292 int tgt_fd, int backlog);
293
294// Target connect() handler.
295SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc,
296 int tgt_fd, VPtr<> buf_ptr, int addrlen);
297
298#if defined(SYS_getdents)
299// Target getdents() handler.
300SyscallReturn 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.
306SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
307 int tgt_fd, VPtr<> buf_ptr, unsigned count);
308#endif
309
310// Target recvmsg() handler.
311SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
312 int tgt_fd, VPtr<> msgPtr, int flags);
313
314// Target sendmsg() handler.
315SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
316 int tgt_fd, VPtr<> msgPtr, int flags);
317
318// Target getuid() handler.
319SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc);
320
322SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc);
323
325SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc);
326
328SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
329
331SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc);
332
334SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc,
335 VPtr<> pathname, mode_t mode);
336SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc,
337 std::string path, mode_t mode);
338
339// Target getsockopt() handler.
340SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
341 int tgt_fd, int level, int optname,
342 VPtr<> valPtr, VPtr<> lenPtr);
343
344// Target setsockopt() handler.
345SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
346 int tgt_fd, int level, int optname,
347 VPtr<> valPtr, socklen_t len);
348
349SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
350 VPtr<uint32_t> cpu, VPtr<uint32_t> node,
351 VPtr<uint32_t> tcache);
352
353// Target getsockname() handler.
354SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc,
355 int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
356
357template <class OS>
358SyscallReturn
359atSyscallPath(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
382template <class OS>
383SyscallReturn
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
515SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
516
517
521const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
522
525template <class T1, class T2>
526void
527getElapsedTimeMicro(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
538template <class T1, class T2>
539void
540getElapsedTimeNano(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
569template <typename OS, typename TgtStatPtr, typename HostStatPtr>
570void
571copyOutStatBuf(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
618template <typename OS, typename TgtStatPtr, typename HostStatPtr>
619void
620copyOutStat64Buf(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
640template <class OS, typename TgtStatPtr, typename HostStatPtr>
641void
642copyOutStatfsBuf(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
684template <class OS>
685SyscallReturn
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
759template <class OS>
760SyscallReturn
762 int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
763{
764 auto p = tc->getProcessPtr();
765
770 std::string path;
771 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
772 return -EFAULT;
773
774#ifdef __CYGWIN32__
775 int host_flags = O_BINARY;
776#else
777 int host_flags = 0;
778#endif
783 for (const auto &p: OS::openFlagTable) {
784 if (tgt_flags & p.first) {
785 tgt_flags &= ~p.first;
786 host_flags |= p.second;
787 }
788 }
789 warn_if(tgt_flags, "%s: cannot decode flags %#x", desc->name(), tgt_flags);
790
791#ifdef __CYGWIN32__
792 host_flags |= O_BINARY;
793#endif
794
807 std::string redir_path = path;
808 std::string abs_path = path;
809 if (tgt_dirfd == OS::TGT_AT_FDCWD) {
810 abs_path = p->absolutePath(path, true);
811 redir_path = p->checkPathRedirect(path);
812 } else if (!startswith(path, "/")) {
813 std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
814 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
815 if (!ffdp)
816 return -EBADF;
817 abs_path = ffdp->getFileName() + path;
818 redir_path = p->checkPathRedirect(abs_path);
819 }
820
827 if (startswith(abs_path, "/dev/")) {
828 std::string filename = abs_path.substr(strlen("/dev/"));
829 EmulatedDriver *drv = p->findDriver(filename);
830 if (drv) {
831 DPRINTF_SYSCALL(Verbose, "%s: passing call to "
832 "driver open with path[%s]\n",
833 desc->name(), abs_path.c_str());
834 return drv->open(tc, mode, host_flags);
835 }
840 }
841
866 int sim_fd = -1;
867 std::string used_path;
868 std::vector<std::string> special_paths =
869 { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
870 "/proc/self/maps", "/dev/urandom",
871 "/sys/devices/system/cpu/online" };
872 for (auto entry : special_paths) {
873 if (startswith(path, entry)) {
874 sim_fd = OS::openSpecialFile(abs_path, p, tc);
875 used_path = abs_path;
876 }
877 }
878 if (sim_fd == -1) {
879 sim_fd = open(redir_path.c_str(), host_flags, mode);
880 used_path = redir_path;
881 }
882 if (sim_fd == -1) {
883 int local = -errno;
884 DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
885 "(inferred from:%s)\n", desc->name(),
886 used_path.c_str(), path.c_str());
887 return local;
888 }
889
898 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
899 // Record the file mode for checkpoint restoring
900 ffdp->setFileMode(mode);
901 int tgt_fd = p->fds->allocFD(ffdp);
902 DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
903 "(inferred from:%s)\n", desc->name(),
904 sim_fd, tgt_fd, used_path.c_str(), path.c_str());
905 return tgt_fd;
906}
907
909template <class OS>
910SyscallReturn
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
919template <class OS>
920SyscallReturn
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
941template <class OS>
942SyscallReturn
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
959template <class OS>
960SyscallReturn
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
1025template <class OS>
1026SyscallReturn
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
1036template <class OS>
1037SyscallReturn
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
1064template <class OS>
1065SyscallReturn
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
1083template <class OS>
1084SyscallReturn
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
1101template <class OS>
1102SyscallReturn
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
1119template <class OS>
1120SyscallReturn
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
1134template <class OS>
1135SyscallReturn
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
1166template <class OS>
1167SyscallReturn
1168chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
1169{
1170 return fchmodatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, mode);
1171}
1172
1173template <class OS>
1174SyscallReturn
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
1247template <class OS>
1248SyscallReturn
1249fchmodFunc(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
1266template <class OS>
1267SyscallReturn
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
1349template <class OS>
1350SyscallReturn
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
1375template <class OS>
1376SyscallReturn
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
1414template <class OS>
1415SyscallReturn
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
1451template <class OS>
1452SyscallReturn
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
1460template <class OS>
1461SyscallReturn
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
1490template <class OS>
1491SyscallReturn
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
1516template <class OS>
1517SyscallReturn
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
1547template <class OS>
1548SyscallReturn
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
1573template <class OS>
1574SyscallReturn
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
1602template <class OS>
1603SyscallReturn
1605 VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1606{
1607 DPRINTF(SyscallVerbose, "Doing clone. pid: %#llx, ctid: %#llx, tls: %#llx"
1608 " flags: %#llx, stack: %#llx\n",
1609 ptidPtr.addr(), ctidPtr.addr(), tlsPtr.addr(), flags, newStack);
1610 auto p = tc->getProcessPtr();
1611
1612 if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1613 ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1614 ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1615 ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1616 ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1617 ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1618 return -EINVAL;
1619
1620 ThreadContext *ctc;
1621 if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1622 DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1623 "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1624 return -EAGAIN;
1625 }
1626
1633 ProcessParams *pp = new ProcessParams();
1634 pp->executable.assign(*(new std::string(p->progName())));
1635 pp->cmd.push_back(*(new std::string(p->progName())));
1636 pp->system = p->system;
1637 pp->cwd.assign(p->tgtCwd);
1638 pp->input.assign("stdin");
1639 pp->output.assign("stdout");
1640 pp->errout.assign("stderr");
1641 pp->uid = p->uid();
1642 pp->euid = p->euid();
1643 pp->gid = p->gid();
1644 pp->egid = p->egid();
1645 pp->release = p->release;
1646
1647 /* Find the first free PID that's less than the maximum */
1648 std::set<int> const& pids = p->system->PIDs;
1649 int temp_pid = *pids.begin();
1650 do {
1651 temp_pid++;
1652 } while (pids.find(temp_pid) != pids.end());
1653 if (temp_pid >= System::maxPID)
1654 fatal("temp_pid is too large: %d", temp_pid);
1655
1656 pp->pid = temp_pid;
1657 pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1658 pp->useArchPT = p->useArchPT;
1659 pp->kvmInSE = p->kvmInSE;
1660 Process *cp = pp->create();
1661 // TODO: there is no way to know when the Process SimObject is done with
1662 // the params pointer. Both the params pointer (pp) and the process
1663 // pointer (cp) are normally managed in python and are never cleaned up.
1664
1665 Process *owner = ctc->getProcessPtr();
1666 ctc->setProcessPtr(cp);
1667 cp->assignThreadContext(ctc->contextId());
1668 owner->revokeThreadContext(ctc->contextId());
1669
1670 if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1671 BufferArg ptidBuf(ptidPtr, sizeof(long));
1672 long *ptid = (long *)ptidBuf.bufferPtr();
1673 *ptid = cp->pid();
1674 ptidBuf.copyOut(SETranslatingPortProxy(tc));
1675 }
1676
1677 if (flags & OS::TGT_CLONE_THREAD) {
1678 cp->pTable->initState();
1679 cp->pTable->shared = true;
1680 cp->useForClone = true;
1681 }
1682
1683 ctc->setUseForClone(true);
1684 cp->initState();
1685 p->clone(tc, ctc, cp, flags);
1686
1687 if (flags & OS::TGT_CLONE_THREAD) {
1688 delete cp->sigchld;
1689 cp->sigchld = p->sigchld;
1690 } else if (flags & OS::TGT_SIGCHLD) {
1691 *cp->sigchld = true;
1692 }
1693
1694 if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1695 BufferArg ctidBuf(ctidPtr, sizeof(long));
1696 long *ctid = (long *)ctidBuf.bufferPtr();
1697 *ctid = cp->pid();
1698 ctidBuf.copyOut(SETranslatingPortProxy(ctc));
1699 }
1700
1701 if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1702 cp->childClearTID = (uint64_t)ctidPtr;
1703
1704 ctc->clearArchRegs();
1705
1706 OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1707
1708 desc->returnInto(ctc, 0);
1709
1710 ctc->activate();
1711
1712 if (flags & OS::TGT_CLONE_VFORK) {
1713 tc->suspend();
1714 }
1715
1716 return cp->pid();
1717}
1718
1719template <class OS>
1720SyscallReturn
1723{
1724 VPtr<uint64_t> ptidPtr((Addr)cl_args->parent_tid, tc);
1725 VPtr<uint64_t> ctidPtr((Addr)cl_args->child_tid, tc);
1726 VPtr<uint64_t> tlsPtr((Addr)cl_args->tls, tc);
1727 // Clone3 gives the stack as the *lowest* address, but clone/__clone2
1728 // expects the stack parameter to be the actual stack pointer
1729 uint64_t new_stack = cl_args->stack + cl_args->stack_size;
1730 uint64_t flags = cl_args->flags;
1731
1732 return doClone<OS>(desc, tc, flags, new_stack, ptidPtr, ctidPtr, tlsPtr);
1733}
1734
1735template <class OS>
1736SyscallReturn
1738 VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
1739{
1740 return doClone<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1741}
1742
1743template <class OS>
1744SyscallReturn
1746 RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr,
1747 VPtr<> ctidPtr)
1748{
1749 return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1750}
1751
1753template <class OS>
1754SyscallReturn
1756 int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1757{
1758 auto p = tc->getProcessPtr();
1759
1760 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1761 if (!ffdp)
1762 return -EBADF;
1763 int sim_fd = ffdp->getSimFD();
1764
1765 struct statfs hostBuf;
1766 int result = fstatfs(sim_fd, &hostBuf);
1767
1768 if (result < 0)
1769 return -errno;
1770
1771 copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1772
1773 return 0;
1774}
1775
1777template <class OS>
1778SyscallReturn
1780 int tgt_fd, uint64_t tiov_base,
1781 typename OS::size_t count)
1782{
1783 auto p = tc->getProcessPtr();
1784
1785 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1786 if (!ffdp)
1787 return -EBADF;
1788 int sim_fd = ffdp->getSimFD();
1789
1790 SETranslatingPortProxy prox(tc);
1791 typename OS::tgt_iovec tiov[count];
1792 struct iovec hiov[count];
1793 for (typename OS::size_t i = 0; i < count; ++i) {
1794 prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1795 &tiov[i], sizeof(typename OS::tgt_iovec));
1796 hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1797 hiov[i].iov_base = new char [hiov[i].iov_len];
1798 }
1799
1800 int result = readv(sim_fd, hiov, count);
1801 int local_errno = errno;
1802
1803 for (typename OS::size_t i = 0; i < count; ++i) {
1804 if (result != -1) {
1805 prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1806 hiov[i].iov_base, hiov[i].iov_len);
1807 }
1808 delete [] (char *)hiov[i].iov_base;
1809 }
1810
1811 return (result == -1) ? -local_errno : result;
1812}
1813
1815template <class OS>
1816SyscallReturn
1818 int tgt_fd, uint64_t tiov_base,
1819 typename OS::size_t count)
1820{
1821 auto p = tc->getProcessPtr();
1822
1823 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1824 if (!hbfdp)
1825 return -EBADF;
1826 int sim_fd = hbfdp->getSimFD();
1827
1828 SETranslatingPortProxy prox(tc);
1829 struct iovec hiov[count];
1830 for (typename OS::size_t i = 0; i < count; ++i) {
1831 typename OS::tgt_iovec tiov;
1832
1833 prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1834 &tiov, sizeof(typename OS::tgt_iovec));
1835 hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1836 hiov[i].iov_base = new char [hiov[i].iov_len];
1837 prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1838 hiov[i].iov_len);
1839 }
1840
1841 int result = writev(sim_fd, hiov, count);
1842
1843 for (typename OS::size_t i = 0; i < count; ++i)
1844 delete [] (char *)hiov[i].iov_base;
1845
1846 return (result == -1) ? -errno : result;
1847}
1848
1850template <class OS>
1851SyscallReturn
1853 VPtr<> start, typename OS::size_t length, int prot,
1854 int tgt_flags, int tgt_fd, typename OS::off_t offset)
1855{
1856 auto p = tc->getProcessPtr();
1857 Addr page_bytes = p->pTable->pageSize();
1858
1859 if (start & (page_bytes - 1) ||
1860 offset & (page_bytes - 1) ||
1861 (tgt_flags & OS::TGT_MAP_PRIVATE &&
1862 tgt_flags & OS::TGT_MAP_SHARED) ||
1863 (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1864 !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1865 !length) {
1866 return -EINVAL;
1867 }
1868
1869 if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1870 // With shared mmaps, there are two cases to consider:
1871 // 1) anonymous: writes should modify the mapping and this should be
1872 // visible to observers who share the mapping. Currently, it's
1873 // difficult to update the shared mapping because there's no
1874 // structure which maintains information about the which virtual
1875 // memory areas are shared. If that structure existed, it would be
1876 // possible to make the translations point to the same frames.
1877 // 2) file-backed: writes should modify the mapping and the file
1878 // which is backed by the mapping. The shared mapping problem is the
1879 // same as what was mentioned about the anonymous mappings. For
1880 // file-backed mappings, the writes to the file are difficult
1881 // because it requires syncing what the mapping holds with the file
1882 // that resides on the host system. So, any write on a real system
1883 // would cause the change to be propagated to the file mapping at
1884 // some point in the future (the inode is tracked along with the
1885 // mapping). This isn't guaranteed to always happen, but it usually
1886 // works well enough. The guarantee is provided by the msync system
1887 // call. We could force the change through with shared mappings with
1888 // a call to msync, but that again would require more information
1889 // than we currently maintain.
1890 warn_once("mmap: writing to shared mmap region is currently "
1891 "unsupported. The write succeeds on the target, but it "
1892 "will not be propagated to the host or shared mappings");
1893 }
1894
1895 length = roundUp(length, page_bytes);
1896
1897 int sim_fd = -1;
1898 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1899 std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1900
1901 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1902 if (dfdp) {
1903 EmulatedDriver *emul_driver = dfdp->getDriver();
1904 return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1905 tgt_fd, offset);
1906 }
1907
1908 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1909 if (!ffdp)
1910 return -EBADF;
1911 sim_fd = ffdp->getSimFD();
1912
1921 if (p->interpImage.contains(tc->pcState().instAddr())) {
1922 std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1923 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1924 auto *lib = loader::createObjectFile(p->checkPathRedirect(
1925 ffdp->getFileName()));
1926 DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1927 ffdp->getFileName());
1928
1929 if (lib) {
1930 Addr offset = lib->buildImage().minAddr() + start;
1931 loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1932 }
1933 }
1934 }
1935
1939 if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1947 if (!(start && p->memState->isUnmapped(start, length))) {
1951 start = p->memState->extendMmap(length);
1952 }
1953 }
1954
1955 DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1956 start, start + length - 1);
1957
1963 if (tgt_flags & OS::TGT_MAP_FIXED) {
1968 p->memState->unmapRegion(start, length);
1969 }
1970
1974 std::string region_name;
1975 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1976 region_name = "anon";
1977 } else {
1978 std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1979 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1980 region_name = ffdp->getFileName();
1981 }
1982
1987 p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1988
1989 return (Addr)start;
1990}
1991
1992template <class OS>
1993SyscallReturn
1995 int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
1996{
1997 auto p = tc->getProcessPtr();
1998
1999 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2000 if (!ffdp)
2001 return -EBADF;
2002 int sim_fd = ffdp->getSimFD();
2003
2004 BufferArg bufArg(bufPtr, nbytes);
2005
2006 int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2007
2008 bufArg.copyOut(SETranslatingPortProxy(tc));
2009
2010 return (bytes_read == -1) ? -errno : bytes_read;
2011}
2012
2013template <class OS>
2014SyscallReturn
2016 int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
2017{
2018 auto p = tc->getProcessPtr();
2019
2020 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
2021 if (!ffdp)
2022 return -EBADF;
2023 int sim_fd = ffdp->getSimFD();
2024
2025 BufferArg bufArg(bufPtr, nbytes);
2026 bufArg.copyIn(SETranslatingPortProxy(tc));
2027
2028 int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
2029
2030 return (bytes_written == -1) ? -errno : bytes_written;
2031}
2032
2034template <class OS>
2035SyscallReturn
2037 VPtr<> start, typename OS::size_t length, int prot,
2038 int tgt_flags, int tgt_fd, typename OS::off_t offset)
2039{
2040 auto page_size = tc->getProcessPtr()->pTable->pageSize();
2041 return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
2042 tgt_fd, offset * page_size);
2043}
2044
2046template <class OS>
2047SyscallReturn
2049 unsigned resource, VPtr<typename OS::rlimit> rlp)
2050{
2051 const ByteOrder bo = OS::byteOrder;
2052 switch (resource) {
2053 case OS::TGT_RLIMIT_STACK:
2054 // max stack size in bytes: make up a number (8MiB for now)
2055 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2056 rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2057 rlp->rlim_max = htog(rlp->rlim_max, bo);
2058 break;
2059
2060 case OS::TGT_RLIMIT_DATA:
2061 // max data segment size in bytes: make up a number
2062 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2063 rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2064 rlp->rlim_max = htog(rlp->rlim_max, bo);
2065 break;
2066
2067 case OS::TGT_RLIMIT_NPROC:
2068 rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
2069 rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2070 rlp->rlim_max = htog(rlp->rlim_max, bo);
2071 break;
2072
2073 default:
2074 warn("getrlimit: unimplemented resource %d", resource);
2075 return -EINVAL;
2076 break;
2077 }
2078
2079 return 0;
2080}
2081
2082template <class OS>
2083SyscallReturn
2085 int pid, int resource, VPtr<> n, VPtr<typename OS::rlimit> rlp)
2086{
2087 if (pid != 0) {
2088 warn("prlimit: ignoring rlimits for nonzero pid");
2089 return -EPERM;
2090 }
2091 if (n)
2092 warn("prlimit: ignoring new rlimit");
2093 if (rlp) {
2094 const ByteOrder bo = OS::byteOrder;
2095 switch (resource) {
2096 case OS::TGT_RLIMIT_STACK:
2097 // max stack size in bytes: make up a number (8MiB for now)
2098 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2099 rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2100 rlp->rlim_max = htog(rlp->rlim_max, bo);
2101 break;
2102 case OS::TGT_RLIMIT_DATA:
2103 // max data segment size in bytes: make up a number
2104 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2105 rlp->rlim_cur = htog(rlp->rlim_cur, bo);
2106 rlp->rlim_max = htog(rlp->rlim_max, bo);
2107 break;
2108 default:
2109 warn("prlimit: unimplemented resource %d", resource);
2110 return -EINVAL;
2111 break;
2112 }
2113 }
2114 return 0;
2115}
2116
2118template <class OS>
2119SyscallReturn
2121 int clk_id, VPtr<typename OS::timespec> tp)
2122{
2123 getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
2124 tp->tv_sec += seconds_since_epoch;
2125 tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2126 tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
2127
2128 return 0;
2129}
2130
2132template <class OS>
2133SyscallReturn
2136{
2137 // Set resolution at ns, which is what clock_gettime() returns
2138 tp->tv_sec = 0;
2139 tp->tv_nsec = 1;
2140
2141 return 0;
2142}
2143
2145template <class OS>
2146SyscallReturn
2149{
2150 getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
2151 tp->tv_sec += seconds_since_epoch;
2152 tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
2153 tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
2154
2155 return 0;
2156}
2157
2159template <class OS>
2160SyscallReturn
2162 int dirfd, VPtr<> pathname, VPtr<typename OS::timeval [2]> tp)
2163{
2164 std::string path;
2165 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
2166 return -EFAULT;
2167
2168 // Modifying path from the directory descriptor
2169 if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
2170 return res;
2171 }
2172
2173 struct timeval hostTimeval[2];
2174 for (int i = 0; i < 2; ++i) {
2175 hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
2176 hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
2177 }
2178
2179 // Adjust path for cwd and redirection
2180 auto process = tc->getProcessPtr();
2181 path = process->checkPathRedirect(path);
2182
2183 int result = utimes(path.c_str(), hostTimeval);
2184
2185 if (result < 0)
2186 return -errno;
2187
2188 return 0;
2189}
2190
2192template <class OS>
2193SyscallReturn
2195 VPtr<typename OS::timeval [2]> tp)
2196{
2197 return futimesatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tp);
2198}
2199
2200template <class OS>
2201SyscallReturn
2203 VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
2204{
2205 auto p = tc->getProcessPtr();
2206
2207 std::string path;
2208 SETranslatingPortProxy mem_proxy(tc);
2209 if (!mem_proxy.tryReadString(path, pathname))
2210 return -EFAULT;
2211
2212 if (access(path.c_str(), F_OK) == -1)
2213 return -EACCES;
2214
2215 auto read_in = [](std::vector<std::string> &vect,
2216 PortProxy &mem_proxy, VPtr<> mem_loc)
2217 {
2218 for (int inc = 0; ; inc++) {
2219 BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
2220 b.copyIn(mem_proxy);
2221
2222 if (!*(Addr*)b.bufferPtr())
2223 break;
2224
2225 vect.push_back(std::string());
2226 mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
2227 }
2228 };
2229
2234 if (!p->vforkContexts.empty()) {
2235 ThreadContext *vtc = p->system->threads[p->vforkContexts.front()];
2236 assert(vtc->status() == ThreadContext::Suspended);
2237 vtc->activate();
2238 }
2239
2246 ProcessParams *pp = new ProcessParams();
2247 pp->executable = path;
2248 read_in(pp->cmd, mem_proxy, argv_mem_loc);
2249 read_in(pp->env, mem_proxy, envp_mem_loc);
2250 pp->uid = p->uid();
2251 pp->egid = p->egid();
2252 pp->euid = p->euid();
2253 pp->gid = p->gid();
2254 pp->ppid = p->ppid();
2255 pp->pid = p->pid();
2256 pp->input.assign("cin");
2257 pp->output.assign("cout");
2258 pp->errout.assign("cerr");
2259 pp->cwd.assign(p->tgtCwd);
2260 pp->system = p->system;
2261 pp->release = p->release;
2270 p->system->PIDs.erase(p->pid());
2271 Process *new_p = pp->create();
2272 // TODO: there is no way to know when the Process SimObject is done with
2273 // the params pointer. Both the params pointer (pp) and the process
2274 // pointer (p) are normally managed in python and are never cleaned up.
2275
2280 new_p->fds = p->fds;
2281 for (int i = 0; i < new_p->fds->getSize(); i++) {
2282 std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2283 if (fdep && fdep->getCOE())
2284 new_p->fds->closeFDEntry(i);
2285 }
2286
2287 *new_p->sigchld = true;
2288
2289 tc->clearArchRegs();
2290 tc->setProcessPtr(new_p);
2291 new_p->assignThreadContext(tc->contextId());
2292 new_p->init();
2293 new_p->initState();
2294 tc->activate();
2295
2296 return SyscallReturn();
2297}
2298
2300template <class OS>
2301SyscallReturn
2303 int who /* THREAD, SELF, or CHILDREN */,
2305{
2306 rup->ru_utime.tv_sec = 0;
2307 rup->ru_utime.tv_usec = 0;
2308 rup->ru_stime.tv_sec = 0;
2309 rup->ru_stime.tv_usec = 0;
2310 rup->ru_maxrss = 0;
2311 rup->ru_ixrss = 0;
2312 rup->ru_idrss = 0;
2313 rup->ru_isrss = 0;
2314 rup->ru_minflt = 0;
2315 rup->ru_majflt = 0;
2316 rup->ru_nswap = 0;
2317 rup->ru_inblock = 0;
2318 rup->ru_oublock = 0;
2319 rup->ru_msgsnd = 0;
2320 rup->ru_msgrcv = 0;
2321 rup->ru_nsignals = 0;
2322 rup->ru_nvcsw = 0;
2323 rup->ru_nivcsw = 0;
2324
2325 switch (who) {
2326 case OS::TGT_RUSAGE_SELF:
2327 getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2328 rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2329 rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2330 break;
2331
2332 case OS::TGT_RUSAGE_CHILDREN:
2333 // do nothing. We have no child processes, so they take no time.
2334 break;
2335
2336 default:
2337 // don't really handle THREAD or CHILDREN, but just warn and
2338 // plow ahead
2339 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2340 who);
2341 }
2342
2343 return 0;
2344}
2345
2347template <class OS>
2348SyscallReturn
2350{
2351 // Fill in the time structure (in clocks)
2352 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / sim_clock::as_int::s;
2353 bufp->tms_utime = clocks;
2354 bufp->tms_stime = 0;
2355 bufp->tms_cutime = 0;
2356 bufp->tms_cstime = 0;
2357
2358 // Convert to host endianness
2359 bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2360
2361 // Return clock ticks since system boot
2362 return clocks;
2363}
2364
2366template <class OS>
2367SyscallReturn
2369{
2370 typename OS::time_t sec, usec;
2371 getElapsedTimeMicro(sec, usec);
2372 sec += seconds_since_epoch;
2373
2375 if (taddr != 0) {
2376 typename OS::time_t t = sec;
2377 t = htog(t, OS::byteOrder);
2378 p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2379 }
2380 return sec;
2381}
2382
2383template <class OS>
2384SyscallReturn
2385tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2386{
2402 System *sys = tc->getSystemPtr();
2403 Process *tgt_proc = nullptr;
2404 for (auto *tc: sys->threads) {
2405 Process *temp = tc->getProcessPtr();
2406 if (temp->pid() == tid) {
2407 tgt_proc = temp;
2408 break;
2409 }
2410 }
2411
2412 if (sig != 0 || sig != OS::TGT_SIGABRT)
2413 return -EINVAL;
2414
2415 if (tgt_proc == nullptr)
2416 return -ESRCH;
2417
2418 if (tgid != -1 && tgt_proc->tgid() != tgid)
2419 return -ESRCH;
2420
2421 if (sig == OS::TGT_SIGABRT)
2422 exitGroupFunc(desc, tc, 0);
2423
2424 return 0;
2425}
2426
2427template <class OS>
2428SyscallReturn
2430 int domain, int type, int prot)
2431{
2432 auto p = tc->getProcessPtr();
2433
2434 int sim_fd = socket(domain, type, prot);
2435 if (sim_fd == -1)
2436 return -errno;
2437
2438 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2439 int tgt_fd = p->fds->allocFD(sfdp);
2440
2441 return tgt_fd;
2442}
2443
2444template <class OS>
2445SyscallReturn
2447 int domain, int type, int prot, VPtr<> svPtr)
2448{
2449 auto p = tc->getProcessPtr();
2450
2451 BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2452 int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2453 if (status == -1)
2454 return -errno;
2455
2456 int *fds = (int *)svBuf.bufferPtr();
2457
2458 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2459 fds[0] = p->fds->allocFD(sfdp1);
2460 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2461 fds[1] = p->fds->allocFD(sfdp2);
2463
2464 return status;
2465}
2466
2467template <class OS>
2468SyscallReturn
2474{
2475 int retval;
2476
2477 auto p = tc->getProcessPtr();
2478
2484 fd_set readfds_h;
2485 FD_ZERO(&readfds_h);
2486 fd_set writefds_h;
2487 FD_ZERO(&writefds_h);
2488 fd_set errorfds_h;
2489 FD_ZERO(&errorfds_h);
2490
2500 int nfds_h = 0;
2501 std::map<int, int> trans_map;
2502 auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2503 fd_set *hst_set_entry,
2504 int iter) -> bool
2505 {
2511 if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2517 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2518 if (!hbfdp)
2519 return true;
2520 auto sim_fd = hbfdp->getSimFD();
2521
2527 trans_map[sim_fd] = iter;
2528
2534 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2535
2540 FD_SET(sim_fd, hst_set_entry);
2541 }
2542 return false;
2543 };
2544
2545 for (int i = 0; i < nfds; i++) {
2546 if (readfds) {
2547 bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2548 if (ebadf)
2549 return -EBADF;
2550 }
2551 if (writefds) {
2552 bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2553 if (ebadf)
2554 return -EBADF;
2555 }
2556 if (errorfds) {
2557 bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2558 if (ebadf)
2559 return -EBADF;
2560 }
2561 }
2562
2563 if (timeout) {
2571 timeout->tv_sec = 0;
2572 timeout->tv_usec = 0;
2573
2574 retval = select(nfds_h,
2575 readfds ? &readfds_h : nullptr,
2576 writefds ? &writefds_h : nullptr,
2577 errorfds ? &errorfds_h : nullptr,
2578 (timeval *)(typename OS::timeval *)timeout);
2579 } else {
2587 struct timeval tv = { 0, 0 };
2588
2589 retval = select(nfds_h,
2590 readfds ? &readfds_h : nullptr,
2591 readfds ? &writefds_h : nullptr,
2592 readfds ? &errorfds_h : nullptr,
2593 &tv);
2594
2595 if (retval == 0) {
2601 for (auto sig : tc->getSystemPtr()->signalList)
2602 if (sig.receiver == p)
2603 return -EINTR;
2604 return SyscallReturn::retry();
2605 }
2606 }
2607
2608 if (retval == -1)
2609 return -errno;
2610
2611 if (readfds) {
2612 FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2613 }
2614 if (writefds) {
2615 FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2616 }
2617 if (errorfds) {
2618 FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2619 }
2620
2626 for (int i = 0; i < nfds_h; i++) {
2627 if (readfds && FD_ISSET(i, &readfds_h))
2628 FD_SET(trans_map[i],
2629 reinterpret_cast<fd_set *>(
2630 (typename OS::fd_set *)readfds));
2631
2632 if (writefds && FD_ISSET(i, &writefds_h))
2633 FD_SET(trans_map[i],
2634 reinterpret_cast<fd_set *>(
2635 (typename OS::fd_set *)writefds));
2636
2637 if (errorfds && FD_ISSET(i, &errorfds_h))
2638 FD_SET(trans_map[i],
2639 reinterpret_cast<fd_set *>(
2640 (typename OS::fd_set *)errorfds));
2641 }
2642
2643 return retval;
2644}
2645
2646template <class OS>
2647SyscallReturn
2649 int tgt_fd, VPtr<> buf_ptr, int nbytes)
2650{
2651 auto p = tc->getProcessPtr();
2652
2653 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2654 if (!hbfdp)
2655 return -EBADF;
2656 int sim_fd = hbfdp->getSimFD();
2657
2658 struct pollfd pfd;
2659 pfd.fd = sim_fd;
2660 pfd.events = POLLIN | POLLPRI;
2661 if ((poll(&pfd, 1, 0) == 0)
2662 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2663 return SyscallReturn::retry();
2664
2665 BufferArg buf_arg(buf_ptr, nbytes);
2666 int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2667
2668 if (bytes_read > 0)
2669 buf_arg.copyOut(SETranslatingPortProxy(tc));
2670
2671 return (bytes_read == -1) ? -errno : bytes_read;
2672}
2673
2674template <class OS>
2675SyscallReturn
2677 int tgt_fd, VPtr<> buf_ptr, int nbytes)
2678{
2679 auto p = tc->getProcessPtr();
2680
2681 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2682 if (!hbfdp)
2683 return -EBADF;
2684 int sim_fd = hbfdp->getSimFD();
2685
2686 BufferArg buf_arg(buf_ptr, nbytes);
2687 buf_arg.copyIn(SETranslatingPortProxy(tc));
2688
2689 struct pollfd pfd;
2690 pfd.fd = sim_fd;
2691 pfd.events = POLLOUT;
2692
2699 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2700 if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2701 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2702 return SyscallReturn::retry();
2703 }
2704
2705 int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2706
2707 if (bytes_written != -1)
2708 fsync(sim_fd);
2709
2710 return (bytes_written == -1) ? -errno : bytes_written;
2711}
2712
2713template <class OS>
2714SyscallReturn
2716 pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
2717{
2718 auto p = tc->getProcessPtr();
2719
2720 if (rusagePtr)
2721 DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2722 "functionality not supported. Ignoring rusage pointer.\n",
2723 rusagePtr);
2724
2733 System *sysh = tc->getSystemPtr();
2735 for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2736 if (iter->receiver == p) {
2737 if (pid < -1) {
2738 if ((iter->sender->pgid() == -pid)
2739 && (iter->signalValue == OS::TGT_SIGCHLD))
2740 goto success;
2741 } else if (pid == -1) {
2742 if (iter->signalValue == OS::TGT_SIGCHLD)
2743 goto success;
2744 } else if (pid == 0) {
2745 if ((iter->sender->pgid() == p->pgid())
2746 && (iter->signalValue == OS::TGT_SIGCHLD))
2747 goto success;
2748 } else {
2749 if ((iter->sender->pid() == pid)
2750 && (iter->signalValue == OS::TGT_SIGCHLD))
2751 goto success;
2752 }
2753 }
2754 }
2755
2756 return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2757
2758success:
2759 // Set status to EXITED for WIFEXITED evaluations.
2760 const int EXITED = 0;
2761 BufferArg statusBuf(statPtr, sizeof(int));
2762 *(int *)statusBuf.bufferPtr() = EXITED;
2763 statusBuf.copyOut(SETranslatingPortProxy(tc));
2764
2765 // Return the child PID.
2766 pid_t retval = iter->sender->pid();
2767 sysh->signalList.erase(iter);
2768 return retval;
2769}
2770
2771template <class OS>
2772SyscallReturn
2774 int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
2775{
2776 struct sockaddr sa;
2777 socklen_t addrLen;
2778 int host_fd;
2779 auto p = tc->getProcessPtr();
2780
2781 BufferArg *lenBufPtr = nullptr;
2782 BufferArg *addrBufPtr = nullptr;
2783
2784 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2785 if (!sfdp)
2786 return -EBADF;
2787 int sim_fd = sfdp->getSimFD();
2788
2795 struct pollfd pfd;
2796 pfd.fd = sim_fd;
2797 pfd.events = POLLIN | POLLPRI;
2798 if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2799 return SyscallReturn::retry();
2800
2801 if (lenPtr) {
2802 lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2803 lenBufPtr->copyIn(SETranslatingPortProxy(tc));
2804 memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2805 sizeof(socklen_t));
2806 }
2807
2808 if (addrPtr) {
2809 addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2810 addrBufPtr->copyIn(SETranslatingPortProxy(tc));
2811 memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2812 sizeof(struct sockaddr));
2813 }
2814
2815 host_fd = accept(sim_fd, &sa, &addrLen);
2816
2817 if (host_fd == -1)
2818 return -errno;
2819
2820 if (addrPtr) {
2821 memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2822 addrBufPtr->copyOut(SETranslatingPortProxy(tc));
2823 delete(addrBufPtr);
2824 }
2825
2826 if (lenPtr) {
2827 *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2828 lenBufPtr->copyOut(SETranslatingPortProxy(tc));
2829 delete(lenBufPtr);
2830 }
2831
2832 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2833 sfdp->_type, sfdp->_protocol);
2834 return p->fds->allocFD(afdp);
2835}
2836
2838template <class OS>
2839SyscallReturn
2841 unsigned initval, int in_flags)
2842{
2843#if defined(__linux__)
2844 auto p = tc->getProcessPtr();
2845
2846 int sim_fd = eventfd(initval, in_flags);
2847 if (sim_fd == -1)
2848 return -errno;
2849
2850 bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2851
2852 int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2853 flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2854
2855 auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2856 int tgt_fd = p->fds->allocFD(hbfdp);
2857 return tgt_fd;
2858#else
2859 warnUnsupportedOS("eventfd");
2860 return -1;
2861#endif
2862}
2863
2865template <class OS>
2866SyscallReturn
2868 pid_t pid, typename OS::size_t cpusetsize,
2869 VPtr<> cpu_set_mask)
2870{
2871#if defined(__linux__)
2872 if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size()))
2873 return -EINVAL;
2874
2875 SETranslatingPortProxy proxy(tc);
2876 BufferArg maskBuf(cpu_set_mask, cpusetsize);
2877 maskBuf.copyIn(proxy);
2878 for (int i = 0; i < tc->getSystemPtr()->threads.size(); i++) {
2879 CPU_SET(i, (cpu_set_t *)maskBuf.bufferPtr());
2880 }
2881 maskBuf.copyOut(proxy);
2882 return CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size());
2883#else
2884 warnUnsupportedOS("sched_getaffinity");
2885 return -1;
2886#endif
2887}
2888
2889// Target recvfrom() handler.
2890template <class OS>
2891SyscallReturn
2893 int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len,
2894 int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
2895{
2896 auto p = tc->getProcessPtr();
2897
2898 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2899 if (!sfdp)
2900 return -EBADF;
2901 int sim_fd = sfdp->getSimFD();
2902
2903 // Reserve buffer space.
2904 BufferArg buf(buf_ptr, buf_len);
2905
2906 SETranslatingPortProxy proxy(tc);
2907
2908 // Get address length.
2909 socklen_t addr_len = 0;
2910 if (addrlen_ptr != 0) {
2911 // Read address length parameter.
2912 BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2913 addrlen_buf.copyIn(proxy);
2914 addr_len = *((socklen_t *)addrlen_buf.bufferPtr());
2915 }
2916
2917 struct sockaddr sa, *sap = NULL;
2918 if (addr_len != 0) {
2919 BufferArg addr_buf(addr_ptr, addr_len);
2920 addr_buf.copyIn(proxy);
2921 memcpy(&sa, (struct sockaddr *)addr_buf.bufferPtr(),
2922 sizeof(struct sockaddr));
2923 sap = &sa;
2924 }
2925
2926 ssize_t recvd_size = recvfrom(sim_fd,
2927 (void *)buf.bufferPtr(),
2928 buf_len, flags, sap, (socklen_t *)&addr_len);
2929
2930 if (recvd_size == -1)
2931 return -errno;
2932
2933 // Pass the received data out.
2934 buf.copyOut(proxy);
2935
2936 // Copy address to addr_ptr and pass it on.
2937 if (sap != NULL) {
2938 BufferArg addr_buf(addr_ptr, addr_len);
2939 memcpy(addr_buf.bufferPtr(), sap, sizeof(sa));
2940 addr_buf.copyOut(proxy);
2941 }
2942
2943 // Copy len to addrlen_ptr and pass it on.
2944 if (addr_len != 0) {
2945 BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t));
2946 *(socklen_t *)addrlen_buf.bufferPtr() = addr_len;
2947 addrlen_buf.copyOut(proxy);
2948 }
2949
2950 return recvd_size;
2951}
2952
2953// Target sendto() handler.
2954template <typename OS>
2955SyscallReturn
2957 int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags,
2958 VPtr<> addr_ptr, socklen_t addr_len)
2959{
2960 auto p = tc->getProcessPtr();
2961
2962 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2963 if (!sfdp)
2964 return -EBADF;
2965 int sim_fd = sfdp->getSimFD();
2966
2967 // Reserve buffer space.
2968 BufferArg buf(buf_ptr, buf_len);
2970
2971 struct sockaddr sa, *sap = nullptr;
2972 memset(&sa, 0, sizeof(sockaddr));
2973 if (addr_len != 0) {
2974 BufferArg addr_buf(addr_ptr, addr_len);
2975 addr_buf.copyIn(SETranslatingPortProxy(tc));
2976 memcpy(&sa, (sockaddr*)addr_buf.bufferPtr(), addr_len);
2977 sap = &sa;
2978 }
2979
2980 ssize_t sent_size = sendto(sim_fd,
2981 (void *)buf.bufferPtr(),
2982 buf_len, flags, sap, (socklen_t)addr_len);
2983
2984 return (sent_size == -1) ? -errno : sent_size;
2985}
2986
2988template <typename OS>
2989SyscallReturn
2991 typename OS::size_t length)
2992{
2993 // Even if the system is currently not capable of recycling physical
2994 // pages, there is no reason we can't unmap them so that we trigger
2995 // appropriate seg faults when the application mistakenly tries to
2996 // access them again.
2997 auto p = tc->getProcessPtr();
2998
2999 if (p->pTable->pageOffset(start))
3000 return -EINVAL;
3001
3002 length = roundUp(length, p->pTable->pageSize());
3003
3004 p->memState->unmapRegion(start, length);
3005
3006 return 0;
3007}
3008
3009// Target fallocate() handler.
3010template <typename OS>
3011SyscallReturn
3013 int tgt_fd, int mode, typename OS::off_t offset,
3014 typename OS::off_t len)
3015{
3016#if defined(__linux__)
3017 auto p = tc->getProcessPtr();
3018
3019 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3020 if (!ffdp)
3021 return -EBADF;
3022 int sim_fd = ffdp->getSimFD();
3023
3024 int result = fallocate(sim_fd, mode, offset, len);
3025 if (result < 0)
3026 return -errno;
3027 return 0;
3028#else
3029 warnUnsupportedOS("fallocate");
3030 return -1;
3031#endif
3032}
3033
3035template <typename OS>
3036SyscallReturn
3038 typename OS::off_t length)
3039{
3040 std::string path;
3041 auto p = tc->getProcessPtr();
3042
3043 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
3044 return -EFAULT;
3045
3046 // Adjust path for cwd and redirection
3047 path = p->checkPathRedirect(path);
3048
3049 int result = truncate(path.c_str(), length);
3050 return (result == -1) ? -errno : result;
3051}
3052
3054template <typename OS>
3055SyscallReturn
3057 typename OS::off_t length)
3058{
3059 auto p = tc->getProcessPtr();
3060
3061 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
3062 if (!ffdp)
3063 return -EBADF;
3064 int sim_fd = ffdp->getSimFD();
3065
3066 int result = ftruncate(sim_fd, length);
3067 return (result == -1) ? -errno : result;
3068}
3069
3070template <typename OS>
3071SyscallReturn
3073 VPtr<> buf_ptr, typename OS::size_t count,
3074 unsigned int flags)
3075{
3076 SETranslatingPortProxy proxy(tc);
3077
3078 TypedBufferArg<uint8_t> buf(buf_ptr, count);
3079 for (int i = 0; i < count; ++i) {
3080 buf[i] = gem5::random_mt.random<uint8_t>();
3081 }
3082 buf.copyOut(proxy);
3083
3084 return count;
3085}
3086
3087} // namespace gem5
3088
3089#endif // __SIM_SYSCALL_EMUL_HH__
#define DPRINTF(x,...)
Definition trace.hh:210
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Addr addr() const
Definition proxy_ptr.hh:173
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
virtual int ioctl(ThreadContext *tc, unsigned req, Addr buf)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver.
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, off_t offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
virtual void initState()
FutexMap class holds a map of all futexes used in the system.
Definition futex_map.hh:110
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
Definition futex_map.cc:89
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
Definition futex_map.cc:141
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition futex_map.cc:53
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition futex_map.cc:59
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition futex_map.cc:108
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:107
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition port_proxy.hh:87
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition process.cc:278
uint64_t pid()
Definition process.hh:86
std::shared_ptr< FDArray > fds
Definition process.hh:286
void assignThreadContext(ContextID context_id)
Definition process.hh:130
bool useForClone
Definition process.hh:182
bool * sigchld
Definition process.hh:298
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition process.cc:424
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition process.cc:288
uint64_t tgid()
Definition process.hh:90
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
Definition process.cc:265
EmulationPageTable * pTable
Definition process.hh:184
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition process.hh:295
This class provides the wrapper interface for the system call implementations which are defined in th...
std::string name() const
virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret)=0
For use within the system call executor if new threads are created and need something returned into t...
This class represents the return value from an emulated system call, including any errno setting.
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
int size() const
Definition system.hh:210
ThreadContext * findFree()
Definition system.cc:121
static const int maxPID
Definition system.hh:600
std::list< BasicSignal > signalList
Definition system.hh:607
FutexMap futexMap
Definition system.hh:598
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void activate()=0
Set the status to Active.
virtual System * getSystemPtr()=0
virtual void clearArchRegs()=0
virtual void setProcessPtr(Process *p)=0
@ Suspended
Temporarily inactive.
virtual const PCStateBase & pcState() const =0
virtual int threadId() const =0
virtual Status status() const =0
virtual Process * getProcessPtr()=0
virtual ContextID contextId() const =0
virtual void suspend()=0
Set the status to Suspended.
void setUseForClone(bool new_val)
virtual int cpuId() const =0
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition symtab.cc:54
STL list class.
Definition stl.hh:51
STL vector class.
Definition stl.hh:37
Random random_mt
Definition random.cc:99
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition random.hh:90
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition intmath.hh:260
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
uint8_t flags
Definition helpers.cc:66
#define warn(...)
Definition logging.hh:256
#define warn_once(...)
Definition logging.hh:260
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:283
Bitfield< 14, 12 > fd
Definition types.hh:150
Bitfield< 31 > n
Bitfield< 3 > sa
Bitfield< 18, 16 > len
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > b
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 7, 4 > domain
Bitfield< 5, 0 > status
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 25, 21 > bo
Definition types.hh:82
Bitfield< 4 > op
Definition types.hh:83
Bitfield< 63 > val
Definition misc.hh:776
Bitfield< 20 > level
Definition intmessage.hh:51
Bitfield< 3 > addr
Definition types.hh:84
Bitfield< 7 > prot
Definition misc.hh:587
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition symtab.cc:43
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Tick ns
nanosecond
Definition core.cc:68
Tick us
microsecond
Definition core.cc:67
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
SyscallReturn getrandomFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, typename OS::size_t count, unsigned int flags)
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_gettime() function.
void warnUnsupportedOS(std::string syscall_name)
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition str.hh:230
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
struct stat hst_stat
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
SyscallReturn selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds, VPtr< typename OS::fd_set > readfds, VPtr< typename OS::fd_set > writefds, VPtr< typename OS::fd_set > errorfds, VPtr< typename OS::timeval > timeout)
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
SyscallReturn doClone(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, typename OS::off_t length)
Target truncate() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
SyscallReturn atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
T gtoh(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:194
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
SyscallReturn fchownatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group, int flags)
Target fchownat() handler.
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags)
Target unlinkat() handler.
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_getres() function.
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int mode)
Target facessat() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
SyscallReturn mknodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknodat() handler.
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, typename OS::off_t offset, typename OS::off_t len)
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
SyscallReturn futimesatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target futimesat() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t length)
Target ftruncate() handler.
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlinkat() handler.
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
SyscallReturn fchmodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target chmod() handler.
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
struct statfs hst_statfs
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length)
Target munmap() handler.
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlink() handler.
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
T htog(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:187
SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, pid_t pid, typename OS::size_t cpusetsize, VPtr<> cpu_set_mask)
Target sched_getaffinity.
uint64_t RegVal
Definition types.hh:173
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
SyscallReturn newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat, int flags)
Target newfstatat() handler.
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn clone3Func(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_clone_args > cl_args, RegVal size)
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target writev() handler.
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags, guest_abi::VarArgs< uint64_t > varargs)
Target mremap() handler.
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, int nbytes, int offset)
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstatat64() handler.
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps.
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
struct stat64 hst_stat64
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int nbytes)
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, socklen_t addr_len)
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, typename OS::size_t count)
Target readv() handler.
SyscallReturn mkdiratFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target mkdirat() handler.
Declarations of a non-full system Page Table.
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
This file defines buffer classes used to handle pointer arguments in emulated syscalls.

Generated on Mon Jul 10 2023 15:32:05 for gem5 by doxygen 1.9.7