syscall_emul.hh revision 6216
17405SAli.Saidi@ARM.com/* 211573SDylan.Johnson@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147405SAli.Saidi@ARM.com * this software without specific prior written permission. 157405SAli.Saidi@ARM.com * 167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277405SAli.Saidi@ARM.com * 287405SAli.Saidi@ARM.com * Authors: Steve Reinhardt 297405SAli.Saidi@ARM.com * Kevin Lim 307405SAli.Saidi@ARM.com */ 317405SAli.Saidi@ARM.com 327405SAli.Saidi@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__ 337405SAli.Saidi@ARM.com#define __SIM_SYSCALL_EMUL_HH__ 347405SAli.Saidi@ARM.com 357405SAli.Saidi@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 367405SAli.Saidi@ARM.com defined(__FreeBSD__) || defined(__CYGWIN__)) 377405SAli.Saidi@ARM.com 387405SAli.Saidi@ARM.com/// 397405SAli.Saidi@ARM.com/// @file syscall_emul.hh 407405SAli.Saidi@ARM.com/// 417405SAli.Saidi@ARM.com/// This file defines objects used to emulate syscalls from the target 4210461SAndreas.Sandberg@ARM.com/// application on the host machine. 439050Schander.sudanthi@arm.com 448887Sgeoffrey.blake@arm.com#include <errno.h> 4510461SAndreas.Sandberg@ARM.com#include <string> 468232Snate@binkert.org#ifdef __CYGWIN32__ 478232Snate@binkert.org#include <sys/fcntl.h> // for O_BINARY 4810844Sandreas.sandberg@arm.com#endif 499384SAndreas.Sandberg@arm.com#include <sys/stat.h> 507678Sgblack@eecs.umich.edu#include <fcntl.h> 518059SAli.Saidi@ARM.com#include <sys/uio.h> 528284SAli.Saidi@ARM.com 537405SAli.Saidi@ARM.com#include "base/chunk_generator.hh" 547405SAli.Saidi@ARM.com#include "base/intmath.hh" // for RoundUp 557405SAli.Saidi@ARM.com#include "base/misc.hh" 567405SAli.Saidi@ARM.com#include "base/trace.hh" 5710037SARM gem5 Developers#include "base/types.hh" 5810037SARM gem5 Developers#include "cpu/base.hh" 5911768SCurtis.Dunham@arm.com#include "cpu/thread_context.hh" 6010037SARM gem5 Developers#include "mem/translating_port.hh" 6110037SARM gem5 Developers#include "mem/page_table.hh" 6210037SARM gem5 Developers#include "sim/process.hh" 6310037SARM gem5 Developers 6411768SCurtis.Dunham@arm.com/// 6510037SARM gem5 Developers/// System call descriptor. 6610037SARM gem5 Developers/// 6711768SCurtis.Dunham@arm.comclass SyscallDesc { 6811768SCurtis.Dunham@arm.com 6911768SCurtis.Dunham@arm.com public: 7011768SCurtis.Dunham@arm.com 7111768SCurtis.Dunham@arm.com /// Typedef for target syscall handler functions. 7211768SCurtis.Dunham@arm.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 7311768SCurtis.Dunham@arm.com LiveProcess *, ThreadContext *); 7411768SCurtis.Dunham@arm.com 7511768SCurtis.Dunham@arm.com const char *name; //!< Syscall name (e.g., "open"). 7611768SCurtis.Dunham@arm.com FuncPtr funcPtr; //!< Pointer to emulation function. 7711768SCurtis.Dunham@arm.com int flags; //!< Flags (see Flags enum). 7811768SCurtis.Dunham@arm.com 7910037SARM gem5 Developers /// Flag values for controlling syscall behavior. 8010037SARM gem5 Developers enum Flags { 8110037SARM gem5 Developers /// Don't set return regs according to funcPtr return value. 8211768SCurtis.Dunham@arm.com /// Used for syscalls with non-standard return conventions 8311768SCurtis.Dunham@arm.com /// that explicitly set the ThreadContext regs (e.g., 8411768SCurtis.Dunham@arm.com /// sigreturn). 8511768SCurtis.Dunham@arm.com SuppressReturnValue = 1 8611768SCurtis.Dunham@arm.com }; 8711768SCurtis.Dunham@arm.com 8811768SCurtis.Dunham@arm.com /// Constructor. 8911768SCurtis.Dunham@arm.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9010037SARM gem5 Developers : name(_name), funcPtr(_funcPtr), flags(_flags) 9111768SCurtis.Dunham@arm.com { 9211768SCurtis.Dunham@arm.com } 9311768SCurtis.Dunham@arm.com 9411768SCurtis.Dunham@arm.com /// Emulate the syscall. Public interface for calling through funcPtr. 9510037SARM gem5 Developers void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 9611768SCurtis.Dunham@arm.com}; 9711768SCurtis.Dunham@arm.com 9811768SCurtis.Dunham@arm.com 9911768SCurtis.Dunham@arm.comclass BaseBufferArg { 10011768SCurtis.Dunham@arm.com 10111768SCurtis.Dunham@arm.com public: 10211768SCurtis.Dunham@arm.com 10311768SCurtis.Dunham@arm.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 10411768SCurtis.Dunham@arm.com { 10511768SCurtis.Dunham@arm.com bufPtr = new uint8_t[size]; 10611768SCurtis.Dunham@arm.com // clear out buffer: in case we only partially populate this, 10711768SCurtis.Dunham@arm.com // and then do a copyOut(), we want to make sure we don't 10811768SCurtis.Dunham@arm.com // introduce any random junk into the simulated address space 10911768SCurtis.Dunham@arm.com memset(bufPtr, 0, size); 11011768SCurtis.Dunham@arm.com } 11111768SCurtis.Dunham@arm.com 11211768SCurtis.Dunham@arm.com virtual ~BaseBufferArg() { delete [] bufPtr; } 11311768SCurtis.Dunham@arm.com 11410037SARM gem5 Developers // 11511768SCurtis.Dunham@arm.com // copy data into simulator space (read from target memory) 11611768SCurtis.Dunham@arm.com // 11711768SCurtis.Dunham@arm.com virtual bool copyIn(TranslatingPort *memport) 11811768SCurtis.Dunham@arm.com { 11910037SARM gem5 Developers memport->readBlob(addr, bufPtr, size); 12011768SCurtis.Dunham@arm.com return true; // no EFAULT detection for now 12111768SCurtis.Dunham@arm.com } 12211768SCurtis.Dunham@arm.com 12311768SCurtis.Dunham@arm.com // 12411768SCurtis.Dunham@arm.com // copy data out of simulator space (write to target memory) 12511768SCurtis.Dunham@arm.com // 12610037SARM gem5 Developers virtual bool copyOut(TranslatingPort *memport) 12711768SCurtis.Dunham@arm.com { 12811768SCurtis.Dunham@arm.com memport->writeBlob(addr, bufPtr, size); 12911768SCurtis.Dunham@arm.com return true; // no EFAULT detection for now 13011768SCurtis.Dunham@arm.com } 13111768SCurtis.Dunham@arm.com 13211768SCurtis.Dunham@arm.com protected: 13311768SCurtis.Dunham@arm.com Addr addr; 13411768SCurtis.Dunham@arm.com int size; 13511768SCurtis.Dunham@arm.com uint8_t *bufPtr; 13611768SCurtis.Dunham@arm.com}; 13711768SCurtis.Dunham@arm.com 13811768SCurtis.Dunham@arm.com 13911768SCurtis.Dunham@arm.comclass BufferArg : public BaseBufferArg 14011768SCurtis.Dunham@arm.com{ 14111768SCurtis.Dunham@arm.com public: 14211768SCurtis.Dunham@arm.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 14311768SCurtis.Dunham@arm.com void *bufferPtr() { return bufPtr; } 14411768SCurtis.Dunham@arm.com}; 14511768SCurtis.Dunham@arm.com 14611768SCurtis.Dunham@arm.comtemplate <class T> 14711768SCurtis.Dunham@arm.comclass TypedBufferArg : public BaseBufferArg 14811768SCurtis.Dunham@arm.com{ 14911768SCurtis.Dunham@arm.com public: 15011768SCurtis.Dunham@arm.com // user can optionally specify a specific number of bytes to 15111768SCurtis.Dunham@arm.com // allocate to deal with those structs that have variable-size 15211768SCurtis.Dunham@arm.com // arrays at the end 15311768SCurtis.Dunham@arm.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 15411768SCurtis.Dunham@arm.com : BaseBufferArg(_addr, _size) 15511768SCurtis.Dunham@arm.com { } 15611768SCurtis.Dunham@arm.com 15711768SCurtis.Dunham@arm.com // type case 15811768SCurtis.Dunham@arm.com operator T*() { return (T *)bufPtr; } 15911768SCurtis.Dunham@arm.com 16011768SCurtis.Dunham@arm.com // dereference operators 16111768SCurtis.Dunham@arm.com T &operator*() { return *((T *)bufPtr); } 16211768SCurtis.Dunham@arm.com T* operator->() { return (T *)bufPtr; } 16311768SCurtis.Dunham@arm.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 16411768SCurtis.Dunham@arm.com}; 16511768SCurtis.Dunham@arm.com 16611768SCurtis.Dunham@arm.com////////////////////////////////////////////////////////////////////// 16711768SCurtis.Dunham@arm.com// 16811768SCurtis.Dunham@arm.com// The following emulation functions are generic enough that they 16911768SCurtis.Dunham@arm.com// don't need to be recompiled for different emulated OS's. They are 17011768SCurtis.Dunham@arm.com// defined in sim/syscall_emul.cc. 17111768SCurtis.Dunham@arm.com// 17211768SCurtis.Dunham@arm.com////////////////////////////////////////////////////////////////////// 17311768SCurtis.Dunham@arm.com 17411768SCurtis.Dunham@arm.com 17511768SCurtis.Dunham@arm.com/// Handler for unimplemented syscalls that we haven't thought about. 17611768SCurtis.Dunham@arm.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 17711768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 17811768SCurtis.Dunham@arm.com 17911768SCurtis.Dunham@arm.com/// Handler for unimplemented syscalls that we never intend to 18011768SCurtis.Dunham@arm.com/// implement (signal handling, etc.) and should not affect the correct 18111768SCurtis.Dunham@arm.com/// behavior of the program. Print a warning only if the appropriate 18211768SCurtis.Dunham@arm.com/// trace flag is enabled. Return success to the target program. 18311768SCurtis.Dunham@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 18411768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 18511768SCurtis.Dunham@arm.com 18611768SCurtis.Dunham@arm.com/// Target exit() handler: terminate current context. 18711768SCurtis.Dunham@arm.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 18811768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 18911768SCurtis.Dunham@arm.com 19011768SCurtis.Dunham@arm.com/// Target exit_group() handler: terminate simulation. (exit all threads) 19111768SCurtis.Dunham@arm.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 19211768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 19311768SCurtis.Dunham@arm.com 19411768SCurtis.Dunham@arm.com/// Target getpagesize() handler. 19511768SCurtis.Dunham@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 19611768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 19711768SCurtis.Dunham@arm.com 19811768SCurtis.Dunham@arm.com/// Target brk() handler: set brk address. 19911768SCurtis.Dunham@arm.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 20011768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 20111768SCurtis.Dunham@arm.com 20211768SCurtis.Dunham@arm.com/// Target close() handler. 20311768SCurtis.Dunham@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 20410037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 20510037SARM gem5 Developers 20610037SARM gem5 Developers/// Target read() handler. 2079384SAndreas.Sandberg@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num, 20810461SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 20910461SAndreas.Sandberg@ARM.com 21011165SRekai.GonzalezAlberquilla@arm.com/// Target write() handler. 21110461SAndreas.Sandberg@ARM.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 21210461SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2139384SAndreas.Sandberg@arm.com 2149384SAndreas.Sandberg@arm.com/// Target lseek() handler. 2159384SAndreas.Sandberg@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 2169384SAndreas.Sandberg@arm.com LiveProcess *p, ThreadContext *tc); 21710037SARM gem5 Developers 21810461SAndreas.Sandberg@ARM.com/// Target _llseek() handler. 21910461SAndreas.Sandberg@ARM.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 22010461SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 22110461SAndreas.Sandberg@ARM.com 22210461SAndreas.Sandberg@ARM.com/// Target munmap() handler. 22310461SAndreas.Sandberg@ARM.comSyscallReturn munmapFunc(SyscallDesc *desc, int num, 22410609Sandreas.sandberg@arm.com LiveProcess *p, ThreadContext *tc); 22510609Sandreas.sandberg@arm.com 22610609Sandreas.sandberg@arm.com/// Target gethostname() handler. 22710037SARM gem5 DevelopersSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 22810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 22910037SARM gem5 Developers 23010037SARM gem5 Developers/// Target getcwd() handler. 23110037SARM gem5 DevelopersSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 23210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23310037SARM gem5 Developers 23410037SARM gem5 Developers/// Target unlink() handler. 23510037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 23610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23710037SARM gem5 Developers 23810037SARM gem5 Developers/// Target unlink() handler. 23910037SARM gem5 DevelopersSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 24010037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24110037SARM gem5 Developers 24210037SARM gem5 Developers/// Target mkdir() handler. 24311768SCurtis.Dunham@arm.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 24411768SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 24510037SARM gem5 Developers 24610037SARM gem5 Developers/// Target rename() handler. 24710037SARM gem5 DevelopersSyscallReturn renameFunc(SyscallDesc *desc, int num, 24810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 2499384SAndreas.Sandberg@arm.com 2509384SAndreas.Sandberg@arm.com 2519384SAndreas.Sandberg@arm.com/// Target truncate() handler. 2529384SAndreas.Sandberg@arm.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 2539384SAndreas.Sandberg@arm.com LiveProcess *p, ThreadContext *tc); 2549384SAndreas.Sandberg@arm.com 2559384SAndreas.Sandberg@arm.com 2569384SAndreas.Sandberg@arm.com/// Target ftruncate() handler. 2579384SAndreas.Sandberg@arm.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2587427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2597427Sgblack@eecs.umich.edu 2607427Sgblack@eecs.umich.edu 2619385SAndreas.Sandberg@arm.com/// Target umask() handler. 2629385SAndreas.Sandberg@arm.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 2637427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2647427Sgblack@eecs.umich.edu 26510037SARM gem5 Developers 26610037SARM gem5 Developers/// Target chown() handler. 26710037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num, 26810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26910037SARM gem5 Developers 27010037SARM gem5 Developers 27110037SARM gem5 Developers/// Target fchown() handler. 27210037SARM gem5 DevelopersSyscallReturn fchownFunc(SyscallDesc *desc, int num, 27310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27410037SARM gem5 Developers 27510037SARM gem5 Developers/// Target dup() handler. 27610037SARM gem5 DevelopersSyscallReturn dupFunc(SyscallDesc *desc, int num, 27710037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 27810037SARM gem5 Developers 2797427Sgblack@eecs.umich.edu/// Target fnctl() handler. 2807427Sgblack@eecs.umich.eduSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2817427Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 2827427Sgblack@eecs.umich.edu 2837427Sgblack@eecs.umich.edu/// Target fcntl64() handler. 2847427Sgblack@eecs.umich.eduSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 28510037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 28610037SARM gem5 Developers 28710037SARM gem5 Developers/// Target setuid() handler. 28810037SARM gem5 DevelopersSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2897427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2907427Sgblack@eecs.umich.edu 2917427Sgblack@eecs.umich.edu/// Target getpid() handler. 29210037SARM gem5 DevelopersSyscallReturn getpidFunc(SyscallDesc *desc, int num, 29310204SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 29410204SAli.Saidi@ARM.com 29510037SARM gem5 Developers/// Target getuid() handler. 2967427Sgblack@eecs.umich.eduSyscallReturn getuidFunc(SyscallDesc *desc, int num, 29710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 2987427Sgblack@eecs.umich.edu 29910037SARM gem5 Developers/// Target getgid() handler. 3007427Sgblack@eecs.umich.eduSyscallReturn getgidFunc(SyscallDesc *desc, int num, 3017427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 30210037SARM gem5 Developers 3037427Sgblack@eecs.umich.edu/// Target getppid() handler. 3047427Sgblack@eecs.umich.eduSyscallReturn getppidFunc(SyscallDesc *desc, int num, 3057427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3067427Sgblack@eecs.umich.edu 3077427Sgblack@eecs.umich.edu/// Target geteuid() handler. 3087427Sgblack@eecs.umich.eduSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 3097427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3107427Sgblack@eecs.umich.edu 3117427Sgblack@eecs.umich.edu/// Target getegid() handler. 3127427Sgblack@eecs.umich.eduSyscallReturn getegidFunc(SyscallDesc *desc, int num, 3137427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3147427Sgblack@eecs.umich.edu 3157427Sgblack@eecs.umich.edu/// Target clone() handler. 3167427Sgblack@eecs.umich.eduSyscallReturn cloneFunc(SyscallDesc *desc, int num, 3177427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3187427Sgblack@eecs.umich.edu 3197427Sgblack@eecs.umich.edu 3207427Sgblack@eecs.umich.edu/// Pseudo Funcs - These functions use a different return convension, 3217427Sgblack@eecs.umich.edu/// returning a second value in a register other than the normal return register 3227427Sgblack@eecs.umich.eduSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 3237427Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3247427Sgblack@eecs.umich.edu 3257427Sgblack@eecs.umich.edu/// Target getpidPseudo() handler. 3267436Sdam.sunwoo@arm.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 3277436Sdam.sunwoo@arm.com LiveProcess *p, ThreadContext *tc); 32810037SARM gem5 Developers 32910037SARM gem5 Developers/// Target getuidPseudo() handler. 3307436Sdam.sunwoo@arm.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 3317436Sdam.sunwoo@arm.com LiveProcess *p, ThreadContext *tc); 3327436Sdam.sunwoo@arm.com 3337436Sdam.sunwoo@arm.com/// Target getgidPseudo() handler. 3347436Sdam.sunwoo@arm.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 3357436Sdam.sunwoo@arm.com LiveProcess *p, ThreadContext *tc); 3367436Sdam.sunwoo@arm.com 3377436Sdam.sunwoo@arm.com 3387436Sdam.sunwoo@arm.com/// A readable name for 1,000,000, for converting microseconds to seconds. 3397436Sdam.sunwoo@arm.comconst int one_million = 1000000; 3407436Sdam.sunwoo@arm.com 3417436Sdam.sunwoo@arm.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 34210037SARM gem5 Developers/// by my reckoning. We want to keep this a constant (not use the 3437436Sdam.sunwoo@arm.com/// real-world time) to keep simulations repeatable. 3447436Sdam.sunwoo@arm.comconst unsigned seconds_since_epoch = 1000000000; 3457436Sdam.sunwoo@arm.com 3467436Sdam.sunwoo@arm.com/// Helper function to convert current elapsed time to seconds and 3477436Sdam.sunwoo@arm.com/// microseconds. 3487436Sdam.sunwoo@arm.comtemplate <class T1, class T2> 3497436Sdam.sunwoo@arm.comvoid 3507436Sdam.sunwoo@arm.comgetElapsedTime(T1 &sec, T2 &usec) 3517436Sdam.sunwoo@arm.com{ 3527436Sdam.sunwoo@arm.com int elapsed_usecs = curTick / Clock::Int::us; 3537436Sdam.sunwoo@arm.com sec = elapsed_usecs / one_million; 3547436Sdam.sunwoo@arm.com usec = elapsed_usecs % one_million; 3557436Sdam.sunwoo@arm.com} 3567436Sdam.sunwoo@arm.com 3577436Sdam.sunwoo@arm.com////////////////////////////////////////////////////////////////////// 3587436Sdam.sunwoo@arm.com// 3597644Sali.saidi@arm.com// The following emulation functions are generic, but need to be 3608147SAli.Saidi@ARM.com// templated to account for differences in types, constants, etc. 3619385SAndreas.Sandberg@arm.com// 3629385SAndreas.Sandberg@arm.com////////////////////////////////////////////////////////////////////// 3639385SAndreas.Sandberg@arm.com 3649385SAndreas.Sandberg@arm.com#if NO_STAT64 3659385SAndreas.Sandberg@arm.com typedef struct stat hst_stat; 3669385SAndreas.Sandberg@arm.com typedef struct stat hst_stat64; 3679385SAndreas.Sandberg@arm.com#else 3689385SAndreas.Sandberg@arm.com typedef struct stat hst_stat; 3699385SAndreas.Sandberg@arm.com typedef struct stat64 hst_stat64; 3709385SAndreas.Sandberg@arm.com#endif 3719385SAndreas.Sandberg@arm.com 3729385SAndreas.Sandberg@arm.com//// Helper function to convert a host stat buffer to a target stat 3739385SAndreas.Sandberg@arm.com//// buffer. Also copies the target buffer out to the simulated 3749385SAndreas.Sandberg@arm.com//// memory space. Used by stat(), fstat(), and lstat(). 3759385SAndreas.Sandberg@arm.com 3769385SAndreas.Sandberg@arm.comtemplate <typename target_stat, typename host_stat> 3779385SAndreas.Sandberg@arm.comstatic void 3789385SAndreas.Sandberg@arm.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 37910037SARM gem5 Developers{ 38010037SARM gem5 Developers using namespace TheISA; 38110037SARM gem5 Developers 38210037SARM gem5 Developers if (fakeTTY) 38310037SARM gem5 Developers tgt->st_dev = 0xA; 38410037SARM gem5 Developers else 38510037SARM gem5 Developers tgt->st_dev = host->st_dev; 38610037SARM gem5 Developers tgt->st_dev = htog(tgt->st_dev); 38710037SARM gem5 Developers tgt->st_ino = host->st_ino; 38810037SARM gem5 Developers tgt->st_ino = htog(tgt->st_ino); 38910037SARM gem5 Developers tgt->st_mode = host->st_mode; 39010037SARM gem5 Developers if (fakeTTY) { 39110037SARM gem5 Developers // Claim to be a character device 39210037SARM gem5 Developers tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 39310037SARM gem5 Developers tgt->st_mode |= S_IFCHR; // Set S_IFCHR 39410037SARM gem5 Developers } 3958147SAli.Saidi@ARM.com tgt->st_mode = htog(tgt->st_mode); 3967427Sgblack@eecs.umich.edu tgt->st_nlink = host->st_nlink; 3977427Sgblack@eecs.umich.edu tgt->st_nlink = htog(tgt->st_nlink); 3987427Sgblack@eecs.umich.edu tgt->st_uid = host->st_uid; 39910037SARM gem5 Developers tgt->st_uid = htog(tgt->st_uid); 40010037SARM gem5 Developers tgt->st_gid = host->st_gid; 40110037SARM gem5 Developers tgt->st_gid = htog(tgt->st_gid); 40210037SARM gem5 Developers if (fakeTTY) 40310037SARM gem5 Developers tgt->st_rdev = 0x880d; 40410037SARM gem5 Developers else 40510037SARM gem5 Developers tgt->st_rdev = host->st_rdev; 40610037SARM gem5 Developers tgt->st_rdev = htog(tgt->st_rdev); 40710037SARM gem5 Developers tgt->st_size = host->st_size; 40810037SARM gem5 Developers tgt->st_size = htog(tgt->st_size); 40910037SARM gem5 Developers tgt->st_atimeX = host->st_atime; 41010037SARM gem5 Developers tgt->st_atimeX = htog(tgt->st_atimeX); 41110037SARM gem5 Developers tgt->st_mtimeX = host->st_mtime; 41210037SARM gem5 Developers tgt->st_mtimeX = htog(tgt->st_mtimeX); 41310037SARM gem5 Developers tgt->st_ctimeX = host->st_ctime; 41410037SARM gem5 Developers tgt->st_ctimeX = htog(tgt->st_ctimeX); 41510037SARM gem5 Developers // Force the block size to be 8k. This helps to ensure buffered io works 41610037SARM gem5 Developers // consistently across different hosts. 41710037SARM gem5 Developers tgt->st_blksize = 0x2000; 41810037SARM gem5 Developers tgt->st_blksize = htog(tgt->st_blksize); 41910037SARM gem5 Developers tgt->st_blocks = host->st_blocks; 42010037SARM gem5 Developers tgt->st_blocks = htog(tgt->st_blocks); 42110037SARM gem5 Developers} 42210037SARM gem5 Developers 42310037SARM gem5 Developers// Same for stat64 42410037SARM gem5 Developers 42510037SARM gem5 Developerstemplate <typename target_stat, typename host_stat64> 42610037SARM gem5 Developersstatic void 42710037SARM gem5 DevelopersconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 42810037SARM gem5 Developers{ 42910037SARM gem5 Developers using namespace TheISA; 43010037SARM gem5 Developers 43110037SARM gem5 Developers convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 43210037SARM gem5 Developers#if defined(STAT_HAVE_NSEC) 43310037SARM gem5 Developers tgt->st_atime_nsec = host->st_atime_nsec; 43410037SARM gem5 Developers tgt->st_atime_nsec = htog(tgt->st_atime_nsec); 43510037SARM gem5 Developers tgt->st_mtime_nsec = host->st_mtime_nsec; 43610037SARM gem5 Developers tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec); 43711574SCurtis.Dunham@arm.com tgt->st_ctime_nsec = host->st_ctime_nsec; 43811574SCurtis.Dunham@arm.com tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec); 43910037SARM gem5 Developers#else 44010037SARM gem5 Developers tgt->st_atime_nsec = 0; 44110037SARM gem5 Developers tgt->st_mtime_nsec = 0; 44210037SARM gem5 Developers tgt->st_ctime_nsec = 0; 44310037SARM gem5 Developers#endif 44410037SARM gem5 Developers} 44510037SARM gem5 Developers 44610037SARM gem5 Developers//Here are a couple convenience functions 44710037SARM gem5 Developerstemplate<class OS> 44810461SAndreas.Sandberg@ARM.comstatic void 44910461SAndreas.Sandberg@ARM.comcopyOutStatBuf(TranslatingPort * mem, Addr addr, 45010461SAndreas.Sandberg@ARM.com hst_stat *host, bool fakeTTY = false) 45110461SAndreas.Sandberg@ARM.com{ 45210037SARM gem5 Developers typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 45310037SARM gem5 Developers tgt_stat_buf tgt(addr); 45410037SARM gem5 Developers convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 45510037SARM gem5 Developers tgt.copyOut(mem); 45610037SARM gem5 Developers} 45710037SARM gem5 Developers 45810037SARM gem5 Developerstemplate<class OS> 45910037SARM gem5 Developersstatic void 46010461SAndreas.Sandberg@ARM.comcopyOutStat64Buf(TranslatingPort * mem, Addr addr, 46110461SAndreas.Sandberg@ARM.com hst_stat64 *host, bool fakeTTY = false) 46210461SAndreas.Sandberg@ARM.com{ 46310461SAndreas.Sandberg@ARM.com typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 46410461SAndreas.Sandberg@ARM.com tgt_stat_buf tgt(addr); 46510037SARM gem5 Developers convertStatBuf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 46610037SARM gem5 Developers tgt.copyOut(mem); 46710037SARM gem5 Developers} 46810037SARM gem5 Developers 46910037SARM gem5 Developers/// Target ioctl() handler. For the most part, programs call ioctl() 47011574SCurtis.Dunham@arm.com/// only to find out if their stdout is a tty, to determine whether to 47110037SARM gem5 Developers/// do line or block buffering. 47210037SARM gem5 Developerstemplate <class OS> 47310037SARM gem5 DevelopersSyscallReturn 47411574SCurtis.Dunham@arm.comioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 47510037SARM gem5 Developers ThreadContext *tc) 47610037SARM gem5 Developers{ 47710037SARM gem5 Developers int fd = process->getSyscallArg(tc, 0); 47810037SARM gem5 Developers unsigned req = process->getSyscallArg(tc, 1); 47910037SARM gem5 Developers 48010037SARM gem5 Developers DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 48110037SARM gem5 Developers 48210037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 48310037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 48410037SARM gem5 Developers return -EBADF; 4857405SAli.Saidi@ARM.com } 48610035Sandreas.hansson@arm.com 4877405SAli.Saidi@ARM.com switch (req) { 4887405SAli.Saidi@ARM.com case OS::TIOCISATTY_: 4897614Sminkyu.jeong@arm.com case OS::TIOCGETP_: 49010037SARM gem5 Developers case OS::TIOCSETP_: 49110037SARM gem5 Developers case OS::TIOCSETN_: 49210037SARM gem5 Developers case OS::TIOCSETC_: 4937614Sminkyu.jeong@arm.com case OS::TIOCGETC_: 49410037SARM gem5 Developers case OS::TIOCGETS_: 49510037SARM gem5 Developers case OS::TIOCGETA_: 49610037SARM gem5 Developers return -ENOTTY; 49710037SARM gem5 Developers 49810037SARM gem5 Developers default: 49910037SARM gem5 Developers fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 50010037SARM gem5 Developers fd, req, tc->readPC()); 50110037SARM gem5 Developers } 50210037SARM gem5 Developers} 50310037SARM gem5 Developers 50410037SARM gem5 Developers/// Target open() handler. 50510037SARM gem5 Developerstemplate <class OS> 50610037SARM gem5 DevelopersSyscallReturn 50710037SARM gem5 DevelopersopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5087614Sminkyu.jeong@arm.com ThreadContext *tc) 5097405SAli.Saidi@ARM.com{ 5107405SAli.Saidi@ARM.com std::string path; 5117405SAli.Saidi@ARM.com 5127405SAli.Saidi@ARM.com if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 5137405SAli.Saidi@ARM.com return -EFAULT; 5147405SAli.Saidi@ARM.com 51510037SARM gem5 Developers if (path == "/dev/sysdev0") { 51610037SARM gem5 Developers // This is a memory-mapped high-resolution timer device on Alpha. 51710037SARM gem5 Developers // We don't support it, so just punt. 5189050Schander.sudanthi@arm.com warn("Ignoring open(%s, ...)\n", path); 5197405SAli.Saidi@ARM.com return -ENOENT; 52010037SARM gem5 Developers } 52110037SARM gem5 Developers 5227720Sgblack@eecs.umich.edu int tgtFlags = process->getSyscallArg(tc, 1); 5237720Sgblack@eecs.umich.edu int mode = process->getSyscallArg(tc, 2); 5247405SAli.Saidi@ARM.com int hostFlags = 0; 5257405SAli.Saidi@ARM.com 5267757SAli.Saidi@ARM.com // translate open flags 52710037SARM gem5 Developers for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 52810037SARM gem5 Developers if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 52910037SARM gem5 Developers tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 53010037SARM gem5 Developers hostFlags |= OS::openFlagTable[i].hostFlag; 53110037SARM gem5 Developers } 53210037SARM gem5 Developers } 53310037SARM gem5 Developers 53410037SARM gem5 Developers // any target flags left? 53510037SARM gem5 Developers if (tgtFlags != 0) 53610037SARM gem5 Developers warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 53710037SARM gem5 Developers 53810037SARM gem5 Developers#ifdef __CYGWIN32__ 53910037SARM gem5 Developers hostFlags |= O_BINARY; 54010037SARM gem5 Developers#endif 54110037SARM gem5 Developers 54210037SARM gem5 Developers // Adjust path for current working directory 54310037SARM gem5 Developers path = process->fullPath(path); 54410037SARM gem5 Developers 54510037SARM gem5 Developers DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 54610037SARM gem5 Developers 54710037SARM gem5 Developers int fd; 54810037SARM gem5 Developers if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 54910037SARM gem5 Developers !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 55010037SARM gem5 Developers // It's a proc/sys entery and requires special handling 55110037SARM gem5 Developers fd = OS::openSpecialFile(path, process, tc); 55210037SARM gem5 Developers return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 55310037SARM gem5 Developers } else { 55410037SARM gem5 Developers // open the file 55510037SARM gem5 Developers fd = open(path.c_str(), hostFlags, mode); 55610037SARM gem5 Developers return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 55710037SARM gem5 Developers } 55810037SARM gem5 Developers 55910037SARM gem5 Developers} 56010037SARM gem5 Developers 56110037SARM gem5 Developers 56210037SARM gem5 Developers/// Target chmod() handler. 56310037SARM gem5 Developerstemplate <class OS> 56410037SARM gem5 DevelopersSyscallReturn 56510037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 56610037SARM gem5 Developers ThreadContext *tc) 56710037SARM gem5 Developers{ 56810037SARM gem5 Developers std::string path; 56910037SARM gem5 Developers 57010037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 57110037SARM gem5 Developers return -EFAULT; 57210037SARM gem5 Developers 5738284SAli.Saidi@ARM.com uint32_t mode = process->getSyscallArg(tc, 1); 57410037SARM gem5 Developers mode_t hostMode = 0; 57510037SARM gem5 Developers 57610037SARM gem5 Developers // XXX translate mode flags via OS::something??? 57710037SARM gem5 Developers hostMode = mode; 5789050Schander.sudanthi@arm.com 57910037SARM gem5 Developers // Adjust path for current working directory 58010037SARM gem5 Developers path = process->fullPath(path); 58110037SARM gem5 Developers 58210037SARM gem5 Developers // do the chmod 58310037SARM gem5 Developers int result = chmod(path.c_str(), hostMode); 58410037SARM gem5 Developers if (result < 0) 58510037SARM gem5 Developers return -errno; 58610037SARM gem5 Developers 58710037SARM gem5 Developers return 0; 58810037SARM gem5 Developers} 58910037SARM gem5 Developers 59010037SARM gem5 Developers 59110037SARM gem5 Developers/// Target fchmod() handler. 59210037SARM gem5 Developerstemplate <class OS> 59310037SARM gem5 DevelopersSyscallReturn 59410037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 59510037SARM gem5 Developers ThreadContext *tc) 59610037SARM gem5 Developers{ 5979050Schander.sudanthi@arm.com int fd = process->getSyscallArg(tc, 0); 5988284SAli.Saidi@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 59910037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 60010037SARM gem5 Developers return -EBADF; 60110037SARM gem5 Developers } 60210037SARM gem5 Developers 60310037SARM gem5 Developers uint32_t mode = process->getSyscallArg(tc, 1); 60410037SARM gem5 Developers mode_t hostMode = 0; 60510037SARM gem5 Developers 6067405SAli.Saidi@ARM.com // XXX translate mode flags via OS::someting??? 6077731SAli.Saidi@ARM.com hostMode = mode; 6088468Swade.walker@arm.com 6098468Swade.walker@arm.com // do the fchmod 6108468Swade.walker@arm.com int result = fchmod(process->sim_fd(fd), hostMode); 6117405SAli.Saidi@ARM.com if (result < 0) 6127731SAli.Saidi@ARM.com return -errno; 6137405SAli.Saidi@ARM.com 6147405SAli.Saidi@ARM.com return 0; 6157583SAli.Saidi@arm.com} 6169130Satgutier@umich.edu 6179130Satgutier@umich.edu/// Target mremap() handler. 6189130Satgutier@umich.edutemplate <class OS> 6199130Satgutier@umich.eduSyscallReturn 6209814Sandreas.hansson@arm.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 6219130Satgutier@umich.edu{ 6229130Satgutier@umich.edu Addr start = process->getSyscallArg(tc, 0); 6239130Satgutier@umich.edu uint64_t old_length = process->getSyscallArg(tc, 1); 6249130Satgutier@umich.edu uint64_t new_length = process->getSyscallArg(tc, 2); 6259130Satgutier@umich.edu uint64_t flags = process->getSyscallArg(tc, 3); 6269130Satgutier@umich.edu 6279130Satgutier@umich.edu if ((start % TheISA::VMPageSize != 0) || 6289130Satgutier@umich.edu (new_length % TheISA::VMPageSize != 0)) { 6299130Satgutier@umich.edu warn("mremap failing: arguments not page aligned"); 6309130Satgutier@umich.edu return -EINVAL; 6319130Satgutier@umich.edu } 6329130Satgutier@umich.edu 6339130Satgutier@umich.edu if (new_length > old_length) { 6349130Satgutier@umich.edu if ((start + old_length) == process->mmap_end) { 6359130Satgutier@umich.edu uint64_t diff = new_length - old_length; 6369130Satgutier@umich.edu process->pTable->allocate(process->mmap_end, diff); 6379130Satgutier@umich.edu process->mmap_end += diff; 6389130Satgutier@umich.edu return start; 6399130Satgutier@umich.edu } else { 6409130Satgutier@umich.edu // sys/mman.h defined MREMAP_MAYMOVE 6419130Satgutier@umich.edu if (!(flags & 1)) { 6429130Satgutier@umich.edu warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 6437583SAli.Saidi@arm.com return -ENOMEM; 6447583SAli.Saidi@arm.com } else { 6457583SAli.Saidi@arm.com process->pTable->remap(start, old_length, process->mmap_end); 64610461SAndreas.Sandberg@ARM.com warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 64710461SAndreas.Sandberg@ARM.com process->mmap_end, process->mmap_end + new_length, new_length); 64810461SAndreas.Sandberg@ARM.com start = process->mmap_end; 64910461SAndreas.Sandberg@ARM.com // add on the remaining unallocated pages 65010461SAndreas.Sandberg@ARM.com process->pTable->allocate(start + old_length, new_length - old_length); 65110461SAndreas.Sandberg@ARM.com process->mmap_end += new_length; 65210461SAndreas.Sandberg@ARM.com warn("returning %08p as start\n", start); 6538302SAli.Saidi@ARM.com return start; 6548302SAli.Saidi@ARM.com } 6557783SGiacomo.Gabrielli@arm.com } 6567783SGiacomo.Gabrielli@arm.com } else { 6577783SGiacomo.Gabrielli@arm.com process->pTable->deallocate(start + new_length, old_length - 6587783SGiacomo.Gabrielli@arm.com new_length); 65910037SARM gem5 Developers return start; 66010037SARM gem5 Developers } 66110037SARM gem5 Developers} 66210037SARM gem5 Developers 66310037SARM gem5 Developers/// Target stat() handler. 66410037SARM gem5 Developerstemplate <class OS> 66510037SARM gem5 DevelopersSyscallReturn 66610037SARM gem5 DevelopersstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 66710037SARM gem5 Developers ThreadContext *tc) 66810037SARM gem5 Developers{ 66910037SARM gem5 Developers std::string path; 67010037SARM gem5 Developers 67110037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 67210037SARM gem5 Developers return -EFAULT; 67310037SARM gem5 Developers 67410037SARM gem5 Developers // Adjust path for current working directory 67510037SARM gem5 Developers path = process->fullPath(path); 67610037SARM gem5 Developers 67710037SARM gem5 Developers struct stat hostBuf; 67810037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 67910037SARM gem5 Developers 68010037SARM gem5 Developers if (result < 0) 68110037SARM gem5 Developers return -errno; 68210037SARM gem5 Developers 68310037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 68410037SARM gem5 Developers &hostBuf); 68510037SARM gem5 Developers 68610037SARM gem5 Developers return 0; 68710037SARM gem5 Developers} 68810037SARM gem5 Developers 68910037SARM gem5 Developers 69010037SARM gem5 Developers/// Target stat64() handler. 69110037SARM gem5 Developerstemplate <class OS> 69210037SARM gem5 DevelopersSyscallReturn 69310037SARM gem5 Developersstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 69410037SARM gem5 Developers ThreadContext *tc) 69510037SARM gem5 Developers{ 69610037SARM gem5 Developers std::string path; 69710338SCurtis.Dunham@arm.com 69810338SCurtis.Dunham@arm.com if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 69910338SCurtis.Dunham@arm.com return -EFAULT; 70010037SARM gem5 Developers 70110037SARM gem5 Developers // Adjust path for current working directory 70210037SARM gem5 Developers path = process->fullPath(path); 70310037SARM gem5 Developers 70410037SARM gem5 Developers#if NO_STAT64 70510037SARM gem5 Developers struct stat hostBuf; 70610037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 70710037SARM gem5 Developers#else 70810037SARM gem5 Developers struct stat64 hostBuf; 70910037SARM gem5 Developers int result = stat64(path.c_str(), &hostBuf); 71010037SARM gem5 Developers#endif 71110037SARM gem5 Developers 71210037SARM gem5 Developers if (result < 0) 71310037SARM gem5 Developers return -errno; 71410037SARM gem5 Developers 71510037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 71610037SARM gem5 Developers &hostBuf); 71710037SARM gem5 Developers 71810037SARM gem5 Developers return 0; 71910037SARM gem5 Developers} 72010037SARM gem5 Developers 72110037SARM gem5 Developers 72210037SARM gem5 Developers/// Target fstat64() handler. 72310037SARM gem5 Developerstemplate <class OS> 72410037SARM gem5 DevelopersSyscallReturn 72510037SARM gem5 Developersfstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 72610037SARM gem5 Developers ThreadContext *tc) 72710037SARM gem5 Developers{ 7288549Sdaniel.johnson@arm.com int fd = process->getSyscallArg(tc, 0); 7298868SMatt.Horsnell@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 7308868SMatt.Horsnell@arm.com // doesn't map to any simulator fd: not a valid target fd 7318868SMatt.Horsnell@arm.com return -EBADF; 7328868SMatt.Horsnell@arm.com } 7338868SMatt.Horsnell@arm.com 7348868SMatt.Horsnell@arm.com#if NO_STAT64 7358868SMatt.Horsnell@arm.com struct stat hostBuf; 7368868SMatt.Horsnell@arm.com int result = fstat(process->sim_fd(fd), &hostBuf); 7378868SMatt.Horsnell@arm.com#else 73810461SAndreas.Sandberg@ARM.com struct stat64 hostBuf; 7398868SMatt.Horsnell@arm.com int result = fstat64(process->sim_fd(fd), &hostBuf); 74010461SAndreas.Sandberg@ARM.com#endif 74110037SARM gem5 Developers 7428868SMatt.Horsnell@arm.com if (result < 0) 74310037SARM gem5 Developers return -errno; 74411150Smitch.hayenga@arm.com 74510037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 74610037SARM gem5 Developers &hostBuf, (fd == 1)); 74710037SARM gem5 Developers 74810037SARM gem5 Developers return 0; 74911150Smitch.hayenga@arm.com} 75010037SARM gem5 Developers 75110037SARM gem5 Developers 75210037SARM gem5 Developers/// Target lstat() handler. 75310037SARM gem5 Developerstemplate <class OS> 75410037SARM gem5 DevelopersSyscallReturn 75510037SARM gem5 DeveloperslstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 75610037SARM gem5 Developers ThreadContext *tc) 75710037SARM gem5 Developers{ 75810037SARM gem5 Developers std::string path; 75910037SARM gem5 Developers 76010037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 76110037SARM gem5 Developers return -EFAULT; 76210037SARM gem5 Developers 76310037SARM gem5 Developers // Adjust path for current working directory 76410037SARM gem5 Developers path = process->fullPath(path); 76510037SARM gem5 Developers 76610037SARM gem5 Developers struct stat hostBuf; 76710037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 76810037SARM gem5 Developers 76910037SARM gem5 Developers if (result < 0) 77010037SARM gem5 Developers return -errno; 77110037SARM gem5 Developers 77210037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 77310037SARM gem5 Developers &hostBuf); 77410037SARM gem5 Developers 77510037SARM gem5 Developers return 0; 77610037SARM gem5 Developers} 77710037SARM gem5 Developers 77810037SARM gem5 Developers/// Target lstat64() handler. 77910037SARM gem5 Developerstemplate <class OS> 78010037SARM gem5 DevelopersSyscallReturn 78110037SARM gem5 Developerslstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 78210037SARM gem5 Developers ThreadContext *tc) 78310037SARM gem5 Developers{ 78410037SARM gem5 Developers std::string path; 78510037SARM gem5 Developers 78610037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 78710037SARM gem5 Developers return -EFAULT; 78810037SARM gem5 Developers 78910037SARM gem5 Developers // Adjust path for current working directory 79010037SARM gem5 Developers path = process->fullPath(path); 79110037SARM gem5 Developers 79210037SARM gem5 Developers#if NO_STAT64 79310037SARM gem5 Developers struct stat hostBuf; 79410037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 79510037SARM gem5 Developers#else 79610037SARM gem5 Developers struct stat64 hostBuf; 79710844Sandreas.sandberg@arm.com int result = lstat64(path.c_str(), &hostBuf); 79810037SARM gem5 Developers#endif 79910844Sandreas.sandberg@arm.com 80010844Sandreas.sandberg@arm.com if (result < 0) 80110844Sandreas.sandberg@arm.com return -errno; 80210844Sandreas.sandberg@arm.com 80310844Sandreas.sandberg@arm.com copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 80410844Sandreas.sandberg@arm.com &hostBuf); 80510188Sgeoffrey.blake@arm.com 80610037SARM gem5 Developers return 0; 80710037SARM gem5 Developers} 8087405SAli.Saidi@ARM.com 8097405SAli.Saidi@ARM.com/// Target fstat() handler. 8107405SAli.Saidi@ARM.comtemplate <class OS> 8117405SAli.Saidi@ARM.comSyscallReturn 8127405SAli.Saidi@ARM.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8137405SAli.Saidi@ARM.com ThreadContext *tc) 8147405SAli.Saidi@ARM.com{ 8157405SAli.Saidi@ARM.com int fd = process->sim_fd(process->getSyscallArg(tc, 0)); 8167614Sminkyu.jeong@arm.com 81710037SARM gem5 Developers DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 81810037SARM gem5 Developers 8197614Sminkyu.jeong@arm.com if (fd < 0) 82010037SARM gem5 Developers return -EBADF; 82110037SARM gem5 Developers 82210037SARM gem5 Developers struct stat hostBuf; 82310037SARM gem5 Developers int result = fstat(fd, &hostBuf); 82410037SARM gem5 Developers 82510037SARM gem5 Developers if (result < 0) 82610037SARM gem5 Developers return -errno; 82710037SARM gem5 Developers 82810037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), 82910037SARM gem5 Developers &hostBuf, (fd == 1)); 83010037SARM gem5 Developers 83110037SARM gem5 Developers return 0; 83210037SARM gem5 Developers} 83310037SARM gem5 Developers 83410037SARM gem5 Developers 83510037SARM gem5 Developers/// Target statfs() handler. 83610037SARM gem5 Developerstemplate <class OS> 83710037SARM gem5 DevelopersSyscallReturn 83810037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8397405SAli.Saidi@ARM.com ThreadContext *tc) 8407405SAli.Saidi@ARM.com{ 8417405SAli.Saidi@ARM.com std::string path; 8427405SAli.Saidi@ARM.com 8437405SAli.Saidi@ARM.com if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 8447749SAli.Saidi@ARM.com return -EFAULT; 8457405SAli.Saidi@ARM.com 8468284SAli.Saidi@ARM.com // Adjust path for current working directory 84710037SARM gem5 Developers path = process->fullPath(path); 84810037SARM gem5 Developers 8498284SAli.Saidi@ARM.com struct statfs hostBuf; 8508284SAli.Saidi@ARM.com int result = statfs(path.c_str(), &hostBuf); 85110037SARM gem5 Developers 85210037SARM gem5 Developers if (result < 0) 85310037SARM gem5 Developers return -errno; 8548284SAli.Saidi@ARM.com 8557405SAli.Saidi@ARM.com OS::copyOutStatfsBuf(tc->getMemPort(), 8567405SAli.Saidi@ARM.com (Addr)(process->getSyscallArg(tc, 1)), &hostBuf); 8577749SAli.Saidi@ARM.com 8587749SAli.Saidi@ARM.com return 0; 8597749SAli.Saidi@ARM.com} 8607749SAli.Saidi@ARM.com 8617405SAli.Saidi@ARM.com 8627749SAli.Saidi@ARM.com/// Target fstatfs() handler. 8637749SAli.Saidi@ARM.comtemplate <class OS> 8647749SAli.Saidi@ARM.comSyscallReturn 8657749SAli.Saidi@ARM.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8667749SAli.Saidi@ARM.com ThreadContext *tc) 8677614Sminkyu.jeong@arm.com{ 8687614Sminkyu.jeong@arm.com int fd = process->sim_fd(process->getSyscallArg(tc, 0)); 8697720Sgblack@eecs.umich.edu 8707720Sgblack@eecs.umich.edu if (fd < 0) 8717720Sgblack@eecs.umich.edu return -EBADF; 8728887Sgeoffrey.blake@arm.com 8738887Sgeoffrey.blake@arm.com struct statfs hostBuf; 8748887Sgeoffrey.blake@arm.com int result = fstatfs(fd, &hostBuf); 8758887Sgeoffrey.blake@arm.com 8768887Sgeoffrey.blake@arm.com if (result < 0) 8778887Sgeoffrey.blake@arm.com return -errno; 8788887Sgeoffrey.blake@arm.com 8798887Sgeoffrey.blake@arm.com OS::copyOutStatfsBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), 8808887Sgeoffrey.blake@arm.com &hostBuf); 8817408Sgblack@eecs.umich.edu 88210037SARM gem5 Developers return 0; 88310037SARM gem5 Developers} 88410037SARM gem5 Developers 88510037SARM gem5 Developers 88610037SARM gem5 Developers/// Target writev() handler. 88710037SARM gem5 Developerstemplate <class OS> 88810037SARM gem5 DevelopersSyscallReturn 88910037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 89010037SARM gem5 Developers ThreadContext *tc) 89110037SARM gem5 Developers{ 89210037SARM gem5 Developers int fd = process->getSyscallArg(tc, 0); 8937408Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 8947408Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 8958206SWilliam.Wang@arm.com return -EBADF; 8968206SWilliam.Wang@arm.com } 8978206SWilliam.Wang@arm.com 8988206SWilliam.Wang@arm.com TranslatingPort *p = tc->getMemPort(); 8998206SWilliam.Wang@arm.com uint64_t tiov_base = process->getSyscallArg(tc, 1); 9008206SWilliam.Wang@arm.com size_t count = process->getSyscallArg(tc, 2); 9018206SWilliam.Wang@arm.com struct iovec hiov[count]; 9028206SWilliam.Wang@arm.com for (int i = 0; i < count; ++i) 90310037SARM gem5 Developers { 90410037SARM gem5 Developers typename OS::tgt_iovec tiov; 90510037SARM gem5 Developers 90610037SARM gem5 Developers p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 90710037SARM gem5 Developers (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 90810037SARM gem5 Developers hiov[i].iov_len = gtoh(tiov.iov_len); 90910037SARM gem5 Developers hiov[i].iov_base = new char [hiov[i].iov_len]; 91010037SARM gem5 Developers p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 91110037SARM gem5 Developers hiov[i].iov_len); 91210037SARM gem5 Developers } 91310037SARM gem5 Developers 91410037SARM gem5 Developers int result = writev(process->sim_fd(fd), hiov, count); 91510037SARM gem5 Developers 91610037SARM gem5 Developers for (int i = 0; i < count; ++i) 9178206SWilliam.Wang@arm.com { 91810037SARM gem5 Developers delete [] (char *)hiov[i].iov_base; 91910037SARM gem5 Developers } 92010037SARM gem5 Developers 92110037SARM gem5 Developers if (result < 0) 92210037SARM gem5 Developers return -errno; 92310037SARM gem5 Developers 92410037SARM gem5 Developers return 0; 92510037SARM gem5 Developers} 92610037SARM gem5 Developers 92710037SARM gem5 Developers 92810037SARM gem5 Developers/// Target mmap() handler. 92910037SARM gem5 Developers/// 93010037SARM gem5 Developers/// We don't really handle mmap(). If the target is mmaping an 93110037SARM gem5 Developers/// anonymous region or /dev/zero, we can get away with doing basically 93210037SARM gem5 Developers/// nothing (since memory is initialized to zero and the simulator 93310037SARM gem5 Developers/// doesn't really check addresses anyway). Always print a warning, 93410037SARM gem5 Developers/// since this could be seriously broken if we're not mapping 93510037SARM gem5 Developers/// /dev/zero. 93610037SARM gem5 Developers// 93710037SARM gem5 Developers/// Someday we should explicitly check for /dev/zero in open, flag the 93810037SARM gem5 Developers/// file descriptor, and fail (or implement!) a non-anonymous mmap to 93910037SARM gem5 Developers/// anything else. 94010037SARM gem5 Developerstemplate <class OS> 94110037SARM gem5 DevelopersSyscallReturn 94210037SARM gem5 DevelopersmmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 94310037SARM gem5 Developers{ 94410037SARM gem5 Developers Addr start = p->getSyscallArg(tc, 0); 94510037SARM gem5 Developers uint64_t length = p->getSyscallArg(tc, 1); 94610037SARM gem5 Developers // int prot = p->getSyscallArg(tc, 2); 94710037SARM gem5 Developers int flags = p->getSyscallArg(tc, 3); 94810037SARM gem5 Developers // int fd = p->sim_fd(p->getSyscallArg(tc, 4)); 94910037SARM gem5 Developers // int offset = p->getSyscallArg(tc, 5); 95010037SARM gem5 Developers 95110037SARM gem5 Developers 95210037SARM gem5 Developers if ((start % TheISA::VMPageSize) != 0 || 95310037SARM gem5 Developers (length % TheISA::VMPageSize) != 0) { 95410037SARM gem5 Developers warn("mmap failing: arguments not page-aligned: " 95510037SARM gem5 Developers "start 0x%x length 0x%x", 95610037SARM gem5 Developers start, length); 95710037SARM gem5 Developers return -EINVAL; 9588206SWilliam.Wang@arm.com } 9598206SWilliam.Wang@arm.com 9607408Sgblack@eecs.umich.edu if (start != 0) { 9617408Sgblack@eecs.umich.edu warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 9627408Sgblack@eecs.umich.edu start, p->mmap_end); 9637731SAli.Saidi@ARM.com } 9648206SWilliam.Wang@arm.com 96510037SARM gem5 Developers // pick next address from our "mmap region" 96610037SARM gem5 Developers start = p->mmap_end; 96710037SARM gem5 Developers p->pTable->allocate(start, length); 96810037SARM gem5 Developers p->mmap_end += length; 96910037SARM gem5 Developers 9707408Sgblack@eecs.umich.edu if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 9717408Sgblack@eecs.umich.edu warn("allowing mmap of file @ fd %d. " 9727408Sgblack@eecs.umich.edu "This will break if not /dev/zero.", p->getSyscallArg(tc, 4)); 9737408Sgblack@eecs.umich.edu } 9747408Sgblack@eecs.umich.edu 9757408Sgblack@eecs.umich.edu return start; 9767408Sgblack@eecs.umich.edu} 9777408Sgblack@eecs.umich.edu 9787408Sgblack@eecs.umich.edu/// Target getrlimit() handler. 9797408Sgblack@eecs.umich.edutemplate <class OS> 98010037SARM gem5 DevelopersSyscallReturn 98110037SARM gem5 DevelopersgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 98210037SARM gem5 Developers ThreadContext *tc) 98310037SARM gem5 Developers{ 98410037SARM gem5 Developers unsigned resource = process->getSyscallArg(tc, 0); 98510037SARM gem5 Developers TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, 1)); 9867408Sgblack@eecs.umich.edu 9877408Sgblack@eecs.umich.edu switch (resource) { 9887408Sgblack@eecs.umich.edu case OS::TGT_RLIMIT_STACK: 9897408Sgblack@eecs.umich.edu // max stack size in bytes: make up a number (8MB for now) 9907408Sgblack@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 9917408Sgblack@eecs.umich.edu rlp->rlim_cur = htog(rlp->rlim_cur); 9927408Sgblack@eecs.umich.edu rlp->rlim_max = htog(rlp->rlim_max); 9937408Sgblack@eecs.umich.edu break; 9947408Sgblack@eecs.umich.edu 9957408Sgblack@eecs.umich.edu case OS::TGT_RLIMIT_DATA: 9967408Sgblack@eecs.umich.edu // max data segment size in bytes: make up a number 9977408Sgblack@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 99810037SARM gem5 Developers rlp->rlim_cur = htog(rlp->rlim_cur); 99910037SARM gem5 Developers rlp->rlim_max = htog(rlp->rlim_max); 10009377Sgblack@eecs.umich.edu break; 10017408Sgblack@eecs.umich.edu 10027408Sgblack@eecs.umich.edu default: 100310037SARM gem5 Developers std::cerr << "getrlimitFunc: unimplemented resource " << resource 100410037SARM gem5 Developers << std::endl; 100510037SARM gem5 Developers abort(); 100610037SARM gem5 Developers break; 100710037SARM gem5 Developers } 100810037SARM gem5 Developers 100910037SARM gem5 Developers rlp.copyOut(tc->getMemPort()); 101010037SARM gem5 Developers return 0; 101110037SARM gem5 Developers} 101210037SARM gem5 Developers 101310037SARM gem5 Developers/// Target gettimeofday() handler. 101410037SARM gem5 Developerstemplate <class OS> 101510037SARM gem5 DevelopersSyscallReturn 101610037SARM gem5 DevelopersgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 101710037SARM gem5 Developers ThreadContext *tc) 101810037SARM gem5 Developers{ 101910037SARM gem5 Developers TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, 0)); 102010037SARM gem5 Developers 102110037SARM gem5 Developers getElapsedTime(tp->tv_sec, tp->tv_usec); 102210037SARM gem5 Developers tp->tv_sec += seconds_since_epoch; 102310037SARM gem5 Developers tp->tv_sec = TheISA::htog(tp->tv_sec); 102410037SARM gem5 Developers tp->tv_usec = TheISA::htog(tp->tv_usec); 102510037SARM gem5 Developers 102610037SARM gem5 Developers tp.copyOut(tc->getMemPort()); 102710037SARM gem5 Developers 102810037SARM gem5 Developers return 0; 102910037SARM gem5 Developers} 103010037SARM gem5 Developers 103110037SARM gem5 Developers 103210037SARM gem5 Developers/// Target utimes() handler. 103310037SARM gem5 Developerstemplate <class OS> 103410037SARM gem5 DevelopersSyscallReturn 103510037SARM gem5 DevelopersutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 103610037SARM gem5 Developers ThreadContext *tc) 103710037SARM gem5 Developers{ 103810037SARM gem5 Developers std::string path; 103910037SARM gem5 Developers 104010037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) 104110037SARM gem5 Developers return -EFAULT; 104210037SARM gem5 Developers 104310037SARM gem5 Developers TypedBufferArg<typename OS::timeval [2]> tp(process->getSyscallArg(tc, 1)); 104410037SARM gem5 Developers tp.copyIn(tc->getMemPort()); 104510037SARM gem5 Developers 10468302SAli.Saidi@ARM.com struct timeval hostTimeval[2]; 10478302SAli.Saidi@ARM.com for (int i = 0; i < 2; ++i) 10488302SAli.Saidi@ARM.com { 104910037SARM gem5 Developers hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 10508302SAli.Saidi@ARM.com hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 10518302SAli.Saidi@ARM.com } 10528302SAli.Saidi@ARM.com 10537783SGiacomo.Gabrielli@arm.com // Adjust path for current working directory 10547783SGiacomo.Gabrielli@arm.com path = process->fullPath(path); 105510037SARM gem5 Developers 105610037SARM gem5 Developers int result = utimes(path.c_str(), hostTimeval); 10577783SGiacomo.Gabrielli@arm.com 10587783SGiacomo.Gabrielli@arm.com if (result < 0) 10597783SGiacomo.Gabrielli@arm.com return -errno; 10607783SGiacomo.Gabrielli@arm.com 10617783SGiacomo.Gabrielli@arm.com return 0; 106210037SARM gem5 Developers} 106310037SARM gem5 Developers/// Target getrusage() function. 10647783SGiacomo.Gabrielli@arm.comtemplate <class OS> 10657783SGiacomo.Gabrielli@arm.comSyscallReturn 10667783SGiacomo.Gabrielli@arm.comgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10677408Sgblack@eecs.umich.edu ThreadContext *tc) 10687408Sgblack@eecs.umich.edu{ 10698206SWilliam.Wang@arm.com int who = process->getSyscallArg(tc, 0); // THREAD, SELF, or CHILDREN 10708206SWilliam.Wang@arm.com TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, 1)); 10717408Sgblack@eecs.umich.edu 10727408Sgblack@eecs.umich.edu rup->ru_utime.tv_sec = 0; 107310037SARM gem5 Developers rup->ru_utime.tv_usec = 0; 10747408Sgblack@eecs.umich.edu rup->ru_stime.tv_sec = 0; 10757408Sgblack@eecs.umich.edu rup->ru_stime.tv_usec = 0; 107610037SARM gem5 Developers rup->ru_maxrss = 0; 107710037SARM gem5 Developers rup->ru_ixrss = 0; 107810037SARM gem5 Developers rup->ru_idrss = 0; 107910037SARM gem5 Developers rup->ru_isrss = 0; 108010037SARM gem5 Developers rup->ru_minflt = 0; 108110037SARM gem5 Developers rup->ru_majflt = 0; 108210037SARM gem5 Developers rup->ru_nswap = 0; 108310037SARM gem5 Developers rup->ru_inblock = 0; 108410037SARM gem5 Developers rup->ru_oublock = 0; 108510037SARM gem5 Developers rup->ru_msgsnd = 0; 108610037SARM gem5 Developers rup->ru_msgrcv = 0; 108710037SARM gem5 Developers rup->ru_nsignals = 0; 108810037SARM gem5 Developers rup->ru_nvcsw = 0; 108910037SARM gem5 Developers rup->ru_nivcsw = 0; 109010037SARM gem5 Developers 109110037SARM gem5 Developers switch (who) { 109210037SARM gem5 Developers case OS::TGT_RUSAGE_SELF: 109310037SARM gem5 Developers getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 109410037SARM gem5 Developers rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 109510037SARM gem5 Developers rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 109610037SARM gem5 Developers break; 109710037SARM gem5 Developers 109810037SARM gem5 Developers case OS::TGT_RUSAGE_CHILDREN: 109910037SARM gem5 Developers // do nothing. We have no child processes, so they take no time. 110010037SARM gem5 Developers break; 110110037SARM gem5 Developers 110210037SARM gem5 Developers default: 110310037SARM gem5 Developers // don't really handle THREAD or CHILDREN, but just warn and 110410037SARM gem5 Developers // plow ahead 110510037SARM gem5 Developers warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 110610037SARM gem5 Developers who); 110710037SARM gem5 Developers } 110810037SARM gem5 Developers 110910037SARM gem5 Developers rup.copyOut(tc->getMemPort()); 111010037SARM gem5 Developers 11117408Sgblack@eecs.umich.edu return 0; 11127408Sgblack@eecs.umich.edu} 11137408Sgblack@eecs.umich.edu 111410037SARM gem5 Developers 111510037SARM gem5 Developers 111610037SARM gem5 Developers 111710037SARM gem5 Developers#endif // __SIM_SYSCALL_EMUL_HH__ 111810037SARM gem5 Developers