syscall_emul.hh revision 2764
17405SAli.Saidi@ARM.com/*
212667Schuan.zhu@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
37405SAli.Saidi@ARM.com * All rights reserved.
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147405SAli.Saidi@ARM.com * this software without specific prior written permission.
157405SAli.Saidi@ARM.com *
167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277405SAli.Saidi@ARM.com *
287405SAli.Saidi@ARM.com * Authors: Steve Reinhardt
297405SAli.Saidi@ARM.com *          Kevin Lim
307405SAli.Saidi@ARM.com *          Korey Sewell
317405SAli.Saidi@ARM.com */
327405SAli.Saidi@ARM.com
337405SAli.Saidi@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__
347405SAli.Saidi@ARM.com#define __SIM_SYSCALL_EMUL_HH__
357405SAli.Saidi@ARM.com
367405SAli.Saidi@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
377405SAli.Saidi@ARM.com                   defined(__FreeBSD__) || defined(__CYGWIN__))
387405SAli.Saidi@ARM.com
397405SAli.Saidi@ARM.com///
407405SAli.Saidi@ARM.com/// @file syscall_emul.hh
417405SAli.Saidi@ARM.com///
4210461SAndreas.Sandberg@ARM.com/// This file defines objects used to emulate syscalls from the target
439050Schander.sudanthi@arm.com/// application on the host machine.
4412406Sgabeblack@google.com
4512605Sgiacomo.travaglini@arm.com#include <errno.h>
4611793Sbrandon.potter@amd.com#include <string>
478887Sgeoffrey.blake@arm.com#ifdef __CYGWIN32__
488232Snate@binkert.org#include <sys/fcntl.h>	// for O_BINARY
498232Snate@binkert.org#endif
5010844Sandreas.sandberg@arm.com#include <sys/uio.h>
519384SAndreas.Sandberg@arm.com
527678Sgblack@eecs.umich.edu#include "arch/isa_traits.hh"	// for Addr
538059SAli.Saidi@ARM.com#include "base/chunk_generator.hh"
548284SAli.Saidi@ARM.com#include "base/intmath.hh"	// for RoundUp
557405SAli.Saidi@ARM.com#include "base/misc.hh"
567405SAli.Saidi@ARM.com#include "base/trace.hh"
577405SAli.Saidi@ARM.com#include "cpu/base.hh"
587405SAli.Saidi@ARM.com#include "cpu/thread_context.hh"
599384SAndreas.Sandberg@arm.com#include "mem/translating_port.hh"
6010461SAndreas.Sandberg@ARM.com#include "mem/page_table.hh"
6110461SAndreas.Sandberg@ARM.com#include "sim/process.hh"
6211165SRekai.GonzalezAlberquilla@arm.com
6312109SRekai.GonzalezAlberquilla@arm.com///
6412714Sgiacomo.travaglini@arm.com/// System call descriptor.
6512714Sgiacomo.travaglini@arm.com///
669384SAndreas.Sandberg@arm.comclass SyscallDesc {
6711770SCurtis.Dunham@arm.com
6810037SARM gem5 Developers  public:
6910461SAndreas.Sandberg@ARM.com
7010461SAndreas.Sandberg@ARM.com    /// Typedef for target syscall handler functions.
7110461SAndreas.Sandberg@ARM.com    typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
7210461SAndreas.Sandberg@ARM.com                           Process *, ThreadContext *);
7310461SAndreas.Sandberg@ARM.com
7410461SAndreas.Sandberg@ARM.com    const char *name;	//!< Syscall name (e.g., "open").
7510609Sandreas.sandberg@arm.com    FuncPtr funcPtr;	//!< Pointer to emulation function.
7610609Sandreas.sandberg@arm.com    int flags;		//!< Flags (see Flags enum).
7710609Sandreas.sandberg@arm.com
7810037SARM gem5 Developers    /// Flag values for controlling syscall behavior.
7910037SARM gem5 Developers    enum Flags {
8010037SARM gem5 Developers        /// Don't set return regs according to funcPtr return value.
8110037SARM gem5 Developers        /// Used for syscalls with non-standard return conventions
8211771SCurtis.Dunham@arm.com        /// that explicitly set the ThreadContext regs (e.g.,
8310037SARM gem5 Developers        /// sigreturn).
8410037SARM gem5 Developers        SuppressReturnValue = 1
8513173Sgiacomo.travaglini@arm.com    };
8610037SARM gem5 Developers
8710037SARM gem5 Developers    /// Constructor.
8813114Sgiacomo.travaglini@arm.com    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
8910037SARM gem5 Developers        : name(_name), funcPtr(_funcPtr), flags(_flags)
9011771SCurtis.Dunham@arm.com    {
9110037SARM gem5 Developers    }
9213173Sgiacomo.travaglini@arm.com
9310037SARM gem5 Developers    /// Emulate the syscall.  Public interface for calling through funcPtr.
9413114Sgiacomo.travaglini@arm.com    void doSyscall(int callnum, Process *proc, ThreadContext *tc);
9510037SARM gem5 Developers};
9610037SARM gem5 Developers
9712477SCurtis.Dunham@arm.com
9810037SARM gem5 Developersclass BaseBufferArg {
9910037SARM gem5 Developers
1009384SAndreas.Sandberg@arm.com  public:
1019384SAndreas.Sandberg@arm.com
1029384SAndreas.Sandberg@arm.com    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
10312479SCurtis.Dunham@arm.com    {
10412479SCurtis.Dunham@arm.com        bufPtr = new uint8_t[size];
1059384SAndreas.Sandberg@arm.com        // clear out buffer: in case we only partially populate this,
1069384SAndreas.Sandberg@arm.com        // and then do a copyOut(), we want to make sure we don't
1079384SAndreas.Sandberg@arm.com        // introduce any random junk into the simulated address space
1089384SAndreas.Sandberg@arm.com        memset(bufPtr, 0, size);
1099384SAndreas.Sandberg@arm.com    }
1109384SAndreas.Sandberg@arm.com
1117427Sgblack@eecs.umich.edu    virtual ~BaseBufferArg() { delete [] bufPtr; }
1127427Sgblack@eecs.umich.edu
1137427Sgblack@eecs.umich.edu    //
1149385SAndreas.Sandberg@arm.com    // copy data into simulator space (read from target memory)
1159385SAndreas.Sandberg@arm.com    //
1167427Sgblack@eecs.umich.edu    virtual bool copyIn(TranslatingPort *memport)
1177427Sgblack@eecs.umich.edu    {
11810037SARM gem5 Developers        memport->readBlob(addr, bufPtr, size);
11913114Sgiacomo.travaglini@arm.com        return true;	// no EFAULT detection for now
12010037SARM gem5 Developers    }
12113114Sgiacomo.travaglini@arm.com
12213114Sgiacomo.travaglini@arm.com    //
12313114Sgiacomo.travaglini@arm.com    // copy data out of simulator space (write to target memory)
12413114Sgiacomo.travaglini@arm.com    //
12513114Sgiacomo.travaglini@arm.com    virtual bool copyOut(TranslatingPort *memport)
12612690Sgiacomo.travaglini@arm.com    {
12710037SARM gem5 Developers        memport->writeBlob(addr, bufPtr, size);
1287427Sgblack@eecs.umich.edu        return true;	// no EFAULT detection for now
1297427Sgblack@eecs.umich.edu    }
13010037SARM gem5 Developers
1317427Sgblack@eecs.umich.edu  protected:
1327427Sgblack@eecs.umich.edu    Addr addr;
1337427Sgblack@eecs.umich.edu    int size;
1347427Sgblack@eecs.umich.edu    uint8_t *bufPtr;
1357427Sgblack@eecs.umich.edu};
1367427Sgblack@eecs.umich.edu
1377427Sgblack@eecs.umich.edu
1387427Sgblack@eecs.umich.educlass BufferArg : public BaseBufferArg
1397427Sgblack@eecs.umich.edu{
1407427Sgblack@eecs.umich.edu  public:
1417427Sgblack@eecs.umich.edu    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1427427Sgblack@eecs.umich.edu    void *bufferPtr()	{ return bufPtr; }
1437427Sgblack@eecs.umich.edu};
1447427Sgblack@eecs.umich.edu
1457427Sgblack@eecs.umich.edutemplate <class T>
1467427Sgblack@eecs.umich.educlass TypedBufferArg : public BaseBufferArg
1477427Sgblack@eecs.umich.edu{
1487427Sgblack@eecs.umich.edu  public:
1497427Sgblack@eecs.umich.edu    // user can optionally specify a specific number of bytes to
1507427Sgblack@eecs.umich.edu    // allocate to deal with those structs that have variable-size
1517427Sgblack@eecs.umich.edu    // arrays at the end
1527427Sgblack@eecs.umich.edu    TypedBufferArg(Addr _addr, int _size = sizeof(T))
1537427Sgblack@eecs.umich.edu        : BaseBufferArg(_addr, _size)
1547436Sdam.sunwoo@arm.com    { }
1557436Sdam.sunwoo@arm.com
15610037SARM gem5 Developers    // type case
15710037SARM gem5 Developers    operator T*() { return (T *)bufPtr; }
1587436Sdam.sunwoo@arm.com
1597436Sdam.sunwoo@arm.com    // dereference operators
1607436Sdam.sunwoo@arm.com    T &operator*()	 { return *((T *)bufPtr); }
1617436Sdam.sunwoo@arm.com    T* operator->()	 { return (T *)bufPtr; }
1627436Sdam.sunwoo@arm.com    T &operator[](int i) { return ((T *)bufPtr)[i]; }
1637436Sdam.sunwoo@arm.com};
1647436Sdam.sunwoo@arm.com
1657436Sdam.sunwoo@arm.com//////////////////////////////////////////////////////////////////////
1667436Sdam.sunwoo@arm.com//
1677436Sdam.sunwoo@arm.com// The following emulation functions are generic enough that they
1687436Sdam.sunwoo@arm.com// don't need to be recompiled for different emulated OS's.  They are
1697436Sdam.sunwoo@arm.com// defined in sim/syscall_emul.cc.
17013393Sgiacomo.travaglini@arm.com//
17110037SARM gem5 Developers//////////////////////////////////////////////////////////////////////
1727436Sdam.sunwoo@arm.com
1737436Sdam.sunwoo@arm.com
1747436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we haven't thought about.
1757436Sdam.sunwoo@arm.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
1767436Sdam.sunwoo@arm.com                                Process *p, ThreadContext *tc);
1777436Sdam.sunwoo@arm.com
1787436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we never intend to
1797436Sdam.sunwoo@arm.com/// implement (signal handling, etc.) and should not affect the correct
1807436Sdam.sunwoo@arm.com/// behavior of the program.  Print a warning only if the appropriate
1817436Sdam.sunwoo@arm.com/// trace flag is enabled.  Return success to the target program.
1827436Sdam.sunwoo@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num,
1837436Sdam.sunwoo@arm.com                         Process *p, ThreadContext *tc);
1847436Sdam.sunwoo@arm.com
1857436Sdam.sunwoo@arm.com/// Target exit() handler: terminate simulation.
1867436Sdam.sunwoo@arm.comSyscallReturn exitFunc(SyscallDesc *desc, int num,
1877436Sdam.sunwoo@arm.com                       Process *p, ThreadContext *tc);
18813393Sgiacomo.travaglini@arm.com
18913393Sgiacomo.travaglini@arm.com/// Target getpagesize() handler.
19013393Sgiacomo.travaglini@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
19113393Sgiacomo.travaglini@arm.com                              Process *p, ThreadContext *tc);
19213393Sgiacomo.travaglini@arm.com
19313393Sgiacomo.travaglini@arm.com/// Target obreak() handler: set brk address.
19413393Sgiacomo.travaglini@arm.comSyscallReturn obreakFunc(SyscallDesc *desc, int num,
19513393Sgiacomo.travaglini@arm.com                         Process *p, ThreadContext *tc);
19613393Sgiacomo.travaglini@arm.com
19713393Sgiacomo.travaglini@arm.com/// Target close() handler.
19813393Sgiacomo.travaglini@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num,
19913393Sgiacomo.travaglini@arm.com                        Process *p, ThreadContext *tc);
20013393Sgiacomo.travaglini@arm.com
20113393Sgiacomo.travaglini@arm.com/// Target read() handler.
20213393Sgiacomo.travaglini@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num,
20313393Sgiacomo.travaglini@arm.com                       Process *p, ThreadContext *tc);
20413396Sgiacomo.travaglini@arm.com
20513396Sgiacomo.travaglini@arm.com/// Target write() handler.
20613396Sgiacomo.travaglini@arm.comSyscallReturn writeFunc(SyscallDesc *desc, int num,
20713396Sgiacomo.travaglini@arm.com                        Process *p, ThreadContext *tc);
20813393Sgiacomo.travaglini@arm.com
20913393Sgiacomo.travaglini@arm.com/// Target lseek() handler.
21013393Sgiacomo.travaglini@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num,
21113393Sgiacomo.travaglini@arm.com                        Process *p, ThreadContext *tc);
21213393Sgiacomo.travaglini@arm.com
21313393Sgiacomo.travaglini@arm.com/// Target munmap() handler.
21413393Sgiacomo.travaglini@arm.comSyscallReturn munmapFunc(SyscallDesc *desc, int num,
21513393Sgiacomo.travaglini@arm.com                         Process *p, ThreadContext *tc);
21613393Sgiacomo.travaglini@arm.com
21713393Sgiacomo.travaglini@arm.com/// Target gethostname() handler.
21813393Sgiacomo.travaglini@arm.comSyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
21913393Sgiacomo.travaglini@arm.com                              Process *p, ThreadContext *tc);
22013393Sgiacomo.travaglini@arm.com
22113393Sgiacomo.travaglini@arm.com/// Target unlink() handler.
22213393Sgiacomo.travaglini@arm.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num,
22313393Sgiacomo.travaglini@arm.com                         Process *p, ThreadContext *tc);
22413393Sgiacomo.travaglini@arm.com
22513393Sgiacomo.travaglini@arm.com/// Target rename() handler.
2267644Sali.saidi@arm.comSyscallReturn renameFunc(SyscallDesc *desc, int num,
2278147SAli.Saidi@ARM.com                         Process *p, ThreadContext *tc);
2289385SAndreas.Sandberg@arm.com
2299385SAndreas.Sandberg@arm.com
23010037SARM gem5 Developers/// Target truncate() handler.
23110037SARM gem5 DevelopersSyscallReturn truncateFunc(SyscallDesc *desc, int num,
23210037SARM gem5 Developers                           Process *p, ThreadContext *tc);
23310037SARM gem5 Developers
23410037SARM gem5 Developers
23510037SARM gem5 Developers/// Target ftruncate() handler.
23610037SARM gem5 DevelopersSyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
23710037SARM gem5 Developers                            Process *p, ThreadContext *tc);
23810037SARM gem5 Developers
23910037SARM gem5 Developers
24010037SARM gem5 Developers/// Target chown() handler.
24110037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num,
24210037SARM gem5 Developers                        Process *p, ThreadContext *tc);
24310037SARM gem5 Developers
24410037SARM gem5 Developers
24510037SARM gem5 Developers/// Target fchown() handler.
2468147SAli.Saidi@ARM.comSyscallReturn fchownFunc(SyscallDesc *desc, int num,
2477427Sgblack@eecs.umich.edu                         Process *p, ThreadContext *tc);
2487427Sgblack@eecs.umich.edu
2497427Sgblack@eecs.umich.edu/// Target fnctl() handler.
25010037SARM gem5 DevelopersSyscallReturn fcntlFunc(SyscallDesc *desc, int num,
25110037SARM gem5 Developers                        Process *process, ThreadContext *tc);
25210037SARM gem5 Developers
25310037SARM gem5 Developers/// Target fcntl64() handler.
25413396Sgiacomo.travaglini@arm.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num,
25510037SARM gem5 Developers                        Process *process, ThreadContext *tc);
25610037SARM gem5 Developers
25710037SARM gem5 Developers/// Target setuid() handler.
25810037SARM gem5 DevelopersSyscallReturn setuidFunc(SyscallDesc *desc, int num,
25910037SARM gem5 Developers                               Process *p, ThreadContext *tc);
26010037SARM gem5 Developers
26110037SARM gem5 Developers/// Target getpid() handler.
26210037SARM gem5 DevelopersSyscallReturn getpidFunc(SyscallDesc *desc, int num,
26310037SARM gem5 Developers                               Process *p, ThreadContext *tc);
26410037SARM gem5 Developers
26510037SARM gem5 Developers/// Target getuid() handler.
26610037SARM gem5 DevelopersSyscallReturn getuidFunc(SyscallDesc *desc, int num,
26710037SARM gem5 Developers                               Process *p, ThreadContext *tc);
26810037SARM gem5 Developers
26910037SARM gem5 Developers/// Target getgid() handler.
27010037SARM gem5 DevelopersSyscallReturn getgidFunc(SyscallDesc *desc, int num,
27110037SARM gem5 Developers                               Process *p, ThreadContext *tc);
27210037SARM gem5 Developers
27310037SARM gem5 Developers/// Target getppid() handler.
27410037SARM gem5 DevelopersSyscallReturn getppidFunc(SyscallDesc *desc, int num,
27510037SARM gem5 Developers                               Process *p, ThreadContext *tc);
27610037SARM gem5 Developers
27710037SARM gem5 Developers/// Target geteuid() handler.
27810037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num,
27910037SARM gem5 Developers                               Process *p, ThreadContext *tc);
28010037SARM gem5 Developers
28110037SARM gem5 Developers/// Target getegid() handler.
28210037SARM gem5 DevelopersSyscallReturn getegidFunc(SyscallDesc *desc, int num,
28310037SARM gem5 Developers                               Process *p, ThreadContext *tc);
28410037SARM gem5 Developers
28510037SARM gem5 Developers
28611770SCurtis.Dunham@arm.com
28710037SARM gem5 Developers/// Pseudo Funcs  - These functions use a different return convension,
28811574SCurtis.Dunham@arm.com/// returning a second value in a register other than the normal return register
28911770SCurtis.Dunham@arm.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
29011770SCurtis.Dunham@arm.com                             Process *process, ThreadContext *tc);
29110037SARM gem5 Developers
29211770SCurtis.Dunham@arm.com/// Target getpidPseudo() handler.
29311770SCurtis.Dunham@arm.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
29410037SARM gem5 Developers                               Process *p, ThreadContext *tc);
29510037SARM gem5 Developers
29610037SARM gem5 Developers/// Target getuidPseudo() handler.
29713114Sgiacomo.travaglini@arm.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
29810037SARM gem5 Developers                               Process *p, ThreadContext *tc);
29913114Sgiacomo.travaglini@arm.com
30013114Sgiacomo.travaglini@arm.com/// Target getgidPseudo() handler.
30113114Sgiacomo.travaglini@arm.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
30213114Sgiacomo.travaglini@arm.com                               Process *p, ThreadContext *tc);
30313114Sgiacomo.travaglini@arm.com
30413114Sgiacomo.travaglini@arm.com
30513114Sgiacomo.travaglini@arm.com/// This struct is used to build an target-OS-dependent table that
30613114Sgiacomo.travaglini@arm.com/// maps the target's open() flags to the host open() flags.
30713114Sgiacomo.travaglini@arm.comstruct OpenFlagTransTable {
30813114Sgiacomo.travaglini@arm.com    int tgtFlag;	//!< Target system flag value.
30913114Sgiacomo.travaglini@arm.com    int hostFlag;	//!< Corresponding host system flag value.
31013114Sgiacomo.travaglini@arm.com};
31113114Sgiacomo.travaglini@arm.com
31213114Sgiacomo.travaglini@arm.com
31313114Sgiacomo.travaglini@arm.com
31413114Sgiacomo.travaglini@arm.com/// A readable name for 1,000,000, for converting microseconds to seconds.
31513114Sgiacomo.travaglini@arm.comconst int one_million = 1000000;
31613114Sgiacomo.travaglini@arm.com
31713114Sgiacomo.travaglini@arm.com/// Approximate seconds since the epoch (1/1/1970).  About a billion,
31813114Sgiacomo.travaglini@arm.com/// by my reckoning.  We want to keep this a constant (not use the
31913114Sgiacomo.travaglini@arm.com/// real-world time) to keep simulations repeatable.
32013114Sgiacomo.travaglini@arm.comconst unsigned seconds_since_epoch = 1000000000;
32113114Sgiacomo.travaglini@arm.com
32213114Sgiacomo.travaglini@arm.com/// Helper function to convert current elapsed time to seconds and
32310037SARM gem5 Developers/// microseconds.
32410037SARM gem5 Developerstemplate <class T1, class T2>
32510037SARM gem5 Developersvoid
32610461SAndreas.Sandberg@ARM.comgetElapsedTime(T1 &sec, T2 &usec)
32710461SAndreas.Sandberg@ARM.com{
32810461SAndreas.Sandberg@ARM.com    int elapsed_usecs = curTick / Clock::Int::us;
32910461SAndreas.Sandberg@ARM.com    sec = elapsed_usecs / one_million;
33010037SARM gem5 Developers    usec = elapsed_usecs % one_million;
33110037SARM gem5 Developers}
33210037SARM gem5 Developers
33310037SARM gem5 Developers//////////////////////////////////////////////////////////////////////
33410037SARM gem5 Developers//
33513116Sgiacomo.travaglini@arm.com// The following emulation functions are generic, but need to be
33610037SARM gem5 Developers// templated to account for differences in types, constants, etc.
33710461SAndreas.Sandberg@ARM.com//
33810461SAndreas.Sandberg@ARM.com//////////////////////////////////////////////////////////////////////
33910461SAndreas.Sandberg@ARM.com
34010461SAndreas.Sandberg@ARM.com/// Target ioctl() handler.  For the most part, programs call ioctl()
34110461SAndreas.Sandberg@ARM.com/// only to find out if their stdout is a tty, to determine whether to
34210037SARM gem5 Developers/// do line or block buffering.
34310037SARM gem5 Developerstemplate <class OS>
34410037SARM gem5 DevelopersSyscallReturn
34510037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, Process *process,
34610037SARM gem5 Developers          ThreadContext *tc)
34711574SCurtis.Dunham@arm.com{
34810037SARM gem5 Developers    int fd = tc->getSyscallArg(0);
34910037SARM gem5 Developers    unsigned req = tc->getSyscallArg(1);
35010037SARM gem5 Developers
35111574SCurtis.Dunham@arm.com    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
35210037SARM gem5 Developers
35310037SARM gem5 Developers    if (fd < 0 || process->sim_fd(fd) < 0) {
35410037SARM gem5 Developers        // doesn't map to any simulator fd: not a valid target fd
35510037SARM gem5 Developers        return -EBADF;
35610037SARM gem5 Developers    }
35710037SARM gem5 Developers
35810037SARM gem5 Developers    switch (req) {
35913114Sgiacomo.travaglini@arm.com      case OS::TIOCISATTY:
36013173Sgiacomo.travaglini@arm.com      case OS::TIOCGETP:
36113173Sgiacomo.travaglini@arm.com      case OS::TIOCSETP:
36213173Sgiacomo.travaglini@arm.com      case OS::TIOCSETN:
36313173Sgiacomo.travaglini@arm.com      case OS::TIOCSETC:
36410037SARM gem5 Developers      case OS::TIOCGETC:
36510037SARM gem5 Developers      case OS::TIOCGETS:
36612972Sandreas.sandberg@arm.com      case OS::TIOCGETA:
36712972Sandreas.sandberg@arm.com        return -ENOTTY;
36812972Sandreas.sandberg@arm.com
36912972Sandreas.sandberg@arm.com      default:
37012972Sandreas.sandberg@arm.com        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
37112972Sandreas.sandberg@arm.com              fd, req, tc->readPC());
37212972Sandreas.sandberg@arm.com    }
37312972Sandreas.sandberg@arm.com}
3747405SAli.Saidi@ARM.com
37510035Sandreas.hansson@arm.com/// Target open() handler.
3767405SAli.Saidi@ARM.comtemplate <class OS>
3777405SAli.Saidi@ARM.comSyscallReturn
3787614Sminkyu.jeong@arm.comopenFunc(SyscallDesc *desc, int callnum, Process *process,
37912478SCurtis.Dunham@arm.com         ThreadContext *tc)
38012478SCurtis.Dunham@arm.com{
38112478SCurtis.Dunham@arm.com    std::string path;
38212478SCurtis.Dunham@arm.com
38312478SCurtis.Dunham@arm.com    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
38412478SCurtis.Dunham@arm.com        return -EFAULT;
38512478SCurtis.Dunham@arm.com
38612478SCurtis.Dunham@arm.com    if (path == "/dev/sysdev0") {
38712478SCurtis.Dunham@arm.com        // This is a memory-mapped high-resolution timer device on Alpha.
38812478SCurtis.Dunham@arm.com        // We don't support it, so just punt.
38912478SCurtis.Dunham@arm.com        warn("Ignoring open(%s, ...)\n", path);
39012478SCurtis.Dunham@arm.com        return -ENOENT;
39112478SCurtis.Dunham@arm.com    }
39212478SCurtis.Dunham@arm.com
39312478SCurtis.Dunham@arm.com    int tgtFlags = tc->getSyscallArg(1);
39412478SCurtis.Dunham@arm.com    int mode = tc->getSyscallArg(2);
3957405SAli.Saidi@ARM.com    int hostFlags = 0;
3967405SAli.Saidi@ARM.com
3977405SAli.Saidi@ARM.com    // translate open flags
3987405SAli.Saidi@ARM.com    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
3997405SAli.Saidi@ARM.com        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
4007405SAli.Saidi@ARM.com            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
40110037SARM gem5 Developers            hostFlags |= OS::openFlagTable[i].hostFlag;
40210037SARM gem5 Developers        }
40310037SARM gem5 Developers    }
4049050Schander.sudanthi@arm.com
4057405SAli.Saidi@ARM.com    // any target flags left?
40610037SARM gem5 Developers    if (tgtFlags != 0)
40710037SARM gem5 Developers        warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
4087720Sgblack@eecs.umich.edu
4097720Sgblack@eecs.umich.edu#ifdef __CYGWIN32__
4107405SAli.Saidi@ARM.com    hostFlags |= O_BINARY;
4117405SAli.Saidi@ARM.com#endif
4127757SAli.Saidi@ARM.com
41310037SARM gem5 Developers    DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
41410037SARM gem5 Developers
41510037SARM gem5 Developers    // open the file
41610037SARM gem5 Developers    int fd = open(path.c_str(), hostFlags, mode);
41710037SARM gem5 Developers
41810037SARM gem5 Developers    return (fd == -1) ? -errno : process->alloc_fd(fd);
41910037SARM gem5 Developers}
42010037SARM gem5 Developers
42110037SARM gem5 Developers
42210037SARM gem5 Developers/// Target chmod() handler.
42310037SARM gem5 Developerstemplate <class OS>
42410037SARM gem5 DevelopersSyscallReturn
42510037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, Process *process,
42610037SARM gem5 Developers          ThreadContext *tc)
42710037SARM gem5 Developers{
42810037SARM gem5 Developers    std::string path;
42910037SARM gem5 Developers
43010037SARM gem5 Developers    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
43110037SARM gem5 Developers        return -EFAULT;
43210037SARM gem5 Developers
43310037SARM gem5 Developers    uint32_t mode = tc->getSyscallArg(1);
43410037SARM gem5 Developers    mode_t hostMode = 0;
43510037SARM gem5 Developers
43610037SARM gem5 Developers    // XXX translate mode flags via OS::something???
43710037SARM gem5 Developers    hostMode = mode;
43810037SARM gem5 Developers
43910037SARM gem5 Developers    // do the chmod
44010037SARM gem5 Developers    int result = chmod(path.c_str(), hostMode);
44110037SARM gem5 Developers    if (result < 0)
44210037SARM gem5 Developers        return -errno;
44310037SARM gem5 Developers
44410037SARM gem5 Developers    return 0;
44510037SARM gem5 Developers}
44612667Schuan.zhu@arm.com
44710037SARM gem5 Developers
44810037SARM gem5 Developers/// Target fchmod() handler.
44910037SARM gem5 Developerstemplate <class OS>
45010037SARM gem5 DevelopersSyscallReturn
45110037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, Process *process,
45210037SARM gem5 Developers           ThreadContext *tc)
45310037SARM gem5 Developers{
45410037SARM gem5 Developers    int fd = tc->getSyscallArg(0);
45510037SARM gem5 Developers    if (fd < 0 || process->sim_fd(fd) < 0) {
45610037SARM gem5 Developers        // doesn't map to any simulator fd: not a valid target fd
45710037SARM gem5 Developers        return -EBADF;
45810037SARM gem5 Developers    }
4598284SAli.Saidi@ARM.com
46010037SARM gem5 Developers    uint32_t mode = tc->getSyscallArg(1);
46110037SARM gem5 Developers    mode_t hostMode = 0;
46210037SARM gem5 Developers
46310037SARM gem5 Developers    // XXX translate mode flags via OS::someting???
4649050Schander.sudanthi@arm.com    hostMode = mode;
46510037SARM gem5 Developers
46610037SARM gem5 Developers    // do the fchmod
46710037SARM gem5 Developers    int result = fchmod(process->sim_fd(fd), hostMode);
46810037SARM gem5 Developers    if (result < 0)
46910037SARM gem5 Developers        return -errno;
47010037SARM gem5 Developers
47110037SARM gem5 Developers    return 0;
47210037SARM gem5 Developers}
47310037SARM gem5 Developers
47410037SARM gem5 Developers
47510037SARM gem5 Developers/// Target stat() handler.
47610037SARM gem5 Developerstemplate <class OS>
47710037SARM gem5 DevelopersSyscallReturn
47810037SARM gem5 DevelopersstatFunc(SyscallDesc *desc, int callnum, Process *process,
47910037SARM gem5 Developers         ThreadContext *tc)
48010037SARM gem5 Developers{
48110037SARM gem5 Developers    std::string path;
48210037SARM gem5 Developers
4839050Schander.sudanthi@arm.com    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
4848284SAli.Saidi@ARM.com    return -EFAULT;
48510037SARM gem5 Developers
48610037SARM gem5 Developers    struct stat hostBuf;
48710037SARM gem5 Developers    int result = stat(path.c_str(), &hostBuf);
48810037SARM gem5 Developers
48910037SARM gem5 Developers    if (result < 0)
49010037SARM gem5 Developers        return -errno;
49110037SARM gem5 Developers
4927405SAli.Saidi@ARM.com    OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
4937731SAli.Saidi@ARM.com
4948468Swade.walker@arm.com    return 0;
4958468Swade.walker@arm.com}
4968468Swade.walker@arm.com
4977405SAli.Saidi@ARM.com
4987731SAli.Saidi@ARM.com/// Target fstat64() handler.
4997405SAli.Saidi@ARM.comtemplate <class OS>
5007405SAli.Saidi@ARM.comSyscallReturn
50111809Sbaz21@cam.ac.ukfstat64Func(SyscallDesc *desc, int callnum, Process *process,
50211809Sbaz21@cam.ac.uk            ThreadContext *tc)
5039130Satgutier@umich.edu{
5049130Satgutier@umich.edu    int fd = tc->getSyscallArg(0);
5059130Satgutier@umich.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
5069130Satgutier@umich.edu        // doesn't map to any simulator fd: not a valid target fd
5079814Sandreas.hansson@arm.com        return -EBADF;
5089130Satgutier@umich.edu    }
5099130Satgutier@umich.edu
5109130Satgutier@umich.edu#if NO_STAT64
5119130Satgutier@umich.edu    struct stat  hostBuf;
5129130Satgutier@umich.edu    int result = fstat(process->sim_fd(fd), &hostBuf);
5139130Satgutier@umich.edu#else
5149130Satgutier@umich.edu    struct stat64  hostBuf;
5159130Satgutier@umich.edu    int result = fstat64(process->sim_fd(fd), &hostBuf);
5169130Satgutier@umich.edu#endif
5179130Satgutier@umich.edu
5189130Satgutier@umich.edu    if (result < 0)
5199130Satgutier@umich.edu        return -errno;
5209130Satgutier@umich.edu
5219130Satgutier@umich.edu    OS::copyOutStat64Buf(tc->getMemPort(), fd, tc->getSyscallArg(1), &hostBuf);
5229130Satgutier@umich.edu
5239130Satgutier@umich.edu    return 0;
5249130Satgutier@umich.edu}
5259130Satgutier@umich.edu
5269130Satgutier@umich.edu
5279130Satgutier@umich.edu/// Target lstat() handler.
5289130Satgutier@umich.edutemplate <class OS>
5299130Satgutier@umich.eduSyscallReturn
5307583SAli.Saidi@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process,
5317583SAli.Saidi@arm.com          ThreadContext *tc)
5327583SAli.Saidi@arm.com{
53310461SAndreas.Sandberg@ARM.com    std::string path;
53410461SAndreas.Sandberg@ARM.com
53510461SAndreas.Sandberg@ARM.com    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
53610461SAndreas.Sandberg@ARM.com      return -EFAULT;
53710461SAndreas.Sandberg@ARM.com
53810461SAndreas.Sandberg@ARM.com    struct stat hostBuf;
53910461SAndreas.Sandberg@ARM.com    int result = lstat(path.c_str(), &hostBuf);
5408302SAli.Saidi@ARM.com
5418302SAli.Saidi@ARM.com    if (result < 0)
5427783SGiacomo.Gabrielli@arm.com        return -errno;
5437783SGiacomo.Gabrielli@arm.com
5447783SGiacomo.Gabrielli@arm.com    OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
5457783SGiacomo.Gabrielli@arm.com
54610037SARM gem5 Developers    return 0;
54710037SARM gem5 Developers}
54810037SARM gem5 Developers
54910037SARM gem5 Developers/// Target lstat64() handler.
55010037SARM gem5 Developerstemplate <class OS>
55110037SARM gem5 DevelopersSyscallReturn
55210037SARM gem5 Developerslstat64Func(SyscallDesc *desc, int callnum, Process *process,
55310037SARM gem5 Developers            ThreadContext *tc)
55410037SARM gem5 Developers{
55510037SARM gem5 Developers    std::string path;
55610037SARM gem5 Developers
55710037SARM gem5 Developers    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
55810037SARM gem5 Developers      return -EFAULT;
55910037SARM gem5 Developers
56010037SARM gem5 Developers#if NO_STAT64
56110037SARM gem5 Developers    struct stat hostBuf;
56210037SARM gem5 Developers    int result = lstat(path.c_str(), &hostBuf);
56310037SARM gem5 Developers#else
56410037SARM gem5 Developers    struct stat64 hostBuf;
56510037SARM gem5 Developers    int result = lstat64(path.c_str(), &hostBuf);
56610037SARM gem5 Developers#endif
56710037SARM gem5 Developers
56810037SARM gem5 Developers    if (result < 0)
56910037SARM gem5 Developers        return -errno;
57010037SARM gem5 Developers
57110037SARM gem5 Developers    OS::copyOutStat64Buf(tc->getMemPort(), -1, tc->getSyscallArg(1), &hostBuf);
57210037SARM gem5 Developers
57310037SARM gem5 Developers    return 0;
57410037SARM gem5 Developers}
57510037SARM gem5 Developers
57610037SARM gem5 Developers/// Target fstat() handler.
57710037SARM gem5 Developerstemplate <class OS>
57810338SCurtis.Dunham@arm.comSyscallReturn
57910338SCurtis.Dunham@arm.comfstatFunc(SyscallDesc *desc, int callnum, Process *process,
58010338SCurtis.Dunham@arm.com          ThreadContext *tc)
58110037SARM gem5 Developers{
58210037SARM gem5 Developers    int fd = process->sim_fd(tc->getSyscallArg(0));
58310037SARM gem5 Developers
58410037SARM gem5 Developers    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
58510037SARM gem5 Developers
58610037SARM gem5 Developers    if (fd < 0)
58710037SARM gem5 Developers        return -EBADF;
58810037SARM gem5 Developers
58910037SARM gem5 Developers    struct stat hostBuf;
59010037SARM gem5 Developers    int result = fstat(fd, &hostBuf);
59110037SARM gem5 Developers
59210037SARM gem5 Developers    if (result < 0)
59310037SARM gem5 Developers        return -errno;
59410037SARM gem5 Developers
59510037SARM gem5 Developers    OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
59610037SARM gem5 Developers
59710037SARM gem5 Developers    return 0;
59810037SARM gem5 Developers}
59910037SARM gem5 Developers
60010037SARM gem5 Developers
60110037SARM gem5 Developers/// Target statfs() handler.
60210037SARM gem5 Developerstemplate <class OS>
60310037SARM gem5 DevelopersSyscallReturn
60410037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
60510037SARM gem5 Developers           ThreadContext *tc)
60610037SARM gem5 Developers{
60710037SARM gem5 Developers    std::string path;
60810037SARM gem5 Developers
6098549Sdaniel.johnson@arm.com    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
6108868SMatt.Horsnell@arm.com      return -EFAULT;
6118868SMatt.Horsnell@arm.com
6128868SMatt.Horsnell@arm.com    struct statfs hostBuf;
6138868SMatt.Horsnell@arm.com    int result = statfs(path.c_str(), &hostBuf);
6148868SMatt.Horsnell@arm.com
6158868SMatt.Horsnell@arm.com    if (result < 0)
6168868SMatt.Horsnell@arm.com        return -errno;
6178868SMatt.Horsnell@arm.com
6188868SMatt.Horsnell@arm.com    OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
61910461SAndreas.Sandberg@ARM.com
6208868SMatt.Horsnell@arm.com    return 0;
62110461SAndreas.Sandberg@ARM.com}
62210037SARM gem5 Developers
6238868SMatt.Horsnell@arm.com
62410037SARM gem5 Developers/// Target fstatfs() handler.
62511150Smitch.hayenga@arm.comtemplate <class OS>
62610037SARM gem5 DevelopersSyscallReturn
62710037SARM gem5 DevelopersfstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
62810037SARM gem5 Developers            ThreadContext *tc)
62910037SARM gem5 Developers{
63011150Smitch.hayenga@arm.com    int fd = process->sim_fd(tc->getSyscallArg(0));
63110037SARM gem5 Developers
63210037SARM gem5 Developers    if (fd < 0)
63310037SARM gem5 Developers        return -EBADF;
63410037SARM gem5 Developers
63510037SARM gem5 Developers    struct statfs hostBuf;
63610037SARM gem5 Developers    int result = fstatfs(fd, &hostBuf);
63710037SARM gem5 Developers
63810037SARM gem5 Developers    if (result < 0)
63910037SARM gem5 Developers        return -errno;
64010037SARM gem5 Developers
64110037SARM gem5 Developers    OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
64210037SARM gem5 Developers
64310037SARM gem5 Developers    return 0;
64410037SARM gem5 Developers}
64510037SARM gem5 Developers
64610037SARM gem5 Developers
64710037SARM gem5 Developers/// Target writev() handler.
64810037SARM gem5 Developerstemplate <class OS>
64910037SARM gem5 DevelopersSyscallReturn
65010037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, Process *process,
65110037SARM gem5 Developers           ThreadContext *tc)
65210037SARM gem5 Developers{
65310037SARM gem5 Developers    int fd = tc->getSyscallArg(0);
65410037SARM gem5 Developers    if (fd < 0 || process->sim_fd(fd) < 0) {
65510037SARM gem5 Developers        // doesn't map to any simulator fd: not a valid target fd
65610037SARM gem5 Developers        return -EBADF;
65710037SARM gem5 Developers    }
65810037SARM gem5 Developers
65910037SARM gem5 Developers    TranslatingPort *p = tc->getMemPort();
66011769SCurtis.Dunham@arm.com    uint64_t tiov_base = tc->getSyscallArg(1);
66111769SCurtis.Dunham@arm.com    size_t count = tc->getSyscallArg(2);
66210037SARM gem5 Developers    struct iovec hiov[count];
66311770SCurtis.Dunham@arm.com    for (int i = 0; i < count; ++i)
66411770SCurtis.Dunham@arm.com    {
66510037SARM gem5 Developers        typename OS::tgt_iovec tiov;
66611770SCurtis.Dunham@arm.com
66711769SCurtis.Dunham@arm.com        p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
66810844Sandreas.sandberg@arm.com                    (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
66911772SCurtis.Dunham@arm.com        hiov[i].iov_len = gtoh(tiov.iov_len);
67011772SCurtis.Dunham@arm.com        hiov[i].iov_base = new char [hiov[i].iov_len];
67111772SCurtis.Dunham@arm.com        p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
67211772SCurtis.Dunham@arm.com                    hiov[i].iov_len);
67311774SCurtis.Dunham@arm.com    }
67411774SCurtis.Dunham@arm.com
67511774SCurtis.Dunham@arm.com    int result = writev(process->sim_fd(fd), hiov, count);
67611774SCurtis.Dunham@arm.com
67711774SCurtis.Dunham@arm.com    for (int i = 0; i < count; ++i)
67811774SCurtis.Dunham@arm.com    {
67911774SCurtis.Dunham@arm.com        delete [] (char *)hiov[i].iov_base;
68011773SCurtis.Dunham@arm.com    }
68111773SCurtis.Dunham@arm.com
68211773SCurtis.Dunham@arm.com    if (result < 0)
68311773SCurtis.Dunham@arm.com        return -errno;
68411773SCurtis.Dunham@arm.com
68511773SCurtis.Dunham@arm.com    return 0;
68611773SCurtis.Dunham@arm.com}
68711772SCurtis.Dunham@arm.com
68810037SARM gem5 Developers
68912816Sgiacomo.travaglini@arm.com/// Target mmap() handler.
69012816Sgiacomo.travaglini@arm.com///
69112816Sgiacomo.travaglini@arm.com/// We don't really handle mmap().  If the target is mmaping an
69210844Sandreas.sandberg@arm.com/// anonymous region or /dev/zero, we can get away with doing basically
69310844Sandreas.sandberg@arm.com/// nothing (since memory is initialized to zero and the simulator
69410844Sandreas.sandberg@arm.com/// doesn't really check addresses anyway).  Always print a warning,
69510844Sandreas.sandberg@arm.com/// since this could be seriously broken if we're not mapping
69610844Sandreas.sandberg@arm.com/// /dev/zero.
69710844Sandreas.sandberg@arm.com//
69810188Sgeoffrey.blake@arm.com/// Someday we should explicitly check for /dev/zero in open, flag the
69910037SARM gem5 Developers/// file descriptor, and fail (or implement!) a non-anonymous mmap to
70010037SARM gem5 Developers/// anything else.
7017405SAli.Saidi@ARM.comtemplate <class OS>
7027405SAli.Saidi@ARM.comSyscallReturn
7037405SAli.Saidi@ARM.commmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
7047405SAli.Saidi@ARM.com{
7057405SAli.Saidi@ARM.com    Addr start = tc->getSyscallArg(0);
7067405SAli.Saidi@ARM.com    uint64_t length = tc->getSyscallArg(1);
7077405SAli.Saidi@ARM.com    // int prot = tc->getSyscallArg(2);
7087405SAli.Saidi@ARM.com    int flags = tc->getSyscallArg(3);
7097614Sminkyu.jeong@arm.com    // int fd = p->sim_fd(tc->getSyscallArg(4));
71012478SCurtis.Dunham@arm.com    // int offset = tc->getSyscallArg(5);
71112478SCurtis.Dunham@arm.com
71212478SCurtis.Dunham@arm.com    if ((start  % TheISA::VMPageSize) != 0 ||
71312478SCurtis.Dunham@arm.com        (length % TheISA::VMPageSize) != 0) {
71412478SCurtis.Dunham@arm.com        warn("mmap failing: arguments not page-aligned: "
71511771SCurtis.Dunham@arm.com             "start 0x%x length 0x%x",
71612478SCurtis.Dunham@arm.com             start, length);
71712478SCurtis.Dunham@arm.com        return -EINVAL;
71810037SARM gem5 Developers    }
71912478SCurtis.Dunham@arm.com
72010037SARM gem5 Developers    if (start != 0) {
72112478SCurtis.Dunham@arm.com        warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
72210037SARM gem5 Developers             start, p->mmap_end);
72312478SCurtis.Dunham@arm.com    }
72410037SARM gem5 Developers
7257405SAli.Saidi@ARM.com    // pick next address from our "mmap region"
7267405SAli.Saidi@ARM.com    start = p->mmap_end;
7277405SAli.Saidi@ARM.com    p->pTable->allocate(start, length);
7287405SAli.Saidi@ARM.com    p->mmap_end += length;
7297405SAli.Saidi@ARM.com
7307749SAli.Saidi@ARM.com    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
7317405SAli.Saidi@ARM.com        warn("allowing mmap of file @ fd %d. "
73210037SARM gem5 Developers             "This will break if not /dev/zero.", tc->getSyscallArg(4));
73310037SARM gem5 Developers    }
7348284SAli.Saidi@ARM.com
7357405SAli.Saidi@ARM.com    return start;
7367405SAli.Saidi@ARM.com}
7377749SAli.Saidi@ARM.com
7387749SAli.Saidi@ARM.com/// Target getrlimit() handler.
7397749SAli.Saidi@ARM.comtemplate <class OS>
7407749SAli.Saidi@ARM.comSyscallReturn
7417405SAli.Saidi@ARM.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
74212510Sgiacomo.travaglini@arm.com        ThreadContext *tc)
74312406Sgabeblack@google.com{
74412406Sgabeblack@google.com    unsigned resource = tc->getSyscallArg(0);
7457749SAli.Saidi@ARM.com    TypedBufferArg<typename OS::rlimit> rlp(tc->getSyscallArg(1));
7467749SAli.Saidi@ARM.com
7477614Sminkyu.jeong@arm.com    switch (resource) {
7487614Sminkyu.jeong@arm.com        case OS::TGT_RLIMIT_STACK:
7497720Sgblack@eecs.umich.edu            // max stack size in bytes: make up a number (2MB for now)
7507720Sgblack@eecs.umich.edu            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
7517720Sgblack@eecs.umich.edu            rlp->rlim_cur = htog(rlp->rlim_cur);
75212763Sgiacomo.travaglini@arm.com            rlp->rlim_max = htog(rlp->rlim_max);
7538887Sgeoffrey.blake@arm.com            break;
7548887Sgeoffrey.blake@arm.com
7558887Sgeoffrey.blake@arm.com        default:
7568887Sgeoffrey.blake@arm.com            std::cerr << "getrlimitFunc: unimplemented resource " << resource
7578887Sgeoffrey.blake@arm.com                << std::endl;
7588887Sgeoffrey.blake@arm.com            abort();
7598887Sgeoffrey.blake@arm.com            break;
7608887Sgeoffrey.blake@arm.com    }
7618887Sgeoffrey.blake@arm.com
7627408Sgblack@eecs.umich.edu    rlp.copyOut(tc->getMemPort());
76310037SARM gem5 Developers    return 0;
76410037SARM gem5 Developers}
76510037SARM gem5 Developers
76610037SARM gem5 Developers/// Target gettimeofday() handler.
76710037SARM gem5 Developerstemplate <class OS>
76810037SARM gem5 DevelopersSyscallReturn
76910037SARM gem5 DevelopersgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
77010037SARM gem5 Developers        ThreadContext *tc)
77110037SARM gem5 Developers{
77210037SARM gem5 Developers    TypedBufferArg<typename OS::timeval> tp(tc->getSyscallArg(0));
77310037SARM gem5 Developers
7747408Sgblack@eecs.umich.edu    getElapsedTime(tp->tv_sec, tp->tv_usec);
7757408Sgblack@eecs.umich.edu    tp->tv_sec += seconds_since_epoch;
7768206SWilliam.Wang@arm.com    tp->tv_sec = htog(tp->tv_sec);
7778206SWilliam.Wang@arm.com    tp->tv_usec = htog(tp->tv_usec);
7788206SWilliam.Wang@arm.com
7798206SWilliam.Wang@arm.com    tp.copyOut(tc->getMemPort());
7808206SWilliam.Wang@arm.com
7818206SWilliam.Wang@arm.com    return 0;
7828206SWilliam.Wang@arm.com}
7838206SWilliam.Wang@arm.com
78410037SARM gem5 Developers
78510037SARM gem5 Developers/// Target utimes() handler.
78610037SARM gem5 Developerstemplate <class OS>
78710037SARM gem5 DevelopersSyscallReturn
78810037SARM gem5 DevelopersutimesFunc(SyscallDesc *desc, int callnum, Process *process,
78912667Schuan.zhu@arm.com           ThreadContext *tc)
79010037SARM gem5 Developers{
79110037SARM gem5 Developers    std::string path;
79210037SARM gem5 Developers
79310037SARM gem5 Developers    if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
79410037SARM gem5 Developers      return -EFAULT;
79510037SARM gem5 Developers
79610037SARM gem5 Developers    TypedBufferArg<typename OS::timeval [2]> tp(tc->getSyscallArg(1));
79710037SARM gem5 Developers    tp.copyIn(tc->getMemPort());
7988206SWilliam.Wang@arm.com
79910037SARM gem5 Developers    struct timeval hostTimeval[2];
80010037SARM gem5 Developers    for (int i = 0; i < 2; ++i)
80110037SARM gem5 Developers    {
80210037SARM gem5 Developers        hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
80310037SARM gem5 Developers        hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
80410037SARM gem5 Developers    }
80510037SARM gem5 Developers    int result = utimes(path.c_str(), hostTimeval);
80610037SARM gem5 Developers
80710037SARM gem5 Developers    if (result < 0)
80810037SARM gem5 Developers        return -errno;
80910037SARM gem5 Developers
81010037SARM gem5 Developers    return 0;
81110037SARM gem5 Developers}
81210037SARM gem5 Developers/// Target getrusage() function.
81310037SARM gem5 Developerstemplate <class OS>
81410037SARM gem5 DevelopersSyscallReturn
81510037SARM gem5 DevelopersgetrusageFunc(SyscallDesc *desc, int callnum, Process *process,
81610037SARM gem5 Developers              ThreadContext *tc)
81710037SARM gem5 Developers{
81810037SARM gem5 Developers    int who = tc->getSyscallArg(0);	// THREAD, SELF, or CHILDREN
81910037SARM gem5 Developers    TypedBufferArg<typename OS::rusage> rup(tc->getSyscallArg(1));
82010037SARM gem5 Developers
82110037SARM gem5 Developers    if (who != OS::TGT_RUSAGE_SELF) {
82210037SARM gem5 Developers        // don't really handle THREAD or CHILDREN, but just warn and
82310037SARM gem5 Developers        // plow ahead
82410037SARM gem5 Developers        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
82510037SARM gem5 Developers             who);
82610037SARM gem5 Developers    }
82710037SARM gem5 Developers
8288206SWilliam.Wang@arm.com    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
8298206SWilliam.Wang@arm.com    rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
8307408Sgblack@eecs.umich.edu    rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
8317408Sgblack@eecs.umich.edu
8327408Sgblack@eecs.umich.edu    rup->ru_stime.tv_sec = 0;
8337731SAli.Saidi@ARM.com    rup->ru_stime.tv_usec = 0;
8348206SWilliam.Wang@arm.com    rup->ru_maxrss = 0;
83510037SARM gem5 Developers    rup->ru_ixrss = 0;
83610037SARM gem5 Developers    rup->ru_idrss = 0;
83710037SARM gem5 Developers    rup->ru_isrss = 0;
83810037SARM gem5 Developers    rup->ru_minflt = 0;
83910037SARM gem5 Developers    rup->ru_majflt = 0;
8407408Sgblack@eecs.umich.edu    rup->ru_nswap = 0;
8417408Sgblack@eecs.umich.edu    rup->ru_inblock = 0;
8427408Sgblack@eecs.umich.edu    rup->ru_oublock = 0;
8437408Sgblack@eecs.umich.edu    rup->ru_msgsnd = 0;
8447408Sgblack@eecs.umich.edu    rup->ru_msgrcv = 0;
8457408Sgblack@eecs.umich.edu    rup->ru_nsignals = 0;
8467408Sgblack@eecs.umich.edu    rup->ru_nvcsw = 0;
8477408Sgblack@eecs.umich.edu    rup->ru_nivcsw = 0;
8487408Sgblack@eecs.umich.edu
8497408Sgblack@eecs.umich.edu    rup.copyOut(tc->getMemPort());
85010037SARM gem5 Developers
85110037SARM gem5 Developers    return 0;
85210037SARM gem5 Developers}
85310037SARM gem5 Developers
85410037SARM gem5 Developers
85510037SARM gem5 Developers
8567408Sgblack@eecs.umich.edu
8577408Sgblack@eecs.umich.edu#endif // __SIM_SYSCALL_EMUL_HH__
8587408Sgblack@eecs.umich.edu