syscall_emul.hh revision 7075
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 310796Sbrandon.potter@amd.com * All rights reserved. 410027SChris.Adeniyi-Jones@arm.com * 510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without 610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are 710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright 810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer; 910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright 1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the 1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution; 1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its 1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from 1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission. 151458SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27360SN/A * 28360SN/A * Authors: Steve Reinhardt 29360SN/A * Kevin Lim 30360SN/A */ 31360SN/A 32360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__ 33360SN/A#define __SIM_SYSCALL_EMUL_HH__ 34360SN/A 35360SN/A#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 36360SN/A defined(__FreeBSD__) || defined(__CYGWIN__)) 37360SN/A 38360SN/A/// 39360SN/A/// @file syscall_emul.hh 402665Ssaidi@eecs.umich.edu/// 412665Ssaidi@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target 422665Ssaidi@eecs.umich.edu/// application on the host machine. 43360SN/A 44360SN/A#ifdef __CYGWIN32__ 451354SN/A#include <sys/fcntl.h> // for O_BINARY 461354SN/A#endif 47360SN/A#include <sys/stat.h> 4812018Sandreas.sandberg@arm.com#include <errno.h> 4912018Sandreas.sandberg@arm.com#include <fcntl.h> 5012018Sandreas.sandberg@arm.com#include <sys/uio.h> 5112018Sandreas.sandberg@arm.com#include <sys/time.h> 5212018Sandreas.sandberg@arm.com 5312018Sandreas.sandberg@arm.com#include <string> 5412018Sandreas.sandberg@arm.com 552064SN/A#include "base/chunk_generator.hh" 56360SN/A#include "base/intmath.hh" // for RoundUp 57360SN/A#include "base/misc.hh" 58360SN/A#include "base/trace.hh" 59360SN/A#include "base/types.hh" 60360SN/A#include "config/the_isa.hh" 61360SN/A#include "cpu/base.hh" 6213936SAndrea.Mondelli@ucf.edu#include "cpu/thread_context.hh" 6313933Sbrandon.potter@amd.com#include "mem/translating_port.hh" 6413933Sbrandon.potter@amd.com#include "mem/page_table.hh" 6513933Sbrandon.potter@amd.com#include "sim/system.hh" 6613936SAndrea.Mondelli@ucf.edu#include "sim/process.hh" 6713936SAndrea.Mondelli@ucf.edu 6813936SAndrea.Mondelli@ucf.edu/// 6913933Sbrandon.potter@amd.com/// System call descriptor. 7013933Sbrandon.potter@amd.com/// 711809SN/Aclass SyscallDesc { 7211800Sbrandon.potter@amd.com 7311392Sbrandon.potter@amd.com public: 741809SN/A 7511392Sbrandon.potter@amd.com /// Typedef for target syscall handler functions. 7613902Sbrandon.potter@amd.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 7713570Sbrandon.potter@amd.com LiveProcess *, ThreadContext *); 7813902Sbrandon.potter@amd.com 7911383Sbrandon.potter@amd.com const char *name; //!< Syscall name (e.g., "open"). 8013568Sbrandon.potter@amd.com FuncPtr funcPtr; //!< Pointer to emulation function. 813113Sgblack@eecs.umich.edu int flags; //!< Flags (see Flags enum). 828229Snate@binkert.org 8313570Sbrandon.potter@amd.com /// Flag values for controlling syscall behavior. 848229Snate@binkert.org enum Flags { 8511594Santhony.gutierrez@amd.com /// Don't set return regs according to funcPtr return value. 867075Snate@binkert.org /// Used for syscalls with non-standard return conventions 878229Snate@binkert.org /// that explicitly set the ThreadContext regs (e.g., 8811856Sbrandon.potter@amd.com /// sigreturn). 897075Snate@binkert.org SuppressReturnValue = 1 90360SN/A }; 9112461Sgabeblack@google.com 9211886Sbrandon.potter@amd.com /// Constructor. 9311800Sbrandon.potter@amd.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9411392Sbrandon.potter@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 9512334Sgabeblack@google.com { 961354SN/A } 976216Snate@binkert.org 986658Snate@binkert.org /// Emulate the syscall. Public interface for calling through funcPtr. 992474SN/A void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1002680Sktlim@umich.edu}; 1018229Snate@binkert.org 10211886Sbrandon.potter@amd.com 10310496Ssteve.reinhardt@amd.comclass BaseBufferArg { 10411911SBrandon.Potter@amd.com 1058229Snate@binkert.org public: 10611794Sbrandon.potter@amd.com 10711886Sbrandon.potter@amd.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 10810497Ssteve.reinhardt@amd.com { 10911794Sbrandon.potter@amd.com bufPtr = new uint8_t[size]; 110360SN/A // clear out buffer: in case we only partially populate this, 11113629SAndrea.Mondelli@ucf.edu // and then do a copyOut(), we want to make sure we don't 11213629SAndrea.Mondelli@ucf.edu // introduce any random junk into the simulated address space 11313629SAndrea.Mondelli@ucf.edu memset(bufPtr, 0, size); 11413629SAndrea.Mondelli@ucf.edu } 115360SN/A 116360SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 117360SN/A 118360SN/A // 119360SN/A // copy data into simulator space (read from target memory) 120360SN/A // 121360SN/A virtual bool copyIn(TranslatingPort *memport) 122360SN/A { 12313933Sbrandon.potter@amd.com memport->readBlob(addr, bufPtr, size); 124360SN/A return true; // no EFAULT detection for now 125378SN/A } 1261706SN/A 12711851Sbrandon.potter@amd.com // 128378SN/A // copy data out of simulator space (write to target memory) 129378SN/A // 130378SN/A virtual bool copyOut(TranslatingPort *memport) 131378SN/A { 132378SN/A memport->writeBlob(addr, bufPtr, size); 1331706SN/A return true; // no EFAULT detection for now 13411851Sbrandon.potter@amd.com } 135360SN/A 13611760Sbrandon.potter@amd.com protected: 13711760Sbrandon.potter@amd.com Addr addr; 13811851Sbrandon.potter@amd.com int size; 13911760Sbrandon.potter@amd.com uint8_t *bufPtr; 1406109Ssanchezd@stanford.edu}; 1411706SN/A 14211851Sbrandon.potter@amd.com 143378SN/Aclass BufferArg : public BaseBufferArg 1446109Ssanchezd@stanford.edu{ 1456109Ssanchezd@stanford.edu public: 14611851Sbrandon.potter@amd.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1476109Ssanchezd@stanford.edu void *bufferPtr() { return bufPtr; } 14811886Sbrandon.potter@amd.com}; 14911886Sbrandon.potter@amd.com 15011886Sbrandon.potter@amd.comtemplate <class T> 15111886Sbrandon.potter@amd.comclass TypedBufferArg : public BaseBufferArg 152378SN/A{ 1531706SN/A public: 15411851Sbrandon.potter@amd.com // user can optionally specify a specific number of bytes to 155378SN/A // allocate to deal with those structs that have variable-size 1565748SSteve.Reinhardt@amd.com // arrays at the end 1575748SSteve.Reinhardt@amd.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 15811851Sbrandon.potter@amd.com : BaseBufferArg(_addr, _size) 159378SN/A { } 160378SN/A 1611706SN/A // type case 16211851Sbrandon.potter@amd.com operator T*() { return (T *)bufPtr; } 163378SN/A 164378SN/A // dereference operators 1651706SN/A T &operator*() { return *((T *)bufPtr); } 16611851Sbrandon.potter@amd.com T* operator->() { return (T *)bufPtr; } 167378SN/A T &operator[](int i) { return ((T *)bufPtr)[i]; } 1684118Sgblack@eecs.umich.edu}; 1694118Sgblack@eecs.umich.edu 17011851Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 1714118Sgblack@eecs.umich.edu// 172378SN/A// The following emulation functions are generic enough that they 1731706SN/A// don't need to be recompiled for different emulated OS's. They are 17411851Sbrandon.potter@amd.com// defined in sim/syscall_emul.cc. 175378SN/A// 17613568Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 17713568Sbrandon.potter@amd.com 17813568Sbrandon.potter@amd.com 17913568Sbrandon.potter@amd.com/// Handler for unimplemented syscalls that we haven't thought about. 180378SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1811706SN/A LiveProcess *p, ThreadContext *tc); 18211851Sbrandon.potter@amd.com 183360SN/A/// Handler for unimplemented syscalls that we never intend to 1845513SMichael.Adler@intel.com/// implement (signal handling, etc.) and should not affect the correct 1855513SMichael.Adler@intel.com/// behavior of the program. Print a warning only if the appropriate 18611851Sbrandon.potter@amd.com/// trace flag is enabled. Return success to the target program. 1875513SMichael.Adler@intel.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 18810203SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 18910203SAli.Saidi@ARM.com 19011851Sbrandon.potter@amd.com/// Target exit() handler: terminate current context. 19110203SAli.Saidi@ARM.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 1925513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 19311851Sbrandon.potter@amd.com 1945513SMichael.Adler@intel.com/// Target exit_group() handler: terminate simulation. (exit all threads) 195511SN/ASyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 19610633Smichaelupton@gmail.com LiveProcess *p, ThreadContext *tc); 19711851Sbrandon.potter@amd.com 19810633Smichaelupton@gmail.com/// Target getpagesize() handler. 1991706SN/ASyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 20011851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 201511SN/A 20212795Smattdsinclair@gmail.com/// Target brk() handler: set brk address. 20312795Smattdsinclair@gmail.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 20412795Smattdsinclair@gmail.com LiveProcess *p, ThreadContext *tc); 20512795Smattdsinclair@gmail.com 20612796Smattdsinclair@gmail.com/// Target close() handler. 20712796Smattdsinclair@gmail.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 20812796Smattdsinclair@gmail.com LiveProcess *p, ThreadContext *tc); 20912796Smattdsinclair@gmail.com 2105513SMichael.Adler@intel.com/// Target read() handler. 2115513SMichael.Adler@intel.comSyscallReturn readFunc(SyscallDesc *desc, int num, 21211851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2135513SMichael.Adler@intel.com 21413031Sbrandon.potter@amd.com/// Target write() handler. 21513031Sbrandon.potter@amd.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 21613031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 21713031Sbrandon.potter@amd.com 21813031Sbrandon.potter@amd.com/// Target lseek() handler. 21913031Sbrandon.potter@amd.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 22013031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 22113031Sbrandon.potter@amd.com 22213031Sbrandon.potter@amd.com/// Target _llseek() handler. 22313031Sbrandon.potter@amd.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 22413031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 22513031Sbrandon.potter@amd.com 226511SN/A/// Target munmap() handler. 2271706SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num, 22811851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2291706SN/A 2301706SN/A/// Target gethostname() handler. 2311706SN/ASyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2321706SN/A LiveProcess *p, ThreadContext *tc); 23311851Sbrandon.potter@amd.com 2341706SN/A/// Target getcwd() handler. 2351706SN/ASyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2361706SN/A LiveProcess *p, ThreadContext *tc); 2371706SN/A 23811851Sbrandon.potter@amd.com/// Target unlink() handler. 2391706SN/ASyscallReturn readlinkFunc(SyscallDesc *desc, int num, 240511SN/A LiveProcess *p, ThreadContext *tc); 2416703Svince@csl.cornell.edu 2426703Svince@csl.cornell.edu/// Target unlink() handler. 24311851Sbrandon.potter@amd.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2446703Svince@csl.cornell.edu LiveProcess *p, ThreadContext *tc); 2456685Stjones1@inf.ed.ac.uk 2466685Stjones1@inf.ed.ac.uk/// Target mkdir() handler. 24711851Sbrandon.potter@amd.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2486685Stjones1@inf.ed.ac.uk LiveProcess *p, ThreadContext *tc); 2496685Stjones1@inf.ed.ac.uk 2505513SMichael.Adler@intel.com/// Target rename() handler. 2515513SMichael.Adler@intel.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 25211851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2535513SMichael.Adler@intel.com 25411885Sbrandon.potter@amd.com 25511885Sbrandon.potter@amd.com/// Target truncate() handler. 25611885Sbrandon.potter@amd.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 2575513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2581999SN/A 2591999SN/A 26011851Sbrandon.potter@amd.com/// Target ftruncate() handler. 2611999SN/ASyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 26211885Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 26311885Sbrandon.potter@amd.com 26411885Sbrandon.potter@amd.com 2651999SN/A/// Target truncate64() handler. 2661999SN/ASyscallReturn truncate64Func(SyscallDesc *desc, int num, 2671999SN/A LiveProcess *p, ThreadContext *tc); 26811851Sbrandon.potter@amd.com 2691999SN/A/// Target ftruncate64() handler. 2703079Sstever@eecs.umich.eduSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2713079Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 27211851Sbrandon.potter@amd.com 2733079Sstever@eecs.umich.edu 27411908SBrandon.Potter@amd.com/// Target umask() handler. 27511908SBrandon.Potter@amd.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 27611908SBrandon.Potter@amd.com LiveProcess *p, ThreadContext *tc); 27711908SBrandon.Potter@amd.com 27811875Sbrandon.potter@amd.com 2792093SN/A/// Target chown() handler. 28011851Sbrandon.potter@amd.comSyscallReturn chownFunc(SyscallDesc *desc, int num, 2812093SN/A LiveProcess *p, ThreadContext *tc); 2822687Sksewell@umich.edu 2832687Sksewell@umich.edu 28411851Sbrandon.potter@amd.com/// Target fchown() handler. 2852687Sksewell@umich.eduSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2862238SN/A LiveProcess *p, ThreadContext *tc); 2872238SN/A 28811851Sbrandon.potter@amd.com/// Target dup() handler. 2892238SN/ASyscallReturn dupFunc(SyscallDesc *desc, int num, 29011908SBrandon.Potter@amd.com LiveProcess *process, ThreadContext *tc); 29111908SBrandon.Potter@amd.com 29211908SBrandon.Potter@amd.com/// Target fnctl() handler. 29311908SBrandon.Potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 29411908SBrandon.Potter@amd.com LiveProcess *process, ThreadContext *tc); 29511908SBrandon.Potter@amd.com 29611908SBrandon.Potter@amd.com/// Target fcntl64() handler. 29711908SBrandon.Potter@amd.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 2982238SN/A LiveProcess *process, ThreadContext *tc); 2992238SN/A 30011851Sbrandon.potter@amd.com/// Target setuid() handler. 3012238SN/ASyscallReturn setuidFunc(SyscallDesc *desc, int num, 30213571Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 30313571Sbrandon.potter@amd.com 30413571Sbrandon.potter@amd.com/// Target getpid() handler. 30513571Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 30613568Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 30713568Sbrandon.potter@amd.com 30813568Sbrandon.potter@amd.com/// Target getuid() handler. 30913568Sbrandon.potter@amd.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 31013568Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 31113568Sbrandon.potter@amd.com 31213568Sbrandon.potter@amd.com/// Target getgid() handler. 31313568Sbrandon.potter@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 31413568Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 31513568Sbrandon.potter@amd.com 31613568Sbrandon.potter@amd.com/// Target getppid() handler. 31713568Sbrandon.potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 31813448Sciro.santilli@arm.com LiveProcess *p, ThreadContext *tc); 31913031Sbrandon.potter@amd.com 32013031Sbrandon.potter@amd.com/// Target geteuid() handler. 32113031Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 32213448Sciro.santilli@arm.com LiveProcess *p, ThreadContext *tc); 32313031Sbrandon.potter@amd.com 32413539Sjavier.setoain@arm.com/// Target getegid() handler. 32513539Sjavier.setoain@arm.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 32613539Sjavier.setoain@arm.com LiveProcess *p, ThreadContext *tc); 32713539Sjavier.setoain@arm.com 32813539Sjavier.setoain@arm.com/// Target clone() handler. 32913539Sjavier.setoain@arm.comSyscallReturn cloneFunc(SyscallDesc *desc, int num, 33013569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 33113569Sbrandon.potter@amd.com 33213569Sbrandon.potter@amd.com 33313569Sbrandon.potter@amd.com/// Pseudo Funcs - These functions use a different return convension, 33413569Sbrandon.potter@amd.com/// returning a second value in a register other than the normal return register 33513569Sbrandon.potter@amd.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 33613569Sbrandon.potter@amd.com LiveProcess *process, ThreadContext *tc); 33713569Sbrandon.potter@amd.com 33813569Sbrandon.potter@amd.com/// Target getpidPseudo() handler. 33913569Sbrandon.potter@amd.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 34013569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 34113569Sbrandon.potter@amd.com 34213569Sbrandon.potter@amd.com/// Target getuidPseudo() handler. 34313569Sbrandon.potter@amd.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 34413569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 34513569Sbrandon.potter@amd.com 34613031Sbrandon.potter@amd.com/// Target getgidPseudo() handler. 3472238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 34811851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 3492238SN/A 3502238SN/A 3512238SN/A/// A readable name for 1,000,000, for converting microseconds to seconds. 35211851Sbrandon.potter@amd.comconst int one_million = 1000000; 3532238SN/A 3542238SN/A/// Approximate seconds since the epoch (1/1/1970). About a billion, 3552238SN/A/// by my reckoning. We want to keep this a constant (not use the 35611851Sbrandon.potter@amd.com/// real-world time) to keep simulations repeatable. 3572238SN/Aconst unsigned seconds_since_epoch = 1000000000; 3582238SN/A 3592238SN/A/// Helper function to convert current elapsed time to seconds and 36011851Sbrandon.potter@amd.com/// microseconds. 3612238SN/Atemplate <class T1, class T2> 3622238SN/Avoid 3632238SN/AgetElapsedTime(T1 &sec, T2 &usec) 36411851Sbrandon.potter@amd.com{ 3652238SN/A int elapsed_usecs = curTick / SimClock::Int::us; 3669455Smitch.hayenga+gem5@gmail.com sec = elapsed_usecs / one_million; 3679455Smitch.hayenga+gem5@gmail.com usec = elapsed_usecs % one_million; 36811851Sbrandon.potter@amd.com} 36910203SAli.Saidi@ARM.com 37011851Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 37111851Sbrandon.potter@amd.com// 3729455Smitch.hayenga+gem5@gmail.com// The following emulation functions are generic, but need to be 37313571Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc. 37413571Sbrandon.potter@amd.com// 37513571Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 37613571Sbrandon.potter@amd.com 37713571Sbrandon.potter@amd.com#if NO_STAT64 37813571Sbrandon.potter@amd.com typedef struct stat hst_stat; 37913571Sbrandon.potter@amd.com typedef struct stat hst_stat64; 38013571Sbrandon.potter@amd.com#else 38113571Sbrandon.potter@amd.com typedef struct stat hst_stat; 38213571Sbrandon.potter@amd.com typedef struct stat64 hst_stat64; 38313571Sbrandon.potter@amd.com#endif 38413571Sbrandon.potter@amd.com 3859112Smarc.orr@gmail.com//// Helper function to convert a host stat buffer to a target stat 38611906SBrandon.Potter@amd.com//// buffer. Also copies the target buffer out to the simulated 38711906SBrandon.Potter@amd.com//// memory space. Used by stat(), fstat(), and lstat(). 3889112Smarc.orr@gmail.com 3899112Smarc.orr@gmail.comtemplate <typename target_stat, typename host_stat> 39011851Sbrandon.potter@amd.comstatic void 3919112Smarc.orr@gmail.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 3929112Smarc.orr@gmail.com{ 39311911SBrandon.Potter@amd.com using namespace TheISA; 3949112Smarc.orr@gmail.com 39511911SBrandon.Potter@amd.com if (fakeTTY) 39611911SBrandon.Potter@amd.com tgt->st_dev = 0xA; 39711911SBrandon.Potter@amd.com else 39811911SBrandon.Potter@amd.com tgt->st_dev = host->st_dev; 39913642Sqtt2@cornell.edu tgt->st_dev = htog(tgt->st_dev); 40013642Sqtt2@cornell.edu tgt->st_ino = host->st_ino; 40113642Sqtt2@cornell.edu tgt->st_ino = htog(tgt->st_ino); 4029112Smarc.orr@gmail.com tgt->st_mode = host->st_mode; 40311911SBrandon.Potter@amd.com if (fakeTTY) { 40411911SBrandon.Potter@amd.com // Claim to be a character device 40511911SBrandon.Potter@amd.com tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 40611911SBrandon.Potter@amd.com tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4079238Slluc.alvarez@bsc.es } 40813642Sqtt2@cornell.edu tgt->st_mode = htog(tgt->st_mode); 4099112Smarc.orr@gmail.com tgt->st_nlink = host->st_nlink; 41011911SBrandon.Potter@amd.com tgt->st_nlink = htog(tgt->st_nlink); 4119112Smarc.orr@gmail.com tgt->st_uid = host->st_uid; 41213642Sqtt2@cornell.edu tgt->st_uid = htog(tgt->st_uid); 41311911SBrandon.Potter@amd.com tgt->st_gid = host->st_gid; 41411911SBrandon.Potter@amd.com tgt->st_gid = htog(tgt->st_gid); 41511911SBrandon.Potter@amd.com if (fakeTTY) 41611911SBrandon.Potter@amd.com tgt->st_rdev = 0x880d; 4179112Smarc.orr@gmail.com else 41811911SBrandon.Potter@amd.com tgt->st_rdev = host->st_rdev; 41911911SBrandon.Potter@amd.com tgt->st_rdev = htog(tgt->st_rdev); 42011911SBrandon.Potter@amd.com tgt->st_size = host->st_size; 42111911SBrandon.Potter@amd.com tgt->st_size = htog(tgt->st_size); 42211911SBrandon.Potter@amd.com tgt->st_atimeX = host->st_atime; 42311911SBrandon.Potter@amd.com tgt->st_atimeX = htog(tgt->st_atimeX); 4249112Smarc.orr@gmail.com tgt->st_mtimeX = host->st_mtime; 4259112Smarc.orr@gmail.com tgt->st_mtimeX = htog(tgt->st_mtimeX); 42613642Sqtt2@cornell.edu tgt->st_ctimeX = host->st_ctime; 42713642Sqtt2@cornell.edu tgt->st_ctimeX = htog(tgt->st_ctimeX); 42813642Sqtt2@cornell.edu // Force the block size to be 8k. This helps to ensure buffered io works 42913642Sqtt2@cornell.edu // consistently across different hosts. 43013642Sqtt2@cornell.edu tgt->st_blksize = 0x2000; 43111911SBrandon.Potter@amd.com tgt->st_blksize = htog(tgt->st_blksize); 4329112Smarc.orr@gmail.com tgt->st_blocks = host->st_blocks; 43311911SBrandon.Potter@amd.com tgt->st_blocks = htog(tgt->st_blocks); 43411911SBrandon.Potter@amd.com} 43513642Sqtt2@cornell.edu 43613642Sqtt2@cornell.edu// Same for stat64 43713650Smw828@cornell.edu 43813650Smw828@cornell.edutemplate <typename target_stat, typename host_stat64> 43913650Smw828@cornell.edustatic void 44013650Smw828@cornell.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 44113650Smw828@cornell.edu{ 44213650Smw828@cornell.edu using namespace TheISA; 44313650Smw828@cornell.edu 44413650Smw828@cornell.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 44513650Smw828@cornell.edu#if defined(STAT_HAVE_NSEC) 44613650Smw828@cornell.edu tgt->st_atime_nsec = host->st_atime_nsec; 44713650Smw828@cornell.edu tgt->st_atime_nsec = htog(tgt->st_atime_nsec); 44813650Smw828@cornell.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 44913650Smw828@cornell.edu tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec); 45013650Smw828@cornell.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 45113651Smw828@cornell.edu tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec); 45213651Smw828@cornell.edu#else 45313651Smw828@cornell.edu tgt->st_atime_nsec = 0; 45413651Smw828@cornell.edu tgt->st_mtime_nsec = 0; 45513651Smw828@cornell.edu tgt->st_ctime_nsec = 0; 45613651Smw828@cornell.edu#endif 45713651Smw828@cornell.edu} 45813651Smw828@cornell.edu 45913651Smw828@cornell.edu//Here are a couple convenience functions 46013651Smw828@cornell.edutemplate<class OS> 46113651Smw828@cornell.edustatic void 46213651Smw828@cornell.educopyOutStatBuf(TranslatingPort * mem, Addr addr, 46313651Smw828@cornell.edu hst_stat *host, bool fakeTTY = false) 46413651Smw828@cornell.edu{ 46513651Smw828@cornell.edu typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 46613651Smw828@cornell.edu tgt_stat_buf tgt(addr); 46713651Smw828@cornell.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 46813651Smw828@cornell.edu tgt.copyOut(mem); 46913651Smw828@cornell.edu} 47013651Smw828@cornell.edu 47113651Smw828@cornell.edutemplate<class OS> 47213651Smw828@cornell.edustatic void 47313651Smw828@cornell.educopyOutStat64Buf(TranslatingPort * mem, Addr addr, 47413651Smw828@cornell.edu hst_stat64 *host, bool fakeTTY = false) 47513651Smw828@cornell.edu{ 47613651Smw828@cornell.edu typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 47713651Smw828@cornell.edu tgt_stat_buf tgt(addr); 47813651Smw828@cornell.edu convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 47913651Smw828@cornell.edu tgt.copyOut(mem); 48013651Smw828@cornell.edu} 48113651Smw828@cornell.edu 48213651Smw828@cornell.edu/// Target ioctl() handler. For the most part, programs call ioctl() 48313651Smw828@cornell.edu/// only to find out if their stdout is a tty, to determine whether to 48413651Smw828@cornell.edu/// do line or block buffering. 48513651Smw828@cornell.edutemplate <class OS> 48613651Smw828@cornell.eduSyscallReturn 48713651Smw828@cornell.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 48813651Smw828@cornell.edu ThreadContext *tc) 48913651Smw828@cornell.edu{ 49013651Smw828@cornell.edu int index = 0; 49113651Smw828@cornell.edu int fd = process->getSyscallArg(tc, index); 49213651Smw828@cornell.edu unsigned req = process->getSyscallArg(tc, index); 49313651Smw828@cornell.edu 49413651Smw828@cornell.edu DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 49513651Smw828@cornell.edu 49613651Smw828@cornell.edu if (fd < 0 || process->sim_fd(fd) < 0) { 49713651Smw828@cornell.edu // doesn't map to any simulator fd: not a valid target fd 49813651Smw828@cornell.edu return -EBADF; 49913651Smw828@cornell.edu } 50013651Smw828@cornell.edu 50113651Smw828@cornell.edu switch (req) { 50213651Smw828@cornell.edu case OS::TIOCISATTY_: 50313651Smw828@cornell.edu case OS::TIOCGETP_: 50413651Smw828@cornell.edu case OS::TIOCSETP_: 50513651Smw828@cornell.edu case OS::TIOCSETN_: 50613651Smw828@cornell.edu case OS::TIOCSETC_: 50713651Smw828@cornell.edu case OS::TIOCGETC_: 50813651Smw828@cornell.edu case OS::TIOCGETS_: 50913651Smw828@cornell.edu case OS::TIOCGETA_: 51013651Smw828@cornell.edu case OS::TCSETAW_: 51113651Smw828@cornell.edu return -ENOTTY; 51213651Smw828@cornell.edu 51313651Smw828@cornell.edu default: 51413651Smw828@cornell.edu fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 51513651Smw828@cornell.edu fd, req, tc->readPC()); 51613651Smw828@cornell.edu } 51713651Smw828@cornell.edu} 51813651Smw828@cornell.edu 51913651Smw828@cornell.edu/// Target open() handler. 52013651Smw828@cornell.edutemplate <class OS> 52113651Smw828@cornell.eduSyscallReturn 5229112Smarc.orr@gmail.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 52311911SBrandon.Potter@amd.com ThreadContext *tc) 52411911SBrandon.Potter@amd.com{ 5259112Smarc.orr@gmail.com std::string path; 5269112Smarc.orr@gmail.com 5272238SN/A int index = 0; 5282238SN/A if (!tc->getMemPort()->tryReadString(path, 5292238SN/A process->getSyscallArg(tc, index))) 5302238SN/A return -EFAULT; 53111851Sbrandon.potter@amd.com 5322238SN/A if (path == "/dev/sysdev0") { 5332238SN/A // This is a memory-mapped high-resolution timer device on Alpha. 5342238SN/A // We don't support it, so just punt. 53511851Sbrandon.potter@amd.com warn("Ignoring open(%s, ...)\n", path); 5362238SN/A return -ENOENT; 5372238SN/A } 5382238SN/A 53911851Sbrandon.potter@amd.com int tgtFlags = process->getSyscallArg(tc, index); 5402238SN/A int mode = process->getSyscallArg(tc, index); 5412238SN/A int hostFlags = 0; 5422238SN/A 54311851Sbrandon.potter@amd.com // translate open flags 5442238SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 5452238SN/A if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 5461354SN/A tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 5471354SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 54810796Sbrandon.potter@amd.com } 54910796Sbrandon.potter@amd.com } 5501354SN/A 5511354SN/A // any target flags left? 5521354SN/A if (tgtFlags != 0) 5531354SN/A warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 5541354SN/A 5551354SN/A#ifdef __CYGWIN32__ 5561354SN/A hostFlags |= O_BINARY; 5571354SN/A#endif 5581354SN/A 5591354SN/A // Adjust path for current working directory 56010796Sbrandon.potter@amd.com path = process->fullPath(path); 5611354SN/A 56210796Sbrandon.potter@amd.com DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 5631354SN/A 5641354SN/A int fd; 5651354SN/A if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 5661354SN/A !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 56710796Sbrandon.potter@amd.com // It's a proc/sys entery and requires special handling 56810796Sbrandon.potter@amd.com fd = OS::openSpecialFile(path, process, tc); 56910796Sbrandon.potter@amd.com return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 57010796Sbrandon.potter@amd.com } else { 57110796Sbrandon.potter@amd.com // open the file 57210796Sbrandon.potter@amd.com fd = open(path.c_str(), hostFlags, mode); 57310796Sbrandon.potter@amd.com return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 57410796Sbrandon.potter@amd.com } 57510796Sbrandon.potter@amd.com 57610796Sbrandon.potter@amd.com} 57710796Sbrandon.potter@amd.com 578360SN/A/// Target sysinfo() handler. 579360SN/Atemplate <class OS> 580360SN/ASyscallReturn 581360SN/AsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 582360SN/A ThreadContext *tc) 583360SN/A{ 584360SN/A 58511759Sbrandon.potter@amd.com int index = 0; 5863113Sgblack@eecs.umich.edu TypedBufferArg<typename OS::tgt_sysinfo> 5873113Sgblack@eecs.umich.edu sysinfo(process->getSyscallArg(tc, index)); 5883113Sgblack@eecs.umich.edu 5893113Sgblack@eecs.umich.edu sysinfo->uptime=seconds_since_epoch; 5903113Sgblack@eecs.umich.edu sysinfo->totalram=process->system->memSize(); 5913113Sgblack@eecs.umich.edu 5923113Sgblack@eecs.umich.edu sysinfo.copyOut(tc->getMemPort()); 5933113Sgblack@eecs.umich.edu 5943113Sgblack@eecs.umich.edu return 0; 5953113Sgblack@eecs.umich.edu} 5963113Sgblack@eecs.umich.edu 5973113Sgblack@eecs.umich.edu/// Target chmod() handler. 5983113Sgblack@eecs.umich.edutemplate <class OS> 59912032Sandreas.sandberg@arm.comSyscallReturn 6003113Sgblack@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6013113Sgblack@eecs.umich.edu ThreadContext *tc) 6024189Sgblack@eecs.umich.edu{ 6034189Sgblack@eecs.umich.edu std::string path; 6043113Sgblack@eecs.umich.edu 6053113Sgblack@eecs.umich.edu int index = 0; 6063113Sgblack@eecs.umich.edu if (!tc->getMemPort()->tryReadString(path, 6073113Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 6088737Skoansin.tan@gmail.com return -EFAULT; 6093113Sgblack@eecs.umich.edu } 6108737Skoansin.tan@gmail.com 6113277Sgblack@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 6125515SMichael.Adler@intel.com mode_t hostMode = 0; 6135515SMichael.Adler@intel.com 6145515SMichael.Adler@intel.com // XXX translate mode flags via OS::something??? 6155515SMichael.Adler@intel.com hostMode = mode; 6165515SMichael.Adler@intel.com 6178737Skoansin.tan@gmail.com // Adjust path for current working directory 6183277Sgblack@eecs.umich.edu path = process->fullPath(path); 6198737Skoansin.tan@gmail.com 6203277Sgblack@eecs.umich.edu // do the chmod 6218737Skoansin.tan@gmail.com int result = chmod(path.c_str(), hostMode); 6223277Sgblack@eecs.umich.edu if (result < 0) 6238737Skoansin.tan@gmail.com return -errno; 6243113Sgblack@eecs.umich.edu 6253113Sgblack@eecs.umich.edu return 0; 6263113Sgblack@eecs.umich.edu} 6273113Sgblack@eecs.umich.edu 6288737Skoansin.tan@gmail.com 6293113Sgblack@eecs.umich.edu/// Target fchmod() handler. 6308737Skoansin.tan@gmail.comtemplate <class OS> 6313114Sgblack@eecs.umich.eduSyscallReturn 6328737Skoansin.tan@gmail.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6333114Sgblack@eecs.umich.edu ThreadContext *tc) 6348737Skoansin.tan@gmail.com{ 6353114Sgblack@eecs.umich.edu int index = 0; 6368737Skoansin.tan@gmail.com int fd = process->getSyscallArg(tc, index); 63711906SBrandon.Potter@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 6384061Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 6394061Sgblack@eecs.umich.edu return -EBADF; 6408737Skoansin.tan@gmail.com } 6413113Sgblack@eecs.umich.edu 6428737Skoansin.tan@gmail.com uint32_t mode = process->getSyscallArg(tc, index); 6433113Sgblack@eecs.umich.edu mode_t hostMode = 0; 6443113Sgblack@eecs.umich.edu 6453113Sgblack@eecs.umich.edu // XXX translate mode flags via OS::someting??? 6463113Sgblack@eecs.umich.edu hostMode = mode; 6473113Sgblack@eecs.umich.edu 64812032Sandreas.sandberg@arm.com // do the fchmod 6493113Sgblack@eecs.umich.edu int result = fchmod(process->sim_fd(fd), hostMode); 6503113Sgblack@eecs.umich.edu if (result < 0) 6514189Sgblack@eecs.umich.edu return -errno; 6524189Sgblack@eecs.umich.edu 6533113Sgblack@eecs.umich.edu return 0; 6543113Sgblack@eecs.umich.edu} 6553113Sgblack@eecs.umich.edu 6568737Skoansin.tan@gmail.com/// Target mremap() handler. 6573113Sgblack@eecs.umich.edutemplate <class OS> 6588737Skoansin.tan@gmail.comSyscallReturn 6593113Sgblack@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 6608737Skoansin.tan@gmail.com{ 6613113Sgblack@eecs.umich.edu int index = 0; 6623113Sgblack@eecs.umich.edu Addr start = process->getSyscallArg(tc, index); 6633113Sgblack@eecs.umich.edu uint64_t old_length = process->getSyscallArg(tc, index); 6643113Sgblack@eecs.umich.edu uint64_t new_length = process->getSyscallArg(tc, index); 6653113Sgblack@eecs.umich.edu uint64_t flags = process->getSyscallArg(tc, index); 6663113Sgblack@eecs.umich.edu 6673113Sgblack@eecs.umich.edu if ((start % TheISA::VMPageSize != 0) || 66811906SBrandon.Potter@amd.com (new_length % TheISA::VMPageSize != 0)) { 6693113Sgblack@eecs.umich.edu warn("mremap failing: arguments not page aligned"); 67012032Sandreas.sandberg@arm.com return -EINVAL; 6718852Sandreas.hansson@arm.com } 67211906SBrandon.Potter@amd.com 6733113Sgblack@eecs.umich.edu if (new_length > old_length) { 6743113Sgblack@eecs.umich.edu if ((start + old_length) == process->mmap_end) { 6753113Sgblack@eecs.umich.edu uint64_t diff = new_length - old_length; 6763113Sgblack@eecs.umich.edu process->pTable->allocate(process->mmap_end, diff); 6773113Sgblack@eecs.umich.edu process->mmap_end += diff; 6783113Sgblack@eecs.umich.edu return start; 6793113Sgblack@eecs.umich.edu } else { 6803113Sgblack@eecs.umich.edu // sys/mman.h defined MREMAP_MAYMOVE 68112032Sandreas.sandberg@arm.com if (!(flags & 1)) { 6828852Sandreas.hansson@arm.com warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 68311906SBrandon.Potter@amd.com return -ENOMEM; 6843113Sgblack@eecs.umich.edu } else { 6853113Sgblack@eecs.umich.edu process->pTable->remap(start, old_length, process->mmap_end); 6863113Sgblack@eecs.umich.edu warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 6876686Stjones1@inf.ed.ac.uk process->mmap_end, process->mmap_end + new_length, new_length); 6883113Sgblack@eecs.umich.edu start = process->mmap_end; 6893113Sgblack@eecs.umich.edu // add on the remaining unallocated pages 6903113Sgblack@eecs.umich.edu process->pTable->allocate(start + old_length, new_length - old_length); 69111759Sbrandon.potter@amd.com process->mmap_end += new_length; 69212032Sandreas.sandberg@arm.com warn("returning %08p as start\n", start); 69311759Sbrandon.potter@amd.com return start; 69411759Sbrandon.potter@amd.com } 69511759Sbrandon.potter@amd.com } 69611759Sbrandon.potter@amd.com } else { 69711759Sbrandon.potter@amd.com process->pTable->deallocate(start + new_length, old_length - 69811812Sbaz21@cam.ac.uk new_length); 69911812Sbaz21@cam.ac.uk return start; 70011812Sbaz21@cam.ac.uk } 70111759Sbrandon.potter@amd.com} 70211812Sbaz21@cam.ac.uk 70311759Sbrandon.potter@amd.com/// Target stat() handler. 70411759Sbrandon.potter@amd.comtemplate <class OS> 70511759Sbrandon.potter@amd.comSyscallReturn 70611759Sbrandon.potter@amd.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 70711759Sbrandon.potter@amd.com ThreadContext *tc) 70811759Sbrandon.potter@amd.com{ 70911759Sbrandon.potter@amd.com std::string path; 71011812Sbaz21@cam.ac.uk 71111812Sbaz21@cam.ac.uk int index = 0; 71211812Sbaz21@cam.ac.uk if (!tc->getMemPort()->tryReadString(path, 71311812Sbaz21@cam.ac.uk process->getSyscallArg(tc, index))) { 71411812Sbaz21@cam.ac.uk return -EFAULT; 71511812Sbaz21@cam.ac.uk } 71611812Sbaz21@cam.ac.uk Addr bufPtr = process->getSyscallArg(tc, index); 71711759Sbrandon.potter@amd.com 71811759Sbrandon.potter@amd.com // Adjust path for current working directory 71911812Sbaz21@cam.ac.uk path = process->fullPath(path); 72011812Sbaz21@cam.ac.uk 72111759Sbrandon.potter@amd.com struct stat hostBuf; 72211812Sbaz21@cam.ac.uk int result = stat(path.c_str(), &hostBuf); 72311812Sbaz21@cam.ac.uk 72411812Sbaz21@cam.ac.uk if (result < 0) 72511812Sbaz21@cam.ac.uk return -errno; 72611812Sbaz21@cam.ac.uk 72711812Sbaz21@cam.ac.uk copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 72811812Sbaz21@cam.ac.uk 72911759Sbrandon.potter@amd.com return 0; 73011759Sbrandon.potter@amd.com} 73111759Sbrandon.potter@amd.com 73211759Sbrandon.potter@amd.com 733378SN/A/// Target stat64() handler. 734378SN/Atemplate <class OS> 7359141Smarc.orr@gmail.comSyscallReturn 7369141Smarc.orr@gmail.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 737360SN/A ThreadContext *tc) 7381450SN/A{ 73911856Sbrandon.potter@amd.com std::string path; 740360SN/A 7416701Sgblack@eecs.umich.edu int index = 0; 74211856Sbrandon.potter@amd.com if (!tc->getMemPort()->tryReadString(path, 74311856Sbrandon.potter@amd.com process->getSyscallArg(tc, index))) 744360SN/A return -EFAULT; 74513907Salexandru.dutu@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 746360SN/A 74711856Sbrandon.potter@amd.com // Adjust path for current working directory 74811856Sbrandon.potter@amd.com path = process->fullPath(path); 74910496Ssteve.reinhardt@amd.com 75011856Sbrandon.potter@amd.com#if NO_STAT64 75113902Sbrandon.potter@amd.com struct stat hostBuf; 75213902Sbrandon.potter@amd.com int result = stat(path.c_str(), &hostBuf); 75313902Sbrandon.potter@amd.com#else 75413902Sbrandon.potter@amd.com struct stat64 hostBuf; 75513902Sbrandon.potter@amd.com int result = stat64(path.c_str(), &hostBuf); 75613902Sbrandon.potter@amd.com#endif 75713902Sbrandon.potter@amd.com 75813902Sbrandon.potter@amd.com if (result < 0) 75913902Sbrandon.potter@amd.com return -errno; 76013902Sbrandon.potter@amd.com 76113902Sbrandon.potter@amd.com copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 76213902Sbrandon.potter@amd.com 76313902Sbrandon.potter@amd.com return 0; 76413902Sbrandon.potter@amd.com} 76513902Sbrandon.potter@amd.com 76613902Sbrandon.potter@amd.com 76713902Sbrandon.potter@amd.com/// Target fstat64() handler. 76813902Sbrandon.potter@amd.comtemplate <class OS> 76913902Sbrandon.potter@amd.comSyscallReturn 77013902Sbrandon.potter@amd.comfstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 77113902Sbrandon.potter@amd.com ThreadContext *tc) 77213902Sbrandon.potter@amd.com{ 77313902Sbrandon.potter@amd.com int index = 0; 77413902Sbrandon.potter@amd.com int fd = process->getSyscallArg(tc, index); 77513902Sbrandon.potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 77613902Sbrandon.potter@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 77713902Sbrandon.potter@amd.com // doesn't map to any simulator fd: not a valid target fd 77813902Sbrandon.potter@amd.com return -EBADF; 77913902Sbrandon.potter@amd.com } 78013902Sbrandon.potter@amd.com 78113902Sbrandon.potter@amd.com#if NO_STAT64 78213902Sbrandon.potter@amd.com struct stat hostBuf; 78313902Sbrandon.potter@amd.com int result = fstat(process->sim_fd(fd), &hostBuf); 78413936SAndrea.Mondelli@ucf.edu#else 78513902Sbrandon.potter@amd.com struct stat64 hostBuf; 78613902Sbrandon.potter@amd.com int result = fstat64(process->sim_fd(fd), &hostBuf); 78713902Sbrandon.potter@amd.com#endif 78813902Sbrandon.potter@amd.com 78913936SAndrea.Mondelli@ucf.edu if (result < 0) 79013902Sbrandon.potter@amd.com return -errno; 79113902Sbrandon.potter@amd.com 79213902Sbrandon.potter@amd.com copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); 79313902Sbrandon.potter@amd.com 79413902Sbrandon.potter@amd.com return 0; 79513902Sbrandon.potter@amd.com} 79613902Sbrandon.potter@amd.com 79713902Sbrandon.potter@amd.com 79813902Sbrandon.potter@amd.com/// Target lstat() handler. 79913902Sbrandon.potter@amd.comtemplate <class OS> 80013902Sbrandon.potter@amd.comSyscallReturn 80113902Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 80213902Sbrandon.potter@amd.com ThreadContext *tc) 80313902Sbrandon.potter@amd.com{ 80410496Ssteve.reinhardt@amd.com std::string path; 80511856Sbrandon.potter@amd.com 80611856Sbrandon.potter@amd.com int index = 0; 80711856Sbrandon.potter@amd.com if (!tc->getMemPort()->tryReadString(path, 80811856Sbrandon.potter@amd.com process->getSyscallArg(tc, index))) { 80911856Sbrandon.potter@amd.com return -EFAULT; 81010930Sbrandon.potter@amd.com } 8119141Smarc.orr@gmail.com Addr bufPtr = process->getSyscallArg(tc, index); 812360SN/A 813360SN/A // Adjust path for current working directory 814360SN/A path = process->fullPath(path); 81511907SBrandon.Potter@amd.com 81611907SBrandon.Potter@amd.com struct stat hostBuf; 81711907SBrandon.Potter@amd.com int result = lstat(path.c_str(), &hostBuf); 818360SN/A 81911907SBrandon.Potter@amd.com if (result < 0) 82011907SBrandon.Potter@amd.com return -errno; 82111907SBrandon.Potter@amd.com 82211907SBrandon.Potter@amd.com copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 82311907SBrandon.Potter@amd.com 82411907SBrandon.Potter@amd.com return 0; 82511907SBrandon.Potter@amd.com} 82611907SBrandon.Potter@amd.com 82711907SBrandon.Potter@amd.com/// Target lstat64() handler. 82811907SBrandon.Potter@amd.comtemplate <class OS> 82911907SBrandon.Potter@amd.comSyscallReturn 83011907SBrandon.Potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 83111907SBrandon.Potter@amd.com ThreadContext *tc) 83211907SBrandon.Potter@amd.com{ 833360SN/A std::string path; 83411907SBrandon.Potter@amd.com 8351458SN/A int index = 0; 836360SN/A if (!tc->getMemPort()->tryReadString(path, 83711907SBrandon.Potter@amd.com process->getSyscallArg(tc, index))) { 83811907SBrandon.Potter@amd.com return -EFAULT; 83911907SBrandon.Potter@amd.com } 84011907SBrandon.Potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 84111907SBrandon.Potter@amd.com 84211907SBrandon.Potter@amd.com // Adjust path for current working directory 84311907SBrandon.Potter@amd.com path = process->fullPath(path); 84411907SBrandon.Potter@amd.com 84511907SBrandon.Potter@amd.com#if NO_STAT64 84611907SBrandon.Potter@amd.com struct stat hostBuf; 847360SN/A int result = lstat(path.c_str(), &hostBuf); 84811907SBrandon.Potter@amd.com#else 84911907SBrandon.Potter@amd.com struct stat64 hostBuf; 85011907SBrandon.Potter@amd.com int result = lstat64(path.c_str(), &hostBuf); 851360SN/A#endif 852360SN/A 85311907SBrandon.Potter@amd.com if (result < 0) 85411907SBrandon.Potter@amd.com return -errno; 85511907SBrandon.Potter@amd.com 85611907SBrandon.Potter@amd.com copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 857360SN/A 85811907SBrandon.Potter@amd.com return 0; 859360SN/A} 860360SN/A 86111907SBrandon.Potter@amd.com/// Target fstat() handler. 8623669Sbinkertn@umich.edutemplate <class OS> 86311907SBrandon.Potter@amd.comSyscallReturn 86411907SBrandon.Potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 86511907SBrandon.Potter@amd.com ThreadContext *tc) 86611907SBrandon.Potter@amd.com{ 86711907SBrandon.Potter@amd.com int index = 0; 86811907SBrandon.Potter@amd.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 86911907SBrandon.Potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 87011907SBrandon.Potter@amd.com 87111907SBrandon.Potter@amd.com DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 87211907SBrandon.Potter@amd.com 87311907SBrandon.Potter@amd.com if (fd < 0) 87411907SBrandon.Potter@amd.com return -EBADF; 87513883Sdavid.hashe@amd.com 87613883Sdavid.hashe@amd.com struct stat hostBuf; 87713883Sdavid.hashe@amd.com int result = fstat(fd, &hostBuf); 87813883Sdavid.hashe@amd.com 87913883Sdavid.hashe@amd.com if (result < 0) 88011907SBrandon.Potter@amd.com return -errno; 88111907SBrandon.Potter@amd.com 88211907SBrandon.Potter@amd.com copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); 88311907SBrandon.Potter@amd.com 88411907SBrandon.Potter@amd.com return 0; 88513883Sdavid.hashe@amd.com} 88613883Sdavid.hashe@amd.com 88711907SBrandon.Potter@amd.com 8881706SN/A/// Target statfs() handler. 88911907SBrandon.Potter@amd.comtemplate <class OS> 89011907SBrandon.Potter@amd.comSyscallReturn 89111907SBrandon.Potter@amd.comstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 89211907SBrandon.Potter@amd.com ThreadContext *tc) 89311907SBrandon.Potter@amd.com{ 89411907SBrandon.Potter@amd.com std::string path; 89513883Sdavid.hashe@amd.com 89613883Sdavid.hashe@amd.com int index = 0; 89711907SBrandon.Potter@amd.com if (!tc->getMemPort()->tryReadString(path, 89811907SBrandon.Potter@amd.com process->getSyscallArg(tc, index))) { 89911907SBrandon.Potter@amd.com return -EFAULT; 90011907SBrandon.Potter@amd.com } 90113883Sdavid.hashe@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 90211907SBrandon.Potter@amd.com 90310496Ssteve.reinhardt@amd.com // Adjust path for current working directory 90411907SBrandon.Potter@amd.com path = process->fullPath(path); 90511907SBrandon.Potter@amd.com 90611907SBrandon.Potter@amd.com struct statfs hostBuf; 90711907SBrandon.Potter@amd.com int result = statfs(path.c_str(), &hostBuf); 90810496Ssteve.reinhardt@amd.com 90910496Ssteve.reinhardt@amd.com if (result < 0) 91011907SBrandon.Potter@amd.com return -errno; 91113883Sdavid.hashe@amd.com 91213883Sdavid.hashe@amd.com OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); 91313883Sdavid.hashe@amd.com 91413883Sdavid.hashe@amd.com return 0; 91513883Sdavid.hashe@amd.com} 91613883Sdavid.hashe@amd.com 91713883Sdavid.hashe@amd.com 91813883Sdavid.hashe@amd.com/// Target fstatfs() handler. 91913883Sdavid.hashe@amd.comtemplate <class OS> 92013883Sdavid.hashe@amd.comSyscallReturn 92113883Sdavid.hashe@amd.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 92213883Sdavid.hashe@amd.com ThreadContext *tc) 92313883Sdavid.hashe@amd.com{ 92413883Sdavid.hashe@amd.com int index = 0; 92513883Sdavid.hashe@amd.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 92613883Sdavid.hashe@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 92713883Sdavid.hashe@amd.com 92813883Sdavid.hashe@amd.com if (fd < 0) 92913883Sdavid.hashe@amd.com return -EBADF; 93013883Sdavid.hashe@amd.com 93113883Sdavid.hashe@amd.com struct statfs hostBuf; 93213883Sdavid.hashe@amd.com int result = fstatfs(fd, &hostBuf); 93311907SBrandon.Potter@amd.com 93411907SBrandon.Potter@amd.com if (result < 0) 93513883Sdavid.hashe@amd.com return -errno; 93611907SBrandon.Potter@amd.com 93713883Sdavid.hashe@amd.com OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); 93813883Sdavid.hashe@amd.com 93911907SBrandon.Potter@amd.com return 0; 94013883Sdavid.hashe@amd.com} 94113883Sdavid.hashe@amd.com 94213883Sdavid.hashe@amd.com 94313883Sdavid.hashe@amd.com/// Target writev() handler. 94411907SBrandon.Potter@amd.comtemplate <class OS> 94511907SBrandon.Potter@amd.comSyscallReturn 94613883Sdavid.hashe@amd.comwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 94713883Sdavid.hashe@amd.com ThreadContext *tc) 94811907SBrandon.Potter@amd.com{ 94911907SBrandon.Potter@amd.com int index = 0; 95011907SBrandon.Potter@amd.com int fd = process->getSyscallArg(tc, index); 95113883Sdavid.hashe@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 95213883Sdavid.hashe@amd.com // doesn't map to any simulator fd: not a valid target fd 95313883Sdavid.hashe@amd.com return -EBADF; 95411907SBrandon.Potter@amd.com } 95511907SBrandon.Potter@amd.com 956360SN/A TranslatingPort *p = tc->getMemPort(); 95711907SBrandon.Potter@amd.com uint64_t tiov_base = process->getSyscallArg(tc, index); 95811907SBrandon.Potter@amd.com size_t count = process->getSyscallArg(tc, index); 95911907SBrandon.Potter@amd.com struct iovec hiov[count]; 96011907SBrandon.Potter@amd.com for (size_t i = 0; i < count; ++i) { 96111907SBrandon.Potter@amd.com typename OS::tgt_iovec tiov; 96211907SBrandon.Potter@amd.com 96311907SBrandon.Potter@amd.com p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 96411907SBrandon.Potter@amd.com (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 96511907SBrandon.Potter@amd.com hiov[i].iov_len = gtoh(tiov.iov_len); 96611907SBrandon.Potter@amd.com hiov[i].iov_base = new char [hiov[i].iov_len]; 96713883Sdavid.hashe@amd.com p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 96813883Sdavid.hashe@amd.com hiov[i].iov_len); 96913883Sdavid.hashe@amd.com } 97011907SBrandon.Potter@amd.com 971360SN/A int result = writev(process->sim_fd(fd), hiov, count); 972360SN/A 97310027SChris.Adeniyi-Jones@arm.com for (size_t i = 0; i < count; ++i) 97410027SChris.Adeniyi-Jones@arm.com delete [] (char *)hiov[i].iov_base; 97510027SChris.Adeniyi-Jones@arm.com 97611851Sbrandon.potter@amd.com if (result < 0) 97710027SChris.Adeniyi-Jones@arm.com return -errno; 97810027SChris.Adeniyi-Jones@arm.com 97911907SBrandon.Potter@amd.com return 0; 98010027SChris.Adeniyi-Jones@arm.com} 98110027SChris.Adeniyi-Jones@arm.com 98210027SChris.Adeniyi-Jones@arm.com 98310027SChris.Adeniyi-Jones@arm.com/// Target mmap() handler. 98410027SChris.Adeniyi-Jones@arm.com/// 98511851Sbrandon.potter@amd.com/// We don't really handle mmap(). If the target is mmaping an 98611851Sbrandon.potter@amd.com/// anonymous region or /dev/zero, we can get away with doing basically 98710027SChris.Adeniyi-Jones@arm.com/// nothing (since memory is initialized to zero and the simulator 98811907SBrandon.Potter@amd.com/// doesn't really check addresses anyway). Always print a warning, 98910027SChris.Adeniyi-Jones@arm.com/// since this could be seriously broken if we're not mapping 99010027SChris.Adeniyi-Jones@arm.com/// /dev/zero. 99110633Smichaelupton@gmail.com// 99210633Smichaelupton@gmail.com/// Someday we should explicitly check for /dev/zero in open, flag the 99310633Smichaelupton@gmail.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to 99411851Sbrandon.potter@amd.com/// anything else. 99510633Smichaelupton@gmail.comtemplate <class OS> 99610633Smichaelupton@gmail.comSyscallReturn 99710633Smichaelupton@gmail.commmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 99810633Smichaelupton@gmail.com{ 99910633Smichaelupton@gmail.com int index = 0; 100010633Smichaelupton@gmail.com Addr start = p->getSyscallArg(tc, index); 100110633Smichaelupton@gmail.com uint64_t length = p->getSyscallArg(tc, index); 100210633Smichaelupton@gmail.com index++; // int prot = p->getSyscallArg(tc, index); 100310633Smichaelupton@gmail.com int flags = p->getSyscallArg(tc, index); 100410633Smichaelupton@gmail.com int fd = p->sim_fd(p->getSyscallArg(tc, index)); 100510203SAli.Saidi@ARM.com // int offset = p->getSyscallArg(tc, index); 100610203SAli.Saidi@ARM.com 100710203SAli.Saidi@ARM.com 100811851Sbrandon.potter@amd.com if ((start % TheISA::VMPageSize) != 0 || 100911851Sbrandon.potter@amd.com (length % TheISA::VMPageSize) != 0) { 101010203SAli.Saidi@ARM.com warn("mmap failing: arguments not page-aligned: " 101110203SAli.Saidi@ARM.com "start 0x%x length 0x%x", 101210203SAli.Saidi@ARM.com start, length); 101310203SAli.Saidi@ARM.com return -EINVAL; 101410203SAli.Saidi@ARM.com } 101510203SAli.Saidi@ARM.com 101610203SAli.Saidi@ARM.com if (start != 0) { 101710203SAli.Saidi@ARM.com warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 101810203SAli.Saidi@ARM.com start, p->mmap_end); 101910203SAli.Saidi@ARM.com } 102010203SAli.Saidi@ARM.com 102111851Sbrandon.potter@amd.com // pick next address from our "mmap region" 102211851Sbrandon.potter@amd.com if (OS::mmapGrowsDown()) { 102310203SAli.Saidi@ARM.com start = p->mmap_end - length; 102410203SAli.Saidi@ARM.com p->mmap_end = start; 102510203SAli.Saidi@ARM.com } else { 102610203SAli.Saidi@ARM.com start = p->mmap_end; 102710203SAli.Saidi@ARM.com p->mmap_end += length; 102810203SAli.Saidi@ARM.com } 102910203SAli.Saidi@ARM.com p->pTable->allocate(start, length); 103010203SAli.Saidi@ARM.com 103110850SGiacomo.Gabrielli@arm.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 103210850SGiacomo.Gabrielli@arm.com warn("allowing mmap of file @ fd %d. " 103310850SGiacomo.Gabrielli@arm.com "This will break if not /dev/zero.", fd); 103411851Sbrandon.potter@amd.com } 103510850SGiacomo.Gabrielli@arm.com 103610850SGiacomo.Gabrielli@arm.com return start; 103710850SGiacomo.Gabrielli@arm.com} 103810850SGiacomo.Gabrielli@arm.com 103910850SGiacomo.Gabrielli@arm.com/// Target getrlimit() handler. 104010850SGiacomo.Gabrielli@arm.comtemplate <class OS> 104110850SGiacomo.Gabrielli@arm.comSyscallReturn 104210850SGiacomo.Gabrielli@arm.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 104310850SGiacomo.Gabrielli@arm.com ThreadContext *tc) 104410850SGiacomo.Gabrielli@arm.com{ 104510850SGiacomo.Gabrielli@arm.com int index = 0; 104610850SGiacomo.Gabrielli@arm.com unsigned resource = process->getSyscallArg(tc, index); 104710850SGiacomo.Gabrielli@arm.com TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 104810850SGiacomo.Gabrielli@arm.com 104910850SGiacomo.Gabrielli@arm.com switch (resource) { 105010850SGiacomo.Gabrielli@arm.com case OS::TGT_RLIMIT_STACK: 105110850SGiacomo.Gabrielli@arm.com // max stack size in bytes: make up a number (8MB for now) 105210850SGiacomo.Gabrielli@arm.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 105310850SGiacomo.Gabrielli@arm.com rlp->rlim_cur = htog(rlp->rlim_cur); 105410850SGiacomo.Gabrielli@arm.com rlp->rlim_max = htog(rlp->rlim_max); 105510850SGiacomo.Gabrielli@arm.com break; 105610850SGiacomo.Gabrielli@arm.com 105710850SGiacomo.Gabrielli@arm.com case OS::TGT_RLIMIT_DATA: 105810850SGiacomo.Gabrielli@arm.com // max data segment size in bytes: make up a number 105913883Sdavid.hashe@amd.com rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 106013883Sdavid.hashe@amd.com rlp->rlim_cur = htog(rlp->rlim_cur); 106113883Sdavid.hashe@amd.com rlp->rlim_max = htog(rlp->rlim_max); 106210850SGiacomo.Gabrielli@arm.com break; 106310850SGiacomo.Gabrielli@arm.com 106410850SGiacomo.Gabrielli@arm.com default: 106510850SGiacomo.Gabrielli@arm.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 106610850SGiacomo.Gabrielli@arm.com << std::endl; 10676640Svince@csl.cornell.edu abort(); 10686640Svince@csl.cornell.edu break; 10696640Svince@csl.cornell.edu } 107011851Sbrandon.potter@amd.com 107111851Sbrandon.potter@amd.com rlp.copyOut(tc->getMemPort()); 10726640Svince@csl.cornell.edu return 0; 10736640Svince@csl.cornell.edu} 10746701Sgblack@eecs.umich.edu 10756701Sgblack@eecs.umich.edu/// Target gettimeofday() handler. 107610793Sbrandon.potter@amd.comtemplate <class OS> 10776640Svince@csl.cornell.eduSyscallReturn 107811758Sbrandon.potter@amd.comgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 107911758Sbrandon.potter@amd.com ThreadContext *tc) 108011758Sbrandon.potter@amd.com{ 10816640Svince@csl.cornell.edu int index = 0; 10828706Sandreas.hansson@arm.com TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 10836640Svince@csl.cornell.edu 10846701Sgblack@eecs.umich.edu getElapsedTime(tp->tv_sec, tp->tv_usec); 10856640Svince@csl.cornell.edu tp->tv_sec += seconds_since_epoch; 1086360SN/A tp->tv_sec = TheISA::htog(tp->tv_sec); 10871999SN/A tp->tv_usec = TheISA::htog(tp->tv_usec); 10881999SN/A 10891999SN/A tp.copyOut(tc->getMemPort()); 109011851Sbrandon.potter@amd.com 10912680Sktlim@umich.edu return 0; 10921999SN/A} 10931999SN/A 10941999SN/A 10956701Sgblack@eecs.umich.edu/// Target utimes() handler. 10968852Sandreas.hansson@arm.comtemplate <class OS> 10976701Sgblack@eecs.umich.eduSyscallReturn 10981999SN/AutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10996701Sgblack@eecs.umich.edu ThreadContext *tc) 11001999SN/A{ 11016701Sgblack@eecs.umich.edu std::string path; 11021999SN/A 11031999SN/A int index = 0; 11041999SN/A if (!tc->getMemPort()->tryReadString(path, 11051999SN/A process->getSyscallArg(tc, index))) { 11061999SN/A return -EFAULT; 110713883Sdavid.hashe@amd.com } 110813883Sdavid.hashe@amd.com 11093669Sbinkertn@umich.edu TypedBufferArg<typename OS::timeval [2]> 11101999SN/A tp(process->getSyscallArg(tc, index)); 11111999SN/A tp.copyIn(tc->getMemPort()); 11121999SN/A 11132218SN/A struct timeval hostTimeval[2]; 11141999SN/A for (int i = 0; i < 2; ++i) 11151999SN/A { 11161999SN/A hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 11171999SN/A hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 111813570Sbrandon.potter@amd.com } 111913570Sbrandon.potter@amd.com 112013570Sbrandon.potter@amd.com // Adjust path for current working directory 112113570Sbrandon.potter@amd.com path = process->fullPath(path); 112213570Sbrandon.potter@amd.com 112313570Sbrandon.potter@amd.com int result = utimes(path.c_str(), hostTimeval); 112413570Sbrandon.potter@amd.com 112513570Sbrandon.potter@amd.com if (result < 0) 112613570Sbrandon.potter@amd.com return -errno; 112713570Sbrandon.potter@amd.com 112813570Sbrandon.potter@amd.com return 0; 112913570Sbrandon.potter@amd.com} 113013570Sbrandon.potter@amd.com/// Target getrusage() function. 113113570Sbrandon.potter@amd.comtemplate <class OS> 113213570Sbrandon.potter@amd.comSyscallReturn 113313570Sbrandon.potter@amd.comgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 113413570Sbrandon.potter@amd.com ThreadContext *tc) 113513570Sbrandon.potter@amd.com{ 113613570Sbrandon.potter@amd.com int index = 0; 113713570Sbrandon.potter@amd.com int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 113813570Sbrandon.potter@amd.com TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 113913570Sbrandon.potter@amd.com 114013570Sbrandon.potter@amd.com rup->ru_utime.tv_sec = 0; 114113570Sbrandon.potter@amd.com rup->ru_utime.tv_usec = 0; 114213570Sbrandon.potter@amd.com rup->ru_stime.tv_sec = 0; 114313570Sbrandon.potter@amd.com rup->ru_stime.tv_usec = 0; 114413570Sbrandon.potter@amd.com rup->ru_maxrss = 0; 114513570Sbrandon.potter@amd.com rup->ru_ixrss = 0; 114613570Sbrandon.potter@amd.com rup->ru_idrss = 0; 114713570Sbrandon.potter@amd.com rup->ru_isrss = 0; 114813570Sbrandon.potter@amd.com rup->ru_minflt = 0; 114913570Sbrandon.potter@amd.com rup->ru_majflt = 0; 115013570Sbrandon.potter@amd.com rup->ru_nswap = 0; 115113570Sbrandon.potter@amd.com rup->ru_inblock = 0; 115213570Sbrandon.potter@amd.com rup->ru_oublock = 0; 115313570Sbrandon.potter@amd.com rup->ru_msgsnd = 0; 115413570Sbrandon.potter@amd.com rup->ru_msgrcv = 0; 115513570Sbrandon.potter@amd.com rup->ru_nsignals = 0; 115613570Sbrandon.potter@amd.com rup->ru_nvcsw = 0; 115713570Sbrandon.potter@amd.com rup->ru_nivcsw = 0; 115813570Sbrandon.potter@amd.com 115913570Sbrandon.potter@amd.com switch (who) { 116013570Sbrandon.potter@amd.com case OS::TGT_RUSAGE_SELF: 116113570Sbrandon.potter@amd.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 116213570Sbrandon.potter@amd.com rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 116313570Sbrandon.potter@amd.com rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 116413570Sbrandon.potter@amd.com break; 116513570Sbrandon.potter@amd.com 116613570Sbrandon.potter@amd.com case OS::TGT_RUSAGE_CHILDREN: 116713570Sbrandon.potter@amd.com // do nothing. We have no child processes, so they take no time. 116813570Sbrandon.potter@amd.com break; 116913570Sbrandon.potter@amd.com 117013570Sbrandon.potter@amd.com default: 117113570Sbrandon.potter@amd.com // don't really handle THREAD or CHILDREN, but just warn and 117213570Sbrandon.potter@amd.com // plow ahead 117313570Sbrandon.potter@amd.com warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 117413570Sbrandon.potter@amd.com who); 117513570Sbrandon.potter@amd.com } 117613570Sbrandon.potter@amd.com 117713570Sbrandon.potter@amd.com rup.copyOut(tc->getMemPort()); 117813570Sbrandon.potter@amd.com 117913570Sbrandon.potter@amd.com return 0; 118013570Sbrandon.potter@amd.com} 118113570Sbrandon.potter@amd.com 118213570Sbrandon.potter@amd.com/// Target times() function. 118313570Sbrandon.potter@amd.comtemplate <class OS> 118413570Sbrandon.potter@amd.comSyscallReturn 118513570Sbrandon.potter@amd.comtimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 118613570Sbrandon.potter@amd.com ThreadContext *tc) 118713570Sbrandon.potter@amd.com{ 118813570Sbrandon.potter@amd.com int index = 0; 118913570Sbrandon.potter@amd.com TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 119013570Sbrandon.potter@amd.com 119113570Sbrandon.potter@amd.com // Fill in the time structure (in clocks) 11921999SN/A int64_t clocks = curTick * OS::M5_SC_CLK_TCK / SimClock::Int::s; 11931999SN/A bufp->tms_utime = clocks; 11941999SN/A bufp->tms_stime = 0; 11951999SN/A bufp->tms_cutime = 0; 119611856Sbrandon.potter@amd.com bufp->tms_cstime = 0; 11971999SN/A 11986701Sgblack@eecs.umich.edu // Convert to host endianness 119911856Sbrandon.potter@amd.com bufp->tms_utime = htog(bufp->tms_utime); 120011856Sbrandon.potter@amd.com 120110931Sbrandon.potter@amd.com // Write back 120211856Sbrandon.potter@amd.com bufp.copyOut(tc->getMemPort()); 120311856Sbrandon.potter@amd.com 12041999SN/A // Return clock ticks since system boot 120511856Sbrandon.potter@amd.com return clocks; 12061999SN/A} 120711856Sbrandon.potter@amd.com 12081999SN/A/// Target time() function. 120911856Sbrandon.potter@amd.comtemplate <class OS> 12101999SN/ASyscallReturn 121111856Sbrandon.potter@amd.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12121999SN/A ThreadContext *tc) 12131999SN/A{ 12145877Shsul@eecs.umich.edu typename OS::time_t sec, usec; 12155877Shsul@eecs.umich.edu getElapsedTime(sec, usec); 12165877Shsul@eecs.umich.edu sec += seconds_since_epoch; 121711851Sbrandon.potter@amd.com 12185877Shsul@eecs.umich.edu int index = 0; 12196701Sgblack@eecs.umich.edu Addr taddr = (Addr)process->getSyscallArg(tc, index); 12206701Sgblack@eecs.umich.edu if(taddr != 0) { 12216701Sgblack@eecs.umich.edu typename OS::time_t t = sec; 12226701Sgblack@eecs.umich.edu t = htog(t); 12236701Sgblack@eecs.umich.edu TranslatingPort *p = tc->getMemPort(); 122410027SChris.Adeniyi-Jones@arm.com p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 122510027SChris.Adeniyi-Jones@arm.com } 122610027SChris.Adeniyi-Jones@arm.com return sec; 122710027SChris.Adeniyi-Jones@arm.com} 122810027SChris.Adeniyi-Jones@arm.com 12295877Shsul@eecs.umich.edu 123010318Sandreas.hansson@arm.com#endif // __SIM_SYSCALL_EMUL_HH__ 123110318Sandreas.hansson@arm.com