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