syscall_emul.hh revision 360
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2003 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 __SYSCALL_EMUL_HH__ 30360SN/A#define __SYSCALL_EMUL_HH__ 31360SN/A 32360SN/A/// 33360SN/A/// @file syscall_emul.hh 34360SN/A/// 35360SN/A/// This file defines objects used to emulate syscalls from the target 36360SN/A/// application on the host machine. 37360SN/A 38360SN/A#include <string> 39360SN/A 402665Ssaidi@eecs.umich.edu#include "base/intmath.hh" // for RoundUp 412665Ssaidi@eecs.umich.edu#include "targetarch/isa_traits.hh" // for Addr 422665Ssaidi@eecs.umich.edu#include "mem/functional_mem/functional_memory.hh" 43360SN/A 44360SN/Aclass Process; 451354SN/Aclass ExecContext; 461354SN/A 47360SN/A/// 4812018Sandreas.sandberg@arm.com/// System call descriptor. 4912018Sandreas.sandberg@arm.com/// 5012018Sandreas.sandberg@arm.comclass SyscallDesc { 5112018Sandreas.sandberg@arm.com 5212018Sandreas.sandberg@arm.com public: 5312018Sandreas.sandberg@arm.com 5412018Sandreas.sandberg@arm.com typedef int (*FuncPtr)(SyscallDesc *, int num, 552064SN/A Process *, ExecContext *); 5612018Sandreas.sandberg@arm.com 5712018Sandreas.sandberg@arm.com const char *name; //!< Syscall name (e.g., "open"). 5812018Sandreas.sandberg@arm.com FuncPtr funcPtr; //!< Pointer to emulation function. 5912018Sandreas.sandberg@arm.com int flags; //!< Flags (see Flags enum). 6012018Sandreas.sandberg@arm.com 6112018Sandreas.sandberg@arm.com 6211799Sbrandon.potter@amd.com /// Flag values for controlling syscall behavior. 6312018Sandreas.sandberg@arm.com enum Flags { 6412018Sandreas.sandberg@arm.com /// Don't set return regs according to funcPtr return value. 6512018Sandreas.sandberg@arm.com /// Used for syscalls with non-standard return conventions 6612018Sandreas.sandberg@arm.com /// that explicitly set the ExecContext regs (e.g., 6712018Sandreas.sandberg@arm.com /// sigreturn). 6812018Sandreas.sandberg@arm.com SuppressReturnValue = 1 6911799Sbrandon.potter@amd.com }; 70360SN/A 71360SN/A /// Constructor. 72360SN/A SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 73360SN/A : name(_name), funcPtr(_funcPtr), flags(_flags) 74360SN/A { 75360SN/A } 761809SN/A 7711800Sbrandon.potter@amd.com /// Emulate the syscall. Public interface for calling through funcPtr. 7811392Sbrandon.potter@amd.com void doSyscall(int callnum, Process *proc, ExecContext *xc); 791809SN/A}; 8011392Sbrandon.potter@amd.com 8111383Sbrandon.potter@amd.com 823113Sgblack@eecs.umich.educlass BaseBufferArg { 8311799Sbrandon.potter@amd.com 8411759Sbrandon.potter@amd.com public: 8511812Sbaz21@cam.ac.uk 8611812Sbaz21@cam.ac.uk BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 8711799Sbrandon.potter@amd.com { 888229Snate@binkert.org bufPtr = new uint8_t[size]; 898229Snate@binkert.org // clear out buffer: in case we only partially populate this, 9011594Santhony.gutierrez@amd.com // and then do a copyOut(), we want to make sure we don't 917075Snate@binkert.org // introduce any random junk into the simulated address space 928229Snate@binkert.org memset(bufPtr, 0, size); 9311856Sbrandon.potter@amd.com } 947075Snate@binkert.org 95360SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 9612461Sgabeblack@google.com 9711886Sbrandon.potter@amd.com // 9811800Sbrandon.potter@amd.com // copy data into simulator space (read from target memory) 9911392Sbrandon.potter@amd.com // 10012334Sgabeblack@google.com virtual bool copyIn(FunctionalMemory *mem) 1011354SN/A { 1026216Snate@binkert.org mem->access(Read, addr, bufPtr, size); 1036658Snate@binkert.org return true; // no EFAULT detection for now 1042474SN/A } 1052680Sktlim@umich.edu 1068229Snate@binkert.org // 10711886Sbrandon.potter@amd.com // copy data out of simulator space (write to target memory) 10810496Ssteve.reinhardt@amd.com // 10911911SBrandon.Potter@amd.com virtual bool copyOut(FunctionalMemory *mem) 1108229Snate@binkert.org { 11111794Sbrandon.potter@amd.com mem->access(Write, addr, bufPtr, size); 11211886Sbrandon.potter@amd.com return true; // no EFAULT detection for now 11310497Ssteve.reinhardt@amd.com } 11411794Sbrandon.potter@amd.com 115360SN/A protected: 116360SN/A Addr addr; 117360SN/A int size; 118360SN/A uint8_t *bufPtr; 119360SN/A}; 120360SN/A 121360SN/A 122360SN/Aclass BufferArg : public BaseBufferArg 123360SN/A{ 124360SN/A public: 125378SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1261706SN/A void *bufferPtr() { return bufPtr; } 12711851Sbrandon.potter@amd.com}; 128378SN/A 129378SN/Atemplate <class T> 130378SN/Aclass TypedBufferArg : public BaseBufferArg 131378SN/A{ 132378SN/A public: 1331706SN/A // user can optionally specify a specific number of bytes to 13411851Sbrandon.potter@amd.com // allocate to deal with those structs that have variable-size 135360SN/A // arrays at the end 13611760Sbrandon.potter@amd.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 13711760Sbrandon.potter@amd.com : BaseBufferArg(_addr, _size) 13811851Sbrandon.potter@amd.com { } 13911760Sbrandon.potter@amd.com 1406109Ssanchezd@stanford.edu // type case 1411706SN/A operator T*() { return (T *)bufPtr; } 14211851Sbrandon.potter@amd.com 143378SN/A // dereference operators 1446109Ssanchezd@stanford.edu T& operator*() { return *((T *)bufPtr); } 1456109Ssanchezd@stanford.edu T* operator->() { return (T *)bufPtr; } 14611851Sbrandon.potter@amd.com T& operator[](int i) { return ((T *)bufPtr)[i]; } 1476109Ssanchezd@stanford.edu}; 14811886Sbrandon.potter@amd.com 14911886Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 15011886Sbrandon.potter@amd.com// 15111886Sbrandon.potter@amd.com// The following emulation functions are generic enough that they 152378SN/A// don't need to be recompiled for different emulated OS's. They are 1531706SN/A// defined in sim/syscall_emul.cc. 15411851Sbrandon.potter@amd.com// 155378SN/A////////////////////////////////////////////////////////////////////// 1565748SSteve.Reinhardt@amd.com 1575748SSteve.Reinhardt@amd.com 15811851Sbrandon.potter@amd.comint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 159378SN/Aint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 160378SN/A 1611706SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 16211851Sbrandon.potter@amd.comint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 163378SN/Aint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 16411886Sbrandon.potter@amd.comint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1651706SN/Aint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 16611851Sbrandon.potter@amd.comint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 167378SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 168378SN/Aint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1691706SN/Aint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 17011851Sbrandon.potter@amd.com 171378SN/A////////////////////////////////////////////////////////////////////// 172378SN/A// 1731706SN/A// The following emulation functions are generic, but need to be 17411851Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc. 175378SN/A// 1764118Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 1774118Sgblack@eecs.umich.edu 17811851Sbrandon.potter@amd.comtemplate <class OS> 1794118Sgblack@eecs.umich.eduint 180378SN/AioctlFunc(SyscallDesc *desc, int callnum, Process *process, 1811706SN/A ExecContext *xc) 18211851Sbrandon.potter@amd.com{ 183378SN/A int fd = xc->getSyscallArg(0); 184378SN/A unsigned req = xc->getSyscallArg(1); 1851706SN/A 18611851Sbrandon.potter@amd.com // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 187360SN/A 1885513SMichael.Adler@intel.com if (fd < 0 || process->sim_fd(fd) < 0) { 1895513SMichael.Adler@intel.com // doesn't map to any simulator fd: not a valid target fd 19011851Sbrandon.potter@amd.com return -EBADF; 1915513SMichael.Adler@intel.com } 19210203SAli.Saidi@ARM.com 19310203SAli.Saidi@ARM.com switch (req) { 19411851Sbrandon.potter@amd.com case OS::TIOCISATTY: 19510203SAli.Saidi@ARM.com case OS::TIOCGETP: 1965513SMichael.Adler@intel.com case OS::TIOCSETP: 19711851Sbrandon.potter@amd.com case OS::TIOCSETN: 1985513SMichael.Adler@intel.com case OS::TIOCSETC: 199511SN/A case OS::TIOCGETC: 20010633Smichaelupton@gmail.com return -ENOTTY; 20111851Sbrandon.potter@amd.com 20210633Smichaelupton@gmail.com default: 2031706SN/A fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req); 20411851Sbrandon.potter@amd.com } 205511SN/A} 20612795Smattdsinclair@gmail.com 20712795Smattdsinclair@gmail.comstruct OpenFlagTransTable { 20812795Smattdsinclair@gmail.com int tgtFlag; 20912795Smattdsinclair@gmail.com int hostFlag; 21012796Smattdsinclair@gmail.com}; 21112796Smattdsinclair@gmail.com 21212796Smattdsinclair@gmail.com 21312796Smattdsinclair@gmail.comtemplate <class OS> 2145513SMichael.Adler@intel.comint 2155513SMichael.Adler@intel.comopenFunc(SyscallDesc *desc, int callnum, Process *process, 21611851Sbrandon.potter@amd.com ExecContext *xc) 2175513SMichael.Adler@intel.com{ 21813031Sbrandon.potter@amd.com std::string path; 21913031Sbrandon.potter@amd.com 22013031Sbrandon.potter@amd.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 22113031Sbrandon.potter@amd.com return -EFAULT; 22213031Sbrandon.potter@amd.com 22313031Sbrandon.potter@amd.com if (path == "/dev/sysdev0") { 22413031Sbrandon.potter@amd.com // This is a memory-mapped high-resolution timer device on Alpha. 22513031Sbrandon.potter@amd.com // We don't support it, so just punt. 22613031Sbrandon.potter@amd.com DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl; 22713031Sbrandon.potter@amd.com return -ENOENT; 22813031Sbrandon.potter@amd.com } 22913031Sbrandon.potter@amd.com 230511SN/A int tgtFlags = xc->getSyscallArg(1); 2311706SN/A int mode = xc->getSyscallArg(2); 23211851Sbrandon.potter@amd.com int hostFlags = 0; 2331706SN/A 2341706SN/A // translate open flags 2351706SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 2361706SN/A if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 23711851Sbrandon.potter@amd.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 2381706SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 2391706SN/A } 2401706SN/A } 2411706SN/A 24211851Sbrandon.potter@amd.com // any target flags left? 2431706SN/A if (tgtFlags != 0) 244511SN/A cerr << "Syscall: open: cannot decode flags: " << tgtFlags << endl; 2456703Svince@csl.cornell.edu 2466703Svince@csl.cornell.edu#ifdef __CYGWIN32__ 24711851Sbrandon.potter@amd.com hostFlags |= O_BINARY; 2486703Svince@csl.cornell.edu#endif 2496685Stjones1@inf.ed.ac.uk 2506685Stjones1@inf.ed.ac.uk // open the file 25111851Sbrandon.potter@amd.com int fd = open(path.c_str(), hostFlags, mode); 2526685Stjones1@inf.ed.ac.uk 2536685Stjones1@inf.ed.ac.uk return (fd == -1) ? -errno : process->open_fd(fd); 2545513SMichael.Adler@intel.com} 2555513SMichael.Adler@intel.com 25611851Sbrandon.potter@amd.com 2575513SMichael.Adler@intel.comtemplate <class OS> 25811885Sbrandon.potter@amd.comint 25911885Sbrandon.potter@amd.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 26011885Sbrandon.potter@amd.com ExecContext *xc) 2615513SMichael.Adler@intel.com{ 2621999SN/A std::string path; 2631999SN/A 26411851Sbrandon.potter@amd.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 2651999SN/A return -EFAULT; 26611885Sbrandon.potter@amd.com 26711885Sbrandon.potter@amd.com struct stat hostBuf; 26811885Sbrandon.potter@amd.com int result = stat(path.c_str(), &hostBuf); 2691999SN/A 2701999SN/A if (result < 0) 2711999SN/A return -errno; 27211851Sbrandon.potter@amd.com 2731999SN/A OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 2743079Sstever@eecs.umich.edu 2753079Sstever@eecs.umich.edu return 0; 27611851Sbrandon.potter@amd.com} 2773079Sstever@eecs.umich.edu 27811908SBrandon.Potter@amd.com 27911908SBrandon.Potter@amd.comtemplate <class OS> 28011908SBrandon.Potter@amd.comint 28111908SBrandon.Potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 28211875Sbrandon.potter@amd.com ExecContext *xc) 2832093SN/A{ 28411851Sbrandon.potter@amd.com std::string path; 2852093SN/A 2862687Sksewell@umich.edu if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 2872687Sksewell@umich.edu return -EFAULT; 28811851Sbrandon.potter@amd.com 2892687Sksewell@umich.edu struct stat hostBuf; 2902238SN/A int result = lstat(path.c_str(), &hostBuf); 2912238SN/A 29211851Sbrandon.potter@amd.com if (result < 0) 2932238SN/A return -errno; 29411908SBrandon.Potter@amd.com 29511908SBrandon.Potter@amd.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 29611908SBrandon.Potter@amd.com 29711908SBrandon.Potter@amd.com return 0; 29811908SBrandon.Potter@amd.com} 29911908SBrandon.Potter@amd.com 30011908SBrandon.Potter@amd.comtemplate <class OS> 30111908SBrandon.Potter@amd.comint 3022238SN/AfstatFunc(SyscallDesc *desc, int callnum, Process *process, 3032238SN/A ExecContext *xc) 30411851Sbrandon.potter@amd.com{ 3052238SN/A int fd = process->sim_fd(xc->getSyscallArg(0)); 30613448Sciro.santilli@arm.com 30713031Sbrandon.potter@amd.com // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd); 30813031Sbrandon.potter@amd.com 30913031Sbrandon.potter@amd.com if (fd < 0) 31013448Sciro.santilli@arm.com return -EBADF; 31113031Sbrandon.potter@amd.com 31213539Sjavier.setoain@arm.com struct stat hostBuf; 31313539Sjavier.setoain@arm.com int result = fstat(fd, &hostBuf); 31413539Sjavier.setoain@arm.com 31513539Sjavier.setoain@arm.com if (result < 0) 31613539Sjavier.setoain@arm.com return -errno; 31713539Sjavier.setoain@arm.com 31813031Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 3192238SN/A 32011851Sbrandon.potter@amd.com return 0; 3212238SN/A} 3222238SN/A 3232238SN/A 32411851Sbrandon.potter@amd.com// 3252238SN/A// We don't really handle mmap(). If the target is mmaping an 3262238SN/A// anonymous region or /dev/zero, we can get away with doing basically 3272238SN/A// nothing (since memory is initialized to zero and the simulator 32811851Sbrandon.potter@amd.com// doesn't really check addresses anyway). Always print a warning, 3292238SN/A// since this could be seriously broken if we're not mapping 3302238SN/A// /dev/zero. 3312238SN/A// 33211851Sbrandon.potter@amd.com// Someday we should explicitly check for /dev/zero in open, flag the 3332238SN/A// file descriptor, and fail (or implement!) a non-anonymous mmap to 3342238SN/A// anything else. 3352238SN/A// 33611851Sbrandon.potter@amd.comtemplate <class OS> 3372238SN/Aint 3389455Smitch.hayenga+gem5@gmail.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 3399455Smitch.hayenga+gem5@gmail.com{ 34011851Sbrandon.potter@amd.com Addr start = xc->getSyscallArg(0); 34110203SAli.Saidi@ARM.com uint64_t length = xc->getSyscallArg(1); 34211851Sbrandon.potter@amd.com // int prot = xc->getSyscallArg(2); 34311851Sbrandon.potter@amd.com int flags = xc->getSyscallArg(3); 3449455Smitch.hayenga+gem5@gmail.com int fd = p->sim_fd(xc->getSyscallArg(4)); 3459112Smarc.orr@gmail.com // int offset = xc->getSyscallArg(5); 34611906SBrandon.Potter@amd.com 34711906SBrandon.Potter@amd.com if (start == 0) { 3489112Smarc.orr@gmail.com // user didn't give an address... pick one from our "mmap region" 3499112Smarc.orr@gmail.com start = p->mmap_base; 35011851Sbrandon.potter@amd.com p->mmap_base += RoundUp<Addr>(length, VMPageSize); 3519112Smarc.orr@gmail.com } 3529112Smarc.orr@gmail.com 35311911SBrandon.Potter@amd.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 3549112Smarc.orr@gmail.com DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d. " 35511911SBrandon.Potter@amd.com "This will break if not /dev/zero.", fd); 35611911SBrandon.Potter@amd.com } 35711911SBrandon.Potter@amd.com 35811911SBrandon.Potter@amd.com return start; 3599112Smarc.orr@gmail.com} 36011911SBrandon.Potter@amd.com 36111911SBrandon.Potter@amd.com 36211911SBrandon.Potter@amd.comtemplate <class OS> 36311911SBrandon.Potter@amd.comint 3649238Slluc.alvarez@bsc.esgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 3659112Smarc.orr@gmail.com ExecContext *xc) 36611911SBrandon.Potter@amd.com{ 3679112Smarc.orr@gmail.com unsigned resource = xc->getSyscallArg(0); 36811911SBrandon.Potter@amd.com TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 36911911SBrandon.Potter@amd.com 37011911SBrandon.Potter@amd.com switch (resource) { 37111911SBrandon.Potter@amd.com case OS::RLIMIT_STACK: 37211911SBrandon.Potter@amd.com // max stack size in bytes: make up a number (2MB for now) 3739112Smarc.orr@gmail.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 37411911SBrandon.Potter@amd.com break; 37511911SBrandon.Potter@amd.com 37611911SBrandon.Potter@amd.com default: 37711911SBrandon.Potter@amd.com cerr << "getrlimitFunc: unimplemented resource " << resource << endl; 37811911SBrandon.Potter@amd.com abort(); 37911911SBrandon.Potter@amd.com break; 3809112Smarc.orr@gmail.com } 3819112Smarc.orr@gmail.com 38211911SBrandon.Potter@amd.com rlp.copyOut(xc->mem); 38311911SBrandon.Potter@amd.com return 0; 3849112Smarc.orr@gmail.com} 38511911SBrandon.Potter@amd.com 38611911SBrandon.Potter@amd.com// 1M usecs in 1 sec, for readability 3879112Smarc.orr@gmail.comconst int one_million = 1000000; 3889112Smarc.orr@gmail.com 38911911SBrandon.Potter@amd.com// seconds since the epoch (1/1/1970)... about a billion, by my reckoning 39011911SBrandon.Potter@amd.comconst unsigned seconds_since_epoch = 1000000000; 3919112Smarc.orr@gmail.com 3929112Smarc.orr@gmail.com// 3932238SN/A// helper function: populate struct timeval with approximation of 3942238SN/A// current elapsed time 3952238SN/A// 3962238SN/Atemplate <class T1, class T2> 39711851Sbrandon.potter@amd.comvoid 3982238SN/AgetElapsedTime(T1 &sec, T2 &usec) 3992238SN/A{ 4002238SN/A int cycles_per_usec = ticksPerSecond / one_million; 40111851Sbrandon.potter@amd.com 4022238SN/A int elapsed_usecs = curTick / cycles_per_usec; 4032238SN/A sec = elapsed_usecs / one_million; 4042238SN/A usec = elapsed_usecs % one_million; 40511851Sbrandon.potter@amd.com} 4062238SN/A 4072238SN/A 4082238SN/Atemplate <class OS> 40911851Sbrandon.potter@amd.comint 4102238SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 4112238SN/A ExecContext *xc) 4121354SN/A{ 4131354SN/A TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 41410796Sbrandon.potter@amd.com 41510796Sbrandon.potter@amd.com getElapsedTime(tp->tv_sec, tp->tv_usec); 4161354SN/A tp->tv_sec += seconds_since_epoch; 4171354SN/A 4181354SN/A tp.copyOut(xc->mem); 4191354SN/A 4201354SN/A return 0; 4211354SN/A} 4221354SN/A 4231354SN/A 4241354SN/Atemplate <class OS> 4251354SN/Aint 42610796Sbrandon.potter@amd.comgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 4271354SN/A ExecContext *xc) 42810796Sbrandon.potter@amd.com{ 4291354SN/A int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 4301354SN/A TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 4311354SN/A 4321354SN/A if (who != OS::RUSAGE_SELF) { 43310796Sbrandon.potter@amd.com // don't really handle THREAD or CHILDREN, but just warn and 43410796Sbrandon.potter@amd.com // plow ahead 43510796Sbrandon.potter@amd.com DCOUT(SyscallWarnings) 43610796Sbrandon.potter@amd.com << "Warning: getrusage() only supports RUSAGE_SELF." 43710796Sbrandon.potter@amd.com << " Parameter " << who << " ignored." << endl; 43810796Sbrandon.potter@amd.com } 43910796Sbrandon.potter@amd.com 44010796Sbrandon.potter@amd.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 44110796Sbrandon.potter@amd.com rup->ru_stime.tv_sec = 0; 44210796Sbrandon.potter@amd.com rup->ru_stime.tv_usec = 0; 44310796Sbrandon.potter@amd.com rup->ru_maxrss = 0; 444360SN/A rup->ru_ixrss = 0; 445360SN/A rup->ru_idrss = 0; 446360SN/A rup->ru_isrss = 0; 447360SN/A rup->ru_minflt = 0; 448360SN/A rup->ru_majflt = 0; 449360SN/A rup->ru_nswap = 0; 450360SN/A rup->ru_inblock = 0; 45111759Sbrandon.potter@amd.com rup->ru_oublock = 0; 4523113Sgblack@eecs.umich.edu rup->ru_msgsnd = 0; 4533113Sgblack@eecs.umich.edu rup->ru_msgrcv = 0; 4543113Sgblack@eecs.umich.edu rup->ru_nsignals = 0; 4553113Sgblack@eecs.umich.edu rup->ru_nvcsw = 0; 4563113Sgblack@eecs.umich.edu rup->ru_nivcsw = 0; 4573113Sgblack@eecs.umich.edu 4583113Sgblack@eecs.umich.edu rup.copyOut(xc->mem); 4593113Sgblack@eecs.umich.edu 4603113Sgblack@eecs.umich.edu return 0; 4613113Sgblack@eecs.umich.edu} 4623113Sgblack@eecs.umich.edu 4633113Sgblack@eecs.umich.edu 4643113Sgblack@eecs.umich.edu 46512032Sandreas.sandberg@arm.com#endif // __SYSCALL_EMUL_HH__ 4663113Sgblack@eecs.umich.edu