syscall_emul.hh revision 7075
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
310796Sbrandon.potter@amd.com * All rights reserved.
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without
610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are
710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright
810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer;
910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright
1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the
1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution;
1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its
1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from
1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission.
151458SN/A *
16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27360SN/A *
28360SN/A * Authors: Steve Reinhardt
29360SN/A *          Kevin Lim
30360SN/A */
31360SN/A
32360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__
33360SN/A#define __SIM_SYSCALL_EMUL_HH__
34360SN/A
35360SN/A#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
36360SN/A                   defined(__FreeBSD__) || defined(__CYGWIN__))
37360SN/A
38360SN/A///
39360SN/A/// @file syscall_emul.hh
402665Ssaidi@eecs.umich.edu///
412665Ssaidi@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target
422665Ssaidi@eecs.umich.edu/// application on the host machine.
43360SN/A
44360SN/A#ifdef __CYGWIN32__
451354SN/A#include <sys/fcntl.h>  // for O_BINARY
461354SN/A#endif
47360SN/A#include <sys/stat.h>
4812018Sandreas.sandberg@arm.com#include <errno.h>
4912018Sandreas.sandberg@arm.com#include <fcntl.h>
5012018Sandreas.sandberg@arm.com#include <sys/uio.h>
5112018Sandreas.sandberg@arm.com#include <sys/time.h>
5212018Sandreas.sandberg@arm.com
5312018Sandreas.sandberg@arm.com#include <string>
5412018Sandreas.sandberg@arm.com
552064SN/A#include "base/chunk_generator.hh"
56360SN/A#include "base/intmath.hh"      // for RoundUp
57360SN/A#include "base/misc.hh"
58360SN/A#include "base/trace.hh"
59360SN/A#include "base/types.hh"
60360SN/A#include "config/the_isa.hh"
61360SN/A#include "cpu/base.hh"
6213936SAndrea.Mondelli@ucf.edu#include "cpu/thread_context.hh"
6313933Sbrandon.potter@amd.com#include "mem/translating_port.hh"
6413933Sbrandon.potter@amd.com#include "mem/page_table.hh"
6513933Sbrandon.potter@amd.com#include "sim/system.hh"
6613936SAndrea.Mondelli@ucf.edu#include "sim/process.hh"
6713936SAndrea.Mondelli@ucf.edu
6813936SAndrea.Mondelli@ucf.edu///
6913933Sbrandon.potter@amd.com/// System call descriptor.
7013933Sbrandon.potter@amd.com///
711809SN/Aclass SyscallDesc {
7211800Sbrandon.potter@amd.com
7311392Sbrandon.potter@amd.com  public:
741809SN/A
7511392Sbrandon.potter@amd.com    /// Typedef for target syscall handler functions.
7613902Sbrandon.potter@amd.com    typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
7713570Sbrandon.potter@amd.com                           LiveProcess *, ThreadContext *);
7813902Sbrandon.potter@amd.com
7911383Sbrandon.potter@amd.com    const char *name;   //!< Syscall name (e.g., "open").
8013568Sbrandon.potter@amd.com    FuncPtr funcPtr;    //!< Pointer to emulation function.
813113Sgblack@eecs.umich.edu    int flags;          //!< Flags (see Flags enum).
828229Snate@binkert.org
8313570Sbrandon.potter@amd.com    /// Flag values for controlling syscall behavior.
848229Snate@binkert.org    enum Flags {
8511594Santhony.gutierrez@amd.com        /// Don't set return regs according to funcPtr return value.
867075Snate@binkert.org        /// Used for syscalls with non-standard return conventions
878229Snate@binkert.org        /// that explicitly set the ThreadContext regs (e.g.,
8811856Sbrandon.potter@amd.com        /// sigreturn).
897075Snate@binkert.org        SuppressReturnValue = 1
90360SN/A    };
9112461Sgabeblack@google.com
9211886Sbrandon.potter@amd.com    /// Constructor.
9311800Sbrandon.potter@amd.com    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
9411392Sbrandon.potter@amd.com        : name(_name), funcPtr(_funcPtr), flags(_flags)
9512334Sgabeblack@google.com    {
961354SN/A    }
976216Snate@binkert.org
986658Snate@binkert.org    /// Emulate the syscall.  Public interface for calling through funcPtr.
992474SN/A    void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
1002680Sktlim@umich.edu};
1018229Snate@binkert.org
10211886Sbrandon.potter@amd.com
10310496Ssteve.reinhardt@amd.comclass BaseBufferArg {
10411911SBrandon.Potter@amd.com
1058229Snate@binkert.org  public:
10611794Sbrandon.potter@amd.com
10711886Sbrandon.potter@amd.com    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
10810497Ssteve.reinhardt@amd.com    {
10911794Sbrandon.potter@amd.com        bufPtr = new uint8_t[size];
110360SN/A        // clear out buffer: in case we only partially populate this,
11113629SAndrea.Mondelli@ucf.edu        // and then do a copyOut(), we want to make sure we don't
11213629SAndrea.Mondelli@ucf.edu        // introduce any random junk into the simulated address space
11313629SAndrea.Mondelli@ucf.edu        memset(bufPtr, 0, size);
11413629SAndrea.Mondelli@ucf.edu    }
115360SN/A
116360SN/A    virtual ~BaseBufferArg() { delete [] bufPtr; }
117360SN/A
118360SN/A    //
119360SN/A    // copy data into simulator space (read from target memory)
120360SN/A    //
121360SN/A    virtual bool copyIn(TranslatingPort *memport)
122360SN/A    {
12313933Sbrandon.potter@amd.com        memport->readBlob(addr, bufPtr, size);
124360SN/A        return true;    // no EFAULT detection for now
125378SN/A    }
1261706SN/A
12711851Sbrandon.potter@amd.com    //
128378SN/A    // copy data out of simulator space (write to target memory)
129378SN/A    //
130378SN/A    virtual bool copyOut(TranslatingPort *memport)
131378SN/A    {
132378SN/A        memport->writeBlob(addr, bufPtr, size);
1331706SN/A        return true;    // no EFAULT detection for now
13411851Sbrandon.potter@amd.com    }
135360SN/A
13611760Sbrandon.potter@amd.com  protected:
13711760Sbrandon.potter@amd.com    Addr addr;
13811851Sbrandon.potter@amd.com    int size;
13911760Sbrandon.potter@amd.com    uint8_t *bufPtr;
1406109Ssanchezd@stanford.edu};
1411706SN/A
14211851Sbrandon.potter@amd.com
143378SN/Aclass BufferArg : public BaseBufferArg
1446109Ssanchezd@stanford.edu{
1456109Ssanchezd@stanford.edu  public:
14611851Sbrandon.potter@amd.com    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1476109Ssanchezd@stanford.edu    void *bufferPtr()   { return bufPtr; }
14811886Sbrandon.potter@amd.com};
14911886Sbrandon.potter@amd.com
15011886Sbrandon.potter@amd.comtemplate <class T>
15111886Sbrandon.potter@amd.comclass TypedBufferArg : public BaseBufferArg
152378SN/A{
1531706SN/A  public:
15411851Sbrandon.potter@amd.com    // user can optionally specify a specific number of bytes to
155378SN/A    // allocate to deal with those structs that have variable-size
1565748SSteve.Reinhardt@amd.com    // arrays at the end
1575748SSteve.Reinhardt@amd.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
15811851Sbrandon.potter@amd.com        : BaseBufferArg(_addr, _size)
159378SN/A    { }
160378SN/A
1611706SN/A    // type case
16211851Sbrandon.potter@amd.com    operator T*() { return (T *)bufPtr; }
163378SN/A
164378SN/A    // dereference operators
1651706SN/A    T &operator*()       { return *((T *)bufPtr); }
16611851Sbrandon.potter@amd.com    T* operator->()      { return (T *)bufPtr; }
167378SN/A    T &operator[](int i) { return ((T *)bufPtr)[i]; }
1684118Sgblack@eecs.umich.edu};
1694118Sgblack@eecs.umich.edu
17011851Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
1714118Sgblack@eecs.umich.edu//
172378SN/A// The following emulation functions are generic enough that they
1731706SN/A// don't need to be recompiled for different emulated OS's.  They are
17411851Sbrandon.potter@amd.com// defined in sim/syscall_emul.cc.
175378SN/A//
17613568Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
17713568Sbrandon.potter@amd.com
17813568Sbrandon.potter@amd.com
17913568Sbrandon.potter@amd.com/// Handler for unimplemented syscalls that we haven't thought about.
180378SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
1811706SN/A                                LiveProcess *p, ThreadContext *tc);
18211851Sbrandon.potter@amd.com
183360SN/A/// Handler for unimplemented syscalls that we never intend to
1845513SMichael.Adler@intel.com/// implement (signal handling, etc.) and should not affect the correct
1855513SMichael.Adler@intel.com/// behavior of the program.  Print a warning only if the appropriate
18611851Sbrandon.potter@amd.com/// trace flag is enabled.  Return success to the target program.
1875513SMichael.Adler@intel.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num,
18810203SAli.Saidi@ARM.com                         LiveProcess *p, ThreadContext *tc);
18910203SAli.Saidi@ARM.com
19011851Sbrandon.potter@amd.com/// Target exit() handler: terminate current context.
19110203SAli.Saidi@ARM.comSyscallReturn exitFunc(SyscallDesc *desc, int num,
1925513SMichael.Adler@intel.com                       LiveProcess *p, ThreadContext *tc);
19311851Sbrandon.potter@amd.com
1945513SMichael.Adler@intel.com/// Target exit_group() handler: terminate simulation. (exit all threads)
195511SN/ASyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
19610633Smichaelupton@gmail.com                       LiveProcess *p, ThreadContext *tc);
19711851Sbrandon.potter@amd.com
19810633Smichaelupton@gmail.com/// Target getpagesize() handler.
1991706SN/ASyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
20011851Sbrandon.potter@amd.com                              LiveProcess *p, ThreadContext *tc);
201511SN/A
20212795Smattdsinclair@gmail.com/// Target brk() handler: set brk address.
20312795Smattdsinclair@gmail.comSyscallReturn brkFunc(SyscallDesc *desc, int num,
20412795Smattdsinclair@gmail.com                      LiveProcess *p, ThreadContext *tc);
20512795Smattdsinclair@gmail.com
20612796Smattdsinclair@gmail.com/// Target close() handler.
20712796Smattdsinclair@gmail.comSyscallReturn closeFunc(SyscallDesc *desc, int num,
20812796Smattdsinclair@gmail.com                        LiveProcess *p, ThreadContext *tc);
20912796Smattdsinclair@gmail.com
2105513SMichael.Adler@intel.com/// Target read() handler.
2115513SMichael.Adler@intel.comSyscallReturn readFunc(SyscallDesc *desc, int num,
21211851Sbrandon.potter@amd.com                       LiveProcess *p, ThreadContext *tc);
2135513SMichael.Adler@intel.com
21413031Sbrandon.potter@amd.com/// Target write() handler.
21513031Sbrandon.potter@amd.comSyscallReturn writeFunc(SyscallDesc *desc, int num,
21613031Sbrandon.potter@amd.com                        LiveProcess *p, ThreadContext *tc);
21713031Sbrandon.potter@amd.com
21813031Sbrandon.potter@amd.com/// Target lseek() handler.
21913031Sbrandon.potter@amd.comSyscallReturn lseekFunc(SyscallDesc *desc, int num,
22013031Sbrandon.potter@amd.com                        LiveProcess *p, ThreadContext *tc);
22113031Sbrandon.potter@amd.com
22213031Sbrandon.potter@amd.com/// Target _llseek() handler.
22313031Sbrandon.potter@amd.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num,
22413031Sbrandon.potter@amd.com                        LiveProcess *p, ThreadContext *tc);
22513031Sbrandon.potter@amd.com
226511SN/A/// Target munmap() handler.
2271706SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num,
22811851Sbrandon.potter@amd.com                         LiveProcess *p, ThreadContext *tc);
2291706SN/A
2301706SN/A/// Target gethostname() handler.
2311706SN/ASyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
2321706SN/A                              LiveProcess *p, ThreadContext *tc);
23311851Sbrandon.potter@amd.com
2341706SN/A/// Target getcwd() handler.
2351706SN/ASyscallReturn getcwdFunc(SyscallDesc *desc, int num,
2361706SN/A                         LiveProcess *p, ThreadContext *tc);
2371706SN/A
23811851Sbrandon.potter@amd.com/// Target unlink() handler.
2391706SN/ASyscallReturn readlinkFunc(SyscallDesc *desc, int num,
240511SN/A                           LiveProcess *p, ThreadContext *tc);
2416703Svince@csl.cornell.edu
2426703Svince@csl.cornell.edu/// Target unlink() handler.
24311851Sbrandon.potter@amd.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num,
2446703Svince@csl.cornell.edu                         LiveProcess *p, ThreadContext *tc);
2456685Stjones1@inf.ed.ac.uk
2466685Stjones1@inf.ed.ac.uk/// Target mkdir() handler.
24711851Sbrandon.potter@amd.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num,
2486685Stjones1@inf.ed.ac.uk                        LiveProcess *p, ThreadContext *tc);
2496685Stjones1@inf.ed.ac.uk
2505513SMichael.Adler@intel.com/// Target rename() handler.
2515513SMichael.Adler@intel.comSyscallReturn renameFunc(SyscallDesc *desc, int num,
25211851Sbrandon.potter@amd.com                         LiveProcess *p, ThreadContext *tc);
2535513SMichael.Adler@intel.com
25411885Sbrandon.potter@amd.com
25511885Sbrandon.potter@amd.com/// Target truncate() handler.
25611885Sbrandon.potter@amd.comSyscallReturn truncateFunc(SyscallDesc *desc, int num,
2575513SMichael.Adler@intel.com                           LiveProcess *p, ThreadContext *tc);
2581999SN/A
2591999SN/A
26011851Sbrandon.potter@amd.com/// Target ftruncate() handler.
2611999SN/ASyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
26211885Sbrandon.potter@amd.com                            LiveProcess *p, ThreadContext *tc);
26311885Sbrandon.potter@amd.com
26411885Sbrandon.potter@amd.com
2651999SN/A/// Target truncate64() handler.
2661999SN/ASyscallReturn truncate64Func(SyscallDesc *desc, int num,
2671999SN/A                             LiveProcess *p, ThreadContext *tc);
26811851Sbrandon.potter@amd.com
2691999SN/A/// Target ftruncate64() handler.
2703079Sstever@eecs.umich.eduSyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
2713079Sstever@eecs.umich.edu                              LiveProcess *p, ThreadContext *tc);
27211851Sbrandon.potter@amd.com
2733079Sstever@eecs.umich.edu
27411908SBrandon.Potter@amd.com/// Target umask() handler.
27511908SBrandon.Potter@amd.comSyscallReturn umaskFunc(SyscallDesc *desc, int num,
27611908SBrandon.Potter@amd.com                        LiveProcess *p, ThreadContext *tc);
27711908SBrandon.Potter@amd.com
27811875Sbrandon.potter@amd.com
2792093SN/A/// Target chown() handler.
28011851Sbrandon.potter@amd.comSyscallReturn chownFunc(SyscallDesc *desc, int num,
2812093SN/A                        LiveProcess *p, ThreadContext *tc);
2822687Sksewell@umich.edu
2832687Sksewell@umich.edu
28411851Sbrandon.potter@amd.com/// Target fchown() handler.
2852687Sksewell@umich.eduSyscallReturn fchownFunc(SyscallDesc *desc, int num,
2862238SN/A                         LiveProcess *p, ThreadContext *tc);
2872238SN/A
28811851Sbrandon.potter@amd.com/// Target dup() handler.
2892238SN/ASyscallReturn dupFunc(SyscallDesc *desc, int num,
29011908SBrandon.Potter@amd.com                      LiveProcess *process, ThreadContext *tc);
29111908SBrandon.Potter@amd.com
29211908SBrandon.Potter@amd.com/// Target fnctl() handler.
29311908SBrandon.Potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num,
29411908SBrandon.Potter@amd.com                        LiveProcess *process, ThreadContext *tc);
29511908SBrandon.Potter@amd.com
29611908SBrandon.Potter@amd.com/// Target fcntl64() handler.
29711908SBrandon.Potter@amd.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num,
2982238SN/A                        LiveProcess *process, ThreadContext *tc);
2992238SN/A
30011851Sbrandon.potter@amd.com/// Target setuid() handler.
3012238SN/ASyscallReturn setuidFunc(SyscallDesc *desc, int num,
30213571Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
30313571Sbrandon.potter@amd.com
30413571Sbrandon.potter@amd.com/// Target getpid() handler.
30513571Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num,
30613568Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
30713568Sbrandon.potter@amd.com
30813568Sbrandon.potter@amd.com/// Target getuid() handler.
30913568Sbrandon.potter@amd.comSyscallReturn getuidFunc(SyscallDesc *desc, int num,
31013568Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
31113568Sbrandon.potter@amd.com
31213568Sbrandon.potter@amd.com/// Target getgid() handler.
31313568Sbrandon.potter@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num,
31413568Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
31513568Sbrandon.potter@amd.com
31613568Sbrandon.potter@amd.com/// Target getppid() handler.
31713568Sbrandon.potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num,
31813448Sciro.santilli@arm.com                               LiveProcess *p, ThreadContext *tc);
31913031Sbrandon.potter@amd.com
32013031Sbrandon.potter@amd.com/// Target geteuid() handler.
32113031Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num,
32213448Sciro.santilli@arm.com                               LiveProcess *p, ThreadContext *tc);
32313031Sbrandon.potter@amd.com
32413539Sjavier.setoain@arm.com/// Target getegid() handler.
32513539Sjavier.setoain@arm.comSyscallReturn getegidFunc(SyscallDesc *desc, int num,
32613539Sjavier.setoain@arm.com                               LiveProcess *p, ThreadContext *tc);
32713539Sjavier.setoain@arm.com
32813539Sjavier.setoain@arm.com/// Target clone() handler.
32913539Sjavier.setoain@arm.comSyscallReturn cloneFunc(SyscallDesc *desc, int num,
33013569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
33113569Sbrandon.potter@amd.com
33213569Sbrandon.potter@amd.com
33313569Sbrandon.potter@amd.com/// Pseudo Funcs  - These functions use a different return convension,
33413569Sbrandon.potter@amd.com/// returning a second value in a register other than the normal return register
33513569Sbrandon.potter@amd.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
33613569Sbrandon.potter@amd.com                             LiveProcess *process, ThreadContext *tc);
33713569Sbrandon.potter@amd.com
33813569Sbrandon.potter@amd.com/// Target getpidPseudo() handler.
33913569Sbrandon.potter@amd.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
34013569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
34113569Sbrandon.potter@amd.com
34213569Sbrandon.potter@amd.com/// Target getuidPseudo() handler.
34313569Sbrandon.potter@amd.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
34413569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
34513569Sbrandon.potter@amd.com
34613031Sbrandon.potter@amd.com/// Target getgidPseudo() handler.
3472238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
34811851Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
3492238SN/A
3502238SN/A
3512238SN/A/// A readable name for 1,000,000, for converting microseconds to seconds.
35211851Sbrandon.potter@amd.comconst int one_million = 1000000;
3532238SN/A
3542238SN/A/// Approximate seconds since the epoch (1/1/1970).  About a billion,
3552238SN/A/// by my reckoning.  We want to keep this a constant (not use the
35611851Sbrandon.potter@amd.com/// real-world time) to keep simulations repeatable.
3572238SN/Aconst unsigned seconds_since_epoch = 1000000000;
3582238SN/A
3592238SN/A/// Helper function to convert current elapsed time to seconds and
36011851Sbrandon.potter@amd.com/// microseconds.
3612238SN/Atemplate <class T1, class T2>
3622238SN/Avoid
3632238SN/AgetElapsedTime(T1 &sec, T2 &usec)
36411851Sbrandon.potter@amd.com{
3652238SN/A    int elapsed_usecs = curTick / SimClock::Int::us;
3669455Smitch.hayenga+gem5@gmail.com    sec = elapsed_usecs / one_million;
3679455Smitch.hayenga+gem5@gmail.com    usec = elapsed_usecs % one_million;
36811851Sbrandon.potter@amd.com}
36910203SAli.Saidi@ARM.com
37011851Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
37111851Sbrandon.potter@amd.com//
3729455Smitch.hayenga+gem5@gmail.com// The following emulation functions are generic, but need to be
37313571Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc.
37413571Sbrandon.potter@amd.com//
37513571Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
37613571Sbrandon.potter@amd.com
37713571Sbrandon.potter@amd.com#if NO_STAT64
37813571Sbrandon.potter@amd.com    typedef struct stat hst_stat;
37913571Sbrandon.potter@amd.com    typedef struct stat hst_stat64;
38013571Sbrandon.potter@amd.com#else
38113571Sbrandon.potter@amd.com    typedef struct stat hst_stat;
38213571Sbrandon.potter@amd.com    typedef struct stat64 hst_stat64;
38313571Sbrandon.potter@amd.com#endif
38413571Sbrandon.potter@amd.com
3859112Smarc.orr@gmail.com//// Helper function to convert a host stat buffer to a target stat
38611906SBrandon.Potter@amd.com//// buffer.  Also copies the target buffer out to the simulated
38711906SBrandon.Potter@amd.com//// memory space.  Used by stat(), fstat(), and lstat().
3889112Smarc.orr@gmail.com
3899112Smarc.orr@gmail.comtemplate <typename target_stat, typename host_stat>
39011851Sbrandon.potter@amd.comstatic void
3919112Smarc.orr@gmail.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
3929112Smarc.orr@gmail.com{
39311911SBrandon.Potter@amd.com    using namespace TheISA;
3949112Smarc.orr@gmail.com
39511911SBrandon.Potter@amd.com    if (fakeTTY)
39611911SBrandon.Potter@amd.com        tgt->st_dev = 0xA;
39711911SBrandon.Potter@amd.com    else
39811911SBrandon.Potter@amd.com        tgt->st_dev = host->st_dev;
39913642Sqtt2@cornell.edu    tgt->st_dev = htog(tgt->st_dev);
40013642Sqtt2@cornell.edu    tgt->st_ino = host->st_ino;
40113642Sqtt2@cornell.edu    tgt->st_ino = htog(tgt->st_ino);
4029112Smarc.orr@gmail.com    tgt->st_mode = host->st_mode;
40311911SBrandon.Potter@amd.com    if (fakeTTY) {
40411911SBrandon.Potter@amd.com        // Claim to be a character device
40511911SBrandon.Potter@amd.com        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
40611911SBrandon.Potter@amd.com        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
4079238Slluc.alvarez@bsc.es    }
40813642Sqtt2@cornell.edu    tgt->st_mode = htog(tgt->st_mode);
4099112Smarc.orr@gmail.com    tgt->st_nlink = host->st_nlink;
41011911SBrandon.Potter@amd.com    tgt->st_nlink = htog(tgt->st_nlink);
4119112Smarc.orr@gmail.com    tgt->st_uid = host->st_uid;
41213642Sqtt2@cornell.edu    tgt->st_uid = htog(tgt->st_uid);
41311911SBrandon.Potter@amd.com    tgt->st_gid = host->st_gid;
41411911SBrandon.Potter@amd.com    tgt->st_gid = htog(tgt->st_gid);
41511911SBrandon.Potter@amd.com    if (fakeTTY)
41611911SBrandon.Potter@amd.com        tgt->st_rdev = 0x880d;
4179112Smarc.orr@gmail.com    else
41811911SBrandon.Potter@amd.com        tgt->st_rdev = host->st_rdev;
41911911SBrandon.Potter@amd.com    tgt->st_rdev = htog(tgt->st_rdev);
42011911SBrandon.Potter@amd.com    tgt->st_size = host->st_size;
42111911SBrandon.Potter@amd.com    tgt->st_size = htog(tgt->st_size);
42211911SBrandon.Potter@amd.com    tgt->st_atimeX = host->st_atime;
42311911SBrandon.Potter@amd.com    tgt->st_atimeX = htog(tgt->st_atimeX);
4249112Smarc.orr@gmail.com    tgt->st_mtimeX = host->st_mtime;
4259112Smarc.orr@gmail.com    tgt->st_mtimeX = htog(tgt->st_mtimeX);
42613642Sqtt2@cornell.edu    tgt->st_ctimeX = host->st_ctime;
42713642Sqtt2@cornell.edu    tgt->st_ctimeX = htog(tgt->st_ctimeX);
42813642Sqtt2@cornell.edu    // Force the block size to be 8k. This helps to ensure buffered io works
42913642Sqtt2@cornell.edu    // consistently across different hosts.
43013642Sqtt2@cornell.edu    tgt->st_blksize = 0x2000;
43111911SBrandon.Potter@amd.com    tgt->st_blksize = htog(tgt->st_blksize);
4329112Smarc.orr@gmail.com    tgt->st_blocks = host->st_blocks;
43311911SBrandon.Potter@amd.com    tgt->st_blocks = htog(tgt->st_blocks);
43411911SBrandon.Potter@amd.com}
43513642Sqtt2@cornell.edu
43613642Sqtt2@cornell.edu// Same for stat64
43713650Smw828@cornell.edu
43813650Smw828@cornell.edutemplate <typename target_stat, typename host_stat64>
43913650Smw828@cornell.edustatic void
44013650Smw828@cornell.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
44113650Smw828@cornell.edu{
44213650Smw828@cornell.edu    using namespace TheISA;
44313650Smw828@cornell.edu
44413650Smw828@cornell.edu    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
44513650Smw828@cornell.edu#if defined(STAT_HAVE_NSEC)
44613650Smw828@cornell.edu    tgt->st_atime_nsec = host->st_atime_nsec;
44713650Smw828@cornell.edu    tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
44813650Smw828@cornell.edu    tgt->st_mtime_nsec = host->st_mtime_nsec;
44913650Smw828@cornell.edu    tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
45013650Smw828@cornell.edu    tgt->st_ctime_nsec = host->st_ctime_nsec;
45113651Smw828@cornell.edu    tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
45213651Smw828@cornell.edu#else
45313651Smw828@cornell.edu    tgt->st_atime_nsec = 0;
45413651Smw828@cornell.edu    tgt->st_mtime_nsec = 0;
45513651Smw828@cornell.edu    tgt->st_ctime_nsec = 0;
45613651Smw828@cornell.edu#endif
45713651Smw828@cornell.edu}
45813651Smw828@cornell.edu
45913651Smw828@cornell.edu//Here are a couple convenience functions
46013651Smw828@cornell.edutemplate<class OS>
46113651Smw828@cornell.edustatic void
46213651Smw828@cornell.educopyOutStatBuf(TranslatingPort * mem, Addr addr,
46313651Smw828@cornell.edu        hst_stat *host, bool fakeTTY = false)
46413651Smw828@cornell.edu{
46513651Smw828@cornell.edu    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
46613651Smw828@cornell.edu    tgt_stat_buf tgt(addr);
46713651Smw828@cornell.edu    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
46813651Smw828@cornell.edu    tgt.copyOut(mem);
46913651Smw828@cornell.edu}
47013651Smw828@cornell.edu
47113651Smw828@cornell.edutemplate<class OS>
47213651Smw828@cornell.edustatic void
47313651Smw828@cornell.educopyOutStat64Buf(TranslatingPort * mem, Addr addr,
47413651Smw828@cornell.edu        hst_stat64 *host, bool fakeTTY = false)
47513651Smw828@cornell.edu{
47613651Smw828@cornell.edu    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
47713651Smw828@cornell.edu    tgt_stat_buf tgt(addr);
47813651Smw828@cornell.edu    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
47913651Smw828@cornell.edu    tgt.copyOut(mem);
48013651Smw828@cornell.edu}
48113651Smw828@cornell.edu
48213651Smw828@cornell.edu/// Target ioctl() handler.  For the most part, programs call ioctl()
48313651Smw828@cornell.edu/// only to find out if their stdout is a tty, to determine whether to
48413651Smw828@cornell.edu/// do line or block buffering.
48513651Smw828@cornell.edutemplate <class OS>
48613651Smw828@cornell.eduSyscallReturn
48713651Smw828@cornell.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
48813651Smw828@cornell.edu          ThreadContext *tc)
48913651Smw828@cornell.edu{
49013651Smw828@cornell.edu    int index = 0;
49113651Smw828@cornell.edu    int fd = process->getSyscallArg(tc, index);
49213651Smw828@cornell.edu    unsigned req = process->getSyscallArg(tc, index);
49313651Smw828@cornell.edu
49413651Smw828@cornell.edu    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
49513651Smw828@cornell.edu
49613651Smw828@cornell.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
49713651Smw828@cornell.edu        // doesn't map to any simulator fd: not a valid target fd
49813651Smw828@cornell.edu        return -EBADF;
49913651Smw828@cornell.edu    }
50013651Smw828@cornell.edu
50113651Smw828@cornell.edu    switch (req) {
50213651Smw828@cornell.edu      case OS::TIOCISATTY_:
50313651Smw828@cornell.edu      case OS::TIOCGETP_:
50413651Smw828@cornell.edu      case OS::TIOCSETP_:
50513651Smw828@cornell.edu      case OS::TIOCSETN_:
50613651Smw828@cornell.edu      case OS::TIOCSETC_:
50713651Smw828@cornell.edu      case OS::TIOCGETC_:
50813651Smw828@cornell.edu      case OS::TIOCGETS_:
50913651Smw828@cornell.edu      case OS::TIOCGETA_:
51013651Smw828@cornell.edu      case OS::TCSETAW_:
51113651Smw828@cornell.edu        return -ENOTTY;
51213651Smw828@cornell.edu
51313651Smw828@cornell.edu      default:
51413651Smw828@cornell.edu        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
51513651Smw828@cornell.edu              fd, req, tc->readPC());
51613651Smw828@cornell.edu    }
51713651Smw828@cornell.edu}
51813651Smw828@cornell.edu
51913651Smw828@cornell.edu/// Target open() handler.
52013651Smw828@cornell.edutemplate <class OS>
52113651Smw828@cornell.eduSyscallReturn
5229112Smarc.orr@gmail.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
52311911SBrandon.Potter@amd.com         ThreadContext *tc)
52411911SBrandon.Potter@amd.com{
5259112Smarc.orr@gmail.com    std::string path;
5269112Smarc.orr@gmail.com
5272238SN/A    int index = 0;
5282238SN/A    if (!tc->getMemPort()->tryReadString(path,
5292238SN/A                process->getSyscallArg(tc, index)))
5302238SN/A        return -EFAULT;
53111851Sbrandon.potter@amd.com
5322238SN/A    if (path == "/dev/sysdev0") {
5332238SN/A        // This is a memory-mapped high-resolution timer device on Alpha.
5342238SN/A        // We don't support it, so just punt.
53511851Sbrandon.potter@amd.com        warn("Ignoring open(%s, ...)\n", path);
5362238SN/A        return -ENOENT;
5372238SN/A    }
5382238SN/A
53911851Sbrandon.potter@amd.com    int tgtFlags = process->getSyscallArg(tc, index);
5402238SN/A    int mode = process->getSyscallArg(tc, index);
5412238SN/A    int hostFlags = 0;
5422238SN/A
54311851Sbrandon.potter@amd.com    // translate open flags
5442238SN/A    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
5452238SN/A        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
5461354SN/A            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
5471354SN/A            hostFlags |= OS::openFlagTable[i].hostFlag;
54810796Sbrandon.potter@amd.com        }
54910796Sbrandon.potter@amd.com    }
5501354SN/A
5511354SN/A    // any target flags left?
5521354SN/A    if (tgtFlags != 0)
5531354SN/A        warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
5541354SN/A
5551354SN/A#ifdef __CYGWIN32__
5561354SN/A    hostFlags |= O_BINARY;
5571354SN/A#endif
5581354SN/A
5591354SN/A    // Adjust path for current working directory
56010796Sbrandon.potter@amd.com    path = process->fullPath(path);
5611354SN/A
56210796Sbrandon.potter@amd.com    DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
5631354SN/A
5641354SN/A    int fd;
5651354SN/A    if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") ||
5661354SN/A        !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) {
56710796Sbrandon.potter@amd.com        // It's a proc/sys entery and requires special handling
56810796Sbrandon.potter@amd.com        fd = OS::openSpecialFile(path, process, tc);
56910796Sbrandon.potter@amd.com        return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
57010796Sbrandon.potter@amd.com     } else {
57110796Sbrandon.potter@amd.com        // open the file
57210796Sbrandon.potter@amd.com        fd = open(path.c_str(), hostFlags, mode);
57310796Sbrandon.potter@amd.com        return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
57410796Sbrandon.potter@amd.com     }
57510796Sbrandon.potter@amd.com
57610796Sbrandon.potter@amd.com}
57710796Sbrandon.potter@amd.com
578360SN/A/// Target sysinfo() handler.
579360SN/Atemplate <class OS>
580360SN/ASyscallReturn
581360SN/AsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
582360SN/A         ThreadContext *tc)
583360SN/A{
584360SN/A
58511759Sbrandon.potter@amd.com    int index = 0;
5863113Sgblack@eecs.umich.edu    TypedBufferArg<typename OS::tgt_sysinfo>
5873113Sgblack@eecs.umich.edu        sysinfo(process->getSyscallArg(tc, index));
5883113Sgblack@eecs.umich.edu
5893113Sgblack@eecs.umich.edu    sysinfo->uptime=seconds_since_epoch;
5903113Sgblack@eecs.umich.edu    sysinfo->totalram=process->system->memSize();
5913113Sgblack@eecs.umich.edu
5923113Sgblack@eecs.umich.edu    sysinfo.copyOut(tc->getMemPort());
5933113Sgblack@eecs.umich.edu
5943113Sgblack@eecs.umich.edu    return 0;
5953113Sgblack@eecs.umich.edu}
5963113Sgblack@eecs.umich.edu
5973113Sgblack@eecs.umich.edu/// Target chmod() handler.
5983113Sgblack@eecs.umich.edutemplate <class OS>
59912032Sandreas.sandberg@arm.comSyscallReturn
6003113Sgblack@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
6013113Sgblack@eecs.umich.edu          ThreadContext *tc)
6024189Sgblack@eecs.umich.edu{
6034189Sgblack@eecs.umich.edu    std::string path;
6043113Sgblack@eecs.umich.edu
6053113Sgblack@eecs.umich.edu    int index = 0;
6063113Sgblack@eecs.umich.edu    if (!tc->getMemPort()->tryReadString(path,
6073113Sgblack@eecs.umich.edu                process->getSyscallArg(tc, index))) {
6088737Skoansin.tan@gmail.com        return -EFAULT;
6093113Sgblack@eecs.umich.edu    }
6108737Skoansin.tan@gmail.com
6113277Sgblack@eecs.umich.edu    uint32_t mode = process->getSyscallArg(tc, index);
6125515SMichael.Adler@intel.com    mode_t hostMode = 0;
6135515SMichael.Adler@intel.com
6145515SMichael.Adler@intel.com    // XXX translate mode flags via OS::something???
6155515SMichael.Adler@intel.com    hostMode = mode;
6165515SMichael.Adler@intel.com
6178737Skoansin.tan@gmail.com    // Adjust path for current working directory
6183277Sgblack@eecs.umich.edu    path = process->fullPath(path);
6198737Skoansin.tan@gmail.com
6203277Sgblack@eecs.umich.edu    // do the chmod
6218737Skoansin.tan@gmail.com    int result = chmod(path.c_str(), hostMode);
6223277Sgblack@eecs.umich.edu    if (result < 0)
6238737Skoansin.tan@gmail.com        return -errno;
6243113Sgblack@eecs.umich.edu
6253113Sgblack@eecs.umich.edu    return 0;
6263113Sgblack@eecs.umich.edu}
6273113Sgblack@eecs.umich.edu
6288737Skoansin.tan@gmail.com
6293113Sgblack@eecs.umich.edu/// Target fchmod() handler.
6308737Skoansin.tan@gmail.comtemplate <class OS>
6313114Sgblack@eecs.umich.eduSyscallReturn
6328737Skoansin.tan@gmail.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
6333114Sgblack@eecs.umich.edu           ThreadContext *tc)
6348737Skoansin.tan@gmail.com{
6353114Sgblack@eecs.umich.edu    int index = 0;
6368737Skoansin.tan@gmail.com    int fd = process->getSyscallArg(tc, index);
63711906SBrandon.Potter@amd.com    if (fd < 0 || process->sim_fd(fd) < 0) {
6384061Sgblack@eecs.umich.edu        // doesn't map to any simulator fd: not a valid target fd
6394061Sgblack@eecs.umich.edu        return -EBADF;
6408737Skoansin.tan@gmail.com    }
6413113Sgblack@eecs.umich.edu
6428737Skoansin.tan@gmail.com    uint32_t mode = process->getSyscallArg(tc, index);
6433113Sgblack@eecs.umich.edu    mode_t hostMode = 0;
6443113Sgblack@eecs.umich.edu
6453113Sgblack@eecs.umich.edu    // XXX translate mode flags via OS::someting???
6463113Sgblack@eecs.umich.edu    hostMode = mode;
6473113Sgblack@eecs.umich.edu
64812032Sandreas.sandberg@arm.com    // do the fchmod
6493113Sgblack@eecs.umich.edu    int result = fchmod(process->sim_fd(fd), hostMode);
6503113Sgblack@eecs.umich.edu    if (result < 0)
6514189Sgblack@eecs.umich.edu        return -errno;
6524189Sgblack@eecs.umich.edu
6533113Sgblack@eecs.umich.edu    return 0;
6543113Sgblack@eecs.umich.edu}
6553113Sgblack@eecs.umich.edu
6568737Skoansin.tan@gmail.com/// Target mremap() handler.
6573113Sgblack@eecs.umich.edutemplate <class OS>
6588737Skoansin.tan@gmail.comSyscallReturn
6593113Sgblack@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
6608737Skoansin.tan@gmail.com{
6613113Sgblack@eecs.umich.edu    int index = 0;
6623113Sgblack@eecs.umich.edu    Addr start = process->getSyscallArg(tc, index);
6633113Sgblack@eecs.umich.edu    uint64_t old_length = process->getSyscallArg(tc, index);
6643113Sgblack@eecs.umich.edu    uint64_t new_length = process->getSyscallArg(tc, index);
6653113Sgblack@eecs.umich.edu    uint64_t flags = process->getSyscallArg(tc, index);
6663113Sgblack@eecs.umich.edu
6673113Sgblack@eecs.umich.edu    if ((start % TheISA::VMPageSize != 0) ||
66811906SBrandon.Potter@amd.com            (new_length % TheISA::VMPageSize != 0)) {
6693113Sgblack@eecs.umich.edu        warn("mremap failing: arguments not page aligned");
67012032Sandreas.sandberg@arm.com        return -EINVAL;
6718852Sandreas.hansson@arm.com    }
67211906SBrandon.Potter@amd.com
6733113Sgblack@eecs.umich.edu    if (new_length > old_length) {
6743113Sgblack@eecs.umich.edu        if ((start + old_length) == process->mmap_end) {
6753113Sgblack@eecs.umich.edu            uint64_t diff = new_length - old_length;
6763113Sgblack@eecs.umich.edu            process->pTable->allocate(process->mmap_end, diff);
6773113Sgblack@eecs.umich.edu            process->mmap_end += diff;
6783113Sgblack@eecs.umich.edu            return start;
6793113Sgblack@eecs.umich.edu        } else {
6803113Sgblack@eecs.umich.edu            // sys/mman.h defined MREMAP_MAYMOVE
68112032Sandreas.sandberg@arm.com            if (!(flags & 1)) {
6828852Sandreas.hansson@arm.com                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
68311906SBrandon.Potter@amd.com                return -ENOMEM;
6843113Sgblack@eecs.umich.edu            } else {
6853113Sgblack@eecs.umich.edu                process->pTable->remap(start, old_length, process->mmap_end);
6863113Sgblack@eecs.umich.edu                warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
6876686Stjones1@inf.ed.ac.uk                        process->mmap_end, process->mmap_end + new_length, new_length);
6883113Sgblack@eecs.umich.edu                start = process->mmap_end;
6893113Sgblack@eecs.umich.edu                // add on the remaining unallocated pages
6903113Sgblack@eecs.umich.edu                process->pTable->allocate(start + old_length, new_length - old_length);
69111759Sbrandon.potter@amd.com                process->mmap_end += new_length;
69212032Sandreas.sandberg@arm.com                warn("returning %08p as start\n", start);
69311759Sbrandon.potter@amd.com                return start;
69411759Sbrandon.potter@amd.com            }
69511759Sbrandon.potter@amd.com        }
69611759Sbrandon.potter@amd.com    } else {
69711759Sbrandon.potter@amd.com        process->pTable->deallocate(start + new_length, old_length -
69811812Sbaz21@cam.ac.uk                new_length);
69911812Sbaz21@cam.ac.uk        return start;
70011812Sbaz21@cam.ac.uk    }
70111759Sbrandon.potter@amd.com}
70211812Sbaz21@cam.ac.uk
70311759Sbrandon.potter@amd.com/// Target stat() handler.
70411759Sbrandon.potter@amd.comtemplate <class OS>
70511759Sbrandon.potter@amd.comSyscallReturn
70611759Sbrandon.potter@amd.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
70711759Sbrandon.potter@amd.com         ThreadContext *tc)
70811759Sbrandon.potter@amd.com{
70911759Sbrandon.potter@amd.com    std::string path;
71011812Sbaz21@cam.ac.uk
71111812Sbaz21@cam.ac.uk    int index = 0;
71211812Sbaz21@cam.ac.uk    if (!tc->getMemPort()->tryReadString(path,
71311812Sbaz21@cam.ac.uk                process->getSyscallArg(tc, index))) {
71411812Sbaz21@cam.ac.uk        return -EFAULT;
71511812Sbaz21@cam.ac.uk    }
71611812Sbaz21@cam.ac.uk    Addr bufPtr = process->getSyscallArg(tc, index);
71711759Sbrandon.potter@amd.com
71811759Sbrandon.potter@amd.com    // Adjust path for current working directory
71911812Sbaz21@cam.ac.uk    path = process->fullPath(path);
72011812Sbaz21@cam.ac.uk
72111759Sbrandon.potter@amd.com    struct stat hostBuf;
72211812Sbaz21@cam.ac.uk    int result = stat(path.c_str(), &hostBuf);
72311812Sbaz21@cam.ac.uk
72411812Sbaz21@cam.ac.uk    if (result < 0)
72511812Sbaz21@cam.ac.uk        return -errno;
72611812Sbaz21@cam.ac.uk
72711812Sbaz21@cam.ac.uk    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
72811812Sbaz21@cam.ac.uk
72911759Sbrandon.potter@amd.com    return 0;
73011759Sbrandon.potter@amd.com}
73111759Sbrandon.potter@amd.com
73211759Sbrandon.potter@amd.com
733378SN/A/// Target stat64() handler.
734378SN/Atemplate <class OS>
7359141Smarc.orr@gmail.comSyscallReturn
7369141Smarc.orr@gmail.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
737360SN/A           ThreadContext *tc)
7381450SN/A{
73911856Sbrandon.potter@amd.com    std::string path;
740360SN/A
7416701Sgblack@eecs.umich.edu    int index = 0;
74211856Sbrandon.potter@amd.com    if (!tc->getMemPort()->tryReadString(path,
74311856Sbrandon.potter@amd.com                process->getSyscallArg(tc, index)))
744360SN/A        return -EFAULT;
74513907Salexandru.dutu@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
746360SN/A
74711856Sbrandon.potter@amd.com    // Adjust path for current working directory
74811856Sbrandon.potter@amd.com    path = process->fullPath(path);
74910496Ssteve.reinhardt@amd.com
75011856Sbrandon.potter@amd.com#if NO_STAT64
75113902Sbrandon.potter@amd.com    struct stat  hostBuf;
75213902Sbrandon.potter@amd.com    int result = stat(path.c_str(), &hostBuf);
75313902Sbrandon.potter@amd.com#else
75413902Sbrandon.potter@amd.com    struct stat64 hostBuf;
75513902Sbrandon.potter@amd.com    int result = stat64(path.c_str(), &hostBuf);
75613902Sbrandon.potter@amd.com#endif
75713902Sbrandon.potter@amd.com
75813902Sbrandon.potter@amd.com    if (result < 0)
75913902Sbrandon.potter@amd.com        return -errno;
76013902Sbrandon.potter@amd.com
76113902Sbrandon.potter@amd.com    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
76213902Sbrandon.potter@amd.com
76313902Sbrandon.potter@amd.com    return 0;
76413902Sbrandon.potter@amd.com}
76513902Sbrandon.potter@amd.com
76613902Sbrandon.potter@amd.com
76713902Sbrandon.potter@amd.com/// Target fstat64() handler.
76813902Sbrandon.potter@amd.comtemplate <class OS>
76913902Sbrandon.potter@amd.comSyscallReturn
77013902Sbrandon.potter@amd.comfstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
77113902Sbrandon.potter@amd.com            ThreadContext *tc)
77213902Sbrandon.potter@amd.com{
77313902Sbrandon.potter@amd.com    int index = 0;
77413902Sbrandon.potter@amd.com    int fd = process->getSyscallArg(tc, index);
77513902Sbrandon.potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
77613902Sbrandon.potter@amd.com    if (fd < 0 || process->sim_fd(fd) < 0) {
77713902Sbrandon.potter@amd.com        // doesn't map to any simulator fd: not a valid target fd
77813902Sbrandon.potter@amd.com        return -EBADF;
77913902Sbrandon.potter@amd.com    }
78013902Sbrandon.potter@amd.com
78113902Sbrandon.potter@amd.com#if NO_STAT64
78213902Sbrandon.potter@amd.com    struct stat  hostBuf;
78313902Sbrandon.potter@amd.com    int result = fstat(process->sim_fd(fd), &hostBuf);
78413936SAndrea.Mondelli@ucf.edu#else
78513902Sbrandon.potter@amd.com    struct stat64  hostBuf;
78613902Sbrandon.potter@amd.com    int result = fstat64(process->sim_fd(fd), &hostBuf);
78713902Sbrandon.potter@amd.com#endif
78813902Sbrandon.potter@amd.com
78913936SAndrea.Mondelli@ucf.edu    if (result < 0)
79013902Sbrandon.potter@amd.com        return -errno;
79113902Sbrandon.potter@amd.com
79213902Sbrandon.potter@amd.com    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
79313902Sbrandon.potter@amd.com
79413902Sbrandon.potter@amd.com    return 0;
79513902Sbrandon.potter@amd.com}
79613902Sbrandon.potter@amd.com
79713902Sbrandon.potter@amd.com
79813902Sbrandon.potter@amd.com/// Target lstat() handler.
79913902Sbrandon.potter@amd.comtemplate <class OS>
80013902Sbrandon.potter@amd.comSyscallReturn
80113902Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
80213902Sbrandon.potter@amd.com          ThreadContext *tc)
80313902Sbrandon.potter@amd.com{
80410496Ssteve.reinhardt@amd.com    std::string path;
80511856Sbrandon.potter@amd.com
80611856Sbrandon.potter@amd.com    int index = 0;
80711856Sbrandon.potter@amd.com    if (!tc->getMemPort()->tryReadString(path,
80811856Sbrandon.potter@amd.com                process->getSyscallArg(tc, index))) {
80911856Sbrandon.potter@amd.com        return -EFAULT;
81010930Sbrandon.potter@amd.com    }
8119141Smarc.orr@gmail.com    Addr bufPtr = process->getSyscallArg(tc, index);
812360SN/A
813360SN/A    // Adjust path for current working directory
814360SN/A    path = process->fullPath(path);
81511907SBrandon.Potter@amd.com
81611907SBrandon.Potter@amd.com    struct stat hostBuf;
81711907SBrandon.Potter@amd.com    int result = lstat(path.c_str(), &hostBuf);
818360SN/A
81911907SBrandon.Potter@amd.com    if (result < 0)
82011907SBrandon.Potter@amd.com        return -errno;
82111907SBrandon.Potter@amd.com
82211907SBrandon.Potter@amd.com    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
82311907SBrandon.Potter@amd.com
82411907SBrandon.Potter@amd.com    return 0;
82511907SBrandon.Potter@amd.com}
82611907SBrandon.Potter@amd.com
82711907SBrandon.Potter@amd.com/// Target lstat64() handler.
82811907SBrandon.Potter@amd.comtemplate <class OS>
82911907SBrandon.Potter@amd.comSyscallReturn
83011907SBrandon.Potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
83111907SBrandon.Potter@amd.com            ThreadContext *tc)
83211907SBrandon.Potter@amd.com{
833360SN/A    std::string path;
83411907SBrandon.Potter@amd.com
8351458SN/A    int index = 0;
836360SN/A    if (!tc->getMemPort()->tryReadString(path,
83711907SBrandon.Potter@amd.com                process->getSyscallArg(tc, index))) {
83811907SBrandon.Potter@amd.com        return -EFAULT;
83911907SBrandon.Potter@amd.com    }
84011907SBrandon.Potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
84111907SBrandon.Potter@amd.com
84211907SBrandon.Potter@amd.com    // Adjust path for current working directory
84311907SBrandon.Potter@amd.com    path = process->fullPath(path);
84411907SBrandon.Potter@amd.com
84511907SBrandon.Potter@amd.com#if NO_STAT64
84611907SBrandon.Potter@amd.com    struct stat hostBuf;
847360SN/A    int result = lstat(path.c_str(), &hostBuf);
84811907SBrandon.Potter@amd.com#else
84911907SBrandon.Potter@amd.com    struct stat64 hostBuf;
85011907SBrandon.Potter@amd.com    int result = lstat64(path.c_str(), &hostBuf);
851360SN/A#endif
852360SN/A
85311907SBrandon.Potter@amd.com    if (result < 0)
85411907SBrandon.Potter@amd.com        return -errno;
85511907SBrandon.Potter@amd.com
85611907SBrandon.Potter@amd.com    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
857360SN/A
85811907SBrandon.Potter@amd.com    return 0;
859360SN/A}
860360SN/A
86111907SBrandon.Potter@amd.com/// Target fstat() handler.
8623669Sbinkertn@umich.edutemplate <class OS>
86311907SBrandon.Potter@amd.comSyscallReturn
86411907SBrandon.Potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
86511907SBrandon.Potter@amd.com          ThreadContext *tc)
86611907SBrandon.Potter@amd.com{
86711907SBrandon.Potter@amd.com    int index = 0;
86811907SBrandon.Potter@amd.com    int fd = process->sim_fd(process->getSyscallArg(tc, index));
86911907SBrandon.Potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
87011907SBrandon.Potter@amd.com
87111907SBrandon.Potter@amd.com    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
87211907SBrandon.Potter@amd.com
87311907SBrandon.Potter@amd.com    if (fd < 0)
87411907SBrandon.Potter@amd.com        return -EBADF;
87513883Sdavid.hashe@amd.com
87613883Sdavid.hashe@amd.com    struct stat hostBuf;
87713883Sdavid.hashe@amd.com    int result = fstat(fd, &hostBuf);
87813883Sdavid.hashe@amd.com
87913883Sdavid.hashe@amd.com    if (result < 0)
88011907SBrandon.Potter@amd.com        return -errno;
88111907SBrandon.Potter@amd.com
88211907SBrandon.Potter@amd.com    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
88311907SBrandon.Potter@amd.com
88411907SBrandon.Potter@amd.com    return 0;
88513883Sdavid.hashe@amd.com}
88613883Sdavid.hashe@amd.com
88711907SBrandon.Potter@amd.com
8881706SN/A/// Target statfs() handler.
88911907SBrandon.Potter@amd.comtemplate <class OS>
89011907SBrandon.Potter@amd.comSyscallReturn
89111907SBrandon.Potter@amd.comstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
89211907SBrandon.Potter@amd.com           ThreadContext *tc)
89311907SBrandon.Potter@amd.com{
89411907SBrandon.Potter@amd.com    std::string path;
89513883Sdavid.hashe@amd.com
89613883Sdavid.hashe@amd.com    int index = 0;
89711907SBrandon.Potter@amd.com    if (!tc->getMemPort()->tryReadString(path,
89811907SBrandon.Potter@amd.com                process->getSyscallArg(tc, index))) {
89911907SBrandon.Potter@amd.com        return -EFAULT;
90011907SBrandon.Potter@amd.com    }
90113883Sdavid.hashe@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
90211907SBrandon.Potter@amd.com
90310496Ssteve.reinhardt@amd.com    // Adjust path for current working directory
90411907SBrandon.Potter@amd.com    path = process->fullPath(path);
90511907SBrandon.Potter@amd.com
90611907SBrandon.Potter@amd.com    struct statfs hostBuf;
90711907SBrandon.Potter@amd.com    int result = statfs(path.c_str(), &hostBuf);
90810496Ssteve.reinhardt@amd.com
90910496Ssteve.reinhardt@amd.com    if (result < 0)
91011907SBrandon.Potter@amd.com        return -errno;
91113883Sdavid.hashe@amd.com
91213883Sdavid.hashe@amd.com    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
91313883Sdavid.hashe@amd.com
91413883Sdavid.hashe@amd.com    return 0;
91513883Sdavid.hashe@amd.com}
91613883Sdavid.hashe@amd.com
91713883Sdavid.hashe@amd.com
91813883Sdavid.hashe@amd.com/// Target fstatfs() handler.
91913883Sdavid.hashe@amd.comtemplate <class OS>
92013883Sdavid.hashe@amd.comSyscallReturn
92113883Sdavid.hashe@amd.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
92213883Sdavid.hashe@amd.com            ThreadContext *tc)
92313883Sdavid.hashe@amd.com{
92413883Sdavid.hashe@amd.com    int index = 0;
92513883Sdavid.hashe@amd.com    int fd = process->sim_fd(process->getSyscallArg(tc, index));
92613883Sdavid.hashe@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
92713883Sdavid.hashe@amd.com
92813883Sdavid.hashe@amd.com    if (fd < 0)
92913883Sdavid.hashe@amd.com        return -EBADF;
93013883Sdavid.hashe@amd.com
93113883Sdavid.hashe@amd.com    struct statfs hostBuf;
93213883Sdavid.hashe@amd.com    int result = fstatfs(fd, &hostBuf);
93311907SBrandon.Potter@amd.com
93411907SBrandon.Potter@amd.com    if (result < 0)
93513883Sdavid.hashe@amd.com        return -errno;
93611907SBrandon.Potter@amd.com
93713883Sdavid.hashe@amd.com    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
93813883Sdavid.hashe@amd.com
93911907SBrandon.Potter@amd.com    return 0;
94013883Sdavid.hashe@amd.com}
94113883Sdavid.hashe@amd.com
94213883Sdavid.hashe@amd.com
94313883Sdavid.hashe@amd.com/// Target writev() handler.
94411907SBrandon.Potter@amd.comtemplate <class OS>
94511907SBrandon.Potter@amd.comSyscallReturn
94613883Sdavid.hashe@amd.comwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
94713883Sdavid.hashe@amd.com           ThreadContext *tc)
94811907SBrandon.Potter@amd.com{
94911907SBrandon.Potter@amd.com    int index = 0;
95011907SBrandon.Potter@amd.com    int fd = process->getSyscallArg(tc, index);
95113883Sdavid.hashe@amd.com    if (fd < 0 || process->sim_fd(fd) < 0) {
95213883Sdavid.hashe@amd.com        // doesn't map to any simulator fd: not a valid target fd
95313883Sdavid.hashe@amd.com        return -EBADF;
95411907SBrandon.Potter@amd.com    }
95511907SBrandon.Potter@amd.com
956360SN/A    TranslatingPort *p = tc->getMemPort();
95711907SBrandon.Potter@amd.com    uint64_t tiov_base = process->getSyscallArg(tc, index);
95811907SBrandon.Potter@amd.com    size_t count = process->getSyscallArg(tc, index);
95911907SBrandon.Potter@amd.com    struct iovec hiov[count];
96011907SBrandon.Potter@amd.com    for (size_t i = 0; i < count; ++i) {
96111907SBrandon.Potter@amd.com        typename OS::tgt_iovec tiov;
96211907SBrandon.Potter@amd.com
96311907SBrandon.Potter@amd.com        p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
96411907SBrandon.Potter@amd.com                    (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
96511907SBrandon.Potter@amd.com        hiov[i].iov_len = gtoh(tiov.iov_len);
96611907SBrandon.Potter@amd.com        hiov[i].iov_base = new char [hiov[i].iov_len];
96713883Sdavid.hashe@amd.com        p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
96813883Sdavid.hashe@amd.com                    hiov[i].iov_len);
96913883Sdavid.hashe@amd.com    }
97011907SBrandon.Potter@amd.com
971360SN/A    int result = writev(process->sim_fd(fd), hiov, count);
972360SN/A
97310027SChris.Adeniyi-Jones@arm.com    for (size_t i = 0; i < count; ++i)
97410027SChris.Adeniyi-Jones@arm.com        delete [] (char *)hiov[i].iov_base;
97510027SChris.Adeniyi-Jones@arm.com
97611851Sbrandon.potter@amd.com    if (result < 0)
97710027SChris.Adeniyi-Jones@arm.com        return -errno;
97810027SChris.Adeniyi-Jones@arm.com
97911907SBrandon.Potter@amd.com    return 0;
98010027SChris.Adeniyi-Jones@arm.com}
98110027SChris.Adeniyi-Jones@arm.com
98210027SChris.Adeniyi-Jones@arm.com
98310027SChris.Adeniyi-Jones@arm.com/// Target mmap() handler.
98410027SChris.Adeniyi-Jones@arm.com///
98511851Sbrandon.potter@amd.com/// We don't really handle mmap().  If the target is mmaping an
98611851Sbrandon.potter@amd.com/// anonymous region or /dev/zero, we can get away with doing basically
98710027SChris.Adeniyi-Jones@arm.com/// nothing (since memory is initialized to zero and the simulator
98811907SBrandon.Potter@amd.com/// doesn't really check addresses anyway).  Always print a warning,
98910027SChris.Adeniyi-Jones@arm.com/// since this could be seriously broken if we're not mapping
99010027SChris.Adeniyi-Jones@arm.com/// /dev/zero.
99110633Smichaelupton@gmail.com//
99210633Smichaelupton@gmail.com/// Someday we should explicitly check for /dev/zero in open, flag the
99310633Smichaelupton@gmail.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to
99411851Sbrandon.potter@amd.com/// anything else.
99510633Smichaelupton@gmail.comtemplate <class OS>
99610633Smichaelupton@gmail.comSyscallReturn
99710633Smichaelupton@gmail.commmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
99810633Smichaelupton@gmail.com{
99910633Smichaelupton@gmail.com    int index = 0;
100010633Smichaelupton@gmail.com    Addr start = p->getSyscallArg(tc, index);
100110633Smichaelupton@gmail.com    uint64_t length = p->getSyscallArg(tc, index);
100210633Smichaelupton@gmail.com    index++; // int prot = p->getSyscallArg(tc, index);
100310633Smichaelupton@gmail.com    int flags = p->getSyscallArg(tc, index);
100410633Smichaelupton@gmail.com    int fd = p->sim_fd(p->getSyscallArg(tc, index));
100510203SAli.Saidi@ARM.com    // int offset = p->getSyscallArg(tc, index);
100610203SAli.Saidi@ARM.com
100710203SAli.Saidi@ARM.com
100811851Sbrandon.potter@amd.com    if ((start  % TheISA::VMPageSize) != 0 ||
100911851Sbrandon.potter@amd.com        (length % TheISA::VMPageSize) != 0) {
101010203SAli.Saidi@ARM.com        warn("mmap failing: arguments not page-aligned: "
101110203SAli.Saidi@ARM.com             "start 0x%x length 0x%x",
101210203SAli.Saidi@ARM.com             start, length);
101310203SAli.Saidi@ARM.com        return -EINVAL;
101410203SAli.Saidi@ARM.com    }
101510203SAli.Saidi@ARM.com
101610203SAli.Saidi@ARM.com    if (start != 0) {
101710203SAli.Saidi@ARM.com        warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
101810203SAli.Saidi@ARM.com             start, p->mmap_end);
101910203SAli.Saidi@ARM.com    }
102010203SAli.Saidi@ARM.com
102111851Sbrandon.potter@amd.com    // pick next address from our "mmap region"
102211851Sbrandon.potter@amd.com    if (OS::mmapGrowsDown()) {
102310203SAli.Saidi@ARM.com        start = p->mmap_end - length;
102410203SAli.Saidi@ARM.com        p->mmap_end = start;
102510203SAli.Saidi@ARM.com    } else {
102610203SAli.Saidi@ARM.com        start = p->mmap_end;
102710203SAli.Saidi@ARM.com        p->mmap_end += length;
102810203SAli.Saidi@ARM.com    }
102910203SAli.Saidi@ARM.com    p->pTable->allocate(start, length);
103010203SAli.Saidi@ARM.com
103110850SGiacomo.Gabrielli@arm.com    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
103210850SGiacomo.Gabrielli@arm.com        warn("allowing mmap of file @ fd %d. "
103310850SGiacomo.Gabrielli@arm.com             "This will break if not /dev/zero.", fd);
103411851Sbrandon.potter@amd.com    }
103510850SGiacomo.Gabrielli@arm.com
103610850SGiacomo.Gabrielli@arm.com    return start;
103710850SGiacomo.Gabrielli@arm.com}
103810850SGiacomo.Gabrielli@arm.com
103910850SGiacomo.Gabrielli@arm.com/// Target getrlimit() handler.
104010850SGiacomo.Gabrielli@arm.comtemplate <class OS>
104110850SGiacomo.Gabrielli@arm.comSyscallReturn
104210850SGiacomo.Gabrielli@arm.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
104310850SGiacomo.Gabrielli@arm.com        ThreadContext *tc)
104410850SGiacomo.Gabrielli@arm.com{
104510850SGiacomo.Gabrielli@arm.com    int index = 0;
104610850SGiacomo.Gabrielli@arm.com    unsigned resource = process->getSyscallArg(tc, index);
104710850SGiacomo.Gabrielli@arm.com    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
104810850SGiacomo.Gabrielli@arm.com
104910850SGiacomo.Gabrielli@arm.com    switch (resource) {
105010850SGiacomo.Gabrielli@arm.com        case OS::TGT_RLIMIT_STACK:
105110850SGiacomo.Gabrielli@arm.com            // max stack size in bytes: make up a number (8MB for now)
105210850SGiacomo.Gabrielli@arm.com            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
105310850SGiacomo.Gabrielli@arm.com            rlp->rlim_cur = htog(rlp->rlim_cur);
105410850SGiacomo.Gabrielli@arm.com            rlp->rlim_max = htog(rlp->rlim_max);
105510850SGiacomo.Gabrielli@arm.com            break;
105610850SGiacomo.Gabrielli@arm.com
105710850SGiacomo.Gabrielli@arm.com        case OS::TGT_RLIMIT_DATA:
105810850SGiacomo.Gabrielli@arm.com            // max data segment size in bytes: make up a number
105913883Sdavid.hashe@amd.com            rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
106013883Sdavid.hashe@amd.com            rlp->rlim_cur = htog(rlp->rlim_cur);
106113883Sdavid.hashe@amd.com            rlp->rlim_max = htog(rlp->rlim_max);
106210850SGiacomo.Gabrielli@arm.com            break;
106310850SGiacomo.Gabrielli@arm.com
106410850SGiacomo.Gabrielli@arm.com        default:
106510850SGiacomo.Gabrielli@arm.com            std::cerr << "getrlimitFunc: unimplemented resource " << resource
106610850SGiacomo.Gabrielli@arm.com                << std::endl;
10676640Svince@csl.cornell.edu            abort();
10686640Svince@csl.cornell.edu            break;
10696640Svince@csl.cornell.edu    }
107011851Sbrandon.potter@amd.com
107111851Sbrandon.potter@amd.com    rlp.copyOut(tc->getMemPort());
10726640Svince@csl.cornell.edu    return 0;
10736640Svince@csl.cornell.edu}
10746701Sgblack@eecs.umich.edu
10756701Sgblack@eecs.umich.edu/// Target gettimeofday() handler.
107610793Sbrandon.potter@amd.comtemplate <class OS>
10776640Svince@csl.cornell.eduSyscallReturn
107811758Sbrandon.potter@amd.comgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
107911758Sbrandon.potter@amd.com        ThreadContext *tc)
108011758Sbrandon.potter@amd.com{
10816640Svince@csl.cornell.edu    int index = 0;
10828706Sandreas.hansson@arm.com    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
10836640Svince@csl.cornell.edu
10846701Sgblack@eecs.umich.edu    getElapsedTime(tp->tv_sec, tp->tv_usec);
10856640Svince@csl.cornell.edu    tp->tv_sec += seconds_since_epoch;
1086360SN/A    tp->tv_sec = TheISA::htog(tp->tv_sec);
10871999SN/A    tp->tv_usec = TheISA::htog(tp->tv_usec);
10881999SN/A
10891999SN/A    tp.copyOut(tc->getMemPort());
109011851Sbrandon.potter@amd.com
10912680Sktlim@umich.edu    return 0;
10921999SN/A}
10931999SN/A
10941999SN/A
10956701Sgblack@eecs.umich.edu/// Target utimes() handler.
10968852Sandreas.hansson@arm.comtemplate <class OS>
10976701Sgblack@eecs.umich.eduSyscallReturn
10981999SN/AutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
10996701Sgblack@eecs.umich.edu           ThreadContext *tc)
11001999SN/A{
11016701Sgblack@eecs.umich.edu    std::string path;
11021999SN/A
11031999SN/A    int index = 0;
11041999SN/A    if (!tc->getMemPort()->tryReadString(path,
11051999SN/A                process->getSyscallArg(tc, index))) {
11061999SN/A        return -EFAULT;
110713883Sdavid.hashe@amd.com    }
110813883Sdavid.hashe@amd.com
11093669Sbinkertn@umich.edu    TypedBufferArg<typename OS::timeval [2]>
11101999SN/A        tp(process->getSyscallArg(tc, index));
11111999SN/A    tp.copyIn(tc->getMemPort());
11121999SN/A
11132218SN/A    struct timeval hostTimeval[2];
11141999SN/A    for (int i = 0; i < 2; ++i)
11151999SN/A    {
11161999SN/A        hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
11171999SN/A        hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
111813570Sbrandon.potter@amd.com    }
111913570Sbrandon.potter@amd.com
112013570Sbrandon.potter@amd.com    // Adjust path for current working directory
112113570Sbrandon.potter@amd.com    path = process->fullPath(path);
112213570Sbrandon.potter@amd.com
112313570Sbrandon.potter@amd.com    int result = utimes(path.c_str(), hostTimeval);
112413570Sbrandon.potter@amd.com
112513570Sbrandon.potter@amd.com    if (result < 0)
112613570Sbrandon.potter@amd.com        return -errno;
112713570Sbrandon.potter@amd.com
112813570Sbrandon.potter@amd.com    return 0;
112913570Sbrandon.potter@amd.com}
113013570Sbrandon.potter@amd.com/// Target getrusage() function.
113113570Sbrandon.potter@amd.comtemplate <class OS>
113213570Sbrandon.potter@amd.comSyscallReturn
113313570Sbrandon.potter@amd.comgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
113413570Sbrandon.potter@amd.com              ThreadContext *tc)
113513570Sbrandon.potter@amd.com{
113613570Sbrandon.potter@amd.com    int index = 0;
113713570Sbrandon.potter@amd.com    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
113813570Sbrandon.potter@amd.com    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
113913570Sbrandon.potter@amd.com
114013570Sbrandon.potter@amd.com    rup->ru_utime.tv_sec = 0;
114113570Sbrandon.potter@amd.com    rup->ru_utime.tv_usec = 0;
114213570Sbrandon.potter@amd.com    rup->ru_stime.tv_sec = 0;
114313570Sbrandon.potter@amd.com    rup->ru_stime.tv_usec = 0;
114413570Sbrandon.potter@amd.com    rup->ru_maxrss = 0;
114513570Sbrandon.potter@amd.com    rup->ru_ixrss = 0;
114613570Sbrandon.potter@amd.com    rup->ru_idrss = 0;
114713570Sbrandon.potter@amd.com    rup->ru_isrss = 0;
114813570Sbrandon.potter@amd.com    rup->ru_minflt = 0;
114913570Sbrandon.potter@amd.com    rup->ru_majflt = 0;
115013570Sbrandon.potter@amd.com    rup->ru_nswap = 0;
115113570Sbrandon.potter@amd.com    rup->ru_inblock = 0;
115213570Sbrandon.potter@amd.com    rup->ru_oublock = 0;
115313570Sbrandon.potter@amd.com    rup->ru_msgsnd = 0;
115413570Sbrandon.potter@amd.com    rup->ru_msgrcv = 0;
115513570Sbrandon.potter@amd.com    rup->ru_nsignals = 0;
115613570Sbrandon.potter@amd.com    rup->ru_nvcsw = 0;
115713570Sbrandon.potter@amd.com    rup->ru_nivcsw = 0;
115813570Sbrandon.potter@amd.com
115913570Sbrandon.potter@amd.com    switch (who) {
116013570Sbrandon.potter@amd.com      case OS::TGT_RUSAGE_SELF:
116113570Sbrandon.potter@amd.com        getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
116213570Sbrandon.potter@amd.com        rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
116313570Sbrandon.potter@amd.com        rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
116413570Sbrandon.potter@amd.com        break;
116513570Sbrandon.potter@amd.com
116613570Sbrandon.potter@amd.com      case OS::TGT_RUSAGE_CHILDREN:
116713570Sbrandon.potter@amd.com        // do nothing.  We have no child processes, so they take no time.
116813570Sbrandon.potter@amd.com        break;
116913570Sbrandon.potter@amd.com
117013570Sbrandon.potter@amd.com      default:
117113570Sbrandon.potter@amd.com        // don't really handle THREAD or CHILDREN, but just warn and
117213570Sbrandon.potter@amd.com        // plow ahead
117313570Sbrandon.potter@amd.com        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
117413570Sbrandon.potter@amd.com             who);
117513570Sbrandon.potter@amd.com    }
117613570Sbrandon.potter@amd.com
117713570Sbrandon.potter@amd.com    rup.copyOut(tc->getMemPort());
117813570Sbrandon.potter@amd.com
117913570Sbrandon.potter@amd.com    return 0;
118013570Sbrandon.potter@amd.com}
118113570Sbrandon.potter@amd.com
118213570Sbrandon.potter@amd.com/// Target times() function.
118313570Sbrandon.potter@amd.comtemplate <class OS>
118413570Sbrandon.potter@amd.comSyscallReturn
118513570Sbrandon.potter@amd.comtimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
118613570Sbrandon.potter@amd.com           ThreadContext *tc)
118713570Sbrandon.potter@amd.com{
118813570Sbrandon.potter@amd.com    int index = 0;
118913570Sbrandon.potter@amd.com    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
119013570Sbrandon.potter@amd.com
119113570Sbrandon.potter@amd.com    // Fill in the time structure (in clocks)
11921999SN/A    int64_t clocks = curTick * OS::M5_SC_CLK_TCK / SimClock::Int::s;
11931999SN/A    bufp->tms_utime = clocks;
11941999SN/A    bufp->tms_stime = 0;
11951999SN/A    bufp->tms_cutime = 0;
119611856Sbrandon.potter@amd.com    bufp->tms_cstime = 0;
11971999SN/A
11986701Sgblack@eecs.umich.edu    // Convert to host endianness
119911856Sbrandon.potter@amd.com    bufp->tms_utime = htog(bufp->tms_utime);
120011856Sbrandon.potter@amd.com
120110931Sbrandon.potter@amd.com    // Write back
120211856Sbrandon.potter@amd.com    bufp.copyOut(tc->getMemPort());
120311856Sbrandon.potter@amd.com
12041999SN/A    // Return clock ticks since system boot
120511856Sbrandon.potter@amd.com    return clocks;
12061999SN/A}
120711856Sbrandon.potter@amd.com
12081999SN/A/// Target time() function.
120911856Sbrandon.potter@amd.comtemplate <class OS>
12101999SN/ASyscallReturn
121111856Sbrandon.potter@amd.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
12121999SN/A           ThreadContext *tc)
12131999SN/A{
12145877Shsul@eecs.umich.edu    typename OS::time_t sec, usec;
12155877Shsul@eecs.umich.edu    getElapsedTime(sec, usec);
12165877Shsul@eecs.umich.edu    sec += seconds_since_epoch;
121711851Sbrandon.potter@amd.com
12185877Shsul@eecs.umich.edu    int index = 0;
12196701Sgblack@eecs.umich.edu    Addr taddr = (Addr)process->getSyscallArg(tc, index);
12206701Sgblack@eecs.umich.edu    if(taddr != 0) {
12216701Sgblack@eecs.umich.edu        typename OS::time_t t = sec;
12226701Sgblack@eecs.umich.edu        t = htog(t);
12236701Sgblack@eecs.umich.edu        TranslatingPort *p = tc->getMemPort();
122410027SChris.Adeniyi-Jones@arm.com        p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
122510027SChris.Adeniyi-Jones@arm.com    }
122610027SChris.Adeniyi-Jones@arm.com    return sec;
122710027SChris.Adeniyi-Jones@arm.com}
122810027SChris.Adeniyi-Jones@arm.com
12295877Shsul@eecs.umich.edu
123010318Sandreas.hansson@arm.com#endif // __SIM_SYSCALL_EMUL_HH__
123110318Sandreas.hansson@arm.com