syscall_emul.hh revision 8601
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 */
317405SAli.Saidi@ARM.com
327405SAli.Saidi@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__
337405SAli.Saidi@ARM.com#define __SIM_SYSCALL_EMUL_HH__
347405SAli.Saidi@ARM.com
357405SAli.Saidi@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
367405SAli.Saidi@ARM.com                   defined(__FreeBSD__) || defined(__CYGWIN__))
377405SAli.Saidi@ARM.com
387405SAli.Saidi@ARM.com///
397405SAli.Saidi@ARM.com/// @file syscall_emul.hh
407405SAli.Saidi@ARM.com///
417405SAli.Saidi@ARM.com/// This file defines objects used to emulate syscalls from the target
4210461SAndreas.Sandberg@ARM.com/// application on the host machine.
439050Schander.sudanthi@arm.com
4412406Sgabeblack@google.com#ifdef __CYGWIN32__
4512605Sgiacomo.travaglini@arm.com#include <sys/fcntl.h>  // for O_BINARY
4611793Sbrandon.potter@amd.com#endif
478887Sgeoffrey.blake@arm.com#include <sys/stat.h>
488232Snate@binkert.org#include <sys/time.h>
498232Snate@binkert.org#include <sys/uio.h>
5010844Sandreas.sandberg@arm.com#include <fcntl.h>
519384SAndreas.Sandberg@arm.com
527678Sgblack@eecs.umich.edu#include <cerrno>
538059SAli.Saidi@ARM.com#include <string>
548284SAli.Saidi@ARM.com
557405SAli.Saidi@ARM.com#include "base/chunk_generator.hh"
567405SAli.Saidi@ARM.com#include "base/intmath.hh"      // for RoundUp
577405SAli.Saidi@ARM.com#include "base/misc.hh"
587405SAli.Saidi@ARM.com#include "base/trace.hh"
599384SAndreas.Sandberg@arm.com#include "base/types.hh"
6010461SAndreas.Sandberg@ARM.com#include "config/the_isa.hh"
6110461SAndreas.Sandberg@ARM.com#include "cpu/base.hh"
6211165SRekai.GonzalezAlberquilla@arm.com#include "cpu/thread_context.hh"
6312109SRekai.GonzalezAlberquilla@arm.com#include "debug/SyscallVerbose.hh"
6412714Sgiacomo.travaglini@arm.com#include "mem/page_table.hh"
6512714Sgiacomo.travaglini@arm.com#include "mem/translating_port.hh"
669384SAndreas.Sandberg@arm.com#include "sim/byteswap.hh"
6711770SCurtis.Dunham@arm.com#include "sim/process.hh"
6810037SARM gem5 Developers#include "sim/system.hh"
6910461SAndreas.Sandberg@ARM.com
7010461SAndreas.Sandberg@ARM.com///
7110461SAndreas.Sandberg@ARM.com/// System call descriptor.
7210461SAndreas.Sandberg@ARM.com///
7310461SAndreas.Sandberg@ARM.comclass SyscallDesc {
7410461SAndreas.Sandberg@ARM.com
7510609Sandreas.sandberg@arm.com  public:
7610609Sandreas.sandberg@arm.com
7710609Sandreas.sandberg@arm.com    /// Typedef for target syscall handler functions.
7810037SARM gem5 Developers    typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
7910037SARM gem5 Developers                           LiveProcess *, ThreadContext *);
8010037SARM gem5 Developers
8110037SARM gem5 Developers    const char *name;   //!< Syscall name (e.g., "open").
8211771SCurtis.Dunham@arm.com    FuncPtr funcPtr;    //!< Pointer to emulation function.
8310037SARM gem5 Developers    int flags;          //!< Flags (see Flags enum).
8410037SARM gem5 Developers
8513173Sgiacomo.travaglini@arm.com    /// Flag values for controlling syscall behavior.
8610037SARM gem5 Developers    enum Flags {
8710037SARM gem5 Developers        /// Don't set return regs according to funcPtr return value.
8813114Sgiacomo.travaglini@arm.com        /// Used for syscalls with non-standard return conventions
8910037SARM gem5 Developers        /// that explicitly set the ThreadContext regs (e.g.,
9011771SCurtis.Dunham@arm.com        /// sigreturn).
9110037SARM gem5 Developers        SuppressReturnValue = 1
9213173Sgiacomo.travaglini@arm.com    };
9310037SARM gem5 Developers
9413114Sgiacomo.travaglini@arm.com    /// Constructor.
9510037SARM gem5 Developers    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
9610037SARM gem5 Developers        : name(_name), funcPtr(_funcPtr), flags(_flags)
9712477SCurtis.Dunham@arm.com    {
9810037SARM gem5 Developers    }
9910037SARM gem5 Developers
1009384SAndreas.Sandberg@arm.com    /// Emulate the syscall.  Public interface for calling through funcPtr.
1019384SAndreas.Sandberg@arm.com    void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
1029384SAndreas.Sandberg@arm.com};
10312479SCurtis.Dunham@arm.com
10412479SCurtis.Dunham@arm.com
1059384SAndreas.Sandberg@arm.comclass BaseBufferArg {
1069384SAndreas.Sandberg@arm.com
1079384SAndreas.Sandberg@arm.com  public:
1089384SAndreas.Sandberg@arm.com
1099384SAndreas.Sandberg@arm.com    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
1109384SAndreas.Sandberg@arm.com    {
1117427Sgblack@eecs.umich.edu        bufPtr = new uint8_t[size];
1127427Sgblack@eecs.umich.edu        // clear out buffer: in case we only partially populate this,
1137427Sgblack@eecs.umich.edu        // and then do a copyOut(), we want to make sure we don't
1149385SAndreas.Sandberg@arm.com        // introduce any random junk into the simulated address space
1159385SAndreas.Sandberg@arm.com        memset(bufPtr, 0, size);
1167427Sgblack@eecs.umich.edu    }
1177427Sgblack@eecs.umich.edu
11810037SARM gem5 Developers    virtual ~BaseBufferArg() { delete [] bufPtr; }
11913114Sgiacomo.travaglini@arm.com
12010037SARM gem5 Developers    //
12113114Sgiacomo.travaglini@arm.com    // copy data into simulator space (read from target memory)
12213114Sgiacomo.travaglini@arm.com    //
12313114Sgiacomo.travaglini@arm.com    virtual bool copyIn(TranslatingPort *memport)
12413114Sgiacomo.travaglini@arm.com    {
12513114Sgiacomo.travaglini@arm.com        memport->readBlob(addr, bufPtr, size);
12612690Sgiacomo.travaglini@arm.com        return true;    // no EFAULT detection for now
12710037SARM gem5 Developers    }
1287427Sgblack@eecs.umich.edu
1297427Sgblack@eecs.umich.edu    //
13010037SARM gem5 Developers    // copy data out of simulator space (write to target memory)
1317427Sgblack@eecs.umich.edu    //
1327427Sgblack@eecs.umich.edu    virtual bool copyOut(TranslatingPort *memport)
1337427Sgblack@eecs.umich.edu    {
1347427Sgblack@eecs.umich.edu        memport->writeBlob(addr, bufPtr, size);
1357427Sgblack@eecs.umich.edu        return true;    // no EFAULT detection for now
1367427Sgblack@eecs.umich.edu    }
1377427Sgblack@eecs.umich.edu
1387427Sgblack@eecs.umich.edu  protected:
1397427Sgblack@eecs.umich.edu    Addr addr;
1407427Sgblack@eecs.umich.edu    int size;
1417427Sgblack@eecs.umich.edu    uint8_t *bufPtr;
1427427Sgblack@eecs.umich.edu};
1437427Sgblack@eecs.umich.edu
1447427Sgblack@eecs.umich.edu
1457427Sgblack@eecs.umich.educlass BufferArg : public BaseBufferArg
1467427Sgblack@eecs.umich.edu{
1477427Sgblack@eecs.umich.edu  public:
1487427Sgblack@eecs.umich.edu    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1497427Sgblack@eecs.umich.edu    void *bufferPtr()   { return bufPtr; }
1507427Sgblack@eecs.umich.edu};
1517427Sgblack@eecs.umich.edu
1527427Sgblack@eecs.umich.edutemplate <class T>
1537427Sgblack@eecs.umich.educlass TypedBufferArg : public BaseBufferArg
1547436Sdam.sunwoo@arm.com{
1557436Sdam.sunwoo@arm.com  public:
15610037SARM gem5 Developers    // user can optionally specify a specific number of bytes to
15710037SARM gem5 Developers    // allocate to deal with those structs that have variable-size
1587436Sdam.sunwoo@arm.com    // arrays at the end
1597436Sdam.sunwoo@arm.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
1607436Sdam.sunwoo@arm.com        : BaseBufferArg(_addr, _size)
1617436Sdam.sunwoo@arm.com    { }
1627436Sdam.sunwoo@arm.com
1637436Sdam.sunwoo@arm.com    // type case
1647436Sdam.sunwoo@arm.com    operator T*() { return (T *)bufPtr; }
1657436Sdam.sunwoo@arm.com
1667436Sdam.sunwoo@arm.com    // dereference operators
1677436Sdam.sunwoo@arm.com    T &operator*()       { return *((T *)bufPtr); }
1687436Sdam.sunwoo@arm.com    T* operator->()      { return (T *)bufPtr; }
1697436Sdam.sunwoo@arm.com    T &operator[](int i) { return ((T *)bufPtr)[i]; }
17013393Sgiacomo.travaglini@arm.com};
17110037SARM gem5 Developers
1727436Sdam.sunwoo@arm.com//////////////////////////////////////////////////////////////////////
1737436Sdam.sunwoo@arm.com//
1747436Sdam.sunwoo@arm.com// The following emulation functions are generic enough that they
1757436Sdam.sunwoo@arm.com// don't need to be recompiled for different emulated OS's.  They are
1767436Sdam.sunwoo@arm.com// defined in sim/syscall_emul.cc.
1777436Sdam.sunwoo@arm.com//
1787436Sdam.sunwoo@arm.com//////////////////////////////////////////////////////////////////////
1797436Sdam.sunwoo@arm.com
1807436Sdam.sunwoo@arm.com
1817436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we haven't thought about.
1827436Sdam.sunwoo@arm.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
1837436Sdam.sunwoo@arm.com                                LiveProcess *p, ThreadContext *tc);
1847436Sdam.sunwoo@arm.com
1857436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we never intend to
1867436Sdam.sunwoo@arm.com/// implement (signal handling, etc.) and should not affect the correct
1877436Sdam.sunwoo@arm.com/// behavior of the program.  Print a warning only if the appropriate
18813393Sgiacomo.travaglini@arm.com/// trace flag is enabled.  Return success to the target program.
18913393Sgiacomo.travaglini@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num,
19013393Sgiacomo.travaglini@arm.com                         LiveProcess *p, ThreadContext *tc);
19113393Sgiacomo.travaglini@arm.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num,
19213393Sgiacomo.travaglini@arm.com                         LiveProcess *p, ThreadContext *tc);
19313393Sgiacomo.travaglini@arm.com
19413393Sgiacomo.travaglini@arm.com/// Target exit() handler: terminate current context.
19513393Sgiacomo.travaglini@arm.comSyscallReturn exitFunc(SyscallDesc *desc, int num,
19613393Sgiacomo.travaglini@arm.com                       LiveProcess *p, ThreadContext *tc);
19713393Sgiacomo.travaglini@arm.com
19813393Sgiacomo.travaglini@arm.com/// Target exit_group() handler: terminate simulation. (exit all threads)
19913393Sgiacomo.travaglini@arm.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
20013393Sgiacomo.travaglini@arm.com                       LiveProcess *p, ThreadContext *tc);
20113393Sgiacomo.travaglini@arm.com
20213393Sgiacomo.travaglini@arm.com/// Target getpagesize() handler.
20313393Sgiacomo.travaglini@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
20413396Sgiacomo.travaglini@arm.com                              LiveProcess *p, ThreadContext *tc);
20513396Sgiacomo.travaglini@arm.com
20613396Sgiacomo.travaglini@arm.com/// Target brk() handler: set brk address.
20713396Sgiacomo.travaglini@arm.comSyscallReturn brkFunc(SyscallDesc *desc, int num,
20813393Sgiacomo.travaglini@arm.com                      LiveProcess *p, ThreadContext *tc);
20913393Sgiacomo.travaglini@arm.com
21013393Sgiacomo.travaglini@arm.com/// Target close() handler.
21113393Sgiacomo.travaglini@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num,
21213393Sgiacomo.travaglini@arm.com                        LiveProcess *p, ThreadContext *tc);
21313393Sgiacomo.travaglini@arm.com
21413393Sgiacomo.travaglini@arm.com/// Target read() handler.
21513393Sgiacomo.travaglini@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num,
21613393Sgiacomo.travaglini@arm.com                       LiveProcess *p, ThreadContext *tc);
21713393Sgiacomo.travaglini@arm.com
21813393Sgiacomo.travaglini@arm.com/// Target write() handler.
21913393Sgiacomo.travaglini@arm.comSyscallReturn writeFunc(SyscallDesc *desc, int num,
22013393Sgiacomo.travaglini@arm.com                        LiveProcess *p, ThreadContext *tc);
22113393Sgiacomo.travaglini@arm.com
22213393Sgiacomo.travaglini@arm.com/// Target lseek() handler.
22313393Sgiacomo.travaglini@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num,
22413393Sgiacomo.travaglini@arm.com                        LiveProcess *p, ThreadContext *tc);
22513393Sgiacomo.travaglini@arm.com
2267644Sali.saidi@arm.com/// Target _llseek() handler.
2278147SAli.Saidi@ARM.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num,
2289385SAndreas.Sandberg@arm.com                        LiveProcess *p, ThreadContext *tc);
2299385SAndreas.Sandberg@arm.com
23010037SARM gem5 Developers/// Target munmap() handler.
23110037SARM gem5 DevelopersSyscallReturn munmapFunc(SyscallDesc *desc, int num,
23210037SARM gem5 Developers                         LiveProcess *p, ThreadContext *tc);
23310037SARM gem5 Developers
23410037SARM gem5 Developers/// Target gethostname() handler.
23510037SARM gem5 DevelopersSyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
23610037SARM gem5 Developers                              LiveProcess *p, ThreadContext *tc);
23710037SARM gem5 Developers
23810037SARM gem5 Developers/// Target getcwd() handler.
23910037SARM gem5 DevelopersSyscallReturn getcwdFunc(SyscallDesc *desc, int num,
24010037SARM gem5 Developers                         LiveProcess *p, ThreadContext *tc);
24110037SARM gem5 Developers
24210037SARM gem5 Developers/// Target unlink() handler.
24310037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num,
24410037SARM gem5 Developers                           LiveProcess *p, ThreadContext *tc);
24510037SARM gem5 Developers
2468147SAli.Saidi@ARM.com/// Target unlink() handler.
2477427Sgblack@eecs.umich.eduSyscallReturn unlinkFunc(SyscallDesc *desc, int num,
2487427Sgblack@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2497427Sgblack@eecs.umich.edu
25010037SARM gem5 Developers/// Target mkdir() handler.
25110037SARM gem5 DevelopersSyscallReturn mkdirFunc(SyscallDesc *desc, int num,
25210037SARM gem5 Developers                        LiveProcess *p, ThreadContext *tc);
25310037SARM gem5 Developers
25413396Sgiacomo.travaglini@arm.com/// Target rename() handler.
25510037SARM gem5 DevelopersSyscallReturn renameFunc(SyscallDesc *desc, int num,
25610037SARM gem5 Developers                         LiveProcess *p, ThreadContext *tc);
25710037SARM gem5 Developers
25810037SARM gem5 Developers
25910037SARM gem5 Developers/// Target truncate() handler.
26010037SARM gem5 DevelopersSyscallReturn truncateFunc(SyscallDesc *desc, int num,
26110037SARM gem5 Developers                           LiveProcess *p, ThreadContext *tc);
26210037SARM gem5 Developers
26310037SARM gem5 Developers
26410037SARM gem5 Developers/// Target ftruncate() handler.
26510037SARM gem5 DevelopersSyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
26610037SARM gem5 Developers                            LiveProcess *p, ThreadContext *tc);
26710037SARM gem5 Developers
26810037SARM gem5 Developers
26910037SARM gem5 Developers/// Target truncate64() handler.
27010037SARM gem5 DevelopersSyscallReturn truncate64Func(SyscallDesc *desc, int num,
27110037SARM gem5 Developers                             LiveProcess *p, ThreadContext *tc);
27210037SARM gem5 Developers
27310037SARM gem5 Developers/// Target ftruncate64() handler.
27410037SARM gem5 DevelopersSyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
27510037SARM gem5 Developers                              LiveProcess *p, ThreadContext *tc);
27610037SARM gem5 Developers
27710037SARM gem5 Developers
27810037SARM gem5 Developers/// Target umask() handler.
27910037SARM gem5 DevelopersSyscallReturn umaskFunc(SyscallDesc *desc, int num,
28010037SARM gem5 Developers                        LiveProcess *p, ThreadContext *tc);
28110037SARM gem5 Developers
28210037SARM gem5 Developers
28310037SARM gem5 Developers/// Target chown() handler.
28410037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num,
28510037SARM gem5 Developers                        LiveProcess *p, ThreadContext *tc);
28611770SCurtis.Dunham@arm.com
28710037SARM gem5 Developers
28811574SCurtis.Dunham@arm.com/// Target fchown() handler.
28911770SCurtis.Dunham@arm.comSyscallReturn fchownFunc(SyscallDesc *desc, int num,
29011770SCurtis.Dunham@arm.com                         LiveProcess *p, ThreadContext *tc);
29110037SARM gem5 Developers
29211770SCurtis.Dunham@arm.com/// Target dup() handler.
29311770SCurtis.Dunham@arm.comSyscallReturn dupFunc(SyscallDesc *desc, int num,
29410037SARM gem5 Developers                      LiveProcess *process, ThreadContext *tc);
29510037SARM gem5 Developers
29610037SARM gem5 Developers/// Target fnctl() handler.
29713114Sgiacomo.travaglini@arm.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num,
29810037SARM gem5 Developers                        LiveProcess *process, ThreadContext *tc);
29913114Sgiacomo.travaglini@arm.com
30013114Sgiacomo.travaglini@arm.com/// Target fcntl64() handler.
30113114Sgiacomo.travaglini@arm.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num,
30213114Sgiacomo.travaglini@arm.com                        LiveProcess *process, ThreadContext *tc);
30313114Sgiacomo.travaglini@arm.com
30413114Sgiacomo.travaglini@arm.com/// Target setuid() handler.
30513114Sgiacomo.travaglini@arm.comSyscallReturn setuidFunc(SyscallDesc *desc, int num,
30613114Sgiacomo.travaglini@arm.com                               LiveProcess *p, ThreadContext *tc);
30713114Sgiacomo.travaglini@arm.com
30813114Sgiacomo.travaglini@arm.com/// Target getpid() handler.
30913114Sgiacomo.travaglini@arm.comSyscallReturn getpidFunc(SyscallDesc *desc, int num,
31013114Sgiacomo.travaglini@arm.com                               LiveProcess *p, ThreadContext *tc);
31113114Sgiacomo.travaglini@arm.com
31213114Sgiacomo.travaglini@arm.com/// Target getuid() handler.
31313114Sgiacomo.travaglini@arm.comSyscallReturn getuidFunc(SyscallDesc *desc, int num,
31413114Sgiacomo.travaglini@arm.com                               LiveProcess *p, ThreadContext *tc);
31513114Sgiacomo.travaglini@arm.com
31613114Sgiacomo.travaglini@arm.com/// Target getgid() handler.
31713114Sgiacomo.travaglini@arm.comSyscallReturn getgidFunc(SyscallDesc *desc, int num,
31813114Sgiacomo.travaglini@arm.com                               LiveProcess *p, ThreadContext *tc);
31913114Sgiacomo.travaglini@arm.com
32013114Sgiacomo.travaglini@arm.com/// Target getppid() handler.
32113114Sgiacomo.travaglini@arm.comSyscallReturn getppidFunc(SyscallDesc *desc, int num,
32213114Sgiacomo.travaglini@arm.com                               LiveProcess *p, ThreadContext *tc);
32310037SARM gem5 Developers
32410037SARM gem5 Developers/// Target geteuid() handler.
32510037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num,
32610461SAndreas.Sandberg@ARM.com                               LiveProcess *p, ThreadContext *tc);
32710461SAndreas.Sandberg@ARM.com
32810461SAndreas.Sandberg@ARM.com/// Target getegid() handler.
32910461SAndreas.Sandberg@ARM.comSyscallReturn getegidFunc(SyscallDesc *desc, int num,
33010037SARM gem5 Developers                               LiveProcess *p, ThreadContext *tc);
33110037SARM gem5 Developers
33210037SARM gem5 Developers/// Target clone() handler.
33310037SARM gem5 DevelopersSyscallReturn cloneFunc(SyscallDesc *desc, int num,
33410037SARM gem5 Developers                               LiveProcess *p, ThreadContext *tc);
33513116Sgiacomo.travaglini@arm.com
33610037SARM gem5 Developers
33710461SAndreas.Sandberg@ARM.com/// Pseudo Funcs  - These functions use a different return convension,
33810461SAndreas.Sandberg@ARM.com/// returning a second value in a register other than the normal return register
33910461SAndreas.Sandberg@ARM.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
34010461SAndreas.Sandberg@ARM.com                             LiveProcess *process, ThreadContext *tc);
34110461SAndreas.Sandberg@ARM.com
34210037SARM gem5 Developers/// Target getpidPseudo() handler.
34310037SARM gem5 DevelopersSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
34410037SARM gem5 Developers                               LiveProcess *p, ThreadContext *tc);
34510037SARM gem5 Developers
34610037SARM gem5 Developers/// Target getuidPseudo() handler.
34711574SCurtis.Dunham@arm.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
34810037SARM gem5 Developers                               LiveProcess *p, ThreadContext *tc);
34910037SARM gem5 Developers
35010037SARM gem5 Developers/// Target getgidPseudo() handler.
35111574SCurtis.Dunham@arm.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
35210037SARM gem5 Developers                               LiveProcess *p, ThreadContext *tc);
35310037SARM gem5 Developers
35410037SARM gem5 Developers
35510037SARM gem5 Developers/// A readable name for 1,000,000, for converting microseconds to seconds.
35610037SARM gem5 Developersconst int one_million = 1000000;
35710037SARM gem5 Developers
35810037SARM gem5 Developers/// Approximate seconds since the epoch (1/1/1970).  About a billion,
35913114Sgiacomo.travaglini@arm.com/// by my reckoning.  We want to keep this a constant (not use the
36013173Sgiacomo.travaglini@arm.com/// real-world time) to keep simulations repeatable.
36113173Sgiacomo.travaglini@arm.comconst unsigned seconds_since_epoch = 1000000000;
36213173Sgiacomo.travaglini@arm.com
36313173Sgiacomo.travaglini@arm.com/// Helper function to convert current elapsed time to seconds and
36410037SARM gem5 Developers/// microseconds.
36510037SARM gem5 Developerstemplate <class T1, class T2>
36612972Sandreas.sandberg@arm.comvoid
36712972Sandreas.sandberg@arm.comgetElapsedTime(T1 &sec, T2 &usec)
36812972Sandreas.sandberg@arm.com{
36912972Sandreas.sandberg@arm.com    int elapsed_usecs = curTick() / SimClock::Int::us;
37012972Sandreas.sandberg@arm.com    sec = elapsed_usecs / one_million;
37112972Sandreas.sandberg@arm.com    usec = elapsed_usecs % one_million;
37212972Sandreas.sandberg@arm.com}
37312972Sandreas.sandberg@arm.com
3747405SAli.Saidi@ARM.com//////////////////////////////////////////////////////////////////////
37510035Sandreas.hansson@arm.com//
3767405SAli.Saidi@ARM.com// The following emulation functions are generic, but need to be
3777405SAli.Saidi@ARM.com// templated to account for differences in types, constants, etc.
3787614Sminkyu.jeong@arm.com//
37912478SCurtis.Dunham@arm.com//////////////////////////////////////////////////////////////////////
38012478SCurtis.Dunham@arm.com
38112478SCurtis.Dunham@arm.com#if NO_STAT64
38212478SCurtis.Dunham@arm.com    typedef struct stat hst_stat;
38312478SCurtis.Dunham@arm.com    typedef struct stat hst_stat64;
38412478SCurtis.Dunham@arm.com#else
38512478SCurtis.Dunham@arm.com    typedef struct stat hst_stat;
38612478SCurtis.Dunham@arm.com    typedef struct stat64 hst_stat64;
38712478SCurtis.Dunham@arm.com#endif
38812478SCurtis.Dunham@arm.com
38912478SCurtis.Dunham@arm.com//// Helper function to convert a host stat buffer to a target stat
39012478SCurtis.Dunham@arm.com//// buffer.  Also copies the target buffer out to the simulated
39112478SCurtis.Dunham@arm.com//// memory space.  Used by stat(), fstat(), and lstat().
39212478SCurtis.Dunham@arm.com
39312478SCurtis.Dunham@arm.comtemplate <typename target_stat, typename host_stat>
39412478SCurtis.Dunham@arm.comstatic void
3957405SAli.Saidi@ARM.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
3967405SAli.Saidi@ARM.com{
3977405SAli.Saidi@ARM.com    using namespace TheISA;
3987405SAli.Saidi@ARM.com
3997405SAli.Saidi@ARM.com    if (fakeTTY)
4007405SAli.Saidi@ARM.com        tgt->st_dev = 0xA;
40110037SARM gem5 Developers    else
40210037SARM gem5 Developers        tgt->st_dev = host->st_dev;
40310037SARM gem5 Developers    tgt->st_dev = htog(tgt->st_dev);
4049050Schander.sudanthi@arm.com    tgt->st_ino = host->st_ino;
4057405SAli.Saidi@ARM.com    tgt->st_ino = htog(tgt->st_ino);
40610037SARM gem5 Developers    tgt->st_mode = host->st_mode;
40710037SARM gem5 Developers    if (fakeTTY) {
4087720Sgblack@eecs.umich.edu        // Claim to be a character device
4097720Sgblack@eecs.umich.edu        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
4107405SAli.Saidi@ARM.com        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
4117405SAli.Saidi@ARM.com    }
4127757SAli.Saidi@ARM.com    tgt->st_mode = htog(tgt->st_mode);
41310037SARM gem5 Developers    tgt->st_nlink = host->st_nlink;
41410037SARM gem5 Developers    tgt->st_nlink = htog(tgt->st_nlink);
41510037SARM gem5 Developers    tgt->st_uid = host->st_uid;
41610037SARM gem5 Developers    tgt->st_uid = htog(tgt->st_uid);
41710037SARM gem5 Developers    tgt->st_gid = host->st_gid;
41810037SARM gem5 Developers    tgt->st_gid = htog(tgt->st_gid);
41910037SARM gem5 Developers    if (fakeTTY)
42010037SARM gem5 Developers        tgt->st_rdev = 0x880d;
42110037SARM gem5 Developers    else
42210037SARM gem5 Developers        tgt->st_rdev = host->st_rdev;
42310037SARM gem5 Developers    tgt->st_rdev = htog(tgt->st_rdev);
42410037SARM gem5 Developers    tgt->st_size = host->st_size;
42510037SARM gem5 Developers    tgt->st_size = htog(tgt->st_size);
42610037SARM gem5 Developers    tgt->st_atimeX = host->st_atime;
42710037SARM gem5 Developers    tgt->st_atimeX = htog(tgt->st_atimeX);
42810037SARM gem5 Developers    tgt->st_mtimeX = host->st_mtime;
42910037SARM gem5 Developers    tgt->st_mtimeX = htog(tgt->st_mtimeX);
43010037SARM gem5 Developers    tgt->st_ctimeX = host->st_ctime;
43110037SARM gem5 Developers    tgt->st_ctimeX = htog(tgt->st_ctimeX);
43210037SARM gem5 Developers    // Force the block size to be 8k. This helps to ensure buffered io works
43310037SARM gem5 Developers    // consistently across different hosts.
43410037SARM gem5 Developers    tgt->st_blksize = 0x2000;
43510037SARM gem5 Developers    tgt->st_blksize = htog(tgt->st_blksize);
43610037SARM gem5 Developers    tgt->st_blocks = host->st_blocks;
43710037SARM gem5 Developers    tgt->st_blocks = htog(tgt->st_blocks);
43810037SARM gem5 Developers}
43910037SARM gem5 Developers
44010037SARM gem5 Developers// Same for stat64
44110037SARM gem5 Developers
44210037SARM gem5 Developerstemplate <typename target_stat, typename host_stat64>
44310037SARM gem5 Developersstatic void
44410037SARM gem5 DevelopersconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
44510037SARM gem5 Developers{
44612667Schuan.zhu@arm.com    using namespace TheISA;
44710037SARM gem5 Developers
44810037SARM gem5 Developers    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
44910037SARM gem5 Developers#if defined(STAT_HAVE_NSEC)
45010037SARM gem5 Developers    tgt->st_atime_nsec = host->st_atime_nsec;
45110037SARM gem5 Developers    tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
45210037SARM gem5 Developers    tgt->st_mtime_nsec = host->st_mtime_nsec;
45310037SARM gem5 Developers    tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
45410037SARM gem5 Developers    tgt->st_ctime_nsec = host->st_ctime_nsec;
45510037SARM gem5 Developers    tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
45610037SARM gem5 Developers#else
45710037SARM gem5 Developers    tgt->st_atime_nsec = 0;
45810037SARM gem5 Developers    tgt->st_mtime_nsec = 0;
4598284SAli.Saidi@ARM.com    tgt->st_ctime_nsec = 0;
46010037SARM gem5 Developers#endif
46110037SARM gem5 Developers}
46210037SARM gem5 Developers
46310037SARM gem5 Developers//Here are a couple convenience functions
4649050Schander.sudanthi@arm.comtemplate<class OS>
46510037SARM gem5 Developersstatic void
46610037SARM gem5 DeveloperscopyOutStatBuf(TranslatingPort * mem, Addr addr,
46710037SARM gem5 Developers        hst_stat *host, bool fakeTTY = false)
46810037SARM gem5 Developers{
46910037SARM gem5 Developers    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
47010037SARM gem5 Developers    tgt_stat_buf tgt(addr);
47110037SARM gem5 Developers    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
47210037SARM gem5 Developers    tgt.copyOut(mem);
47310037SARM gem5 Developers}
47410037SARM gem5 Developers
47510037SARM gem5 Developerstemplate<class OS>
47610037SARM gem5 Developersstatic void
47710037SARM gem5 DeveloperscopyOutStat64Buf(TranslatingPort * mem, Addr addr,
47810037SARM gem5 Developers        hst_stat64 *host, bool fakeTTY = false)
47910037SARM gem5 Developers{
48010037SARM gem5 Developers    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
48110037SARM gem5 Developers    tgt_stat_buf tgt(addr);
48210037SARM gem5 Developers    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
4839050Schander.sudanthi@arm.com    tgt.copyOut(mem);
4848284SAli.Saidi@ARM.com}
48510037SARM gem5 Developers
48610037SARM gem5 Developers/// Target ioctl() handler.  For the most part, programs call ioctl()
48710037SARM gem5 Developers/// only to find out if their stdout is a tty, to determine whether to
48810037SARM gem5 Developers/// do line or block buffering.
48910037SARM gem5 Developerstemplate <class OS>
49010037SARM gem5 DevelopersSyscallReturn
49110037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
4927405SAli.Saidi@ARM.com          ThreadContext *tc)
4937731SAli.Saidi@ARM.com{
4948468Swade.walker@arm.com    int index = 0;
4958468Swade.walker@arm.com    int fd = process->getSyscallArg(tc, index);
4968468Swade.walker@arm.com    unsigned req = process->getSyscallArg(tc, index);
4977405SAli.Saidi@ARM.com
4987731SAli.Saidi@ARM.com    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
4997405SAli.Saidi@ARM.com
5007405SAli.Saidi@ARM.com    if (fd < 0 || process->sim_fd(fd) < 0) {
50111809Sbaz21@cam.ac.uk        // doesn't map to any simulator fd: not a valid target fd
50211809Sbaz21@cam.ac.uk        return -EBADF;
5039130Satgutier@umich.edu    }
5049130Satgutier@umich.edu
5059130Satgutier@umich.edu    switch (req) {
5069130Satgutier@umich.edu      case OS::TIOCISATTY_:
5079814Sandreas.hansson@arm.com      case OS::TIOCGETP_:
5089130Satgutier@umich.edu      case OS::TIOCSETP_:
5099130Satgutier@umich.edu      case OS::TIOCSETN_:
5109130Satgutier@umich.edu      case OS::TIOCSETC_:
5119130Satgutier@umich.edu      case OS::TIOCGETC_:
5129130Satgutier@umich.edu      case OS::TIOCGETS_:
5139130Satgutier@umich.edu      case OS::TIOCGETA_:
5149130Satgutier@umich.edu      case OS::TCSETAW_:
5159130Satgutier@umich.edu        return -ENOTTY;
5169130Satgutier@umich.edu
5179130Satgutier@umich.edu      default:
5189130Satgutier@umich.edu        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
5199130Satgutier@umich.edu              fd, req, tc->pcState());
5209130Satgutier@umich.edu    }
5219130Satgutier@umich.edu}
5229130Satgutier@umich.edu
5239130Satgutier@umich.edu/// Target open() handler.
5249130Satgutier@umich.edutemplate <class OS>
5259130Satgutier@umich.eduSyscallReturn
5269130Satgutier@umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
5279130Satgutier@umich.edu         ThreadContext *tc)
5289130Satgutier@umich.edu{
5299130Satgutier@umich.edu    std::string path;
5307583SAli.Saidi@arm.com
5317583SAli.Saidi@arm.com    int index = 0;
5327583SAli.Saidi@arm.com    if (!tc->getMemPort()->tryReadString(path,
53310461SAndreas.Sandberg@ARM.com                process->getSyscallArg(tc, index)))
53410461SAndreas.Sandberg@ARM.com        return -EFAULT;
53510461SAndreas.Sandberg@ARM.com
53610461SAndreas.Sandberg@ARM.com    if (path == "/dev/sysdev0") {
53710461SAndreas.Sandberg@ARM.com        // This is a memory-mapped high-resolution timer device on Alpha.
53810461SAndreas.Sandberg@ARM.com        // We don't support it, so just punt.
53910461SAndreas.Sandberg@ARM.com        warn("Ignoring open(%s, ...)\n", path);
5408302SAli.Saidi@ARM.com        return -ENOENT;
5418302SAli.Saidi@ARM.com    }
5427783SGiacomo.Gabrielli@arm.com
5437783SGiacomo.Gabrielli@arm.com    int tgtFlags = process->getSyscallArg(tc, index);
5447783SGiacomo.Gabrielli@arm.com    int mode = process->getSyscallArg(tc, index);
5457783SGiacomo.Gabrielli@arm.com    int hostFlags = 0;
54610037SARM gem5 Developers
54710037SARM gem5 Developers    // translate open flags
54810037SARM gem5 Developers    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
54910037SARM gem5 Developers        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
55010037SARM gem5 Developers            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
55110037SARM gem5 Developers            hostFlags |= OS::openFlagTable[i].hostFlag;
55210037SARM gem5 Developers        }
55310037SARM gem5 Developers    }
55410037SARM gem5 Developers
55510037SARM gem5 Developers    // any target flags left?
55610037SARM gem5 Developers    if (tgtFlags != 0)
55710037SARM gem5 Developers        warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
55810037SARM gem5 Developers
55910037SARM gem5 Developers#ifdef __CYGWIN32__
56010037SARM gem5 Developers    hostFlags |= O_BINARY;
56110037SARM gem5 Developers#endif
56210037SARM gem5 Developers
56310037SARM gem5 Developers    // Adjust path for current working directory
56410037SARM gem5 Developers    path = process->fullPath(path);
56510037SARM gem5 Developers
56610037SARM gem5 Developers    DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
56710037SARM gem5 Developers
56810037SARM gem5 Developers    int fd;
56910037SARM gem5 Developers    if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") ||
57010037SARM gem5 Developers        !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) {
57110037SARM gem5 Developers        // It's a proc/sys entery and requires special handling
57210037SARM gem5 Developers        fd = OS::openSpecialFile(path, process, tc);
57310037SARM gem5 Developers        return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
57410037SARM gem5 Developers     } else {
57510037SARM gem5 Developers        // open the file
57610037SARM gem5 Developers        fd = open(path.c_str(), hostFlags, mode);
57710037SARM gem5 Developers        return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
57810338SCurtis.Dunham@arm.com     }
57910338SCurtis.Dunham@arm.com
58010338SCurtis.Dunham@arm.com}
58110037SARM gem5 Developers
58210037SARM gem5 Developers/// Target sysinfo() handler.
58310037SARM gem5 Developerstemplate <class OS>
58410037SARM gem5 DevelopersSyscallReturn
58510037SARM gem5 DeveloperssysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
58610037SARM gem5 Developers         ThreadContext *tc)
58710037SARM gem5 Developers{
58810037SARM gem5 Developers
58910037SARM gem5 Developers    int index = 0;
59010037SARM gem5 Developers    TypedBufferArg<typename OS::tgt_sysinfo>
59110037SARM gem5 Developers        sysinfo(process->getSyscallArg(tc, index));
59210037SARM gem5 Developers
59310037SARM gem5 Developers    sysinfo->uptime=seconds_since_epoch;
59410037SARM gem5 Developers    sysinfo->totalram=process->system->memSize();
59510037SARM gem5 Developers
59610037SARM gem5 Developers    sysinfo.copyOut(tc->getMemPort());
59710037SARM gem5 Developers
59810037SARM gem5 Developers    return 0;
59910037SARM gem5 Developers}
60010037SARM gem5 Developers
60110037SARM gem5 Developers/// Target chmod() handler.
60210037SARM gem5 Developerstemplate <class OS>
60310037SARM gem5 DevelopersSyscallReturn
60410037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
60510037SARM gem5 Developers          ThreadContext *tc)
60610037SARM gem5 Developers{
60710037SARM gem5 Developers    std::string path;
60810037SARM gem5 Developers
6098549Sdaniel.johnson@arm.com    int index = 0;
6108868SMatt.Horsnell@arm.com    if (!tc->getMemPort()->tryReadString(path,
6118868SMatt.Horsnell@arm.com                process->getSyscallArg(tc, index))) {
6128868SMatt.Horsnell@arm.com        return -EFAULT;
6138868SMatt.Horsnell@arm.com    }
6148868SMatt.Horsnell@arm.com
6158868SMatt.Horsnell@arm.com    uint32_t mode = process->getSyscallArg(tc, index);
6168868SMatt.Horsnell@arm.com    mode_t hostMode = 0;
6178868SMatt.Horsnell@arm.com
6188868SMatt.Horsnell@arm.com    // XXX translate mode flags via OS::something???
61910461SAndreas.Sandberg@ARM.com    hostMode = mode;
6208868SMatt.Horsnell@arm.com
62110461SAndreas.Sandberg@ARM.com    // Adjust path for current working directory
62210037SARM gem5 Developers    path = process->fullPath(path);
6238868SMatt.Horsnell@arm.com
62410037SARM gem5 Developers    // do the chmod
62511150Smitch.hayenga@arm.com    int result = chmod(path.c_str(), hostMode);
62610037SARM gem5 Developers    if (result < 0)
62710037SARM gem5 Developers        return -errno;
62810037SARM gem5 Developers
62910037SARM gem5 Developers    return 0;
63011150Smitch.hayenga@arm.com}
63110037SARM gem5 Developers
63210037SARM gem5 Developers
63310037SARM gem5 Developers/// Target fchmod() handler.
63410037SARM gem5 Developerstemplate <class OS>
63510037SARM gem5 DevelopersSyscallReturn
63610037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
63710037SARM gem5 Developers           ThreadContext *tc)
63810037SARM gem5 Developers{
63910037SARM gem5 Developers    int index = 0;
64010037SARM gem5 Developers    int fd = process->getSyscallArg(tc, index);
64110037SARM gem5 Developers    if (fd < 0 || process->sim_fd(fd) < 0) {
64210037SARM gem5 Developers        // doesn't map to any simulator fd: not a valid target fd
64310037SARM gem5 Developers        return -EBADF;
64410037SARM gem5 Developers    }
64510037SARM gem5 Developers
64610037SARM gem5 Developers    uint32_t mode = process->getSyscallArg(tc, index);
64710037SARM gem5 Developers    mode_t hostMode = 0;
64810037SARM gem5 Developers
64910037SARM gem5 Developers    // XXX translate mode flags via OS::someting???
65010037SARM gem5 Developers    hostMode = mode;
65110037SARM gem5 Developers
65210037SARM gem5 Developers    // do the fchmod
65310037SARM gem5 Developers    int result = fchmod(process->sim_fd(fd), hostMode);
65410037SARM gem5 Developers    if (result < 0)
65510037SARM gem5 Developers        return -errno;
65610037SARM gem5 Developers
65710037SARM gem5 Developers    return 0;
65810037SARM gem5 Developers}
65910037SARM gem5 Developers
66011769SCurtis.Dunham@arm.com/// Target mremap() handler.
66111769SCurtis.Dunham@arm.comtemplate <class OS>
66210037SARM gem5 DevelopersSyscallReturn
66311770SCurtis.Dunham@arm.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
66411770SCurtis.Dunham@arm.com{
66510037SARM gem5 Developers    int index = 0;
66611770SCurtis.Dunham@arm.com    Addr start = process->getSyscallArg(tc, index);
66711769SCurtis.Dunham@arm.com    uint64_t old_length = process->getSyscallArg(tc, index);
66810844Sandreas.sandberg@arm.com    uint64_t new_length = process->getSyscallArg(tc, index);
66911772SCurtis.Dunham@arm.com    uint64_t flags = process->getSyscallArg(tc, index);
67011772SCurtis.Dunham@arm.com
67111772SCurtis.Dunham@arm.com    if ((start % TheISA::VMPageSize != 0) ||
67211772SCurtis.Dunham@arm.com            (new_length % TheISA::VMPageSize != 0)) {
67311774SCurtis.Dunham@arm.com        warn("mremap failing: arguments not page aligned");
67411774SCurtis.Dunham@arm.com        return -EINVAL;
67511774SCurtis.Dunham@arm.com    }
67611774SCurtis.Dunham@arm.com
67711774SCurtis.Dunham@arm.com    if (new_length > old_length) {
67811774SCurtis.Dunham@arm.com        if ((start + old_length) == process->mmap_end) {
67911774SCurtis.Dunham@arm.com            uint64_t diff = new_length - old_length;
68011773SCurtis.Dunham@arm.com            process->allocateMem(process->mmap_end, diff);
68111773SCurtis.Dunham@arm.com            process->mmap_end += diff;
68211773SCurtis.Dunham@arm.com            return start;
68311773SCurtis.Dunham@arm.com        } else {
68411773SCurtis.Dunham@arm.com            // sys/mman.h defined MREMAP_MAYMOVE
68511773SCurtis.Dunham@arm.com            if (!(flags & 1)) {
68611773SCurtis.Dunham@arm.com                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
68711772SCurtis.Dunham@arm.com                return -ENOMEM;
68810037SARM gem5 Developers            } else {
68912816Sgiacomo.travaglini@arm.com                process->pTable->remap(start, old_length, process->mmap_end);
69012816Sgiacomo.travaglini@arm.com                warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
69112816Sgiacomo.travaglini@arm.com                        process->mmap_end, process->mmap_end + new_length, new_length);
69210844Sandreas.sandberg@arm.com                start = process->mmap_end;
69310844Sandreas.sandberg@arm.com                // add on the remaining unallocated pages
69410844Sandreas.sandberg@arm.com                process->allocateMem(start + old_length,
69510844Sandreas.sandberg@arm.com                                     new_length - old_length);
69610844Sandreas.sandberg@arm.com                process->mmap_end += new_length;
69710844Sandreas.sandberg@arm.com                warn("returning %08p as start\n", start);
69810188Sgeoffrey.blake@arm.com                return start;
69910037SARM gem5 Developers            }
70010037SARM gem5 Developers        }
7017405SAli.Saidi@ARM.com    } else {
7027405SAli.Saidi@ARM.com        process->pTable->unmap(start + new_length, old_length - new_length);
7037405SAli.Saidi@ARM.com        return start;
7047405SAli.Saidi@ARM.com    }
7057405SAli.Saidi@ARM.com}
7067405SAli.Saidi@ARM.com
7077405SAli.Saidi@ARM.com/// Target stat() handler.
7087405SAli.Saidi@ARM.comtemplate <class OS>
7097614Sminkyu.jeong@arm.comSyscallReturn
71012478SCurtis.Dunham@arm.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
71112478SCurtis.Dunham@arm.com         ThreadContext *tc)
71212478SCurtis.Dunham@arm.com{
71312478SCurtis.Dunham@arm.com    std::string path;
71412478SCurtis.Dunham@arm.com
71511771SCurtis.Dunham@arm.com    int index = 0;
71612478SCurtis.Dunham@arm.com    if (!tc->getMemPort()->tryReadString(path,
71712478SCurtis.Dunham@arm.com                process->getSyscallArg(tc, index))) {
71810037SARM gem5 Developers        return -EFAULT;
71912478SCurtis.Dunham@arm.com    }
72010037SARM gem5 Developers    Addr bufPtr = process->getSyscallArg(tc, index);
72112478SCurtis.Dunham@arm.com
72210037SARM gem5 Developers    // Adjust path for current working directory
72312478SCurtis.Dunham@arm.com    path = process->fullPath(path);
72410037SARM gem5 Developers
7257405SAli.Saidi@ARM.com    struct stat hostBuf;
7267405SAli.Saidi@ARM.com    int result = stat(path.c_str(), &hostBuf);
7277405SAli.Saidi@ARM.com
7287405SAli.Saidi@ARM.com    if (result < 0)
7297405SAli.Saidi@ARM.com        return -errno;
7307749SAli.Saidi@ARM.com
7317405SAli.Saidi@ARM.com    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
73210037SARM gem5 Developers
73310037SARM gem5 Developers    return 0;
7348284SAli.Saidi@ARM.com}
7357405SAli.Saidi@ARM.com
7367405SAli.Saidi@ARM.com
7377749SAli.Saidi@ARM.com/// Target stat64() handler.
7387749SAli.Saidi@ARM.comtemplate <class OS>
7397749SAli.Saidi@ARM.comSyscallReturn
7407749SAli.Saidi@ARM.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
7417405SAli.Saidi@ARM.com           ThreadContext *tc)
74212510Sgiacomo.travaglini@arm.com{
74312406Sgabeblack@google.com    std::string path;
74412406Sgabeblack@google.com
7457749SAli.Saidi@ARM.com    int index = 0;
7467749SAli.Saidi@ARM.com    if (!tc->getMemPort()->tryReadString(path,
7477614Sminkyu.jeong@arm.com                process->getSyscallArg(tc, index)))
7487614Sminkyu.jeong@arm.com        return -EFAULT;
7497720Sgblack@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
7507720Sgblack@eecs.umich.edu
7517720Sgblack@eecs.umich.edu    // Adjust path for current working directory
75212763Sgiacomo.travaglini@arm.com    path = process->fullPath(path);
7538887Sgeoffrey.blake@arm.com
7548887Sgeoffrey.blake@arm.com#if NO_STAT64
7558887Sgeoffrey.blake@arm.com    struct stat  hostBuf;
7568887Sgeoffrey.blake@arm.com    int result = stat(path.c_str(), &hostBuf);
7578887Sgeoffrey.blake@arm.com#else
7588887Sgeoffrey.blake@arm.com    struct stat64 hostBuf;
7598887Sgeoffrey.blake@arm.com    int result = stat64(path.c_str(), &hostBuf);
7608887Sgeoffrey.blake@arm.com#endif
7618887Sgeoffrey.blake@arm.com
7627408Sgblack@eecs.umich.edu    if (result < 0)
76310037SARM gem5 Developers        return -errno;
76410037SARM gem5 Developers
76510037SARM gem5 Developers    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
76610037SARM gem5 Developers
76710037SARM gem5 Developers    return 0;
76810037SARM gem5 Developers}
76910037SARM gem5 Developers
77010037SARM gem5 Developers
77110037SARM gem5 Developers/// Target fstat64() handler.
77210037SARM gem5 Developerstemplate <class OS>
77310037SARM gem5 DevelopersSyscallReturn
7747408Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
7757408Sgblack@eecs.umich.edu            ThreadContext *tc)
7768206SWilliam.Wang@arm.com{
7778206SWilliam.Wang@arm.com    int index = 0;
7788206SWilliam.Wang@arm.com    int fd = process->getSyscallArg(tc, index);
7798206SWilliam.Wang@arm.com    Addr bufPtr = process->getSyscallArg(tc, index);
7808206SWilliam.Wang@arm.com    if (fd < 0 || process->sim_fd(fd) < 0) {
7818206SWilliam.Wang@arm.com        // doesn't map to any simulator fd: not a valid target fd
7828206SWilliam.Wang@arm.com        return -EBADF;
7838206SWilliam.Wang@arm.com    }
78410037SARM gem5 Developers
78510037SARM gem5 Developers#if NO_STAT64
78610037SARM gem5 Developers    struct stat  hostBuf;
78710037SARM gem5 Developers    int result = fstat(process->sim_fd(fd), &hostBuf);
78810037SARM gem5 Developers#else
78912667Schuan.zhu@arm.com    struct stat64  hostBuf;
79010037SARM gem5 Developers    int result = fstat64(process->sim_fd(fd), &hostBuf);
79110037SARM gem5 Developers#endif
79210037SARM gem5 Developers
79310037SARM gem5 Developers    if (result < 0)
79410037SARM gem5 Developers        return -errno;
79510037SARM gem5 Developers
79610037SARM gem5 Developers    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
79710037SARM gem5 Developers
7988206SWilliam.Wang@arm.com    return 0;
79910037SARM gem5 Developers}
80010037SARM gem5 Developers
80110037SARM gem5 Developers
80210037SARM gem5 Developers/// Target lstat() handler.
80310037SARM gem5 Developerstemplate <class OS>
80410037SARM gem5 DevelopersSyscallReturn
80510037SARM gem5 DeveloperslstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
80610037SARM gem5 Developers          ThreadContext *tc)
80710037SARM gem5 Developers{
80810037SARM gem5 Developers    std::string path;
80910037SARM gem5 Developers
81010037SARM gem5 Developers    int index = 0;
81110037SARM gem5 Developers    if (!tc->getMemPort()->tryReadString(path,
81210037SARM gem5 Developers                process->getSyscallArg(tc, index))) {
81310037SARM gem5 Developers        return -EFAULT;
81410037SARM gem5 Developers    }
81510037SARM gem5 Developers    Addr bufPtr = process->getSyscallArg(tc, index);
81610037SARM gem5 Developers
81710037SARM gem5 Developers    // Adjust path for current working directory
81810037SARM gem5 Developers    path = process->fullPath(path);
81910037SARM gem5 Developers
82010037SARM gem5 Developers    struct stat hostBuf;
82110037SARM gem5 Developers    int result = lstat(path.c_str(), &hostBuf);
82210037SARM gem5 Developers
82310037SARM gem5 Developers    if (result < 0)
82410037SARM gem5 Developers        return -errno;
82510037SARM gem5 Developers
82610037SARM gem5 Developers    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
82710037SARM gem5 Developers
8288206SWilliam.Wang@arm.com    return 0;
8298206SWilliam.Wang@arm.com}
8307408Sgblack@eecs.umich.edu
8317408Sgblack@eecs.umich.edu/// Target lstat64() handler.
8327408Sgblack@eecs.umich.edutemplate <class OS>
8337731SAli.Saidi@ARM.comSyscallReturn
8348206SWilliam.Wang@arm.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
83510037SARM gem5 Developers            ThreadContext *tc)
83610037SARM gem5 Developers{
83710037SARM gem5 Developers    std::string path;
83810037SARM gem5 Developers
83910037SARM gem5 Developers    int index = 0;
8407408Sgblack@eecs.umich.edu    if (!tc->getMemPort()->tryReadString(path,
8417408Sgblack@eecs.umich.edu                process->getSyscallArg(tc, index))) {
8427408Sgblack@eecs.umich.edu        return -EFAULT;
8437408Sgblack@eecs.umich.edu    }
8447408Sgblack@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
8457408Sgblack@eecs.umich.edu
8467408Sgblack@eecs.umich.edu    // Adjust path for current working directory
8477408Sgblack@eecs.umich.edu    path = process->fullPath(path);
8487408Sgblack@eecs.umich.edu
8497408Sgblack@eecs.umich.edu#if NO_STAT64
85010037SARM gem5 Developers    struct stat hostBuf;
85110037SARM gem5 Developers    int result = lstat(path.c_str(), &hostBuf);
85210037SARM gem5 Developers#else
85310037SARM gem5 Developers    struct stat64 hostBuf;
85410037SARM gem5 Developers    int result = lstat64(path.c_str(), &hostBuf);
85510037SARM gem5 Developers#endif
8567408Sgblack@eecs.umich.edu
8577408Sgblack@eecs.umich.edu    if (result < 0)
8587408Sgblack@eecs.umich.edu        return -errno;
8597408Sgblack@eecs.umich.edu
8607408Sgblack@eecs.umich.edu    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
8617408Sgblack@eecs.umich.edu
8627408Sgblack@eecs.umich.edu    return 0;
8637408Sgblack@eecs.umich.edu}
8647408Sgblack@eecs.umich.edu
8657408Sgblack@eecs.umich.edu/// Target fstat() handler.
8667408Sgblack@eecs.umich.edutemplate <class OS>
8677408Sgblack@eecs.umich.eduSyscallReturn
86810037SARM gem5 DevelopersfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
86910037SARM gem5 Developers          ThreadContext *tc)
8709377Sgblack@eecs.umich.edu{
8717408Sgblack@eecs.umich.edu    int index = 0;
8727408Sgblack@eecs.umich.edu    int fd = process->sim_fd(process->getSyscallArg(tc, index));
87310037SARM gem5 Developers    Addr bufPtr = process->getSyscallArg(tc, index);
87410037SARM gem5 Developers
87510037SARM gem5 Developers    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
87610037SARM gem5 Developers
87710037SARM gem5 Developers    if (fd < 0)
87810037SARM gem5 Developers        return -EBADF;
87910037SARM gem5 Developers
88010037SARM gem5 Developers    struct stat hostBuf;
88110037SARM gem5 Developers    int result = fstat(fd, &hostBuf);
88210037SARM gem5 Developers
88310037SARM gem5 Developers    if (result < 0)
88410037SARM gem5 Developers        return -errno;
88510037SARM gem5 Developers
88610037SARM gem5 Developers    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
88710037SARM gem5 Developers
88810037SARM gem5 Developers    return 0;
88910037SARM gem5 Developers}
89010037SARM gem5 Developers
89110037SARM gem5 Developers
89210037SARM gem5 Developers/// Target statfs() handler.
89310037SARM gem5 Developerstemplate <class OS>
89410037SARM gem5 DevelopersSyscallReturn
89510037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
89610037SARM gem5 Developers           ThreadContext *tc)
89710037SARM gem5 Developers{
89810037SARM gem5 Developers    std::string path;
89910037SARM gem5 Developers
90010037SARM gem5 Developers    int index = 0;
90110037SARM gem5 Developers    if (!tc->getMemPort()->tryReadString(path,
90210037SARM gem5 Developers                process->getSyscallArg(tc, index))) {
90310037SARM gem5 Developers        return -EFAULT;
90410037SARM gem5 Developers    }
90510037SARM gem5 Developers    Addr bufPtr = process->getSyscallArg(tc, index);
90610037SARM gem5 Developers
90710037SARM gem5 Developers    // Adjust path for current working directory
90810037SARM gem5 Developers    path = process->fullPath(path);
90910037SARM gem5 Developers
9108302SAli.Saidi@ARM.com    struct statfs hostBuf;
9118302SAli.Saidi@ARM.com    int result = statfs(path.c_str(), &hostBuf);
9128302SAli.Saidi@ARM.com
91310037SARM gem5 Developers    if (result < 0)
9148302SAli.Saidi@ARM.com        return -errno;
9158302SAli.Saidi@ARM.com
9168302SAli.Saidi@ARM.com    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
9177783SGiacomo.Gabrielli@arm.com
9187783SGiacomo.Gabrielli@arm.com    return 0;
91910037SARM gem5 Developers}
92010037SARM gem5 Developers
9217783SGiacomo.Gabrielli@arm.com
9227783SGiacomo.Gabrielli@arm.com/// Target fstatfs() handler.
9237783SGiacomo.Gabrielli@arm.comtemplate <class OS>
9247783SGiacomo.Gabrielli@arm.comSyscallReturn
9257783SGiacomo.Gabrielli@arm.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
92610037SARM gem5 Developers            ThreadContext *tc)
92710037SARM gem5 Developers{
9287783SGiacomo.Gabrielli@arm.com    int index = 0;
9297783SGiacomo.Gabrielli@arm.com    int fd = process->sim_fd(process->getSyscallArg(tc, index));
9307783SGiacomo.Gabrielli@arm.com    Addr bufPtr = process->getSyscallArg(tc, index);
9317408Sgblack@eecs.umich.edu
9327408Sgblack@eecs.umich.edu    if (fd < 0)
9338206SWilliam.Wang@arm.com        return -EBADF;
9348206SWilliam.Wang@arm.com
9357408Sgblack@eecs.umich.edu    struct statfs hostBuf;
9367408Sgblack@eecs.umich.edu    int result = fstatfs(fd, &hostBuf);
93710037SARM gem5 Developers
9387408Sgblack@eecs.umich.edu    if (result < 0)
9397408Sgblack@eecs.umich.edu        return -errno;
94010037SARM gem5 Developers
94110037SARM gem5 Developers    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
94210037SARM gem5 Developers
94310037SARM gem5 Developers    return 0;
94410037SARM gem5 Developers}
94510037SARM gem5 Developers
94610037SARM gem5 Developers
94710037SARM gem5 Developers/// Target writev() handler.
94810037SARM gem5 Developerstemplate <class OS>
94910037SARM gem5 DevelopersSyscallReturn
95010037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
95110037SARM gem5 Developers           ThreadContext *tc)
95210037SARM gem5 Developers{
95310037SARM gem5 Developers    int index = 0;
95410037SARM gem5 Developers    int fd = process->getSyscallArg(tc, index);
95510037SARM gem5 Developers    if (fd < 0 || process->sim_fd(fd) < 0) {
95610037SARM gem5 Developers        // doesn't map to any simulator fd: not a valid target fd
95710037SARM gem5 Developers        return -EBADF;
95810037SARM gem5 Developers    }
95910037SARM gem5 Developers
96010037SARM gem5 Developers    TranslatingPort *p = tc->getMemPort();
96110037SARM gem5 Developers    uint64_t tiov_base = process->getSyscallArg(tc, index);
96210037SARM gem5 Developers    size_t count = process->getSyscallArg(tc, index);
96310037SARM gem5 Developers    struct iovec hiov[count];
96410037SARM gem5 Developers    for (size_t i = 0; i < count; ++i) {
96510037SARM gem5 Developers        typename OS::tgt_iovec tiov;
96610037SARM gem5 Developers
96710037SARM gem5 Developers        p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
96810037SARM gem5 Developers                    (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
96910037SARM gem5 Developers        hiov[i].iov_len = gtoh(tiov.iov_len);
97010037SARM gem5 Developers        hiov[i].iov_base = new char [hiov[i].iov_len];
97110037SARM gem5 Developers        p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
97212406Sgabeblack@google.com                    hiov[i].iov_len);
97312406Sgabeblack@google.com    }
97410037SARM gem5 Developers
9757408Sgblack@eecs.umich.edu    int result = writev(process->sim_fd(fd), hiov, count);
9767408Sgblack@eecs.umich.edu
9777408Sgblack@eecs.umich.edu    for (size_t i = 0; i < count; ++i)
97810037SARM gem5 Developers        delete [] (char *)hiov[i].iov_base;
97912639Sgiacomo.travaglini@arm.com
98012639Sgiacomo.travaglini@arm.com    if (result < 0)
98112639Sgiacomo.travaglini@arm.com        return -errno;
98212639Sgiacomo.travaglini@arm.com
98312639Sgiacomo.travaglini@arm.com    return 0;
98412639Sgiacomo.travaglini@arm.com}
98512639Sgiacomo.travaglini@arm.com
98612639Sgiacomo.travaglini@arm.com
98710037SARM gem5 Developers/// Target mmap() handler.
9887408Sgblack@eecs.umich.edu///
98910037SARM gem5 Developers/// We don't really handle mmap().  If the target is mmaping an
99010037SARM gem5 Developers/// anonymous region or /dev/zero, we can get away with doing basically
99112406Sgabeblack@google.com/// nothing (since memory is initialized to zero and the simulator
99212406Sgabeblack@google.com/// doesn't really check addresses anyway).
9937408Sgblack@eecs.umich.edu///
9949385SAndreas.Sandberg@arm.comtemplate <class OS>
9959385SAndreas.Sandberg@arm.comSyscallReturn
9969385SAndreas.Sandberg@arm.commmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
99710461SAndreas.Sandberg@ARM.com{
9989385SAndreas.Sandberg@arm.com    int index = 0;
9999385SAndreas.Sandberg@arm.com    Addr start = p->getSyscallArg(tc, index);
10009385SAndreas.Sandberg@arm.com    uint64_t length = p->getSyscallArg(tc, index);
10019385SAndreas.Sandberg@arm.com    index++; // int prot = p->getSyscallArg(tc, index);
10029385SAndreas.Sandberg@arm.com    int flags = p->getSyscallArg(tc, index);
10039385SAndreas.Sandberg@arm.com    int tgt_fd = p->getSyscallArg(tc, index);
10049385SAndreas.Sandberg@arm.com    // int offset = p->getSyscallArg(tc, index);
10059385SAndreas.Sandberg@arm.com
10069385SAndreas.Sandberg@arm.com    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
10079385SAndreas.Sandberg@arm.com        Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd);
10089385SAndreas.Sandberg@arm.com        if (!fd_map || fd_map->fd < 0) {
10099385SAndreas.Sandberg@arm.com            warn("mmap failing: target fd %d is not valid\n", tgt_fd);
10109385SAndreas.Sandberg@arm.com            return -EBADF;
10117408Sgblack@eecs.umich.edu        }
10127408Sgblack@eecs.umich.edu
10137408Sgblack@eecs.umich.edu        if (fd_map->filename != "/dev/zero") {
101410037SARM gem5 Developers            // This is very likely broken, but leave a warning here
101510037SARM gem5 Developers            // (rather than panic) in case /dev/zero is known by
101610037SARM gem5 Developers            // another name on some platform
101710037SARM gem5 Developers            warn("allowing mmap of file %s; mmap not supported on files"
101810037SARM gem5 Developers                 " other than /dev/zero\n", fd_map->filename);
101910037SARM gem5 Developers        }
102010037SARM gem5 Developers    }
102110037SARM gem5 Developers
102210037SARM gem5 Developers    if ((start  % TheISA::VMPageSize) != 0 ||
102313116Sgiacomo.travaglini@arm.com        (length % TheISA::VMPageSize) != 0) {
102410037SARM gem5 Developers        warn("mmap failing: arguments not page-aligned: "
102510037SARM gem5 Developers             "start 0x%x length 0x%x",
10269385SAndreas.Sandberg@arm.com             start, length);
10277408Sgblack@eecs.umich.edu        return -EINVAL;
10289385SAndreas.Sandberg@arm.com    }
102912605Sgiacomo.travaglini@arm.com
103012605Sgiacomo.travaglini@arm.com    // are we ok with clobbering existing mappings?  only set this to
103112605Sgiacomo.travaglini@arm.com    // true if the user has been warned.
103212605Sgiacomo.travaglini@arm.com    bool clobber = false;
103312605Sgiacomo.travaglini@arm.com
103412605Sgiacomo.travaglini@arm.com    // try to use the caller-provided address if there is one
103512605Sgiacomo.travaglini@arm.com    bool use_provided_address = (start != 0);
103612605Sgiacomo.travaglini@arm.com
103712605Sgiacomo.travaglini@arm.com    if (use_provided_address) {
103812605Sgiacomo.travaglini@arm.com        // check to see if the desired address is already in use
103912605Sgiacomo.travaglini@arm.com        if (!p->pTable->isUnmapped(start, length)) {
10407408Sgblack@eecs.umich.edu            // there are existing mappings in the desired range
104112605Sgiacomo.travaglini@arm.com            // whether we clobber them or not depends on whether the caller
104212605Sgiacomo.travaglini@arm.com            // specified MAP_FIXED
104312605Sgiacomo.travaglini@arm.com            if (flags & OS::TGT_MAP_FIXED) {
104412605Sgiacomo.travaglini@arm.com                // MAP_FIXED specified: clobber existing mappings
104512605Sgiacomo.travaglini@arm.com                warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n",
104612605Sgiacomo.travaglini@arm.com                     start);
104712605Sgiacomo.travaglini@arm.com                clobber = true;
104812605Sgiacomo.travaglini@arm.com            } else {
104912605Sgiacomo.travaglini@arm.com                // MAP_FIXED not specified: ignore suggested start address
10507408Sgblack@eecs.umich.edu                warn("mmap: ignoring suggested map address 0x%x\n", start);
105112605Sgiacomo.travaglini@arm.com                use_provided_address = false;
105212605Sgiacomo.travaglini@arm.com            }
105312605Sgiacomo.travaglini@arm.com        }
105412605Sgiacomo.travaglini@arm.com    }
105512605Sgiacomo.travaglini@arm.com
105612605Sgiacomo.travaglini@arm.com    if (!use_provided_address) {
105712605Sgiacomo.travaglini@arm.com        // no address provided, or provided address unusable:
105812605Sgiacomo.travaglini@arm.com        // pick next address from our "mmap region"
105912605Sgiacomo.travaglini@arm.com        if (OS::mmapGrowsDown()) {
10607408Sgblack@eecs.umich.edu            start = p->mmap_end - length;
106112605Sgiacomo.travaglini@arm.com            p->mmap_end = start;
106212605Sgiacomo.travaglini@arm.com        } else {
106312605Sgiacomo.travaglini@arm.com            start = p->mmap_end;
106412605Sgiacomo.travaglini@arm.com            p->mmap_end += length;
106512605Sgiacomo.travaglini@arm.com        }
106612605Sgiacomo.travaglini@arm.com    }
106712605Sgiacomo.travaglini@arm.com
106812605Sgiacomo.travaglini@arm.com    p->allocateMem(start, length, clobber);
106912605Sgiacomo.travaglini@arm.com
107012605Sgiacomo.travaglini@arm.com    return start;
107112605Sgiacomo.travaglini@arm.com}
107212605Sgiacomo.travaglini@arm.com
107312605Sgiacomo.travaglini@arm.com/// Target getrlimit() handler.
107412576Sgiacomo.travaglini@arm.comtemplate <class OS>
107512605Sgiacomo.travaglini@arm.comSyscallReturn
107612605Sgiacomo.travaglini@arm.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
107712605Sgiacomo.travaglini@arm.com        ThreadContext *tc)
107812605Sgiacomo.travaglini@arm.com{
107912605Sgiacomo.travaglini@arm.com    int index = 0;
108012605Sgiacomo.travaglini@arm.com    unsigned resource = process->getSyscallArg(tc, index);
108112605Sgiacomo.travaglini@arm.com    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
108212605Sgiacomo.travaglini@arm.com
108312605Sgiacomo.travaglini@arm.com    switch (resource) {
108412605Sgiacomo.travaglini@arm.com        case OS::TGT_RLIMIT_STACK:
108512605Sgiacomo.travaglini@arm.com            // max stack size in bytes: make up a number (8MB for now)
108612605Sgiacomo.travaglini@arm.com            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
108712605Sgiacomo.travaglini@arm.com            rlp->rlim_cur = htog(rlp->rlim_cur);
108812605Sgiacomo.travaglini@arm.com            rlp->rlim_max = htog(rlp->rlim_max);
108912576Sgiacomo.travaglini@arm.com            break;
109012605Sgiacomo.travaglini@arm.com
109112605Sgiacomo.travaglini@arm.com        case OS::TGT_RLIMIT_DATA:
109212605Sgiacomo.travaglini@arm.com            // max data segment size in bytes: make up a number
109312605Sgiacomo.travaglini@arm.com            rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
109412605Sgiacomo.travaglini@arm.com            rlp->rlim_cur = htog(rlp->rlim_cur);
109512605Sgiacomo.travaglini@arm.com            rlp->rlim_max = htog(rlp->rlim_max);
109612605Sgiacomo.travaglini@arm.com            break;
109712605Sgiacomo.travaglini@arm.com
109812605Sgiacomo.travaglini@arm.com        default:
109912605Sgiacomo.travaglini@arm.com            std::cerr << "getrlimitFunc: unimplemented resource " << resource
110012605Sgiacomo.travaglini@arm.com                << std::endl;
110112605Sgiacomo.travaglini@arm.com            abort();
110212605Sgiacomo.travaglini@arm.com            break;
110312605Sgiacomo.travaglini@arm.com    }
110412605Sgiacomo.travaglini@arm.com
110512605Sgiacomo.travaglini@arm.com    rlp.copyOut(tc->getMemPort());
110612605Sgiacomo.travaglini@arm.com    return 0;
110712605Sgiacomo.travaglini@arm.com}
110812605Sgiacomo.travaglini@arm.com
110912605Sgiacomo.travaglini@arm.com/// Target gettimeofday() handler.
111012605Sgiacomo.travaglini@arm.comtemplate <class OS>
111112605Sgiacomo.travaglini@arm.comSyscallReturn
111212605Sgiacomo.travaglini@arm.comgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
111312605Sgiacomo.travaglini@arm.com        ThreadContext *tc)
111412605Sgiacomo.travaglini@arm.com{
111512605Sgiacomo.travaglini@arm.com    int index = 0;
11167408Sgblack@eecs.umich.edu    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
111712605Sgiacomo.travaglini@arm.com
111812605Sgiacomo.travaglini@arm.com    getElapsedTime(tp->tv_sec, tp->tv_usec);
111912605Sgiacomo.travaglini@arm.com    tp->tv_sec += seconds_since_epoch;
112012605Sgiacomo.travaglini@arm.com    tp->tv_sec = TheISA::htog(tp->tv_sec);
112112605Sgiacomo.travaglini@arm.com    tp->tv_usec = TheISA::htog(tp->tv_usec);
112212605Sgiacomo.travaglini@arm.com
112312605Sgiacomo.travaglini@arm.com    tp.copyOut(tc->getMemPort());
112412605Sgiacomo.travaglini@arm.com
112512605Sgiacomo.travaglini@arm.com    return 0;
112612605Sgiacomo.travaglini@arm.com}
112712605Sgiacomo.travaglini@arm.com
112812605Sgiacomo.travaglini@arm.com
112912605Sgiacomo.travaglini@arm.com/// Target utimes() handler.
113012605Sgiacomo.travaglini@arm.comtemplate <class OS>
113112605Sgiacomo.travaglini@arm.comSyscallReturn
113212605Sgiacomo.travaglini@arm.comutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
113312576Sgiacomo.travaglini@arm.com           ThreadContext *tc)
113412605Sgiacomo.travaglini@arm.com{
113512605Sgiacomo.travaglini@arm.com    std::string path;
113612605Sgiacomo.travaglini@arm.com
113712605Sgiacomo.travaglini@arm.com    int index = 0;
113812605Sgiacomo.travaglini@arm.com    if (!tc->getMemPort()->tryReadString(path,
113912605Sgiacomo.travaglini@arm.com                process->getSyscallArg(tc, index))) {
114012605Sgiacomo.travaglini@arm.com        return -EFAULT;
114112605Sgiacomo.travaglini@arm.com    }
114212605Sgiacomo.travaglini@arm.com
114312605Sgiacomo.travaglini@arm.com    TypedBufferArg<typename OS::timeval [2]>
114412605Sgiacomo.travaglini@arm.com        tp(process->getSyscallArg(tc, index));
114512605Sgiacomo.travaglini@arm.com    tp.copyIn(tc->getMemPort());
114612576Sgiacomo.travaglini@arm.com
114712605Sgiacomo.travaglini@arm.com    struct timeval hostTimeval[2];
114812605Sgiacomo.travaglini@arm.com    for (int i = 0; i < 2; ++i)
114912605Sgiacomo.travaglini@arm.com    {
115012605Sgiacomo.travaglini@arm.com        hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
115112605Sgiacomo.travaglini@arm.com        hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
115212605Sgiacomo.travaglini@arm.com    }
115312605Sgiacomo.travaglini@arm.com
115412605Sgiacomo.travaglini@arm.com    // Adjust path for current working directory
115512605Sgiacomo.travaglini@arm.com    path = process->fullPath(path);
115612605Sgiacomo.travaglini@arm.com
115712605Sgiacomo.travaglini@arm.com    int result = utimes(path.c_str(), hostTimeval);
115812605Sgiacomo.travaglini@arm.com
115912605Sgiacomo.travaglini@arm.com    if (result < 0)
116012605Sgiacomo.travaglini@arm.com        return -errno;
116112605Sgiacomo.travaglini@arm.com
116212576Sgiacomo.travaglini@arm.com    return 0;
116312605Sgiacomo.travaglini@arm.com}
116412605Sgiacomo.travaglini@arm.com/// Target getrusage() function.
116512605Sgiacomo.travaglini@arm.comtemplate <class OS>
116612605Sgiacomo.travaglini@arm.comSyscallReturn
116712605Sgiacomo.travaglini@arm.comgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
116812605Sgiacomo.travaglini@arm.com              ThreadContext *tc)
116912605Sgiacomo.travaglini@arm.com{
117012605Sgiacomo.travaglini@arm.com    int index = 0;
117112605Sgiacomo.travaglini@arm.com    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
117212605Sgiacomo.travaglini@arm.com    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
117312605Sgiacomo.travaglini@arm.com
117412605Sgiacomo.travaglini@arm.com    rup->ru_utime.tv_sec = 0;
117512576Sgiacomo.travaglini@arm.com    rup->ru_utime.tv_usec = 0;
117612605Sgiacomo.travaglini@arm.com    rup->ru_stime.tv_sec = 0;
117712605Sgiacomo.travaglini@arm.com    rup->ru_stime.tv_usec = 0;
117812605Sgiacomo.travaglini@arm.com    rup->ru_maxrss = 0;
117912605Sgiacomo.travaglini@arm.com    rup->ru_ixrss = 0;
118012605Sgiacomo.travaglini@arm.com    rup->ru_idrss = 0;
118112605Sgiacomo.travaglini@arm.com    rup->ru_isrss = 0;
118212605Sgiacomo.travaglini@arm.com    rup->ru_minflt = 0;
118312605Sgiacomo.travaglini@arm.com    rup->ru_majflt = 0;
118412605Sgiacomo.travaglini@arm.com    rup->ru_nswap = 0;
118512605Sgiacomo.travaglini@arm.com    rup->ru_inblock = 0;
118612605Sgiacomo.travaglini@arm.com    rup->ru_oublock = 0;
118712605Sgiacomo.travaglini@arm.com    rup->ru_msgsnd = 0;
118812605Sgiacomo.travaglini@arm.com    rup->ru_msgrcv = 0;
118912605Sgiacomo.travaglini@arm.com    rup->ru_nsignals = 0;
119012605Sgiacomo.travaglini@arm.com    rup->ru_nvcsw = 0;
119112577Sgiacomo.travaglini@arm.com    rup->ru_nivcsw = 0;
119212605Sgiacomo.travaglini@arm.com
119312605Sgiacomo.travaglini@arm.com    switch (who) {
119412605Sgiacomo.travaglini@arm.com      case OS::TGT_RUSAGE_SELF:
119512605Sgiacomo.travaglini@arm.com        getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
119612605Sgiacomo.travaglini@arm.com        rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
119712605Sgiacomo.travaglini@arm.com        rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
119812605Sgiacomo.travaglini@arm.com        break;
119912605Sgiacomo.travaglini@arm.com
120012605Sgiacomo.travaglini@arm.com      case OS::TGT_RUSAGE_CHILDREN:
120112605Sgiacomo.travaglini@arm.com        // do nothing.  We have no child processes, so they take no time.
120212605Sgiacomo.travaglini@arm.com        break;
120312605Sgiacomo.travaglini@arm.com
120412605Sgiacomo.travaglini@arm.com      default:
120512605Sgiacomo.travaglini@arm.com        // don't really handle THREAD or CHILDREN, but just warn and
120612577Sgiacomo.travaglini@arm.com        // plow ahead
120712605Sgiacomo.travaglini@arm.com        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
120812605Sgiacomo.travaglini@arm.com             who);
120912605Sgiacomo.travaglini@arm.com    }
121012605Sgiacomo.travaglini@arm.com
121112605Sgiacomo.travaglini@arm.com    rup.copyOut(tc->getMemPort());
121212605Sgiacomo.travaglini@arm.com
121312605Sgiacomo.travaglini@arm.com    return 0;
121412605Sgiacomo.travaglini@arm.com}
121512605Sgiacomo.travaglini@arm.com
121612605Sgiacomo.travaglini@arm.com/// Target times() function.
121712605Sgiacomo.travaglini@arm.comtemplate <class OS>
121812605Sgiacomo.travaglini@arm.comSyscallReturn
121910037SARM gem5 DeveloperstimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
122012605Sgiacomo.travaglini@arm.com           ThreadContext *tc)
122112605Sgiacomo.travaglini@arm.com{
122212605Sgiacomo.travaglini@arm.com    int index = 0;
122312605Sgiacomo.travaglini@arm.com    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
122412605Sgiacomo.travaglini@arm.com
122512605Sgiacomo.travaglini@arm.com    // Fill in the time structure (in clocks)
122612605Sgiacomo.travaglini@arm.com    int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
122712605Sgiacomo.travaglini@arm.com    bufp->tms_utime = clocks;
122812605Sgiacomo.travaglini@arm.com    bufp->tms_stime = 0;
122912605Sgiacomo.travaglini@arm.com    bufp->tms_cutime = 0;
123012605Sgiacomo.travaglini@arm.com    bufp->tms_cstime = 0;
123112605Sgiacomo.travaglini@arm.com
123212605Sgiacomo.travaglini@arm.com    // Convert to host endianness
123310037SARM gem5 Developers    bufp->tms_utime = htog(bufp->tms_utime);
123412605Sgiacomo.travaglini@arm.com
123512605Sgiacomo.travaglini@arm.com    // Write back
123612605Sgiacomo.travaglini@arm.com    bufp.copyOut(tc->getMemPort());
123712605Sgiacomo.travaglini@arm.com
123812605Sgiacomo.travaglini@arm.com    // Return clock ticks since system boot
123912605Sgiacomo.travaglini@arm.com    return clocks;
124012605Sgiacomo.travaglini@arm.com}
124112605Sgiacomo.travaglini@arm.com
124212605Sgiacomo.travaglini@arm.com/// Target time() function.
124312605Sgiacomo.travaglini@arm.comtemplate <class OS>
124412605Sgiacomo.travaglini@arm.comSyscallReturn
124512605Sgiacomo.travaglini@arm.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
124612605Sgiacomo.travaglini@arm.com           ThreadContext *tc)
124710037SARM gem5 Developers{
124812605Sgiacomo.travaglini@arm.com    typename OS::time_t sec, usec;
124912605Sgiacomo.travaglini@arm.com    getElapsedTime(sec, usec);
125012605Sgiacomo.travaglini@arm.com    sec += seconds_since_epoch;
125112605Sgiacomo.travaglini@arm.com
125212605Sgiacomo.travaglini@arm.com    int index = 0;
125312605Sgiacomo.travaglini@arm.com    Addr taddr = (Addr)process->getSyscallArg(tc, index);
125412605Sgiacomo.travaglini@arm.com    if(taddr != 0) {
125512605Sgiacomo.travaglini@arm.com        typename OS::time_t t = sec;
125612605Sgiacomo.travaglini@arm.com        t = htog(t);
125712605Sgiacomo.travaglini@arm.com        TranslatingPort *p = tc->getMemPort();
125812605Sgiacomo.travaglini@arm.com        p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
125912605Sgiacomo.travaglini@arm.com    }
126010037SARM gem5 Developers    return sec;
126112605Sgiacomo.travaglini@arm.com}
126212605Sgiacomo.travaglini@arm.com
126312605Sgiacomo.travaglini@arm.com
126412605Sgiacomo.travaglini@arm.com#endif // __SIM_SYSCALL_EMUL_HH__
126512605Sgiacomo.travaglini@arm.com