syscall_emul.hh revision 2461
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 4812018Sandreas.sandberg@arm.com#include "base/intmath.hh" // for RoundUp 4912018Sandreas.sandberg@arm.com#include "mem/translating_port.hh" 5012018Sandreas.sandberg@arm.com#include "arch/isa_traits.hh" // for Addr 5112018Sandreas.sandberg@arm.com 5212018Sandreas.sandberg@arm.com#include "base/trace.hh" 5312018Sandreas.sandberg@arm.com#include "cpu/exec_context.hh" 5412018Sandreas.sandberg@arm.com#include "cpu/base.hh" 552064SN/A#include "sim/process.hh" 5612018Sandreas.sandberg@arm.com 5712018Sandreas.sandberg@arm.com/// 5812018Sandreas.sandberg@arm.com/// System call descriptor. 5912018Sandreas.sandberg@arm.com/// 6012018Sandreas.sandberg@arm.comclass SyscallDesc { 6112018Sandreas.sandberg@arm.com 6211799Sbrandon.potter@amd.com public: 6312018Sandreas.sandberg@arm.com 6412018Sandreas.sandberg@arm.com /// Typedef for target syscall handler functions. 6512018Sandreas.sandberg@arm.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 6612018Sandreas.sandberg@arm.com Process *, ExecContext *); 6712018Sandreas.sandberg@arm.com 6812018Sandreas.sandberg@arm.com const char *name; //!< Syscall name (e.g., "open"). 6911799Sbrandon.potter@amd.com FuncPtr funcPtr; //!< Pointer to emulation function. 70360SN/A int flags; //!< Flags (see Flags enum). 71360SN/A 72360SN/A /// Flag values for controlling syscall behavior. 73360SN/A enum Flags { 74360SN/A /// Don't set return regs according to funcPtr return value. 75360SN/A /// Used for syscalls with non-standard return conventions 761809SN/A /// that explicitly set the ExecContext regs (e.g., 7711800Sbrandon.potter@amd.com /// sigreturn). 7811392Sbrandon.potter@amd.com SuppressReturnValue = 1 791809SN/A }; 8011392Sbrandon.potter@amd.com 8111383Sbrandon.potter@amd.com /// Constructor. 823113Sgblack@eecs.umich.edu SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 8311799Sbrandon.potter@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 8411759Sbrandon.potter@amd.com { 8511812Sbaz21@cam.ac.uk } 8611812Sbaz21@cam.ac.uk 8711799Sbrandon.potter@amd.com /// Emulate the syscall. Public interface for calling through funcPtr. 888229Snate@binkert.org void doSyscall(int callnum, Process *proc, ExecContext *xc); 898229Snate@binkert.org}; 9011594Santhony.gutierrez@amd.com 917075Snate@binkert.org 928229Snate@binkert.orgclass BaseBufferArg { 9311856Sbrandon.potter@amd.com 947075Snate@binkert.org public: 95360SN/A 9612461Sgabeblack@google.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 9711886Sbrandon.potter@amd.com { 9811800Sbrandon.potter@amd.com bufPtr = new uint8_t[size]; 9911392Sbrandon.potter@amd.com // clear out buffer: in case we only partially populate this, 10012334Sgabeblack@google.com // and then do a copyOut(), we want to make sure we don't 1011354SN/A // introduce any random junk into the simulated address space 1026216Snate@binkert.org memset(bufPtr, 0, size); 1036658Snate@binkert.org } 1042474SN/A 1052680Sktlim@umich.edu virtual ~BaseBufferArg() { delete [] bufPtr; } 1068229Snate@binkert.org 10711886Sbrandon.potter@amd.com // 10810496Ssteve.reinhardt@amd.com // copy data into simulator space (read from target memory) 10911911SBrandon.Potter@amd.com // 1108229Snate@binkert.org virtual bool copyIn(TranslatingPort *memport) 11111794Sbrandon.potter@amd.com { 11211886Sbrandon.potter@amd.com memport->readBlob(addr, bufPtr, size); 11310497Ssteve.reinhardt@amd.com return true; // no EFAULT detection for now 11411794Sbrandon.potter@amd.com } 115360SN/A 116360SN/A // 117360SN/A // copy data out of simulator space (write to target memory) 118360SN/A // 119360SN/A virtual bool copyOut(TranslatingPort *memport) 120360SN/A { 121360SN/A memport->writeBlob(addr, bufPtr, size); 122360SN/A return true; // no EFAULT detection for now 123360SN/A } 124360SN/A 125378SN/A protected: 1261706SN/A Addr addr; 12711851Sbrandon.potter@amd.com int size; 128378SN/A uint8_t *bufPtr; 129378SN/A}; 130378SN/A 131378SN/A 132378SN/Aclass BufferArg : public BaseBufferArg 1331706SN/A{ 13411851Sbrandon.potter@amd.com public: 135360SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 13611760Sbrandon.potter@amd.com void *bufferPtr() { return bufPtr; } 13711760Sbrandon.potter@amd.com}; 13811851Sbrandon.potter@amd.com 13911760Sbrandon.potter@amd.comtemplate <class T> 1406109Ssanchezd@stanford.educlass TypedBufferArg : public BaseBufferArg 1411706SN/A{ 14211851Sbrandon.potter@amd.com public: 143378SN/A // user can optionally specify a specific number of bytes to 1446109Ssanchezd@stanford.edu // allocate to deal with those structs that have variable-size 1456109Ssanchezd@stanford.edu // arrays at the end 14611851Sbrandon.potter@amd.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1476109Ssanchezd@stanford.edu : BaseBufferArg(_addr, _size) 14811886Sbrandon.potter@amd.com { } 14911886Sbrandon.potter@amd.com 15011886Sbrandon.potter@amd.com // type case 15111886Sbrandon.potter@amd.com operator T*() { return (T *)bufPtr; } 152378SN/A 1531706SN/A // dereference operators 15411851Sbrandon.potter@amd.com T &operator*() { return *((T *)bufPtr); } 155378SN/A T* operator->() { return (T *)bufPtr; } 1565748SSteve.Reinhardt@amd.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 1575748SSteve.Reinhardt@amd.com}; 15811851Sbrandon.potter@amd.com 159378SN/A////////////////////////////////////////////////////////////////////// 160378SN/A// 1611706SN/A// The following emulation functions are generic enough that they 16211851Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's. They are 163378SN/A// defined in sim/syscall_emul.cc. 16411886Sbrandon.potter@amd.com// 1651706SN/A////////////////////////////////////////////////////////////////////// 16611851Sbrandon.potter@amd.com 167378SN/A 168378SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1691706SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 17011851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 171378SN/A 172378SN/A/// Handler for unimplemented syscalls that we never intend to 1731706SN/A/// implement (signal handling, etc.) and should not affect the correct 17411851Sbrandon.potter@amd.com/// behavior of the program. Print a warning only if the appropriate 175378SN/A/// trace flag is enabled. Return success to the target program. 1764118Sgblack@eecs.umich.eduSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1774118Sgblack@eecs.umich.edu Process *p, ExecContext *xc); 17811851Sbrandon.potter@amd.com 1794118Sgblack@eecs.umich.edu/// Target exit() handler: terminate simulation. 180378SN/ASyscallReturn exitFunc(SyscallDesc *desc, int num, 1811706SN/A Process *p, ExecContext *xc); 18211851Sbrandon.potter@amd.com 183378SN/A/// Target getpagesize() handler. 184378SN/ASyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 1851706SN/A Process *p, ExecContext *xc); 18611851Sbrandon.potter@amd.com 187360SN/A/// Target obreak() handler: set brk address. 1885513SMichael.Adler@intel.comSyscallReturn obreakFunc(SyscallDesc *desc, int num, 1895513SMichael.Adler@intel.com Process *p, ExecContext *xc); 19011851Sbrandon.potter@amd.com 1915513SMichael.Adler@intel.com/// Target close() handler. 19210203SAli.Saidi@ARM.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 19310203SAli.Saidi@ARM.com Process *p, ExecContext *xc); 19411851Sbrandon.potter@amd.com 19510203SAli.Saidi@ARM.com/// Target read() handler. 1965513SMichael.Adler@intel.comSyscallReturn readFunc(SyscallDesc *desc, int num, 19711851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 1985513SMichael.Adler@intel.com 199511SN/A/// Target write() handler. 20010633Smichaelupton@gmail.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 20111851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 20210633Smichaelupton@gmail.com 2031706SN/A/// Target lseek() handler. 20411851Sbrandon.potter@amd.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 205511SN/A Process *p, ExecContext *xc); 20612795Smattdsinclair@gmail.com 20712795Smattdsinclair@gmail.com/// Target munmap() handler. 20812795Smattdsinclair@gmail.comSyscallReturn munmapFunc(SyscallDesc *desc, int num, 20912795Smattdsinclair@gmail.com Process *p, ExecContext *xc); 2105513SMichael.Adler@intel.com 2115513SMichael.Adler@intel.com/// Target gethostname() handler. 21211851Sbrandon.potter@amd.comSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2135513SMichael.Adler@intel.com Process *p, ExecContext *xc); 214511SN/A 2151706SN/A/// Target unlink() handler. 21611851Sbrandon.potter@amd.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2171706SN/A Process *p, ExecContext *xc); 2181706SN/A 2191706SN/A/// Target rename() handler. 2201706SN/ASyscallReturn renameFunc(SyscallDesc *desc, int num, 22111851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2221706SN/A 2231706SN/A 2241706SN/A/// Target truncate() handler. 2251706SN/ASyscallReturn truncateFunc(SyscallDesc *desc, int num, 22611851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2271706SN/A 228511SN/A 2296703Svince@csl.cornell.edu/// Target ftruncate() handler. 2306703Svince@csl.cornell.eduSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 23111851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2326703Svince@csl.cornell.edu 2336685Stjones1@inf.ed.ac.uk 2346685Stjones1@inf.ed.ac.uk/// Target chown() handler. 23511851Sbrandon.potter@amd.comSyscallReturn chownFunc(SyscallDesc *desc, int num, 2366685Stjones1@inf.ed.ac.uk Process *p, ExecContext *xc); 2376685Stjones1@inf.ed.ac.uk 2385513SMichael.Adler@intel.com 2395513SMichael.Adler@intel.com/// Target fchown() handler. 24011851Sbrandon.potter@amd.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2415513SMichael.Adler@intel.com Process *p, ExecContext *xc); 24211885Sbrandon.potter@amd.com 24311885Sbrandon.potter@amd.com/// Target fnctl() handler. 24411885Sbrandon.potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2455513SMichael.Adler@intel.com Process *process, ExecContext *xc); 2461999SN/A 2471999SN/A/// Target setuid() handler. 24811851Sbrandon.potter@amd.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2491999SN/A Process *p, ExecContext *xc); 25011885Sbrandon.potter@amd.com 25111885Sbrandon.potter@amd.com/// Target getpid() handler. 25211885Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 2531999SN/A Process *p, ExecContext *xc); 2541999SN/A 2551999SN/A/// Target getuid() handler. 25611851Sbrandon.potter@amd.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 2571999SN/A Process *p, ExecContext *xc); 2583079Sstever@eecs.umich.edu 2593079Sstever@eecs.umich.edu/// Target getgid() handler. 26011851Sbrandon.potter@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 2613079Sstever@eecs.umich.edu Process *p, ExecContext *xc); 26211908SBrandon.Potter@amd.com 26311908SBrandon.Potter@amd.com/// Target getppid() handler. 26411908SBrandon.Potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 26511908SBrandon.Potter@amd.com Process *p, ExecContext *xc); 26611875Sbrandon.potter@amd.com 2672093SN/A/// Target geteuid() handler. 26811851Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 2692093SN/A Process *p, ExecContext *xc); 2702687Sksewell@umich.edu 2712687Sksewell@umich.edu/// Target getegid() handler. 27211851Sbrandon.potter@amd.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 2732687Sksewell@umich.edu Process *p, ExecContext *xc); 2742238SN/A 2752238SN/A 27611851Sbrandon.potter@amd.com 2772238SN/A/// Pseudo Funcs - These functions use a different return convension, 27811908SBrandon.Potter@amd.com/// returning a second value in a register other than the normal return register 27911908SBrandon.Potter@amd.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 28011908SBrandon.Potter@amd.com Process *process, ExecContext *xc); 28111908SBrandon.Potter@amd.com 28211908SBrandon.Potter@amd.com/// Target getpidPseudo() handler. 28311908SBrandon.Potter@amd.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 28411908SBrandon.Potter@amd.com Process *p, ExecContext *xc); 28511908SBrandon.Potter@amd.com 2862238SN/A/// Target getuidPseudo() handler. 2872238SN/ASyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 28811851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2892238SN/A 2902238SN/A/// Target getgidPseudo() handler. 2912238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 29211851Sbrandon.potter@amd.com Process *p, ExecContext *xc); 2932238SN/A 2942238SN/A 2952238SN/A/// This struct is used to build an target-OS-dependent table that 29611851Sbrandon.potter@amd.com/// maps the target's open() flags to the host open() flags. 2972238SN/Astruct OpenFlagTransTable { 2982238SN/A int tgtFlag; //!< Target system flag value. 2992238SN/A int hostFlag; //!< Corresponding host system flag value. 30011851Sbrandon.potter@amd.com}; 3012238SN/A 3022238SN/A 3032238SN/A 30411851Sbrandon.potter@amd.com/// A readable name for 1,000,000, for converting microseconds to seconds. 3052238SN/Aconst int one_million = 1000000; 3062238SN/A 3072238SN/A/// Approximate seconds since the epoch (1/1/1970). About a billion, 30811851Sbrandon.potter@amd.com/// by my reckoning. We want to keep this a constant (not use the 3092238SN/A/// real-world time) to keep simulations repeatable. 3109455Smitch.hayenga+gem5@gmail.comconst unsigned seconds_since_epoch = 1000000000; 3119455Smitch.hayenga+gem5@gmail.com 31211851Sbrandon.potter@amd.com/// Helper function to convert current elapsed time to seconds and 31310203SAli.Saidi@ARM.com/// microseconds. 31411851Sbrandon.potter@amd.comtemplate <class T1, class T2> 31511851Sbrandon.potter@amd.comvoid 3169455Smitch.hayenga+gem5@gmail.comgetElapsedTime(T1 &sec, T2 &usec) 3179112Smarc.orr@gmail.com{ 31811906SBrandon.Potter@amd.com int elapsed_usecs = curTick / Clock::Int::us; 31911906SBrandon.Potter@amd.com sec = elapsed_usecs / one_million; 3209112Smarc.orr@gmail.com usec = elapsed_usecs % one_million; 3219112Smarc.orr@gmail.com} 32211851Sbrandon.potter@amd.com 3239112Smarc.orr@gmail.com////////////////////////////////////////////////////////////////////// 3249112Smarc.orr@gmail.com// 32511911SBrandon.Potter@amd.com// The following emulation functions are generic, but need to be 3269112Smarc.orr@gmail.com// templated to account for differences in types, constants, etc. 32711911SBrandon.Potter@amd.com// 32811911SBrandon.Potter@amd.com////////////////////////////////////////////////////////////////////// 32911911SBrandon.Potter@amd.com 33011911SBrandon.Potter@amd.com/// Target ioctl() handler. For the most part, programs call ioctl() 3319112Smarc.orr@gmail.com/// only to find out if their stdout is a tty, to determine whether to 33211911SBrandon.Potter@amd.com/// do line or block buffering. 33311911SBrandon.Potter@amd.comtemplate <class OS> 33411911SBrandon.Potter@amd.comSyscallReturn 33511911SBrandon.Potter@amd.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 3369238Slluc.alvarez@bsc.es ExecContext *xc) 3379112Smarc.orr@gmail.com{ 33811911SBrandon.Potter@amd.com int fd = xc->getSyscallArg(0); 3399112Smarc.orr@gmail.com unsigned req = xc->getSyscallArg(1); 34011911SBrandon.Potter@amd.com 34111911SBrandon.Potter@amd.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 34211911SBrandon.Potter@amd.com 34311911SBrandon.Potter@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 34411911SBrandon.Potter@amd.com // doesn't map to any simulator fd: not a valid target fd 3459112Smarc.orr@gmail.com return -EBADF; 34611911SBrandon.Potter@amd.com } 34711911SBrandon.Potter@amd.com 34811911SBrandon.Potter@amd.com switch (req) { 34911911SBrandon.Potter@amd.com case OS::TIOCISATTY: 35011911SBrandon.Potter@amd.com case OS::TIOCGETP: 35111911SBrandon.Potter@amd.com case OS::TIOCSETP: 3529112Smarc.orr@gmail.com case OS::TIOCSETN: 3539112Smarc.orr@gmail.com case OS::TIOCSETC: 35411911SBrandon.Potter@amd.com case OS::TIOCGETC: 35511911SBrandon.Potter@amd.com case OS::TIOCGETS: 3569112Smarc.orr@gmail.com case OS::TIOCGETA: 35711911SBrandon.Potter@amd.com return -ENOTTY; 35811911SBrandon.Potter@amd.com 3599112Smarc.orr@gmail.com default: 3609112Smarc.orr@gmail.com fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 36111911SBrandon.Potter@amd.com fd, req, xc->readPC()); 36211911SBrandon.Potter@amd.com } 3639112Smarc.orr@gmail.com} 3649112Smarc.orr@gmail.com 3652238SN/A/// Target open() handler. 3662238SN/Atemplate <class OS> 3672238SN/ASyscallReturn 3682238SN/AopenFunc(SyscallDesc *desc, int callnum, Process *process, 36911851Sbrandon.potter@amd.com ExecContext *xc) 3702238SN/A{ 3712238SN/A std::string path; 3722238SN/A 37311851Sbrandon.potter@amd.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 3742238SN/A return -EFAULT; 3752238SN/A 3762238SN/A if (path == "/dev/sysdev0") { 37711851Sbrandon.potter@amd.com // This is a memory-mapped high-resolution timer device on Alpha. 3782238SN/A // We don't support it, so just punt. 3792238SN/A warn("Ignoring open(%s, ...)\n", path); 3802238SN/A return -ENOENT; 38111851Sbrandon.potter@amd.com } 3822238SN/A 3832238SN/A int tgtFlags = xc->getSyscallArg(1); 3841354SN/A int mode = xc->getSyscallArg(2); 3851354SN/A int hostFlags = 0; 38610796Sbrandon.potter@amd.com 38710796Sbrandon.potter@amd.com // translate open flags 3881354SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 3891354SN/A if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 3901354SN/A tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 3911354SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 3921354SN/A } 3931354SN/A } 3941354SN/A 3951354SN/A // any target flags left? 3961354SN/A if (tgtFlags != 0) 3971354SN/A warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 39810796Sbrandon.potter@amd.com 3991354SN/A#ifdef __CYGWIN32__ 40010796Sbrandon.potter@amd.com hostFlags |= O_BINARY; 4011354SN/A#endif 4021354SN/A 4031354SN/A DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 4041354SN/A 40510796Sbrandon.potter@amd.com // open the file 40610796Sbrandon.potter@amd.com int fd = open(path.c_str(), hostFlags, mode); 40710796Sbrandon.potter@amd.com 40810796Sbrandon.potter@amd.com return (fd == -1) ? -errno : process->alloc_fd(fd); 40910796Sbrandon.potter@amd.com} 41010796Sbrandon.potter@amd.com 41110796Sbrandon.potter@amd.com 41210796Sbrandon.potter@amd.com/// Target chmod() handler. 41310796Sbrandon.potter@amd.comtemplate <class OS> 41410796Sbrandon.potter@amd.comSyscallReturn 41510796Sbrandon.potter@amd.comchmodFunc(SyscallDesc *desc, int callnum, Process *process, 416360SN/A ExecContext *xc) 417360SN/A{ 418360SN/A std::string path; 419360SN/A 420360SN/A if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 421360SN/A return -EFAULT; 422360SN/A 42311759Sbrandon.potter@amd.com uint32_t mode = xc->getSyscallArg(1); 4243113Sgblack@eecs.umich.edu mode_t hostMode = 0; 4253113Sgblack@eecs.umich.edu 4263113Sgblack@eecs.umich.edu // XXX translate mode flags via OS::something??? 4273113Sgblack@eecs.umich.edu hostMode = mode; 4283113Sgblack@eecs.umich.edu 4293113Sgblack@eecs.umich.edu // do the chmod 4303113Sgblack@eecs.umich.edu int result = chmod(path.c_str(), hostMode); 4313113Sgblack@eecs.umich.edu if (result < 0) 4323113Sgblack@eecs.umich.edu return -errno; 4333113Sgblack@eecs.umich.edu 4343113Sgblack@eecs.umich.edu return 0; 4353113Sgblack@eecs.umich.edu} 4363113Sgblack@eecs.umich.edu 43712032Sandreas.sandberg@arm.com 4383113Sgblack@eecs.umich.edu/// Target fchmod() handler. 4393113Sgblack@eecs.umich.edutemplate <class OS> 4404189Sgblack@eecs.umich.eduSyscallReturn 4414189Sgblack@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, Process *process, 4423113Sgblack@eecs.umich.edu ExecContext *xc) 4433113Sgblack@eecs.umich.edu{ 4443113Sgblack@eecs.umich.edu int fd = xc->getSyscallArg(0); 4453113Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 4468737Skoansin.tan@gmail.com // doesn't map to any simulator fd: not a valid target fd 4473113Sgblack@eecs.umich.edu return -EBADF; 4488737Skoansin.tan@gmail.com } 4493277Sgblack@eecs.umich.edu 4505515SMichael.Adler@intel.com uint32_t mode = xc->getSyscallArg(1); 4515515SMichael.Adler@intel.com mode_t hostMode = 0; 4525515SMichael.Adler@intel.com 4535515SMichael.Adler@intel.com // XXX translate mode flags via OS::someting??? 4545515SMichael.Adler@intel.com hostMode = mode; 4558737Skoansin.tan@gmail.com 4563277Sgblack@eecs.umich.edu // do the fchmod 4578737Skoansin.tan@gmail.com int result = fchmod(process->sim_fd(fd), hostMode); 4583277Sgblack@eecs.umich.edu if (result < 0) 4598737Skoansin.tan@gmail.com return -errno; 4603277Sgblack@eecs.umich.edu 4618737Skoansin.tan@gmail.com return 0; 4623113Sgblack@eecs.umich.edu} 4633113Sgblack@eecs.umich.edu 4643113Sgblack@eecs.umich.edu 4653113Sgblack@eecs.umich.edu/// Target stat() handler. 4668737Skoansin.tan@gmail.comtemplate <class OS> 4673113Sgblack@eecs.umich.eduSyscallReturn 4688737Skoansin.tan@gmail.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 4693114Sgblack@eecs.umich.edu ExecContext *xc) 4708737Skoansin.tan@gmail.com{ 4713114Sgblack@eecs.umich.edu std::string path; 4728737Skoansin.tan@gmail.com 4733114Sgblack@eecs.umich.edu if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 4748737Skoansin.tan@gmail.com return -EFAULT; 47511906SBrandon.Potter@amd.com 4764061Sgblack@eecs.umich.edu struct stat hostBuf; 4774061Sgblack@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 4788737Skoansin.tan@gmail.com 4793113Sgblack@eecs.umich.edu if (result < 0) 4808737Skoansin.tan@gmail.com return -errno; 4813113Sgblack@eecs.umich.edu 4823113Sgblack@eecs.umich.edu OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 4833113Sgblack@eecs.umich.edu 4843113Sgblack@eecs.umich.edu return 0; 4853113Sgblack@eecs.umich.edu} 48612032Sandreas.sandberg@arm.com 4873113Sgblack@eecs.umich.edu 4883113Sgblack@eecs.umich.edu/// Target fstat64() handler. 4894189Sgblack@eecs.umich.edutemplate <class OS> 4904189Sgblack@eecs.umich.eduSyscallReturn 4913113Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, Process *process, 4923113Sgblack@eecs.umich.edu ExecContext *xc) 4933113Sgblack@eecs.umich.edu{ 4948737Skoansin.tan@gmail.com int fd = xc->getSyscallArg(0); 4953113Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 4968737Skoansin.tan@gmail.com // doesn't map to any simulator fd: not a valid target fd 4973113Sgblack@eecs.umich.edu return -EBADF; 4988737Skoansin.tan@gmail.com } 4993113Sgblack@eecs.umich.edu 5003113Sgblack@eecs.umich.edu#if BSD_HOST 5013113Sgblack@eecs.umich.edu struct stat hostBuf; 5023113Sgblack@eecs.umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 5033113Sgblack@eecs.umich.edu#else 5043113Sgblack@eecs.umich.edu struct stat64 hostBuf; 5053113Sgblack@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 50611906SBrandon.Potter@amd.com#endif 5073113Sgblack@eecs.umich.edu 50812032Sandreas.sandberg@arm.com if (result < 0) 5098852Sandreas.hansson@arm.com return -errno; 51011906SBrandon.Potter@amd.com 5113113Sgblack@eecs.umich.edu OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf); 5123113Sgblack@eecs.umich.edu 5133113Sgblack@eecs.umich.edu return 0; 5143113Sgblack@eecs.umich.edu} 5153113Sgblack@eecs.umich.edu 5163113Sgblack@eecs.umich.edu 5173113Sgblack@eecs.umich.edu/// Target lstat() handler. 5183113Sgblack@eecs.umich.edutemplate <class OS> 51912032Sandreas.sandberg@arm.comSyscallReturn 5208852Sandreas.hansson@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 52111906SBrandon.Potter@amd.com ExecContext *xc) 5223113Sgblack@eecs.umich.edu{ 5233113Sgblack@eecs.umich.edu std::string path; 5243113Sgblack@eecs.umich.edu 5256686Stjones1@inf.ed.ac.uk if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 5263113Sgblack@eecs.umich.edu return -EFAULT; 5273113Sgblack@eecs.umich.edu 5283113Sgblack@eecs.umich.edu struct stat hostBuf; 52911759Sbrandon.potter@amd.com int result = lstat(path.c_str(), &hostBuf); 53012032Sandreas.sandberg@arm.com 53111759Sbrandon.potter@amd.com if (result < 0) 53211759Sbrandon.potter@amd.com return -errno; 53311759Sbrandon.potter@amd.com 53411759Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 53511759Sbrandon.potter@amd.com 53611812Sbaz21@cam.ac.uk return 0; 53711812Sbaz21@cam.ac.uk} 53811812Sbaz21@cam.ac.uk 53911759Sbrandon.potter@amd.com/// Target lstat64() handler. 54011812Sbaz21@cam.ac.uktemplate <class OS> 54111759Sbrandon.potter@amd.comSyscallReturn 54211759Sbrandon.potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, Process *process, 54311759Sbrandon.potter@amd.com ExecContext *xc) 54411759Sbrandon.potter@amd.com{ 54511759Sbrandon.potter@amd.com std::string path; 54611759Sbrandon.potter@amd.com 54711759Sbrandon.potter@amd.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 54811812Sbaz21@cam.ac.uk return -EFAULT; 54911812Sbaz21@cam.ac.uk 55011812Sbaz21@cam.ac.uk#if BSD_HOST 55111812Sbaz21@cam.ac.uk struct stat hostBuf; 55211812Sbaz21@cam.ac.uk int result = lstat(path.c_str(), &hostBuf); 55311812Sbaz21@cam.ac.uk#else 55411812Sbaz21@cam.ac.uk struct stat64 hostBuf; 55511759Sbrandon.potter@amd.com int result = lstat64(path.c_str(), &hostBuf); 55611759Sbrandon.potter@amd.com#endif 55711812Sbaz21@cam.ac.uk 55811812Sbaz21@cam.ac.uk if (result < 0) 55911759Sbrandon.potter@amd.com return -errno; 56011812Sbaz21@cam.ac.uk 56111812Sbaz21@cam.ac.uk OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf); 56211812Sbaz21@cam.ac.uk 56311812Sbaz21@cam.ac.uk return 0; 56411812Sbaz21@cam.ac.uk} 56511812Sbaz21@cam.ac.uk 56611812Sbaz21@cam.ac.uk/// Target fstat() handler. 56711759Sbrandon.potter@amd.comtemplate <class OS> 56811759Sbrandon.potter@amd.comSyscallReturn 56911759Sbrandon.potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, Process *process, 57011759Sbrandon.potter@amd.com ExecContext *xc) 571378SN/A{ 572378SN/A int fd = process->sim_fd(xc->getSyscallArg(0)); 5739141Smarc.orr@gmail.com 5749141Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 575360SN/A 5761450SN/A if (fd < 0) 57711856Sbrandon.potter@amd.com return -EBADF; 578360SN/A 5796701Sgblack@eecs.umich.edu struct stat hostBuf; 58011856Sbrandon.potter@amd.com int result = fstat(fd, &hostBuf); 58111856Sbrandon.potter@amd.com 582360SN/A if (result < 0) 58310930Sbrandon.potter@amd.com return -errno; 584360SN/A 58511856Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 58611856Sbrandon.potter@amd.com 58710496Ssteve.reinhardt@amd.com return 0; 58811856Sbrandon.potter@amd.com} 58911856Sbrandon.potter@amd.com 5901458SN/A 591360SN/A/// Target statfs() handler. 59211856Sbrandon.potter@amd.comtemplate <class OS> 59311856Sbrandon.potter@amd.comSyscallReturn 59411856Sbrandon.potter@amd.comstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 59511856Sbrandon.potter@amd.com ExecContext *xc) 59611856Sbrandon.potter@amd.com{ 59711856Sbrandon.potter@amd.com std::string path; 59811856Sbrandon.potter@amd.com 59911856Sbrandon.potter@amd.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 60010496Ssteve.reinhardt@amd.com return -EFAULT; 60111856Sbrandon.potter@amd.com 60211856Sbrandon.potter@amd.com struct statfs hostBuf; 60311856Sbrandon.potter@amd.com int result = statfs(path.c_str(), &hostBuf); 60411856Sbrandon.potter@amd.com 60511856Sbrandon.potter@amd.com if (result < 0) 60610930Sbrandon.potter@amd.com return -errno; 6079141Smarc.orr@gmail.com 608360SN/A OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 609360SN/A 610360SN/A return 0; 61111907SBrandon.Potter@amd.com} 61211907SBrandon.Potter@amd.com 61311907SBrandon.Potter@amd.com 614360SN/A/// Target fstatfs() handler. 61511907SBrandon.Potter@amd.comtemplate <class OS> 61611907SBrandon.Potter@amd.comSyscallReturn 61711907SBrandon.Potter@amd.comfstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 61811907SBrandon.Potter@amd.com ExecContext *xc) 61911907SBrandon.Potter@amd.com{ 62011907SBrandon.Potter@amd.com int fd = process->sim_fd(xc->getSyscallArg(0)); 62111907SBrandon.Potter@amd.com 62211907SBrandon.Potter@amd.com if (fd < 0) 62311907SBrandon.Potter@amd.com return -EBADF; 62411907SBrandon.Potter@amd.com 62511907SBrandon.Potter@amd.com struct statfs hostBuf; 62611907SBrandon.Potter@amd.com int result = fstatfs(fd, &hostBuf); 62711907SBrandon.Potter@amd.com 62811907SBrandon.Potter@amd.com if (result < 0) 629360SN/A return -errno; 63011907SBrandon.Potter@amd.com 6311458SN/A OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); 632360SN/A 63311907SBrandon.Potter@amd.com return 0; 63411907SBrandon.Potter@amd.com} 63511907SBrandon.Potter@amd.com 63611907SBrandon.Potter@amd.com 63711907SBrandon.Potter@amd.com/// Target writev() handler. 63811907SBrandon.Potter@amd.comtemplate <class OS> 63911907SBrandon.Potter@amd.comSyscallReturn 64011907SBrandon.Potter@amd.comwritevFunc(SyscallDesc *desc, int callnum, Process *process, 64111907SBrandon.Potter@amd.com ExecContext *xc) 64211907SBrandon.Potter@amd.com{ 643360SN/A int fd = xc->getSyscallArg(0); 64411907SBrandon.Potter@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 64511907SBrandon.Potter@amd.com // doesn't map to any simulator fd: not a valid target fd 64611907SBrandon.Potter@amd.com return -EBADF; 647360SN/A } 648360SN/A 64911907SBrandon.Potter@amd.com TranslatingPort *p = xc->getMemPort(); 65011907SBrandon.Potter@amd.com uint64_t tiov_base = xc->getSyscallArg(1); 65111907SBrandon.Potter@amd.com size_t count = xc->getSyscallArg(2); 65211907SBrandon.Potter@amd.com struct iovec hiov[count]; 653360SN/A for (int i = 0; i < count; ++i) 65411907SBrandon.Potter@amd.com { 655360SN/A typename OS::tgt_iovec tiov; 656360SN/A 65711907SBrandon.Potter@amd.com p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 6583669Sbinkertn@umich.edu (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 65911907SBrandon.Potter@amd.com hiov[i].iov_len = gtoh(tiov.iov_len); 66011907SBrandon.Potter@amd.com hiov[i].iov_base = new char [hiov[i].iov_len]; 66111907SBrandon.Potter@amd.com p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 66211907SBrandon.Potter@amd.com hiov[i].iov_len); 66311907SBrandon.Potter@amd.com } 66411907SBrandon.Potter@amd.com 66511907SBrandon.Potter@amd.com int result = writev(process->sim_fd(fd), hiov, count); 66611907SBrandon.Potter@amd.com 66711907SBrandon.Potter@amd.com for (int i = 0; i < count; ++i) 66811907SBrandon.Potter@amd.com { 66911907SBrandon.Potter@amd.com delete [] (char *)hiov[i].iov_base; 67011907SBrandon.Potter@amd.com } 67111907SBrandon.Potter@amd.com 67211907SBrandon.Potter@amd.com if (result < 0) 67311907SBrandon.Potter@amd.com return -errno; 67411907SBrandon.Potter@amd.com 67511907SBrandon.Potter@amd.com return 0; 67611907SBrandon.Potter@amd.com} 67711907SBrandon.Potter@amd.com 67811907SBrandon.Potter@amd.com 67911907SBrandon.Potter@amd.com/// Target mmap() handler. 6801706SN/A/// 68111907SBrandon.Potter@amd.com/// We don't really handle mmap(). If the target is mmaping an 68211907SBrandon.Potter@amd.com/// anonymous region or /dev/zero, we can get away with doing basically 68311907SBrandon.Potter@amd.com/// nothing (since memory is initialized to zero and the simulator 68411907SBrandon.Potter@amd.com/// doesn't really check addresses anyway). Always print a warning, 68511907SBrandon.Potter@amd.com/// since this could be seriously broken if we're not mapping 68611907SBrandon.Potter@amd.com/// /dev/zero. 68710496Ssteve.reinhardt@amd.com// 68810496Ssteve.reinhardt@amd.com/// Someday we should explicitly check for /dev/zero in open, flag the 68911907SBrandon.Potter@amd.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to 69011907SBrandon.Potter@amd.com/// anything else. 69111907SBrandon.Potter@amd.comtemplate <class OS> 69211907SBrandon.Potter@amd.comSyscallReturn 69311907SBrandon.Potter@amd.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 69411907SBrandon.Potter@amd.com{ 69510496Ssteve.reinhardt@amd.com Addr start = xc->getSyscallArg(0); 69611907SBrandon.Potter@amd.com uint64_t length = xc->getSyscallArg(1); 69711907SBrandon.Potter@amd.com // int prot = xc->getSyscallArg(2); 69811907SBrandon.Potter@amd.com int flags = xc->getSyscallArg(3); 69911907SBrandon.Potter@amd.com // int fd = p->sim_fd(xc->getSyscallArg(4)); 70010496Ssteve.reinhardt@amd.com // int offset = xc->getSyscallArg(5); 70110496Ssteve.reinhardt@amd.com 70211907SBrandon.Potter@amd.com if (start == 0) { 70311907SBrandon.Potter@amd.com // user didn't give an address... pick one from our "mmap region" 70411907SBrandon.Potter@amd.com start = p->mmap_end; 70511907SBrandon.Potter@amd.com p->mmap_end += roundUp(length, TheISA::VMPageSize); 70611907SBrandon.Potter@amd.com if (p->nxm_start != 0) { 70711907SBrandon.Potter@amd.com //If we have an nxm space, make sure we haven't colided 70811907SBrandon.Potter@amd.com assert(p->mmap_end < p->nxm_start); 70911907SBrandon.Potter@amd.com } 71011907SBrandon.Potter@amd.com } 71111907SBrandon.Potter@amd.com 71211907SBrandon.Potter@amd.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 71311907SBrandon.Potter@amd.com warn("allowing mmap of file @ fd %d. " 71411907SBrandon.Potter@amd.com "This will break if not /dev/zero.", xc->getSyscallArg(4)); 71511907SBrandon.Potter@amd.com } 71611907SBrandon.Potter@amd.com 71711907SBrandon.Potter@amd.com return start; 71811907SBrandon.Potter@amd.com} 71911907SBrandon.Potter@amd.com 72011907SBrandon.Potter@amd.com/// Target getrlimit() handler. 72111907SBrandon.Potter@amd.comtemplate <class OS> 72211907SBrandon.Potter@amd.comSyscallReturn 72311907SBrandon.Potter@amd.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 72411907SBrandon.Potter@amd.com ExecContext *xc) 72511907SBrandon.Potter@amd.com{ 72611907SBrandon.Potter@amd.com unsigned resource = xc->getSyscallArg(0); 727360SN/A TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 72811907SBrandon.Potter@amd.com 72911907SBrandon.Potter@amd.com switch (resource) { 73011907SBrandon.Potter@amd.com case OS::TGT_RLIMIT_STACK: 73111907SBrandon.Potter@amd.com // max stack size in bytes: make up a number (2MB for now) 73211907SBrandon.Potter@amd.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 73311907SBrandon.Potter@amd.com rlp->rlim_cur = htog(rlp->rlim_cur); 73411907SBrandon.Potter@amd.com rlp->rlim_max = htog(rlp->rlim_max); 73511907SBrandon.Potter@amd.com break; 73611907SBrandon.Potter@amd.com 73711907SBrandon.Potter@amd.com default: 73811907SBrandon.Potter@amd.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 73911907SBrandon.Potter@amd.com << std::endl; 74011907SBrandon.Potter@amd.com abort(); 741360SN/A break; 742360SN/A } 74310027SChris.Adeniyi-Jones@arm.com 74410027SChris.Adeniyi-Jones@arm.com rlp.copyOut(xc->getMemPort()); 74510027SChris.Adeniyi-Jones@arm.com return 0; 74611851Sbrandon.potter@amd.com} 74710027SChris.Adeniyi-Jones@arm.com 74810027SChris.Adeniyi-Jones@arm.com/// Target gettimeofday() handler. 74911907SBrandon.Potter@amd.comtemplate <class OS> 75010027SChris.Adeniyi-Jones@arm.comSyscallReturn 75110027SChris.Adeniyi-Jones@arm.comgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 75210027SChris.Adeniyi-Jones@arm.com ExecContext *xc) 75310027SChris.Adeniyi-Jones@arm.com{ 75410027SChris.Adeniyi-Jones@arm.com TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 75511851Sbrandon.potter@amd.com 75611851Sbrandon.potter@amd.com getElapsedTime(tp->tv_sec, tp->tv_usec); 75710027SChris.Adeniyi-Jones@arm.com tp->tv_sec += seconds_since_epoch; 75811907SBrandon.Potter@amd.com tp->tv_sec = htog(tp->tv_sec); 75910027SChris.Adeniyi-Jones@arm.com tp->tv_usec = htog(tp->tv_usec); 76010027SChris.Adeniyi-Jones@arm.com 76110633Smichaelupton@gmail.com tp.copyOut(xc->getMemPort()); 76210633Smichaelupton@gmail.com 76310633Smichaelupton@gmail.com return 0; 76411851Sbrandon.potter@amd.com} 76510633Smichaelupton@gmail.com 76610633Smichaelupton@gmail.com 76710633Smichaelupton@gmail.com/// Target utimes() handler. 76810633Smichaelupton@gmail.comtemplate <class OS> 76910633Smichaelupton@gmail.comSyscallReturn 77010633Smichaelupton@gmail.comutimesFunc(SyscallDesc *desc, int callnum, Process *process, 77110633Smichaelupton@gmail.com ExecContext *xc) 77210633Smichaelupton@gmail.com{ 77310633Smichaelupton@gmail.com std::string path; 77410633Smichaelupton@gmail.com 77510203SAli.Saidi@ARM.com if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) 77610203SAli.Saidi@ARM.com return -EFAULT; 77710203SAli.Saidi@ARM.com 77811851Sbrandon.potter@amd.com TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); 77911851Sbrandon.potter@amd.com tp.copyIn(xc->getMemPort()); 78010203SAli.Saidi@ARM.com 78110203SAli.Saidi@ARM.com struct timeval hostTimeval[2]; 78210203SAli.Saidi@ARM.com for (int i = 0; i < 2; ++i) 78310203SAli.Saidi@ARM.com { 78410203SAli.Saidi@ARM.com hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 78510203SAli.Saidi@ARM.com hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 78610203SAli.Saidi@ARM.com } 78710203SAli.Saidi@ARM.com int result = utimes(path.c_str(), hostTimeval); 78810203SAli.Saidi@ARM.com 78910203SAli.Saidi@ARM.com if (result < 0) 79010203SAli.Saidi@ARM.com return -errno; 79111851Sbrandon.potter@amd.com 79211851Sbrandon.potter@amd.com return 0; 79310203SAli.Saidi@ARM.com} 79410203SAli.Saidi@ARM.com/// Target getrusage() function. 79510203SAli.Saidi@ARM.comtemplate <class OS> 79610203SAli.Saidi@ARM.comSyscallReturn 79710203SAli.Saidi@ARM.comgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 79810203SAli.Saidi@ARM.com ExecContext *xc) 79910203SAli.Saidi@ARM.com{ 80010203SAli.Saidi@ARM.com int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 80110850SGiacomo.Gabrielli@arm.com TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 80210850SGiacomo.Gabrielli@arm.com 80310850SGiacomo.Gabrielli@arm.com if (who != OS::TGT_RUSAGE_SELF) { 80411851Sbrandon.potter@amd.com // don't really handle THREAD or CHILDREN, but just warn and 80510850SGiacomo.Gabrielli@arm.com // plow ahead 80610850SGiacomo.Gabrielli@arm.com warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 80710850SGiacomo.Gabrielli@arm.com who); 80810850SGiacomo.Gabrielli@arm.com } 80910850SGiacomo.Gabrielli@arm.com 81010850SGiacomo.Gabrielli@arm.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 81110850SGiacomo.Gabrielli@arm.com rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 81210850SGiacomo.Gabrielli@arm.com rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 81310850SGiacomo.Gabrielli@arm.com 81410850SGiacomo.Gabrielli@arm.com rup->ru_stime.tv_sec = 0; 81510850SGiacomo.Gabrielli@arm.com rup->ru_stime.tv_usec = 0; 81610850SGiacomo.Gabrielli@arm.com rup->ru_maxrss = 0; 81710850SGiacomo.Gabrielli@arm.com rup->ru_ixrss = 0; 81810850SGiacomo.Gabrielli@arm.com rup->ru_idrss = 0; 81910850SGiacomo.Gabrielli@arm.com rup->ru_isrss = 0; 82010850SGiacomo.Gabrielli@arm.com rup->ru_minflt = 0; 82110850SGiacomo.Gabrielli@arm.com rup->ru_majflt = 0; 82210850SGiacomo.Gabrielli@arm.com rup->ru_nswap = 0; 82310850SGiacomo.Gabrielli@arm.com rup->ru_inblock = 0; 82410850SGiacomo.Gabrielli@arm.com rup->ru_oublock = 0; 82510850SGiacomo.Gabrielli@arm.com rup->ru_msgsnd = 0; 82610850SGiacomo.Gabrielli@arm.com rup->ru_msgrcv = 0; 82710850SGiacomo.Gabrielli@arm.com rup->ru_nsignals = 0; 82810850SGiacomo.Gabrielli@arm.com rup->ru_nvcsw = 0; 82910850SGiacomo.Gabrielli@arm.com rup->ru_nivcsw = 0; 83010850SGiacomo.Gabrielli@arm.com 83110850SGiacomo.Gabrielli@arm.com rup.copyOut(xc->getMemPort()); 83210850SGiacomo.Gabrielli@arm.com 83310850SGiacomo.Gabrielli@arm.com return 0; 83410850SGiacomo.Gabrielli@arm.com} 83510850SGiacomo.Gabrielli@arm.com 83610850SGiacomo.Gabrielli@arm.com#endif // __SIM_SYSCALL_EMUL_HH__ 8376640Svince@csl.cornell.edu