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