syscall_emul.hh revision 8852
16019Shines@cs.fsu.edu/* 211496Sandreas.sandberg@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Steve Reinhardt 296019Shines@cs.fsu.edu * Kevin Lim 306019Shines@cs.fsu.edu */ 316019Shines@cs.fsu.edu 326019Shines@cs.fsu.edu#ifndef __SIM_SYSCALL_EMUL_HH__ 336019Shines@cs.fsu.edu#define __SIM_SYSCALL_EMUL_HH__ 346019Shines@cs.fsu.edu 356019Shines@cs.fsu.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 366019Shines@cs.fsu.edu defined(__FreeBSD__) || defined(__CYGWIN__)) 376019Shines@cs.fsu.edu 386019Shines@cs.fsu.edu/// 396019Shines@cs.fsu.edu/// @file syscall_emul.hh 406019Shines@cs.fsu.edu/// 416735Sgblack@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target 426735Sgblack@eecs.umich.edu/// application on the host machine. 4310037SARM gem5 Developers 4410037SARM gem5 Developers#ifdef __CYGWIN32__ 456019Shines@cs.fsu.edu#include <sys/fcntl.h> // for O_BINARY 466019Shines@cs.fsu.edu#endif 476019Shines@cs.fsu.edu#include <sys/stat.h> 4811793Sbrandon.potter@amd.com#include <sys/time.h> 4911793Sbrandon.potter@amd.com#include <sys/uio.h> 5010037SARM gem5 Developers#include <fcntl.h> 5110037SARM gem5 Developers 5210037SARM gem5 Developers#include <cerrno> 538229Snate@binkert.org#include <string> 548229Snate@binkert.org 556019Shines@cs.fsu.edu#include "base/chunk_generator.hh" 568232Snate@binkert.org#include "base/intmath.hh" // for RoundUp 578782Sgblack@eecs.umich.edu#include "base/misc.hh" 586019Shines@cs.fsu.edu#include "base/trace.hh" 596019Shines@cs.fsu.edu#include "base/types.hh" 606019Shines@cs.fsu.edu#include "config/the_isa.hh" 616019Shines@cs.fsu.edu#include "cpu/base.hh" 6210037SARM gem5 Developers#include "cpu/thread_context.hh" 6310037SARM gem5 Developers#include "debug/SyscallVerbose.hh" 6410037SARM gem5 Developers#include "mem/page_table.hh" 6510037SARM gem5 Developers#include "mem/se_translating_port_proxy.hh" 6610037SARM gem5 Developers#include "sim/byteswap.hh" 6710037SARM gem5 Developers#include "sim/process.hh" 6810037SARM gem5 Developers#include "sim/syscallreturn.hh" 6910037SARM gem5 Developers#include "sim/system.hh" 7010037SARM gem5 Developers 7110037SARM gem5 Developers/// 7210037SARM gem5 Developers/// System call descriptor. 7310037SARM gem5 Developers/// 7410037SARM gem5 Developersclass SyscallDesc { 7510037SARM gem5 Developers 7610037SARM gem5 Developers public: 7710037SARM gem5 Developers 7810037SARM gem5 Developers /// Typedef for target syscall handler functions. 7910037SARM gem5 Developers typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 8010037SARM gem5 Developers LiveProcess *, ThreadContext *); 8110037SARM gem5 Developers 8210037SARM gem5 Developers const char *name; //!< Syscall name (e.g., "open"). 8310037SARM gem5 Developers FuncPtr funcPtr; //!< Pointer to emulation function. 8410037SARM gem5 Developers int flags; //!< Flags (see Flags enum). 8510037SARM gem5 Developers 8610037SARM gem5 Developers /// Flag values for controlling syscall behavior. 8710037SARM gem5 Developers enum Flags { 8810037SARM gem5 Developers /// Don't set return regs according to funcPtr return value. 8910037SARM gem5 Developers /// Used for syscalls with non-standard return conventions 9010037SARM gem5 Developers /// that explicitly set the ThreadContext regs (e.g., 9110037SARM gem5 Developers /// sigreturn). 9210037SARM gem5 Developers SuppressReturnValue = 1 9310037SARM gem5 Developers }; 9410037SARM gem5 Developers 9510037SARM gem5 Developers /// Constructor. 9610037SARM gem5 Developers SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9710037SARM gem5 Developers : name(_name), funcPtr(_funcPtr), flags(_flags) 9810037SARM gem5 Developers { 9910037SARM gem5 Developers } 10010037SARM gem5 Developers 10110037SARM gem5 Developers /// Emulate the syscall. Public interface for calling through funcPtr. 1026019Shines@cs.fsu.edu void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 10310037SARM gem5 Developers}; 10410037SARM gem5 Developers 10510037SARM gem5 Developers 1066019Shines@cs.fsu.educlass BaseBufferArg { 10710037SARM gem5 Developers 10810037SARM gem5 Developers public: 10910037SARM gem5 Developers 11010037SARM gem5 Developers BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 11110037SARM gem5 Developers { 11210037SARM gem5 Developers bufPtr = new uint8_t[size]; 11310037SARM gem5 Developers // clear out buffer: in case we only partially populate this, 11410037SARM gem5 Developers // and then do a copyOut(), we want to make sure we don't 11510037SARM gem5 Developers // introduce any random junk into the simulated address space 11610037SARM gem5 Developers memset(bufPtr, 0, size); 11710037SARM gem5 Developers } 11810037SARM gem5 Developers 11910037SARM gem5 Developers virtual ~BaseBufferArg() { delete [] bufPtr; } 12010037SARM gem5 Developers 12110037SARM gem5 Developers // 12210037SARM gem5 Developers // copy data into simulator space (read from target memory) 12310037SARM gem5 Developers // 12410037SARM gem5 Developers virtual bool copyIn(SETranslatingPortProxy &memproxy) 12510037SARM gem5 Developers { 12610037SARM gem5 Developers memproxy.readBlob(addr, bufPtr, size); 12710037SARM gem5 Developers return true; // no EFAULT detection for now 12810037SARM gem5 Developers } 12910037SARM gem5 Developers 13010037SARM gem5 Developers // 13110037SARM gem5 Developers // copy data out of simulator space (write to target memory) 13210037SARM gem5 Developers // 13310037SARM gem5 Developers virtual bool copyOut(SETranslatingPortProxy &memproxy) 13410037SARM gem5 Developers { 13510037SARM gem5 Developers memproxy.writeBlob(addr, bufPtr, size); 13610037SARM gem5 Developers return true; // no EFAULT detection for now 13710037SARM gem5 Developers } 13810037SARM gem5 Developers 13910037SARM gem5 Developers protected: 14010037SARM gem5 Developers Addr addr; 14110037SARM gem5 Developers int size; 14210037SARM gem5 Developers uint8_t *bufPtr; 14310037SARM gem5 Developers}; 14410037SARM gem5 Developers 14510037SARM gem5 Developers 14610037SARM gem5 Developersclass BufferArg : public BaseBufferArg 1476019Shines@cs.fsu.edu{ 14810037SARM gem5 Developers public: 14910037SARM gem5 Developers BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 15010037SARM gem5 Developers void *bufferPtr() { return bufPtr; } 1516019Shines@cs.fsu.edu}; 15210037SARM gem5 Developers 15310037SARM gem5 Developerstemplate <class T> 15410037SARM gem5 Developersclass TypedBufferArg : public BaseBufferArg 15510037SARM gem5 Developers{ 15610037SARM gem5 Developers public: 15710037SARM gem5 Developers // user can optionally specify a specific number of bytes to 15810037SARM gem5 Developers // allocate to deal with those structs that have variable-size 15910037SARM gem5 Developers // arrays at the end 16010037SARM gem5 Developers TypedBufferArg(Addr _addr, int _size = sizeof(T)) 16110037SARM gem5 Developers : BaseBufferArg(_addr, _size) 16210037SARM gem5 Developers { } 16310037SARM gem5 Developers 16410037SARM gem5 Developers // type case 16510037SARM gem5 Developers operator T*() { return (T *)bufPtr; } 16610037SARM gem5 Developers 16710037SARM gem5 Developers // dereference operators 16810037SARM gem5 Developers T &operator*() { return *((T *)bufPtr); } 16910037SARM gem5 Developers T* operator->() { return (T *)bufPtr; } 17010037SARM gem5 Developers T &operator[](int i) { return ((T *)bufPtr)[i]; } 17110037SARM gem5 Developers}; 17210037SARM gem5 Developers 17310037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 17410037SARM gem5 Developers// 17510037SARM gem5 Developers// The following emulation functions are generic enough that they 17610037SARM gem5 Developers// don't need to be recompiled for different emulated OS's. They are 17710037SARM gem5 Developers// defined in sim/syscall_emul.cc. 17810037SARM gem5 Developers// 17910037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 18010037SARM gem5 Developers 18110037SARM gem5 Developers 18210037SARM gem5 Developers/// Handler for unimplemented syscalls that we haven't thought about. 18310037SARM gem5 DevelopersSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 18410037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 18510037SARM gem5 Developers 18610037SARM gem5 Developers/// Handler for unimplemented syscalls that we never intend to 18710037SARM gem5 Developers/// implement (signal handling, etc.) and should not affect the correct 18810037SARM gem5 Developers/// behavior of the program. Print a warning only if the appropriate 18910037SARM gem5 Developers/// trace flag is enabled. Return success to the target program. 19010037SARM gem5 DevelopersSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 19110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 19210037SARM gem5 DevelopersSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 1936019Shines@cs.fsu.edu LiveProcess *p, ThreadContext *tc); 19410037SARM gem5 Developers 19510037SARM gem5 Developers/// Target exit() handler: terminate current context. 19610037SARM gem5 DevelopersSyscallReturn exitFunc(SyscallDesc *desc, int num, 1976019Shines@cs.fsu.edu LiveProcess *p, ThreadContext *tc); 19810037SARM gem5 Developers 19910037SARM gem5 Developers/// Target exit_group() handler: terminate simulation. (exit all threads) 20010037SARM gem5 DevelopersSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 20110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 20210037SARM gem5 Developers 20310037SARM gem5 Developers/// Target getpagesize() handler. 20410037SARM gem5 DevelopersSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 20510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 20610037SARM gem5 Developers 20710037SARM gem5 Developers/// Target brk() handler: set brk address. 20810037SARM gem5 DevelopersSyscallReturn brkFunc(SyscallDesc *desc, int num, 20910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 21010037SARM gem5 Developers 21110037SARM gem5 Developers/// Target close() handler. 21210037SARM gem5 DevelopersSyscallReturn closeFunc(SyscallDesc *desc, int num, 21310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 21410037SARM gem5 Developers 21510037SARM gem5 Developers/// Target read() handler. 21610037SARM gem5 DevelopersSyscallReturn readFunc(SyscallDesc *desc, int num, 21710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 21810037SARM gem5 Developers 21910037SARM gem5 Developers/// Target write() handler. 22010037SARM gem5 DevelopersSyscallReturn writeFunc(SyscallDesc *desc, int num, 22110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 22210037SARM gem5 Developers 22310037SARM gem5 Developers/// Target lseek() handler. 22410037SARM gem5 DevelopersSyscallReturn lseekFunc(SyscallDesc *desc, int num, 22510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 22610037SARM gem5 Developers 22710037SARM gem5 Developers/// Target _llseek() handler. 22810037SARM gem5 DevelopersSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 22910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23010037SARM gem5 Developers 23110037SARM gem5 Developers/// Target munmap() handler. 23210037SARM gem5 DevelopersSyscallReturn munmapFunc(SyscallDesc *desc, int num, 23310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23410037SARM gem5 Developers 23510037SARM gem5 Developers/// Target gethostname() handler. 23610037SARM gem5 DevelopersSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 23710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23810037SARM gem5 Developers 23910037SARM gem5 Developers/// Target getcwd() handler. 24010037SARM gem5 DevelopersSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 24110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24210037SARM gem5 Developers 24310037SARM gem5 Developers/// Target unlink() handler. 24410037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 24510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24610037SARM gem5 Developers 24710037SARM gem5 Developers/// Target unlink() handler. 24810037SARM gem5 DevelopersSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 24910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25010037SARM gem5 Developers 25110037SARM gem5 Developers/// Target mkdir() handler. 25210037SARM gem5 DevelopersSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 25310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25410037SARM gem5 Developers 25510037SARM gem5 Developers/// Target rename() handler. 25610037SARM gem5 DevelopersSyscallReturn renameFunc(SyscallDesc *desc, int num, 25710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25810037SARM gem5 Developers 25910037SARM gem5 Developers 26010037SARM gem5 Developers/// Target truncate() handler. 26110037SARM gem5 DevelopersSyscallReturn truncateFunc(SyscallDesc *desc, int num, 26210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26310037SARM gem5 Developers 26410037SARM gem5 Developers 26510037SARM gem5 Developers/// Target ftruncate() handler. 26610037SARM gem5 DevelopersSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 26710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26810037SARM gem5 Developers 26910037SARM gem5 Developers 27010037SARM gem5 Developers/// Target truncate64() handler. 27110037SARM gem5 DevelopersSyscallReturn truncate64Func(SyscallDesc *desc, int num, 27210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27310037SARM gem5 Developers 27410037SARM gem5 Developers/// Target ftruncate64() handler. 27510037SARM gem5 DevelopersSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 27610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27710037SARM gem5 Developers 27810037SARM gem5 Developers 27910037SARM gem5 Developers/// Target umask() handler. 28010037SARM gem5 DevelopersSyscallReturn umaskFunc(SyscallDesc *desc, int num, 28110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 28210037SARM gem5 Developers 28310037SARM gem5 Developers 28410037SARM gem5 Developers/// Target chown() handler. 28510037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num, 28610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 28710037SARM gem5 Developers 28810037SARM gem5 Developers 28910037SARM gem5 Developers/// Target fchown() handler. 29010037SARM gem5 DevelopersSyscallReturn fchownFunc(SyscallDesc *desc, int num, 29110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 29210037SARM gem5 Developers 29310037SARM gem5 Developers/// Target dup() handler. 29410037SARM gem5 DevelopersSyscallReturn dupFunc(SyscallDesc *desc, int num, 29510037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 2966019Shines@cs.fsu.edu 29710037SARM gem5 Developers/// Target fnctl() handler. 2987362Sgblack@eecs.umich.eduSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2996735Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 30010037SARM gem5 Developers 3016019Shines@cs.fsu.edu/// Target fcntl64() handler. 30210037SARM gem5 DevelopersSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 30310037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 3047400SAli.Saidi@ARM.com 3056735Sgblack@eecs.umich.edu/// Target setuid() handler. 3066735Sgblack@eecs.umich.eduSyscallReturn setuidFunc(SyscallDesc *desc, int num, 30710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 3086735Sgblack@eecs.umich.edu 30910037SARM gem5 Developers/// Target getpid() handler. 31010037SARM gem5 DevelopersSyscallReturn getpidFunc(SyscallDesc *desc, int num, 31110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 31210037SARM gem5 Developers 3137400SAli.Saidi@ARM.com/// Target getuid() handler. 31410037SARM gem5 DevelopersSyscallReturn getuidFunc(SyscallDesc *desc, int num, 31510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 31610037SARM gem5 Developers 31710037SARM gem5 Developers/// Target getgid() handler. 31810037SARM gem5 DevelopersSyscallReturn getgidFunc(SyscallDesc *desc, int num, 31910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 32010037SARM gem5 Developers 32110037SARM gem5 Developers/// Target getppid() handler. 32210037SARM gem5 DevelopersSyscallReturn getppidFunc(SyscallDesc *desc, int num, 32310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 32410037SARM gem5 Developers 32510037SARM gem5 Developers/// Target geteuid() handler. 32610037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 32710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 32810037SARM gem5 Developers 32910037SARM gem5 Developers/// Target getegid() handler. 33010037SARM gem5 DevelopersSyscallReturn getegidFunc(SyscallDesc *desc, int num, 3316019Shines@cs.fsu.edu LiveProcess *p, ThreadContext *tc); 3326019Shines@cs.fsu.edu 33310037SARM gem5 Developers/// Target clone() handler. 33410037SARM gem5 DevelopersSyscallReturn cloneFunc(SyscallDesc *desc, int num, 33510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 33610037SARM gem5 Developers 33710037SARM gem5 Developers 33810037SARM gem5 Developers/// Pseudo Funcs - These functions use a different return convension, 33910037SARM gem5 Developers/// returning a second value in a register other than the normal return register 34010037SARM gem5 DevelopersSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 34110037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 34211574SCurtis.Dunham@arm.com 34311574SCurtis.Dunham@arm.com/// Target getpidPseudo() handler. 34411574SCurtis.Dunham@arm.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 34511574SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 34610037SARM gem5 Developers 34710037SARM gem5 Developers/// Target getuidPseudo() handler. 34810037SARM gem5 DevelopersSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 34910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 35010037SARM gem5 Developers 35110037SARM gem5 Developers/// Target getgidPseudo() handler. 35210037SARM gem5 DevelopersSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 35310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 35410037SARM gem5 Developers 35510037SARM gem5 Developers 35610037SARM gem5 Developers/// A readable name for 1,000,000, for converting microseconds to seconds. 35710037SARM gem5 Developersconst int one_million = 1000000; 35810037SARM gem5 Developers 35910037SARM gem5 Developers/// Approximate seconds since the epoch (1/1/1970). About a billion, 36010037SARM gem5 Developers/// by my reckoning. We want to keep this a constant (not use the 36110037SARM gem5 Developers/// real-world time) to keep simulations repeatable. 36210037SARM gem5 Developersconst unsigned seconds_since_epoch = 1000000000; 36310037SARM gem5 Developers 36410037SARM gem5 Developers/// Helper function to convert current elapsed time to seconds and 36510037SARM gem5 Developers/// microseconds. 36610037SARM gem5 Developerstemplate <class T1, class T2> 36710037SARM gem5 Developersvoid 36810037SARM gem5 DevelopersgetElapsedTime(T1 &sec, T2 &usec) 36910037SARM gem5 Developers{ 37010037SARM gem5 Developers int elapsed_usecs = curTick() / SimClock::Int::us; 37110037SARM gem5 Developers sec = elapsed_usecs / one_million; 37210037SARM gem5 Developers usec = elapsed_usecs % one_million; 37310037SARM gem5 Developers} 37410037SARM gem5 Developers 37510037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 37610037SARM gem5 Developers// 37710037SARM gem5 Developers// The following emulation functions are generic, but need to be 37810037SARM gem5 Developers// templated to account for differences in types, constants, etc. 37910037SARM gem5 Developers// 38010037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 38110037SARM gem5 Developers 38210037SARM gem5 Developers#if NO_STAT64 38310037SARM gem5 Developers typedef struct stat hst_stat; 38410037SARM gem5 Developers typedef struct stat hst_stat64; 38510037SARM gem5 Developers#else 38610037SARM gem5 Developers typedef struct stat hst_stat; 38710037SARM gem5 Developers typedef struct stat64 hst_stat64; 38810037SARM gem5 Developers#endif 38910037SARM gem5 Developers 39010037SARM gem5 Developers//// Helper function to convert a host stat buffer to a target stat 39110037SARM gem5 Developers//// buffer. Also copies the target buffer out to the simulated 39210037SARM gem5 Developers//// memory space. Used by stat(), fstat(), and lstat(). 39310037SARM gem5 Developers 39410037SARM gem5 Developerstemplate <typename target_stat, typename host_stat> 39510037SARM gem5 Developersstatic void 39610037SARM gem5 DevelopersconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 39710037SARM gem5 Developers{ 39810037SARM gem5 Developers using namespace TheISA; 39910037SARM gem5 Developers 40010037SARM gem5 Developers if (fakeTTY) 40110037SARM gem5 Developers tgt->st_dev = 0xA; 40210037SARM gem5 Developers else 40310037SARM gem5 Developers tgt->st_dev = host->st_dev; 40410037SARM gem5 Developers tgt->st_dev = TheISA::htog(tgt->st_dev); 40510037SARM gem5 Developers tgt->st_ino = host->st_ino; 40610037SARM gem5 Developers tgt->st_ino = TheISA::htog(tgt->st_ino); 40710037SARM gem5 Developers tgt->st_mode = host->st_mode; 40810037SARM gem5 Developers if (fakeTTY) { 40910037SARM gem5 Developers // Claim to be a character device 41010037SARM gem5 Developers tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 41110037SARM gem5 Developers tgt->st_mode |= S_IFCHR; // Set S_IFCHR 41210037SARM gem5 Developers } 41310037SARM gem5 Developers tgt->st_mode = TheISA::htog(tgt->st_mode); 41410037SARM gem5 Developers tgt->st_nlink = host->st_nlink; 41510037SARM gem5 Developers tgt->st_nlink = TheISA::htog(tgt->st_nlink); 41610037SARM gem5 Developers tgt->st_uid = host->st_uid; 41710037SARM gem5 Developers tgt->st_uid = TheISA::htog(tgt->st_uid); 41810037SARM gem5 Developers tgt->st_gid = host->st_gid; 41910037SARM gem5 Developers tgt->st_gid = TheISA::htog(tgt->st_gid); 42010037SARM gem5 Developers if (fakeTTY) 42110037SARM gem5 Developers tgt->st_rdev = 0x880d; 42210037SARM gem5 Developers else 42310037SARM gem5 Developers tgt->st_rdev = host->st_rdev; 42410037SARM gem5 Developers tgt->st_rdev = TheISA::htog(tgt->st_rdev); 42510037SARM gem5 Developers tgt->st_size = host->st_size; 42610037SARM gem5 Developers tgt->st_size = TheISA::htog(tgt->st_size); 42710037SARM gem5 Developers tgt->st_atimeX = host->st_atime; 42810037SARM gem5 Developers tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 42910417Sandreas.hansson@arm.com tgt->st_mtimeX = host->st_mtime; 4306019Shines@cs.fsu.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 43110037SARM gem5 Developers tgt->st_ctimeX = host->st_ctime; 43210037SARM gem5 Developers tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 43310037SARM gem5 Developers // Force the block size to be 8k. This helps to ensure buffered io works 43410037SARM gem5 Developers // consistently across different hosts. 43510037SARM gem5 Developers tgt->st_blksize = 0x2000; 43610037SARM gem5 Developers tgt->st_blksize = TheISA::htog(tgt->st_blksize); 43710037SARM gem5 Developers tgt->st_blocks = host->st_blocks; 43810037SARM gem5 Developers tgt->st_blocks = TheISA::htog(tgt->st_blocks); 43910037SARM gem5 Developers} 44010037SARM gem5 Developers 44110037SARM gem5 Developers// Same for stat64 44210037SARM gem5 Developers 44311578SDylan.Johnson@ARM.comtemplate <typename target_stat, typename host_stat64> 44411578SDylan.Johnson@ARM.comstatic void 44510037SARM gem5 DevelopersconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 44610037SARM gem5 Developers{ 44710037SARM gem5 Developers using namespace TheISA; 44810037SARM gem5 Developers 44910037SARM gem5 Developers convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 45010037SARM gem5 Developers#if defined(STAT_HAVE_NSEC) 45110037SARM gem5 Developers tgt->st_atime_nsec = host->st_atime_nsec; 45210037SARM gem5 Developers tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 45310037SARM gem5 Developers tgt->st_mtime_nsec = host->st_mtime_nsec; 45410037SARM gem5 Developers tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 45510037SARM gem5 Developers tgt->st_ctime_nsec = host->st_ctime_nsec; 45610037SARM gem5 Developers tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 45710037SARM gem5 Developers#else 45810037SARM gem5 Developers tgt->st_atime_nsec = 0; 45910037SARM gem5 Developers tgt->st_mtime_nsec = 0; 46010037SARM gem5 Developers tgt->st_ctime_nsec = 0; 46110037SARM gem5 Developers#endif 46210037SARM gem5 Developers} 4636735Sgblack@eecs.umich.edu 4648782Sgblack@eecs.umich.edu//Here are a couple convenience functions 4658782Sgblack@eecs.umich.edutemplate<class OS> 4666735Sgblack@eecs.umich.edustatic void 4676019Shines@cs.fsu.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 4686735Sgblack@eecs.umich.edu hst_stat *host, bool fakeTTY = false) 46910037SARM gem5 Developers{ 4708303SAli.Saidi@ARM.com typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 47110338SCurtis.Dunham@arm.com tgt_stat_buf tgt(addr); 47210338SCurtis.Dunham@arm.com convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 47310338SCurtis.Dunham@arm.com tgt.copyOut(mem); 47410338SCurtis.Dunham@arm.com} 4758303SAli.Saidi@ARM.com 4767720Sgblack@eecs.umich.edutemplate<class OS> 4778205SAli.Saidi@ARM.comstatic void 4788205SAli.Saidi@ARM.comcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 4798205SAli.Saidi@ARM.com hst_stat64 *host, bool fakeTTY = false) 4806735Sgblack@eecs.umich.edu{ 48110037SARM gem5 Developers typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 48210037SARM gem5 Developers tgt_stat_buf tgt(addr); 48310037SARM gem5 Developers convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 48410037SARM gem5 Developers tgt.copyOut(mem); 48510037SARM gem5 Developers} 48610037SARM gem5 Developers 48710037SARM gem5 Developers/// Target ioctl() handler. For the most part, programs call ioctl() 48810037SARM gem5 Developers/// only to find out if their stdout is a tty, to determine whether to 48910037SARM gem5 Developers/// do line or block buffering. 49010037SARM gem5 Developerstemplate <class OS> 49110037SARM gem5 DevelopersSyscallReturn 49210037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 49310037SARM gem5 Developers ThreadContext *tc) 49410037SARM gem5 Developers{ 49510037SARM gem5 Developers int index = 0; 49610037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 49710037SARM gem5 Developers unsigned req = process->getSyscallArg(tc, index); 49810037SARM gem5 Developers 49910037SARM gem5 Developers DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 50010037SARM gem5 Developers 50110037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 50210037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 50310037SARM gem5 Developers return -EBADF; 50410037SARM gem5 Developers } 50510037SARM gem5 Developers 50610037SARM gem5 Developers switch (req) { 50710037SARM gem5 Developers case OS::TIOCISATTY_: 50810037SARM gem5 Developers case OS::TIOCGETP_: 50910037SARM gem5 Developers case OS::TIOCSETP_: 51010037SARM gem5 Developers case OS::TIOCSETN_: 51110037SARM gem5 Developers case OS::TIOCSETC_: 51210037SARM gem5 Developers case OS::TIOCGETC_: 51310037SARM gem5 Developers case OS::TIOCGETS_: 51410037SARM gem5 Developers case OS::TIOCGETA_: 51510037SARM gem5 Developers case OS::TCSETAW_: 51610037SARM gem5 Developers return -ENOTTY; 51710037SARM gem5 Developers 51810037SARM gem5 Developers default: 51910037SARM gem5 Developers fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 52010037SARM gem5 Developers fd, req, tc->pcState()); 52110037SARM gem5 Developers } 52210037SARM gem5 Developers} 52310037SARM gem5 Developers 52410037SARM gem5 Developers/// Target open() handler. 52510037SARM gem5 Developerstemplate <class OS> 52610037SARM gem5 DevelopersSyscallReturn 52710037SARM gem5 DevelopersopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 52810037SARM gem5 Developers ThreadContext *tc) 5296735Sgblack@eecs.umich.edu{ 5306735Sgblack@eecs.umich.edu std::string path; 5316735Sgblack@eecs.umich.edu 53210037SARM gem5 Developers int index = 0; 5338518Sgeoffrey.blake@arm.com if (!tc->getMemProxy().tryReadString(path, 5348518Sgeoffrey.blake@arm.com process->getSyscallArg(tc, index))) 5356735Sgblack@eecs.umich.edu return -EFAULT; 53610037SARM gem5 Developers 53710037SARM gem5 Developers if (path == "/dev/sysdev0") { 53810037SARM gem5 Developers // This is a memory-mapped high-resolution timer device on Alpha. 53910037SARM gem5 Developers // We don't support it, so just punt. 54010037SARM gem5 Developers warn("Ignoring open(%s, ...)\n", path); 54110037SARM gem5 Developers return -ENOENT; 54210037SARM gem5 Developers } 54310037SARM gem5 Developers 54410037SARM gem5 Developers int tgtFlags = process->getSyscallArg(tc, index); 54510037SARM gem5 Developers int mode = process->getSyscallArg(tc, index); 54610037SARM gem5 Developers int hostFlags = 0; 54710037SARM gem5 Developers 5486735Sgblack@eecs.umich.edu // translate open flags 5496735Sgblack@eecs.umich.edu for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 5506735Sgblack@eecs.umich.edu if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 5516735Sgblack@eecs.umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 5526735Sgblack@eecs.umich.edu hostFlags |= OS::openFlagTable[i].hostFlag; 5536735Sgblack@eecs.umich.edu } 5546735Sgblack@eecs.umich.edu } 5556735Sgblack@eecs.umich.edu 5566735Sgblack@eecs.umich.edu // any target flags left? 55710037SARM gem5 Developers if (tgtFlags != 0) 55810037SARM gem5 Developers warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 55910037SARM gem5 Developers 5606735Sgblack@eecs.umich.edu#ifdef __CYGWIN32__ 5616735Sgblack@eecs.umich.edu hostFlags |= O_BINARY; 5626735Sgblack@eecs.umich.edu#endif 5636735Sgblack@eecs.umich.edu 56410037SARM gem5 Developers // Adjust path for current working directory 56510037SARM gem5 Developers path = process->fullPath(path); 56610037SARM gem5 Developers 56710037SARM gem5 Developers DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 56810037SARM gem5 Developers 56910037SARM gem5 Developers int fd; 57010037SARM gem5 Developers if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 57110037SARM gem5 Developers !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 57210037SARM gem5 Developers // It's a proc/sys entery and requires special handling 57310037SARM gem5 Developers fd = OS::openSpecialFile(path, process, tc); 5746735Sgblack@eecs.umich.edu return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 5756735Sgblack@eecs.umich.edu } else { 5767093Sgblack@eecs.umich.edu // open the file 5777093Sgblack@eecs.umich.edu fd = open(path.c_str(), hostFlags, mode); 5787720Sgblack@eecs.umich.edu return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 5797585SAli.Saidi@arm.com } 5807720Sgblack@eecs.umich.edu 5817720Sgblack@eecs.umich.edu} 5827720Sgblack@eecs.umich.edu 5837720Sgblack@eecs.umich.edu/// Target sysinfo() handler. 5847720Sgblack@eecs.umich.edutemplate <class OS> 5857720Sgblack@eecs.umich.eduSyscallReturn 58610037SARM gem5 DeveloperssysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 58710037SARM gem5 Developers ThreadContext *tc) 5887720Sgblack@eecs.umich.edu{ 5896019Shines@cs.fsu.edu 5907189Sgblack@eecs.umich.edu int index = 0; 5917400SAli.Saidi@ARM.com TypedBufferArg<typename OS::tgt_sysinfo> 59210417Sandreas.hansson@arm.com sysinfo(process->getSyscallArg(tc, index)); 59310037SARM gem5 Developers 59410037SARM gem5 Developers sysinfo->uptime=seconds_since_epoch; 59510037SARM gem5 Developers sysinfo->totalram=process->system->memSize(); 59610037SARM gem5 Developers 59710037SARM gem5 Developers sysinfo.copyOut(tc->getMemProxy()); 59810037SARM gem5 Developers 59910037SARM gem5 Developers return 0; 60010037SARM gem5 Developers} 60111574SCurtis.Dunham@arm.com 60211574SCurtis.Dunham@arm.com/// Target chmod() handler. 60311574SCurtis.Dunham@arm.comtemplate <class OS> 60411574SCurtis.Dunham@arm.comSyscallReturn 60511574SCurtis.Dunham@arm.comchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 60610037SARM gem5 Developers ThreadContext *tc) 60710037SARM gem5 Developers{ 60810037SARM gem5 Developers std::string path; 60910037SARM gem5 Developers 61010037SARM gem5 Developers int index = 0; 61110037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 61210037SARM gem5 Developers process->getSyscallArg(tc, index))) { 61310037SARM gem5 Developers return -EFAULT; 61410037SARM gem5 Developers } 61510037SARM gem5 Developers 61610037SARM gem5 Developers uint32_t mode = process->getSyscallArg(tc, index); 61710037SARM gem5 Developers mode_t hostMode = 0; 61810037SARM gem5 Developers 61910338SCurtis.Dunham@arm.com // XXX translate mode flags via OS::something??? 62010338SCurtis.Dunham@arm.com hostMode = mode; 62110338SCurtis.Dunham@arm.com 62210037SARM gem5 Developers // Adjust path for current working directory 62310037SARM gem5 Developers path = process->fullPath(path); 62410037SARM gem5 Developers 62510037SARM gem5 Developers // do the chmod 62610037SARM gem5 Developers int result = chmod(path.c_str(), hostMode); 62710037SARM gem5 Developers if (result < 0) 62810037SARM gem5 Developers return -errno; 62910037SARM gem5 Developers 63010037SARM gem5 Developers return 0; 63110037SARM gem5 Developers} 63210338SCurtis.Dunham@arm.com 63310037SARM gem5 Developers 63410037SARM gem5 Developers/// Target fchmod() handler. 63510037SARM gem5 Developerstemplate <class OS> 63610037SARM gem5 DevelopersSyscallReturn 63710037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 63810037SARM gem5 Developers ThreadContext *tc) 63910037SARM gem5 Developers{ 64010037SARM gem5 Developers int index = 0; 64110037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 64210037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 64310037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 64410037SARM gem5 Developers return -EBADF; 64510037SARM gem5 Developers } 64610037SARM gem5 Developers 64710037SARM gem5 Developers uint32_t mode = process->getSyscallArg(tc, index); 64810037SARM gem5 Developers mode_t hostMode = 0; 64910037SARM gem5 Developers 65010037SARM gem5 Developers // XXX translate mode flags via OS::someting??? 65110037SARM gem5 Developers hostMode = mode; 65210037SARM gem5 Developers 65310037SARM gem5 Developers // do the fchmod 65410037SARM gem5 Developers int result = fchmod(process->sim_fd(fd), hostMode); 65510037SARM gem5 Developers if (result < 0) 65610037SARM gem5 Developers return -errno; 65710037SARM gem5 Developers 65810037SARM gem5 Developers return 0; 65910037SARM gem5 Developers} 66010037SARM gem5 Developers 66110037SARM gem5 Developers/// Target mremap() handler. 66210037SARM gem5 Developerstemplate <class OS> 66310037SARM gem5 DevelopersSyscallReturn 66410037SARM gem5 DevelopersmremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 66510037SARM gem5 Developers{ 66610037SARM gem5 Developers int index = 0; 66710037SARM gem5 Developers Addr start = process->getSyscallArg(tc, index); 66810037SARM gem5 Developers uint64_t old_length = process->getSyscallArg(tc, index); 66910037SARM gem5 Developers uint64_t new_length = process->getSyscallArg(tc, index); 67010037SARM gem5 Developers uint64_t flags = process->getSyscallArg(tc, index); 67110037SARM gem5 Developers 67210037SARM gem5 Developers if ((start % TheISA::VMPageSize != 0) || 67310037SARM gem5 Developers (new_length % TheISA::VMPageSize != 0)) { 67410037SARM gem5 Developers warn("mremap failing: arguments not page aligned"); 67510037SARM gem5 Developers return -EINVAL; 67610037SARM gem5 Developers } 67710037SARM gem5 Developers 67810037SARM gem5 Developers if (new_length > old_length) { 67910037SARM gem5 Developers if ((start + old_length) == process->mmap_end) { 68010037SARM gem5 Developers uint64_t diff = new_length - old_length; 68110037SARM gem5 Developers process->allocateMem(process->mmap_end, diff); 68210417Sandreas.hansson@arm.com process->mmap_end += diff; 6837400SAli.Saidi@ARM.com return start; 6848782Sgblack@eecs.umich.edu } else { 68511150Smitch.hayenga@arm.com // sys/mman.h defined MREMAP_MAYMOVE 6868782Sgblack@eecs.umich.edu if (!(flags & 1)) { 6878782Sgblack@eecs.umich.edu warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 68810037SARM gem5 Developers return -ENOMEM; 68910037SARM gem5 Developers } else { 69010037SARM gem5 Developers process->pTable->remap(start, old_length, process->mmap_end); 69110037SARM gem5 Developers warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 69210037SARM gem5 Developers process->mmap_end, process->mmap_end + new_length, new_length); 69310037SARM gem5 Developers start = process->mmap_end; 69410037SARM gem5 Developers // add on the remaining unallocated pages 69510037SARM gem5 Developers process->allocateMem(start + old_length, 69610037SARM gem5 Developers new_length - old_length); 69710037SARM gem5 Developers process->mmap_end += new_length; 69810037SARM gem5 Developers warn("returning %08p as start\n", start); 69910037SARM gem5 Developers return start; 70010037SARM gem5 Developers } 70110037SARM gem5 Developers } 70210037SARM gem5 Developers } else { 70310037SARM gem5 Developers process->pTable->unmap(start + new_length, old_length - new_length); 70410037SARM gem5 Developers return start; 70510037SARM gem5 Developers } 70610037SARM gem5 Developers} 7077400SAli.Saidi@ARM.com 7087400SAli.Saidi@ARM.com/// Target stat() handler. 7097189Sgblack@eecs.umich.edutemplate <class OS> 71010417Sandreas.hansson@arm.comSyscallReturn 7117189Sgblack@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7128782Sgblack@eecs.umich.edu ThreadContext *tc) 7138782Sgblack@eecs.umich.edu{ 7148806Sgblack@eecs.umich.edu std::string path; 7158806Sgblack@eecs.umich.edu 7168806Sgblack@eecs.umich.edu int index = 0; 7178806Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 7188806Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 7198806Sgblack@eecs.umich.edu return -EFAULT; 7208806Sgblack@eecs.umich.edu } 7218806Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 7228806Sgblack@eecs.umich.edu 7238806Sgblack@eecs.umich.edu // Adjust path for current working directory 7248806Sgblack@eecs.umich.edu path = process->fullPath(path); 7257189Sgblack@eecs.umich.edu 7268806Sgblack@eecs.umich.edu struct stat hostBuf; 7278806Sgblack@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 7287189Sgblack@eecs.umich.edu 7297189Sgblack@eecs.umich.edu if (result < 0) 7307189Sgblack@eecs.umich.edu return -errno; 73110037SARM gem5 Developers 73210037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 73310037SARM gem5 Developers 73410037SARM gem5 Developers return 0; 73510037SARM gem5 Developers} 73610037SARM gem5 Developers 73710037SARM gem5 Developers 73810037SARM gem5 Developers/// Target stat64() handler. 73910037SARM gem5 Developerstemplate <class OS> 74010037SARM gem5 DevelopersSyscallReturn 74110037SARM gem5 Developersstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 74210037SARM gem5 Developers ThreadContext *tc) 74310037SARM gem5 Developers{ 74410037SARM gem5 Developers std::string path; 74510037SARM gem5 Developers 74610037SARM gem5 Developers int index = 0; 74710037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 74810037SARM gem5 Developers process->getSyscallArg(tc, index))) 74910037SARM gem5 Developers return -EFAULT; 75010037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 75110037SARM gem5 Developers 75210037SARM gem5 Developers // Adjust path for current working directory 75310037SARM gem5 Developers path = process->fullPath(path); 75410037SARM gem5 Developers 75510037SARM gem5 Developers#if NO_STAT64 75610037SARM gem5 Developers struct stat hostBuf; 75710037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 75810037SARM gem5 Developers#else 75910037SARM gem5 Developers struct stat64 hostBuf; 76010037SARM gem5 Developers int result = stat64(path.c_str(), &hostBuf); 76110037SARM gem5 Developers#endif 76210037SARM gem5 Developers 76310037SARM gem5 Developers if (result < 0) 76410037SARM gem5 Developers return -errno; 76510037SARM gem5 Developers 76610037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 76710037SARM gem5 Developers 76810037SARM gem5 Developers return 0; 76910037SARM gem5 Developers} 7707197Sgblack@eecs.umich.edu 77110417Sandreas.hansson@arm.com 7727197Sgblack@eecs.umich.edu/// Target fstat64() handler. 7738782Sgblack@eecs.umich.edutemplate <class OS> 7748782Sgblack@eecs.umich.eduSyscallReturn 7758806Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 7768806Sgblack@eecs.umich.edu ThreadContext *tc) 7777197Sgblack@eecs.umich.edu{ 7788806Sgblack@eecs.umich.edu int index = 0; 7798806Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 7808806Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 78110037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 78210037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 78310037SARM gem5 Developers return -EBADF; 78410037SARM gem5 Developers } 78510037SARM gem5 Developers 78610037SARM gem5 Developers#if NO_STAT64 7878806Sgblack@eecs.umich.edu struct stat hostBuf; 7888806Sgblack@eecs.umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 7898806Sgblack@eecs.umich.edu#else 7908806Sgblack@eecs.umich.edu struct stat64 hostBuf; 7918806Sgblack@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 7928806Sgblack@eecs.umich.edu#endif 7938806Sgblack@eecs.umich.edu 7947197Sgblack@eecs.umich.edu if (result < 0) 7957197Sgblack@eecs.umich.edu return -errno; 79610037SARM gem5 Developers 79710037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 79810037SARM gem5 Developers 79910037SARM gem5 Developers return 0; 80010037SARM gem5 Developers} 80110037SARM gem5 Developers 80210037SARM gem5 Developers 80310037SARM gem5 Developers/// Target lstat() handler. 80410037SARM gem5 Developerstemplate <class OS> 80510037SARM gem5 DevelopersSyscallReturn 80610037SARM gem5 DeveloperslstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 80710037SARM gem5 Developers ThreadContext *tc) 80810037SARM gem5 Developers{ 80910037SARM gem5 Developers std::string path; 81010037SARM gem5 Developers 81110037SARM gem5 Developers int index = 0; 81210037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 81310037SARM gem5 Developers process->getSyscallArg(tc, index))) { 81410037SARM gem5 Developers return -EFAULT; 81510037SARM gem5 Developers } 81610037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 81710037SARM gem5 Developers 81810037SARM gem5 Developers // Adjust path for current working directory 81910037SARM gem5 Developers path = process->fullPath(path); 82010037SARM gem5 Developers 82110037SARM gem5 Developers struct stat hostBuf; 82210037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 82310037SARM gem5 Developers 82410037SARM gem5 Developers if (result < 0) 82510037SARM gem5 Developers return -errno; 82610037SARM gem5 Developers 82710037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 82810037SARM gem5 Developers 82910037SARM gem5 Developers return 0; 83010037SARM gem5 Developers} 83110037SARM gem5 Developers 83210037SARM gem5 Developers/// Target lstat64() handler. 83310037SARM gem5 Developerstemplate <class OS> 83410037SARM gem5 DevelopersSyscallReturn 83510037SARM gem5 Developerslstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 83610037SARM gem5 Developers ThreadContext *tc) 83710037SARM gem5 Developers{ 83810037SARM gem5 Developers std::string path; 83910037SARM gem5 Developers 84010037SARM gem5 Developers int index = 0; 84110037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 84210037SARM gem5 Developers process->getSyscallArg(tc, index))) { 84310037SARM gem5 Developers return -EFAULT; 84410037SARM gem5 Developers } 84510037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 84610037SARM gem5 Developers 84711576SDylan.Johnson@ARM.com // Adjust path for current working directory 84811576SDylan.Johnson@ARM.com path = process->fullPath(path); 84911576SDylan.Johnson@ARM.com 85011576SDylan.Johnson@ARM.com#if NO_STAT64 85111576SDylan.Johnson@ARM.com struct stat hostBuf; 85211576SDylan.Johnson@ARM.com int result = lstat(path.c_str(), &hostBuf); 85310037SARM gem5 Developers#else 85410037SARM gem5 Developers struct stat64 hostBuf; 85510037SARM gem5 Developers int result = lstat64(path.c_str(), &hostBuf); 85610037SARM gem5 Developers#endif 85710037SARM gem5 Developers 85810037SARM gem5 Developers if (result < 0) 85910037SARM gem5 Developers return -errno; 86010037SARM gem5 Developers 86110037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 86210037SARM gem5 Developers 86310037SARM gem5 Developers return 0; 86410037SARM gem5 Developers} 86510037SARM gem5 Developers 86610037SARM gem5 Developers/// Target fstat() handler. 86710037SARM gem5 Developerstemplate <class OS> 86810037SARM gem5 DevelopersSyscallReturn 86910037SARM gem5 DevelopersfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 87010037SARM gem5 Developers ThreadContext *tc) 87110037SARM gem5 Developers{ 87210037SARM gem5 Developers int index = 0; 87310037SARM gem5 Developers int fd = process->sim_fd(process->getSyscallArg(tc, index)); 87410037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 87510037SARM gem5 Developers 87610037SARM gem5 Developers DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 87710037SARM gem5 Developers 87810037SARM gem5 Developers if (fd < 0) 87910037SARM gem5 Developers return -EBADF; 88010037SARM gem5 Developers 88110037SARM gem5 Developers struct stat hostBuf; 88210037SARM gem5 Developers int result = fstat(fd, &hostBuf); 88310037SARM gem5 Developers 88410037SARM gem5 Developers if (result < 0) 88510037SARM gem5 Developers return -errno; 88610037SARM gem5 Developers 88710037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 88810037SARM gem5 Developers 88910037SARM gem5 Developers return 0; 89010037SARM gem5 Developers} 89110037SARM gem5 Developers 89210037SARM gem5 Developers 89310037SARM gem5 Developers/// Target statfs() handler. 89410417Sandreas.hansson@arm.comtemplate <class OS> 89510037SARM gem5 DevelopersSyscallReturn 89610037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 89710037SARM gem5 Developers ThreadContext *tc) 89810037SARM gem5 Developers{ 89910037SARM gem5 Developers std::string path; 90010037SARM gem5 Developers 90110037SARM gem5 Developers int index = 0; 90210037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 90310037SARM gem5 Developers process->getSyscallArg(tc, index))) { 90410037SARM gem5 Developers return -EFAULT; 90510037SARM gem5 Developers } 90610037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 90710037SARM gem5 Developers 90810037SARM gem5 Developers // Adjust path for current working directory 90910037SARM gem5 Developers path = process->fullPath(path); 91010037SARM gem5 Developers 91110037SARM gem5 Developers struct statfs hostBuf; 91210037SARM gem5 Developers int result = statfs(path.c_str(), &hostBuf); 91310037SARM gem5 Developers 91410037SARM gem5 Developers if (result < 0) 91510037SARM gem5 Developers return -errno; 91610037SARM gem5 Developers 91710037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 91810037SARM gem5 Developers 91910037SARM gem5 Developers return 0; 92010037SARM gem5 Developers} 9217362Sgblack@eecs.umich.edu 9227362Sgblack@eecs.umich.edu 92310417Sandreas.hansson@arm.com/// Target fstatfs() handler. 9247362Sgblack@eecs.umich.edutemplate <class OS> 92510037SARM gem5 DevelopersSyscallReturn 92610037SARM gem5 DevelopersfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 92710037SARM gem5 Developers ThreadContext *tc) 92810037SARM gem5 Developers{ 92910037SARM gem5 Developers int index = 0; 93010037SARM gem5 Developers int fd = process->sim_fd(process->getSyscallArg(tc, index)); 93110037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 93210037SARM gem5 Developers 93310037SARM gem5 Developers if (fd < 0) 93410037SARM gem5 Developers return -EBADF; 93510037SARM gem5 Developers 93610037SARM gem5 Developers struct statfs hostBuf; 93710037SARM gem5 Developers int result = fstatfs(fd, &hostBuf); 93810037SARM gem5 Developers 93910037SARM gem5 Developers if (result < 0) 94010037SARM gem5 Developers return -errno; 94110037SARM gem5 Developers 94210037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 94310037SARM gem5 Developers 94410037SARM gem5 Developers return 0; 94510037SARM gem5 Developers} 94610037SARM gem5 Developers 94710037SARM gem5 Developers 94811150Smitch.hayenga@arm.com/// Target writev() handler. 94910037SARM gem5 Developerstemplate <class OS> 95010037SARM gem5 DevelopersSyscallReturn 95110037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 95210037SARM gem5 Developers ThreadContext *tc) 95310037SARM gem5 Developers{ 95410037SARM gem5 Developers int index = 0; 95510037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 9568205SAli.Saidi@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 95710037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 95811496Sandreas.sandberg@arm.com return -EBADF; 95910037SARM gem5 Developers } 96010037SARM gem5 Developers 96110037SARM gem5 Developers SETranslatingPortProxy &p = tc->getMemProxy(); 96210037SARM gem5 Developers uint64_t tiov_base = process->getSyscallArg(tc, index); 96310037SARM gem5 Developers size_t count = process->getSyscallArg(tc, index); 96410037SARM gem5 Developers struct iovec hiov[count]; 96510037SARM gem5 Developers for (size_t i = 0; i < count; ++i) { 96610037SARM gem5 Developers typename OS::tgt_iovec tiov; 96710037SARM gem5 Developers 96810037SARM gem5 Developers p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 96910037SARM gem5 Developers (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 97010037SARM gem5 Developers hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 97110037SARM gem5 Developers hiov[i].iov_base = new char [hiov[i].iov_len]; 97210037SARM gem5 Developers p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 97311585SDylan.Johnson@ARM.com hiov[i].iov_len); 97411585SDylan.Johnson@ARM.com } 97511585SDylan.Johnson@ARM.com 97611585SDylan.Johnson@ARM.com int result = writev(process->sim_fd(fd), hiov, count); 97711585SDylan.Johnson@ARM.com 97811585SDylan.Johnson@ARM.com for (size_t i = 0; i < count; ++i) 97911585SDylan.Johnson@ARM.com delete [] (char *)hiov[i].iov_base; 98011585SDylan.Johnson@ARM.com 98111585SDylan.Johnson@ARM.com if (result < 0) 98211585SDylan.Johnson@ARM.com return -errno; 98311585SDylan.Johnson@ARM.com 98410037SARM gem5 Developers return 0; 98510037SARM gem5 Developers} 98610037SARM gem5 Developers 98710037SARM gem5 Developers 98810037SARM gem5 Developers/// Target mmap() handler. 98910037SARM gem5 Developers/// 99010037SARM gem5 Developers/// We don't really handle mmap(). If the target is mmaping an 9917362Sgblack@eecs.umich.edu/// anonymous region or /dev/zero, we can get away with doing basically 9928314Sgeoffrey.blake@arm.com/// nothing (since memory is initialized to zero and the simulator 99310037SARM gem5 Developers/// doesn't really check addresses anyway). 99410037SARM gem5 Developers/// 99510037SARM gem5 Developerstemplate <class OS> 99610037SARM gem5 DevelopersSyscallReturn 99710037SARM gem5 DevelopersmmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 99810037SARM gem5 Developers{ 99910037SARM gem5 Developers int index = 0; 100010037SARM gem5 Developers Addr start = p->getSyscallArg(tc, index); 100110037SARM gem5 Developers uint64_t length = p->getSyscallArg(tc, index); 100210037SARM gem5 Developers index++; // int prot = p->getSyscallArg(tc, index); 100310037SARM gem5 Developers int flags = p->getSyscallArg(tc, index); 100410037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 100510037SARM gem5 Developers // int offset = p->getSyscallArg(tc, index); 100610037SARM gem5 Developers 100710037SARM gem5 Developers if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 100810037SARM gem5 Developers Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 100910037SARM gem5 Developers if (!fd_map || fd_map->fd < 0) { 101010037SARM gem5 Developers warn("mmap failing: target fd %d is not valid\n", tgt_fd); 101110037SARM gem5 Developers return -EBADF; 101210037SARM gem5 Developers } 101310037SARM gem5 Developers 101410037SARM gem5 Developers if (fd_map->filename != "/dev/zero") { 101510037SARM gem5 Developers // This is very likely broken, but leave a warning here 101610037SARM gem5 Developers // (rather than panic) in case /dev/zero is known by 101710037SARM gem5 Developers // another name on some platform 101810037SARM gem5 Developers warn("allowing mmap of file %s; mmap not supported on files" 101910037SARM gem5 Developers " other than /dev/zero\n", fd_map->filename); 102010037SARM gem5 Developers } 102110037SARM gem5 Developers } 102210037SARM gem5 Developers 102310037SARM gem5 Developers if ((start % TheISA::VMPageSize) != 0 || 102410037SARM gem5 Developers (length % TheISA::VMPageSize) != 0) { 102510037SARM gem5 Developers warn("mmap failing: arguments not page-aligned: " 102610037SARM gem5 Developers "start 0x%x length 0x%x", 102710037SARM gem5 Developers start, length); 102810037SARM gem5 Developers return -EINVAL; 102910037SARM gem5 Developers } 103010037SARM gem5 Developers 103110037SARM gem5 Developers // are we ok with clobbering existing mappings? only set this to 103210037SARM gem5 Developers // true if the user has been warned. 103310037SARM gem5 Developers bool clobber = false; 103410037SARM gem5 Developers 103510037SARM gem5 Developers // try to use the caller-provided address if there is one 103610037SARM gem5 Developers bool use_provided_address = (start != 0); 103710037SARM gem5 Developers 103810037SARM gem5 Developers if (use_provided_address) { 103910037SARM gem5 Developers // check to see if the desired address is already in use 104010037SARM gem5 Developers if (!p->pTable->isUnmapped(start, length)) { 104110037SARM gem5 Developers // there are existing mappings in the desired range 104210037SARM gem5 Developers // whether we clobber them or not depends on whether the caller 104310037SARM gem5 Developers // specified MAP_FIXED 104410037SARM gem5 Developers if (flags & OS::TGT_MAP_FIXED) { 104510037SARM gem5 Developers // MAP_FIXED specified: clobber existing mappings 104610037SARM gem5 Developers warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 104710037SARM gem5 Developers start); 104810037SARM gem5 Developers clobber = true; 104910037SARM gem5 Developers } else { 105010037SARM gem5 Developers // MAP_FIXED not specified: ignore suggested start address 105110037SARM gem5 Developers warn("mmap: ignoring suggested map address 0x%x\n", start); 105210037SARM gem5 Developers use_provided_address = false; 105310037SARM gem5 Developers } 105410037SARM gem5 Developers } 105510037SARM gem5 Developers } 105610037SARM gem5 Developers 105710037SARM gem5 Developers if (!use_provided_address) { 105810037SARM gem5 Developers // no address provided, or provided address unusable: 105910037SARM gem5 Developers // pick next address from our "mmap region" 106010037SARM gem5 Developers if (OS::mmapGrowsDown()) { 106110037SARM gem5 Developers start = p->mmap_end - length; 106210037SARM gem5 Developers p->mmap_end = start; 106310037SARM gem5 Developers } else { 106410037SARM gem5 Developers start = p->mmap_end; 106510037SARM gem5 Developers p->mmap_end += length; 106610037SARM gem5 Developers } 106710037SARM gem5 Developers } 106810037SARM gem5 Developers 106910037SARM gem5 Developers p->allocateMem(start, length, clobber); 107010037SARM gem5 Developers 107110037SARM gem5 Developers return start; 107210037SARM gem5 Developers} 107310037SARM gem5 Developers 107410037SARM gem5 Developers/// Target getrlimit() handler. 107510037SARM gem5 Developerstemplate <class OS> 107610037SARM gem5 DevelopersSyscallReturn 107710037SARM gem5 DevelopersgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 107810037SARM gem5 Developers ThreadContext *tc) 107910037SARM gem5 Developers{ 108010037SARM gem5 Developers int index = 0; 108110037SARM gem5 Developers unsigned resource = process->getSyscallArg(tc, index); 108210037SARM gem5 Developers TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 108310037SARM gem5 Developers 108410037SARM gem5 Developers switch (resource) { 108510037SARM gem5 Developers case OS::TGT_RLIMIT_STACK: 108610037SARM gem5 Developers // max stack size in bytes: make up a number (8MB for now) 108710037SARM gem5 Developers rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 108810037SARM gem5 Developers rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 108910037SARM gem5 Developers rlp->rlim_max = TheISA::htog(rlp->rlim_max); 109010037SARM gem5 Developers break; 109110037SARM gem5 Developers 109210037SARM gem5 Developers case OS::TGT_RLIMIT_DATA: 109310037SARM gem5 Developers // max data segment size in bytes: make up a number 109410037SARM gem5 Developers rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 109510037SARM gem5 Developers rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 109610037SARM gem5 Developers rlp->rlim_max = TheISA::htog(rlp->rlim_max); 109710037SARM gem5 Developers break; 109810037SARM gem5 Developers 109910037SARM gem5 Developers default: 110010037SARM gem5 Developers std::cerr << "getrlimitFunc: unimplemented resource " << resource 110110037SARM gem5 Developers << std::endl; 110210037SARM gem5 Developers abort(); 110310037SARM gem5 Developers break; 110410037SARM gem5 Developers } 110510037SARM gem5 Developers 110610037SARM gem5 Developers rlp.copyOut(tc->getMemProxy()); 110710037SARM gem5 Developers return 0; 110810037SARM gem5 Developers} 110910037SARM gem5 Developers 111010037SARM gem5 Developers/// Target gettimeofday() handler. 111110037SARM gem5 Developerstemplate <class OS> 111210037SARM gem5 DevelopersSyscallReturn 111310037SARM gem5 DevelopersgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 111410037SARM gem5 Developers ThreadContext *tc) 111510037SARM gem5 Developers{ 111610037SARM gem5 Developers int index = 0; 111710037SARM gem5 Developers TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 111810037SARM gem5 Developers 111910037SARM gem5 Developers getElapsedTime(tp->tv_sec, tp->tv_usec); 112010037SARM gem5 Developers tp->tv_sec += seconds_since_epoch; 112110037SARM gem5 Developers tp->tv_sec = TheISA::htog(tp->tv_sec); 112210037SARM gem5 Developers tp->tv_usec = TheISA::htog(tp->tv_usec); 112310037SARM gem5 Developers 112410037SARM gem5 Developers tp.copyOut(tc->getMemProxy()); 112510037SARM gem5 Developers 112610037SARM gem5 Developers return 0; 112710037SARM gem5 Developers} 112810037SARM gem5 Developers 112910037SARM gem5 Developers 113011581SDylan.Johnson@ARM.com/// Target utimes() handler. 113110037SARM gem5 Developerstemplate <class OS> 113210037SARM gem5 DevelopersSyscallReturn 113310037SARM gem5 DevelopersutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 113410037SARM gem5 Developers ThreadContext *tc) 113510037SARM gem5 Developers{ 113610037SARM gem5 Developers std::string path; 113710037SARM gem5 Developers 113810037SARM gem5 Developers int index = 0; 113910037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 114010367SAndrew.Bardsley@arm.com process->getSyscallArg(tc, index))) { 114110367SAndrew.Bardsley@arm.com return -EFAULT; 114210037SARM gem5 Developers } 114310037SARM gem5 Developers 114410037SARM gem5 Developers TypedBufferArg<typename OS::timeval [2]> 114510037SARM gem5 Developers tp(process->getSyscallArg(tc, index)); 114610037SARM gem5 Developers tp.copyIn(tc->getMemProxy()); 114710037SARM gem5 Developers 114810037SARM gem5 Developers struct timeval hostTimeval[2]; 114910037SARM gem5 Developers for (int i = 0; i < 2; ++i) 115010037SARM gem5 Developers { 115110037SARM gem5 Developers hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 115210037SARM gem5 Developers hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 115310037SARM gem5 Developers } 115410037SARM gem5 Developers 115510037SARM gem5 Developers // Adjust path for current working directory 115610037SARM gem5 Developers path = process->fullPath(path); 115710037SARM gem5 Developers 115810037SARM gem5 Developers int result = utimes(path.c_str(), hostTimeval); 115910037SARM gem5 Developers 116010037SARM gem5 Developers if (result < 0) 116110037SARM gem5 Developers return -errno; 116210037SARM gem5 Developers 116310037SARM gem5 Developers return 0; 116410037SARM gem5 Developers} 116510037SARM gem5 Developers/// Target getrusage() function. 116610037SARM gem5 Developerstemplate <class OS> 116710037SARM gem5 DevelopersSyscallReturn 116810037SARM gem5 DevelopersgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 116910037SARM gem5 Developers ThreadContext *tc) 117010037SARM gem5 Developers{ 117110037SARM gem5 Developers int index = 0; 117210037SARM gem5 Developers int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 117310037SARM gem5 Developers TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 117410037SARM gem5 Developers 117510037SARM gem5 Developers rup->ru_utime.tv_sec = 0; 117610037SARM gem5 Developers rup->ru_utime.tv_usec = 0; 117710037SARM gem5 Developers rup->ru_stime.tv_sec = 0; 117810037SARM gem5 Developers rup->ru_stime.tv_usec = 0; 117910037SARM gem5 Developers rup->ru_maxrss = 0; 118010037SARM gem5 Developers rup->ru_ixrss = 0; 118110037SARM gem5 Developers rup->ru_idrss = 0; 118210037SARM gem5 Developers rup->ru_isrss = 0; 118310037SARM gem5 Developers rup->ru_minflt = 0; 118410037SARM gem5 Developers rup->ru_majflt = 0; 118510037SARM gem5 Developers rup->ru_nswap = 0; 118610037SARM gem5 Developers rup->ru_inblock = 0; 118710037SARM gem5 Developers rup->ru_oublock = 0; 118810037SARM gem5 Developers rup->ru_msgsnd = 0; 118910037SARM gem5 Developers rup->ru_msgrcv = 0; 119010037SARM gem5 Developers rup->ru_nsignals = 0; 119110037SARM gem5 Developers rup->ru_nvcsw = 0; 119210037SARM gem5 Developers rup->ru_nivcsw = 0; 119310037SARM gem5 Developers 119410037SARM gem5 Developers switch (who) { 119510037SARM gem5 Developers case OS::TGT_RUSAGE_SELF: 119611581SDylan.Johnson@ARM.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 119710037SARM gem5 Developers rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 119810037SARM gem5 Developers rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 119910037SARM gem5 Developers break; 120010037SARM gem5 Developers 120110037SARM gem5 Developers case OS::TGT_RUSAGE_CHILDREN: 120210037SARM gem5 Developers // do nothing. We have no child processes, so they take no time. 120310037SARM gem5 Developers break; 120410037SARM gem5 Developers 120510037SARM gem5 Developers default: 120610037SARM gem5 Developers // don't really handle THREAD or CHILDREN, but just warn and 120710037SARM gem5 Developers // plow ahead 120810037SARM gem5 Developers warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 120910037SARM gem5 Developers who); 121010037SARM gem5 Developers } 121110037SARM gem5 Developers 121210037SARM gem5 Developers rup.copyOut(tc->getMemProxy()); 121310037SARM gem5 Developers 121410037SARM gem5 Developers return 0; 121510037SARM gem5 Developers} 121610037SARM gem5 Developers 121710037SARM gem5 Developers/// Target times() function. 121810037SARM gem5 Developerstemplate <class OS> 121910037SARM gem5 DevelopersSyscallReturn 122010037SARM gem5 DeveloperstimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 122110037SARM gem5 Developers ThreadContext *tc) 122210037SARM gem5 Developers{ 122310037SARM gem5 Developers int index = 0; 122410037SARM gem5 Developers TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 122510037SARM gem5 Developers 122610037SARM gem5 Developers // Fill in the time structure (in clocks) 122710037SARM gem5 Developers int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 122810037SARM gem5 Developers bufp->tms_utime = clocks; 122910037SARM gem5 Developers bufp->tms_stime = 0; 123010037SARM gem5 Developers bufp->tms_cutime = 0; 123110037SARM gem5 Developers bufp->tms_cstime = 0; 123210037SARM gem5 Developers 123310037SARM gem5 Developers // Convert to host endianness 123410037SARM gem5 Developers bufp->tms_utime = TheISA::htog(bufp->tms_utime); 123510037SARM gem5 Developers 123610037SARM gem5 Developers // Write back 123710037SARM gem5 Developers bufp.copyOut(tc->getMemProxy()); 123810037SARM gem5 Developers 123910037SARM gem5 Developers // Return clock ticks since system boot 124010037SARM gem5 Developers return clocks; 124110037SARM gem5 Developers} 124210037SARM gem5 Developers 124310037SARM gem5 Developers/// Target time() function. 124410037SARM gem5 Developerstemplate <class OS> 124510037SARM gem5 DevelopersSyscallReturn 124610037SARM gem5 DeveloperstimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 124710037SARM gem5 Developers ThreadContext *tc) 124810037SARM gem5 Developers{ 124910037SARM gem5 Developers typename OS::time_t sec, usec; 125010037SARM gem5 Developers getElapsedTime(sec, usec); 125110037SARM gem5 Developers sec += seconds_since_epoch; 125210037SARM gem5 Developers 125310037SARM gem5 Developers int index = 0; 125410037SARM gem5 Developers Addr taddr = (Addr)process->getSyscallArg(tc, index); 125510037SARM gem5 Developers if(taddr != 0) { 125610037SARM gem5 Developers typename OS::time_t t = sec; 125710417Sandreas.hansson@arm.com t = TheISA::htog(t); 125810037SARM gem5 Developers SETranslatingPortProxy &p = tc->getMemProxy(); 125910037SARM gem5 Developers p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 126010037SARM gem5 Developers } 126110037SARM gem5 Developers return sec; 126210037SARM gem5 Developers} 126310037SARM gem5 Developers 126410037SARM gem5 Developers 126510037SARM gem5 Developers#endif // __SIM_SYSCALL_EMUL_HH__ 126610037SARM gem5 Developers