syscall_emul.hh revision 2544
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 29360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__ 30360SN/A#define __SIM_SYSCALL_EMUL_HH__ 31360SN/A 32360SN/A#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \ 33360SN/A defined(__FreeBSD__)) 34360SN/A 35360SN/A/// 36360SN/A/// @file syscall_emul.hh 37360SN/A/// 38360SN/A/// This file defines objects used to emulate syscalls from the target 39360SN/A/// application on the host machine. 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.edu#include <errno.h> 422665Ssaidi@eecs.umich.edu#include <string> 43360SN/A#ifdef __CYGWIN32__ 44360SN/A#include <sys/fcntl.h> // for O_BINARY 451354SN/A#endif 461354SN/A#include <sys/uio.h> 47360SN/A 482764Sstever@eecs.umich.edu#include "arch/isa_traits.hh" // for Addr 499202Spalle@lyckegaard.dk#include "base/chunk_generator.hh" 509202Spalle@lyckegaard.dk#include "base/intmath.hh" // for RoundUp 512064SN/A#include "base/misc.hh" 5211799Sbrandon.potter@amd.com#include "base/trace.hh" 5311799Sbrandon.potter@amd.com#include "cpu/base.hh" 5411799Sbrandon.potter@amd.com#include "cpu/exec_context.hh" 5511799Sbrandon.potter@amd.com#include "mem/translating_port.hh" 5611799Sbrandon.potter@amd.com#include "mem/page_table.hh" 5711799Sbrandon.potter@amd.com#include "sim/process.hh" 58360SN/A 59360SN/A/// 60360SN/A/// System call descriptor. 61360SN/A/// 62360SN/Aclass SyscallDesc { 63360SN/A 641809SN/A public: 6511800Sbrandon.potter@amd.com 6611392Sbrandon.potter@amd.com /// Typedef for target syscall handler functions. 671809SN/A typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 6811392Sbrandon.potter@amd.com Process *, ExecContext *); 6911383Sbrandon.potter@amd.com 703113Sgblack@eecs.umich.edu const char *name; //!< Syscall name (e.g., "open"). 7111799Sbrandon.potter@amd.com FuncPtr funcPtr; //!< Pointer to emulation function. 7211759Sbrandon.potter@amd.com int flags; //!< Flags (see Flags enum). 7311812Sbaz21@cam.ac.uk 7411812Sbaz21@cam.ac.uk /// Flag values for controlling syscall behavior. 7511799Sbrandon.potter@amd.com enum Flags { 768229Snate@binkert.org /// Don't set return regs according to funcPtr return value. 778229Snate@binkert.org /// Used for syscalls with non-standard return conventions 7811594Santhony.gutierrez@amd.com /// that explicitly set the ExecContext regs (e.g., 797075Snate@binkert.org /// sigreturn). 808229Snate@binkert.org SuppressReturnValue = 1 8111856Sbrandon.potter@amd.com }; 827075Snate@binkert.org 83360SN/A /// Constructor. 8411886Sbrandon.potter@amd.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 8511800Sbrandon.potter@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 8611392Sbrandon.potter@amd.com { 872462SN/A } 881354SN/A 896216Snate@binkert.org /// Emulate the syscall. Public interface for calling through funcPtr. 906658Snate@binkert.org void doSyscall(int callnum, Process *proc, ExecContext *xc); 912474SN/A}; 922680Sktlim@umich.edu 938229Snate@binkert.org 9411886Sbrandon.potter@amd.comclass BaseBufferArg { 9510496Ssteve.reinhardt@amd.com 968229Snate@binkert.org public: 9711794Sbrandon.potter@amd.com 9811886Sbrandon.potter@amd.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 9910497Ssteve.reinhardt@amd.com { 10011794Sbrandon.potter@amd.com bufPtr = new uint8_t[size]; 101360SN/A // clear out buffer: in case we only partially populate this, 102360SN/A // and then do a copyOut(), we want to make sure we don't 103360SN/A // introduce any random junk into the simulated address space 104360SN/A memset(bufPtr, 0, size); 105360SN/A } 106360SN/A 107360SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 108360SN/A 109360SN/A // 110360SN/A // copy data into simulator space (read from target memory) 111378SN/A // 1121706SN/A virtual bool copyIn(TranslatingPort *memport) 11311851Sbrandon.potter@amd.com { 114378SN/A memport->readBlob(addr, bufPtr, size); 115378SN/A return true; // no EFAULT detection for now 116378SN/A } 117378SN/A 118378SN/A // 1191706SN/A // copy data out of simulator space (write to target memory) 12011851Sbrandon.potter@amd.com // 121360SN/A virtual bool copyOut(TranslatingPort *memport) 12211760Sbrandon.potter@amd.com { 12311760Sbrandon.potter@amd.com memport->writeBlob(addr, bufPtr, size); 12411851Sbrandon.potter@amd.com return true; // no EFAULT detection for now 12511760Sbrandon.potter@amd.com } 1266109Ssanchezd@stanford.edu 1271706SN/A protected: 12811851Sbrandon.potter@amd.com Addr addr; 129378SN/A int size; 1306109Ssanchezd@stanford.edu uint8_t *bufPtr; 1316109Ssanchezd@stanford.edu}; 13211851Sbrandon.potter@amd.com 1336109Ssanchezd@stanford.edu 13411886Sbrandon.potter@amd.comclass BufferArg : public BaseBufferArg 13511886Sbrandon.potter@amd.com{ 13611886Sbrandon.potter@amd.com public: 13711886Sbrandon.potter@amd.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 138378SN/A void *bufferPtr() { return bufPtr; } 1391706SN/A}; 14011851Sbrandon.potter@amd.com 141378SN/Atemplate <class T> 1425748SSteve.Reinhardt@amd.comclass TypedBufferArg : public BaseBufferArg 1435748SSteve.Reinhardt@amd.com{ 14411851Sbrandon.potter@amd.com public: 145378SN/A // user can optionally specify a specific number of bytes to 146378SN/A // allocate to deal with those structs that have variable-size 1471706SN/A // arrays at the end 14811851Sbrandon.potter@amd.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 149378SN/A : BaseBufferArg(_addr, _size) 15011886Sbrandon.potter@amd.com { } 1511706SN/A 15211851Sbrandon.potter@amd.com // type case 153378SN/A operator T*() { return (T *)bufPtr; } 154378SN/A 1551706SN/A // dereference operators 15611851Sbrandon.potter@amd.com T &operator*() { return *((T *)bufPtr); } 157378SN/A T* operator->() { return (T *)bufPtr; } 158378SN/A T &operator[](int i) { return ((T *)bufPtr)[i]; } 1591706SN/A}; 16011851Sbrandon.potter@amd.com 161378SN/A////////////////////////////////////////////////////////////////////// 1624118Sgblack@eecs.umich.edu// 1634118Sgblack@eecs.umich.edu// The following emulation functions are generic enough that they 16411851Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's. They are 1654118Sgblack@eecs.umich.edu// defined in sim/syscall_emul.cc. 166378SN/A// 1671706SN/A////////////////////////////////////////////////////////////////////// 16811851Sbrandon.potter@amd.com 169378SN/A 170378SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1711706SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 17211851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 173360SN/A 1745513SMichael.Adler@intel.com/// Handler for unimplemented syscalls that we never intend to 1755513SMichael.Adler@intel.com/// implement (signal handling, etc.) and should not affect the correct 17611851Sbrandon.potter@amd.com/// behavior of the program. Print a warning only if the appropriate 1775513SMichael.Adler@intel.com/// trace flag is enabled. Return success to the target program. 17810203SAli.Saidi@ARM.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 17910203SAli.Saidi@ARM.com Process *p, ExecContext *xc); 18011851Sbrandon.potter@amd.com 18110203SAli.Saidi@ARM.com/// Target exit() handler: terminate simulation. 1825513SMichael.Adler@intel.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 18311851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 1845513SMichael.Adler@intel.com 185511SN/A/// Target getpagesize() handler. 18610633Smichaelupton@gmail.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 18711851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 18810633Smichaelupton@gmail.com 1891706SN/A/// Target obreak() handler: set brk address. 19011851Sbrandon.potter@amd.comSyscallReturn obreakFunc(SyscallDesc *desc, int num, 191511SN/A Process *p, ExecContext *xc); 1925513SMichael.Adler@intel.com 1935513SMichael.Adler@intel.com/// Target close() handler. 19411851Sbrandon.potter@amd.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 1955513SMichael.Adler@intel.com Process *p, ExecContext *xc); 196511SN/A 1971706SN/A/// Target read() handler. 19811851Sbrandon.potter@amd.comSyscallReturn readFunc(SyscallDesc *desc, int num, 1991706SN/A Process *p, ExecContext *xc); 2001706SN/A 2011706SN/A/// Target write() handler. 2021706SN/ASyscallReturn writeFunc(SyscallDesc *desc, int num, 20311851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2041706SN/A 2051706SN/A/// Target lseek() handler. 2061706SN/ASyscallReturn lseekFunc(SyscallDesc *desc, int num, 2071706SN/A Process *p, ExecContext *xc); 20811851Sbrandon.potter@amd.com 2091706SN/A/// Target munmap() handler. 210511SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num, 2116703Svince@csl.cornell.edu Process *p, ExecContext *xc); 2126703Svince@csl.cornell.edu 21311851Sbrandon.potter@amd.com/// Target gethostname() handler. 2146703Svince@csl.cornell.eduSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2156685Stjones1@inf.ed.ac.uk Process *p, ExecContext *xc); 2166685Stjones1@inf.ed.ac.uk 21711851Sbrandon.potter@amd.com/// Target unlink() handler. 2186685Stjones1@inf.ed.ac.ukSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2196685Stjones1@inf.ed.ac.uk Process *p, ExecContext *xc); 2205513SMichael.Adler@intel.com 2215513SMichael.Adler@intel.com/// Target rename() handler. 22211851Sbrandon.potter@amd.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 2235513SMichael.Adler@intel.com Process *p, ExecContext *xc); 22411885Sbrandon.potter@amd.com 22511885Sbrandon.potter@amd.com 22611885Sbrandon.potter@amd.com/// Target truncate() handler. 2275513SMichael.Adler@intel.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 2281999SN/A Process *p, ExecContext *xc); 2291999SN/A 23011851Sbrandon.potter@amd.com 2311999SN/A/// Target ftruncate() handler. 23211885Sbrandon.potter@amd.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 23311885Sbrandon.potter@amd.com Process *p, ExecContext *xc); 23411885Sbrandon.potter@amd.com 2351999SN/A 2361999SN/A/// Target chown() handler. 2371999SN/ASyscallReturn chownFunc(SyscallDesc *desc, int num, 23811851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2391999SN/A 2403079Sstever@eecs.umich.edu 2413079Sstever@eecs.umich.edu/// Target fchown() handler. 24211851Sbrandon.potter@amd.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2433079Sstever@eecs.umich.edu Process *p, ExecContext *xc); 24411875Sbrandon.potter@amd.com 2452093SN/A/// Target fnctl() handler. 24611851Sbrandon.potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2472093SN/A Process *process, ExecContext *xc); 2482687Sksewell@umich.edu 2492687Sksewell@umich.edu/// Target setuid() handler. 25011851Sbrandon.potter@amd.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2512687Sksewell@umich.edu Process *p, ExecContext *xc); 2522238SN/A 2532238SN/A/// Target getpid() handler. 25411851Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 2552238SN/A Process *p, ExecContext *xc); 2562238SN/A 2572238SN/A/// Target getuid() handler. 25811851Sbrandon.potter@amd.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 2592238SN/A Process *p, ExecContext *xc); 2602238SN/A 2612238SN/A/// Target getgid() handler. 26211851Sbrandon.potter@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 2632238SN/A Process *p, ExecContext *xc); 2642238SN/A 2652238SN/A/// Target getppid() handler. 26611851Sbrandon.potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 2672238SN/A Process *p, ExecContext *xc); 2682238SN/A 2692238SN/A/// Target geteuid() handler. 27011851Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 2712238SN/A Process *p, ExecContext *xc); 2722238SN/A 2732238SN/A/// Target getegid() handler. 27411851Sbrandon.potter@amd.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 2752238SN/A Process *p, ExecContext *xc); 2762238SN/A 2772238SN/A 27811851Sbrandon.potter@amd.com 2792238SN/A/// Pseudo Funcs - These functions use a different return convension, 2809455Smitch.hayenga+gem5@gmail.com/// returning a second value in a register other than the normal return register 2819455Smitch.hayenga+gem5@gmail.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 28211851Sbrandon.potter@amd.com Process *process, ExecContext *xc); 28310203SAli.Saidi@ARM.com 28411851Sbrandon.potter@amd.com/// Target getpidPseudo() handler. 28511851Sbrandon.potter@amd.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 2869455Smitch.hayenga+gem5@gmail.com Process *p, ExecContext *xc); 2879112Smarc.orr@gmail.com 2889112Smarc.orr@gmail.com/// Target getuidPseudo() handler. 2899112Smarc.orr@gmail.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 2909112Smarc.orr@gmail.com Process *p, ExecContext *xc); 2919112Smarc.orr@gmail.com 29211851Sbrandon.potter@amd.com/// Target getgidPseudo() handler. 2939112Smarc.orr@gmail.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 2949112Smarc.orr@gmail.com Process *p, ExecContext *xc); 2959112Smarc.orr@gmail.com 2969112Smarc.orr@gmail.com 2979112Smarc.orr@gmail.com/// This struct is used to build an target-OS-dependent table that 2989112Smarc.orr@gmail.com/// maps the target's open() flags to the host open() flags. 2999112Smarc.orr@gmail.comstruct OpenFlagTransTable { 3009112Smarc.orr@gmail.com int tgtFlag; //!< Target system flag value. 3019112Smarc.orr@gmail.com int hostFlag; //!< Corresponding host system flag value. 3029112Smarc.orr@gmail.com}; 3039112Smarc.orr@gmail.com 3049112Smarc.orr@gmail.com 3059112Smarc.orr@gmail.com 3069112Smarc.orr@gmail.com/// A readable name for 1,000,000, for converting microseconds to seconds. 3079112Smarc.orr@gmail.comconst int one_million = 1000000; 30811886Sbrandon.potter@amd.com 3099112Smarc.orr@gmail.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 3109112Smarc.orr@gmail.com/// by my reckoning. We want to keep this a constant (not use the 3119238Slluc.alvarez@bsc.es/// real-world time) to keep simulations repeatable. 3129112Smarc.orr@gmail.comconst unsigned seconds_since_epoch = 1000000000; 3139112Smarc.orr@gmail.com 3149112Smarc.orr@gmail.com/// Helper function to convert current elapsed time to seconds and 31511886Sbrandon.potter@amd.com/// microseconds. 3169112Smarc.orr@gmail.comtemplate <class T1, class T2> 3179112Smarc.orr@gmail.comvoid 3189112Smarc.orr@gmail.comgetElapsedTime(T1 &sec, T2 &usec) 3199112Smarc.orr@gmail.com{ 3209112Smarc.orr@gmail.com int elapsed_usecs = curTick / Clock::Int::us; 3219112Smarc.orr@gmail.com sec = elapsed_usecs / one_million; 32211367Sandreas.hansson@arm.com usec = elapsed_usecs % one_million; 3239112Smarc.orr@gmail.com} 32411321Ssteve.reinhardt@amd.com 32511886Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 3269112Smarc.orr@gmail.com// 3279112Smarc.orr@gmail.com// The following emulation functions are generic, but need to be 3289112Smarc.orr@gmail.com// templated to account for differences in types, constants, etc. 3299112Smarc.orr@gmail.com// 3309112Smarc.orr@gmail.com////////////////////////////////////////////////////////////////////// 3319112Smarc.orr@gmail.com 3329112Smarc.orr@gmail.com/// Target ioctl() handler. For the most part, programs call ioctl() 3339112Smarc.orr@gmail.com/// only to find out if their stdout is a tty, to determine whether to 3349112Smarc.orr@gmail.com/// do line or block buffering. 3359112Smarc.orr@gmail.comtemplate <class OS> 3369112Smarc.orr@gmail.comSyscallReturn 3379112Smarc.orr@gmail.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 3389112Smarc.orr@gmail.com ExecContext *xc) 3399112Smarc.orr@gmail.com{ 34011886Sbrandon.potter@amd.com int fd = xc->getSyscallArg(0); 34111886Sbrandon.potter@amd.com unsigned req = xc->getSyscallArg(1); 3429112Smarc.orr@gmail.com 3439112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 3449112Smarc.orr@gmail.com 3459112Smarc.orr@gmail.com if (fd < 0 || process->sim_fd(fd) < 0) { 3469112Smarc.orr@gmail.com // doesn't map to any simulator fd: not a valid target fd 3479112Smarc.orr@gmail.com return -EBADF; 3489112Smarc.orr@gmail.com } 3499112Smarc.orr@gmail.com 3509112Smarc.orr@gmail.com switch (req) { 3519112Smarc.orr@gmail.com case OS::TIOCISATTY: 3529112Smarc.orr@gmail.com case OS::TIOCGETP: 3539112Smarc.orr@gmail.com case OS::TIOCSETP: 35411321Ssteve.reinhardt@amd.com case OS::TIOCSETN: 3559112Smarc.orr@gmail.com case OS::TIOCSETC: 3569112Smarc.orr@gmail.com case OS::TIOCGETC: 3579112Smarc.orr@gmail.com case OS::TIOCGETS: 3589112Smarc.orr@gmail.com case OS::TIOCGETA: 35911886Sbrandon.potter@amd.com return -ENOTTY; 36011886Sbrandon.potter@amd.com 36111886Sbrandon.potter@amd.com default: 3629112Smarc.orr@gmail.com fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 3639112Smarc.orr@gmail.com fd, req, xc->readPC()); 36411886Sbrandon.potter@amd.com } 3659112Smarc.orr@gmail.com} 3669112Smarc.orr@gmail.com 3679112Smarc.orr@gmail.com/// Target open() handler. 3689112Smarc.orr@gmail.comtemplate <class OS> 3699112Smarc.orr@gmail.comSyscallReturn 3702238SN/AopenFunc(SyscallDesc *desc, int callnum, Process *process, 3712238SN/A ExecContext *xc) 3722238SN/A{ 3732238SN/A std::string path; 37411851Sbrandon.potter@amd.com 3752238SN/A if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 3762238SN/A return -EFAULT; 3772238SN/A 37811851Sbrandon.potter@amd.com if (path == "/dev/sysdev0") { 3792238SN/A // This is a memory-mapped high-resolution timer device on Alpha. 3802238SN/A // We don't support it, so just punt. 3812238SN/A warn("Ignoring open(%s, ...)\n", path); 38211851Sbrandon.potter@amd.com return -ENOENT; 3832238SN/A } 3842238SN/A 3852238SN/A int tgtFlags = xc->getSyscallArg(1); 38611851Sbrandon.potter@amd.com int mode = xc->getSyscallArg(2); 3872238SN/A int hostFlags = 0; 3882238SN/A 3891354SN/A // translate open flags 3901354SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 39110796Sbrandon.potter@amd.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 39210796Sbrandon.potter@amd.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 3931354SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 3941354SN/A } 3951354SN/A } 3961354SN/A 3971354SN/A // any target flags left? 3981354SN/A if (tgtFlags != 0) 3991354SN/A warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 4001354SN/A 4011354SN/A#ifdef __CYGWIN32__ 4021354SN/A hostFlags |= O_BINARY; 40310796Sbrandon.potter@amd.com#endif 4041354SN/A 40510796Sbrandon.potter@amd.com DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 4061354SN/A 4071354SN/A // open the file 4081354SN/A int fd = open(path.c_str(), hostFlags, mode); 4091354SN/A 41010796Sbrandon.potter@amd.com return (fd == -1) ? -errno : process->alloc_fd(fd); 41110796Sbrandon.potter@amd.com} 41210796Sbrandon.potter@amd.com 41310796Sbrandon.potter@amd.com 41410796Sbrandon.potter@amd.com/// Target chmod() handler. 41510796Sbrandon.potter@amd.comtemplate <class OS> 41610796Sbrandon.potter@amd.comSyscallReturn 41710796Sbrandon.potter@amd.comchmodFunc(SyscallDesc *desc, int callnum, Process *process, 41810796Sbrandon.potter@amd.com ExecContext *xc) 41910796Sbrandon.potter@amd.com{ 42010796Sbrandon.potter@amd.com std::string path; 421360SN/A 422360SN/A if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 423360SN/A return -EFAULT; 424360SN/A 425360SN/A uint32_t mode = xc->getSyscallArg(1); 426360SN/A mode_t hostMode = 0; 427360SN/A 42811759Sbrandon.potter@amd.com // XXX translate mode flags via OS::something??? 4293113Sgblack@eecs.umich.edu hostMode = mode; 4303113Sgblack@eecs.umich.edu 4313113Sgblack@eecs.umich.edu // do the chmod 4323113Sgblack@eecs.umich.edu int result = chmod(path.c_str(), hostMode); 4333113Sgblack@eecs.umich.edu if (result < 0) 4343113Sgblack@eecs.umich.edu return -errno; 4353113Sgblack@eecs.umich.edu 4363113Sgblack@eecs.umich.edu return 0; 4373113Sgblack@eecs.umich.edu} 4383113Sgblack@eecs.umich.edu 4393113Sgblack@eecs.umich.edu 4403113Sgblack@eecs.umich.edu/// Target fchmod() handler. 4413113Sgblack@eecs.umich.edutemplate <class OS> 4423113Sgblack@eecs.umich.eduSyscallReturn 4433113Sgblack@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, Process *process, 4443113Sgblack@eecs.umich.edu ExecContext *xc) 4454189Sgblack@eecs.umich.edu{ 4464189Sgblack@eecs.umich.edu int fd = xc->getSyscallArg(0); 4473113Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 4483113Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 4493113Sgblack@eecs.umich.edu return -EBADF; 4503113Sgblack@eecs.umich.edu } 4518737Skoansin.tan@gmail.com 4523113Sgblack@eecs.umich.edu uint32_t mode = xc->getSyscallArg(1); 4538737Skoansin.tan@gmail.com mode_t hostMode = 0; 4543277Sgblack@eecs.umich.edu 4555515SMichael.Adler@intel.com // XXX translate mode flags via OS::someting??? 4565515SMichael.Adler@intel.com hostMode = mode; 4575515SMichael.Adler@intel.com 4585515SMichael.Adler@intel.com // do the fchmod 4595515SMichael.Adler@intel.com int result = fchmod(process->sim_fd(fd), hostMode); 4608737Skoansin.tan@gmail.com if (result < 0) 4613277Sgblack@eecs.umich.edu return -errno; 4628737Skoansin.tan@gmail.com 4633277Sgblack@eecs.umich.edu return 0; 4648737Skoansin.tan@gmail.com} 4653277Sgblack@eecs.umich.edu 4668737Skoansin.tan@gmail.com 4673113Sgblack@eecs.umich.edu/// Target stat() handler. 4683113Sgblack@eecs.umich.edutemplate <class OS> 4693113Sgblack@eecs.umich.eduSyscallReturn 4703113Sgblack@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, Process *process, 4718737Skoansin.tan@gmail.com ExecContext *xc) 4723113Sgblack@eecs.umich.edu{ 4738737Skoansin.tan@gmail.com std::string path; 4743114Sgblack@eecs.umich.edu 4758737Skoansin.tan@gmail.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 4763114Sgblack@eecs.umich.edu return -EFAULT; 4778737Skoansin.tan@gmail.com 4783114Sgblack@eecs.umich.edu struct stat hostBuf; 4798737Skoansin.tan@gmail.com int result = stat(path.c_str(), &hostBuf); 4804061Sgblack@eecs.umich.edu 4814061Sgblack@eecs.umich.edu if (result < 0) 4824061Sgblack@eecs.umich.edu return -errno; 4838737Skoansin.tan@gmail.com 4843113Sgblack@eecs.umich.edu OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 4858737Skoansin.tan@gmail.com 4863113Sgblack@eecs.umich.edu return 0; 4873113Sgblack@eecs.umich.edu} 4883113Sgblack@eecs.umich.edu 4893113Sgblack@eecs.umich.edu 4903113Sgblack@eecs.umich.edu/// Target fstat64() handler. 4913113Sgblack@eecs.umich.edutemplate <class OS> 4923113Sgblack@eecs.umich.eduSyscallReturn 4933113Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, Process *process, 4944189Sgblack@eecs.umich.edu ExecContext *xc) 4954189Sgblack@eecs.umich.edu{ 4963113Sgblack@eecs.umich.edu int fd = xc->getSyscallArg(0); 4973113Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 4983113Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 4998737Skoansin.tan@gmail.com return -EBADF; 5003113Sgblack@eecs.umich.edu } 5018737Skoansin.tan@gmail.com 5023113Sgblack@eecs.umich.edu#if BSD_HOST 5038737Skoansin.tan@gmail.com struct stat hostBuf; 5043113Sgblack@eecs.umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 5053113Sgblack@eecs.umich.edu#else 5063113Sgblack@eecs.umich.edu struct stat64 hostBuf; 5073113Sgblack@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 5083113Sgblack@eecs.umich.edu#endif 5093113Sgblack@eecs.umich.edu 5103113Sgblack@eecs.umich.edu if (result < 0) 5113113Sgblack@eecs.umich.edu return -errno; 5123113Sgblack@eecs.umich.edu 5133113Sgblack@eecs.umich.edu OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf); 5148852Sandreas.hansson@arm.com 5153113Sgblack@eecs.umich.edu return 0; 5163113Sgblack@eecs.umich.edu} 5173113Sgblack@eecs.umich.edu 5183113Sgblack@eecs.umich.edu 5193113Sgblack@eecs.umich.edu/// Target lstat() handler. 5203113Sgblack@eecs.umich.edutemplate <class OS> 5213113Sgblack@eecs.umich.eduSyscallReturn 5223113Sgblack@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, Process *process, 5233113Sgblack@eecs.umich.edu ExecContext *xc) 5243113Sgblack@eecs.umich.edu{ 5258852Sandreas.hansson@arm.com std::string path; 5263113Sgblack@eecs.umich.edu 5273113Sgblack@eecs.umich.edu if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 5283113Sgblack@eecs.umich.edu return -EFAULT; 5293113Sgblack@eecs.umich.edu 5306686Stjones1@inf.ed.ac.uk struct stat hostBuf; 5313113Sgblack@eecs.umich.edu int result = lstat(path.c_str(), &hostBuf); 5323113Sgblack@eecs.umich.edu 5333113Sgblack@eecs.umich.edu if (result < 0) 53411759Sbrandon.potter@amd.com return -errno; 53511759Sbrandon.potter@amd.com 53611759Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 53711759Sbrandon.potter@amd.com 53811759Sbrandon.potter@amd.com return 0; 53911759Sbrandon.potter@amd.com} 54011759Sbrandon.potter@amd.com 54111812Sbaz21@cam.ac.uk/// Target lstat64() handler. 54211812Sbaz21@cam.ac.uktemplate <class OS> 54311812Sbaz21@cam.ac.ukSyscallReturn 54411759Sbrandon.potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, Process *process, 54511812Sbaz21@cam.ac.uk ExecContext *xc) 54611759Sbrandon.potter@amd.com{ 54711759Sbrandon.potter@amd.com std::string path; 54811759Sbrandon.potter@amd.com 54911759Sbrandon.potter@amd.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 55011759Sbrandon.potter@amd.com return -EFAULT; 55111759Sbrandon.potter@amd.com 55211759Sbrandon.potter@amd.com#if BSD_HOST 55311812Sbaz21@cam.ac.uk struct stat hostBuf; 55411812Sbaz21@cam.ac.uk int result = lstat(path.c_str(), &hostBuf); 55511812Sbaz21@cam.ac.uk#else 55611812Sbaz21@cam.ac.uk struct stat64 hostBuf; 55711812Sbaz21@cam.ac.uk int result = lstat64(path.c_str(), &hostBuf); 55811812Sbaz21@cam.ac.uk#endif 55911812Sbaz21@cam.ac.uk 56011759Sbrandon.potter@amd.com if (result < 0) 56111759Sbrandon.potter@amd.com return -errno; 56211812Sbaz21@cam.ac.uk 56311812Sbaz21@cam.ac.uk OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf); 56411759Sbrandon.potter@amd.com 56511812Sbaz21@cam.ac.uk return 0; 56611812Sbaz21@cam.ac.uk} 56711812Sbaz21@cam.ac.uk 56811812Sbaz21@cam.ac.uk/// Target fstat() handler. 56911812Sbaz21@cam.ac.uktemplate <class OS> 57011812Sbaz21@cam.ac.ukSyscallReturn 57111812Sbaz21@cam.ac.ukfstatFunc(SyscallDesc *desc, int callnum, Process *process, 57211759Sbrandon.potter@amd.com ExecContext *xc) 57311759Sbrandon.potter@amd.com{ 57411759Sbrandon.potter@amd.com int fd = process->sim_fd(xc->getSyscallArg(0)); 57511759Sbrandon.potter@amd.com 576378SN/A DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 577378SN/A 5789141Smarc.orr@gmail.com if (fd < 0) 5799141Smarc.orr@gmail.com return -EBADF; 580360SN/A 5811450SN/A struct stat hostBuf; 58211856Sbrandon.potter@amd.com int result = fstat(fd, &hostBuf); 583360SN/A 5846701Sgblack@eecs.umich.edu if (result < 0) 58511856Sbrandon.potter@amd.com return -errno; 58611856Sbrandon.potter@amd.com 587360SN/A OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 58810930Sbrandon.potter@amd.com 589360SN/A return 0; 59011856Sbrandon.potter@amd.com} 59111856Sbrandon.potter@amd.com 59210496Ssteve.reinhardt@amd.com 59311856Sbrandon.potter@amd.com/// Target statfs() handler. 59411856Sbrandon.potter@amd.comtemplate <class OS> 5951458SN/ASyscallReturn 596360SN/AstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 59711856Sbrandon.potter@amd.com ExecContext *xc) 59811856Sbrandon.potter@amd.com{ 59911856Sbrandon.potter@amd.com std::string path; 60011856Sbrandon.potter@amd.com 60111856Sbrandon.potter@amd.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 60211856Sbrandon.potter@amd.com return -EFAULT; 60311856Sbrandon.potter@amd.com 60411856Sbrandon.potter@amd.com struct statfs hostBuf; 60510496Ssteve.reinhardt@amd.com int result = statfs(path.c_str(), &hostBuf); 60611856Sbrandon.potter@amd.com 60711856Sbrandon.potter@amd.com if (result < 0) 60811856Sbrandon.potter@amd.com return -errno; 60911856Sbrandon.potter@amd.com 61011856Sbrandon.potter@amd.com OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 61110930Sbrandon.potter@amd.com 6129141Smarc.orr@gmail.com return 0; 613360SN/A} 614360SN/A 615360SN/A 61610027SChris.Adeniyi-Jones@arm.com/// Target fstatfs() handler. 61711851Sbrandon.potter@amd.comtemplate <class OS> 61810027SChris.Adeniyi-Jones@arm.comSyscallReturn 619360SN/AfstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 620360SN/A ExecContext *xc) 621360SN/A{ 6228852Sandreas.hansson@arm.com int fd = process->sim_fd(xc->getSyscallArg(0)); 6236701Sgblack@eecs.umich.edu 6241458SN/A if (fd < 0) 625360SN/A return -EBADF; 6266701Sgblack@eecs.umich.edu 6276701Sgblack@eecs.umich.edu struct statfs hostBuf; 628360SN/A int result = fstatfs(fd, &hostBuf); 629360SN/A 630360SN/A if (result < 0) 631360SN/A return -errno; 632360SN/A 633360SN/A OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 634360SN/A 635360SN/A return 0; 636360SN/A} 637360SN/A 638360SN/A 639360SN/A/// Target writev() handler. 6401706SN/Atemplate <class OS> 641360SN/ASyscallReturn 642360SN/AwritevFunc(SyscallDesc *desc, int callnum, Process *process, 643360SN/A ExecContext *xc) 644360SN/A{ 645360SN/A int fd = xc->getSyscallArg(0); 6463669Sbinkertn@umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 6473669Sbinkertn@umich.edu // doesn't map to any simulator fd: not a valid target fd 6483669Sbinkertn@umich.edu return -EBADF; 6491706SN/A } 6501706SN/A 65110496Ssteve.reinhardt@amd.com TranslatingPort *p = xc->getMemPort(); 65210496Ssteve.reinhardt@amd.com uint64_t tiov_base = xc->getSyscallArg(1); 65310496Ssteve.reinhardt@amd.com size_t count = xc->getSyscallArg(2); 65410496Ssteve.reinhardt@amd.com struct iovec hiov[count]; 65510496Ssteve.reinhardt@amd.com for (int i = 0; i < count; ++i) 65610496Ssteve.reinhardt@amd.com { 65710496Ssteve.reinhardt@amd.com typename OS::tgt_iovec tiov; 65810496Ssteve.reinhardt@amd.com 65910496Ssteve.reinhardt@amd.com p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 66010496Ssteve.reinhardt@amd.com (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 66111856Sbrandon.potter@amd.com hiov[i].iov_len = gtoh(tiov.iov_len); 66210496Ssteve.reinhardt@amd.com hiov[i].iov_base = new char [hiov[i].iov_len]; 66310496Ssteve.reinhardt@amd.com p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 66410496Ssteve.reinhardt@amd.com hiov[i].iov_len); 66510496Ssteve.reinhardt@amd.com } 66610496Ssteve.reinhardt@amd.com 66710496Ssteve.reinhardt@amd.com int result = writev(process->sim_fd(fd), hiov, count); 66810496Ssteve.reinhardt@amd.com 66910496Ssteve.reinhardt@amd.com for (int i = 0; i < count; ++i) 67010496Ssteve.reinhardt@amd.com { 6715795Ssaidi@eecs.umich.edu delete [] (char *)hiov[i].iov_base; 6729143Ssteve.reinhardt@amd.com } 6739142Ssteve.reinhardt@amd.com 6749142Ssteve.reinhardt@amd.com if (result < 0) 6759143Ssteve.reinhardt@amd.com return -errno; 6765795Ssaidi@eecs.umich.edu 6779143Ssteve.reinhardt@amd.com return 0; 6785795Ssaidi@eecs.umich.edu} 6795795Ssaidi@eecs.umich.edu 6805795Ssaidi@eecs.umich.edu 6819143Ssteve.reinhardt@amd.com/// Target mmap() handler. 6825795Ssaidi@eecs.umich.edu/// 683360SN/A/// We don't really handle mmap(). If the target is mmaping an 6849143Ssteve.reinhardt@amd.com/// anonymous region or /dev/zero, we can get away with doing basically 6859143Ssteve.reinhardt@amd.com/// nothing (since memory is initialized to zero and the simulator 6869143Ssteve.reinhardt@amd.com/// doesn't really check addresses anyway). Always print a warning, 68711856Sbrandon.potter@amd.com/// since this could be seriously broken if we're not mapping 68811856Sbrandon.potter@amd.com/// /dev/zero. 68911856Sbrandon.potter@amd.com// 690360SN/A/// Someday we should explicitly check for /dev/zero in open, flag the 691360SN/A/// file descriptor, and fail (or implement!) a non-anonymous mmap to 69210027SChris.Adeniyi-Jones@arm.com/// anything else. 69310027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 69410027SChris.Adeniyi-Jones@arm.comSyscallReturn 69511851Sbrandon.potter@amd.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 69610027SChris.Adeniyi-Jones@arm.com{ 69710027SChris.Adeniyi-Jones@arm.com Addr start = xc->getSyscallArg(0); 69810027SChris.Adeniyi-Jones@arm.com uint64_t length = xc->getSyscallArg(1); 69910027SChris.Adeniyi-Jones@arm.com // int prot = xc->getSyscallArg(2); 70010027SChris.Adeniyi-Jones@arm.com int flags = xc->getSyscallArg(3); 70110027SChris.Adeniyi-Jones@arm.com // int fd = p->sim_fd(xc->getSyscallArg(4)); 70210027SChris.Adeniyi-Jones@arm.com // int offset = xc->getSyscallArg(5); 70310027SChris.Adeniyi-Jones@arm.com 70411851Sbrandon.potter@amd.com if ((start % TheISA::VMPageSize) != 0 || 70511851Sbrandon.potter@amd.com (length % TheISA::VMPageSize) != 0) { 70610027SChris.Adeniyi-Jones@arm.com warn("mmap failing: arguments not page-aligned: " 70710027SChris.Adeniyi-Jones@arm.com "start 0x%x length 0x%x", 70810027SChris.Adeniyi-Jones@arm.com start, length); 70910027SChris.Adeniyi-Jones@arm.com return -EINVAL; 71010027SChris.Adeniyi-Jones@arm.com } 71110027SChris.Adeniyi-Jones@arm.com 71210027SChris.Adeniyi-Jones@arm.com if (start != 0) { 71310027SChris.Adeniyi-Jones@arm.com warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 71410633Smichaelupton@gmail.com start, p->mmap_end); 71510633Smichaelupton@gmail.com } 71610633Smichaelupton@gmail.com 71711851Sbrandon.potter@amd.com // pick next address from our "mmap region" 71810633Smichaelupton@gmail.com start = p->mmap_end; 71910633Smichaelupton@gmail.com p->pTable->allocate(start, length); 72010633Smichaelupton@gmail.com p->mmap_end += length; 72110633Smichaelupton@gmail.com 72210633Smichaelupton@gmail.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 72310633Smichaelupton@gmail.com warn("allowing mmap of file @ fd %d. " 72410633Smichaelupton@gmail.com "This will break if not /dev/zero.", xc->getSyscallArg(4)); 72510633Smichaelupton@gmail.com } 72610633Smichaelupton@gmail.com 72710633Smichaelupton@gmail.com return start; 72810203SAli.Saidi@ARM.com} 72910203SAli.Saidi@ARM.com 73010203SAli.Saidi@ARM.com/// Target getrlimit() handler. 73111851Sbrandon.potter@amd.comtemplate <class OS> 73211851Sbrandon.potter@amd.comSyscallReturn 73310203SAli.Saidi@ARM.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 73410203SAli.Saidi@ARM.com ExecContext *xc) 73510203SAli.Saidi@ARM.com{ 73610203SAli.Saidi@ARM.com unsigned resource = xc->getSyscallArg(0); 73710203SAli.Saidi@ARM.com TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 73810203SAli.Saidi@ARM.com 73910203SAli.Saidi@ARM.com switch (resource) { 74010203SAli.Saidi@ARM.com case OS::TGT_RLIMIT_STACK: 74110203SAli.Saidi@ARM.com // max stack size in bytes: make up a number (2MB for now) 74210203SAli.Saidi@ARM.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 74310203SAli.Saidi@ARM.com rlp->rlim_cur = htog(rlp->rlim_cur); 74411851Sbrandon.potter@amd.com rlp->rlim_max = htog(rlp->rlim_max); 74511851Sbrandon.potter@amd.com break; 74610203SAli.Saidi@ARM.com 74710203SAli.Saidi@ARM.com default: 74810203SAli.Saidi@ARM.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 74910203SAli.Saidi@ARM.com << std::endl; 75010203SAli.Saidi@ARM.com abort(); 75110203SAli.Saidi@ARM.com break; 75210203SAli.Saidi@ARM.com } 75310203SAli.Saidi@ARM.com 75410850SGiacomo.Gabrielli@arm.com rlp.copyOut(xc->getMemPort()); 75510850SGiacomo.Gabrielli@arm.com return 0; 75610850SGiacomo.Gabrielli@arm.com} 75711851Sbrandon.potter@amd.com 75810850SGiacomo.Gabrielli@arm.com/// Target gettimeofday() handler. 75910850SGiacomo.Gabrielli@arm.comtemplate <class OS> 76010850SGiacomo.Gabrielli@arm.comSyscallReturn 76110850SGiacomo.Gabrielli@arm.comgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 76210850SGiacomo.Gabrielli@arm.com ExecContext *xc) 76310850SGiacomo.Gabrielli@arm.com{ 76410850SGiacomo.Gabrielli@arm.com TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 76510850SGiacomo.Gabrielli@arm.com 76610850SGiacomo.Gabrielli@arm.com getElapsedTime(tp->tv_sec, tp->tv_usec); 76710850SGiacomo.Gabrielli@arm.com tp->tv_sec += seconds_since_epoch; 76810850SGiacomo.Gabrielli@arm.com tp->tv_sec = htog(tp->tv_sec); 76910850SGiacomo.Gabrielli@arm.com tp->tv_usec = htog(tp->tv_usec); 77010850SGiacomo.Gabrielli@arm.com 77110850SGiacomo.Gabrielli@arm.com tp.copyOut(xc->getMemPort()); 77210850SGiacomo.Gabrielli@arm.com 77310850SGiacomo.Gabrielli@arm.com return 0; 77410850SGiacomo.Gabrielli@arm.com} 77510850SGiacomo.Gabrielli@arm.com 77610850SGiacomo.Gabrielli@arm.com 77710850SGiacomo.Gabrielli@arm.com/// Target utimes() handler. 77810850SGiacomo.Gabrielli@arm.comtemplate <class OS> 77910850SGiacomo.Gabrielli@arm.comSyscallReturn 78010850SGiacomo.Gabrielli@arm.comutimesFunc(SyscallDesc *desc, int callnum, Process *process, 78110850SGiacomo.Gabrielli@arm.com ExecContext *xc) 78210850SGiacomo.Gabrielli@arm.com{ 78310850SGiacomo.Gabrielli@arm.com std::string path; 78410850SGiacomo.Gabrielli@arm.com 78510850SGiacomo.Gabrielli@arm.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 78610850SGiacomo.Gabrielli@arm.com return -EFAULT; 78710850SGiacomo.Gabrielli@arm.com 78810850SGiacomo.Gabrielli@arm.com TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); 78910850SGiacomo.Gabrielli@arm.com tp.copyIn(xc->getMemPort()); 7906640Svince@csl.cornell.edu 7916640Svince@csl.cornell.edu struct timeval hostTimeval[2]; 7926640Svince@csl.cornell.edu for (int i = 0; i < 2; ++i) 79311851Sbrandon.potter@amd.com { 79411851Sbrandon.potter@amd.com hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 7956640Svince@csl.cornell.edu hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 7966640Svince@csl.cornell.edu } 7976701Sgblack@eecs.umich.edu int result = utimes(path.c_str(), hostTimeval); 7986701Sgblack@eecs.umich.edu 79910793Sbrandon.potter@amd.com if (result < 0) 8006640Svince@csl.cornell.edu return -errno; 80111758Sbrandon.potter@amd.com 80211758Sbrandon.potter@amd.com return 0; 80311758Sbrandon.potter@amd.com} 8046640Svince@csl.cornell.edu/// Target getrusage() function. 8058706Sandreas.hansson@arm.comtemplate <class OS> 8066640Svince@csl.cornell.eduSyscallReturn 8076701Sgblack@eecs.umich.edugetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 8086640Svince@csl.cornell.edu ExecContext *xc) 809360SN/A{ 8101999SN/A int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 8111999SN/A TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 8121999SN/A 81311851Sbrandon.potter@amd.com if (who != OS::TGT_RUSAGE_SELF) { 8142680Sktlim@umich.edu // don't really handle THREAD or CHILDREN, but just warn and 8151999SN/A // plow ahead 8161999SN/A warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 8171999SN/A who); 8186701Sgblack@eecs.umich.edu } 8198852Sandreas.hansson@arm.com 8206701Sgblack@eecs.umich.edu getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 8211999SN/A rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 8226701Sgblack@eecs.umich.edu rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 8231999SN/A 8246701Sgblack@eecs.umich.edu rup->ru_stime.tv_sec = 0; 8251999SN/A rup->ru_stime.tv_usec = 0; 8261999SN/A rup->ru_maxrss = 0; 8271999SN/A rup->ru_ixrss = 0; 8281999SN/A rup->ru_idrss = 0; 8291999SN/A rup->ru_isrss = 0; 8303669Sbinkertn@umich.edu rup->ru_minflt = 0; 8313669Sbinkertn@umich.edu rup->ru_majflt = 0; 8323669Sbinkertn@umich.edu rup->ru_nswap = 0; 8331999SN/A rup->ru_inblock = 0; 8341999SN/A rup->ru_oublock = 0; 8351999SN/A rup->ru_msgsnd = 0; 8362218SN/A rup->ru_msgrcv = 0; 8371999SN/A rup->ru_nsignals = 0; 8381999SN/A rup->ru_nvcsw = 0; 8391999SN/A rup->ru_nivcsw = 0; 8401999SN/A 8411999SN/A rup.copyOut(xc->getMemPort()); 8421999SN/A 8431999SN/A return 0; 8441999SN/A} 84511856Sbrandon.potter@amd.com 8461999SN/A#endif // __SIM_SYSCALL_EMUL_HH__ 8476701Sgblack@eecs.umich.edu