syscall_emul.hh revision 3113
19651SAndreas.Sandberg@ARM.com/* 210858Sandreas.sandberg@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 39651SAndreas.Sandberg@ARM.com * All rights reserved. 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 69651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 79651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 89651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 99651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 109651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 119651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 129651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 139651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 149651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 159651SAndreas.Sandberg@ARM.com * 169651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279651SAndreas.Sandberg@ARM.com * 289651SAndreas.Sandberg@ARM.com * Authors: Steve Reinhardt 299651SAndreas.Sandberg@ARM.com * Kevin Lim 309651SAndreas.Sandberg@ARM.com */ 319651SAndreas.Sandberg@ARM.com 329651SAndreas.Sandberg@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__ 339651SAndreas.Sandberg@ARM.com#define __SIM_SYSCALL_EMUL_HH__ 349651SAndreas.Sandberg@ARM.com 359651SAndreas.Sandberg@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 369651SAndreas.Sandberg@ARM.com defined(__FreeBSD__) || defined(__CYGWIN__)) 379651SAndreas.Sandberg@ARM.com 389651SAndreas.Sandberg@ARM.com/// 399651SAndreas.Sandberg@ARM.com/// @file syscall_emul.hh 4011793Sbrandon.potter@amd.com/// 4111793Sbrandon.potter@amd.com/// This file defines objects used to emulate syscalls from the target 429651SAndreas.Sandberg@ARM.com/// application on the host machine. 439651SAndreas.Sandberg@ARM.com 449651SAndreas.Sandberg@ARM.com#include <errno.h> 459651SAndreas.Sandberg@ARM.com#include <string> 469651SAndreas.Sandberg@ARM.com#ifdef __CYGWIN32__ 479651SAndreas.Sandberg@ARM.com#include <sys/fcntl.h> // for O_BINARY 489651SAndreas.Sandberg@ARM.com#endif 499651SAndreas.Sandberg@ARM.com#include <sys/stat.h> 509651SAndreas.Sandberg@ARM.com#include <fcntl.h> 519760Sandreas@sandberg.pp.se#include <sys/uio.h> 529651SAndreas.Sandberg@ARM.com 539683Sandreas@sandberg.pp.se#include "sim/host.hh" // for Addr 549753Sandreas@sandberg.pp.se#include "base/chunk_generator.hh" 559651SAndreas.Sandberg@ARM.com#include "base/intmath.hh" // for RoundUp 569651SAndreas.Sandberg@ARM.com#include "base/misc.hh" 579651SAndreas.Sandberg@ARM.com#include "base/trace.hh" 589651SAndreas.Sandberg@ARM.com#include "cpu/base.hh" 599651SAndreas.Sandberg@ARM.com#include "cpu/thread_context.hh" 609651SAndreas.Sandberg@ARM.com#include "mem/translating_port.hh" 619651SAndreas.Sandberg@ARM.com#include "mem/page_table.hh" 629651SAndreas.Sandberg@ARM.com#include "sim/process.hh" 639651SAndreas.Sandberg@ARM.com 649651SAndreas.Sandberg@ARM.com/// 659651SAndreas.Sandberg@ARM.com/// System call descriptor. 669651SAndreas.Sandberg@ARM.com/// 6711839SCurtis.Dunham@arm.comclass SyscallDesc { 689651SAndreas.Sandberg@ARM.com 699651SAndreas.Sandberg@ARM.com public: 709651SAndreas.Sandberg@ARM.com 7111399Sandreas.sandberg@arm.com /// Typedef for target syscall handler functions. 729652SAndreas.Sandberg@ARM.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 739652SAndreas.Sandberg@ARM.com Process *, ThreadContext *); 749651SAndreas.Sandberg@ARM.com 759651SAndreas.Sandberg@ARM.com const char *name; //!< Syscall name (e.g., "open"). 769651SAndreas.Sandberg@ARM.com FuncPtr funcPtr; //!< Pointer to emulation function. 779651SAndreas.Sandberg@ARM.com int flags; //!< Flags (see Flags enum). 789892Sandreas@sandberg.pp.se 799655SAndreas.Sandberg@ARM.com /// Flag values for controlling syscall behavior. 809752Sandreas@sandberg.pp.se enum Flags { 819752Sandreas@sandberg.pp.se /// Don't set return regs according to funcPtr return value. 829651SAndreas.Sandberg@ARM.com /// Used for syscalls with non-standard return conventions 839651SAndreas.Sandberg@ARM.com /// that explicitly set the ThreadContext regs (e.g., 849651SAndreas.Sandberg@ARM.com /// sigreturn). 859651SAndreas.Sandberg@ARM.com SuppressReturnValue = 1 869651SAndreas.Sandberg@ARM.com }; 8710553Salexandru.dutu@amd.com 8810553Salexandru.dutu@amd.com /// Constructor. 8910553Salexandru.dutu@amd.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9010553Salexandru.dutu@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 9110553Salexandru.dutu@amd.com { 9210553Salexandru.dutu@amd.com } 9310553Salexandru.dutu@amd.com 9410553Salexandru.dutu@amd.com /// Emulate the syscall. Public interface for calling through funcPtr. 959651SAndreas.Sandberg@ARM.com void doSyscall(int callnum, Process *proc, ThreadContext *tc); 969651SAndreas.Sandberg@ARM.com}; 979651SAndreas.Sandberg@ARM.com 989651SAndreas.Sandberg@ARM.com 999651SAndreas.Sandberg@ARM.comclass BaseBufferArg { 1009651SAndreas.Sandberg@ARM.com 1019651SAndreas.Sandberg@ARM.com public: 1029651SAndreas.Sandberg@ARM.com 1039651SAndreas.Sandberg@ARM.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 1049651SAndreas.Sandberg@ARM.com { 1059651SAndreas.Sandberg@ARM.com bufPtr = new uint8_t[size]; 1069651SAndreas.Sandberg@ARM.com // clear out buffer: in case we only partially populate this, 1079651SAndreas.Sandberg@ARM.com // and then do a copyOut(), we want to make sure we don't 1089651SAndreas.Sandberg@ARM.com // introduce any random junk into the simulated address space 1099651SAndreas.Sandberg@ARM.com memset(bufPtr, 0, size); 1109651SAndreas.Sandberg@ARM.com } 1119651SAndreas.Sandberg@ARM.com 1129651SAndreas.Sandberg@ARM.com virtual ~BaseBufferArg() { delete [] bufPtr; } 1139651SAndreas.Sandberg@ARM.com 1149651SAndreas.Sandberg@ARM.com // 1159651SAndreas.Sandberg@ARM.com // copy data into simulator space (read from target memory) 1169651SAndreas.Sandberg@ARM.com // 1179651SAndreas.Sandberg@ARM.com virtual bool copyIn(TranslatingPort *memport) 1189651SAndreas.Sandberg@ARM.com { 1199651SAndreas.Sandberg@ARM.com memport->readBlob(addr, bufPtr, size); 1209651SAndreas.Sandberg@ARM.com return true; // no EFAULT detection for now 1219651SAndreas.Sandberg@ARM.com } 1229651SAndreas.Sandberg@ARM.com 1239651SAndreas.Sandberg@ARM.com // 1249651SAndreas.Sandberg@ARM.com // copy data out of simulator space (write to target memory) 1259690Sandreas@sandberg.pp.se // 1269690Sandreas@sandberg.pp.se virtual bool copyOut(TranslatingPort *memport) 1279690Sandreas@sandberg.pp.se { 12811363Sandreas@sandberg.pp.se memport->writeBlob(addr, bufPtr, size); 1299651SAndreas.Sandberg@ARM.com return true; // no EFAULT detection for now 1309651SAndreas.Sandberg@ARM.com } 1319651SAndreas.Sandberg@ARM.com 1329651SAndreas.Sandberg@ARM.com protected: 1339651SAndreas.Sandberg@ARM.com Addr addr; 1349651SAndreas.Sandberg@ARM.com int size; 1359651SAndreas.Sandberg@ARM.com uint8_t *bufPtr; 1369651SAndreas.Sandberg@ARM.com}; 1379651SAndreas.Sandberg@ARM.com 1389651SAndreas.Sandberg@ARM.com 1399651SAndreas.Sandberg@ARM.comclass BufferArg : public BaseBufferArg 1409651SAndreas.Sandberg@ARM.com{ 1419651SAndreas.Sandberg@ARM.com public: 1429651SAndreas.Sandberg@ARM.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1439651SAndreas.Sandberg@ARM.com void *bufferPtr() { return bufPtr; } 1449651SAndreas.Sandberg@ARM.com}; 1459651SAndreas.Sandberg@ARM.com 1469651SAndreas.Sandberg@ARM.comtemplate <class T> 1479651SAndreas.Sandberg@ARM.comclass TypedBufferArg : public BaseBufferArg 1489651SAndreas.Sandberg@ARM.com{ 1499651SAndreas.Sandberg@ARM.com public: 1509651SAndreas.Sandberg@ARM.com // user can optionally specify a specific number of bytes to 1519651SAndreas.Sandberg@ARM.com // allocate to deal with those structs that have variable-size 1529651SAndreas.Sandberg@ARM.com // arrays at the end 1539651SAndreas.Sandberg@ARM.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1549690Sandreas@sandberg.pp.se : BaseBufferArg(_addr, _size) 1559690Sandreas@sandberg.pp.se { } 1569690Sandreas@sandberg.pp.se 1579651SAndreas.Sandberg@ARM.com // type case 1589651SAndreas.Sandberg@ARM.com operator T*() { return (T *)bufPtr; } 1599651SAndreas.Sandberg@ARM.com 1609651SAndreas.Sandberg@ARM.com // dereference operators 1619651SAndreas.Sandberg@ARM.com T &operator*() { return *((T *)bufPtr); } 1629651SAndreas.Sandberg@ARM.com T* operator->() { return (T *)bufPtr; } 1639732Sandreas@sandberg.pp.se T &operator[](int i) { return ((T *)bufPtr)[i]; } 1649732Sandreas@sandberg.pp.se}; 16510073Sandreas@sandberg.pp.se 16610073Sandreas@sandberg.pp.se////////////////////////////////////////////////////////////////////// 16712085Sspwilson2@wisc.edu// 16810073Sandreas@sandberg.pp.se// The following emulation functions are generic enough that they 16910073Sandreas@sandberg.pp.se// don't need to be recompiled for different emulated OS's. They are 17010073Sandreas@sandberg.pp.se// defined in sim/syscall_emul.cc. 17111629Smichael.lebeane@amd.com// 17211629Smichael.lebeane@amd.com////////////////////////////////////////////////////////////////////// 17311629Smichael.lebeane@amd.com 17411629Smichael.lebeane@amd.com 17511629Smichael.lebeane@amd.com/// Handler for unimplemented syscalls that we haven't thought about. 17611629Smichael.lebeane@amd.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 17711629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 17811629Smichael.lebeane@amd.com 17911629Smichael.lebeane@amd.com/// Handler for unimplemented syscalls that we never intend to 18011629Smichael.lebeane@amd.com/// implement (signal handling, etc.) and should not affect the correct 18111629Smichael.lebeane@amd.com/// behavior of the program. Print a warning only if the appropriate 18211629Smichael.lebeane@amd.com/// trace flag is enabled. Return success to the target program. 18311629Smichael.lebeane@amd.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 18411629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 18511629Smichael.lebeane@amd.com 18611629Smichael.lebeane@amd.com/// Target exit() handler: terminate simulation. 18711629Smichael.lebeane@amd.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 18811629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 18911629Smichael.lebeane@amd.com 19011629Smichael.lebeane@amd.com/// Target getpagesize() handler. 19111629Smichael.lebeane@amd.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 19211629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 19311629Smichael.lebeane@amd.com 19411629Smichael.lebeane@amd.com/// Target obreak() handler: set brk address. 19511629Smichael.lebeane@amd.comSyscallReturn obreakFunc(SyscallDesc *desc, int num, 19611629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 19711629Smichael.lebeane@amd.com 19811629Smichael.lebeane@amd.com/// Target close() handler. 19911629Smichael.lebeane@amd.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 20011629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 20111629Smichael.lebeane@amd.com 20211629Smichael.lebeane@amd.com/// Target read() handler. 20311629Smichael.lebeane@amd.comSyscallReturn readFunc(SyscallDesc *desc, int num, 20411629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 20511629Smichael.lebeane@amd.com 20611629Smichael.lebeane@amd.com/// Target write() handler. 20711629Smichael.lebeane@amd.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 20811629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 20911629Smichael.lebeane@amd.com 21011629Smichael.lebeane@amd.com/// Target lseek() handler. 21111629Smichael.lebeane@amd.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 21211629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 21311629Smichael.lebeane@amd.com 21411629Smichael.lebeane@amd.com/// Target munmap() handler. 21511629Smichael.lebeane@amd.comSyscallReturn munmapFunc(SyscallDesc *desc, int num, 21611629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 21711629Smichael.lebeane@amd.com 21811629Smichael.lebeane@amd.com/// Target gethostname() handler. 21911629Smichael.lebeane@amd.comSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 22011629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 22111629Smichael.lebeane@amd.com 22211629Smichael.lebeane@amd.com/// Target unlink() handler. 22311629Smichael.lebeane@amd.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 22411629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 22511629Smichael.lebeane@amd.com 22611629Smichael.lebeane@amd.com/// Target rename() handler. 22711629Smichael.lebeane@amd.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 22811629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 22911629Smichael.lebeane@amd.com 23011629Smichael.lebeane@amd.com 23111629Smichael.lebeane@amd.com/// Target truncate() handler. 23211629Smichael.lebeane@amd.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 23311629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 23411629Smichael.lebeane@amd.com 23511629Smichael.lebeane@amd.com 23611629Smichael.lebeane@amd.com/// Target ftruncate() handler. 23711629Smichael.lebeane@amd.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 23811629Smichael.lebeane@amd.com Process *p, ThreadContext *tc); 23911629Smichael.lebeane@amd.com 24011629Smichael.lebeane@amd.com 24110073Sandreas@sandberg.pp.se/// Target chown() handler. 24210073Sandreas@sandberg.pp.seSyscallReturn chownFunc(SyscallDesc *desc, int num, 24310073Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 24410073Sandreas@sandberg.pp.se 24510073Sandreas@sandberg.pp.se 24610073Sandreas@sandberg.pp.se/// Target fchown() handler. 24710073Sandreas@sandberg.pp.seSyscallReturn fchownFunc(SyscallDesc *desc, int num, 24810073Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 24910073Sandreas@sandberg.pp.se 25010073Sandreas@sandberg.pp.se/// Target dup() handler. 25110114Sandreas@sandberg.pp.seSyscallReturn dupFunc(SyscallDesc *desc, int num, 25210114Sandreas@sandberg.pp.se Process *process, ThreadContext *tc); 25310098Sandreas@sandberg.pp.se 25410098Sandreas@sandberg.pp.se/// Target fnctl() handler. 25510098Sandreas@sandberg.pp.seSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 25610098Sandreas@sandberg.pp.se Process *process, ThreadContext *tc); 25710073Sandreas@sandberg.pp.se 25810073Sandreas@sandberg.pp.se/// Target fcntl64() handler. 25910073Sandreas@sandberg.pp.seSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 26010073Sandreas@sandberg.pp.se Process *process, ThreadContext *tc); 26110114Sandreas@sandberg.pp.se 26210073Sandreas@sandberg.pp.se/// Target setuid() handler. 26310073Sandreas@sandberg.pp.seSyscallReturn setuidFunc(SyscallDesc *desc, int num, 26410073Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 26510114Sandreas@sandberg.pp.se 26610073Sandreas@sandberg.pp.se/// Target getpid() handler. 26710073Sandreas@sandberg.pp.seSyscallReturn getpidFunc(SyscallDesc *desc, int num, 26810073Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 2699651SAndreas.Sandberg@ARM.com 2709651SAndreas.Sandberg@ARM.com/// Target getuid() handler. 2719651SAndreas.Sandberg@ARM.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 2729651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 2739651SAndreas.Sandberg@ARM.com 2749651SAndreas.Sandberg@ARM.com/// Target getgid() handler. 2759651SAndreas.Sandberg@ARM.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 2769651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 2779651SAndreas.Sandberg@ARM.com 2789684Sandreas@sandberg.pp.se/// Target getppid() handler. 2799684Sandreas@sandberg.pp.seSyscallReturn getppidFunc(SyscallDesc *desc, int num, 2809684Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 2819684Sandreas@sandberg.pp.se 2829684Sandreas@sandberg.pp.se/// Target geteuid() handler. 2839651SAndreas.Sandberg@ARM.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 2849651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 2859651SAndreas.Sandberg@ARM.com 2869651SAndreas.Sandberg@ARM.com/// Target getegid() handler. 2879651SAndreas.Sandberg@ARM.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 2889755Sandreas@sandberg.pp.se Process *p, ThreadContext *tc); 2899755Sandreas@sandberg.pp.se 2909755Sandreas@sandberg.pp.se 2919755Sandreas@sandberg.pp.se 2929755Sandreas@sandberg.pp.se/// Pseudo Funcs - These functions use a different return convension, 2939755Sandreas@sandberg.pp.se/// returning a second value in a register other than the normal return register 2949755Sandreas@sandberg.pp.seSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 2959755Sandreas@sandberg.pp.se Process *process, ThreadContext *tc); 2969755Sandreas@sandberg.pp.se 2979755Sandreas@sandberg.pp.se/// Target getpidPseudo() handler. 2989651SAndreas.Sandberg@ARM.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 2999651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 3009651SAndreas.Sandberg@ARM.com 3019651SAndreas.Sandberg@ARM.com/// Target getuidPseudo() handler. 3029651SAndreas.Sandberg@ARM.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 3039651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 3049651SAndreas.Sandberg@ARM.com 3059651SAndreas.Sandberg@ARM.com/// Target getgidPseudo() handler. 3069651SAndreas.Sandberg@ARM.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 3079651SAndreas.Sandberg@ARM.com Process *p, ThreadContext *tc); 3089651SAndreas.Sandberg@ARM.com 3099651SAndreas.Sandberg@ARM.com 3109651SAndreas.Sandberg@ARM.com/// A readable name for 1,000,000, for converting microseconds to seconds. 3119651SAndreas.Sandberg@ARM.comconst int one_million = 1000000; 3129651SAndreas.Sandberg@ARM.com 3139651SAndreas.Sandberg@ARM.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 3149651SAndreas.Sandberg@ARM.com/// by my reckoning. We want to keep this a constant (not use the 3159651SAndreas.Sandberg@ARM.com/// real-world time) to keep simulations repeatable. 3169651SAndreas.Sandberg@ARM.comconst unsigned seconds_since_epoch = 1000000000; 3179651SAndreas.Sandberg@ARM.com 3189651SAndreas.Sandberg@ARM.com/// Helper function to convert current elapsed time to seconds and 3199651SAndreas.Sandberg@ARM.com/// microseconds. 3209651SAndreas.Sandberg@ARM.comtemplate <class T1, class T2> 3219651SAndreas.Sandberg@ARM.comvoid 3229651SAndreas.Sandberg@ARM.comgetElapsedTime(T1 &sec, T2 &usec) 3239651SAndreas.Sandberg@ARM.com{ 3249651SAndreas.Sandberg@ARM.com int elapsed_usecs = curTick / Clock::Int::us; 3259651SAndreas.Sandberg@ARM.com sec = elapsed_usecs / one_million; 3269651SAndreas.Sandberg@ARM.com usec = elapsed_usecs % one_million; 3279651SAndreas.Sandberg@ARM.com} 3289651SAndreas.Sandberg@ARM.com 3299651SAndreas.Sandberg@ARM.com////////////////////////////////////////////////////////////////////// 33010905Sandreas.sandberg@arm.com// 3319651SAndreas.Sandberg@ARM.com// The following emulation functions are generic, but need to be 3329683Sandreas@sandberg.pp.se// templated to account for differences in types, constants, etc. 3339683Sandreas@sandberg.pp.se// 3349683Sandreas@sandberg.pp.se////////////////////////////////////////////////////////////////////// 3359683Sandreas@sandberg.pp.se 3369683Sandreas@sandberg.pp.se#if NO_STAT64 3379651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat; 3389651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat64; 33910905Sandreas.sandberg@arm.com#else 3409651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat; 3419651SAndreas.Sandberg@ARM.com typedef struct stat64 hst_stat64; 3429651SAndreas.Sandberg@ARM.com#endif 34310905Sandreas.sandberg@arm.com 3449651SAndreas.Sandberg@ARM.com//// Helper function to convert a host stat buffer to a target stat 3459683Sandreas@sandberg.pp.se//// buffer. Also copies the target buffer out to the simulated 3469683Sandreas@sandberg.pp.se//// memory space. Used by stat(), fstat(), and lstat(). 3479651SAndreas.Sandberg@ARM.com 3489651SAndreas.Sandberg@ARM.comtemplate <typename target_stat, typename host_stat> 34910905Sandreas.sandberg@arm.comstatic void 3509652SAndreas.Sandberg@ARM.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 3519651SAndreas.Sandberg@ARM.com{ 3529651SAndreas.Sandberg@ARM.com if (fakeTTY) 35310913Sandreas.sandberg@arm.com tgt->st_dev = 0xA; 35410913Sandreas.sandberg@arm.com else 3559651SAndreas.Sandberg@ARM.com tgt->st_dev = host->st_dev; 3569651SAndreas.Sandberg@ARM.com tgt->st_dev = htog(tgt->st_dev); 35710913Sandreas.sandberg@arm.com tgt->st_ino = host->st_ino; 3589651SAndreas.Sandberg@ARM.com tgt->st_ino = htog(tgt->st_ino); 3599753Sandreas@sandberg.pp.se if (fakeTTY) 3609753Sandreas@sandberg.pp.se tgt->st_rdev = 0x880d; 3619753Sandreas@sandberg.pp.se else 3629753Sandreas@sandberg.pp.se tgt->st_rdev = host->st_rdev; 3639753Sandreas@sandberg.pp.se tgt->st_rdev = htog(tgt->st_rdev); 3649753Sandreas@sandberg.pp.se tgt->st_size = host->st_size; 3659753Sandreas@sandberg.pp.se tgt->st_size = htog(tgt->st_size); 3669753Sandreas@sandberg.pp.se tgt->st_atimeX = host->st_atimeX; 36710913Sandreas.sandberg@arm.com tgt->st_atimeX = htog(tgt->st_atimeX); 36810913Sandreas.sandberg@arm.com tgt->st_mtimeX = host->st_mtimeX; 3699651SAndreas.Sandberg@ARM.com tgt->st_mtimeX = htog(tgt->st_mtimeX); 3709753Sandreas@sandberg.pp.se tgt->st_ctimeX = host->st_ctimeX; 3719753Sandreas@sandberg.pp.se tgt->st_ctimeX = htog(tgt->st_ctimeX); 3729753Sandreas@sandberg.pp.se tgt->st_blksize = host->st_blksize; 3739753Sandreas@sandberg.pp.se tgt->st_blksize = htog(tgt->st_blksize); 3749753Sandreas@sandberg.pp.se tgt->st_blocks = host->st_blocks; 3759753Sandreas@sandberg.pp.se tgt->st_blocks = htog(tgt->st_blocks); 3769753Sandreas@sandberg.pp.se} 3779651SAndreas.Sandberg@ARM.com 3789753Sandreas@sandberg.pp.se// Same for stat64 3799753Sandreas@sandberg.pp.se 3809753Sandreas@sandberg.pp.setemplate <typename target_stat, typename host_stat64> 3819753Sandreas@sandberg.pp.sestatic void 3829753Sandreas@sandberg.pp.seconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 3839753Sandreas@sandberg.pp.se{ 3849753Sandreas@sandberg.pp.se convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 3859753Sandreas@sandberg.pp.se#if defined(STAT_HAVE_NSEC) 3869753Sandreas@sandberg.pp.se tgt->st_atime_nsec = host->st_atime_nsec; 38710913Sandreas.sandberg@arm.com tgt->st_atime_nsec = htog(tgt->st_atime_nsec); 3889753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = host->st_mtime_nsec; 3899753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec); 3909753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = host->st_ctime_nsec; 3919753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec); 3929753Sandreas@sandberg.pp.se#else 3939753Sandreas@sandberg.pp.se tgt->st_atime_nsec = 0; 3949753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = 0; 3959753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = 0; 3969753Sandreas@sandberg.pp.se#endif 3979753Sandreas@sandberg.pp.se} 39810913Sandreas.sandberg@arm.com 3999753Sandreas@sandberg.pp.se//Here are a couple convenience functions 40011629Smichael.lebeane@amd.comtemplate<class OS> 40111629Smichael.lebeane@amd.comstatic void 40211629Smichael.lebeane@amd.comcopyOutStatBuf(TranslatingPort * mem, Addr addr, 40311629Smichael.lebeane@amd.com hst_stat *host, bool fakeTTY = false) 40411629Smichael.lebeane@amd.com{ 40511629Smichael.lebeane@amd.com typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 4069753Sandreas@sandberg.pp.se tgt_stat_buf tgt(addr); 4079753Sandreas@sandberg.pp.se convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 4089753Sandreas@sandberg.pp.se tgt.copyOut(mem); 40910913Sandreas.sandberg@arm.com} 4109753Sandreas@sandberg.pp.se 4119753Sandreas@sandberg.pp.setemplate<class OS> 4129753Sandreas@sandberg.pp.sestatic void 41310913Sandreas.sandberg@arm.comcopyOutStat64Buf(TranslatingPort * mem, Addr addr, 4149753Sandreas@sandberg.pp.se hst_stat64 *host, bool fakeTTY = false) 4159651SAndreas.Sandberg@ARM.com{ 4169651SAndreas.Sandberg@ARM.com typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 4179651SAndreas.Sandberg@ARM.com tgt_stat_buf tgt(addr); 4189651SAndreas.Sandberg@ARM.com convertStatBuf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 4199651SAndreas.Sandberg@ARM.com tgt.copyOut(mem); 4209651SAndreas.Sandberg@ARM.com} 4219651SAndreas.Sandberg@ARM.com 4229651SAndreas.Sandberg@ARM.com/// Target ioctl() handler. For the most part, programs call ioctl() 4239651SAndreas.Sandberg@ARM.com/// only to find out if their stdout is a tty, to determine whether to 4249651SAndreas.Sandberg@ARM.com/// do line or block buffering. 4259651SAndreas.Sandberg@ARM.comtemplate <class OS> 4269651SAndreas.Sandberg@ARM.comSyscallReturn 4279651SAndreas.Sandberg@ARM.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 4289651SAndreas.Sandberg@ARM.com ThreadContext *tc) 4299651SAndreas.Sandberg@ARM.com{ 4309651SAndreas.Sandberg@ARM.com int fd = tc->getSyscallArg(0); 4319651SAndreas.Sandberg@ARM.com unsigned req = tc->getSyscallArg(1); 4329651SAndreas.Sandberg@ARM.com 4339651SAndreas.Sandberg@ARM.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 4349651SAndreas.Sandberg@ARM.com 4359651SAndreas.Sandberg@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 4369651SAndreas.Sandberg@ARM.com // doesn't map to any simulator fd: not a valid target fd 4379651SAndreas.Sandberg@ARM.com return -EBADF; 4389651SAndreas.Sandberg@ARM.com } 4399651SAndreas.Sandberg@ARM.com 4409651SAndreas.Sandberg@ARM.com switch (req) { 44111363Sandreas@sandberg.pp.se case OS::TIOCISATTY: 44211363Sandreas@sandberg.pp.se case OS::TIOCGETP: 44311363Sandreas@sandberg.pp.se case OS::TIOCSETP: 44411363Sandreas@sandberg.pp.se case OS::TIOCSETN: 44511363Sandreas@sandberg.pp.se case OS::TIOCSETC: 44611363Sandreas@sandberg.pp.se case OS::TIOCGETC: 44711363Sandreas@sandberg.pp.se case OS::TIOCGETS: 44811363Sandreas@sandberg.pp.se case OS::TIOCGETA: 44911363Sandreas@sandberg.pp.se return -ENOTTY; 45011363Sandreas@sandberg.pp.se 45111363Sandreas@sandberg.pp.se default: 45211363Sandreas@sandberg.pp.se fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 45311363Sandreas@sandberg.pp.se fd, req, tc->readPC()); 45411363Sandreas@sandberg.pp.se } 45511363Sandreas@sandberg.pp.se} 45611363Sandreas@sandberg.pp.se 45711363Sandreas@sandberg.pp.se/// Target open() handler. 45811363Sandreas@sandberg.pp.setemplate <class OS> 45911363Sandreas@sandberg.pp.seSyscallReturn 46011363Sandreas@sandberg.pp.seopenFunc(SyscallDesc *desc, int callnum, Process *process, 46111363Sandreas@sandberg.pp.se ThreadContext *tc) 46211363Sandreas@sandberg.pp.se{ 46311363Sandreas@sandberg.pp.se std::string path; 4649651SAndreas.Sandberg@ARM.com 4659651SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 4669652SAndreas.Sandberg@ARM.com return -EFAULT; 4679652SAndreas.Sandberg@ARM.com 4689651SAndreas.Sandberg@ARM.com if (path == "/dev/sysdev0") { 4699651SAndreas.Sandberg@ARM.com // This is a memory-mapped high-resolution timer device on Alpha. 4709651SAndreas.Sandberg@ARM.com // We don't support it, so just punt. 4719651SAndreas.Sandberg@ARM.com warn("Ignoring open(%s, ...)\n", path); 4729651SAndreas.Sandberg@ARM.com return -ENOENT; 4739651SAndreas.Sandberg@ARM.com } 4749651SAndreas.Sandberg@ARM.com 4759651SAndreas.Sandberg@ARM.com int tgtFlags = tc->getSyscallArg(1); 4769651SAndreas.Sandberg@ARM.com int mode = tc->getSyscallArg(2); 4779651SAndreas.Sandberg@ARM.com int hostFlags = 0; 4789651SAndreas.Sandberg@ARM.com 4799651SAndreas.Sandberg@ARM.com // translate open flags 4809651SAndreas.Sandberg@ARM.com for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 4819651SAndreas.Sandberg@ARM.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 4829651SAndreas.Sandberg@ARM.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 4839651SAndreas.Sandberg@ARM.com hostFlags |= OS::openFlagTable[i].hostFlag; 4849651SAndreas.Sandberg@ARM.com } 4859651SAndreas.Sandberg@ARM.com } 4869651SAndreas.Sandberg@ARM.com 4879651SAndreas.Sandberg@ARM.com // any target flags left? 4889651SAndreas.Sandberg@ARM.com if (tgtFlags != 0) 4899651SAndreas.Sandberg@ARM.com warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 4909651SAndreas.Sandberg@ARM.com 4919753Sandreas@sandberg.pp.se#ifdef __CYGWIN32__ 4929753Sandreas@sandberg.pp.se hostFlags |= O_BINARY; 4939753Sandreas@sandberg.pp.se#endif 4949753Sandreas@sandberg.pp.se 4959753Sandreas@sandberg.pp.se DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 4969753Sandreas@sandberg.pp.se 4979651SAndreas.Sandberg@ARM.com // open the file 4989651SAndreas.Sandberg@ARM.com int fd = open(path.c_str(), hostFlags, mode); 4999651SAndreas.Sandberg@ARM.com 5009651SAndreas.Sandberg@ARM.com return (fd == -1) ? -errno : process->alloc_fd(fd); 5019651SAndreas.Sandberg@ARM.com} 50211629Smichael.lebeane@amd.com 5039651SAndreas.Sandberg@ARM.com 50411629Smichael.lebeane@amd.com/// Target chmod() handler. 5059651SAndreas.Sandberg@ARM.comtemplate <class OS> 5069651SAndreas.Sandberg@ARM.comSyscallReturn 5079651SAndreas.Sandberg@ARM.comchmodFunc(SyscallDesc *desc, int callnum, Process *process, 5089651SAndreas.Sandberg@ARM.com ThreadContext *tc) 50911151Smitch.hayenga@arm.com{ 5109651SAndreas.Sandberg@ARM.com std::string path; 5119651SAndreas.Sandberg@ARM.com 51210157Sandreas@sandberg.pp.se if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 51310157Sandreas@sandberg.pp.se return -EFAULT; 51410157Sandreas@sandberg.pp.se 51510157Sandreas@sandberg.pp.se uint32_t mode = tc->getSyscallArg(1); 51610157Sandreas@sandberg.pp.se mode_t hostMode = 0; 51710157Sandreas@sandberg.pp.se 51810157Sandreas@sandberg.pp.se // XXX translate mode flags via OS::something??? 5199651SAndreas.Sandberg@ARM.com hostMode = mode; 5209651SAndreas.Sandberg@ARM.com 5219651SAndreas.Sandberg@ARM.com // do the chmod 5229651SAndreas.Sandberg@ARM.com int result = chmod(path.c_str(), hostMode); 5239651SAndreas.Sandberg@ARM.com if (result < 0) 5249651SAndreas.Sandberg@ARM.com return -errno; 5259651SAndreas.Sandberg@ARM.com 5269651SAndreas.Sandberg@ARM.com return 0; 52710407Smitch.hayenga@arm.com} 5289651SAndreas.Sandberg@ARM.com 52910407Smitch.hayenga@arm.com 5309651SAndreas.Sandberg@ARM.com/// Target fchmod() handler. 5319651SAndreas.Sandberg@ARM.comtemplate <class OS> 5329651SAndreas.Sandberg@ARM.comSyscallReturn 5339651SAndreas.Sandberg@ARM.comfchmodFunc(SyscallDesc *desc, int callnum, Process *process, 5349651SAndreas.Sandberg@ARM.com ThreadContext *tc) 5359651SAndreas.Sandberg@ARM.com{ 5369651SAndreas.Sandberg@ARM.com int fd = tc->getSyscallArg(0); 5379754Sandreas@sandberg.pp.se if (fd < 0 || process->sim_fd(fd) < 0) { 5389651SAndreas.Sandberg@ARM.com // doesn't map to any simulator fd: not a valid target fd 53910407Smitch.hayenga@arm.com return -EBADF; 5409651SAndreas.Sandberg@ARM.com } 5419651SAndreas.Sandberg@ARM.com 5429651SAndreas.Sandberg@ARM.com uint32_t mode = tc->getSyscallArg(1); 5439651SAndreas.Sandberg@ARM.com mode_t hostMode = 0; 5449651SAndreas.Sandberg@ARM.com 5459651SAndreas.Sandberg@ARM.com // XXX translate mode flags via OS::someting??? 5469651SAndreas.Sandberg@ARM.com hostMode = mode; 5479651SAndreas.Sandberg@ARM.com 5489651SAndreas.Sandberg@ARM.com // do the fchmod 5499651SAndreas.Sandberg@ARM.com int result = fchmod(process->sim_fd(fd), hostMode); 5509651SAndreas.Sandberg@ARM.com if (result < 0) 5519651SAndreas.Sandberg@ARM.com return -errno; 5529651SAndreas.Sandberg@ARM.com 5539651SAndreas.Sandberg@ARM.com return 0; 5549651SAndreas.Sandberg@ARM.com} 55510553Salexandru.dutu@amd.com 5569651SAndreas.Sandberg@ARM.com 5579651SAndreas.Sandberg@ARM.com/// Target stat() handler. 5589651SAndreas.Sandberg@ARM.comtemplate <class OS> 5599651SAndreas.Sandberg@ARM.comSyscallReturn 5609651SAndreas.Sandberg@ARM.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 5619651SAndreas.Sandberg@ARM.com ThreadContext *tc) 5629651SAndreas.Sandberg@ARM.com{ 5639651SAndreas.Sandberg@ARM.com std::string path; 5649651SAndreas.Sandberg@ARM.com 5659651SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 5669651SAndreas.Sandberg@ARM.com return -EFAULT; 5679651SAndreas.Sandberg@ARM.com 5689651SAndreas.Sandberg@ARM.com struct stat hostBuf; 5699651SAndreas.Sandberg@ARM.com int result = stat(path.c_str(), &hostBuf); 5709651SAndreas.Sandberg@ARM.com 5719651SAndreas.Sandberg@ARM.com if (result < 0) 5729651SAndreas.Sandberg@ARM.com return -errno; 5739651SAndreas.Sandberg@ARM.com 5749651SAndreas.Sandberg@ARM.com copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 5759651SAndreas.Sandberg@ARM.com 5769651SAndreas.Sandberg@ARM.com return 0; 5779651SAndreas.Sandberg@ARM.com} 5789651SAndreas.Sandberg@ARM.com 5799651SAndreas.Sandberg@ARM.com 5809651SAndreas.Sandberg@ARM.com/// Target fstat64() handler. 5819652SAndreas.Sandberg@ARM.comtemplate <class OS> 5829652SAndreas.Sandberg@ARM.comSyscallReturn 5839652SAndreas.Sandberg@ARM.comfstat64Func(SyscallDesc *desc, int callnum, Process *process, 5849652SAndreas.Sandberg@ARM.com ThreadContext *tc) 5859652SAndreas.Sandberg@ARM.com{ 5869652SAndreas.Sandberg@ARM.com int fd = tc->getSyscallArg(0); 5879652SAndreas.Sandberg@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 5889652SAndreas.Sandberg@ARM.com // doesn't map to any simulator fd: not a valid target fd 5899652SAndreas.Sandberg@ARM.com return -EBADF; 5909651SAndreas.Sandberg@ARM.com } 5919651SAndreas.Sandberg@ARM.com 5929651SAndreas.Sandberg@ARM.com#if NO_STAT64 5939752Sandreas@sandberg.pp.se struct stat hostBuf; 5949651SAndreas.Sandberg@ARM.com int result = fstat(process->sim_fd(fd), &hostBuf); 5959651SAndreas.Sandberg@ARM.com#else 5969651SAndreas.Sandberg@ARM.com struct stat64 hostBuf; 5979651SAndreas.Sandberg@ARM.com int result = fstat64(process->sim_fd(fd), &hostBuf); 5989651SAndreas.Sandberg@ARM.com#endif 5999651SAndreas.Sandberg@ARM.com 6009752Sandreas@sandberg.pp.se if (result < 0) 6019651SAndreas.Sandberg@ARM.com return -errno; 6029651SAndreas.Sandberg@ARM.com 6039651SAndreas.Sandberg@ARM.com copyOutStat64Buf<OS>(tc->getMemPort(), fd, tc->getSyscallArg(1), &hostBuf); 60410905Sandreas.sandberg@arm.com 6059651SAndreas.Sandberg@ARM.com return 0; 6069651SAndreas.Sandberg@ARM.com} 6079651SAndreas.Sandberg@ARM.com 6089651SAndreas.Sandberg@ARM.com 6099651SAndreas.Sandberg@ARM.com/// Target lstat() handler. 6109651SAndreas.Sandberg@ARM.comtemplate <class OS> 6119651SAndreas.Sandberg@ARM.comSyscallReturn 6129753Sandreas@sandberg.pp.selstatFunc(SyscallDesc *desc, int callnum, Process *process, 61311629Smichael.lebeane@amd.com ThreadContext *tc) 6149651SAndreas.Sandberg@ARM.com{ 6159651SAndreas.Sandberg@ARM.com std::string path; 6169753Sandreas@sandberg.pp.se 6179753Sandreas@sandberg.pp.se if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 6189753Sandreas@sandberg.pp.se return -EFAULT; 6199753Sandreas@sandberg.pp.se 6209753Sandreas@sandberg.pp.se struct stat hostBuf; 6219753Sandreas@sandberg.pp.se int result = lstat(path.c_str(), &hostBuf); 6229651SAndreas.Sandberg@ARM.com 6239651SAndreas.Sandberg@ARM.com if (result < 0) 6249753Sandreas@sandberg.pp.se return -errno; 6259753Sandreas@sandberg.pp.se 62610858Sandreas.sandberg@arm.com copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 62710858Sandreas.sandberg@arm.com 62810858Sandreas.sandberg@arm.com return 0; 62910858Sandreas.sandberg@arm.com} 63010858Sandreas.sandberg@arm.com 63110858Sandreas.sandberg@arm.com/// Target lstat64() handler. 63210858Sandreas.sandberg@arm.comtemplate <class OS> 63310858Sandreas.sandberg@arm.comSyscallReturn 6349753Sandreas@sandberg.pp.selstat64Func(SyscallDesc *desc, int callnum, Process *process, 63511399Sandreas.sandberg@arm.com ThreadContext *tc) 63611399Sandreas.sandberg@arm.com{ 63711399Sandreas.sandberg@arm.com std::string path; 6389753Sandreas@sandberg.pp.se 6399753Sandreas@sandberg.pp.se if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 6409753Sandreas@sandberg.pp.se return -EFAULT; 6419892Sandreas@sandberg.pp.se 64210858Sandreas.sandberg@arm.com#if NO_STAT64 64310858Sandreas.sandberg@arm.com struct stat hostBuf; 64410858Sandreas.sandberg@arm.com int result = lstat(path.c_str(), &hostBuf); 64510858Sandreas.sandberg@arm.com#else 6469892Sandreas@sandberg.pp.se struct stat64 hostBuf; 6479753Sandreas@sandberg.pp.se int result = lstat64(path.c_str(), &hostBuf); 64810913Sandreas.sandberg@arm.com#endif 6499753Sandreas@sandberg.pp.se 6509753Sandreas@sandberg.pp.se if (result < 0) 6519753Sandreas@sandberg.pp.se return -errno; 6529753Sandreas@sandberg.pp.se 6539753Sandreas@sandberg.pp.se copyOutStat64Buf<OS>(tc->getMemPort(), -1, tc->getSyscallArg(1), &hostBuf); 6549753Sandreas@sandberg.pp.se 6559753Sandreas@sandberg.pp.se return 0; 6569753Sandreas@sandberg.pp.se} 6579753Sandreas@sandberg.pp.se 65810112Sandreas@sandberg.pp.se/// Target fstat() handler. 65910112Sandreas@sandberg.pp.setemplate <class OS> 66010112Sandreas@sandberg.pp.seSyscallReturn 66110112Sandreas@sandberg.pp.sefstatFunc(SyscallDesc *desc, int callnum, Process *process, 66210112Sandreas@sandberg.pp.se ThreadContext *tc) 66310112Sandreas@sandberg.pp.se{ 6649753Sandreas@sandberg.pp.se int fd = process->sim_fd(tc->getSyscallArg(0)); 6659753Sandreas@sandberg.pp.se 6669753Sandreas@sandberg.pp.se DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 6679753Sandreas@sandberg.pp.se 6689753Sandreas@sandberg.pp.se if (fd < 0) 66911399Sandreas.sandberg@arm.com return -EBADF; 67011399Sandreas.sandberg@arm.com 67111399Sandreas.sandberg@arm.com struct stat hostBuf; 6729753Sandreas@sandberg.pp.se int result = fstat(fd, &hostBuf); 6739753Sandreas@sandberg.pp.se 6749755Sandreas@sandberg.pp.se if (result < 0) 6759753Sandreas@sandberg.pp.se return -errno; 6769755Sandreas@sandberg.pp.se 6779755Sandreas@sandberg.pp.se copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 6789753Sandreas@sandberg.pp.se 6799755Sandreas@sandberg.pp.se return 0; 6809753Sandreas@sandberg.pp.se} 6819904Sandreas@sandberg.pp.se 6829904Sandreas@sandberg.pp.se 6839904Sandreas@sandberg.pp.se/// Target statfs() handler. 6849904Sandreas@sandberg.pp.setemplate <class OS> 6859904Sandreas@sandberg.pp.seSyscallReturn 6869904Sandreas@sandberg.pp.sestatfsFunc(SyscallDesc *desc, int callnum, Process *process, 6879753Sandreas@sandberg.pp.se ThreadContext *tc) 6889753Sandreas@sandberg.pp.se{ 6899753Sandreas@sandberg.pp.se std::string path; 6909753Sandreas@sandberg.pp.se 6919651SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 6929753Sandreas@sandberg.pp.se return -EFAULT; 6939753Sandreas@sandberg.pp.se 6949651SAndreas.Sandberg@ARM.com struct statfs hostBuf; 6959753Sandreas@sandberg.pp.se int result = statfs(path.c_str(), &hostBuf); 6969753Sandreas@sandberg.pp.se 69711629Smichael.lebeane@amd.com if (result < 0) 6989753Sandreas@sandberg.pp.se return -errno; 6999753Sandreas@sandberg.pp.se 7009753Sandreas@sandberg.pp.se copyOutStatfsBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 7019753Sandreas@sandberg.pp.se 7029753Sandreas@sandberg.pp.se return 0; 7039753Sandreas@sandberg.pp.se} 7049753Sandreas@sandberg.pp.se 7059753Sandreas@sandberg.pp.se 70611629Smichael.lebeane@amd.com/// Target fstatfs() handler. 70711629Smichael.lebeane@amd.comtemplate <class OS> 70811629Smichael.lebeane@amd.comSyscallReturn 7099753Sandreas@sandberg.pp.sefstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 7109753Sandreas@sandberg.pp.se ThreadContext *tc) 7119753Sandreas@sandberg.pp.se{ 7129753Sandreas@sandberg.pp.se int fd = process->sim_fd(tc->getSyscallArg(0)); 7139651SAndreas.Sandberg@ARM.com 7149651SAndreas.Sandberg@ARM.com if (fd < 0) 7159735Sandreas@sandberg.pp.se return -EBADF; 7169735Sandreas@sandberg.pp.se 7179735Sandreas@sandberg.pp.se struct statfs hostBuf; 7189735Sandreas@sandberg.pp.se int result = fstatfs(fd, &hostBuf); 7199735Sandreas@sandberg.pp.se 7209735Sandreas@sandberg.pp.se if (result < 0) 7219651SAndreas.Sandberg@ARM.com return -errno; 7229651SAndreas.Sandberg@ARM.com 7239651SAndreas.Sandberg@ARM.com copyOutStatfsBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 7249753Sandreas@sandberg.pp.se 72511363Sandreas@sandberg.pp.se return 0; 72611363Sandreas@sandberg.pp.se} 72711363Sandreas@sandberg.pp.se 7289651SAndreas.Sandberg@ARM.com 7299655SAndreas.Sandberg@ARM.com/// Target writev() handler. 7309753Sandreas@sandberg.pp.setemplate <class OS> 7319753Sandreas@sandberg.pp.seSyscallReturn 7329753Sandreas@sandberg.pp.sewritevFunc(SyscallDesc *desc, int callnum, Process *process, 7339753Sandreas@sandberg.pp.se ThreadContext *tc) 7349753Sandreas@sandberg.pp.se{ 7359735Sandreas@sandberg.pp.se int fd = tc->getSyscallArg(0); 7369755Sandreas@sandberg.pp.se if (fd < 0 || process->sim_fd(fd) < 0) { 7379755Sandreas@sandberg.pp.se // doesn't map to any simulator fd: not a valid target fd 73810114Sandreas@sandberg.pp.se return -EBADF; 73910114Sandreas@sandberg.pp.se } 74010114Sandreas@sandberg.pp.se 7419753Sandreas@sandberg.pp.se TranslatingPort *p = tc->getMemPort(); 74210114Sandreas@sandberg.pp.se uint64_t tiov_base = tc->getSyscallArg(1); 7439655SAndreas.Sandberg@ARM.com size_t count = tc->getSyscallArg(2); 74410114Sandreas@sandberg.pp.se struct iovec hiov[count]; 74510114Sandreas@sandberg.pp.se for (int i = 0; i < count; ++i) 74610114Sandreas@sandberg.pp.se { 7479753Sandreas@sandberg.pp.se typename OS::tgt_iovec tiov; 74810114Sandreas@sandberg.pp.se 74910114Sandreas@sandberg.pp.se p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 7509753Sandreas@sandberg.pp.se (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 7519753Sandreas@sandberg.pp.se hiov[i].iov_len = gtoh(tiov.iov_len); 7529753Sandreas@sandberg.pp.se hiov[i].iov_base = new char [hiov[i].iov_len]; 7539753Sandreas@sandberg.pp.se p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 7549753Sandreas@sandberg.pp.se hiov[i].iov_len); 7559753Sandreas@sandberg.pp.se } 7569753Sandreas@sandberg.pp.se 75710157Sandreas@sandberg.pp.se int result = writev(process->sim_fd(fd), hiov, count); 75810157Sandreas@sandberg.pp.se 75910157Sandreas@sandberg.pp.se for (int i = 0; i < count; ++i) 76010157Sandreas@sandberg.pp.se { 76110157Sandreas@sandberg.pp.se delete [] (char *)hiov[i].iov_base; 76210157Sandreas@sandberg.pp.se } 76310157Sandreas@sandberg.pp.se 76410157Sandreas@sandberg.pp.se if (result < 0) 7659753Sandreas@sandberg.pp.se return -errno; 7669753Sandreas@sandberg.pp.se 7679753Sandreas@sandberg.pp.se return 0; 7689753Sandreas@sandberg.pp.se} 7699753Sandreas@sandberg.pp.se 7709753Sandreas@sandberg.pp.se 7719753Sandreas@sandberg.pp.se/// Target mmap() handler. 7729753Sandreas@sandberg.pp.se/// 7739753Sandreas@sandberg.pp.se/// We don't really handle mmap(). If the target is mmaping an 7749753Sandreas@sandberg.pp.se/// anonymous region or /dev/zero, we can get away with doing basically 7759753Sandreas@sandberg.pp.se/// nothing (since memory is initialized to zero and the simulator 7769753Sandreas@sandberg.pp.se/// doesn't really check addresses anyway). Always print a warning, 7779753Sandreas@sandberg.pp.se/// since this could be seriously broken if we're not mapping 7789753Sandreas@sandberg.pp.se/// /dev/zero. 7799753Sandreas@sandberg.pp.se// 7809753Sandreas@sandberg.pp.se/// Someday we should explicitly check for /dev/zero in open, flag the 7819753Sandreas@sandberg.pp.se/// file descriptor, and fail (or implement!) a non-anonymous mmap to 7829753Sandreas@sandberg.pp.se/// anything else. 7839753Sandreas@sandberg.pp.setemplate <class OS> 7849753Sandreas@sandberg.pp.seSyscallReturn 7859753Sandreas@sandberg.pp.semmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 7869753Sandreas@sandberg.pp.se{ 7879753Sandreas@sandberg.pp.se Addr start = tc->getSyscallArg(0); 7889753Sandreas@sandberg.pp.se uint64_t length = tc->getSyscallArg(1); 7899753Sandreas@sandberg.pp.se // int prot = tc->getSyscallArg(2); 79010114Sandreas@sandberg.pp.se int flags = tc->getSyscallArg(3); 7919753Sandreas@sandberg.pp.se // int fd = p->sim_fd(tc->getSyscallArg(4)); 7929753Sandreas@sandberg.pp.se // int offset = tc->getSyscallArg(5); 7939753Sandreas@sandberg.pp.se 7949753Sandreas@sandberg.pp.se if ((start % TheISA::VMPageSize) != 0 || 79510114Sandreas@sandberg.pp.se (length % TheISA::VMPageSize) != 0) { 7969753Sandreas@sandberg.pp.se warn("mmap failing: arguments not page-aligned: " 7979753Sandreas@sandberg.pp.se "start 0x%x length 0x%x", 7989753Sandreas@sandberg.pp.se start, length); 7999753Sandreas@sandberg.pp.se return -EINVAL; 8009753Sandreas@sandberg.pp.se } 8019753Sandreas@sandberg.pp.se 8029753Sandreas@sandberg.pp.se if (start != 0) { 8039753Sandreas@sandberg.pp.se warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 8049753Sandreas@sandberg.pp.se start, p->mmap_end); 8059753Sandreas@sandberg.pp.se } 8069753Sandreas@sandberg.pp.se 8079753Sandreas@sandberg.pp.se // pick next address from our "mmap region" 8089753Sandreas@sandberg.pp.se start = p->mmap_end; 8099753Sandreas@sandberg.pp.se p->pTable->allocate(start, length); 8109753Sandreas@sandberg.pp.se p->mmap_end += length; 8119753Sandreas@sandberg.pp.se 8129651SAndreas.Sandberg@ARM.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 8139655SAndreas.Sandberg@ARM.com warn("allowing mmap of file @ fd %d. " 8149651SAndreas.Sandberg@ARM.com "This will break if not /dev/zero.", tc->getSyscallArg(4)); 8159651SAndreas.Sandberg@ARM.com } 8169651SAndreas.Sandberg@ARM.com 8179651SAndreas.Sandberg@ARM.com return start; 8189651SAndreas.Sandberg@ARM.com} 8199651SAndreas.Sandberg@ARM.com 8209651SAndreas.Sandberg@ARM.com/// Target getrlimit() handler. 8219651SAndreas.Sandberg@ARM.comtemplate <class OS> 8229651SAndreas.Sandberg@ARM.comSyscallReturn 8239651SAndreas.Sandberg@ARM.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 8249651SAndreas.Sandberg@ARM.com ThreadContext *tc) 8259651SAndreas.Sandberg@ARM.com{ 8269651SAndreas.Sandberg@ARM.com unsigned resource = tc->getSyscallArg(0); 8279651SAndreas.Sandberg@ARM.com TypedBufferArg<typename OS::rlimit> rlp(tc->getSyscallArg(1)); 8289651SAndreas.Sandberg@ARM.com 8299651SAndreas.Sandberg@ARM.com switch (resource) { 8309651SAndreas.Sandberg@ARM.com case OS::TGT_RLIMIT_STACK: 8319651SAndreas.Sandberg@ARM.com // max stack size in bytes: make up a number (2MB for now) 8329651SAndreas.Sandberg@ARM.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 8339651SAndreas.Sandberg@ARM.com rlp->rlim_cur = htog(rlp->rlim_cur); 8349651SAndreas.Sandberg@ARM.com rlp->rlim_max = htog(rlp->rlim_max); 8359651SAndreas.Sandberg@ARM.com break; 8369651SAndreas.Sandberg@ARM.com 8379651SAndreas.Sandberg@ARM.com default: 8389651SAndreas.Sandberg@ARM.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 8399651SAndreas.Sandberg@ARM.com << std::endl; 8409651SAndreas.Sandberg@ARM.com abort(); 8419651SAndreas.Sandberg@ARM.com break; 8429651SAndreas.Sandberg@ARM.com } 8439651SAndreas.Sandberg@ARM.com 8449651SAndreas.Sandberg@ARM.com rlp.copyOut(tc->getMemPort()); 8459651SAndreas.Sandberg@ARM.com return 0; 8469651SAndreas.Sandberg@ARM.com} 8479651SAndreas.Sandberg@ARM.com 8489651SAndreas.Sandberg@ARM.com/// Target gettimeofday() handler. 8499651SAndreas.Sandberg@ARM.comtemplate <class OS> 8509651SAndreas.Sandberg@ARM.comSyscallReturn 8519651SAndreas.Sandberg@ARM.comgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 8529651SAndreas.Sandberg@ARM.com ThreadContext *tc) 8539651SAndreas.Sandberg@ARM.com{ 8549651SAndreas.Sandberg@ARM.com TypedBufferArg<typename OS::timeval> tp(tc->getSyscallArg(0)); 8559651SAndreas.Sandberg@ARM.com 8569651SAndreas.Sandberg@ARM.com getElapsedTime(tp->tv_sec, tp->tv_usec); 8579651SAndreas.Sandberg@ARM.com tp->tv_sec += seconds_since_epoch; 8589651SAndreas.Sandberg@ARM.com tp->tv_sec = htog(tp->tv_sec); 8599651SAndreas.Sandberg@ARM.com tp->tv_usec = htog(tp->tv_usec); 8609651SAndreas.Sandberg@ARM.com 8619651SAndreas.Sandberg@ARM.com tp.copyOut(tc->getMemPort()); 8629651SAndreas.Sandberg@ARM.com 8639651SAndreas.Sandberg@ARM.com return 0; 8649651SAndreas.Sandberg@ARM.com} 8659651SAndreas.Sandberg@ARM.com 8669651SAndreas.Sandberg@ARM.com 8679651SAndreas.Sandberg@ARM.com/// Target utimes() handler. 8689651SAndreas.Sandberg@ARM.comtemplate <class OS> 8699651SAndreas.Sandberg@ARM.comSyscallReturn 8709651SAndreas.Sandberg@ARM.comutimesFunc(SyscallDesc *desc, int callnum, Process *process, 8719651SAndreas.Sandberg@ARM.com ThreadContext *tc) 8729651SAndreas.Sandberg@ARM.com{ 8739651SAndreas.Sandberg@ARM.com std::string path; 8749651SAndreas.Sandberg@ARM.com 8759651SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 8769651SAndreas.Sandberg@ARM.com return -EFAULT; 8779651SAndreas.Sandberg@ARM.com 8789651SAndreas.Sandberg@ARM.com TypedBufferArg<typename OS::timeval [2]> tp(tc->getSyscallArg(1)); 8799651SAndreas.Sandberg@ARM.com tp.copyIn(tc->getMemPort()); 8809651SAndreas.Sandberg@ARM.com 8819651SAndreas.Sandberg@ARM.com struct timeval hostTimeval[2]; 8829651SAndreas.Sandberg@ARM.com for (int i = 0; i < 2; ++i) 8839651SAndreas.Sandberg@ARM.com { 8849651SAndreas.Sandberg@ARM.com hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 8859651SAndreas.Sandberg@ARM.com hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 8869651SAndreas.Sandberg@ARM.com } 8879651SAndreas.Sandberg@ARM.com int result = utimes(path.c_str(), hostTimeval); 8889651SAndreas.Sandberg@ARM.com 8899651SAndreas.Sandberg@ARM.com if (result < 0) 8909651SAndreas.Sandberg@ARM.com return -errno; 8919651SAndreas.Sandberg@ARM.com 8929651SAndreas.Sandberg@ARM.com return 0; 8939651SAndreas.Sandberg@ARM.com} 8949651SAndreas.Sandberg@ARM.com/// Target getrusage() function. 8959651SAndreas.Sandberg@ARM.comtemplate <class OS> 8969651SAndreas.Sandberg@ARM.comSyscallReturn 8979651SAndreas.Sandberg@ARM.comgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 8989651SAndreas.Sandberg@ARM.com ThreadContext *tc) 8999651SAndreas.Sandberg@ARM.com{ 9009651SAndreas.Sandberg@ARM.com int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 9019651SAndreas.Sandberg@ARM.com TypedBufferArg<typename OS::rusage> rup(tc->getSyscallArg(1)); 9029651SAndreas.Sandberg@ARM.com 9039651SAndreas.Sandberg@ARM.com if (who != OS::TGT_RUSAGE_SELF) { 9049651SAndreas.Sandberg@ARM.com // don't really handle THREAD or CHILDREN, but just warn and 9059651SAndreas.Sandberg@ARM.com // plow ahead 9069651SAndreas.Sandberg@ARM.com warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 9079651SAndreas.Sandberg@ARM.com who); 9089651SAndreas.Sandberg@ARM.com } 9099651SAndreas.Sandberg@ARM.com 9109651SAndreas.Sandberg@ARM.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 9119651SAndreas.Sandberg@ARM.com rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 9129651SAndreas.Sandberg@ARM.com rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 9139651SAndreas.Sandberg@ARM.com 9149651SAndreas.Sandberg@ARM.com rup->ru_stime.tv_sec = 0; 9159651SAndreas.Sandberg@ARM.com rup->ru_stime.tv_usec = 0; 9169651SAndreas.Sandberg@ARM.com rup->ru_maxrss = 0; 9179651SAndreas.Sandberg@ARM.com rup->ru_ixrss = 0; 9189651SAndreas.Sandberg@ARM.com rup->ru_idrss = 0; 9199651SAndreas.Sandberg@ARM.com rup->ru_isrss = 0; 9209651SAndreas.Sandberg@ARM.com rup->ru_minflt = 0; 9219651SAndreas.Sandberg@ARM.com rup->ru_majflt = 0; 9229651SAndreas.Sandberg@ARM.com rup->ru_nswap = 0; 9239651SAndreas.Sandberg@ARM.com rup->ru_inblock = 0; 9249651SAndreas.Sandberg@ARM.com rup->ru_oublock = 0; 9259651SAndreas.Sandberg@ARM.com rup->ru_msgsnd = 0; 9269651SAndreas.Sandberg@ARM.com rup->ru_msgrcv = 0; 92710843Sandreas.sandberg@arm.com rup->ru_nsignals = 0; 92810843Sandreas.sandberg@arm.com rup->ru_nvcsw = 0; 92910843Sandreas.sandberg@arm.com rup->ru_nivcsw = 0; 93010843Sandreas.sandberg@arm.com 93110843Sandreas.sandberg@arm.com rup.copyOut(tc->getMemPort()); 93210843Sandreas.sandberg@arm.com 93310843Sandreas.sandberg@arm.com return 0; 93410843Sandreas.sandberg@arm.com} 9359651SAndreas.Sandberg@ARM.com 9369651SAndreas.Sandberg@ARM.com 9379651SAndreas.Sandberg@ARM.com 9389651SAndreas.Sandberg@ARM.com 9399651SAndreas.Sandberg@ARM.com#endif // __SIM_SYSCALL_EMUL_HH__ 9409651SAndreas.Sandberg@ARM.com