syscall_emul.hh revision 9238
15952Ssaidi@eecs.umich.edu/*
25952Ssaidi@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
35952Ssaidi@eecs.umich.edu * All rights reserved.
45952Ssaidi@eecs.umich.edu *
55952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
75952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145952Ssaidi@eecs.umich.edu * this software without specific prior written permission.
155952Ssaidi@eecs.umich.edu *
165952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185952Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205952Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215952Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255952Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275952Ssaidi@eecs.umich.edu *
285952Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
295952Ssaidi@eecs.umich.edu *          Kevin Lim
305952Ssaidi@eecs.umich.edu */
318229Snate@binkert.org
325952Ssaidi@eecs.umich.edu#ifndef __SIM_SYSCALL_EMUL_HH__
338229Snate@binkert.org#define __SIM_SYSCALL_EMUL_HH__
348229Snate@binkert.org
355952Ssaidi@eecs.umich.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
365952Ssaidi@eecs.umich.edu  defined(__FreeBSD__) || defined(__CYGWIN__) || \
375952Ssaidi@eecs.umich.edu  defined(__NetBSD__))
386658Snate@binkert.org
395952Ssaidi@eecs.umich.edu///
405952Ssaidi@eecs.umich.edu/// @file syscall_emul.hh
415952Ssaidi@eecs.umich.edu///
425952Ssaidi@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target
435952Ssaidi@eecs.umich.edu/// application on the host machine.
445952Ssaidi@eecs.umich.edu
455952Ssaidi@eecs.umich.edu#ifdef __CYGWIN32__
465952Ssaidi@eecs.umich.edu#include <sys/fcntl.h>  // for O_BINARY
475952Ssaidi@eecs.umich.edu#endif
485952Ssaidi@eecs.umich.edu#include <sys/stat.h>
495952Ssaidi@eecs.umich.edu#include <sys/time.h>
505952Ssaidi@eecs.umich.edu#include <sys/uio.h>
515952Ssaidi@eecs.umich.edu#include <fcntl.h>
525952Ssaidi@eecs.umich.edu
535952Ssaidi@eecs.umich.edu#include <cerrno>
545952Ssaidi@eecs.umich.edu#include <string>
555952Ssaidi@eecs.umich.edu
565952Ssaidi@eecs.umich.edu#include "base/chunk_generator.hh"
575952Ssaidi@eecs.umich.edu#include "base/intmath.hh"      // for RoundUp
585952Ssaidi@eecs.umich.edu#include "base/misc.hh"
595952Ssaidi@eecs.umich.edu#include "base/trace.hh"
605952Ssaidi@eecs.umich.edu#include "base/types.hh"
615952Ssaidi@eecs.umich.edu#include "config/the_isa.hh"
625952Ssaidi@eecs.umich.edu#include "cpu/base.hh"
635952Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh"
645952Ssaidi@eecs.umich.edu#include "debug/SyscallVerbose.hh"
655952Ssaidi@eecs.umich.edu#include "mem/page_table.hh"
665952Ssaidi@eecs.umich.edu#include "mem/se_translating_port_proxy.hh"
675952Ssaidi@eecs.umich.edu#include "sim/byteswap.hh"
685952Ssaidi@eecs.umich.edu#include "sim/process.hh"
695952Ssaidi@eecs.umich.edu#include "sim/syscallreturn.hh"
705952Ssaidi@eecs.umich.edu#include "sim/system.hh"
715952Ssaidi@eecs.umich.edu
725952Ssaidi@eecs.umich.edu///
735952Ssaidi@eecs.umich.edu/// System call descriptor.
745952Ssaidi@eecs.umich.edu///
755952Ssaidi@eecs.umich.educlass SyscallDesc {
765952Ssaidi@eecs.umich.edu
775952Ssaidi@eecs.umich.edu  public:
785952Ssaidi@eecs.umich.edu
795952Ssaidi@eecs.umich.edu    /// Typedef for target syscall handler functions.
805952Ssaidi@eecs.umich.edu    typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
815952Ssaidi@eecs.umich.edu                           LiveProcess *, ThreadContext *);
825952Ssaidi@eecs.umich.edu
835952Ssaidi@eecs.umich.edu    const char *name;   //!< Syscall name (e.g., "open").
845952Ssaidi@eecs.umich.edu    FuncPtr funcPtr;    //!< Pointer to emulation function.
855952Ssaidi@eecs.umich.edu    int flags;          //!< Flags (see Flags enum).
865952Ssaidi@eecs.umich.edu
875952Ssaidi@eecs.umich.edu    /// Flag values for controlling syscall behavior.
885952Ssaidi@eecs.umich.edu    enum Flags {
895952Ssaidi@eecs.umich.edu        /// Don't set return regs according to funcPtr return value.
905952Ssaidi@eecs.umich.edu        /// Used for syscalls with non-standard return conventions
915952Ssaidi@eecs.umich.edu        /// that explicitly set the ThreadContext regs (e.g.,
925952Ssaidi@eecs.umich.edu        /// sigreturn).
935952Ssaidi@eecs.umich.edu        SuppressReturnValue = 1
945952Ssaidi@eecs.umich.edu    };
955952Ssaidi@eecs.umich.edu
965952Ssaidi@eecs.umich.edu    /// Constructor.
975952Ssaidi@eecs.umich.edu    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
985952Ssaidi@eecs.umich.edu        : name(_name), funcPtr(_funcPtr), flags(_flags)
995952Ssaidi@eecs.umich.edu    {
1005952Ssaidi@eecs.umich.edu    }
1015952Ssaidi@eecs.umich.edu
1025952Ssaidi@eecs.umich.edu    /// Emulate the syscall.  Public interface for calling through funcPtr.
1035952Ssaidi@eecs.umich.edu    void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
1045952Ssaidi@eecs.umich.edu};
1055952Ssaidi@eecs.umich.edu
1065952Ssaidi@eecs.umich.edu
1075952Ssaidi@eecs.umich.educlass BaseBufferArg {
1085952Ssaidi@eecs.umich.edu
1095952Ssaidi@eecs.umich.edu  public:
1105952Ssaidi@eecs.umich.edu
1115952Ssaidi@eecs.umich.edu    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
1125952Ssaidi@eecs.umich.edu    {
1135952Ssaidi@eecs.umich.edu        bufPtr = new uint8_t[size];
1145952Ssaidi@eecs.umich.edu        // clear out buffer: in case we only partially populate this,
1155952Ssaidi@eecs.umich.edu        // and then do a copyOut(), we want to make sure we don't
1165952Ssaidi@eecs.umich.edu        // introduce any random junk into the simulated address space
1175952Ssaidi@eecs.umich.edu        memset(bufPtr, 0, size);
1185952Ssaidi@eecs.umich.edu    }
1195952Ssaidi@eecs.umich.edu
1205952Ssaidi@eecs.umich.edu    virtual ~BaseBufferArg() { delete [] bufPtr; }
1215952Ssaidi@eecs.umich.edu
1225952Ssaidi@eecs.umich.edu    //
1235952Ssaidi@eecs.umich.edu    // copy data into simulator space (read from target memory)
1245952Ssaidi@eecs.umich.edu    //
1255952Ssaidi@eecs.umich.edu    virtual bool copyIn(SETranslatingPortProxy &memproxy)
1265952Ssaidi@eecs.umich.edu    {
1275952Ssaidi@eecs.umich.edu        memproxy.readBlob(addr, bufPtr, size);
1285952Ssaidi@eecs.umich.edu        return true;    // no EFAULT detection for now
1295952Ssaidi@eecs.umich.edu    }
1305952Ssaidi@eecs.umich.edu
1315952Ssaidi@eecs.umich.edu    //
1325952Ssaidi@eecs.umich.edu    // copy data out of simulator space (write to target memory)
1335952Ssaidi@eecs.umich.edu    //
1345952Ssaidi@eecs.umich.edu    virtual bool copyOut(SETranslatingPortProxy &memproxy)
1355952Ssaidi@eecs.umich.edu    {
1365952Ssaidi@eecs.umich.edu        memproxy.writeBlob(addr, bufPtr, size);
1375952Ssaidi@eecs.umich.edu        return true;    // no EFAULT detection for now
1385952Ssaidi@eecs.umich.edu    }
1395952Ssaidi@eecs.umich.edu
1405952Ssaidi@eecs.umich.edu  protected:
1415952Ssaidi@eecs.umich.edu    Addr addr;
1425952Ssaidi@eecs.umich.edu    int size;
1435952Ssaidi@eecs.umich.edu    uint8_t *bufPtr;
1445952Ssaidi@eecs.umich.edu};
1455952Ssaidi@eecs.umich.edu
1465952Ssaidi@eecs.umich.edu
1475952Ssaidi@eecs.umich.educlass BufferArg : public BaseBufferArg
1485952Ssaidi@eecs.umich.edu{
1495952Ssaidi@eecs.umich.edu  public:
1505952Ssaidi@eecs.umich.edu    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1515952Ssaidi@eecs.umich.edu    void *bufferPtr()   { return bufPtr; }
1525952Ssaidi@eecs.umich.edu};
1535952Ssaidi@eecs.umich.edu
1545952Ssaidi@eecs.umich.edutemplate <class T>
1555952Ssaidi@eecs.umich.educlass TypedBufferArg : public BaseBufferArg
1565952Ssaidi@eecs.umich.edu{
1575952Ssaidi@eecs.umich.edu  public:
1585952Ssaidi@eecs.umich.edu    // user can optionally specify a specific number of bytes to
1595952Ssaidi@eecs.umich.edu    // allocate to deal with those structs that have variable-size
1605952Ssaidi@eecs.umich.edu    // arrays at the end
1615952Ssaidi@eecs.umich.edu    TypedBufferArg(Addr _addr, int _size = sizeof(T))
1625952Ssaidi@eecs.umich.edu        : BaseBufferArg(_addr, _size)
1635952Ssaidi@eecs.umich.edu    { }
1647823Ssteve.reinhardt@amd.com
1655952Ssaidi@eecs.umich.edu    // type case
1665952Ssaidi@eecs.umich.edu    operator T*() { return (T *)bufPtr; }
1675952Ssaidi@eecs.umich.edu
1685952Ssaidi@eecs.umich.edu    // dereference operators
1695952Ssaidi@eecs.umich.edu    T &operator*()       { return *((T *)bufPtr); }
1705952Ssaidi@eecs.umich.edu    T* operator->()      { return (T *)bufPtr; }
1715952Ssaidi@eecs.umich.edu    T &operator[](int i) { return ((T *)bufPtr)[i]; }
1725952Ssaidi@eecs.umich.edu};
1735952Ssaidi@eecs.umich.edu
1745952Ssaidi@eecs.umich.edu//////////////////////////////////////////////////////////////////////
1755952Ssaidi@eecs.umich.edu//
1765952Ssaidi@eecs.umich.edu// The following emulation functions are generic enough that they
1775952Ssaidi@eecs.umich.edu// don't need to be recompiled for different emulated OS's.  They are
1785952Ssaidi@eecs.umich.edu// defined in sim/syscall_emul.cc.
1795952Ssaidi@eecs.umich.edu//
1805952Ssaidi@eecs.umich.edu//////////////////////////////////////////////////////////////////////
1815952Ssaidi@eecs.umich.edu
1825952Ssaidi@eecs.umich.edu
1835952Ssaidi@eecs.umich.edu/// Handler for unimplemented syscalls that we haven't thought about.
1845952Ssaidi@eecs.umich.eduSyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
1855952Ssaidi@eecs.umich.edu                                LiveProcess *p, ThreadContext *tc);
1865952Ssaidi@eecs.umich.edu
1875952Ssaidi@eecs.umich.edu/// Handler for unimplemented syscalls that we never intend to
1885952Ssaidi@eecs.umich.edu/// implement (signal handling, etc.) and should not affect the correct
1895952Ssaidi@eecs.umich.edu/// behavior of the program.  Print a warning only if the appropriate
1905952Ssaidi@eecs.umich.edu/// trace flag is enabled.  Return success to the target program.
1915952Ssaidi@eecs.umich.eduSyscallReturn ignoreFunc(SyscallDesc *desc, int num,
1925952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
1935952Ssaidi@eecs.umich.eduSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num,
1945952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
1955952Ssaidi@eecs.umich.edu
1965952Ssaidi@eecs.umich.edu/// Target exit() handler: terminate current context.
1975952Ssaidi@eecs.umich.eduSyscallReturn exitFunc(SyscallDesc *desc, int num,
1985952Ssaidi@eecs.umich.edu                       LiveProcess *p, ThreadContext *tc);
1995952Ssaidi@eecs.umich.edu
2005952Ssaidi@eecs.umich.edu/// Target exit_group() handler: terminate simulation. (exit all threads)
2015952Ssaidi@eecs.umich.eduSyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
2025952Ssaidi@eecs.umich.edu                       LiveProcess *p, ThreadContext *tc);
2035952Ssaidi@eecs.umich.edu
2045952Ssaidi@eecs.umich.edu/// Target getpagesize() handler.
2055952Ssaidi@eecs.umich.eduSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
2065952Ssaidi@eecs.umich.edu                              LiveProcess *p, ThreadContext *tc);
2075952Ssaidi@eecs.umich.edu
2085952Ssaidi@eecs.umich.edu/// Target brk() handler: set brk address.
2095952Ssaidi@eecs.umich.eduSyscallReturn brkFunc(SyscallDesc *desc, int num,
2105952Ssaidi@eecs.umich.edu                      LiveProcess *p, ThreadContext *tc);
2115952Ssaidi@eecs.umich.edu
2125952Ssaidi@eecs.umich.edu/// Target close() handler.
2135952Ssaidi@eecs.umich.eduSyscallReturn closeFunc(SyscallDesc *desc, int num,
2145952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2155952Ssaidi@eecs.umich.edu
2165952Ssaidi@eecs.umich.edu/// Target read() handler.
2175952Ssaidi@eecs.umich.eduSyscallReturn readFunc(SyscallDesc *desc, int num,
2185952Ssaidi@eecs.umich.edu                       LiveProcess *p, ThreadContext *tc);
2195952Ssaidi@eecs.umich.edu
2205952Ssaidi@eecs.umich.edu/// Target write() handler.
2215952Ssaidi@eecs.umich.eduSyscallReturn writeFunc(SyscallDesc *desc, int num,
2225952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2235952Ssaidi@eecs.umich.edu
2245952Ssaidi@eecs.umich.edu/// Target lseek() handler.
2255952Ssaidi@eecs.umich.eduSyscallReturn lseekFunc(SyscallDesc *desc, int num,
2265952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2275952Ssaidi@eecs.umich.edu
2285952Ssaidi@eecs.umich.edu/// Target _llseek() handler.
2295952Ssaidi@eecs.umich.eduSyscallReturn _llseekFunc(SyscallDesc *desc, int num,
2305952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2315952Ssaidi@eecs.umich.edu
2325952Ssaidi@eecs.umich.edu/// Target munmap() handler.
2335952Ssaidi@eecs.umich.eduSyscallReturn munmapFunc(SyscallDesc *desc, int num,
2345952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2355952Ssaidi@eecs.umich.edu
2365952Ssaidi@eecs.umich.edu/// Target gethostname() handler.
2375952Ssaidi@eecs.umich.eduSyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
2385952Ssaidi@eecs.umich.edu                              LiveProcess *p, ThreadContext *tc);
2395952Ssaidi@eecs.umich.edu
2405952Ssaidi@eecs.umich.edu/// Target getcwd() handler.
2415952Ssaidi@eecs.umich.eduSyscallReturn getcwdFunc(SyscallDesc *desc, int num,
2425952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2435952Ssaidi@eecs.umich.edu
2445952Ssaidi@eecs.umich.edu/// Target unlink() handler.
2455952Ssaidi@eecs.umich.eduSyscallReturn readlinkFunc(SyscallDesc *desc, int num,
2465952Ssaidi@eecs.umich.edu                           LiveProcess *p, ThreadContext *tc);
2475952Ssaidi@eecs.umich.edu
2485952Ssaidi@eecs.umich.edu/// Target unlink() handler.
2495952Ssaidi@eecs.umich.eduSyscallReturn unlinkFunc(SyscallDesc *desc, int num,
2505952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2515952Ssaidi@eecs.umich.edu
2525952Ssaidi@eecs.umich.edu/// Target mkdir() handler.
2535952Ssaidi@eecs.umich.eduSyscallReturn mkdirFunc(SyscallDesc *desc, int num,
2545952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2555952Ssaidi@eecs.umich.edu
2565952Ssaidi@eecs.umich.edu/// Target rename() handler.
2575952Ssaidi@eecs.umich.eduSyscallReturn renameFunc(SyscallDesc *desc, int num,
2585952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2595952Ssaidi@eecs.umich.edu
2605952Ssaidi@eecs.umich.edu
2615952Ssaidi@eecs.umich.edu/// Target truncate() handler.
2625952Ssaidi@eecs.umich.eduSyscallReturn truncateFunc(SyscallDesc *desc, int num,
2635952Ssaidi@eecs.umich.edu                           LiveProcess *p, ThreadContext *tc);
2645952Ssaidi@eecs.umich.edu
2655952Ssaidi@eecs.umich.edu
2665952Ssaidi@eecs.umich.edu/// Target ftruncate() handler.
2675952Ssaidi@eecs.umich.eduSyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
2685952Ssaidi@eecs.umich.edu                            LiveProcess *p, ThreadContext *tc);
2695952Ssaidi@eecs.umich.edu
2705952Ssaidi@eecs.umich.edu
2715952Ssaidi@eecs.umich.edu/// Target truncate64() handler.
2725952Ssaidi@eecs.umich.eduSyscallReturn truncate64Func(SyscallDesc *desc, int num,
2735952Ssaidi@eecs.umich.edu                             LiveProcess *p, ThreadContext *tc);
2745952Ssaidi@eecs.umich.edu
2755952Ssaidi@eecs.umich.edu/// Target ftruncate64() handler.
2767823Ssteve.reinhardt@amd.comSyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
2775952Ssaidi@eecs.umich.edu                              LiveProcess *p, ThreadContext *tc);
2785952Ssaidi@eecs.umich.edu
2795952Ssaidi@eecs.umich.edu
2805952Ssaidi@eecs.umich.edu/// Target umask() handler.
2815952Ssaidi@eecs.umich.eduSyscallReturn umaskFunc(SyscallDesc *desc, int num,
2825952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2835952Ssaidi@eecs.umich.edu
2845952Ssaidi@eecs.umich.edu
2855952Ssaidi@eecs.umich.edu/// Target chown() handler.
2865952Ssaidi@eecs.umich.eduSyscallReturn chownFunc(SyscallDesc *desc, int num,
2875952Ssaidi@eecs.umich.edu                        LiveProcess *p, ThreadContext *tc);
2885952Ssaidi@eecs.umich.edu
2895952Ssaidi@eecs.umich.edu
2905952Ssaidi@eecs.umich.edu/// Target fchown() handler.
2915952Ssaidi@eecs.umich.eduSyscallReturn fchownFunc(SyscallDesc *desc, int num,
2925952Ssaidi@eecs.umich.edu                         LiveProcess *p, ThreadContext *tc);
2935952Ssaidi@eecs.umich.edu
2945952Ssaidi@eecs.umich.edu/// Target dup() handler.
2955952Ssaidi@eecs.umich.eduSyscallReturn dupFunc(SyscallDesc *desc, int num,
2965952Ssaidi@eecs.umich.edu                      LiveProcess *process, ThreadContext *tc);
2975952Ssaidi@eecs.umich.edu
2985952Ssaidi@eecs.umich.edu/// Target fnctl() handler.
2995952Ssaidi@eecs.umich.eduSyscallReturn fcntlFunc(SyscallDesc *desc, int num,
3005952Ssaidi@eecs.umich.edu                        LiveProcess *process, ThreadContext *tc);
3015952Ssaidi@eecs.umich.edu
3025952Ssaidi@eecs.umich.edu/// Target fcntl64() handler.
3035952Ssaidi@eecs.umich.eduSyscallReturn fcntl64Func(SyscallDesc *desc, int num,
3045952Ssaidi@eecs.umich.edu                        LiveProcess *process, ThreadContext *tc);
3055952Ssaidi@eecs.umich.edu
3065952Ssaidi@eecs.umich.edu/// Target setuid() handler.
3075952Ssaidi@eecs.umich.eduSyscallReturn setuidFunc(SyscallDesc *desc, int num,
3085952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3095952Ssaidi@eecs.umich.edu
3105952Ssaidi@eecs.umich.edu/// Target getpid() handler.
3115952Ssaidi@eecs.umich.eduSyscallReturn getpidFunc(SyscallDesc *desc, int num,
3125952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3135952Ssaidi@eecs.umich.edu
3145952Ssaidi@eecs.umich.edu/// Target getuid() handler.
3155952Ssaidi@eecs.umich.eduSyscallReturn getuidFunc(SyscallDesc *desc, int num,
3165952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3175952Ssaidi@eecs.umich.edu
3185952Ssaidi@eecs.umich.edu/// Target getgid() handler.
3197823Ssteve.reinhardt@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num,
3205952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3215952Ssaidi@eecs.umich.edu
3225952Ssaidi@eecs.umich.edu/// Target getppid() handler.
3235952Ssaidi@eecs.umich.eduSyscallReturn getppidFunc(SyscallDesc *desc, int num,
3245952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3255952Ssaidi@eecs.umich.edu
3265952Ssaidi@eecs.umich.edu/// Target geteuid() handler.
3275952Ssaidi@eecs.umich.eduSyscallReturn geteuidFunc(SyscallDesc *desc, int num,
3285952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3295952Ssaidi@eecs.umich.edu
3305952Ssaidi@eecs.umich.edu/// Target getegid() handler.
3315952Ssaidi@eecs.umich.eduSyscallReturn getegidFunc(SyscallDesc *desc, int num,
3325952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3335952Ssaidi@eecs.umich.edu
3345952Ssaidi@eecs.umich.edu/// Target clone() handler.
3355952Ssaidi@eecs.umich.eduSyscallReturn cloneFunc(SyscallDesc *desc, int num,
3365952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
3375952Ssaidi@eecs.umich.edu
3385952Ssaidi@eecs.umich.edu/// Futex system call
3395952Ssaidi@eecs.umich.edu///  Implemented by Daniel Sanchez
3405952Ssaidi@eecs.umich.edu///  Used by printf's in multi-threaded apps
3415952Ssaidi@eecs.umich.edutemplate <class OS>
3425952Ssaidi@eecs.umich.eduSyscallReturn
3435952Ssaidi@eecs.umich.edufutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
3445952Ssaidi@eecs.umich.edu          ThreadContext *tc)
3455952Ssaidi@eecs.umich.edu{
3465952Ssaidi@eecs.umich.edu    int index_uaddr = 0;
3475952Ssaidi@eecs.umich.edu    int index_op = 1;
3485952Ssaidi@eecs.umich.edu    int index_val = 2;
3495952Ssaidi@eecs.umich.edu    int index_timeout = 3;
3505952Ssaidi@eecs.umich.edu
3515952Ssaidi@eecs.umich.edu    uint64_t uaddr = process->getSyscallArg(tc, index_uaddr);
3525952Ssaidi@eecs.umich.edu    int op = process->getSyscallArg(tc, index_op);
3535952Ssaidi@eecs.umich.edu    int val = process->getSyscallArg(tc, index_val);
3545952Ssaidi@eecs.umich.edu    uint64_t timeout = process->getSyscallArg(tc, index_timeout);
3555952Ssaidi@eecs.umich.edu
3565952Ssaidi@eecs.umich.edu    std::map<uint64_t, std::list<ThreadContext *> * >
3575952Ssaidi@eecs.umich.edu        &futex_map = tc->getSystemPtr()->futexMap;
3585952Ssaidi@eecs.umich.edu
3595952Ssaidi@eecs.umich.edu    DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n",
3605952Ssaidi@eecs.umich.edu            uaddr, op, val);
3615952Ssaidi@eecs.umich.edu
3625952Ssaidi@eecs.umich.edu    op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
3635952Ssaidi@eecs.umich.edu
3645952Ssaidi@eecs.umich.edu    if (op == OS::TGT_FUTEX_WAIT) {
3655952Ssaidi@eecs.umich.edu        if (timeout != 0) {
3665952Ssaidi@eecs.umich.edu            warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;"
3675952Ssaidi@eecs.umich.edu                 "we'll wait indefinitely");
3685952Ssaidi@eecs.umich.edu        }
3695952Ssaidi@eecs.umich.edu
3705952Ssaidi@eecs.umich.edu        uint8_t *buf = new uint8_t[sizeof(int)];
3715952Ssaidi@eecs.umich.edu        tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int));
3725952Ssaidi@eecs.umich.edu        int mem_val = *((int *)buf);
3735952Ssaidi@eecs.umich.edu        delete buf;
3745952Ssaidi@eecs.umich.edu
3755952Ssaidi@eecs.umich.edu        if(val != mem_val) {
3765952Ssaidi@eecs.umich.edu            DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, "
3775952Ssaidi@eecs.umich.edu                                    "expected: %d\n", mem_val, val);
3785952Ssaidi@eecs.umich.edu            return -OS::TGT_EWOULDBLOCK;
3795952Ssaidi@eecs.umich.edu        }
3805952Ssaidi@eecs.umich.edu
3815952Ssaidi@eecs.umich.edu        // Queue the thread context
3825952Ssaidi@eecs.umich.edu        std::list<ThreadContext *> * tcWaitList;
3835952Ssaidi@eecs.umich.edu        if (futex_map.count(uaddr)) {
3845952Ssaidi@eecs.umich.edu            tcWaitList = futex_map.find(uaddr)->second;
3855952Ssaidi@eecs.umich.edu        } else {
3865952Ssaidi@eecs.umich.edu            tcWaitList = new std::list<ThreadContext *>();
3875952Ssaidi@eecs.umich.edu            futex_map.insert(std::pair< uint64_t,
3885952Ssaidi@eecs.umich.edu                            std::list<ThreadContext *> * >(uaddr, tcWaitList));
3895952Ssaidi@eecs.umich.edu        }
3905952Ssaidi@eecs.umich.edu        tcWaitList->push_back(tc);
3915952Ssaidi@eecs.umich.edu        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling "
3925952Ssaidi@eecs.umich.edu                                "thread context\n");
3935952Ssaidi@eecs.umich.edu        tc->suspend();
3945952Ssaidi@eecs.umich.edu        return 0;
3955952Ssaidi@eecs.umich.edu    } else if (op == OS::TGT_FUTEX_WAKE){
3965952Ssaidi@eecs.umich.edu        int wokenUp = 0;
3975952Ssaidi@eecs.umich.edu        std::list<ThreadContext *> * tcWaitList;
3985952Ssaidi@eecs.umich.edu        if (futex_map.count(uaddr)) {
3995952Ssaidi@eecs.umich.edu            tcWaitList = futex_map.find(uaddr)->second;
4005952Ssaidi@eecs.umich.edu            while (tcWaitList->size() > 0 && wokenUp < val) {
4015952Ssaidi@eecs.umich.edu                tcWaitList->front()->activate();
4025952Ssaidi@eecs.umich.edu                tcWaitList->pop_front();
4035952Ssaidi@eecs.umich.edu                wokenUp++;
4045952Ssaidi@eecs.umich.edu            }
4055952Ssaidi@eecs.umich.edu            if(tcWaitList->empty()) {
4065952Ssaidi@eecs.umich.edu                futex_map.erase(uaddr);
4075952Ssaidi@eecs.umich.edu                delete tcWaitList;
4085952Ssaidi@eecs.umich.edu            }
4095952Ssaidi@eecs.umich.edu        }
4105952Ssaidi@eecs.umich.edu        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting "
4115952Ssaidi@eecs.umich.edu                                "thread contexts\n", wokenUp);
4125952Ssaidi@eecs.umich.edu        return wokenUp;
4135952Ssaidi@eecs.umich.edu    } else {
4145952Ssaidi@eecs.umich.edu        warn("sys_futex: op %d is not implemented, just returning...", op);
4155952Ssaidi@eecs.umich.edu        return 0;
4165952Ssaidi@eecs.umich.edu    }
4175952Ssaidi@eecs.umich.edu
4185952Ssaidi@eecs.umich.edu}
4195952Ssaidi@eecs.umich.edu
4205952Ssaidi@eecs.umich.edu
4215952Ssaidi@eecs.umich.edu/// Pseudo Funcs  - These functions use a different return convension,
4225952Ssaidi@eecs.umich.edu/// returning a second value in a register other than the normal return register
4235952Ssaidi@eecs.umich.eduSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
4245952Ssaidi@eecs.umich.edu                             LiveProcess *process, ThreadContext *tc);
4255952Ssaidi@eecs.umich.edu
4265952Ssaidi@eecs.umich.edu/// Target getpidPseudo() handler.
4275952Ssaidi@eecs.umich.eduSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
4285952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
4295952Ssaidi@eecs.umich.edu
4305952Ssaidi@eecs.umich.edu/// Target getuidPseudo() handler.
4315952Ssaidi@eecs.umich.eduSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
4325952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
4335952Ssaidi@eecs.umich.edu
4345952Ssaidi@eecs.umich.edu/// Target getgidPseudo() handler.
4355952Ssaidi@eecs.umich.eduSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
4365952Ssaidi@eecs.umich.edu                               LiveProcess *p, ThreadContext *tc);
4375952Ssaidi@eecs.umich.edu
4385952Ssaidi@eecs.umich.edu
4395952Ssaidi@eecs.umich.edu/// A readable name for 1,000,000, for converting microseconds to seconds.
4405952Ssaidi@eecs.umich.educonst int one_million = 1000000;
4415952Ssaidi@eecs.umich.edu
4425952Ssaidi@eecs.umich.edu/// Approximate seconds since the epoch (1/1/1970).  About a billion,
4435952Ssaidi@eecs.umich.edu/// by my reckoning.  We want to keep this a constant (not use the
4445952Ssaidi@eecs.umich.edu/// real-world time) to keep simulations repeatable.
4455952Ssaidi@eecs.umich.educonst unsigned seconds_since_epoch = 1000000000;
4465952Ssaidi@eecs.umich.edu
4475952Ssaidi@eecs.umich.edu/// Helper function to convert current elapsed time to seconds and
4485952Ssaidi@eecs.umich.edu/// microseconds.
4495952Ssaidi@eecs.umich.edutemplate <class T1, class T2>
4505952Ssaidi@eecs.umich.eduvoid
4515952Ssaidi@eecs.umich.edugetElapsedTime(T1 &sec, T2 &usec)
4525952Ssaidi@eecs.umich.edu{
4535952Ssaidi@eecs.umich.edu    int elapsed_usecs = curTick() / SimClock::Int::us;
4545952Ssaidi@eecs.umich.edu    sec = elapsed_usecs / one_million;
4555952Ssaidi@eecs.umich.edu    usec = elapsed_usecs % one_million;
4565952Ssaidi@eecs.umich.edu}
4575952Ssaidi@eecs.umich.edu
4585952Ssaidi@eecs.umich.edu//////////////////////////////////////////////////////////////////////
4595952Ssaidi@eecs.umich.edu//
4605952Ssaidi@eecs.umich.edu// The following emulation functions are generic, but need to be
4615952Ssaidi@eecs.umich.edu// templated to account for differences in types, constants, etc.
4625952Ssaidi@eecs.umich.edu//
4635952Ssaidi@eecs.umich.edu//////////////////////////////////////////////////////////////////////
4645952Ssaidi@eecs.umich.edu
4655952Ssaidi@eecs.umich.edu#if NO_STAT64
4665952Ssaidi@eecs.umich.edu    typedef struct stat hst_stat;
4675952Ssaidi@eecs.umich.edu    typedef struct stat hst_stat64;
4685952Ssaidi@eecs.umich.edu#else
4695952Ssaidi@eecs.umich.edu    typedef struct stat hst_stat;
4705952Ssaidi@eecs.umich.edu    typedef struct stat64 hst_stat64;
4715952Ssaidi@eecs.umich.edu#endif
4725952Ssaidi@eecs.umich.edu
4735952Ssaidi@eecs.umich.edu//// Helper function to convert a host stat buffer to a target stat
4745952Ssaidi@eecs.umich.edu//// buffer.  Also copies the target buffer out to the simulated
4755952Ssaidi@eecs.umich.edu//// memory space.  Used by stat(), fstat(), and lstat().
4765952Ssaidi@eecs.umich.edu
4775952Ssaidi@eecs.umich.edutemplate <typename target_stat, typename host_stat>
4785952Ssaidi@eecs.umich.edustatic void
4795952Ssaidi@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
4805952Ssaidi@eecs.umich.edu{
4815952Ssaidi@eecs.umich.edu    using namespace TheISA;
4825952Ssaidi@eecs.umich.edu
4835952Ssaidi@eecs.umich.edu    if (fakeTTY)
4845952Ssaidi@eecs.umich.edu        tgt->st_dev = 0xA;
4855952Ssaidi@eecs.umich.edu    else
4865952Ssaidi@eecs.umich.edu        tgt->st_dev = host->st_dev;
4875952Ssaidi@eecs.umich.edu    tgt->st_dev = TheISA::htog(tgt->st_dev);
4885952Ssaidi@eecs.umich.edu    tgt->st_ino = host->st_ino;
4895952Ssaidi@eecs.umich.edu    tgt->st_ino = TheISA::htog(tgt->st_ino);
4905952Ssaidi@eecs.umich.edu    tgt->st_mode = host->st_mode;
4915952Ssaidi@eecs.umich.edu    if (fakeTTY) {
4925952Ssaidi@eecs.umich.edu        // Claim to be a character device
4935952Ssaidi@eecs.umich.edu        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
4945952Ssaidi@eecs.umich.edu        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
4955952Ssaidi@eecs.umich.edu    }
4965952Ssaidi@eecs.umich.edu    tgt->st_mode = TheISA::htog(tgt->st_mode);
4975952Ssaidi@eecs.umich.edu    tgt->st_nlink = host->st_nlink;
4985952Ssaidi@eecs.umich.edu    tgt->st_nlink = TheISA::htog(tgt->st_nlink);
4995952Ssaidi@eecs.umich.edu    tgt->st_uid = host->st_uid;
5005952Ssaidi@eecs.umich.edu    tgt->st_uid = TheISA::htog(tgt->st_uid);
5015952Ssaidi@eecs.umich.edu    tgt->st_gid = host->st_gid;
5025952Ssaidi@eecs.umich.edu    tgt->st_gid = TheISA::htog(tgt->st_gid);
5035952Ssaidi@eecs.umich.edu    if (fakeTTY)
5045952Ssaidi@eecs.umich.edu        tgt->st_rdev = 0x880d;
5055952Ssaidi@eecs.umich.edu    else
5065952Ssaidi@eecs.umich.edu        tgt->st_rdev = host->st_rdev;
5075952Ssaidi@eecs.umich.edu    tgt->st_rdev = TheISA::htog(tgt->st_rdev);
5085952Ssaidi@eecs.umich.edu    tgt->st_size = host->st_size;
5095952Ssaidi@eecs.umich.edu    tgt->st_size = TheISA::htog(tgt->st_size);
5105952Ssaidi@eecs.umich.edu    tgt->st_atimeX = host->st_atime;
5115952Ssaidi@eecs.umich.edu    tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
5125952Ssaidi@eecs.umich.edu    tgt->st_mtimeX = host->st_mtime;
5135952Ssaidi@eecs.umich.edu    tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
5145952Ssaidi@eecs.umich.edu    tgt->st_ctimeX = host->st_ctime;
5155952Ssaidi@eecs.umich.edu    tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
5165952Ssaidi@eecs.umich.edu    // Force the block size to be 8k. This helps to ensure buffered io works
5175952Ssaidi@eecs.umich.edu    // consistently across different hosts.
5185952Ssaidi@eecs.umich.edu    tgt->st_blksize = 0x2000;
5195952Ssaidi@eecs.umich.edu    tgt->st_blksize = TheISA::htog(tgt->st_blksize);
5205952Ssaidi@eecs.umich.edu    tgt->st_blocks = host->st_blocks;
5215952Ssaidi@eecs.umich.edu    tgt->st_blocks = TheISA::htog(tgt->st_blocks);
5225952Ssaidi@eecs.umich.edu}
5235952Ssaidi@eecs.umich.edu
5245952Ssaidi@eecs.umich.edu// Same for stat64
5255952Ssaidi@eecs.umich.edu
5265952Ssaidi@eecs.umich.edutemplate <typename target_stat, typename host_stat64>
5275952Ssaidi@eecs.umich.edustatic void
5285952Ssaidi@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
5295952Ssaidi@eecs.umich.edu{
5305952Ssaidi@eecs.umich.edu    using namespace TheISA;
5315952Ssaidi@eecs.umich.edu
5325952Ssaidi@eecs.umich.edu    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
5335952Ssaidi@eecs.umich.edu#if defined(STAT_HAVE_NSEC)
5345952Ssaidi@eecs.umich.edu    tgt->st_atime_nsec = host->st_atime_nsec;
5355952Ssaidi@eecs.umich.edu    tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
5365952Ssaidi@eecs.umich.edu    tgt->st_mtime_nsec = host->st_mtime_nsec;
5375952Ssaidi@eecs.umich.edu    tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
5385952Ssaidi@eecs.umich.edu    tgt->st_ctime_nsec = host->st_ctime_nsec;
5395952Ssaidi@eecs.umich.edu    tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
5405952Ssaidi@eecs.umich.edu#else
5415952Ssaidi@eecs.umich.edu    tgt->st_atime_nsec = 0;
5425952Ssaidi@eecs.umich.edu    tgt->st_mtime_nsec = 0;
5435952Ssaidi@eecs.umich.edu    tgt->st_ctime_nsec = 0;
5445952Ssaidi@eecs.umich.edu#endif
5455952Ssaidi@eecs.umich.edu}
5465952Ssaidi@eecs.umich.edu
5475952Ssaidi@eecs.umich.edu//Here are a couple convenience functions
5485952Ssaidi@eecs.umich.edutemplate<class OS>
5495952Ssaidi@eecs.umich.edustatic void
5505952Ssaidi@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr,
5515952Ssaidi@eecs.umich.edu        hst_stat *host, bool fakeTTY = false)
5525952Ssaidi@eecs.umich.edu{
5535952Ssaidi@eecs.umich.edu    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
5545952Ssaidi@eecs.umich.edu    tgt_stat_buf tgt(addr);
5555952Ssaidi@eecs.umich.edu    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
5565952Ssaidi@eecs.umich.edu    tgt.copyOut(mem);
5575952Ssaidi@eecs.umich.edu}
5585952Ssaidi@eecs.umich.edu
5595952Ssaidi@eecs.umich.edutemplate<class OS>
5605952Ssaidi@eecs.umich.edustatic void
5615952Ssaidi@eecs.umich.educopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr,
5625952Ssaidi@eecs.umich.edu        hst_stat64 *host, bool fakeTTY = false)
5635952Ssaidi@eecs.umich.edu{
5645952Ssaidi@eecs.umich.edu    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
5655952Ssaidi@eecs.umich.edu    tgt_stat_buf tgt(addr);
5665952Ssaidi@eecs.umich.edu    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
5675952Ssaidi@eecs.umich.edu    tgt.copyOut(mem);
5685952Ssaidi@eecs.umich.edu}
5695952Ssaidi@eecs.umich.edu
5705952Ssaidi@eecs.umich.edu/// Target ioctl() handler.  For the most part, programs call ioctl()
5715952Ssaidi@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to
5725952Ssaidi@eecs.umich.edu/// do line or block buffering.  We always claim that output fds are
5735952Ssaidi@eecs.umich.edu/// not TTYs to provide repeatable results.
5745952Ssaidi@eecs.umich.edutemplate <class OS>
5755952Ssaidi@eecs.umich.eduSyscallReturn
5765952Ssaidi@eecs.umich.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
5775952Ssaidi@eecs.umich.edu          ThreadContext *tc)
5785952Ssaidi@eecs.umich.edu{
5795952Ssaidi@eecs.umich.edu    int index = 0;
5805952Ssaidi@eecs.umich.edu    int fd = process->getSyscallArg(tc, index);
5815952Ssaidi@eecs.umich.edu    unsigned req = process->getSyscallArg(tc, index);
5825952Ssaidi@eecs.umich.edu
5835952Ssaidi@eecs.umich.edu    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
5845952Ssaidi@eecs.umich.edu
5855952Ssaidi@eecs.umich.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
5865952Ssaidi@eecs.umich.edu        // doesn't map to any simulator fd: not a valid target fd
5875952Ssaidi@eecs.umich.edu        return -EBADF;
5885952Ssaidi@eecs.umich.edu    }
5895952Ssaidi@eecs.umich.edu
5905952Ssaidi@eecs.umich.edu    if (OS::isTtyReq(req)) {
5915952Ssaidi@eecs.umich.edu        return -ENOTTY;
5925952Ssaidi@eecs.umich.edu    }
5935952Ssaidi@eecs.umich.edu
5945952Ssaidi@eecs.umich.edu    warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
5955952Ssaidi@eecs.umich.edu         fd, req, tc->pcState());
5965952Ssaidi@eecs.umich.edu    return -ENOTTY;
5975952Ssaidi@eecs.umich.edu}
5985952Ssaidi@eecs.umich.edu
5995952Ssaidi@eecs.umich.edu/// Target open() handler.
6005952Ssaidi@eecs.umich.edutemplate <class OS>
6015952Ssaidi@eecs.umich.eduSyscallReturn
6025952Ssaidi@eecs.umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
6035952Ssaidi@eecs.umich.edu         ThreadContext *tc)
6045952Ssaidi@eecs.umich.edu{
6055952Ssaidi@eecs.umich.edu    std::string path;
6065952Ssaidi@eecs.umich.edu
6075952Ssaidi@eecs.umich.edu    int index = 0;
6085952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
6095952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index)))
6105952Ssaidi@eecs.umich.edu        return -EFAULT;
6115952Ssaidi@eecs.umich.edu
6125952Ssaidi@eecs.umich.edu    if (path == "/dev/sysdev0") {
6135952Ssaidi@eecs.umich.edu        // This is a memory-mapped high-resolution timer device on Alpha.
6145952Ssaidi@eecs.umich.edu        // We don't support it, so just punt.
6155952Ssaidi@eecs.umich.edu        warn("Ignoring open(%s, ...)\n", path);
6165952Ssaidi@eecs.umich.edu        return -ENOENT;
6175952Ssaidi@eecs.umich.edu    }
6185952Ssaidi@eecs.umich.edu
6195952Ssaidi@eecs.umich.edu    int tgtFlags = process->getSyscallArg(tc, index);
6205952Ssaidi@eecs.umich.edu    int mode = process->getSyscallArg(tc, index);
6215952Ssaidi@eecs.umich.edu    int hostFlags = 0;
6225952Ssaidi@eecs.umich.edu
6235952Ssaidi@eecs.umich.edu    // translate open flags
6245952Ssaidi@eecs.umich.edu    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
6255952Ssaidi@eecs.umich.edu        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
6265952Ssaidi@eecs.umich.edu            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
6275952Ssaidi@eecs.umich.edu            hostFlags |= OS::openFlagTable[i].hostFlag;
6285952Ssaidi@eecs.umich.edu        }
6295952Ssaidi@eecs.umich.edu    }
6305952Ssaidi@eecs.umich.edu
6315952Ssaidi@eecs.umich.edu    // any target flags left?
6325952Ssaidi@eecs.umich.edu    if (tgtFlags != 0)
6335952Ssaidi@eecs.umich.edu        warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
6345952Ssaidi@eecs.umich.edu
6355952Ssaidi@eecs.umich.edu#ifdef __CYGWIN32__
6365952Ssaidi@eecs.umich.edu    hostFlags |= O_BINARY;
6375952Ssaidi@eecs.umich.edu#endif
6385952Ssaidi@eecs.umich.edu
6395952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
6405952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
6415952Ssaidi@eecs.umich.edu
6425952Ssaidi@eecs.umich.edu    DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
6435952Ssaidi@eecs.umich.edu
6445952Ssaidi@eecs.umich.edu    int fd;
6455952Ssaidi@eecs.umich.edu    int local_errno;
6465952Ssaidi@eecs.umich.edu    if (startswith(path, "/proc/") || startswith(path, "/system/") ||
6475952Ssaidi@eecs.umich.edu        startswith(path, "/platform/") || startswith(path, "/sys/")) {
6485952Ssaidi@eecs.umich.edu        // It's a proc/sys entry and requires special handling
6495952Ssaidi@eecs.umich.edu        fd = OS::openSpecialFile(path, process, tc);
6505952Ssaidi@eecs.umich.edu        local_errno = ENOENT;
6515952Ssaidi@eecs.umich.edu     } else {
6525952Ssaidi@eecs.umich.edu        // open the file
6535952Ssaidi@eecs.umich.edu        fd = open(path.c_str(), hostFlags, mode);
6545952Ssaidi@eecs.umich.edu        local_errno = errno;
6555952Ssaidi@eecs.umich.edu     }
6565952Ssaidi@eecs.umich.edu
6575952Ssaidi@eecs.umich.edu    if (fd == -1)
6585952Ssaidi@eecs.umich.edu        return -local_errno;
6595952Ssaidi@eecs.umich.edu
6605952Ssaidi@eecs.umich.edu    return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false);
6615952Ssaidi@eecs.umich.edu}
6625952Ssaidi@eecs.umich.edu
6635952Ssaidi@eecs.umich.edu/// Target sysinfo() handler.
6645952Ssaidi@eecs.umich.edutemplate <class OS>
6655952Ssaidi@eecs.umich.eduSyscallReturn
6665952Ssaidi@eecs.umich.edusysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
6675952Ssaidi@eecs.umich.edu         ThreadContext *tc)
6685952Ssaidi@eecs.umich.edu{
6695952Ssaidi@eecs.umich.edu
6705952Ssaidi@eecs.umich.edu    int index = 0;
6715952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::tgt_sysinfo>
6725952Ssaidi@eecs.umich.edu        sysinfo(process->getSyscallArg(tc, index));
6735952Ssaidi@eecs.umich.edu
6745952Ssaidi@eecs.umich.edu    sysinfo->uptime=seconds_since_epoch;
6755952Ssaidi@eecs.umich.edu    sysinfo->totalram=process->system->memSize();
6765952Ssaidi@eecs.umich.edu
6775952Ssaidi@eecs.umich.edu    sysinfo.copyOut(tc->getMemProxy());
6785952Ssaidi@eecs.umich.edu
6795952Ssaidi@eecs.umich.edu    return 0;
6805952Ssaidi@eecs.umich.edu}
6815952Ssaidi@eecs.umich.edu
6825952Ssaidi@eecs.umich.edu/// Target chmod() handler.
6835952Ssaidi@eecs.umich.edutemplate <class OS>
6845952Ssaidi@eecs.umich.eduSyscallReturn
6855952Ssaidi@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
6865952Ssaidi@eecs.umich.edu          ThreadContext *tc)
6875952Ssaidi@eecs.umich.edu{
6885952Ssaidi@eecs.umich.edu    std::string path;
6895952Ssaidi@eecs.umich.edu
6905952Ssaidi@eecs.umich.edu    int index = 0;
6917823Ssteve.reinhardt@amd.com    if (!tc->getMemProxy().tryReadString(path,
6925952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
6935952Ssaidi@eecs.umich.edu        return -EFAULT;
6947823Ssteve.reinhardt@amd.com    }
6955952Ssaidi@eecs.umich.edu
6965952Ssaidi@eecs.umich.edu    uint32_t mode = process->getSyscallArg(tc, index);
6975952Ssaidi@eecs.umich.edu    mode_t hostMode = 0;
6985952Ssaidi@eecs.umich.edu
6995952Ssaidi@eecs.umich.edu    // XXX translate mode flags via OS::something???
7005952Ssaidi@eecs.umich.edu    hostMode = mode;
7015952Ssaidi@eecs.umich.edu
7025952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
7035952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
7045952Ssaidi@eecs.umich.edu
7055952Ssaidi@eecs.umich.edu    // do the chmod
7065952Ssaidi@eecs.umich.edu    int result = chmod(path.c_str(), hostMode);
7075952Ssaidi@eecs.umich.edu    if (result < 0)
7085952Ssaidi@eecs.umich.edu        return -errno;
7095952Ssaidi@eecs.umich.edu
7105952Ssaidi@eecs.umich.edu    return 0;
7115952Ssaidi@eecs.umich.edu}
7125952Ssaidi@eecs.umich.edu
7135952Ssaidi@eecs.umich.edu
7145952Ssaidi@eecs.umich.edu/// Target fchmod() handler.
7155952Ssaidi@eecs.umich.edutemplate <class OS>
7165952Ssaidi@eecs.umich.eduSyscallReturn
7175952Ssaidi@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
7185952Ssaidi@eecs.umich.edu           ThreadContext *tc)
7195952Ssaidi@eecs.umich.edu{
7205952Ssaidi@eecs.umich.edu    int index = 0;
7215952Ssaidi@eecs.umich.edu    int fd = process->getSyscallArg(tc, index);
7225952Ssaidi@eecs.umich.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
7235952Ssaidi@eecs.umich.edu        // doesn't map to any simulator fd: not a valid target fd
7245952Ssaidi@eecs.umich.edu        return -EBADF;
7255952Ssaidi@eecs.umich.edu    }
7265952Ssaidi@eecs.umich.edu
7275952Ssaidi@eecs.umich.edu    uint32_t mode = process->getSyscallArg(tc, index);
7285952Ssaidi@eecs.umich.edu    mode_t hostMode = 0;
7295952Ssaidi@eecs.umich.edu
7305952Ssaidi@eecs.umich.edu    // XXX translate mode flags via OS::someting???
7315952Ssaidi@eecs.umich.edu    hostMode = mode;
7325952Ssaidi@eecs.umich.edu
7335952Ssaidi@eecs.umich.edu    // do the fchmod
7345952Ssaidi@eecs.umich.edu    int result = fchmod(process->sim_fd(fd), hostMode);
7355952Ssaidi@eecs.umich.edu    if (result < 0)
7365952Ssaidi@eecs.umich.edu        return -errno;
7375952Ssaidi@eecs.umich.edu
7385952Ssaidi@eecs.umich.edu    return 0;
7395952Ssaidi@eecs.umich.edu}
7405952Ssaidi@eecs.umich.edu
7415952Ssaidi@eecs.umich.edu/// Target mremap() handler.
7425952Ssaidi@eecs.umich.edutemplate <class OS>
7435952Ssaidi@eecs.umich.eduSyscallReturn
7445952Ssaidi@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
7455952Ssaidi@eecs.umich.edu{
7465952Ssaidi@eecs.umich.edu    int index = 0;
7475952Ssaidi@eecs.umich.edu    Addr start = process->getSyscallArg(tc, index);
7485952Ssaidi@eecs.umich.edu    uint64_t old_length = process->getSyscallArg(tc, index);
7495952Ssaidi@eecs.umich.edu    uint64_t new_length = process->getSyscallArg(tc, index);
7505952Ssaidi@eecs.umich.edu    uint64_t flags = process->getSyscallArg(tc, index);
7515952Ssaidi@eecs.umich.edu
7525952Ssaidi@eecs.umich.edu    if ((start % TheISA::VMPageSize != 0) ||
7535952Ssaidi@eecs.umich.edu            (new_length % TheISA::VMPageSize != 0)) {
7545952Ssaidi@eecs.umich.edu        warn("mremap failing: arguments not page aligned");
7555952Ssaidi@eecs.umich.edu        return -EINVAL;
7565952Ssaidi@eecs.umich.edu    }
7575952Ssaidi@eecs.umich.edu
7585952Ssaidi@eecs.umich.edu    if (new_length > old_length) {
7595952Ssaidi@eecs.umich.edu        if ((start + old_length) == process->mmap_end) {
7605952Ssaidi@eecs.umich.edu            uint64_t diff = new_length - old_length;
7615952Ssaidi@eecs.umich.edu            process->allocateMem(process->mmap_end, diff);
7625952Ssaidi@eecs.umich.edu            process->mmap_end += diff;
7635952Ssaidi@eecs.umich.edu            return start;
7645952Ssaidi@eecs.umich.edu        } else {
7655952Ssaidi@eecs.umich.edu            // sys/mman.h defined MREMAP_MAYMOVE
7665952Ssaidi@eecs.umich.edu            if (!(flags & 1)) {
7675952Ssaidi@eecs.umich.edu                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
7685952Ssaidi@eecs.umich.edu                return -ENOMEM;
7695952Ssaidi@eecs.umich.edu            } else {
7705952Ssaidi@eecs.umich.edu                process->pTable->remap(start, old_length, process->mmap_end);
7715952Ssaidi@eecs.umich.edu                warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
7725952Ssaidi@eecs.umich.edu                        process->mmap_end, process->mmap_end + new_length, new_length);
7735952Ssaidi@eecs.umich.edu                start = process->mmap_end;
7745952Ssaidi@eecs.umich.edu                // add on the remaining unallocated pages
7755952Ssaidi@eecs.umich.edu                process->allocateMem(start + old_length,
7765952Ssaidi@eecs.umich.edu                                     new_length - old_length);
7775952Ssaidi@eecs.umich.edu                process->mmap_end += new_length;
7785952Ssaidi@eecs.umich.edu                warn("returning %08p as start\n", start);
7795952Ssaidi@eecs.umich.edu                return start;
7805952Ssaidi@eecs.umich.edu            }
7815952Ssaidi@eecs.umich.edu        }
7825952Ssaidi@eecs.umich.edu    } else {
7835952Ssaidi@eecs.umich.edu        process->pTable->unmap(start + new_length, old_length - new_length);
7845952Ssaidi@eecs.umich.edu        return start;
7855952Ssaidi@eecs.umich.edu    }
7865952Ssaidi@eecs.umich.edu}
7875952Ssaidi@eecs.umich.edu
7885952Ssaidi@eecs.umich.edu/// Target stat() handler.
7895952Ssaidi@eecs.umich.edutemplate <class OS>
7905952Ssaidi@eecs.umich.eduSyscallReturn
7915952Ssaidi@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
7925952Ssaidi@eecs.umich.edu         ThreadContext *tc)
7935952Ssaidi@eecs.umich.edu{
7945952Ssaidi@eecs.umich.edu    std::string path;
7955952Ssaidi@eecs.umich.edu
7965952Ssaidi@eecs.umich.edu    int index = 0;
7975952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
7985952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
7995952Ssaidi@eecs.umich.edu        return -EFAULT;
8005952Ssaidi@eecs.umich.edu    }
8015952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
8025952Ssaidi@eecs.umich.edu
8035952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
8045952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
8055952Ssaidi@eecs.umich.edu
8065952Ssaidi@eecs.umich.edu    struct stat hostBuf;
8075952Ssaidi@eecs.umich.edu    int result = stat(path.c_str(), &hostBuf);
8085952Ssaidi@eecs.umich.edu
8095952Ssaidi@eecs.umich.edu    if (result < 0)
8105952Ssaidi@eecs.umich.edu        return -errno;
8115952Ssaidi@eecs.umich.edu
8125952Ssaidi@eecs.umich.edu    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
8135952Ssaidi@eecs.umich.edu
8145952Ssaidi@eecs.umich.edu    return 0;
8155952Ssaidi@eecs.umich.edu}
8167823Ssteve.reinhardt@amd.com
8175952Ssaidi@eecs.umich.edu
8185952Ssaidi@eecs.umich.edu/// Target stat64() handler.
8195952Ssaidi@eecs.umich.edutemplate <class OS>
8205952Ssaidi@eecs.umich.eduSyscallReturn
8215952Ssaidi@eecs.umich.edustat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
8225952Ssaidi@eecs.umich.edu           ThreadContext *tc)
8235952Ssaidi@eecs.umich.edu{
8245952Ssaidi@eecs.umich.edu    std::string path;
8255952Ssaidi@eecs.umich.edu
8265952Ssaidi@eecs.umich.edu    int index = 0;
8275952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
8285952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index)))
8295952Ssaidi@eecs.umich.edu        return -EFAULT;
8305952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
8315952Ssaidi@eecs.umich.edu
8325952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
8335952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
8345952Ssaidi@eecs.umich.edu
8355952Ssaidi@eecs.umich.edu#if NO_STAT64
8365952Ssaidi@eecs.umich.edu    struct stat  hostBuf;
8375952Ssaidi@eecs.umich.edu    int result = stat(path.c_str(), &hostBuf);
8385952Ssaidi@eecs.umich.edu#else
8395952Ssaidi@eecs.umich.edu    struct stat64 hostBuf;
8405952Ssaidi@eecs.umich.edu    int result = stat64(path.c_str(), &hostBuf);
8415952Ssaidi@eecs.umich.edu#endif
8425952Ssaidi@eecs.umich.edu
8435952Ssaidi@eecs.umich.edu    if (result < 0)
8445952Ssaidi@eecs.umich.edu        return -errno;
8455952Ssaidi@eecs.umich.edu
8465952Ssaidi@eecs.umich.edu    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
8475952Ssaidi@eecs.umich.edu
8485952Ssaidi@eecs.umich.edu    return 0;
8495952Ssaidi@eecs.umich.edu}
8505952Ssaidi@eecs.umich.edu
8515952Ssaidi@eecs.umich.edu
8525952Ssaidi@eecs.umich.edu/// Target fstat64() handler.
8535952Ssaidi@eecs.umich.edutemplate <class OS>
8545952Ssaidi@eecs.umich.eduSyscallReturn
8555952Ssaidi@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
8565952Ssaidi@eecs.umich.edu            ThreadContext *tc)
8575952Ssaidi@eecs.umich.edu{
8585952Ssaidi@eecs.umich.edu    int index = 0;
8595952Ssaidi@eecs.umich.edu    int fd = process->getSyscallArg(tc, index);
8605952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
8615952Ssaidi@eecs.umich.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
8625952Ssaidi@eecs.umich.edu        // doesn't map to any simulator fd: not a valid target fd
8635952Ssaidi@eecs.umich.edu        return -EBADF;
8645952Ssaidi@eecs.umich.edu    }
8655952Ssaidi@eecs.umich.edu
8665952Ssaidi@eecs.umich.edu#if NO_STAT64
8675952Ssaidi@eecs.umich.edu    struct stat  hostBuf;
8685952Ssaidi@eecs.umich.edu    int result = fstat(process->sim_fd(fd), &hostBuf);
8695952Ssaidi@eecs.umich.edu#else
8705952Ssaidi@eecs.umich.edu    struct stat64  hostBuf;
8715952Ssaidi@eecs.umich.edu    int result = fstat64(process->sim_fd(fd), &hostBuf);
8725952Ssaidi@eecs.umich.edu#endif
8735952Ssaidi@eecs.umich.edu
8745952Ssaidi@eecs.umich.edu    if (result < 0)
8755952Ssaidi@eecs.umich.edu        return -errno;
8765952Ssaidi@eecs.umich.edu
8775952Ssaidi@eecs.umich.edu    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
8785952Ssaidi@eecs.umich.edu
8795952Ssaidi@eecs.umich.edu    return 0;
8805952Ssaidi@eecs.umich.edu}
8815952Ssaidi@eecs.umich.edu
8825952Ssaidi@eecs.umich.edu
8835952Ssaidi@eecs.umich.edu/// Target lstat() handler.
8845952Ssaidi@eecs.umich.edutemplate <class OS>
8855952Ssaidi@eecs.umich.eduSyscallReturn
8865952Ssaidi@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
8875952Ssaidi@eecs.umich.edu          ThreadContext *tc)
8885952Ssaidi@eecs.umich.edu{
8895952Ssaidi@eecs.umich.edu    std::string path;
8905952Ssaidi@eecs.umich.edu
8915952Ssaidi@eecs.umich.edu    int index = 0;
8925952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
8935952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
8945952Ssaidi@eecs.umich.edu        return -EFAULT;
8955952Ssaidi@eecs.umich.edu    }
8965952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
8975952Ssaidi@eecs.umich.edu
8985952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
8995952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
9005952Ssaidi@eecs.umich.edu
9015952Ssaidi@eecs.umich.edu    struct stat hostBuf;
9025952Ssaidi@eecs.umich.edu    int result = lstat(path.c_str(), &hostBuf);
9035952Ssaidi@eecs.umich.edu
9045952Ssaidi@eecs.umich.edu    if (result < 0)
9055952Ssaidi@eecs.umich.edu        return -errno;
9065952Ssaidi@eecs.umich.edu
9075952Ssaidi@eecs.umich.edu    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
9085952Ssaidi@eecs.umich.edu
9095952Ssaidi@eecs.umich.edu    return 0;
9105952Ssaidi@eecs.umich.edu}
9115952Ssaidi@eecs.umich.edu
9125952Ssaidi@eecs.umich.edu/// Target lstat64() handler.
9135952Ssaidi@eecs.umich.edutemplate <class OS>
9145952Ssaidi@eecs.umich.eduSyscallReturn
9155952Ssaidi@eecs.umich.edulstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
9165952Ssaidi@eecs.umich.edu            ThreadContext *tc)
9175952Ssaidi@eecs.umich.edu{
9185952Ssaidi@eecs.umich.edu    std::string path;
9195952Ssaidi@eecs.umich.edu
9205952Ssaidi@eecs.umich.edu    int index = 0;
9215952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
9225952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
9235952Ssaidi@eecs.umich.edu        return -EFAULT;
9245952Ssaidi@eecs.umich.edu    }
9255952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
9265952Ssaidi@eecs.umich.edu
9275952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
9285952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
9295952Ssaidi@eecs.umich.edu
9305952Ssaidi@eecs.umich.edu#if NO_STAT64
9315952Ssaidi@eecs.umich.edu    struct stat hostBuf;
9325952Ssaidi@eecs.umich.edu    int result = lstat(path.c_str(), &hostBuf);
9335952Ssaidi@eecs.umich.edu#else
9345952Ssaidi@eecs.umich.edu    struct stat64 hostBuf;
9355952Ssaidi@eecs.umich.edu    int result = lstat64(path.c_str(), &hostBuf);
9365952Ssaidi@eecs.umich.edu#endif
9375952Ssaidi@eecs.umich.edu
9385952Ssaidi@eecs.umich.edu    if (result < 0)
9395952Ssaidi@eecs.umich.edu        return -errno;
9405952Ssaidi@eecs.umich.edu
9415952Ssaidi@eecs.umich.edu    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
9425952Ssaidi@eecs.umich.edu
9435952Ssaidi@eecs.umich.edu    return 0;
9445952Ssaidi@eecs.umich.edu}
9455952Ssaidi@eecs.umich.edu
9465952Ssaidi@eecs.umich.edu/// Target fstat() handler.
9475952Ssaidi@eecs.umich.edutemplate <class OS>
9485952Ssaidi@eecs.umich.eduSyscallReturn
9495952Ssaidi@eecs.umich.edufstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
9505952Ssaidi@eecs.umich.edu          ThreadContext *tc)
9515952Ssaidi@eecs.umich.edu{
9525952Ssaidi@eecs.umich.edu    int index = 0;
9535952Ssaidi@eecs.umich.edu    int fd = process->sim_fd(process->getSyscallArg(tc, index));
9545952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
9555952Ssaidi@eecs.umich.edu
9565952Ssaidi@eecs.umich.edu    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
9575952Ssaidi@eecs.umich.edu
9585952Ssaidi@eecs.umich.edu    if (fd < 0)
9595952Ssaidi@eecs.umich.edu        return -EBADF;
9605952Ssaidi@eecs.umich.edu
9615952Ssaidi@eecs.umich.edu    struct stat hostBuf;
9625952Ssaidi@eecs.umich.edu    int result = fstat(fd, &hostBuf);
9635952Ssaidi@eecs.umich.edu
9645952Ssaidi@eecs.umich.edu    if (result < 0)
9655952Ssaidi@eecs.umich.edu        return -errno;
9665952Ssaidi@eecs.umich.edu
9675952Ssaidi@eecs.umich.edu    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
9685952Ssaidi@eecs.umich.edu
9695952Ssaidi@eecs.umich.edu    return 0;
9705952Ssaidi@eecs.umich.edu}
9715952Ssaidi@eecs.umich.edu
9725952Ssaidi@eecs.umich.edu
9735952Ssaidi@eecs.umich.edu/// Target statfs() handler.
9745952Ssaidi@eecs.umich.edutemplate <class OS>
9755952Ssaidi@eecs.umich.eduSyscallReturn
9765952Ssaidi@eecs.umich.edustatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
9775952Ssaidi@eecs.umich.edu           ThreadContext *tc)
9785952Ssaidi@eecs.umich.edu{
9795952Ssaidi@eecs.umich.edu    std::string path;
9805952Ssaidi@eecs.umich.edu
9815952Ssaidi@eecs.umich.edu    int index = 0;
9825952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
9835952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
9845952Ssaidi@eecs.umich.edu        return -EFAULT;
9855952Ssaidi@eecs.umich.edu    }
9865952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
9875952Ssaidi@eecs.umich.edu
9885952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
9895952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
9905952Ssaidi@eecs.umich.edu
9915952Ssaidi@eecs.umich.edu    struct statfs hostBuf;
9925952Ssaidi@eecs.umich.edu    int result = statfs(path.c_str(), &hostBuf);
9935952Ssaidi@eecs.umich.edu
9945952Ssaidi@eecs.umich.edu    if (result < 0)
9955952Ssaidi@eecs.umich.edu        return -errno;
9965952Ssaidi@eecs.umich.edu
9975952Ssaidi@eecs.umich.edu    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
9985952Ssaidi@eecs.umich.edu
9995952Ssaidi@eecs.umich.edu    return 0;
10005952Ssaidi@eecs.umich.edu}
10015952Ssaidi@eecs.umich.edu
10025952Ssaidi@eecs.umich.edu
10035952Ssaidi@eecs.umich.edu/// Target fstatfs() handler.
10045952Ssaidi@eecs.umich.edutemplate <class OS>
10055952Ssaidi@eecs.umich.eduSyscallReturn
10065952Ssaidi@eecs.umich.edufstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
10075952Ssaidi@eecs.umich.edu            ThreadContext *tc)
10085952Ssaidi@eecs.umich.edu{
10095952Ssaidi@eecs.umich.edu    int index = 0;
10105952Ssaidi@eecs.umich.edu    int fd = process->sim_fd(process->getSyscallArg(tc, index));
10115952Ssaidi@eecs.umich.edu    Addr bufPtr = process->getSyscallArg(tc, index);
10125952Ssaidi@eecs.umich.edu
10135952Ssaidi@eecs.umich.edu    if (fd < 0)
10145952Ssaidi@eecs.umich.edu        return -EBADF;
10155952Ssaidi@eecs.umich.edu
10165952Ssaidi@eecs.umich.edu    struct statfs hostBuf;
10175952Ssaidi@eecs.umich.edu    int result = fstatfs(fd, &hostBuf);
10185952Ssaidi@eecs.umich.edu
10195952Ssaidi@eecs.umich.edu    if (result < 0)
10205952Ssaidi@eecs.umich.edu        return -errno;
10215952Ssaidi@eecs.umich.edu
10225952Ssaidi@eecs.umich.edu    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
10235952Ssaidi@eecs.umich.edu
10245952Ssaidi@eecs.umich.edu    return 0;
10255952Ssaidi@eecs.umich.edu}
10265952Ssaidi@eecs.umich.edu
10275952Ssaidi@eecs.umich.edu
10285952Ssaidi@eecs.umich.edu/// Target writev() handler.
10295952Ssaidi@eecs.umich.edutemplate <class OS>
10305952Ssaidi@eecs.umich.eduSyscallReturn
10315952Ssaidi@eecs.umich.eduwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
10325952Ssaidi@eecs.umich.edu           ThreadContext *tc)
10335952Ssaidi@eecs.umich.edu{
10345952Ssaidi@eecs.umich.edu    int index = 0;
10355952Ssaidi@eecs.umich.edu    int fd = process->getSyscallArg(tc, index);
10365952Ssaidi@eecs.umich.edu    if (fd < 0 || process->sim_fd(fd) < 0) {
10375952Ssaidi@eecs.umich.edu        // doesn't map to any simulator fd: not a valid target fd
10385952Ssaidi@eecs.umich.edu        return -EBADF;
10395952Ssaidi@eecs.umich.edu    }
10405952Ssaidi@eecs.umich.edu
10415952Ssaidi@eecs.umich.edu    SETranslatingPortProxy &p = tc->getMemProxy();
10425952Ssaidi@eecs.umich.edu    uint64_t tiov_base = process->getSyscallArg(tc, index);
10435952Ssaidi@eecs.umich.edu    size_t count = process->getSyscallArg(tc, index);
10445952Ssaidi@eecs.umich.edu    struct iovec hiov[count];
10455952Ssaidi@eecs.umich.edu    for (size_t i = 0; i < count; ++i) {
10465952Ssaidi@eecs.umich.edu        typename OS::tgt_iovec tiov;
10475952Ssaidi@eecs.umich.edu
10485952Ssaidi@eecs.umich.edu        p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
10495952Ssaidi@eecs.umich.edu                   (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
10505952Ssaidi@eecs.umich.edu        hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
10515952Ssaidi@eecs.umich.edu        hiov[i].iov_base = new char [hiov[i].iov_len];
10525952Ssaidi@eecs.umich.edu        p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
10535952Ssaidi@eecs.umich.edu                   hiov[i].iov_len);
10545952Ssaidi@eecs.umich.edu    }
10555952Ssaidi@eecs.umich.edu
10565952Ssaidi@eecs.umich.edu    int result = writev(process->sim_fd(fd), hiov, count);
10575952Ssaidi@eecs.umich.edu
10585952Ssaidi@eecs.umich.edu    for (size_t i = 0; i < count; ++i)
10595952Ssaidi@eecs.umich.edu        delete [] (char *)hiov[i].iov_base;
10605952Ssaidi@eecs.umich.edu
10615952Ssaidi@eecs.umich.edu    if (result < 0)
10625952Ssaidi@eecs.umich.edu        return -errno;
10635952Ssaidi@eecs.umich.edu
10645952Ssaidi@eecs.umich.edu    return 0;
10655952Ssaidi@eecs.umich.edu}
10665952Ssaidi@eecs.umich.edu
10675952Ssaidi@eecs.umich.edu
10685952Ssaidi@eecs.umich.edu/// Target mmap() handler.
10695952Ssaidi@eecs.umich.edu///
10705952Ssaidi@eecs.umich.edu/// We don't really handle mmap().  If the target is mmaping an
10715952Ssaidi@eecs.umich.edu/// anonymous region or /dev/zero, we can get away with doing basically
10725952Ssaidi@eecs.umich.edu/// nothing (since memory is initialized to zero and the simulator
10735952Ssaidi@eecs.umich.edu/// doesn't really check addresses anyway).
10745952Ssaidi@eecs.umich.edu///
10755952Ssaidi@eecs.umich.edutemplate <class OS>
10765952Ssaidi@eecs.umich.eduSyscallReturn
10775952Ssaidi@eecs.umich.edummapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
10785952Ssaidi@eecs.umich.edu{
10795952Ssaidi@eecs.umich.edu    int index = 0;
10805952Ssaidi@eecs.umich.edu    Addr start = p->getSyscallArg(tc, index);
10815952Ssaidi@eecs.umich.edu    uint64_t length = p->getSyscallArg(tc, index);
10825952Ssaidi@eecs.umich.edu    index++; // int prot = p->getSyscallArg(tc, index);
10835952Ssaidi@eecs.umich.edu    int flags = p->getSyscallArg(tc, index);
10845952Ssaidi@eecs.umich.edu    int tgt_fd = p->getSyscallArg(tc, index);
10855952Ssaidi@eecs.umich.edu    // int offset = p->getSyscallArg(tc, index);
10865952Ssaidi@eecs.umich.edu
10875952Ssaidi@eecs.umich.edu    if (length > 0x100000000ULL)
10885952Ssaidi@eecs.umich.edu        warn("mmap length argument %#x is unreasonably large.\n", length);
10895952Ssaidi@eecs.umich.edu
10905952Ssaidi@eecs.umich.edu    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
10915952Ssaidi@eecs.umich.edu        Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd);
10925952Ssaidi@eecs.umich.edu        if (!fd_map || fd_map->fd < 0) {
10935952Ssaidi@eecs.umich.edu            warn("mmap failing: target fd %d is not valid\n", tgt_fd);
10945952Ssaidi@eecs.umich.edu            return -EBADF;
10955952Ssaidi@eecs.umich.edu        }
10965952Ssaidi@eecs.umich.edu
10975952Ssaidi@eecs.umich.edu        if (fd_map->filename != "/dev/zero") {
10985952Ssaidi@eecs.umich.edu            // This is very likely broken, but leave a warning here
10995952Ssaidi@eecs.umich.edu            // (rather than panic) in case /dev/zero is known by
11005952Ssaidi@eecs.umich.edu            // another name on some platform
11015952Ssaidi@eecs.umich.edu            warn("allowing mmap of file %s; mmap not supported on files"
11025952Ssaidi@eecs.umich.edu                 " other than /dev/zero\n", fd_map->filename);
11035952Ssaidi@eecs.umich.edu        }
11045952Ssaidi@eecs.umich.edu    }
11055952Ssaidi@eecs.umich.edu
11065952Ssaidi@eecs.umich.edu    if ((start  % TheISA::VMPageSize) != 0 ||
11075952Ssaidi@eecs.umich.edu        (length % TheISA::VMPageSize) != 0) {
11085952Ssaidi@eecs.umich.edu        warn("mmap failing: arguments not page-aligned: "
11095952Ssaidi@eecs.umich.edu             "start 0x%x length 0x%x",
11105952Ssaidi@eecs.umich.edu             start, length);
11115952Ssaidi@eecs.umich.edu        return -EINVAL;
11125952Ssaidi@eecs.umich.edu    }
11135952Ssaidi@eecs.umich.edu
11145952Ssaidi@eecs.umich.edu    // are we ok with clobbering existing mappings?  only set this to
11155952Ssaidi@eecs.umich.edu    // true if the user has been warned.
11165952Ssaidi@eecs.umich.edu    bool clobber = false;
11175952Ssaidi@eecs.umich.edu
11185952Ssaidi@eecs.umich.edu    // try to use the caller-provided address if there is one
11195952Ssaidi@eecs.umich.edu    bool use_provided_address = (start != 0);
11205952Ssaidi@eecs.umich.edu
11215952Ssaidi@eecs.umich.edu    if (use_provided_address) {
11225952Ssaidi@eecs.umich.edu        // check to see if the desired address is already in use
11235952Ssaidi@eecs.umich.edu        if (!p->pTable->isUnmapped(start, length)) {
11245952Ssaidi@eecs.umich.edu            // there are existing mappings in the desired range
11255952Ssaidi@eecs.umich.edu            // whether we clobber them or not depends on whether the caller
11265952Ssaidi@eecs.umich.edu            // specified MAP_FIXED
11275952Ssaidi@eecs.umich.edu            if (flags & OS::TGT_MAP_FIXED) {
11285952Ssaidi@eecs.umich.edu                // MAP_FIXED specified: clobber existing mappings
11295952Ssaidi@eecs.umich.edu                warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n",
11305952Ssaidi@eecs.umich.edu                     start);
11315952Ssaidi@eecs.umich.edu                clobber = true;
11325952Ssaidi@eecs.umich.edu            } else {
11335952Ssaidi@eecs.umich.edu                // MAP_FIXED not specified: ignore suggested start address
11345952Ssaidi@eecs.umich.edu                warn("mmap: ignoring suggested map address 0x%x\n", start);
11355952Ssaidi@eecs.umich.edu                use_provided_address = false;
11365952Ssaidi@eecs.umich.edu            }
11375952Ssaidi@eecs.umich.edu        }
11385952Ssaidi@eecs.umich.edu    }
11395952Ssaidi@eecs.umich.edu
11405952Ssaidi@eecs.umich.edu    if (!use_provided_address) {
11415952Ssaidi@eecs.umich.edu        // no address provided, or provided address unusable:
11425952Ssaidi@eecs.umich.edu        // pick next address from our "mmap region"
11435952Ssaidi@eecs.umich.edu        if (OS::mmapGrowsDown()) {
11445952Ssaidi@eecs.umich.edu            start = p->mmap_end - length;
11455952Ssaidi@eecs.umich.edu            p->mmap_end = start;
11465952Ssaidi@eecs.umich.edu        } else {
11475952Ssaidi@eecs.umich.edu            start = p->mmap_end;
11485952Ssaidi@eecs.umich.edu            p->mmap_end += length;
11495952Ssaidi@eecs.umich.edu        }
11505952Ssaidi@eecs.umich.edu    }
11515952Ssaidi@eecs.umich.edu
11525952Ssaidi@eecs.umich.edu    p->allocateMem(start, length, clobber);
11535952Ssaidi@eecs.umich.edu
11545952Ssaidi@eecs.umich.edu    return start;
11555952Ssaidi@eecs.umich.edu}
11565952Ssaidi@eecs.umich.edu
11575952Ssaidi@eecs.umich.edu/// Target getrlimit() handler.
11585952Ssaidi@eecs.umich.edutemplate <class OS>
11595952Ssaidi@eecs.umich.eduSyscallReturn
11605952Ssaidi@eecs.umich.edugetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
11615952Ssaidi@eecs.umich.edu        ThreadContext *tc)
11625952Ssaidi@eecs.umich.edu{
11635952Ssaidi@eecs.umich.edu    int index = 0;
11645952Ssaidi@eecs.umich.edu    unsigned resource = process->getSyscallArg(tc, index);
11655952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
11665952Ssaidi@eecs.umich.edu
11675952Ssaidi@eecs.umich.edu    switch (resource) {
11685952Ssaidi@eecs.umich.edu        case OS::TGT_RLIMIT_STACK:
11695952Ssaidi@eecs.umich.edu            // max stack size in bytes: make up a number (8MB for now)
11705952Ssaidi@eecs.umich.edu            rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
11715952Ssaidi@eecs.umich.edu            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
11725952Ssaidi@eecs.umich.edu            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
11735952Ssaidi@eecs.umich.edu            break;
11745952Ssaidi@eecs.umich.edu
11755952Ssaidi@eecs.umich.edu        case OS::TGT_RLIMIT_DATA:
11765952Ssaidi@eecs.umich.edu            // max data segment size in bytes: make up a number
11775952Ssaidi@eecs.umich.edu            rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
11785952Ssaidi@eecs.umich.edu            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
11795952Ssaidi@eecs.umich.edu            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
11805952Ssaidi@eecs.umich.edu            break;
11815952Ssaidi@eecs.umich.edu
11825952Ssaidi@eecs.umich.edu        default:
11835952Ssaidi@eecs.umich.edu            std::cerr << "getrlimitFunc: unimplemented resource " << resource
11845952Ssaidi@eecs.umich.edu                << std::endl;
11855952Ssaidi@eecs.umich.edu            abort();
11865952Ssaidi@eecs.umich.edu            break;
11875952Ssaidi@eecs.umich.edu    }
11885952Ssaidi@eecs.umich.edu
11895952Ssaidi@eecs.umich.edu    rlp.copyOut(tc->getMemProxy());
11905952Ssaidi@eecs.umich.edu    return 0;
11915952Ssaidi@eecs.umich.edu}
11925952Ssaidi@eecs.umich.edu
11935952Ssaidi@eecs.umich.edu/// Target gettimeofday() handler.
11945952Ssaidi@eecs.umich.edutemplate <class OS>
11955952Ssaidi@eecs.umich.eduSyscallReturn
11965952Ssaidi@eecs.umich.edugettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
11975952Ssaidi@eecs.umich.edu        ThreadContext *tc)
11985952Ssaidi@eecs.umich.edu{
11995952Ssaidi@eecs.umich.edu    int index = 0;
12005952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
12015952Ssaidi@eecs.umich.edu
12025952Ssaidi@eecs.umich.edu    getElapsedTime(tp->tv_sec, tp->tv_usec);
12035952Ssaidi@eecs.umich.edu    tp->tv_sec += seconds_since_epoch;
12045952Ssaidi@eecs.umich.edu    tp->tv_sec = TheISA::htog(tp->tv_sec);
12055952Ssaidi@eecs.umich.edu    tp->tv_usec = TheISA::htog(tp->tv_usec);
12065952Ssaidi@eecs.umich.edu
12075952Ssaidi@eecs.umich.edu    tp.copyOut(tc->getMemProxy());
12085952Ssaidi@eecs.umich.edu
12095952Ssaidi@eecs.umich.edu    return 0;
12105952Ssaidi@eecs.umich.edu}
12115952Ssaidi@eecs.umich.edu
12125952Ssaidi@eecs.umich.edu
12135952Ssaidi@eecs.umich.edu/// Target utimes() handler.
12145952Ssaidi@eecs.umich.edutemplate <class OS>
12155952Ssaidi@eecs.umich.eduSyscallReturn
12165952Ssaidi@eecs.umich.eduutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
12175952Ssaidi@eecs.umich.edu           ThreadContext *tc)
12185952Ssaidi@eecs.umich.edu{
12195952Ssaidi@eecs.umich.edu    std::string path;
12205952Ssaidi@eecs.umich.edu
12215952Ssaidi@eecs.umich.edu    int index = 0;
12225952Ssaidi@eecs.umich.edu    if (!tc->getMemProxy().tryReadString(path,
12235952Ssaidi@eecs.umich.edu                process->getSyscallArg(tc, index))) {
12245952Ssaidi@eecs.umich.edu        return -EFAULT;
12255952Ssaidi@eecs.umich.edu    }
12265952Ssaidi@eecs.umich.edu
12275952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::timeval [2]>
12285952Ssaidi@eecs.umich.edu        tp(process->getSyscallArg(tc, index));
12295952Ssaidi@eecs.umich.edu    tp.copyIn(tc->getMemProxy());
12305952Ssaidi@eecs.umich.edu
12315952Ssaidi@eecs.umich.edu    struct timeval hostTimeval[2];
12325952Ssaidi@eecs.umich.edu    for (int i = 0; i < 2; ++i)
12335952Ssaidi@eecs.umich.edu    {
12345952Ssaidi@eecs.umich.edu        hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
12355952Ssaidi@eecs.umich.edu        hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
12365952Ssaidi@eecs.umich.edu    }
12375952Ssaidi@eecs.umich.edu
12385952Ssaidi@eecs.umich.edu    // Adjust path for current working directory
12395952Ssaidi@eecs.umich.edu    path = process->fullPath(path);
12405952Ssaidi@eecs.umich.edu
12415952Ssaidi@eecs.umich.edu    int result = utimes(path.c_str(), hostTimeval);
12425952Ssaidi@eecs.umich.edu
12435952Ssaidi@eecs.umich.edu    if (result < 0)
12445952Ssaidi@eecs.umich.edu        return -errno;
12455952Ssaidi@eecs.umich.edu
12465952Ssaidi@eecs.umich.edu    return 0;
12475952Ssaidi@eecs.umich.edu}
12485952Ssaidi@eecs.umich.edu/// Target getrusage() function.
12495952Ssaidi@eecs.umich.edutemplate <class OS>
12505952Ssaidi@eecs.umich.eduSyscallReturn
12515952Ssaidi@eecs.umich.edugetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
12525952Ssaidi@eecs.umich.edu              ThreadContext *tc)
12535952Ssaidi@eecs.umich.edu{
12545952Ssaidi@eecs.umich.edu    int index = 0;
12555952Ssaidi@eecs.umich.edu    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
12565952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
12575952Ssaidi@eecs.umich.edu
12585952Ssaidi@eecs.umich.edu    rup->ru_utime.tv_sec = 0;
12595952Ssaidi@eecs.umich.edu    rup->ru_utime.tv_usec = 0;
12605952Ssaidi@eecs.umich.edu    rup->ru_stime.tv_sec = 0;
12615952Ssaidi@eecs.umich.edu    rup->ru_stime.tv_usec = 0;
12625952Ssaidi@eecs.umich.edu    rup->ru_maxrss = 0;
12635952Ssaidi@eecs.umich.edu    rup->ru_ixrss = 0;
12645952Ssaidi@eecs.umich.edu    rup->ru_idrss = 0;
12655952Ssaidi@eecs.umich.edu    rup->ru_isrss = 0;
12665952Ssaidi@eecs.umich.edu    rup->ru_minflt = 0;
12675952Ssaidi@eecs.umich.edu    rup->ru_majflt = 0;
12685952Ssaidi@eecs.umich.edu    rup->ru_nswap = 0;
12695952Ssaidi@eecs.umich.edu    rup->ru_inblock = 0;
12705952Ssaidi@eecs.umich.edu    rup->ru_oublock = 0;
12715952Ssaidi@eecs.umich.edu    rup->ru_msgsnd = 0;
12725952Ssaidi@eecs.umich.edu    rup->ru_msgrcv = 0;
12735952Ssaidi@eecs.umich.edu    rup->ru_nsignals = 0;
12745952Ssaidi@eecs.umich.edu    rup->ru_nvcsw = 0;
12755952Ssaidi@eecs.umich.edu    rup->ru_nivcsw = 0;
12765952Ssaidi@eecs.umich.edu
12775952Ssaidi@eecs.umich.edu    switch (who) {
12785952Ssaidi@eecs.umich.edu      case OS::TGT_RUSAGE_SELF:
12795952Ssaidi@eecs.umich.edu        getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
12805952Ssaidi@eecs.umich.edu        rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
12815952Ssaidi@eecs.umich.edu        rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
12825952Ssaidi@eecs.umich.edu        break;
12835952Ssaidi@eecs.umich.edu
12845952Ssaidi@eecs.umich.edu      case OS::TGT_RUSAGE_CHILDREN:
12855952Ssaidi@eecs.umich.edu        // do nothing.  We have no child processes, so they take no time.
12865952Ssaidi@eecs.umich.edu        break;
12875952Ssaidi@eecs.umich.edu
12885952Ssaidi@eecs.umich.edu      default:
12895952Ssaidi@eecs.umich.edu        // don't really handle THREAD or CHILDREN, but just warn and
12905952Ssaidi@eecs.umich.edu        // plow ahead
12915952Ssaidi@eecs.umich.edu        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
12925952Ssaidi@eecs.umich.edu             who);
12935952Ssaidi@eecs.umich.edu    }
12945952Ssaidi@eecs.umich.edu
12955952Ssaidi@eecs.umich.edu    rup.copyOut(tc->getMemProxy());
12965952Ssaidi@eecs.umich.edu
12975952Ssaidi@eecs.umich.edu    return 0;
12985952Ssaidi@eecs.umich.edu}
12995952Ssaidi@eecs.umich.edu
13005952Ssaidi@eecs.umich.edu/// Target times() function.
13015952Ssaidi@eecs.umich.edutemplate <class OS>
13025952Ssaidi@eecs.umich.eduSyscallReturn
13035952Ssaidi@eecs.umich.edutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
13045952Ssaidi@eecs.umich.edu           ThreadContext *tc)
13055952Ssaidi@eecs.umich.edu{
13065952Ssaidi@eecs.umich.edu    int index = 0;
13075952Ssaidi@eecs.umich.edu    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
13085952Ssaidi@eecs.umich.edu
13095952Ssaidi@eecs.umich.edu    // Fill in the time structure (in clocks)
13105952Ssaidi@eecs.umich.edu    int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
13115952Ssaidi@eecs.umich.edu    bufp->tms_utime = clocks;
13125952Ssaidi@eecs.umich.edu    bufp->tms_stime = 0;
13135952Ssaidi@eecs.umich.edu    bufp->tms_cutime = 0;
13145952Ssaidi@eecs.umich.edu    bufp->tms_cstime = 0;
13155952Ssaidi@eecs.umich.edu
13165952Ssaidi@eecs.umich.edu    // Convert to host endianness
13175952Ssaidi@eecs.umich.edu    bufp->tms_utime = TheISA::htog(bufp->tms_utime);
13185952Ssaidi@eecs.umich.edu
13195952Ssaidi@eecs.umich.edu    // Write back
13205952Ssaidi@eecs.umich.edu    bufp.copyOut(tc->getMemProxy());
13215952Ssaidi@eecs.umich.edu
13225952Ssaidi@eecs.umich.edu    // Return clock ticks since system boot
13235952Ssaidi@eecs.umich.edu    return clocks;
13245952Ssaidi@eecs.umich.edu}
13255952Ssaidi@eecs.umich.edu
13265952Ssaidi@eecs.umich.edu/// Target time() function.
13275952Ssaidi@eecs.umich.edutemplate <class OS>
13285952Ssaidi@eecs.umich.eduSyscallReturn
13295952Ssaidi@eecs.umich.edutimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
13305952Ssaidi@eecs.umich.edu           ThreadContext *tc)
13315952Ssaidi@eecs.umich.edu{
13325952Ssaidi@eecs.umich.edu    typename OS::time_t sec, usec;
13335952Ssaidi@eecs.umich.edu    getElapsedTime(sec, usec);
13345952Ssaidi@eecs.umich.edu    sec += seconds_since_epoch;
13355952Ssaidi@eecs.umich.edu
13365952Ssaidi@eecs.umich.edu    int index = 0;
13375952Ssaidi@eecs.umich.edu    Addr taddr = (Addr)process->getSyscallArg(tc, index);
13385952Ssaidi@eecs.umich.edu    if(taddr != 0) {
13395952Ssaidi@eecs.umich.edu        typename OS::time_t t = sec;
13405952Ssaidi@eecs.umich.edu        t = TheISA::htog(t);
13415952Ssaidi@eecs.umich.edu        SETranslatingPortProxy &p = tc->getMemProxy();
13425952Ssaidi@eecs.umich.edu        p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
13435952Ssaidi@eecs.umich.edu    }
13445952Ssaidi@eecs.umich.edu    return sec;
13455952Ssaidi@eecs.umich.edu}
13465952Ssaidi@eecs.umich.edu
13475952Ssaidi@eecs.umich.edu
13485952Ssaidi@eecs.umich.edu#endif // __SIM_SYSCALL_EMUL_HH__
13495952Ssaidi@eecs.umich.edu