syscall_emul.hh revision 13568:9c11b79e3223
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * Copyright (c) 2015 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2003-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 *          Kevin Lim
43 */
44
45#ifndef __SIM_SYSCALL_EMUL_HH__
46#define __SIM_SYSCALL_EMUL_HH__
47
48#if (defined(__APPLE__) || defined(__OpenBSD__) ||      \
49     defined(__FreeBSD__) || defined(__CYGWIN__) ||     \
50     defined(__NetBSD__))
51#define NO_STAT64 1
52#else
53#define NO_STAT64 0
54#endif
55
56#if (defined(__APPLE__) || defined(__OpenBSD__) ||      \
57     defined(__FreeBSD__) || defined(__NetBSD__))
58#define NO_STATFS 1
59#else
60#define NO_STATFS 0
61#endif
62
63#if (defined(__APPLE__) || defined(__OpenBSD__) ||      \
64     defined(__FreeBSD__) || defined(__NetBSD__))
65#define NO_FALLOCATE 1
66#else
67#define NO_FALLOCATE 0
68#endif
69
70///
71/// @file syscall_emul.hh
72///
73/// This file defines objects used to emulate syscalls from the target
74/// application on the host machine.
75
76#ifdef __CYGWIN32__
77#include <sys/fcntl.h>
78
79#endif
80#include <fcntl.h>
81#include <sys/mman.h>
82#include <sys/socket.h>
83#include <sys/stat.h>
84#if (NO_STATFS == 0)
85#include <sys/statfs.h>
86#else
87#include <sys/mount.h>
88#endif
89#include <sys/time.h>
90#include <sys/uio.h>
91#include <unistd.h>
92
93#include <cerrno>
94#include <memory>
95#include <string>
96
97#include "arch/generic/tlb.hh"
98#include "arch/utility.hh"
99#include "base/intmath.hh"
100#include "base/loader/object_file.hh"
101#include "base/logging.hh"
102#include "base/trace.hh"
103#include "base/types.hh"
104#include "config/the_isa.hh"
105#include "cpu/base.hh"
106#include "cpu/thread_context.hh"
107#include "mem/page_table.hh"
108#include "params/Process.hh"
109#include "sim/emul_driver.hh"
110#include "sim/futex_map.hh"
111#include "sim/process.hh"
112#include "sim/syscall_debug_macros.hh"
113#include "sim/syscall_desc.hh"
114#include "sim/syscall_emul_buf.hh"
115#include "sim/syscall_return.hh"
116
117//////////////////////////////////////////////////////////////////////
118//
119// The following emulation functions are generic enough that they
120// don't need to be recompiled for different emulated OS's.  They are
121// defined in sim/syscall_emul.cc.
122//
123//////////////////////////////////////////////////////////////////////
124
125
126/// Handler for unimplemented syscalls that we haven't thought about.
127SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
128                                Process *p, ThreadContext *tc);
129
130/// Handler for unimplemented syscalls that we never intend to
131/// implement (signal handling, etc.) and should not affect the correct
132/// behavior of the program.  Print a warning only if the appropriate
133/// trace flag is enabled.  Return success to the target program.
134SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
135                         Process *p, ThreadContext *tc);
136
137// Target fallocateFunc() handler.
138SyscallReturn fallocateFunc(SyscallDesc *desc, int num,
139                            Process *p, ThreadContext *tc);
140
141/// Target exit() handler: terminate current context.
142SyscallReturn exitFunc(SyscallDesc *desc, int num,
143                       Process *p, ThreadContext *tc);
144
145/// Target exit_group() handler: terminate simulation. (exit all threads)
146SyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
147                       Process *p, ThreadContext *tc);
148
149/// Target set_tid_address() handler.
150SyscallReturn setTidAddressFunc(SyscallDesc *desc, int num,
151                                Process *p, ThreadContext *tc);
152
153/// Target getpagesize() handler.
154SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
155                              Process *p, ThreadContext *tc);
156
157/// Target brk() handler: set brk address.
158SyscallReturn brkFunc(SyscallDesc *desc, int num,
159                      Process *p, ThreadContext *tc);
160
161/// Target close() handler.
162SyscallReturn closeFunc(SyscallDesc *desc, int num,
163                        Process *p, ThreadContext *tc);
164
165// Target read() handler.
166SyscallReturn readFunc(SyscallDesc *desc, int num,
167                       Process *p, ThreadContext *tc);
168
169/// Target write() handler.
170SyscallReturn writeFunc(SyscallDesc *desc, int num,
171                        Process *p, ThreadContext *tc);
172
173/// Target lseek() handler.
174SyscallReturn lseekFunc(SyscallDesc *desc, int num,
175                        Process *p, ThreadContext *tc);
176
177/// Target _llseek() handler.
178SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
179                          Process *p, ThreadContext *tc);
180
181/// Target munmap() handler.
182SyscallReturn munmapFunc(SyscallDesc *desc, int num,
183                         Process *p, ThreadContext *tc);
184
185/// Target shutdown() handler.
186SyscallReturn shutdownFunc(SyscallDesc *desc, int num,
187                           Process *p, ThreadContext *tc);
188
189/// Target gethostname() handler.
190SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
191                              Process *p, ThreadContext *tc);
192
193/// Target getcwd() handler.
194SyscallReturn getcwdFunc(SyscallDesc *desc, int num,
195                         Process *p, ThreadContext *tc);
196
197/// Target readlink() handler.
198SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
199                           Process *p, ThreadContext *tc,
200                           int index = 0);
201SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
202                           Process *p, ThreadContext *tc);
203
204/// Target unlink() handler.
205SyscallReturn unlinkHelper(SyscallDesc *desc, int num,
206                           Process *p, ThreadContext *tc,
207                           int index);
208SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
209                         Process *p, ThreadContext *tc);
210
211/// Target link() handler
212SyscallReturn linkFunc(SyscallDesc *desc, int num, Process *p,
213                       ThreadContext *tc);
214
215/// Target symlink() handler.
216SyscallReturn symlinkFunc(SyscallDesc *desc, int num, Process *p,
217                          ThreadContext *tc);
218
219/// Target mkdir() handler.
220SyscallReturn mkdirFunc(SyscallDesc *desc, int num,
221                        Process *p, ThreadContext *tc);
222
223/// Target mknod() handler.
224SyscallReturn mknodFunc(SyscallDesc *desc, int num,
225                        Process *p, ThreadContext *tc);
226
227/// Target chdir() handler.
228SyscallReturn chdirFunc(SyscallDesc *desc, int num,
229                        Process *p, ThreadContext *tc);
230
231// Target rmdir() handler.
232SyscallReturn rmdirFunc(SyscallDesc *desc, int num,
233                        Process *p, ThreadContext *tc);
234
235/// Target rename() handler.
236SyscallReturn renameFunc(SyscallDesc *desc, int num,
237                         Process *p, ThreadContext *tc);
238
239
240/// Target truncate() handler.
241SyscallReturn truncateFunc(SyscallDesc *desc, int num,
242                           Process *p, ThreadContext *tc);
243
244
245/// Target ftruncate() handler.
246SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
247                            Process *p, ThreadContext *tc);
248
249
250/// Target truncate64() handler.
251SyscallReturn truncate64Func(SyscallDesc *desc, int num,
252                             Process *p, ThreadContext *tc);
253
254/// Target ftruncate64() handler.
255SyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
256                              Process *p, ThreadContext *tc);
257
258
259/// Target umask() handler.
260SyscallReturn umaskFunc(SyscallDesc *desc, int num,
261                        Process *p, ThreadContext *tc);
262
263/// Target gettid() handler.
264SyscallReturn gettidFunc(SyscallDesc *desc, int num,
265                         Process *p, ThreadContext *tc);
266
267/// Target chown() handler.
268SyscallReturn chownFunc(SyscallDesc *desc, int num,
269                        Process *p, ThreadContext *tc);
270
271/// Target setpgid() handler.
272SyscallReturn setpgidFunc(SyscallDesc *desc, int num,
273                          Process *p, ThreadContext *tc);
274
275/// Target fchown() handler.
276SyscallReturn fchownFunc(SyscallDesc *desc, int num,
277                         Process *p, ThreadContext *tc);
278
279/// Target dup() handler.
280SyscallReturn dupFunc(SyscallDesc *desc, int num,
281                      Process *process, ThreadContext *tc);
282
283/// Target dup2() handler.
284SyscallReturn dup2Func(SyscallDesc *desc, int num,
285                       Process *process, ThreadContext *tc);
286
287/// Target fcntl() handler.
288SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
289                        Process *process, ThreadContext *tc);
290
291/// Target fcntl64() handler.
292SyscallReturn fcntl64Func(SyscallDesc *desc, int num,
293                          Process *process, ThreadContext *tc);
294
295/// Target setuid() handler.
296SyscallReturn setuidFunc(SyscallDesc *desc, int num,
297                         Process *p, ThreadContext *tc);
298
299/// Target pipe() handler.
300SyscallReturn pipeFunc(SyscallDesc *desc, int num,
301                       Process *p, ThreadContext *tc);
302
303/// Internal pipe() handler.
304SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p,
305                       ThreadContext *tc, bool pseudoPipe);
306
307/// Target getpid() handler.
308SyscallReturn getpidFunc(SyscallDesc *desc, int num,
309                         Process *p, ThreadContext *tc);
310
311// Target bind() handler.
312SyscallReturn bindFunc(SyscallDesc *desc, int num,
313                       Process *p, ThreadContext *tc);
314
315// Target listen() handler.
316SyscallReturn listenFunc(SyscallDesc *desc, int num,
317                         Process *p, ThreadContext *tc);
318
319// Target connect() handler.
320SyscallReturn connectFunc(SyscallDesc *desc, int num,
321                          Process *p, ThreadContext *tc);
322
323#if defined(SYS_getdents)
324// Target getdents() handler.
325SyscallReturn getdentsFunc(SyscallDesc *desc, int num,
326                           Process *p, ThreadContext *tc);
327#endif
328
329#if defined(SYS_getdents64)
330// Target getdents() handler.
331SyscallReturn getdents64Func(SyscallDesc *desc, int num,
332                           Process *p, ThreadContext *tc);
333#endif
334
335// Target getuid() handler.
336SyscallReturn getuidFunc(SyscallDesc *desc, int num,
337                         Process *p, ThreadContext *tc);
338
339/// Target getgid() handler.
340SyscallReturn getgidFunc(SyscallDesc *desc, int num,
341                         Process *p, ThreadContext *tc);
342
343/// Target getppid() handler.
344SyscallReturn getppidFunc(SyscallDesc *desc, int num,
345                          Process *p, ThreadContext *tc);
346
347/// Target geteuid() handler.
348SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
349                          Process *p, ThreadContext *tc);
350
351/// Target getegid() handler.
352SyscallReturn getegidFunc(SyscallDesc *desc, int num,
353                          Process *p, ThreadContext *tc);
354
355/// Target access() handler
356SyscallReturn accessFunc(SyscallDesc *desc, int num,
357                         Process *p, ThreadContext *tc);
358SyscallReturn accessFunc(SyscallDesc *desc, int num,
359                         Process *p, ThreadContext *tc,
360                         int index);
361
362/// Futex system call
363/// Implemented by Daniel Sanchez
364/// Used by printf's in multi-threaded apps
365template <class OS>
366SyscallReturn
367futexFunc(SyscallDesc *desc, int callnum, Process *process,
368          ThreadContext *tc)
369{
370    using namespace std;
371
372    int index = 0;
373    Addr uaddr = process->getSyscallArg(tc, index);
374    int op = process->getSyscallArg(tc, index);
375    int val = process->getSyscallArg(tc, index);
376
377    /*
378     * Unsupported option that does not affect the correctness of the
379     * application. This is a performance optimization utilized by Linux.
380     */
381    op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
382
383    FutexMap &futex_map = tc->getSystemPtr()->futexMap;
384
385    if (OS::TGT_FUTEX_WAIT == op) {
386        // Ensure futex system call accessed atomically.
387        BufferArg buf(uaddr, sizeof(int));
388        buf.copyIn(tc->getMemProxy());
389        int mem_val = *(int*)buf.bufferPtr();
390
391        /*
392         * The value in memory at uaddr is not equal with the expected val
393         * (a different thread must have changed it before the system call was
394         * invoked). In this case, we need to throw an error.
395         */
396        if (val != mem_val)
397            return -OS::TGT_EWOULDBLOCK;
398
399        futex_map.suspend(uaddr, process->tgid(), tc);
400
401        return 0;
402    } else if (OS::TGT_FUTEX_WAKE == op) {
403        return futex_map.wakeup(uaddr, process->tgid(), val);
404    }
405
406    warn("futex: op %d not implemented; ignoring.", op);
407    return -ENOSYS;
408}
409
410
411/// Pseudo Funcs  - These functions use a different return convension,
412/// returning a second value in a register other than the normal return register
413SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
414                             Process *process, ThreadContext *tc);
415
416/// Target getpidPseudo() handler.
417SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
418                               Process *p, ThreadContext *tc);
419
420/// Target getuidPseudo() handler.
421SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
422                               Process *p, ThreadContext *tc);
423
424/// Target getgidPseudo() handler.
425SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
426                               Process *p, ThreadContext *tc);
427
428
429/// A readable name for 1,000,000, for converting microseconds to seconds.
430const int one_million = 1000000;
431/// A readable name for 1,000,000,000, for converting nanoseconds to seconds.
432const int one_billion = 1000000000;
433
434/// Approximate seconds since the epoch (1/1/1970).  About a billion,
435/// by my reckoning.  We want to keep this a constant (not use the
436/// real-world time) to keep simulations repeatable.
437const unsigned seconds_since_epoch = 1000000000;
438
439/// Helper function to convert current elapsed time to seconds and
440/// microseconds.
441template <class T1, class T2>
442void
443getElapsedTimeMicro(T1 &sec, T2 &usec)
444{
445    uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
446    sec = elapsed_usecs / one_million;
447    usec = elapsed_usecs % one_million;
448}
449
450/// Helper function to convert current elapsed time to seconds and
451/// nanoseconds.
452template <class T1, class T2>
453void
454getElapsedTimeNano(T1 &sec, T2 &nsec)
455{
456    uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
457    sec = elapsed_nsecs / one_billion;
458    nsec = elapsed_nsecs % one_billion;
459}
460
461//////////////////////////////////////////////////////////////////////
462//
463// The following emulation functions are generic, but need to be
464// templated to account for differences in types, constants, etc.
465//
466//////////////////////////////////////////////////////////////////////
467
468    typedef struct statfs hst_statfs;
469#if NO_STAT64
470    typedef struct stat hst_stat;
471    typedef struct stat hst_stat64;
472#else
473    typedef struct stat hst_stat;
474    typedef struct stat64 hst_stat64;
475#endif
476
477//// Helper function to convert a host stat buffer to a target stat
478//// buffer.  Also copies the target buffer out to the simulated
479//// memory space.  Used by stat(), fstat(), and lstat().
480
481template <typename target_stat, typename host_stat>
482void
483convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
484{
485    using namespace TheISA;
486
487    if (fakeTTY)
488        tgt->st_dev = 0xA;
489    else
490        tgt->st_dev = host->st_dev;
491    tgt->st_dev = TheISA::htog(tgt->st_dev);
492    tgt->st_ino = host->st_ino;
493    tgt->st_ino = TheISA::htog(tgt->st_ino);
494    tgt->st_mode = host->st_mode;
495    if (fakeTTY) {
496        // Claim to be a character device
497        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
498        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
499    }
500    tgt->st_mode = TheISA::htog(tgt->st_mode);
501    tgt->st_nlink = host->st_nlink;
502    tgt->st_nlink = TheISA::htog(tgt->st_nlink);
503    tgt->st_uid = host->st_uid;
504    tgt->st_uid = TheISA::htog(tgt->st_uid);
505    tgt->st_gid = host->st_gid;
506    tgt->st_gid = TheISA::htog(tgt->st_gid);
507    if (fakeTTY)
508        tgt->st_rdev = 0x880d;
509    else
510        tgt->st_rdev = host->st_rdev;
511    tgt->st_rdev = TheISA::htog(tgt->st_rdev);
512    tgt->st_size = host->st_size;
513    tgt->st_size = TheISA::htog(tgt->st_size);
514    tgt->st_atimeX = host->st_atime;
515    tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
516    tgt->st_mtimeX = host->st_mtime;
517    tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
518    tgt->st_ctimeX = host->st_ctime;
519    tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
520    // Force the block size to be 8KB. This helps to ensure buffered io works
521    // consistently across different hosts.
522    tgt->st_blksize = 0x2000;
523    tgt->st_blksize = TheISA::htog(tgt->st_blksize);
524    tgt->st_blocks = host->st_blocks;
525    tgt->st_blocks = TheISA::htog(tgt->st_blocks);
526}
527
528// Same for stat64
529
530template <typename target_stat, typename host_stat64>
531void
532convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
533{
534    using namespace TheISA;
535
536    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
537#if defined(STAT_HAVE_NSEC)
538    tgt->st_atime_nsec = host->st_atime_nsec;
539    tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
540    tgt->st_mtime_nsec = host->st_mtime_nsec;
541    tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
542    tgt->st_ctime_nsec = host->st_ctime_nsec;
543    tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
544#else
545    tgt->st_atime_nsec = 0;
546    tgt->st_mtime_nsec = 0;
547    tgt->st_ctime_nsec = 0;
548#endif
549}
550
551// Here are a couple of convenience functions
552template<class OS>
553void
554copyOutStatBuf(SETranslatingPortProxy &mem, Addr addr,
555               hst_stat *host, bool fakeTTY = false)
556{
557    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
558    tgt_stat_buf tgt(addr);
559    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
560    tgt.copyOut(mem);
561}
562
563template<class OS>
564void
565copyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr,
566                 hst_stat64 *host, bool fakeTTY = false)
567{
568    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
569    tgt_stat_buf tgt(addr);
570    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
571    tgt.copyOut(mem);
572}
573
574template <class OS>
575void
576copyOutStatfsBuf(SETranslatingPortProxy &mem, Addr addr,
577                 hst_statfs *host)
578{
579    TypedBufferArg<typename OS::tgt_statfs> tgt(addr);
580
581    tgt->f_type = TheISA::htog(host->f_type);
582#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
583    tgt->f_bsize = TheISA::htog(host->f_iosize);
584#else
585    tgt->f_bsize = TheISA::htog(host->f_bsize);
586#endif
587    tgt->f_blocks = TheISA::htog(host->f_blocks);
588    tgt->f_bfree = TheISA::htog(host->f_bfree);
589    tgt->f_bavail = TheISA::htog(host->f_bavail);
590    tgt->f_files = TheISA::htog(host->f_files);
591    tgt->f_ffree = TheISA::htog(host->f_ffree);
592    memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
593#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
594    tgt->f_namelen = TheISA::htog(host->f_namemax);
595    tgt->f_frsize = TheISA::htog(host->f_bsize);
596#elif defined(__APPLE__)
597    tgt->f_namelen = 0;
598    tgt->f_frsize = 0;
599#else
600    tgt->f_namelen = TheISA::htog(host->f_namelen);
601    tgt->f_frsize = TheISA::htog(host->f_frsize);
602#endif
603#if defined(__linux__)
604    memcpy(&tgt->f_spare, &host->f_spare, sizeof(host->f_spare));
605#else
606    /*
607     * The fields are different sizes per OS. Don't bother with
608     * f_spare or f_reserved on non-Linux for now.
609     */
610    memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
611#endif
612
613    tgt.copyOut(mem);
614}
615
616/// Target ioctl() handler.  For the most part, programs call ioctl()
617/// only to find out if their stdout is a tty, to determine whether to
618/// do line or block buffering.  We always claim that output fds are
619/// not TTYs to provide repeatable results.
620template <class OS>
621SyscallReturn
622ioctlFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
623{
624    int index = 0;
625    int tgt_fd = p->getSyscallArg(tc, index);
626    unsigned req = p->getSyscallArg(tc, index);
627
628    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
629
630    if (OS::isTtyReq(req))
631        return -ENOTTY;
632
633    auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
634    if (!dfdp)
635        return -EBADF;
636
637    /**
638     * If the driver is valid, issue the ioctl through it. Otherwise,
639     * there's an implicit assumption that the device is a TTY type and we
640     * return that we do not have a valid TTY.
641     */
642    EmulatedDriver *emul_driver = dfdp->getDriver();
643    if (emul_driver)
644        return emul_driver->ioctl(p, tc, req);
645
646    /**
647     * For lack of a better return code, return ENOTTY. Ideally, we should
648     * return something better here, but at least we issue the warning.
649     */
650    warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
651         tgt_fd, req, tc->pcState());
652    return -ENOTTY;
653}
654
655template <class OS>
656SyscallReturn
657openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
658         bool isopenat)
659{
660    int index = 0;
661    int tgt_dirfd = -1;
662
663    /**
664     * If using the openat variant, read in the target directory file
665     * descriptor from the simulated process.
666     */
667    if (isopenat)
668        tgt_dirfd = p->getSyscallArg(tc, index);
669
670    /**
671     * Retrieve the simulated process' memory proxy and then read in the path
672     * string from that memory space into the host's working memory space.
673     */
674    std::string path;
675    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
676        return -EFAULT;
677
678#ifdef __CYGWIN32__
679    int host_flags = O_BINARY;
680#else
681    int host_flags = 0;
682#endif
683    /**
684     * Translate target flags into host flags. Flags exist which are not
685     * ported between architectures which can cause check failures.
686     */
687    int tgt_flags = p->getSyscallArg(tc, index);
688    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
689        if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
690            tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
691            host_flags |= OS::openFlagTable[i].hostFlag;
692        }
693    }
694    if (tgt_flags) {
695        warn("open%s: cannot decode flags 0x%x",
696             isopenat ? "at" : "", tgt_flags);
697    }
698#ifdef __CYGWIN32__
699    host_flags |= O_BINARY;
700#endif
701
702    int mode = p->getSyscallArg(tc, index);
703
704    /**
705     * If the simulated process called open or openat with AT_FDCWD specified,
706     * take the current working directory value which was passed into the
707     * process class as a Python parameter and append the current path to
708     * create a full path.
709     * Otherwise, openat with a valid target directory file descriptor has
710     * been called. If the path option, which was passed in as a parameter,
711     * is not absolute, retrieve the directory file descriptor's path and
712     * prepend it to the path passed in as a parameter.
713     * In every case, we should have a full path (which is relevant to the
714     * host) to work with after this block has been passed.
715     */
716    if (!isopenat || (isopenat && tgt_dirfd == OS::TGT_AT_FDCWD)) {
717        path = p->fullPath(path);
718    } else if (!startswith(path, "/")) {
719        std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
720        auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
721        if (!ffdp)
722            return -EBADF;
723        path.insert(0, ffdp->getFileName() + "/");
724    }
725
726    /**
727     * Since this is an emulated environment, we create pseudo file
728     * descriptors for device requests that have been registered with
729     * the process class through Python; this allows us to create a file
730     * descriptor for subsequent ioctl or mmap calls.
731     */
732    if (startswith(path, "/dev/")) {
733        std::string filename = path.substr(strlen("/dev/"));
734        EmulatedDriver *drv = p->findDriver(filename);
735        if (drv) {
736            DPRINTF_SYSCALL(Verbose, "open%s: passing call to "
737                            "driver open with path[%s]\n",
738                            isopenat ? "at" : "", path.c_str());
739            return drv->open(p, tc, mode, host_flags);
740        }
741        /**
742         * Fall through here for pass through to host devices, such
743         * as /dev/zero
744         */
745    }
746
747    /**
748     * Some special paths and files cannot be called on the host and need
749     * to be handled as special cases inside the simulator.
750     * If the full path that was created above does not match any of the
751     * special cases, pass it through to the open call on the host to let
752     * the host open the file on our behalf.
753     * If the host cannot open the file, return the host's error code back
754     * through the system call to the simulated process.
755     */
756    int sim_fd = -1;
757    std::vector<std::string> special_paths =
758            { "/proc/", "/system/", "/sys/", "/platform/", "/etc/passwd" };
759    for (auto entry : special_paths) {
760        if (startswith(path, entry))
761            sim_fd = OS::openSpecialFile(path, p, tc);
762    }
763    if (sim_fd == -1) {
764        sim_fd = open(path.c_str(), host_flags, mode);
765    }
766    if (sim_fd == -1) {
767        int local = -errno;
768        DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n",
769                        isopenat ? "at" : "", path.c_str());
770        return local;
771    }
772
773    /**
774     * The file was opened successfully and needs to be recorded in the
775     * process' file descriptor array so that it can be retrieved later.
776     * The target file descriptor that is chosen will be the lowest unused
777     * file descriptor.
778     * Return the indirect target file descriptor back to the simulated
779     * process to act as a handle for the opened file.
780     */
781    auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
782    int tgt_fd = p->fds->allocFD(ffdp);
783    DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n",
784                    isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str());
785    return tgt_fd;
786}
787
788/// Target open() handler.
789template <class OS>
790SyscallReturn
791openFunc(SyscallDesc *desc, int callnum, Process *process,
792         ThreadContext *tc)
793{
794    return openImpl<OS>(desc, callnum, process, tc, false);
795}
796
797/// Target openat() handler.
798template <class OS>
799SyscallReturn
800openatFunc(SyscallDesc *desc, int callnum, Process *process,
801           ThreadContext *tc)
802{
803    return openImpl<OS>(desc, callnum, process, tc, true);
804}
805
806/// Target unlinkat() handler.
807template <class OS>
808SyscallReturn
809unlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
810             ThreadContext *tc)
811{
812    int index = 0;
813    int dirfd = process->getSyscallArg(tc, index);
814    if (dirfd != OS::TGT_AT_FDCWD)
815        warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
816
817    return unlinkHelper(desc, callnum, process, tc, 1);
818}
819
820/// Target facessat() handler
821template <class OS>
822SyscallReturn
823faccessatFunc(SyscallDesc *desc, int callnum, Process *process,
824              ThreadContext *tc)
825{
826    int index = 0;
827    int dirfd = process->getSyscallArg(tc, index);
828    if (dirfd != OS::TGT_AT_FDCWD)
829        warn("faccessat: first argument not AT_FDCWD; unlikely to work");
830    return accessFunc(desc, callnum, process, tc, 1);
831}
832
833/// Target readlinkat() handler
834template <class OS>
835SyscallReturn
836readlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
837               ThreadContext *tc)
838{
839    int index = 0;
840    int dirfd = process->getSyscallArg(tc, index);
841    if (dirfd != OS::TGT_AT_FDCWD)
842        warn("openat: first argument not AT_FDCWD; unlikely to work");
843    return readlinkFunc(desc, callnum, process, tc, 1);
844}
845
846/// Target renameat() handler.
847template <class OS>
848SyscallReturn
849renameatFunc(SyscallDesc *desc, int callnum, Process *process,
850             ThreadContext *tc)
851{
852    int index = 0;
853
854    int olddirfd = process->getSyscallArg(tc, index);
855    if (olddirfd != OS::TGT_AT_FDCWD)
856        warn("renameat: first argument not AT_FDCWD; unlikely to work");
857
858    std::string old_name;
859
860    if (!tc->getMemProxy().tryReadString(old_name,
861                                         process->getSyscallArg(tc, index)))
862        return -EFAULT;
863
864    int newdirfd = process->getSyscallArg(tc, index);
865    if (newdirfd != OS::TGT_AT_FDCWD)
866        warn("renameat: third argument not AT_FDCWD; unlikely to work");
867
868    std::string new_name;
869
870    if (!tc->getMemProxy().tryReadString(new_name,
871                                         process->getSyscallArg(tc, index)))
872        return -EFAULT;
873
874    // Adjust path for current working directory
875    old_name = process->fullPath(old_name);
876    new_name = process->fullPath(new_name);
877
878    int result = rename(old_name.c_str(), new_name.c_str());
879    return (result == -1) ? -errno : result;
880}
881
882/// Target sysinfo() handler.
883template <class OS>
884SyscallReturn
885sysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
886            ThreadContext *tc)
887{
888
889    int index = 0;
890    TypedBufferArg<typename OS::tgt_sysinfo>
891        sysinfo(process->getSyscallArg(tc, index));
892
893    sysinfo->uptime = seconds_since_epoch;
894    sysinfo->totalram = process->system->memSize();
895    sysinfo->mem_unit = 1;
896
897    sysinfo.copyOut(tc->getMemProxy());
898
899    return 0;
900}
901
902/// Target chmod() handler.
903template <class OS>
904SyscallReturn
905chmodFunc(SyscallDesc *desc, int callnum, Process *process,
906          ThreadContext *tc)
907{
908    std::string path;
909
910    int index = 0;
911    if (!tc->getMemProxy().tryReadString(path,
912                process->getSyscallArg(tc, index))) {
913        return -EFAULT;
914    }
915
916    uint32_t mode = process->getSyscallArg(tc, index);
917    mode_t hostMode = 0;
918
919    // XXX translate mode flags via OS::something???
920    hostMode = mode;
921
922    // Adjust path for current working directory
923    path = process->fullPath(path);
924
925    // do the chmod
926    int result = chmod(path.c_str(), hostMode);
927    if (result < 0)
928        return -errno;
929
930    return 0;
931}
932
933
934/// Target fchmod() handler.
935template <class OS>
936SyscallReturn
937fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
938{
939    int index = 0;
940    int tgt_fd = p->getSyscallArg(tc, index);
941    uint32_t mode = p->getSyscallArg(tc, index);
942
943    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
944    if (!ffdp)
945        return -EBADF;
946    int sim_fd = ffdp->getSimFD();
947
948    mode_t hostMode = mode;
949
950    int result = fchmod(sim_fd, hostMode);
951
952    return (result < 0) ? -errno : 0;
953}
954
955/// Target mremap() handler.
956template <class OS>
957SyscallReturn
958mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
959{
960    int index = 0;
961    Addr start = process->getSyscallArg(tc, index);
962    uint64_t old_length = process->getSyscallArg(tc, index);
963    uint64_t new_length = process->getSyscallArg(tc, index);
964    uint64_t flags = process->getSyscallArg(tc, index);
965    uint64_t provided_address = 0;
966    bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
967
968    if (use_provided_address)
969        provided_address = process->getSyscallArg(tc, index);
970
971    if ((start % TheISA::PageBytes != 0) ||
972        (provided_address % TheISA::PageBytes != 0)) {
973        warn("mremap failing: arguments not page aligned");
974        return -EINVAL;
975    }
976
977    new_length = roundUp(new_length, TheISA::PageBytes);
978
979    if (new_length > old_length) {
980        std::shared_ptr<MemState> mem_state = process->memState;
981        Addr mmap_end = mem_state->getMmapEnd();
982
983        if ((start + old_length) == mmap_end &&
984            (!use_provided_address || provided_address == start)) {
985            // This case cannot occur when growing downward, as
986            // start is greater than or equal to mmap_end.
987            uint64_t diff = new_length - old_length;
988            process->allocateMem(mmap_end, diff);
989            mem_state->setMmapEnd(mmap_end + diff);
990            return start;
991        } else {
992            if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
993                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
994                return -ENOMEM;
995            } else {
996                uint64_t new_start = provided_address;
997                if (!use_provided_address) {
998                    new_start = process->mmapGrowsDown() ?
999                                mmap_end - new_length : mmap_end;
1000                    mmap_end = process->mmapGrowsDown() ?
1001                               new_start : mmap_end + new_length;
1002                    mem_state->setMmapEnd(mmap_end);
1003                }
1004
1005                process->pTable->remap(start, old_length, new_start);
1006                warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1007                     new_start, new_start + new_length,
1008                     new_length - old_length);
1009                // add on the remaining unallocated pages
1010                process->allocateMem(new_start + old_length,
1011                                     new_length - old_length,
1012                                     use_provided_address /* clobber */);
1013                if (use_provided_address &&
1014                    ((new_start + new_length > mem_state->getMmapEnd() &&
1015                      !process->mmapGrowsDown()) ||
1016                    (new_start < mem_state->getMmapEnd() &&
1017                      process->mmapGrowsDown()))) {
1018                    // something fishy going on here, at least notify the user
1019                    // @todo: increase mmap_end?
1020                    warn("mmap region limit exceeded with MREMAP_FIXED\n");
1021                }
1022                warn("returning %08p as start\n", new_start);
1023                return new_start;
1024            }
1025        }
1026    } else {
1027        if (use_provided_address && provided_address != start)
1028            process->pTable->remap(start, new_length, provided_address);
1029        process->pTable->unmap(start + new_length, old_length - new_length);
1030        return use_provided_address ? provided_address : start;
1031    }
1032}
1033
1034/// Target stat() handler.
1035template <class OS>
1036SyscallReturn
1037statFunc(SyscallDesc *desc, int callnum, Process *process,
1038         ThreadContext *tc)
1039{
1040    std::string path;
1041
1042    int index = 0;
1043    if (!tc->getMemProxy().tryReadString(path,
1044                process->getSyscallArg(tc, index))) {
1045        return -EFAULT;
1046    }
1047    Addr bufPtr = process->getSyscallArg(tc, index);
1048
1049    // Adjust path for current working directory
1050    path = process->fullPath(path);
1051
1052    struct stat hostBuf;
1053    int result = stat(path.c_str(), &hostBuf);
1054
1055    if (result < 0)
1056        return -errno;
1057
1058    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1059
1060    return 0;
1061}
1062
1063
1064/// Target stat64() handler.
1065template <class OS>
1066SyscallReturn
1067stat64Func(SyscallDesc *desc, int callnum, Process *process,
1068           ThreadContext *tc)
1069{
1070    std::string path;
1071
1072    int index = 0;
1073    if (!tc->getMemProxy().tryReadString(path,
1074                process->getSyscallArg(tc, index)))
1075        return -EFAULT;
1076    Addr bufPtr = process->getSyscallArg(tc, index);
1077
1078    // Adjust path for current working directory
1079    path = process->fullPath(path);
1080
1081#if NO_STAT64
1082    struct stat  hostBuf;
1083    int result = stat(path.c_str(), &hostBuf);
1084#else
1085    struct stat64 hostBuf;
1086    int result = stat64(path.c_str(), &hostBuf);
1087#endif
1088
1089    if (result < 0)
1090        return -errno;
1091
1092    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1093
1094    return 0;
1095}
1096
1097
1098/// Target fstatat64() handler.
1099template <class OS>
1100SyscallReturn
1101fstatat64Func(SyscallDesc *desc, int callnum, Process *process,
1102              ThreadContext *tc)
1103{
1104    int index = 0;
1105    int dirfd = process->getSyscallArg(tc, index);
1106    if (dirfd != OS::TGT_AT_FDCWD)
1107        warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1108
1109    std::string path;
1110    if (!tc->getMemProxy().tryReadString(path,
1111                process->getSyscallArg(tc, index)))
1112        return -EFAULT;
1113    Addr bufPtr = process->getSyscallArg(tc, index);
1114
1115    // Adjust path for current working directory
1116    path = process->fullPath(path);
1117
1118#if NO_STAT64
1119    struct stat  hostBuf;
1120    int result = stat(path.c_str(), &hostBuf);
1121#else
1122    struct stat64 hostBuf;
1123    int result = stat64(path.c_str(), &hostBuf);
1124#endif
1125
1126    if (result < 0)
1127        return -errno;
1128
1129    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1130
1131    return 0;
1132}
1133
1134
1135/// Target fstat64() handler.
1136template <class OS>
1137SyscallReturn
1138fstat64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1139{
1140    int index = 0;
1141    int tgt_fd = p->getSyscallArg(tc, index);
1142    Addr bufPtr = p->getSyscallArg(tc, index);
1143
1144    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1145    if (!ffdp)
1146        return -EBADF;
1147    int sim_fd = ffdp->getSimFD();
1148
1149#if NO_STAT64
1150    struct stat  hostBuf;
1151    int result = fstat(sim_fd, &hostBuf);
1152#else
1153    struct stat64  hostBuf;
1154    int result = fstat64(sim_fd, &hostBuf);
1155#endif
1156
1157    if (result < 0)
1158        return -errno;
1159
1160    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1161
1162    return 0;
1163}
1164
1165
1166/// Target lstat() handler.
1167template <class OS>
1168SyscallReturn
1169lstatFunc(SyscallDesc *desc, int callnum, Process *process,
1170          ThreadContext *tc)
1171{
1172    std::string path;
1173
1174    int index = 0;
1175    if (!tc->getMemProxy().tryReadString(path,
1176                process->getSyscallArg(tc, index))) {
1177        return -EFAULT;
1178    }
1179    Addr bufPtr = process->getSyscallArg(tc, index);
1180
1181    // Adjust path for current working directory
1182    path = process->fullPath(path);
1183
1184    struct stat hostBuf;
1185    int result = lstat(path.c_str(), &hostBuf);
1186
1187    if (result < 0)
1188        return -errno;
1189
1190    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1191
1192    return 0;
1193}
1194
1195/// Target lstat64() handler.
1196template <class OS>
1197SyscallReturn
1198lstat64Func(SyscallDesc *desc, int callnum, Process *process,
1199            ThreadContext *tc)
1200{
1201    std::string path;
1202
1203    int index = 0;
1204    if (!tc->getMemProxy().tryReadString(path,
1205                process->getSyscallArg(tc, index))) {
1206        return -EFAULT;
1207    }
1208    Addr bufPtr = process->getSyscallArg(tc, index);
1209
1210    // Adjust path for current working directory
1211    path = process->fullPath(path);
1212
1213#if NO_STAT64
1214    struct stat hostBuf;
1215    int result = lstat(path.c_str(), &hostBuf);
1216#else
1217    struct stat64 hostBuf;
1218    int result = lstat64(path.c_str(), &hostBuf);
1219#endif
1220
1221    if (result < 0)
1222        return -errno;
1223
1224    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1225
1226    return 0;
1227}
1228
1229/// Target fstat() handler.
1230template <class OS>
1231SyscallReturn
1232fstatFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1233{
1234    int index = 0;
1235    int tgt_fd = p->getSyscallArg(tc, index);
1236    Addr bufPtr = p->getSyscallArg(tc, index);
1237
1238    DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1239
1240    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1241    if (!ffdp)
1242        return -EBADF;
1243    int sim_fd = ffdp->getSimFD();
1244
1245    struct stat hostBuf;
1246    int result = fstat(sim_fd, &hostBuf);
1247
1248    if (result < 0)
1249        return -errno;
1250
1251    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1252
1253    return 0;
1254}
1255
1256
1257/// Target statfs() handler.
1258template <class OS>
1259SyscallReturn
1260statfsFunc(SyscallDesc *desc, int callnum, Process *process,
1261           ThreadContext *tc)
1262{
1263#if NO_STATFS
1264    warn("Host OS cannot support calls to statfs. Ignoring syscall");
1265#else
1266    std::string path;
1267
1268    int index = 0;
1269    if (!tc->getMemProxy().tryReadString(path,
1270                process->getSyscallArg(tc, index))) {
1271        return -EFAULT;
1272    }
1273    Addr bufPtr = process->getSyscallArg(tc, index);
1274
1275    // Adjust path for current working directory
1276    path = process->fullPath(path);
1277
1278    struct statfs hostBuf;
1279    int result = statfs(path.c_str(), &hostBuf);
1280
1281    if (result < 0)
1282        return -errno;
1283
1284    copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1285#endif
1286    return 0;
1287}
1288
1289template <class OS>
1290SyscallReturn
1291cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1292{
1293    int index = 0;
1294
1295    RegVal flags = p->getSyscallArg(tc, index);
1296    RegVal newStack = p->getSyscallArg(tc, index);
1297    Addr ptidPtr = p->getSyscallArg(tc, index);
1298
1299#if THE_ISA == RISCV_ISA or THE_ISA == ARM_ISA
1300    /**
1301     * Linux sets CLONE_BACKWARDS flag for RISC-V and Arm.
1302     * The flag defines the list of clone() arguments in the following
1303     * order: flags -> newStack -> ptidPtr -> tlsPtr -> ctidPtr
1304     */
1305    Addr tlsPtr = p->getSyscallArg(tc, index);
1306    Addr ctidPtr = p->getSyscallArg(tc, index);
1307#else
1308    Addr ctidPtr = p->getSyscallArg(tc, index);
1309    Addr tlsPtr = p->getSyscallArg(tc, index);
1310#endif
1311
1312    if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1313        ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1314        ((flags & OS::TGT_CLONE_FS)     &&  (flags & OS::TGT_CLONE_NEWNS)) ||
1315        ((flags & OS::TGT_CLONE_NEWIPC) &&  (flags & OS::TGT_CLONE_SYSVSEM)) ||
1316        ((flags & OS::TGT_CLONE_NEWPID) &&  (flags & OS::TGT_CLONE_THREAD)) ||
1317        ((flags & OS::TGT_CLONE_VM)     && !(newStack)))
1318        return -EINVAL;
1319
1320    ThreadContext *ctc;
1321    if (!(ctc = p->findFreeContext()))
1322        fatal("clone: no spare thread context in system");
1323
1324    /**
1325     * Note that ProcessParams is generated by swig and there are no other
1326     * examples of how to create anything but this default constructor. The
1327     * fields are manually initialized instead of passing parameters to the
1328     * constructor.
1329     */
1330    ProcessParams *pp = new ProcessParams();
1331    pp->executable.assign(*(new std::string(p->progName())));
1332    pp->cmd.push_back(*(new std::string(p->progName())));
1333    pp->system = p->system;
1334    pp->cwd.assign(p->getcwd());
1335    pp->input.assign("stdin");
1336    pp->output.assign("stdout");
1337    pp->errout.assign("stderr");
1338    pp->uid = p->uid();
1339    pp->euid = p->euid();
1340    pp->gid = p->gid();
1341    pp->egid = p->egid();
1342
1343    /* Find the first free PID that's less than the maximum */
1344    std::set<int> const& pids = p->system->PIDs;
1345    int temp_pid = *pids.begin();
1346    do {
1347        temp_pid++;
1348    } while (pids.find(temp_pid) != pids.end());
1349    if (temp_pid >= System::maxPID)
1350        fatal("temp_pid is too large: %d", temp_pid);
1351
1352    pp->pid = temp_pid;
1353    pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1354    Process *cp = pp->create();
1355    delete pp;
1356
1357    Process *owner = ctc->getProcessPtr();
1358    ctc->setProcessPtr(cp);
1359    cp->assignThreadContext(ctc->contextId());
1360    owner->revokeThreadContext(ctc->contextId());
1361
1362    if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1363        BufferArg ptidBuf(ptidPtr, sizeof(long));
1364        long *ptid = (long *)ptidBuf.bufferPtr();
1365        *ptid = cp->pid();
1366        ptidBuf.copyOut(tc->getMemProxy());
1367    }
1368
1369    cp->initState();
1370    p->clone(tc, ctc, cp, flags);
1371
1372    if (flags & OS::TGT_CLONE_THREAD) {
1373        delete cp->sigchld;
1374        cp->sigchld = p->sigchld;
1375    } else if (flags & OS::TGT_SIGCHLD) {
1376        *cp->sigchld = true;
1377    }
1378
1379    if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1380        BufferArg ctidBuf(ctidPtr, sizeof(long));
1381        long *ctid = (long *)ctidBuf.bufferPtr();
1382        *ctid = cp->pid();
1383        ctidBuf.copyOut(ctc->getMemProxy());
1384    }
1385
1386    if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1387        cp->childClearTID = (uint64_t)ctidPtr;
1388
1389    ctc->clearArchRegs();
1390
1391    OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1392
1393    cp->setSyscallReturn(ctc, 0);
1394
1395#if THE_ISA == ALPHA_ISA
1396    ctc->setIntReg(TheISA::SyscallSuccessReg, 0);
1397#elif THE_ISA == SPARC_ISA
1398    tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0);
1399    ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1);
1400#endif
1401
1402    TheISA::PCState cpc = tc->pcState();
1403    cpc.advance();
1404    ctc->pcState(cpc);
1405    ctc->activate();
1406
1407    return cp->pid();
1408}
1409
1410/// Target fstatfs() handler.
1411template <class OS>
1412SyscallReturn
1413fstatfsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1414{
1415    int index = 0;
1416    int tgt_fd = p->getSyscallArg(tc, index);
1417    Addr bufPtr = p->getSyscallArg(tc, index);
1418
1419    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1420    if (!ffdp)
1421        return -EBADF;
1422    int sim_fd = ffdp->getSimFD();
1423
1424    struct statfs hostBuf;
1425    int result = fstatfs(sim_fd, &hostBuf);
1426
1427    if (result < 0)
1428        return -errno;
1429
1430    copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
1431
1432    return 0;
1433}
1434
1435
1436/// Target writev() handler.
1437template <class OS>
1438SyscallReturn
1439writevFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1440{
1441    int index = 0;
1442    int tgt_fd = p->getSyscallArg(tc, index);
1443
1444    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1445    if (!hbfdp)
1446        return -EBADF;
1447    int sim_fd = hbfdp->getSimFD();
1448
1449    SETranslatingPortProxy &prox = tc->getMemProxy();
1450    uint64_t tiov_base = p->getSyscallArg(tc, index);
1451    size_t count = p->getSyscallArg(tc, index);
1452    struct iovec hiov[count];
1453    for (size_t i = 0; i < count; ++i) {
1454        typename OS::tgt_iovec tiov;
1455
1456        prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1457                      (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
1458        hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
1459        hiov[i].iov_base = new char [hiov[i].iov_len];
1460        prox.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
1461                      hiov[i].iov_len);
1462    }
1463
1464    int result = writev(sim_fd, hiov, count);
1465
1466    for (size_t i = 0; i < count; ++i)
1467        delete [] (char *)hiov[i].iov_base;
1468
1469    if (result < 0)
1470        return -errno;
1471
1472    return result;
1473}
1474
1475/// Real mmap handler.
1476template <class OS>
1477SyscallReturn
1478mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
1479         bool is_mmap2)
1480{
1481    int index = 0;
1482    Addr start = p->getSyscallArg(tc, index);
1483    uint64_t length = p->getSyscallArg(tc, index);
1484    int prot = p->getSyscallArg(tc, index);
1485    int tgt_flags = p->getSyscallArg(tc, index);
1486    int tgt_fd = p->getSyscallArg(tc, index);
1487    int offset = p->getSyscallArg(tc, index);
1488
1489    if (is_mmap2)
1490        offset *= TheISA::PageBytes;
1491
1492    if (start & (TheISA::PageBytes - 1) ||
1493        offset & (TheISA::PageBytes - 1) ||
1494        (tgt_flags & OS::TGT_MAP_PRIVATE &&
1495         tgt_flags & OS::TGT_MAP_SHARED) ||
1496        (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1497         !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1498        !length) {
1499        return -EINVAL;
1500    }
1501
1502    if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1503        // With shared mmaps, there are two cases to consider:
1504        // 1) anonymous: writes should modify the mapping and this should be
1505        // visible to observers who share the mapping. Currently, it's
1506        // difficult to update the shared mapping because there's no
1507        // structure which maintains information about the which virtual
1508        // memory areas are shared. If that structure existed, it would be
1509        // possible to make the translations point to the same frames.
1510        // 2) file-backed: writes should modify the mapping and the file
1511        // which is backed by the mapping. The shared mapping problem is the
1512        // same as what was mentioned about the anonymous mappings. For
1513        // file-backed mappings, the writes to the file are difficult
1514        // because it requires syncing what the mapping holds with the file
1515        // that resides on the host system. So, any write on a real system
1516        // would cause the change to be propagated to the file mapping at
1517        // some point in the future (the inode is tracked along with the
1518        // mapping). This isn't guaranteed to always happen, but it usually
1519        // works well enough. The guarantee is provided by the msync system
1520        // call. We could force the change through with shared mappings with
1521        // a call to msync, but that again would require more information
1522        // than we currently maintain.
1523        warn("mmap: writing to shared mmap region is currently "
1524             "unsupported. The write succeeds on the target, but it "
1525             "will not be propagated to the host or shared mappings");
1526    }
1527
1528    length = roundUp(length, TheISA::PageBytes);
1529
1530    int sim_fd = -1;
1531    uint8_t *pmap = nullptr;
1532    if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1533        std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1534
1535        auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1536        if (dfdp) {
1537            EmulatedDriver *emul_driver = dfdp->getDriver();
1538            return emul_driver->mmap(p, tc, start, length, prot,
1539                                     tgt_flags, tgt_fd, offset);
1540        }
1541
1542        auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1543        if (!ffdp)
1544            return -EBADF;
1545        sim_fd = ffdp->getSimFD();
1546
1547        pmap = (decltype(pmap))mmap(nullptr, length, PROT_READ, MAP_PRIVATE,
1548                                    sim_fd, offset);
1549
1550        if (pmap == (decltype(pmap))-1) {
1551            warn("mmap: failed to map file into host address space");
1552            return -errno;
1553        }
1554    }
1555
1556    // Extend global mmap region if necessary. Note that we ignore the
1557    // start address unless MAP_FIXED is specified.
1558    if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1559        std::shared_ptr<MemState> mem_state = p->memState;
1560        Addr mmap_end = mem_state->getMmapEnd();
1561
1562        start = p->mmapGrowsDown() ? mmap_end - length : mmap_end;
1563        mmap_end = p->mmapGrowsDown() ? start : mmap_end + length;
1564
1565        mem_state->setMmapEnd(mmap_end);
1566    }
1567
1568    DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1569                    start, start + length - 1);
1570
1571    // We only allow mappings to overwrite existing mappings if
1572    // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem
1573    // because we ignore the start hint if TGT_MAP_FIXED is not set.
1574    int clobber = tgt_flags & OS::TGT_MAP_FIXED;
1575    if (clobber) {
1576        for (auto tc : p->system->threadContexts) {
1577            // If we might be overwriting old mappings, we need to
1578            // invalidate potentially stale mappings out of the TLBs.
1579            tc->getDTBPtr()->flushAll();
1580            tc->getITBPtr()->flushAll();
1581        }
1582    }
1583
1584    // Allocate physical memory and map it in. If the page table is already
1585    // mapped and clobber is not set, the simulator will issue throw a
1586    // fatal and bail out of the simulation.
1587    p->allocateMem(start, length, clobber);
1588
1589    // Transfer content into target address space.
1590    SETranslatingPortProxy &tp = tc->getMemProxy();
1591    if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1592        // In general, we should zero the mapped area for anonymous mappings,
1593        // with something like:
1594        //     tp.memsetBlob(start, 0, length);
1595        // However, given that we don't support sparse mappings, and
1596        // some applications can map a couple of gigabytes of space
1597        // (intending sparse usage), that can get painfully expensive.
1598        // Fortunately, since we don't properly implement munmap either,
1599        // there's no danger of remapping used memory, so for now all
1600        // newly mapped memory should already be zeroed so we can skip it.
1601    } else {
1602        // It is possible to mmap an area larger than a file, however
1603        // accessing unmapped portions the system triggers a "Bus error"
1604        // on the host. We must know when to stop copying the file from
1605        // the host into the target address space.
1606        struct stat file_stat;
1607        if (fstat(sim_fd, &file_stat) > 0)
1608            fatal("mmap: cannot stat file");
1609
1610        // Copy the portion of the file that is resident. This requires
1611        // checking both the mmap size and the filesize that we are
1612        // trying to mmap into this space; the mmap size also depends
1613        // on the specified offset into the file.
1614        uint64_t size = std::min((uint64_t)file_stat.st_size - offset,
1615                                 length);
1616        tp.writeBlob(start, pmap, size);
1617
1618        // Cleanup the mmap region before exiting this function.
1619        munmap(pmap, length);
1620
1621        // Maintain the symbol table for dynamic executables.
1622        // The loader will call mmap to map the images into its address
1623        // space and we intercept that here. We can verify that we are
1624        // executing inside the loader by checking the program counter value.
1625        // XXX: with multiprogrammed workloads or multi-node configurations,
1626        // this will not work since there is a single global symbol table.
1627        ObjectFile *interpreter = p->getInterpreter();
1628        if (interpreter) {
1629            Addr text_start = interpreter->textBase();
1630            Addr text_end = text_start + interpreter->textSize();
1631
1632            Addr pc = tc->pcState().pc();
1633
1634            if (pc >= text_start && pc < text_end) {
1635                std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1636                auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1637                ObjectFile *lib = createObjectFile(ffdp->getFileName());
1638
1639                if (lib) {
1640                    lib->loadAllSymbols(debugSymbolTable,
1641                                        lib->textBase(), start);
1642                }
1643            }
1644        }
1645
1646        // Note that we do not zero out the remainder of the mapping. This
1647        // is done by a real system, but it probably will not affect
1648        // execution (hopefully).
1649    }
1650
1651    return start;
1652}
1653
1654template <class OS>
1655SyscallReturn
1656pwrite64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1657{
1658    int index = 0;
1659    int tgt_fd = p->getSyscallArg(tc, index);
1660    Addr bufPtr = p->getSyscallArg(tc, index);
1661    int nbytes = p->getSyscallArg(tc, index);
1662    int offset = p->getSyscallArg(tc, index);
1663
1664    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1665    if (!ffdp)
1666        return -EBADF;
1667    int sim_fd = ffdp->getSimFD();
1668
1669    BufferArg bufArg(bufPtr, nbytes);
1670    bufArg.copyIn(tc->getMemProxy());
1671
1672    int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1673
1674    return (bytes_written == -1) ? -errno : bytes_written;
1675}
1676
1677/// Target mmap() handler.
1678template <class OS>
1679SyscallReturn
1680mmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1681{
1682    return mmapImpl<OS>(desc, num, p, tc, false);
1683}
1684
1685/// Target mmap2() handler.
1686template <class OS>
1687SyscallReturn
1688mmap2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1689{
1690    return mmapImpl<OS>(desc, num, p, tc, true);
1691}
1692
1693/// Target getrlimit() handler.
1694template <class OS>
1695SyscallReturn
1696getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
1697              ThreadContext *tc)
1698{
1699    int index = 0;
1700    unsigned resource = process->getSyscallArg(tc, index);
1701    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
1702
1703    switch (resource) {
1704      case OS::TGT_RLIMIT_STACK:
1705        // max stack size in bytes: make up a number (8MB for now)
1706        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1707        rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1708        rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1709        break;
1710
1711      case OS::TGT_RLIMIT_DATA:
1712        // max data segment size in bytes: make up a number
1713        rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1714        rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1715        rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1716        break;
1717
1718      default:
1719        warn("getrlimit: unimplemented resource %d", resource);
1720        return -EINVAL;
1721        break;
1722    }
1723
1724    rlp.copyOut(tc->getMemProxy());
1725    return 0;
1726}
1727
1728template <class OS>
1729SyscallReturn
1730prlimitFunc(SyscallDesc *desc, int callnum, Process *process,
1731            ThreadContext *tc)
1732{
1733    int index = 0;
1734    if (process->getSyscallArg(tc, index) != 0)
1735    {
1736        warn("prlimit: ignoring rlimits for nonzero pid");
1737        return -EPERM;
1738    }
1739    int resource = process->getSyscallArg(tc, index);
1740    Addr n = process->getSyscallArg(tc, index);
1741    if (n != 0)
1742        warn("prlimit: ignoring new rlimit");
1743    Addr o = process->getSyscallArg(tc, index);
1744    if (o != 0)
1745    {
1746        TypedBufferArg<typename OS::rlimit> rlp(o);
1747        switch (resource) {
1748          case OS::TGT_RLIMIT_STACK:
1749            // max stack size in bytes: make up a number (8MB for now)
1750            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1751            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1752            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1753            break;
1754          case OS::TGT_RLIMIT_DATA:
1755            // max data segment size in bytes: make up a number
1756            rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1757            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
1758            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1759            break;
1760          default:
1761            warn("prlimit: unimplemented resource %d", resource);
1762            return -EINVAL;
1763            break;
1764        }
1765        rlp.copyOut(tc->getMemProxy());
1766    }
1767    return 0;
1768}
1769
1770/// Target clock_gettime() function.
1771template <class OS>
1772SyscallReturn
1773clock_gettimeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1774{
1775    int index = 1;
1776    //int clk_id = p->getSyscallArg(tc, index);
1777    TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index));
1778
1779    getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1780    tp->tv_sec += seconds_since_epoch;
1781    tp->tv_sec = TheISA::htog(tp->tv_sec);
1782    tp->tv_nsec = TheISA::htog(tp->tv_nsec);
1783
1784    tp.copyOut(tc->getMemProxy());
1785
1786    return 0;
1787}
1788
1789/// Target clock_getres() function.
1790template <class OS>
1791SyscallReturn
1792clock_getresFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1793{
1794    int index = 1;
1795    TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index));
1796
1797    // Set resolution at ns, which is what clock_gettime() returns
1798    tp->tv_sec = 0;
1799    tp->tv_nsec = 1;
1800
1801    tp.copyOut(tc->getMemProxy());
1802
1803    return 0;
1804}
1805
1806/// Target gettimeofday() handler.
1807template <class OS>
1808SyscallReturn
1809gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
1810                 ThreadContext *tc)
1811{
1812    int index = 0;
1813    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
1814
1815    getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1816    tp->tv_sec += seconds_since_epoch;
1817    tp->tv_sec = TheISA::htog(tp->tv_sec);
1818    tp->tv_usec = TheISA::htog(tp->tv_usec);
1819
1820    tp.copyOut(tc->getMemProxy());
1821
1822    return 0;
1823}
1824
1825
1826/// Target utimes() handler.
1827template <class OS>
1828SyscallReturn
1829utimesFunc(SyscallDesc *desc, int callnum, Process *process,
1830           ThreadContext *tc)
1831{
1832    std::string path;
1833
1834    int index = 0;
1835    if (!tc->getMemProxy().tryReadString(path,
1836                process->getSyscallArg(tc, index))) {
1837        return -EFAULT;
1838    }
1839
1840    TypedBufferArg<typename OS::timeval [2]>
1841        tp(process->getSyscallArg(tc, index));
1842    tp.copyIn(tc->getMemProxy());
1843
1844    struct timeval hostTimeval[2];
1845    for (int i = 0; i < 2; ++i) {
1846        hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
1847        hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
1848    }
1849
1850    // Adjust path for current working directory
1851    path = process->fullPath(path);
1852
1853    int result = utimes(path.c_str(), hostTimeval);
1854
1855    if (result < 0)
1856        return -errno;
1857
1858    return 0;
1859}
1860
1861template <class OS>
1862SyscallReturn
1863execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1864{
1865    desc->setFlags(0);
1866
1867    int index = 0;
1868    std::string path;
1869    SETranslatingPortProxy & mem_proxy = tc->getMemProxy();
1870    if (!mem_proxy.tryReadString(path, p->getSyscallArg(tc, index)))
1871        return -EFAULT;
1872
1873    if (access(path.c_str(), F_OK) == -1)
1874        return -EACCES;
1875
1876    auto read_in = [](std::vector<std::string> & vect,
1877                      SETranslatingPortProxy & mem_proxy,
1878                      Addr mem_loc)
1879    {
1880        for (int inc = 0; ; inc++) {
1881            BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
1882            b.copyIn(mem_proxy);
1883
1884            if (!*(Addr*)b.bufferPtr())
1885                break;
1886
1887            vect.push_back(std::string());
1888            mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
1889        }
1890    };
1891
1892    /**
1893     * Note that ProcessParams is generated by swig and there are no other
1894     * examples of how to create anything but this default constructor. The
1895     * fields are manually initialized instead of passing parameters to the
1896     * constructor.
1897     */
1898    ProcessParams *pp = new ProcessParams();
1899    pp->executable = path;
1900    Addr argv_mem_loc = p->getSyscallArg(tc, index);
1901    read_in(pp->cmd, mem_proxy, argv_mem_loc);
1902    Addr envp_mem_loc = p->getSyscallArg(tc, index);
1903    read_in(pp->env, mem_proxy, envp_mem_loc);
1904    pp->uid = p->uid();
1905    pp->egid = p->egid();
1906    pp->euid = p->euid();
1907    pp->gid = p->gid();
1908    pp->ppid = p->ppid();
1909    pp->pid = p->pid();
1910    pp->input.assign("cin");
1911    pp->output.assign("cout");
1912    pp->errout.assign("cerr");
1913    pp->cwd.assign(p->getcwd());
1914    pp->system = p->system;
1915    /**
1916     * Prevent process object creation with identical PIDs (which will trip
1917     * a fatal check in Process constructor). The execve call is supposed to
1918     * take over the currently executing process' identity but replace
1919     * whatever it is doing with a new process image. Instead of hijacking
1920     * the process object in the simulator, we create a new process object
1921     * and bind to the previous process' thread below (hijacking the thread).
1922     */
1923    p->system->PIDs.erase(p->pid());
1924    Process *new_p = pp->create();
1925    delete pp;
1926
1927    /**
1928     * Work through the file descriptor array and close any files marked
1929     * close-on-exec.
1930     */
1931    new_p->fds = p->fds;
1932    for (int i = 0; i < new_p->fds->getSize(); i++) {
1933        std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
1934        if (fdep && fdep->getCOE())
1935            new_p->fds->closeFDEntry(i);
1936    }
1937
1938    *new_p->sigchld = true;
1939
1940    delete p;
1941    tc->clearArchRegs();
1942    tc->setProcessPtr(new_p);
1943    new_p->assignThreadContext(tc->contextId());
1944    new_p->initState();
1945    tc->activate();
1946    TheISA::PCState pcState = tc->pcState();
1947    tc->setNPC(pcState.instAddr());
1948
1949    desc->setFlags(SyscallDesc::SuppressReturnValue);
1950    return 0;
1951}
1952
1953/// Target getrusage() function.
1954template <class OS>
1955SyscallReturn
1956getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
1957              ThreadContext *tc)
1958{
1959    int index = 0;
1960    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
1961    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
1962
1963    rup->ru_utime.tv_sec = 0;
1964    rup->ru_utime.tv_usec = 0;
1965    rup->ru_stime.tv_sec = 0;
1966    rup->ru_stime.tv_usec = 0;
1967    rup->ru_maxrss = 0;
1968    rup->ru_ixrss = 0;
1969    rup->ru_idrss = 0;
1970    rup->ru_isrss = 0;
1971    rup->ru_minflt = 0;
1972    rup->ru_majflt = 0;
1973    rup->ru_nswap = 0;
1974    rup->ru_inblock = 0;
1975    rup->ru_oublock = 0;
1976    rup->ru_msgsnd = 0;
1977    rup->ru_msgrcv = 0;
1978    rup->ru_nsignals = 0;
1979    rup->ru_nvcsw = 0;
1980    rup->ru_nivcsw = 0;
1981
1982    switch (who) {
1983      case OS::TGT_RUSAGE_SELF:
1984        getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
1985        rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
1986        rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
1987        break;
1988
1989      case OS::TGT_RUSAGE_CHILDREN:
1990        // do nothing.  We have no child processes, so they take no time.
1991        break;
1992
1993      default:
1994        // don't really handle THREAD or CHILDREN, but just warn and
1995        // plow ahead
1996        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
1997             who);
1998    }
1999
2000    rup.copyOut(tc->getMemProxy());
2001
2002    return 0;
2003}
2004
2005/// Target times() function.
2006template <class OS>
2007SyscallReturn
2008timesFunc(SyscallDesc *desc, int callnum, Process *process,
2009          ThreadContext *tc)
2010{
2011    int index = 0;
2012    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
2013
2014    // Fill in the time structure (in clocks)
2015    int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
2016    bufp->tms_utime = clocks;
2017    bufp->tms_stime = 0;
2018    bufp->tms_cutime = 0;
2019    bufp->tms_cstime = 0;
2020
2021    // Convert to host endianness
2022    bufp->tms_utime = TheISA::htog(bufp->tms_utime);
2023
2024    // Write back
2025    bufp.copyOut(tc->getMemProxy());
2026
2027    // Return clock ticks since system boot
2028    return clocks;
2029}
2030
2031/// Target time() function.
2032template <class OS>
2033SyscallReturn
2034timeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
2035{
2036    typename OS::time_t sec, usec;
2037    getElapsedTimeMicro(sec, usec);
2038    sec += seconds_since_epoch;
2039
2040    int index = 0;
2041    Addr taddr = (Addr)process->getSyscallArg(tc, index);
2042    if (taddr != 0) {
2043        typename OS::time_t t = sec;
2044        t = TheISA::htog(t);
2045        SETranslatingPortProxy &p = tc->getMemProxy();
2046        p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
2047    }
2048    return sec;
2049}
2050
2051template <class OS>
2052SyscallReturn
2053tgkillFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
2054{
2055    int index = 0;
2056    int tgid = process->getSyscallArg(tc, index);
2057    int tid = process->getSyscallArg(tc, index);
2058    int sig = process->getSyscallArg(tc, index);
2059
2060    /**
2061     * This system call is intended to allow killing a specific thread
2062     * within an arbitrary thread group if sanctioned with permission checks.
2063     * It's usually true that threads share the termination signal as pointed
2064     * out by the pthread_kill man page and this seems to be the intended
2065     * usage. Due to this being an emulated environment, assume the following:
2066     * Threads are allowed to call tgkill because the EUID for all threads
2067     * should be the same. There is no signal handling mechanism for kernel
2068     * registration of signal handlers since signals are poorly supported in
2069     * emulation mode. Since signal handlers cannot be registered, all
2070     * threads within in a thread group must share the termination signal.
2071     * We never exhaust PIDs so there's no chance of finding the wrong one
2072     * due to PID rollover.
2073     */
2074
2075    System *sys = tc->getSystemPtr();
2076    Process *tgt_proc = nullptr;
2077    for (int i = 0; i < sys->numContexts(); i++) {
2078        Process *temp = sys->threadContexts[i]->getProcessPtr();
2079        if (temp->pid() == tid) {
2080            tgt_proc = temp;
2081            break;
2082        }
2083    }
2084
2085    if (sig != 0 || sig != OS::TGT_SIGABRT)
2086        return -EINVAL;
2087
2088    if (tgt_proc == nullptr)
2089        return -ESRCH;
2090
2091    if (tgid != -1 && tgt_proc->tgid() != tgid)
2092        return -ESRCH;
2093
2094    if (sig == OS::TGT_SIGABRT)
2095        exitGroupFunc(desc, 252, process, tc);
2096
2097    return 0;
2098}
2099
2100template <class OS>
2101SyscallReturn
2102socketFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2103{
2104    int index = 0;
2105    int domain = p->getSyscallArg(tc, index);
2106    int type = p->getSyscallArg(tc, index);
2107    int prot = p->getSyscallArg(tc, index);
2108
2109    int sim_fd = socket(domain, type, prot);
2110    if (sim_fd == -1)
2111        return -errno;
2112
2113    auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2114    int tgt_fd = p->fds->allocFD(sfdp);
2115
2116    return tgt_fd;
2117}
2118
2119template <class OS>
2120SyscallReturn
2121socketpairFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2122{
2123    int index = 0;
2124    int domain = p->getSyscallArg(tc, index);
2125    int type = p->getSyscallArg(tc, index);
2126    int prot = p->getSyscallArg(tc, index);
2127    Addr svPtr = p->getSyscallArg(tc, index);
2128
2129    BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2130    int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2131    if (status == -1)
2132        return -errno;
2133
2134    int *fds = (int *)svBuf.bufferPtr();
2135
2136    auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2137    fds[0] = p->fds->allocFD(sfdp1);
2138    auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2139    fds[1] = p->fds->allocFD(sfdp2);
2140    svBuf.copyOut(tc->getMemProxy());
2141
2142    return status;
2143}
2144
2145#endif // __SIM_SYSCALL_EMUL_HH__
2146