syscall_emul.hh revision 10027
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2012-2013 ARM Limited
310796Sbrandon.potter@amd.com * All rights reserved
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall
610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual
710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating
810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software
910027SChris.Adeniyi-Jones@arm.com * licensed hereunder.  You may use the software subject to the license
1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated
1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software,
1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form.
1310027SChris.Adeniyi-Jones@arm.com *
1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
151458SN/A * All rights reserved.
16360SN/A *
17360SN/A * Redistribution and use in source and binary forms, with or without
18360SN/A * modification, are permitted provided that the following conditions are
19360SN/A * met: redistributions of source code must retain the above copyright
20360SN/A * notice, this list of conditions and the following disclaimer;
21360SN/A * redistributions in binary form must reproduce the above copyright
22360SN/A * notice, this list of conditions and the following disclaimer in the
23360SN/A * documentation and/or other materials provided with the distribution;
24360SN/A * neither the name of the copyright holders nor the names of its
25360SN/A * contributors may be used to endorse or promote products derived from
26360SN/A * this software without specific prior written permission.
27360SN/A *
28360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39360SN/A *
402665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
412665Ssaidi@eecs.umich.edu *          Kevin Lim
422665Ssaidi@eecs.umich.edu */
43360SN/A
44360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__
451354SN/A#define __SIM_SYSCALL_EMUL_HH__
461354SN/A
47360SN/A#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
4812018Sandreas.sandberg@arm.com  defined(__FreeBSD__) || defined(__CYGWIN__) || \
4912018Sandreas.sandberg@arm.com  defined(__NetBSD__))
5012018Sandreas.sandberg@arm.com
5112018Sandreas.sandberg@arm.com///
5212018Sandreas.sandberg@arm.com/// @file syscall_emul.hh
5312018Sandreas.sandberg@arm.com///
5412018Sandreas.sandberg@arm.com/// This file defines objects used to emulate syscalls from the target
552064SN/A/// application on the host machine.
5612018Sandreas.sandberg@arm.com
5712018Sandreas.sandberg@arm.com#ifdef __CYGWIN32__
5812018Sandreas.sandberg@arm.com#include <sys/fcntl.h>  // for O_BINARY
5912018Sandreas.sandberg@arm.com#endif
6012018Sandreas.sandberg@arm.com#include <sys/stat.h>
6112018Sandreas.sandberg@arm.com#include <sys/time.h>
6211799Sbrandon.potter@amd.com#include <sys/uio.h>
6312018Sandreas.sandberg@arm.com#include <fcntl.h>
6412018Sandreas.sandberg@arm.com
6512018Sandreas.sandberg@arm.com#include <cerrno>
6612018Sandreas.sandberg@arm.com#include <string>
6712018Sandreas.sandberg@arm.com
6812018Sandreas.sandberg@arm.com#include "base/chunk_generator.hh"
6911799Sbrandon.potter@amd.com#include "base/intmath.hh"      // for RoundUp
70360SN/A#include "base/misc.hh"
71360SN/A#include "base/trace.hh"
72360SN/A#include "base/types.hh"
73360SN/A#include "config/the_isa.hh"
74360SN/A#include "cpu/base.hh"
75360SN/A#include "cpu/thread_context.hh"
761809SN/A#include "debug/SyscallVerbose.hh"
7711800Sbrandon.potter@amd.com#include "mem/page_table.hh"
7811392Sbrandon.potter@amd.com#include "mem/se_translating_port_proxy.hh"
791809SN/A#include "sim/byteswap.hh"
8011392Sbrandon.potter@amd.com#include "sim/process.hh"
8113570Sbrandon.potter@amd.com#include "sim/syscallreturn.hh"
8211383Sbrandon.potter@amd.com#include "sim/system.hh"
8313568Sbrandon.potter@amd.com
843113Sgblack@eecs.umich.edu///
8511799Sbrandon.potter@amd.com/// System call descriptor.
8611759Sbrandon.potter@amd.com///
8711812Sbaz21@cam.ac.ukclass SyscallDesc {
8811812Sbaz21@cam.ac.uk
8911799Sbrandon.potter@amd.com  public:
908229Snate@binkert.org
9113570Sbrandon.potter@amd.com    /// Typedef for target syscall handler functions.
928229Snate@binkert.org    typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
9311594Santhony.gutierrez@amd.com                           LiveProcess *, ThreadContext *);
947075Snate@binkert.org
958229Snate@binkert.org    const char *name;   //!< Syscall name (e.g., "open").
9611856Sbrandon.potter@amd.com    FuncPtr funcPtr;    //!< Pointer to emulation function.
977075Snate@binkert.org    int flags;          //!< Flags (see Flags enum).
98360SN/A
9912461Sgabeblack@google.com    /// Flag values for controlling syscall behavior.
10011886Sbrandon.potter@amd.com    enum Flags {
10111800Sbrandon.potter@amd.com        /// Don't set return regs according to funcPtr return value.
10211392Sbrandon.potter@amd.com        /// Used for syscalls with non-standard return conventions
10312334Sgabeblack@google.com        /// that explicitly set the ThreadContext regs (e.g.,
1041354SN/A        /// sigreturn).
1056216Snate@binkert.org        SuppressReturnValue = 1
1066658Snate@binkert.org    };
1072474SN/A
1082680Sktlim@umich.edu    /// Constructor.
1098229Snate@binkert.org    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
11011886Sbrandon.potter@amd.com        : name(_name), funcPtr(_funcPtr), flags(_flags)
11110496Ssteve.reinhardt@amd.com    {
11211911SBrandon.Potter@amd.com    }
1138229Snate@binkert.org
11411794Sbrandon.potter@amd.com    /// Emulate the syscall.  Public interface for calling through funcPtr.
11511886Sbrandon.potter@amd.com    void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
11610497Ssteve.reinhardt@amd.com};
11711794Sbrandon.potter@amd.com
118360SN/A
119360SN/Aclass BaseBufferArg {
120360SN/A
121360SN/A  public:
122360SN/A
123360SN/A    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
124360SN/A    {
125360SN/A        bufPtr = new uint8_t[size];
126360SN/A        // clear out buffer: in case we only partially populate this,
127360SN/A        // and then do a copyOut(), we want to make sure we don't
128378SN/A        // introduce any random junk into the simulated address space
1291706SN/A        memset(bufPtr, 0, size);
13011851Sbrandon.potter@amd.com    }
131378SN/A
132378SN/A    virtual ~BaseBufferArg() { delete [] bufPtr; }
133378SN/A
134378SN/A    //
135378SN/A    // copy data into simulator space (read from target memory)
1361706SN/A    //
13711851Sbrandon.potter@amd.com    virtual bool copyIn(SETranslatingPortProxy &memproxy)
138360SN/A    {
13911760Sbrandon.potter@amd.com        memproxy.readBlob(addr, bufPtr, size);
14011760Sbrandon.potter@amd.com        return true;    // no EFAULT detection for now
14111851Sbrandon.potter@amd.com    }
14211760Sbrandon.potter@amd.com
1436109Ssanchezd@stanford.edu    //
1441706SN/A    // copy data out of simulator space (write to target memory)
14511851Sbrandon.potter@amd.com    //
146378SN/A    virtual bool copyOut(SETranslatingPortProxy &memproxy)
1476109Ssanchezd@stanford.edu    {
1486109Ssanchezd@stanford.edu        memproxy.writeBlob(addr, bufPtr, size);
14911851Sbrandon.potter@amd.com        return true;    // no EFAULT detection for now
1506109Ssanchezd@stanford.edu    }
15111886Sbrandon.potter@amd.com
15211886Sbrandon.potter@amd.com  protected:
15311886Sbrandon.potter@amd.com    Addr addr;
15411886Sbrandon.potter@amd.com    int size;
155378SN/A    uint8_t *bufPtr;
1561706SN/A};
15711851Sbrandon.potter@amd.com
158378SN/A
1595748SSteve.Reinhardt@amd.comclass BufferArg : public BaseBufferArg
1605748SSteve.Reinhardt@amd.com{
16111851Sbrandon.potter@amd.com  public:
162378SN/A    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
163378SN/A    void *bufferPtr()   { return bufPtr; }
1641706SN/A};
16511851Sbrandon.potter@amd.com
166378SN/Atemplate <class T>
167378SN/Aclass TypedBufferArg : public BaseBufferArg
1681706SN/A{
16911851Sbrandon.potter@amd.com  public:
170378SN/A    // user can optionally specify a specific number of bytes to
1714118Sgblack@eecs.umich.edu    // allocate to deal with those structs that have variable-size
1724118Sgblack@eecs.umich.edu    // arrays at the end
17311851Sbrandon.potter@amd.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
1744118Sgblack@eecs.umich.edu        : BaseBufferArg(_addr, _size)
175378SN/A    { }
1761706SN/A
17711851Sbrandon.potter@amd.com    // type case
178378SN/A    operator T*() { return (T *)bufPtr; }
17913568Sbrandon.potter@amd.com
18013568Sbrandon.potter@amd.com    // dereference operators
18113568Sbrandon.potter@amd.com    T &operator*()       { return *((T *)bufPtr); }
18213568Sbrandon.potter@amd.com    T* operator->()      { return (T *)bufPtr; }
183378SN/A    T &operator[](int i) { return ((T *)bufPtr)[i]; }
1841706SN/A};
18511851Sbrandon.potter@amd.com
186360SN/A//////////////////////////////////////////////////////////////////////
1875513SMichael.Adler@intel.com//
1885513SMichael.Adler@intel.com// The following emulation functions are generic enough that they
18911851Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's.  They are
1905513SMichael.Adler@intel.com// defined in sim/syscall_emul.cc.
19110203SAli.Saidi@ARM.com//
19210203SAli.Saidi@ARM.com//////////////////////////////////////////////////////////////////////
19311851Sbrandon.potter@amd.com
19410203SAli.Saidi@ARM.com
1955513SMichael.Adler@intel.com/// Handler for unimplemented syscalls that we haven't thought about.
19611851Sbrandon.potter@amd.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
1975513SMichael.Adler@intel.com                                LiveProcess *p, ThreadContext *tc);
198511SN/A
19910633Smichaelupton@gmail.com/// Handler for unimplemented syscalls that we never intend to
20011851Sbrandon.potter@amd.com/// implement (signal handling, etc.) and should not affect the correct
20110633Smichaelupton@gmail.com/// behavior of the program.  Print a warning only if the appropriate
2021706SN/A/// trace flag is enabled.  Return success to the target program.
20311851Sbrandon.potter@amd.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num,
204511SN/A                         LiveProcess *p, ThreadContext *tc);
20512795Smattdsinclair@gmail.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num,
20612795Smattdsinclair@gmail.com                         LiveProcess *p, ThreadContext *tc);
20712795Smattdsinclair@gmail.com
20812795Smattdsinclair@gmail.com/// Target exit() handler: terminate current context.
20912796Smattdsinclair@gmail.comSyscallReturn exitFunc(SyscallDesc *desc, int num,
21012796Smattdsinclair@gmail.com                       LiveProcess *p, ThreadContext *tc);
21112796Smattdsinclair@gmail.com
21212796Smattdsinclair@gmail.com/// Target exit_group() handler: terminate simulation. (exit all threads)
2135513SMichael.Adler@intel.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
2145513SMichael.Adler@intel.com                       LiveProcess *p, ThreadContext *tc);
21511851Sbrandon.potter@amd.com
2165513SMichael.Adler@intel.com/// Target getpagesize() handler.
21713031Sbrandon.potter@amd.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
21813031Sbrandon.potter@amd.com                              LiveProcess *p, ThreadContext *tc);
21913031Sbrandon.potter@amd.com
22013031Sbrandon.potter@amd.com/// Target brk() handler: set brk address.
22113031Sbrandon.potter@amd.comSyscallReturn brkFunc(SyscallDesc *desc, int num,
22213031Sbrandon.potter@amd.com                      LiveProcess *p, ThreadContext *tc);
22313031Sbrandon.potter@amd.com
22413031Sbrandon.potter@amd.com/// Target close() handler.
22513031Sbrandon.potter@amd.comSyscallReturn closeFunc(SyscallDesc *desc, int num,
22613031Sbrandon.potter@amd.com                        LiveProcess *p, ThreadContext *tc);
22713031Sbrandon.potter@amd.com
22813031Sbrandon.potter@amd.com/// Target read() handler.
229511SN/ASyscallReturn readFunc(SyscallDesc *desc, int num,
2301706SN/A                       LiveProcess *p, ThreadContext *tc);
23111851Sbrandon.potter@amd.com
2321706SN/A/// Target write() handler.
2331706SN/ASyscallReturn writeFunc(SyscallDesc *desc, int num,
2341706SN/A                        LiveProcess *p, ThreadContext *tc);
2351706SN/A
23611851Sbrandon.potter@amd.com/// Target lseek() handler.
2371706SN/ASyscallReturn lseekFunc(SyscallDesc *desc, int num,
2381706SN/A                        LiveProcess *p, ThreadContext *tc);
2391706SN/A
2401706SN/A/// Target _llseek() handler.
24111851Sbrandon.potter@amd.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num,
2421706SN/A                        LiveProcess *p, ThreadContext *tc);
243511SN/A
2446703Svince@csl.cornell.edu/// Target munmap() handler.
2456703Svince@csl.cornell.eduSyscallReturn munmapFunc(SyscallDesc *desc, int num,
24611851Sbrandon.potter@amd.com                         LiveProcess *p, ThreadContext *tc);
2476703Svince@csl.cornell.edu
2486685Stjones1@inf.ed.ac.uk/// Target gethostname() handler.
2496685Stjones1@inf.ed.ac.ukSyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
25011851Sbrandon.potter@amd.com                              LiveProcess *p, ThreadContext *tc);
2516685Stjones1@inf.ed.ac.uk
2526685Stjones1@inf.ed.ac.uk/// Target getcwd() handler.
2535513SMichael.Adler@intel.comSyscallReturn getcwdFunc(SyscallDesc *desc, int num,
2545513SMichael.Adler@intel.com                         LiveProcess *p, ThreadContext *tc);
25511851Sbrandon.potter@amd.com
2565513SMichael.Adler@intel.com/// Target unlink() handler.
25711885Sbrandon.potter@amd.comSyscallReturn readlinkFunc(SyscallDesc *desc, int num,
25811885Sbrandon.potter@amd.com                           LiveProcess *p, ThreadContext *tc);
25911885Sbrandon.potter@amd.com
2605513SMichael.Adler@intel.com/// Target unlink() handler.
2611999SN/ASyscallReturn unlinkFunc(SyscallDesc *desc, int num,
2621999SN/A                         LiveProcess *p, ThreadContext *tc);
26311851Sbrandon.potter@amd.com
2641999SN/A/// Target mkdir() handler.
26511885Sbrandon.potter@amd.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num,
26611885Sbrandon.potter@amd.com                        LiveProcess *p, ThreadContext *tc);
26711885Sbrandon.potter@amd.com
2681999SN/A/// Target rename() handler.
2691999SN/ASyscallReturn renameFunc(SyscallDesc *desc, int num,
2701999SN/A                         LiveProcess *p, ThreadContext *tc);
27111851Sbrandon.potter@amd.com
2721999SN/A
2733079Sstever@eecs.umich.edu/// Target truncate() handler.
2743079Sstever@eecs.umich.eduSyscallReturn truncateFunc(SyscallDesc *desc, int num,
27511851Sbrandon.potter@amd.com                           LiveProcess *p, ThreadContext *tc);
2763079Sstever@eecs.umich.edu
27711908SBrandon.Potter@amd.com
27811908SBrandon.Potter@amd.com/// Target ftruncate() handler.
27911908SBrandon.Potter@amd.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
28011908SBrandon.Potter@amd.com                            LiveProcess *p, ThreadContext *tc);
28111875Sbrandon.potter@amd.com
2822093SN/A
28311851Sbrandon.potter@amd.com/// Target truncate64() handler.
2842093SN/ASyscallReturn truncate64Func(SyscallDesc *desc, int num,
2852687Sksewell@umich.edu                             LiveProcess *p, ThreadContext *tc);
2862687Sksewell@umich.edu
28711851Sbrandon.potter@amd.com/// Target ftruncate64() handler.
2882687Sksewell@umich.eduSyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
2892238SN/A                              LiveProcess *p, ThreadContext *tc);
2902238SN/A
29111851Sbrandon.potter@amd.com
2922238SN/A/// Target umask() handler.
29311908SBrandon.Potter@amd.comSyscallReturn umaskFunc(SyscallDesc *desc, int num,
29411908SBrandon.Potter@amd.com                        LiveProcess *p, ThreadContext *tc);
29511908SBrandon.Potter@amd.com
29611908SBrandon.Potter@amd.com
29711908SBrandon.Potter@amd.com/// Target chown() handler.
29811908SBrandon.Potter@amd.comSyscallReturn chownFunc(SyscallDesc *desc, int num,
29911908SBrandon.Potter@amd.com                        LiveProcess *p, ThreadContext *tc);
30011908SBrandon.Potter@amd.com
3012238SN/A
3022238SN/A/// Target fchown() handler.
30311851Sbrandon.potter@amd.comSyscallReturn fchownFunc(SyscallDesc *desc, int num,
3042238SN/A                         LiveProcess *p, ThreadContext *tc);
30513571Sbrandon.potter@amd.com
30613571Sbrandon.potter@amd.com/// Target dup() handler.
30713571Sbrandon.potter@amd.comSyscallReturn dupFunc(SyscallDesc *desc, int num,
30813571Sbrandon.potter@amd.com                      LiveProcess *process, ThreadContext *tc);
30913568Sbrandon.potter@amd.com
31013568Sbrandon.potter@amd.com/// Target fnctl() handler.
31113568Sbrandon.potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num,
31213568Sbrandon.potter@amd.com                        LiveProcess *process, ThreadContext *tc);
31313568Sbrandon.potter@amd.com
31413568Sbrandon.potter@amd.com/// Target fcntl64() handler.
31513568Sbrandon.potter@amd.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num,
31613568Sbrandon.potter@amd.com                        LiveProcess *process, ThreadContext *tc);
31713568Sbrandon.potter@amd.com
31813568Sbrandon.potter@amd.com/// Target setuid() handler.
31913568Sbrandon.potter@amd.comSyscallReturn setuidFunc(SyscallDesc *desc, int num,
32013568Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
32113448Sciro.santilli@arm.com
32213031Sbrandon.potter@amd.com/// Target getpid() handler.
32313031Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num,
32413031Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
32513448Sciro.santilli@arm.com
32613031Sbrandon.potter@amd.com/// Target getuid() handler.
32713539Sjavier.setoain@arm.comSyscallReturn getuidFunc(SyscallDesc *desc, int num,
32813539Sjavier.setoain@arm.com                               LiveProcess *p, ThreadContext *tc);
32913539Sjavier.setoain@arm.com
33013539Sjavier.setoain@arm.com/// Target getgid() handler.
33113539Sjavier.setoain@arm.comSyscallReturn getgidFunc(SyscallDesc *desc, int num,
33213539Sjavier.setoain@arm.com                               LiveProcess *p, ThreadContext *tc);
33313569Sbrandon.potter@amd.com
33413569Sbrandon.potter@amd.com/// Target getppid() handler.
33513569Sbrandon.potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num,
33613569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
33713569Sbrandon.potter@amd.com
33813569Sbrandon.potter@amd.com/// Target geteuid() handler.
33913569Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num,
34013569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
34113569Sbrandon.potter@amd.com
34213569Sbrandon.potter@amd.com/// Target getegid() handler.
34313569Sbrandon.potter@amd.comSyscallReturn getegidFunc(SyscallDesc *desc, int num,
34413569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
34513569Sbrandon.potter@amd.com
34613569Sbrandon.potter@amd.com/// Target clone() handler.
34713569Sbrandon.potter@amd.comSyscallReturn cloneFunc(SyscallDesc *desc, int num,
34813569Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
34913031Sbrandon.potter@amd.com
3502238SN/A/// Target access() handler
35111851Sbrandon.potter@amd.comSyscallReturn accessFunc(SyscallDesc *desc, int num,
3522238SN/A                               LiveProcess *p, ThreadContext *tc);
3532238SN/A
3542238SN/A/// Futex system call
35511851Sbrandon.potter@amd.com///  Implemented by Daniel Sanchez
3562238SN/A///  Used by printf's in multi-threaded apps
3572238SN/Atemplate <class OS>
3582238SN/ASyscallReturn
35911851Sbrandon.potter@amd.comfutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
3602238SN/A          ThreadContext *tc)
3612238SN/A{
3622238SN/A    int index_uaddr = 0;
36311851Sbrandon.potter@amd.com    int index_op = 1;
3642238SN/A    int index_val = 2;
3652238SN/A    int index_timeout = 3;
3662238SN/A
36711851Sbrandon.potter@amd.com    uint64_t uaddr = process->getSyscallArg(tc, index_uaddr);
3682238SN/A    int op = process->getSyscallArg(tc, index_op);
3699455Smitch.hayenga+gem5@gmail.com    int val = process->getSyscallArg(tc, index_val);
3709455Smitch.hayenga+gem5@gmail.com    uint64_t timeout = process->getSyscallArg(tc, index_timeout);
37111851Sbrandon.potter@amd.com
37210203SAli.Saidi@ARM.com    std::map<uint64_t, std::list<ThreadContext *> * >
37311851Sbrandon.potter@amd.com        &futex_map = tc->getSystemPtr()->futexMap;
37411851Sbrandon.potter@amd.com
3759455Smitch.hayenga+gem5@gmail.com    DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n",
37613571Sbrandon.potter@amd.com            uaddr, op, val);
37713571Sbrandon.potter@amd.com
37813571Sbrandon.potter@amd.com    op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
37913571Sbrandon.potter@amd.com
38013571Sbrandon.potter@amd.com    if (op == OS::TGT_FUTEX_WAIT) {
38113571Sbrandon.potter@amd.com        if (timeout != 0) {
38213571Sbrandon.potter@amd.com            warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;"
38313571Sbrandon.potter@amd.com                 "we'll wait indefinitely");
38413571Sbrandon.potter@amd.com        }
38513571Sbrandon.potter@amd.com
38613571Sbrandon.potter@amd.com        uint8_t *buf = new uint8_t[sizeof(int)];
38713571Sbrandon.potter@amd.com        tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int));
3889112Smarc.orr@gmail.com        int mem_val = *((int *)buf);
38911906SBrandon.Potter@amd.com        delete buf;
39011906SBrandon.Potter@amd.com
3919112Smarc.orr@gmail.com        if(val != mem_val) {
3929112Smarc.orr@gmail.com            DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, "
39311851Sbrandon.potter@amd.com                                    "expected: %d\n", mem_val, val);
3949112Smarc.orr@gmail.com            return -OS::TGT_EWOULDBLOCK;
3959112Smarc.orr@gmail.com        }
39611911SBrandon.Potter@amd.com
3979112Smarc.orr@gmail.com        // Queue the thread context
39811911SBrandon.Potter@amd.com        std::list<ThreadContext *> * tcWaitList;
39911911SBrandon.Potter@amd.com        if (futex_map.count(uaddr)) {
40011911SBrandon.Potter@amd.com            tcWaitList = futex_map.find(uaddr)->second;
40111911SBrandon.Potter@amd.com        } else {
4029112Smarc.orr@gmail.com            tcWaitList = new std::list<ThreadContext *>();
40311911SBrandon.Potter@amd.com            futex_map.insert(std::pair< uint64_t,
40411911SBrandon.Potter@amd.com                            std::list<ThreadContext *> * >(uaddr, tcWaitList));
40511911SBrandon.Potter@amd.com        }
40611911SBrandon.Potter@amd.com        tcWaitList->push_back(tc);
4079238Slluc.alvarez@bsc.es        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling "
4089112Smarc.orr@gmail.com                                "thread context\n");
40911911SBrandon.Potter@amd.com        tc->suspend();
4109112Smarc.orr@gmail.com        return 0;
41111911SBrandon.Potter@amd.com    } else if (op == OS::TGT_FUTEX_WAKE){
41211911SBrandon.Potter@amd.com        int wokenUp = 0;
41311911SBrandon.Potter@amd.com        std::list<ThreadContext *> * tcWaitList;
41411911SBrandon.Potter@amd.com        if (futex_map.count(uaddr)) {
41511911SBrandon.Potter@amd.com            tcWaitList = futex_map.find(uaddr)->second;
4169112Smarc.orr@gmail.com            while (tcWaitList->size() > 0 && wokenUp < val) {
41711911SBrandon.Potter@amd.com                tcWaitList->front()->activate();
41811911SBrandon.Potter@amd.com                tcWaitList->pop_front();
41911911SBrandon.Potter@amd.com                wokenUp++;
42011911SBrandon.Potter@amd.com            }
42111911SBrandon.Potter@amd.com            if(tcWaitList->empty()) {
42211911SBrandon.Potter@amd.com                futex_map.erase(uaddr);
4239112Smarc.orr@gmail.com                delete tcWaitList;
4249112Smarc.orr@gmail.com            }
42511911SBrandon.Potter@amd.com        }
42611911SBrandon.Potter@amd.com        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting "
4279112Smarc.orr@gmail.com                                "thread contexts\n", wokenUp);
42811911SBrandon.Potter@amd.com        return wokenUp;
42911911SBrandon.Potter@amd.com    } else {
4309112Smarc.orr@gmail.com        warn("sys_futex: op %d is not implemented, just returning...", op);
4319112Smarc.orr@gmail.com        return 0;
43211911SBrandon.Potter@amd.com    }
43311911SBrandon.Potter@amd.com
4349112Smarc.orr@gmail.com}
4359112Smarc.orr@gmail.com
4362238SN/A
4372238SN/A/// Pseudo Funcs  - These functions use a different return convension,
4382238SN/A/// returning a second value in a register other than the normal return register
4392238SN/ASyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
44011851Sbrandon.potter@amd.com                             LiveProcess *process, ThreadContext *tc);
4412238SN/A
4422238SN/A/// Target getpidPseudo() handler.
4432238SN/ASyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
44411851Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
4452238SN/A
4462238SN/A/// Target getuidPseudo() handler.
4472238SN/ASyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
44811851Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
4492238SN/A
4502238SN/A/// Target getgidPseudo() handler.
4512238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
45211851Sbrandon.potter@amd.com                               LiveProcess *p, ThreadContext *tc);
4532238SN/A
4542238SN/A
4551354SN/A/// A readable name for 1,000,000, for converting microseconds to seconds.
4561354SN/Aconst int one_million = 1000000;
45710796Sbrandon.potter@amd.com
45810796Sbrandon.potter@amd.com/// Approximate seconds since the epoch (1/1/1970).  About a billion,
4591354SN/A/// by my reckoning.  We want to keep this a constant (not use the
4601354SN/A/// real-world time) to keep simulations repeatable.
4611354SN/Aconst unsigned seconds_since_epoch = 1000000000;
4621354SN/A
4631354SN/A/// Helper function to convert current elapsed time to seconds and
4641354SN/A/// microseconds.
4651354SN/Atemplate <class T1, class T2>
4661354SN/Avoid
4671354SN/AgetElapsedTime(T1 &sec, T2 &usec)
4681354SN/A{
46910796Sbrandon.potter@amd.com    int elapsed_usecs = curTick() / SimClock::Int::us;
4701354SN/A    sec = elapsed_usecs / one_million;
47110796Sbrandon.potter@amd.com    usec = elapsed_usecs % one_million;
4721354SN/A}
4731354SN/A
4741354SN/A//////////////////////////////////////////////////////////////////////
4751354SN/A//
47610796Sbrandon.potter@amd.com// The following emulation functions are generic, but need to be
47710796Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc.
47810796Sbrandon.potter@amd.com//
47910796Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
48010796Sbrandon.potter@amd.com
48110796Sbrandon.potter@amd.com#if NO_STAT64
48210796Sbrandon.potter@amd.com    typedef struct stat hst_stat;
48310796Sbrandon.potter@amd.com    typedef struct stat hst_stat64;
48410796Sbrandon.potter@amd.com#else
48510796Sbrandon.potter@amd.com    typedef struct stat hst_stat;
48610796Sbrandon.potter@amd.com    typedef struct stat64 hst_stat64;
487360SN/A#endif
488360SN/A
489360SN/A//// Helper function to convert a host stat buffer to a target stat
490360SN/A//// buffer.  Also copies the target buffer out to the simulated
491360SN/A//// memory space.  Used by stat(), fstat(), and lstat().
492360SN/A
493360SN/Atemplate <typename target_stat, typename host_stat>
49411759Sbrandon.potter@amd.comstatic void
4953113Sgblack@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
4963113Sgblack@eecs.umich.edu{
4973113Sgblack@eecs.umich.edu    using namespace TheISA;
4983113Sgblack@eecs.umich.edu
4993113Sgblack@eecs.umich.edu    if (fakeTTY)
5003113Sgblack@eecs.umich.edu        tgt->st_dev = 0xA;
5013113Sgblack@eecs.umich.edu    else
5023113Sgblack@eecs.umich.edu        tgt->st_dev = host->st_dev;
5033113Sgblack@eecs.umich.edu    tgt->st_dev = TheISA::htog(tgt->st_dev);
5043113Sgblack@eecs.umich.edu    tgt->st_ino = host->st_ino;
5053113Sgblack@eecs.umich.edu    tgt->st_ino = TheISA::htog(tgt->st_ino);
5063113Sgblack@eecs.umich.edu    tgt->st_mode = host->st_mode;
5073113Sgblack@eecs.umich.edu    if (fakeTTY) {
50812032Sandreas.sandberg@arm.com        // Claim to be a character device
5093113Sgblack@eecs.umich.edu        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
5103113Sgblack@eecs.umich.edu        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
5114189Sgblack@eecs.umich.edu    }
5124189Sgblack@eecs.umich.edu    tgt->st_mode = TheISA::htog(tgt->st_mode);
5133113Sgblack@eecs.umich.edu    tgt->st_nlink = host->st_nlink;
5143113Sgblack@eecs.umich.edu    tgt->st_nlink = TheISA::htog(tgt->st_nlink);
5153113Sgblack@eecs.umich.edu    tgt->st_uid = host->st_uid;
5163113Sgblack@eecs.umich.edu    tgt->st_uid = TheISA::htog(tgt->st_uid);
5178737Skoansin.tan@gmail.com    tgt->st_gid = host->st_gid;
5183113Sgblack@eecs.umich.edu    tgt->st_gid = TheISA::htog(tgt->st_gid);
5198737Skoansin.tan@gmail.com    if (fakeTTY)
5203277Sgblack@eecs.umich.edu        tgt->st_rdev = 0x880d;
5215515SMichael.Adler@intel.com    else
5225515SMichael.Adler@intel.com        tgt->st_rdev = host->st_rdev;
5235515SMichael.Adler@intel.com    tgt->st_rdev = TheISA::htog(tgt->st_rdev);
5245515SMichael.Adler@intel.com    tgt->st_size = host->st_size;
5255515SMichael.Adler@intel.com    tgt->st_size = TheISA::htog(tgt->st_size);
5268737Skoansin.tan@gmail.com    tgt->st_atimeX = host->st_atime;
5273277Sgblack@eecs.umich.edu    tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
5288737Skoansin.tan@gmail.com    tgt->st_mtimeX = host->st_mtime;
5293277Sgblack@eecs.umich.edu    tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
5308737Skoansin.tan@gmail.com    tgt->st_ctimeX = host->st_ctime;
5313277Sgblack@eecs.umich.edu    tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
5328737Skoansin.tan@gmail.com    // Force the block size to be 8k. This helps to ensure buffered io works
5333113Sgblack@eecs.umich.edu    // consistently across different hosts.
5343113Sgblack@eecs.umich.edu    tgt->st_blksize = 0x2000;
5353113Sgblack@eecs.umich.edu    tgt->st_blksize = TheISA::htog(tgt->st_blksize);
5363113Sgblack@eecs.umich.edu    tgt->st_blocks = host->st_blocks;
5378737Skoansin.tan@gmail.com    tgt->st_blocks = TheISA::htog(tgt->st_blocks);
5383113Sgblack@eecs.umich.edu}
5398737Skoansin.tan@gmail.com
5403114Sgblack@eecs.umich.edu// Same for stat64
5418737Skoansin.tan@gmail.com
5423114Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat64>
5438737Skoansin.tan@gmail.comstatic void
5443114Sgblack@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
5458737Skoansin.tan@gmail.com{
54611906SBrandon.Potter@amd.com    using namespace TheISA;
5474061Sgblack@eecs.umich.edu
5484061Sgblack@eecs.umich.edu    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
5498737Skoansin.tan@gmail.com#if defined(STAT_HAVE_NSEC)
5503113Sgblack@eecs.umich.edu    tgt->st_atime_nsec = host->st_atime_nsec;
5518737Skoansin.tan@gmail.com    tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
5523113Sgblack@eecs.umich.edu    tgt->st_mtime_nsec = host->st_mtime_nsec;
5533113Sgblack@eecs.umich.edu    tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
5543113Sgblack@eecs.umich.edu    tgt->st_ctime_nsec = host->st_ctime_nsec;
5553113Sgblack@eecs.umich.edu    tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
5563113Sgblack@eecs.umich.edu#else
55712032Sandreas.sandberg@arm.com    tgt->st_atime_nsec = 0;
5583113Sgblack@eecs.umich.edu    tgt->st_mtime_nsec = 0;
5593113Sgblack@eecs.umich.edu    tgt->st_ctime_nsec = 0;
5604189Sgblack@eecs.umich.edu#endif
5614189Sgblack@eecs.umich.edu}
5623113Sgblack@eecs.umich.edu
5633113Sgblack@eecs.umich.edu//Here are a couple convenience functions
5643113Sgblack@eecs.umich.edutemplate<class OS>
5658737Skoansin.tan@gmail.comstatic void
5663113Sgblack@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr,
5678737Skoansin.tan@gmail.com        hst_stat *host, bool fakeTTY = false)
5683113Sgblack@eecs.umich.edu{
5698737Skoansin.tan@gmail.com    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
5703113Sgblack@eecs.umich.edu    tgt_stat_buf tgt(addr);
5713113Sgblack@eecs.umich.edu    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
5723113Sgblack@eecs.umich.edu    tgt.copyOut(mem);
5733113Sgblack@eecs.umich.edu}
5743113Sgblack@eecs.umich.edu
5753113Sgblack@eecs.umich.edutemplate<class OS>
5763113Sgblack@eecs.umich.edustatic void
57711906SBrandon.Potter@amd.comcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr,
5783113Sgblack@eecs.umich.edu        hst_stat64 *host, bool fakeTTY = false)
57912032Sandreas.sandberg@arm.com{
5808852Sandreas.hansson@arm.com    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
58111906SBrandon.Potter@amd.com    tgt_stat_buf tgt(addr);
5823113Sgblack@eecs.umich.edu    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
5833113Sgblack@eecs.umich.edu    tgt.copyOut(mem);
5843113Sgblack@eecs.umich.edu}
5853113Sgblack@eecs.umich.edu
5863113Sgblack@eecs.umich.edu/// Target ioctl() handler.  For the most part, programs call ioctl()
5873113Sgblack@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to
5883113Sgblack@eecs.umich.edu/// do line or block buffering.  We always claim that output fds are
5893113Sgblack@eecs.umich.edu/// not TTYs to provide repeatable results.
59012032Sandreas.sandberg@arm.comtemplate <class OS>
5918852Sandreas.hansson@arm.comSyscallReturn
59211906SBrandon.Potter@amd.comioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
5933113Sgblack@eecs.umich.edu          ThreadContext *tc)
5943113Sgblack@eecs.umich.edu{
5953113Sgblack@eecs.umich.edu    int index = 0;
5966686Stjones1@inf.ed.ac.uk    int fd = process->getSyscallArg(tc, index);
5973113Sgblack@eecs.umich.edu    unsigned req = process->getSyscallArg(tc, index);
5983113Sgblack@eecs.umich.edu
5993113Sgblack@eecs.umich.edu    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
60011759Sbrandon.potter@amd.com
60112032Sandreas.sandberg@arm.com    if (fd < 0 || process->sim_fd(fd) < 0) {
60211759Sbrandon.potter@amd.com        // doesn't map to any simulator fd: not a valid target fd
60311759Sbrandon.potter@amd.com        return -EBADF;
60411759Sbrandon.potter@amd.com    }
60511759Sbrandon.potter@amd.com
60611759Sbrandon.potter@amd.com    if (OS::isTtyReq(req)) {
60711812Sbaz21@cam.ac.uk        return -ENOTTY;
60811812Sbaz21@cam.ac.uk    }
60911812Sbaz21@cam.ac.uk
61011759Sbrandon.potter@amd.com    warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
61111812Sbaz21@cam.ac.uk         fd, req, tc->pcState());
61211759Sbrandon.potter@amd.com    return -ENOTTY;
61311759Sbrandon.potter@amd.com}
61411759Sbrandon.potter@amd.com
61511759Sbrandon.potter@amd.comtemplate <class OS>
61611759Sbrandon.potter@amd.comstatic SyscallReturn
61711759Sbrandon.potter@amd.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
61811759Sbrandon.potter@amd.com         ThreadContext *tc, int index)
61911812Sbaz21@cam.ac.uk{
62011812Sbaz21@cam.ac.uk    std::string path;
62111812Sbaz21@cam.ac.uk
62211812Sbaz21@cam.ac.uk    if (!tc->getMemProxy().tryReadString(path,
62311812Sbaz21@cam.ac.uk                process->getSyscallArg(tc, index)))
62411812Sbaz21@cam.ac.uk        return -EFAULT;
62511812Sbaz21@cam.ac.uk
62611759Sbrandon.potter@amd.com    if (path == "/dev/sysdev0") {
62711759Sbrandon.potter@amd.com        // This is a memory-mapped high-resolution timer device on Alpha.
62811812Sbaz21@cam.ac.uk        // We don't support it, so just punt.
62911812Sbaz21@cam.ac.uk        warn("Ignoring open(%s, ...)\n", path);
63011759Sbrandon.potter@amd.com        return -ENOENT;
63111812Sbaz21@cam.ac.uk    }
63211812Sbaz21@cam.ac.uk
63311812Sbaz21@cam.ac.uk    int tgtFlags = process->getSyscallArg(tc, index);
63411812Sbaz21@cam.ac.uk    int mode = process->getSyscallArg(tc, index);
63511812Sbaz21@cam.ac.uk    int hostFlags = 0;
63611812Sbaz21@cam.ac.uk
63711812Sbaz21@cam.ac.uk    // translate open flags
63811759Sbrandon.potter@amd.com    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
63911759Sbrandon.potter@amd.com        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
64011759Sbrandon.potter@amd.com            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
64111759Sbrandon.potter@amd.com            hostFlags |= OS::openFlagTable[i].hostFlag;
642378SN/A        }
643378SN/A    }
6449141Smarc.orr@gmail.com
6459141Smarc.orr@gmail.com    // any target flags left?
646360SN/A    if (tgtFlags != 0)
6471450SN/A        warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
64811856Sbrandon.potter@amd.com
649360SN/A#ifdef __CYGWIN32__
6506701Sgblack@eecs.umich.edu    hostFlags |= O_BINARY;
65111856Sbrandon.potter@amd.com#endif
65211856Sbrandon.potter@amd.com
653360SN/A    // Adjust path for current working directory
65410930Sbrandon.potter@amd.com    path = process->fullPath(path);
655360SN/A
65611856Sbrandon.potter@amd.com    DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
65711856Sbrandon.potter@amd.com
65810496Ssteve.reinhardt@amd.com    int fd;
65911856Sbrandon.potter@amd.com    int local_errno;
66011856Sbrandon.potter@amd.com    if (startswith(path, "/proc/") || startswith(path, "/system/") ||
6611458SN/A        startswith(path, "/platform/") || startswith(path, "/sys/")) {
662360SN/A        // It's a proc/sys entry and requires special handling
66311856Sbrandon.potter@amd.com        fd = OS::openSpecialFile(path, process, tc);
66411856Sbrandon.potter@amd.com        local_errno = ENOENT;
66511856Sbrandon.potter@amd.com     } else {
66611856Sbrandon.potter@amd.com        // open the file
66711856Sbrandon.potter@amd.com        fd = open(path.c_str(), hostFlags, mode);
66811856Sbrandon.potter@amd.com        local_errno = errno;
66911856Sbrandon.potter@amd.com     }
67011856Sbrandon.potter@amd.com
67110496Ssteve.reinhardt@amd.com    if (fd == -1)
67211856Sbrandon.potter@amd.com        return -local_errno;
67311856Sbrandon.potter@amd.com
67411856Sbrandon.potter@amd.com    return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false);
67511856Sbrandon.potter@amd.com}
67611856Sbrandon.potter@amd.com
67710930Sbrandon.potter@amd.com/// Target open() handler.
6789141Smarc.orr@gmail.comtemplate <class OS>
679360SN/ASyscallReturn
680360SN/AopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
681360SN/A         ThreadContext *tc)
68211907SBrandon.Potter@amd.com{
68311907SBrandon.Potter@amd.com    return openFunc<OS>(desc, callnum, process, tc, 0);
68411907SBrandon.Potter@amd.com}
685360SN/A
68611907SBrandon.Potter@amd.com/// Target openat() handler.
68711907SBrandon.Potter@amd.comtemplate <class OS>
68811907SBrandon.Potter@amd.comSyscallReturn
68911907SBrandon.Potter@amd.comopenatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
69011907SBrandon.Potter@amd.com         ThreadContext *tc)
69111907SBrandon.Potter@amd.com{
69211907SBrandon.Potter@amd.com    int index = 0;
69311907SBrandon.Potter@amd.com    int dirfd = process->getSyscallArg(tc, index);
69411907SBrandon.Potter@amd.com    if (dirfd != OS::TGT_AT_FDCWD)
69511907SBrandon.Potter@amd.com        warn("openat: first argument not AT_FDCWD; unlikely to work");
69611907SBrandon.Potter@amd.com    return openFunc<OS>(desc, callnum, process, tc, 1);
69711907SBrandon.Potter@amd.com}
69811907SBrandon.Potter@amd.com
69911907SBrandon.Potter@amd.com/// Target sysinfo() handler.
700360SN/Atemplate <class OS>
70111907SBrandon.Potter@amd.comSyscallReturn
7021458SN/AsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
703360SN/A         ThreadContext *tc)
70411907SBrandon.Potter@amd.com{
70511907SBrandon.Potter@amd.com
70611907SBrandon.Potter@amd.com    int index = 0;
70711907SBrandon.Potter@amd.com    TypedBufferArg<typename OS::tgt_sysinfo>
70811907SBrandon.Potter@amd.com        sysinfo(process->getSyscallArg(tc, index));
70911907SBrandon.Potter@amd.com
71011907SBrandon.Potter@amd.com    sysinfo->uptime=seconds_since_epoch;
71111907SBrandon.Potter@amd.com    sysinfo->totalram=process->system->memSize();
71211907SBrandon.Potter@amd.com
71311907SBrandon.Potter@amd.com    sysinfo.copyOut(tc->getMemProxy());
714360SN/A
71511907SBrandon.Potter@amd.com    return 0;
71611907SBrandon.Potter@amd.com}
71711907SBrandon.Potter@amd.com
718360SN/A/// Target chmod() handler.
719360SN/Atemplate <class OS>
72011907SBrandon.Potter@amd.comSyscallReturn
72111907SBrandon.Potter@amd.comchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
72211907SBrandon.Potter@amd.com          ThreadContext *tc)
72311907SBrandon.Potter@amd.com{
724360SN/A    std::string path;
72511907SBrandon.Potter@amd.com
726360SN/A    int index = 0;
727360SN/A    if (!tc->getMemProxy().tryReadString(path,
72811907SBrandon.Potter@amd.com                process->getSyscallArg(tc, index))) {
7293669Sbinkertn@umich.edu        return -EFAULT;
73011907SBrandon.Potter@amd.com    }
73111907SBrandon.Potter@amd.com
73211907SBrandon.Potter@amd.com    uint32_t mode = process->getSyscallArg(tc, index);
73311907SBrandon.Potter@amd.com    mode_t hostMode = 0;
73411907SBrandon.Potter@amd.com
73511907SBrandon.Potter@amd.com    // XXX translate mode flags via OS::something???
73611907SBrandon.Potter@amd.com    hostMode = mode;
73711907SBrandon.Potter@amd.com
73811907SBrandon.Potter@amd.com    // Adjust path for current working directory
73911907SBrandon.Potter@amd.com    path = process->fullPath(path);
74011907SBrandon.Potter@amd.com
74111907SBrandon.Potter@amd.com    // do the chmod
74211907SBrandon.Potter@amd.com    int result = chmod(path.c_str(), hostMode);
74311907SBrandon.Potter@amd.com    if (result < 0)
74411907SBrandon.Potter@amd.com        return -errno;
74511907SBrandon.Potter@amd.com
74611907SBrandon.Potter@amd.com    return 0;
74711907SBrandon.Potter@amd.com}
74811907SBrandon.Potter@amd.com
74913371Sciro.santilli@arm.com
75011907SBrandon.Potter@amd.com/// Target fchmod() handler.
7511706SN/Atemplate <class OS>
75211907SBrandon.Potter@amd.comSyscallReturn
75311907SBrandon.Potter@amd.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
75411907SBrandon.Potter@amd.com           ThreadContext *tc)
75511907SBrandon.Potter@amd.com{
75611907SBrandon.Potter@amd.com    int index = 0;
75711907SBrandon.Potter@amd.com    int fd = process->getSyscallArg(tc, index);
75810496Ssteve.reinhardt@amd.com    if (fd < 0 || process->sim_fd(fd) < 0) {
75910496Ssteve.reinhardt@amd.com        // doesn't map to any simulator fd: not a valid target fd
76011907SBrandon.Potter@amd.com        return -EBADF;
76111907SBrandon.Potter@amd.com    }
76211907SBrandon.Potter@amd.com
76311907SBrandon.Potter@amd.com    uint32_t mode = process->getSyscallArg(tc, index);
76411907SBrandon.Potter@amd.com    mode_t hostMode = 0;
76511907SBrandon.Potter@amd.com
76610496Ssteve.reinhardt@amd.com    // XXX translate mode flags via OS::someting???
76711907SBrandon.Potter@amd.com    hostMode = mode;
76811907SBrandon.Potter@amd.com
76911907SBrandon.Potter@amd.com    // do the fchmod
77011907SBrandon.Potter@amd.com    int result = fchmod(process->sim_fd(fd), hostMode);
77110496Ssteve.reinhardt@amd.com    if (result < 0)
77210496Ssteve.reinhardt@amd.com        return -errno;
77311907SBrandon.Potter@amd.com
77411907SBrandon.Potter@amd.com    return 0;
77511907SBrandon.Potter@amd.com}
77611907SBrandon.Potter@amd.com
77711907SBrandon.Potter@amd.com/// Target mremap() handler.
77811907SBrandon.Potter@amd.comtemplate <class OS>
77911907SBrandon.Potter@amd.comSyscallReturn
78011907SBrandon.Potter@amd.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
78111907SBrandon.Potter@amd.com{
78211907SBrandon.Potter@amd.com    int index = 0;
78311907SBrandon.Potter@amd.com    Addr start = process->getSyscallArg(tc, index);
78411907SBrandon.Potter@amd.com    uint64_t old_length = process->getSyscallArg(tc, index);
78511907SBrandon.Potter@amd.com    uint64_t new_length = process->getSyscallArg(tc, index);
78611907SBrandon.Potter@amd.com    uint64_t flags = process->getSyscallArg(tc, index);
78711907SBrandon.Potter@amd.com    uint64_t provided_address = 0;
78811907SBrandon.Potter@amd.com    bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
78911907SBrandon.Potter@amd.com
79011907SBrandon.Potter@amd.com    if (use_provided_address)
79111907SBrandon.Potter@amd.com        provided_address = process->getSyscallArg(tc, index);
79211907SBrandon.Potter@amd.com
79311907SBrandon.Potter@amd.com    if ((start % TheISA::VMPageSize != 0) ||
79411907SBrandon.Potter@amd.com        (new_length % TheISA::VMPageSize != 0) ||
79511907SBrandon.Potter@amd.com        (provided_address % TheISA::VMPageSize != 0)) {
79611907SBrandon.Potter@amd.com        warn("mremap failing: arguments not page aligned");
79711907SBrandon.Potter@amd.com        return -EINVAL;
798360SN/A    }
79911907SBrandon.Potter@amd.com
80011907SBrandon.Potter@amd.com    if (new_length > old_length) {
80111907SBrandon.Potter@amd.com        if ((start + old_length) == process->mmap_end &&
80211907SBrandon.Potter@amd.com            (!use_provided_address || provided_address == start)) {
80311907SBrandon.Potter@amd.com            uint64_t diff = new_length - old_length;
80411907SBrandon.Potter@amd.com            process->allocateMem(process->mmap_end, diff);
80511907SBrandon.Potter@amd.com            process->mmap_end += diff;
80611907SBrandon.Potter@amd.com            return start;
80711907SBrandon.Potter@amd.com        } else {
80811907SBrandon.Potter@amd.com            if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
80911907SBrandon.Potter@amd.com                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
81011907SBrandon.Potter@amd.com                return -ENOMEM;
81111907SBrandon.Potter@amd.com            } else {
812360SN/A                uint64_t new_start = use_provided_address ?
813360SN/A                    provided_address : process->mmap_end;
81410027SChris.Adeniyi-Jones@arm.com                process->pTable->remap(start, old_length, new_start);
81510027SChris.Adeniyi-Jones@arm.com                warn("mremapping to new vaddr %08p-%08p, adding %d\n",
81610027SChris.Adeniyi-Jones@arm.com                     new_start, new_start + new_length,
81711851Sbrandon.potter@amd.com                     new_length - old_length);
81810027SChris.Adeniyi-Jones@arm.com                // add on the remaining unallocated pages
81910027SChris.Adeniyi-Jones@arm.com                process->allocateMem(new_start + old_length,
82011907SBrandon.Potter@amd.com                                     new_length - old_length,
82110027SChris.Adeniyi-Jones@arm.com                                     use_provided_address /* clobber */);
82210027SChris.Adeniyi-Jones@arm.com                if (!use_provided_address)
82310027SChris.Adeniyi-Jones@arm.com                    process->mmap_end += new_length;
82410027SChris.Adeniyi-Jones@arm.com                if (use_provided_address &&
82510027SChris.Adeniyi-Jones@arm.com                    new_start + new_length > process->mmap_end) {
82611851Sbrandon.potter@amd.com                    // something fishy going on here, at least notify the user
82711851Sbrandon.potter@amd.com                    // @todo: increase mmap_end?
82810027SChris.Adeniyi-Jones@arm.com                    warn("mmap region limit exceeded with MREMAP_FIXED\n");
82911907SBrandon.Potter@amd.com                }
83010027SChris.Adeniyi-Jones@arm.com                warn("returning %08p as start\n", new_start);
83110027SChris.Adeniyi-Jones@arm.com                return new_start;
83210633Smichaelupton@gmail.com            }
83310633Smichaelupton@gmail.com        }
83410633Smichaelupton@gmail.com    } else {
83511851Sbrandon.potter@amd.com        if (use_provided_address && provided_address != start)
83610633Smichaelupton@gmail.com            process->pTable->remap(start, new_length, provided_address);
83710633Smichaelupton@gmail.com        process->pTable->unmap(start + new_length, old_length - new_length);
83810633Smichaelupton@gmail.com        return use_provided_address ? provided_address : start;
83910633Smichaelupton@gmail.com    }
84010633Smichaelupton@gmail.com}
84110633Smichaelupton@gmail.com
84210633Smichaelupton@gmail.com/// Target stat() handler.
84310633Smichaelupton@gmail.comtemplate <class OS>
84410633Smichaelupton@gmail.comSyscallReturn
84510633Smichaelupton@gmail.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
84610203SAli.Saidi@ARM.com         ThreadContext *tc)
84710203SAli.Saidi@ARM.com{
84810203SAli.Saidi@ARM.com    std::string path;
84911851Sbrandon.potter@amd.com
85011851Sbrandon.potter@amd.com    int index = 0;
85110203SAli.Saidi@ARM.com    if (!tc->getMemProxy().tryReadString(path,
85210203SAli.Saidi@ARM.com                process->getSyscallArg(tc, index))) {
85310203SAli.Saidi@ARM.com        return -EFAULT;
85410203SAli.Saidi@ARM.com    }
85510203SAli.Saidi@ARM.com    Addr bufPtr = process->getSyscallArg(tc, index);
85610203SAli.Saidi@ARM.com
85710203SAli.Saidi@ARM.com    // Adjust path for current working directory
85810203SAli.Saidi@ARM.com    path = process->fullPath(path);
85910203SAli.Saidi@ARM.com
86010203SAli.Saidi@ARM.com    struct stat hostBuf;
86110203SAli.Saidi@ARM.com    int result = stat(path.c_str(), &hostBuf);
86211851Sbrandon.potter@amd.com
86311851Sbrandon.potter@amd.com    if (result < 0)
86410203SAli.Saidi@ARM.com        return -errno;
86510203SAli.Saidi@ARM.com
86610203SAli.Saidi@ARM.com    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
86710203SAli.Saidi@ARM.com
86810203SAli.Saidi@ARM.com    return 0;
86910203SAli.Saidi@ARM.com}
87010203SAli.Saidi@ARM.com
87110203SAli.Saidi@ARM.com
87210850SGiacomo.Gabrielli@arm.com/// Target stat64() handler.
87310850SGiacomo.Gabrielli@arm.comtemplate <class OS>
87410850SGiacomo.Gabrielli@arm.comSyscallReturn
87511851Sbrandon.potter@amd.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
87610850SGiacomo.Gabrielli@arm.com           ThreadContext *tc)
87710850SGiacomo.Gabrielli@arm.com{
87810850SGiacomo.Gabrielli@arm.com    std::string path;
87910850SGiacomo.Gabrielli@arm.com
88010850SGiacomo.Gabrielli@arm.com    int index = 0;
88110850SGiacomo.Gabrielli@arm.com    if (!tc->getMemProxy().tryReadString(path,
88210850SGiacomo.Gabrielli@arm.com                process->getSyscallArg(tc, index)))
88310850SGiacomo.Gabrielli@arm.com        return -EFAULT;
88410850SGiacomo.Gabrielli@arm.com    Addr bufPtr = process->getSyscallArg(tc, index);
88510850SGiacomo.Gabrielli@arm.com
88610850SGiacomo.Gabrielli@arm.com    // Adjust path for current working directory
88710850SGiacomo.Gabrielli@arm.com    path = process->fullPath(path);
88810850SGiacomo.Gabrielli@arm.com
88910850SGiacomo.Gabrielli@arm.com#if NO_STAT64
89010850SGiacomo.Gabrielli@arm.com    struct stat  hostBuf;
89110850SGiacomo.Gabrielli@arm.com    int result = stat(path.c_str(), &hostBuf);
89210850SGiacomo.Gabrielli@arm.com#else
89310850SGiacomo.Gabrielli@arm.com    struct stat64 hostBuf;
89410850SGiacomo.Gabrielli@arm.com    int result = stat64(path.c_str(), &hostBuf);
89510850SGiacomo.Gabrielli@arm.com#endif
89610850SGiacomo.Gabrielli@arm.com
89710850SGiacomo.Gabrielli@arm.com    if (result < 0)
89810850SGiacomo.Gabrielli@arm.com        return -errno;
89910850SGiacomo.Gabrielli@arm.com
90010850SGiacomo.Gabrielli@arm.com    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
90110850SGiacomo.Gabrielli@arm.com
90210850SGiacomo.Gabrielli@arm.com    return 0;
90310850SGiacomo.Gabrielli@arm.com}
90410850SGiacomo.Gabrielli@arm.com
90510850SGiacomo.Gabrielli@arm.com
90610850SGiacomo.Gabrielli@arm.com/// Target fstatat64() handler.
90710850SGiacomo.Gabrielli@arm.comtemplate <class OS>
9086640Svince@csl.cornell.eduSyscallReturn
9096640Svince@csl.cornell.edufstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
9106640Svince@csl.cornell.edu              ThreadContext *tc)
91111851Sbrandon.potter@amd.com{
91211851Sbrandon.potter@amd.com    int index = 0;
9136640Svince@csl.cornell.edu    int dirfd = process->getSyscallArg(tc, index);
9146640Svince@csl.cornell.edu    if (dirfd != OS::TGT_AT_FDCWD)
9156701Sgblack@eecs.umich.edu        warn("openat: first argument not AT_FDCWD; unlikely to work");
9166701Sgblack@eecs.umich.edu
91710793Sbrandon.potter@amd.com    std::string path;
9186640Svince@csl.cornell.edu    if (!tc->getMemProxy().tryReadString(path,
91911758Sbrandon.potter@amd.com                process->getSyscallArg(tc, index)))
92011758Sbrandon.potter@amd.com        return -EFAULT;
92111758Sbrandon.potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
9226640Svince@csl.cornell.edu
9238706Sandreas.hansson@arm.com    // Adjust path for current working directory
9246640Svince@csl.cornell.edu    path = process->fullPath(path);
9256701Sgblack@eecs.umich.edu
9266640Svince@csl.cornell.edu#if NO_STAT64
927360SN/A    struct stat  hostBuf;
9281999SN/A    int result = stat(path.c_str(), &hostBuf);
9291999SN/A#else
9301999SN/A    struct stat64 hostBuf;
93111851Sbrandon.potter@amd.com    int result = stat64(path.c_str(), &hostBuf);
9322680Sktlim@umich.edu#endif
9331999SN/A
9341999SN/A    if (result < 0)
9351999SN/A        return -errno;
9366701Sgblack@eecs.umich.edu
9378852Sandreas.hansson@arm.com    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
9386701Sgblack@eecs.umich.edu
9391999SN/A    return 0;
9406701Sgblack@eecs.umich.edu}
9411999SN/A
9426701Sgblack@eecs.umich.edu
9431999SN/A/// Target fstat64() handler.
9441999SN/Atemplate <class OS>
9451999SN/ASyscallReturn
9461999SN/Afstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
9471999SN/A            ThreadContext *tc)
9483669Sbinkertn@umich.edu{
9493669Sbinkertn@umich.edu    int index = 0;
9503669Sbinkertn@umich.edu    int fd = process->getSyscallArg(tc, index);
9511999SN/A    Addr bufPtr = process->getSyscallArg(tc, index);
9521999SN/A    if (fd < 0 || process->sim_fd(fd) < 0) {
9531999SN/A        // doesn't map to any simulator fd: not a valid target fd
9542218SN/A        return -EBADF;
9551999SN/A    }
9561999SN/A
9571999SN/A#if NO_STAT64
9581999SN/A    struct stat  hostBuf;
95913570Sbrandon.potter@amd.com    int result = fstat(process->sim_fd(fd), &hostBuf);
96013570Sbrandon.potter@amd.com#else
96113570Sbrandon.potter@amd.com    struct stat64  hostBuf;
96213570Sbrandon.potter@amd.com    int result = fstat64(process->sim_fd(fd), &hostBuf);
96313570Sbrandon.potter@amd.com#endif
96413570Sbrandon.potter@amd.com
96513570Sbrandon.potter@amd.com    if (result < 0)
96613570Sbrandon.potter@amd.com        return -errno;
96713570Sbrandon.potter@amd.com
96813570Sbrandon.potter@amd.com    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
96913570Sbrandon.potter@amd.com
97013570Sbrandon.potter@amd.com    return 0;
97113570Sbrandon.potter@amd.com}
97213570Sbrandon.potter@amd.com
97313570Sbrandon.potter@amd.com
97413570Sbrandon.potter@amd.com/// Target lstat() handler.
97513570Sbrandon.potter@amd.comtemplate <class OS>
97613570Sbrandon.potter@amd.comSyscallReturn
97713570Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
97813570Sbrandon.potter@amd.com          ThreadContext *tc)
97913570Sbrandon.potter@amd.com{
98013570Sbrandon.potter@amd.com    std::string path;
98113570Sbrandon.potter@amd.com
98213570Sbrandon.potter@amd.com    int index = 0;
98313570Sbrandon.potter@amd.com    if (!tc->getMemProxy().tryReadString(path,
98413570Sbrandon.potter@amd.com                process->getSyscallArg(tc, index))) {
98513570Sbrandon.potter@amd.com        return -EFAULT;
98613570Sbrandon.potter@amd.com    }
98713570Sbrandon.potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
98813570Sbrandon.potter@amd.com
98913570Sbrandon.potter@amd.com    // Adjust path for current working directory
99013570Sbrandon.potter@amd.com    path = process->fullPath(path);
99113570Sbrandon.potter@amd.com
99213570Sbrandon.potter@amd.com    struct stat hostBuf;
99313570Sbrandon.potter@amd.com    int result = lstat(path.c_str(), &hostBuf);
99413570Sbrandon.potter@amd.com
99513570Sbrandon.potter@amd.com    if (result < 0)
99613570Sbrandon.potter@amd.com        return -errno;
99713570Sbrandon.potter@amd.com
99813570Sbrandon.potter@amd.com    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
99913570Sbrandon.potter@amd.com
100013570Sbrandon.potter@amd.com    return 0;
100113570Sbrandon.potter@amd.com}
100213570Sbrandon.potter@amd.com
100313570Sbrandon.potter@amd.com/// Target lstat64() handler.
100413570Sbrandon.potter@amd.comtemplate <class OS>
100513570Sbrandon.potter@amd.comSyscallReturn
100613570Sbrandon.potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
100713570Sbrandon.potter@amd.com            ThreadContext *tc)
100813570Sbrandon.potter@amd.com{
100913570Sbrandon.potter@amd.com    std::string path;
101013570Sbrandon.potter@amd.com
101113570Sbrandon.potter@amd.com    int index = 0;
101213570Sbrandon.potter@amd.com    if (!tc->getMemProxy().tryReadString(path,
101313570Sbrandon.potter@amd.com                process->getSyscallArg(tc, index))) {
101413570Sbrandon.potter@amd.com        return -EFAULT;
101513570Sbrandon.potter@amd.com    }
101613570Sbrandon.potter@amd.com    Addr bufPtr = process->getSyscallArg(tc, index);
101713570Sbrandon.potter@amd.com
101813570Sbrandon.potter@amd.com    // Adjust path for current working directory
101913570Sbrandon.potter@amd.com    path = process->fullPath(path);
102013570Sbrandon.potter@amd.com
102113570Sbrandon.potter@amd.com#if NO_STAT64
102213570Sbrandon.potter@amd.com    struct stat hostBuf;
102313570Sbrandon.potter@amd.com    int result = lstat(path.c_str(), &hostBuf);
102413570Sbrandon.potter@amd.com#else
102513570Sbrandon.potter@amd.com    struct stat64 hostBuf;
102613570Sbrandon.potter@amd.com    int result = lstat64(path.c_str(), &hostBuf);
102713570Sbrandon.potter@amd.com#endif
102813570Sbrandon.potter@amd.com
102913570Sbrandon.potter@amd.com    if (result < 0)
103013570Sbrandon.potter@amd.com        return -errno;
103113570Sbrandon.potter@amd.com
103213570Sbrandon.potter@amd.com    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
10331999SN/A
10341999SN/A    return 0;
10351999SN/A}
10361999SN/A
103711856Sbrandon.potter@amd.com/// Target fstat() handler.
10381999SN/Atemplate <class OS>
10396701Sgblack@eecs.umich.eduSyscallReturn
104011856Sbrandon.potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
104111856Sbrandon.potter@amd.com          ThreadContext *tc)
104210931Sbrandon.potter@amd.com{
104311856Sbrandon.potter@amd.com    int index = 0;
104411856Sbrandon.potter@amd.com    int fd = process->sim_fd(process->getSyscallArg(tc, index));
10451999SN/A    Addr bufPtr = process->getSyscallArg(tc, index);
104611856Sbrandon.potter@amd.com
10471999SN/A    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
104811856Sbrandon.potter@amd.com
10491999SN/A    if (fd < 0)
105011856Sbrandon.potter@amd.com        return -EBADF;
10511999SN/A
105211856Sbrandon.potter@amd.com    struct stat hostBuf;
10531999SN/A    int result = fstat(fd, &hostBuf);
10541999SN/A
10555877Shsul@eecs.umich.edu    if (result < 0)
10565877Shsul@eecs.umich.edu        return -errno;
10575877Shsul@eecs.umich.edu
105811851Sbrandon.potter@amd.com    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
10595877Shsul@eecs.umich.edu
10606701Sgblack@eecs.umich.edu    return 0;
10616701Sgblack@eecs.umich.edu}
10626701Sgblack@eecs.umich.edu
10636701Sgblack@eecs.umich.edu
10646701Sgblack@eecs.umich.edu/// Target statfs() handler.
106510027SChris.Adeniyi-Jones@arm.comtemplate <class OS>
106610027SChris.Adeniyi-Jones@arm.comSyscallReturn
106710027SChris.Adeniyi-Jones@arm.comstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
106810027SChris.Adeniyi-Jones@arm.com           ThreadContext *tc)
106910027SChris.Adeniyi-Jones@arm.com{
10705877Shsul@eecs.umich.edu    std::string path;
107110318Sandreas.hansson@arm.com
107210318Sandreas.hansson@arm.com    int index = 0;
10735877Shsul@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
10745877Shsul@eecs.umich.edu                process->getSyscallArg(tc, index))) {
10755877Shsul@eecs.umich.edu        return -EFAULT;
10765877Shsul@eecs.umich.edu    }
107710486Stjablin@gmail.com    Addr bufPtr = process->getSyscallArg(tc, index);
107810486Stjablin@gmail.com
10795877Shsul@eecs.umich.edu    // Adjust path for current working directory
108011905SBrandon.Potter@amd.com    path = process->fullPath(path);
108111905SBrandon.Potter@amd.com
108211905SBrandon.Potter@amd.com    struct statfs hostBuf;
108311905SBrandon.Potter@amd.com    int result = statfs(path.c_str(), &hostBuf);
108410027SChris.Adeniyi-Jones@arm.com
108512206Srico.amslinger@informatik.uni-augsburg.de    if (result < 0)
108612206Srico.amslinger@informatik.uni-augsburg.de        return -errno;
10875877Shsul@eecs.umich.edu
108811905SBrandon.Potter@amd.com    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
108911905SBrandon.Potter@amd.com
10905877Shsul@eecs.umich.edu    return 0;
10915877Shsul@eecs.umich.edu}
109210027SChris.Adeniyi-Jones@arm.com
10935877Shsul@eecs.umich.edu
10945877Shsul@eecs.umich.edu/// Target fstatfs() handler.
10955877Shsul@eecs.umich.edutemplate <class OS>
109612206Srico.amslinger@informatik.uni-augsburg.deSyscallReturn
109712206Srico.amslinger@informatik.uni-augsburg.defstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
109812206Srico.amslinger@informatik.uni-augsburg.de            ThreadContext *tc)
109912206Srico.amslinger@informatik.uni-augsburg.de{
110012206Srico.amslinger@informatik.uni-augsburg.de    int index = 0;
110112206Srico.amslinger@informatik.uni-augsburg.de    int fd = process->sim_fd(process->getSyscallArg(tc, index));
110212206Srico.amslinger@informatik.uni-augsburg.de    Addr bufPtr = process->getSyscallArg(tc, index);
110312206Srico.amslinger@informatik.uni-augsburg.de
110412206Srico.amslinger@informatik.uni-augsburg.de    if (fd < 0)
110510027SChris.Adeniyi-Jones@arm.com        return -EBADF;
110610027SChris.Adeniyi-Jones@arm.com
110710027SChris.Adeniyi-Jones@arm.com    struct statfs hostBuf;
110810027SChris.Adeniyi-Jones@arm.com    int result = fstatfs(fd, &hostBuf);
11095877Shsul@eecs.umich.edu
111010027SChris.Adeniyi-Jones@arm.com    if (result < 0)
111110027SChris.Adeniyi-Jones@arm.com        return -errno;
111210027SChris.Adeniyi-Jones@arm.com
111310027SChris.Adeniyi-Jones@arm.com    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
111412206Srico.amslinger@informatik.uni-augsburg.de
111512206Srico.amslinger@informatik.uni-augsburg.de    return 0;
111612206Srico.amslinger@informatik.uni-augsburg.de}
111712206Srico.amslinger@informatik.uni-augsburg.de
111810027SChris.Adeniyi-Jones@arm.com
111910027SChris.Adeniyi-Jones@arm.com/// Target writev() handler.
112010027SChris.Adeniyi-Jones@arm.comtemplate <class OS>
112110027SChris.Adeniyi-Jones@arm.comSyscallReturn
112210027SChris.Adeniyi-Jones@arm.comwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
112310027SChris.Adeniyi-Jones@arm.com           ThreadContext *tc)
11245877Shsul@eecs.umich.edu{
11255877Shsul@eecs.umich.edu    int index = 0;
11265877Shsul@eecs.umich.edu    int fd = process->getSyscallArg(tc, index);
112710027SChris.Adeniyi-Jones@arm.com    if (fd < 0 || process->sim_fd(fd) < 0) {
112810027SChris.Adeniyi-Jones@arm.com        // doesn't map to any simulator fd: not a valid target fd
11298601Ssteve.reinhardt@amd.com        return -EBADF;
113010027SChris.Adeniyi-Jones@arm.com    }
11315877Shsul@eecs.umich.edu
11325877Shsul@eecs.umich.edu    SETranslatingPortProxy &p = tc->getMemProxy();
11331999SN/A    uint64_t tiov_base = process->getSyscallArg(tc, index);
1134378SN/A    size_t count = process->getSyscallArg(tc, index);
1135360SN/A    struct iovec hiov[count];
11361450SN/A    for (size_t i = 0; i < count; ++i) {
113711851Sbrandon.potter@amd.com        typename OS::tgt_iovec tiov;
11382680Sktlim@umich.edu
1139360SN/A        p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1140360SN/A                   (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
1141360SN/A        hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
11426701Sgblack@eecs.umich.edu        hiov[i].iov_base = new char [hiov[i].iov_len];
11438852Sandreas.hansson@arm.com        p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
11446701Sgblack@eecs.umich.edu                   hiov[i].iov_len);
11456701Sgblack@eecs.umich.edu    }
11466701Sgblack@eecs.umich.edu
11476701Sgblack@eecs.umich.edu    int result = writev(process->sim_fd(fd), hiov, count);
1148360SN/A
11493669Sbinkertn@umich.edu    for (size_t i = 0; i < count; ++i)
11503669Sbinkertn@umich.edu        delete [] (char *)hiov[i].iov_base;
11513669Sbinkertn@umich.edu
1152360SN/A    if (result < 0)
1153360SN/A        return -errno;
1154360SN/A
1155360SN/A    return 0;
11562218SN/A}
1157360SN/A
11588706Sandreas.hansson@arm.com
1159360SN/A/// Target mmap() handler.
11601458SN/A///
1161360SN/A/// We don't really handle mmap().  If the target is mmaping an
1162360SN/A/// anonymous region or /dev/zero, we can get away with doing basically
1163360SN/A/// nothing (since memory is initialized to zero and the simulator
11645074Ssaidi@eecs.umich.edu/// doesn't really check addresses anyway).
11655074Ssaidi@eecs.umich.edu///
11665074Ssaidi@eecs.umich.edutemplate <class OS>
116711851Sbrandon.potter@amd.comSyscallReturn
11685074Ssaidi@eecs.umich.edummapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
11695074Ssaidi@eecs.umich.edu{
11705074Ssaidi@eecs.umich.edu    int index = 0;
11715074Ssaidi@eecs.umich.edu    Addr start = p->getSyscallArg(tc, index);
11726701Sgblack@eecs.umich.edu    uint64_t length = p->getSyscallArg(tc, index);
11738852Sandreas.hansson@arm.com    index++; // int prot = p->getSyscallArg(tc, index);
11746701Sgblack@eecs.umich.edu    int flags = p->getSyscallArg(tc, index);
11755074Ssaidi@eecs.umich.edu    int tgt_fd = p->getSyscallArg(tc, index);
11766701Sgblack@eecs.umich.edu    // int offset = p->getSyscallArg(tc, index);
11775074Ssaidi@eecs.umich.edu
11785074Ssaidi@eecs.umich.edu    if (length > 0x100000000ULL)
11795074Ssaidi@eecs.umich.edu        warn("mmap length argument %#x is unreasonably large.\n", length);
11805074Ssaidi@eecs.umich.edu
11815208Ssaidi@eecs.umich.edu    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
11825208Ssaidi@eecs.umich.edu        Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd);
11835208Ssaidi@eecs.umich.edu        if (!fd_map || fd_map->fd < 0) {
11845208Ssaidi@eecs.umich.edu            warn("mmap failing: target fd %d is not valid\n", tgt_fd);
11855074Ssaidi@eecs.umich.edu            return -EBADF;
11865074Ssaidi@eecs.umich.edu        }
11875208Ssaidi@eecs.umich.edu
11885074Ssaidi@eecs.umich.edu        if (fd_map->filename != "/dev/zero") {
11895074Ssaidi@eecs.umich.edu            // This is very likely broken, but leave a warning here
11905074Ssaidi@eecs.umich.edu            // (rather than panic) in case /dev/zero is known by
11915074Ssaidi@eecs.umich.edu            // another name on some platform
11928706Sandreas.hansson@arm.com            warn("allowing mmap of file %s; mmap not supported on files"
11935074Ssaidi@eecs.umich.edu                 " other than /dev/zero\n", fd_map->filename);
11945074Ssaidi@eecs.umich.edu        }
11955074Ssaidi@eecs.umich.edu    }
11965074Ssaidi@eecs.umich.edu
11975074Ssaidi@eecs.umich.edu    if ((start  % TheISA::VMPageSize) != 0 ||
119810027SChris.Adeniyi-Jones@arm.com        (length % TheISA::VMPageSize) != 0) {
119910027SChris.Adeniyi-Jones@arm.com        warn("mmap failing: arguments not page-aligned: "
120010027SChris.Adeniyi-Jones@arm.com             "start 0x%x length 0x%x",
120111851Sbrandon.potter@amd.com             start, length);
120210027SChris.Adeniyi-Jones@arm.com        return -EINVAL;
120310027SChris.Adeniyi-Jones@arm.com    }
120410027SChris.Adeniyi-Jones@arm.com
120510027SChris.Adeniyi-Jones@arm.com    // are we ok with clobbering existing mappings?  only set this to
120610027SChris.Adeniyi-Jones@arm.com    // true if the user has been warned.
120710793Sbrandon.potter@amd.com    bool clobber = false;
120810027SChris.Adeniyi-Jones@arm.com
120910027SChris.Adeniyi-Jones@arm.com    // try to use the caller-provided address if there is one
121010027SChris.Adeniyi-Jones@arm.com    bool use_provided_address = (start != 0);
121110027SChris.Adeniyi-Jones@arm.com
121210027SChris.Adeniyi-Jones@arm.com    if (use_provided_address) {
121310027SChris.Adeniyi-Jones@arm.com        // check to see if the desired address is already in use
121410027SChris.Adeniyi-Jones@arm.com        if (!p->pTable->isUnmapped(start, length)) {
121510027SChris.Adeniyi-Jones@arm.com            // there are existing mappings in the desired range
121610027SChris.Adeniyi-Jones@arm.com            // whether we clobber them or not depends on whether the caller
121710027SChris.Adeniyi-Jones@arm.com            // specified MAP_FIXED
121810027SChris.Adeniyi-Jones@arm.com            if (flags & OS::TGT_MAP_FIXED) {
121910027SChris.Adeniyi-Jones@arm.com                // MAP_FIXED specified: clobber existing mappings
122010027SChris.Adeniyi-Jones@arm.com                warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n",
122110027SChris.Adeniyi-Jones@arm.com                     start);
122210027SChris.Adeniyi-Jones@arm.com                clobber = true;
122310027SChris.Adeniyi-Jones@arm.com            } else {
122410027SChris.Adeniyi-Jones@arm.com                // MAP_FIXED not specified: ignore suggested start address
122510027SChris.Adeniyi-Jones@arm.com                warn("mmap: ignoring suggested map address 0x%x\n", start);
122610027SChris.Adeniyi-Jones@arm.com                use_provided_address = false;
122710027SChris.Adeniyi-Jones@arm.com            }
122810027SChris.Adeniyi-Jones@arm.com        }
122910027SChris.Adeniyi-Jones@arm.com    }
123010027SChris.Adeniyi-Jones@arm.com
123110027SChris.Adeniyi-Jones@arm.com    if (!use_provided_address) {
123210027SChris.Adeniyi-Jones@arm.com        // no address provided, or provided address unusable:
123310027SChris.Adeniyi-Jones@arm.com        // pick next address from our "mmap region"
123410027SChris.Adeniyi-Jones@arm.com        if (OS::mmapGrowsDown()) {
12351999SN/A            start = p->mmap_end - length;
12361999SN/A            p->mmap_end = start;
12371999SN/A        } else {
123811856Sbrandon.potter@amd.com            start = p->mmap_end;
12391999SN/A            p->mmap_end += length;
12406701Sgblack@eecs.umich.edu        }
124111856Sbrandon.potter@amd.com    }
124211856Sbrandon.potter@amd.com
124310931Sbrandon.potter@amd.com    p->allocateMem(start, length, clobber);
124411856Sbrandon.potter@amd.com
124511856Sbrandon.potter@amd.com    return start;
12461999SN/A}
124711856Sbrandon.potter@amd.com
12481999SN/A/// Target getrlimit() handler.
12492764Sstever@eecs.umich.edutemplate <class OS>
12502064SN/ASyscallReturn
125110931Sbrandon.potter@amd.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
12522064SN/A        ThreadContext *tc)
12532064SN/A{
125410931Sbrandon.potter@amd.com    int index = 0;
12552064SN/A    unsigned resource = process->getSyscallArg(tc, index);
12561999SN/A    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
12571999SN/A
12582218SN/A    switch (resource) {
12591999SN/A        case OS::TGT_RLIMIT_STACK:
126010931Sbrandon.potter@amd.com            // max stack size in bytes: make up a number (8MB for now)
12611999SN/A            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
12621999SN/A            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
12631999SN/A            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
12641999SN/A            break;
12651999SN/A
1266378SN/A        case OS::TGT_RLIMIT_DATA:
1267360SN/A            // max data segment size in bytes: make up a number
12681450SN/A            rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
126911851Sbrandon.potter@amd.com            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
12702680Sktlim@umich.edu            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
1271360SN/A            break;
1272360SN/A
1273360SN/A        default:
12746701Sgblack@eecs.umich.edu            std::cerr << "getrlimitFunc: unimplemented resource " << resource
12758852Sandreas.hansson@arm.com                << std::endl;
12766701Sgblack@eecs.umich.edu            abort();
12776701Sgblack@eecs.umich.edu            break;
12786701Sgblack@eecs.umich.edu    }
12796701Sgblack@eecs.umich.edu
1280360SN/A    rlp.copyOut(tc->getMemProxy());
12813669Sbinkertn@umich.edu    return 0;
12823669Sbinkertn@umich.edu}
12833669Sbinkertn@umich.edu
1284360SN/A/// Target gettimeofday() handler.
1285360SN/Atemplate <class OS>
1286360SN/ASyscallReturn
1287360SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
12881458SN/A        ThreadContext *tc)
1289360SN/A{
12908706Sandreas.hansson@arm.com    int index = 0;
1291360SN/A    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
12921458SN/A
1293360SN/A    getElapsedTime(tp->tv_sec, tp->tv_usec);
1294360SN/A    tp->tv_sec += seconds_since_epoch;
12951999SN/A    tp->tv_sec = TheISA::htog(tp->tv_sec);
12961999SN/A    tp->tv_usec = TheISA::htog(tp->tv_usec);
12971999SN/A
129811851Sbrandon.potter@amd.com    tp.copyOut(tc->getMemProxy());
12992680Sktlim@umich.edu
13001999SN/A    return 0;
13011999SN/A}
13021999SN/A
13036701Sgblack@eecs.umich.edu
13048852Sandreas.hansson@arm.com/// Target utimes() handler.
13056701Sgblack@eecs.umich.edutemplate <class OS>
13066701Sgblack@eecs.umich.eduSyscallReturn
13076701Sgblack@eecs.umich.eduutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
13086701Sgblack@eecs.umich.edu           ThreadContext *tc)
13091999SN/A{
13103669Sbinkertn@umich.edu    std::string path;
13113669Sbinkertn@umich.edu
13123669Sbinkertn@umich.edu    int index = 0;
13132764Sstever@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
13142064SN/A                process->getSyscallArg(tc, index))) {
13152064SN/A        return -EFAULT;
13162064SN/A    }
13171999SN/A
13181999SN/A    TypedBufferArg<typename OS::timeval [2]>
13192064SN/A        tp(process->getSyscallArg(tc, index));
13201999SN/A    tp.copyIn(tc->getMemProxy());
13211999SN/A
13221999SN/A    struct timeval hostTimeval[2];
13231999SN/A    for (int i = 0; i < 2; ++i)
13248706Sandreas.hansson@arm.com    {
13251999SN/A        hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
13261999SN/A        hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
13271999SN/A    }
13281999SN/A
1329378SN/A    // Adjust path for current working directory
1330360SN/A    path = process->fullPath(path);
13311450SN/A
133211856Sbrandon.potter@amd.com    int result = utimes(path.c_str(), hostTimeval);
1333360SN/A
13346701Sgblack@eecs.umich.edu    if (result < 0)
133511856Sbrandon.potter@amd.com        return -errno;
133611856Sbrandon.potter@amd.com
1337360SN/A    return 0;
133811380Salexandru.dutu@amd.com}
1339360SN/A/// Target getrusage() function.
134011856Sbrandon.potter@amd.comtemplate <class OS>
134111856Sbrandon.potter@amd.comSyscallReturn
13421458SN/AgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
134311856Sbrandon.potter@amd.com              ThreadContext *tc)
1344360SN/A{
1345360SN/A    int index = 0;
134610931Sbrandon.potter@amd.com    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
1347360SN/A    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
1348360SN/A
13491458SN/A    rup->ru_utime.tv_sec = 0;
1350360SN/A    rup->ru_utime.tv_usec = 0;
135110931Sbrandon.potter@amd.com    rup->ru_stime.tv_sec = 0;
13522021SN/A    rup->ru_stime.tv_usec = 0;
13531458SN/A    rup->ru_maxrss = 0;
1354360SN/A    rup->ru_ixrss = 0;
1355360SN/A    rup->ru_idrss = 0;
13561706SN/A    rup->ru_isrss = 0;
13571706SN/A    rup->ru_minflt = 0;
13581706SN/A    rup->ru_majflt = 0;
135911851Sbrandon.potter@amd.com    rup->ru_nswap = 0;
13602680Sktlim@umich.edu    rup->ru_inblock = 0;
13611706SN/A    rup->ru_oublock = 0;
136211799Sbrandon.potter@amd.com    rup->ru_msgsnd = 0;
136311799Sbrandon.potter@amd.com    rup->ru_msgrcv = 0;
136411799Sbrandon.potter@amd.com    rup->ru_nsignals = 0;
13651706SN/A    rup->ru_nvcsw = 0;
13661706SN/A    rup->ru_nivcsw = 0;
13676701Sgblack@eecs.umich.edu
13688852Sandreas.hansson@arm.com    switch (who) {
13696701Sgblack@eecs.umich.edu      case OS::TGT_RUSAGE_SELF:
13706701Sgblack@eecs.umich.edu        getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
13716701Sgblack@eecs.umich.edu        rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
13726701Sgblack@eecs.umich.edu        rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
13731706SN/A        break;
13743669Sbinkertn@umich.edu
13753669Sbinkertn@umich.edu      case OS::TGT_RUSAGE_CHILDREN:
13763669Sbinkertn@umich.edu        // do nothing.  We have no child processes, so they take no time.
13771706SN/A        break;
13781706SN/A
13791706SN/A      default:
13801706SN/A        // don't really handle THREAD or CHILDREN, but just warn and
13812218SN/A        // plow ahead
13821706SN/A        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
138311759Sbrandon.potter@amd.com             who);
138411799Sbrandon.potter@amd.com    }
13851706SN/A
13861706SN/A    rup.copyOut(tc->getMemProxy());
13871706SN/A
138811886Sbrandon.potter@amd.com    return 0;
138911886Sbrandon.potter@amd.com}
139011886Sbrandon.potter@amd.com
139111886Sbrandon.potter@amd.com/// Target times() function.
139211886Sbrandon.potter@amd.comtemplate <class OS>
139312426Sqtt2@cornell.eduSyscallReturn
139413557Sgabeblack@google.comtimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
139513557Sgabeblack@google.com           ThreadContext *tc)
139611886Sbrandon.potter@amd.com{
139712426Sqtt2@cornell.edu    int index = 0;
139813534Sandreas.sandberg@arm.com    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
139912426Sqtt2@cornell.edu
140013534Sandreas.sandberg@arm.com    // Fill in the time structure (in clocks)
140112426Sqtt2@cornell.edu    int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
140212426Sqtt2@cornell.edu    bufp->tms_utime = clocks;
140312426Sqtt2@cornell.edu    bufp->tms_stime = 0;
140413536Sandreas.sandberg@arm.com    bufp->tms_cutime = 0;
140512426Sqtt2@cornell.edu    bufp->tms_cstime = 0;
140612426Sqtt2@cornell.edu
140711886Sbrandon.potter@amd.com    // Convert to host endianness
140813536Sandreas.sandberg@arm.com    bufp->tms_utime = TheISA::htog(bufp->tms_utime);
140912426Sqtt2@cornell.edu
141011886Sbrandon.potter@amd.com    // Write back
141111886Sbrandon.potter@amd.com    bufp.copyOut(tc->getMemProxy());
141211886Sbrandon.potter@amd.com
141311886Sbrandon.potter@amd.com    // Return clock ticks since system boot
141411886Sbrandon.potter@amd.com    return clocks;
141511886Sbrandon.potter@amd.com}
141611886Sbrandon.potter@amd.com
141711886Sbrandon.potter@amd.com/// Target time() function.
141811886Sbrandon.potter@amd.comtemplate <class OS>
141911886Sbrandon.potter@amd.comSyscallReturn
142011886Sbrandon.potter@amd.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
142111886Sbrandon.potter@amd.com           ThreadContext *tc)
142211886Sbrandon.potter@amd.com{
142311886Sbrandon.potter@amd.com    typename OS::time_t sec, usec;
142411886Sbrandon.potter@amd.com    getElapsedTime(sec, usec);
142511886Sbrandon.potter@amd.com    sec += seconds_since_epoch;
142611886Sbrandon.potter@amd.com
142711886Sbrandon.potter@amd.com    int index = 0;
142811886Sbrandon.potter@amd.com    Addr taddr = (Addr)process->getSyscallArg(tc, index);
142911886Sbrandon.potter@amd.com    if(taddr != 0) {
143011886Sbrandon.potter@amd.com        typename OS::time_t t = sec;
143111886Sbrandon.potter@amd.com        t = TheISA::htog(t);
143211886Sbrandon.potter@amd.com        SETranslatingPortProxy &p = tc->getMemProxy();
143311886Sbrandon.potter@amd.com        p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
143411886Sbrandon.potter@amd.com    }
143511886Sbrandon.potter@amd.com    return sec;
143611886Sbrandon.potter@amd.com}
143711886Sbrandon.potter@amd.com
143811886Sbrandon.potter@amd.com
143911886Sbrandon.potter@amd.com#endif // __SIM_SYSCALL_EMUL_HH__
144011886Sbrandon.potter@amd.com