syscall_emul.hh revision 378
12810SN/A/* 210764Sandreas.hansson@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 39663Suri.wiener@arm.com * All rights reserved. 49663Suri.wiener@arm.com * 59663Suri.wiener@arm.com * Redistribution and use in source and binary forms, with or without 69663Suri.wiener@arm.com * modification, are permitted provided that the following conditions are 79663Suri.wiener@arm.com * met: redistributions of source code must retain the above copyright 89663Suri.wiener@arm.com * notice, this list of conditions and the following disclaimer; 99663Suri.wiener@arm.com * redistributions in binary form must reproduce the above copyright 109663Suri.wiener@arm.com * notice, this list of conditions and the following disclaimer in the 119663Suri.wiener@arm.com * documentation and/or other materials provided with the distribution; 129663Suri.wiener@arm.com * neither the name of the copyright holders nor the names of its 139663Suri.wiener@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 157636Ssteve.reinhardt@amd.com * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A */ 282810SN/A 292810SN/A#ifndef __SYSCALL_EMUL_HH__ 302810SN/A#define __SYSCALL_EMUL_HH__ 312810SN/A 322810SN/A/// 332810SN/A/// @file syscall_emul.hh 342810SN/A/// 352810SN/A/// This file defines objects used to emulate syscalls from the target 362810SN/A/// application on the host machine. 372810SN/A 382810SN/A#include <string> 392810SN/A 402810SN/A#include "base/intmath.hh" // for RoundUp 412810SN/A#include "targetarch/isa_traits.hh" // for Addr 422810SN/A#include "mem/functional_mem/functional_memory.hh" 432810SN/A 442810SN/Aclass Process; 452810SN/Aclass ExecContext; 462810SN/A 472810SN/A/// 482810SN/A/// System call descriptor. 492810SN/A/// 506216Snate@binkert.orgclass SyscallDesc { 516216Snate@binkert.org 522810SN/A public: 532810SN/A 542810SN/A /// Typedef for target syscall handler functions. 556216Snate@binkert.org typedef int (*FuncPtr)(SyscallDesc *, int num, 566216Snate@binkert.org Process *, ExecContext *); 578232Snate@binkert.org 586216Snate@binkert.org const char *name; //!< Syscall name (e.g., "open"). 595338Sstever@gmail.com FuncPtr funcPtr; //!< Pointer to emulation function. 606216Snate@binkert.org int flags; //!< Flags (see Flags enum). 612810SN/A 622810SN/A /// Flag values for controlling syscall behavior. 632810SN/A enum Flags { 649725Sandreas.hansson@arm.com /// Don't set return regs according to funcPtr return value. 6510582SCurtis.Dunham@arm.com /// Used for syscalls with non-standard return conventions 6610503SCurtis.Dunham@arm.com /// that explicitly set the ExecContext regs (e.g., 6710764Sandreas.hansson@arm.com /// sigreturn). 6810764Sandreas.hansson@arm.com SuppressReturnValue = 1 6910503SCurtis.Dunham@arm.com }; 702810SN/A 712810SN/A /// Constructor. 722810SN/A SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 734903SN/A : name(_name), funcPtr(_funcPtr), flags(_flags) 744903SN/A { 754903SN/A } 764903SN/A 774903SN/A /// Emulate the syscall. Public interface for calling through funcPtr. 784903SN/A void doSyscall(int callnum, Process *proc, ExecContext *xc); 794903SN/A}; 804908SN/A 815875Ssteve.reinhardt@amd.com 824903SN/Aclass BaseBufferArg { 835875Ssteve.reinhardt@amd.com 844903SN/A public: 854903SN/A 864903SN/A BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 874903SN/A { 887669Ssteve.reinhardt@amd.com bufPtr = new uint8_t[size]; 897669Ssteve.reinhardt@amd.com // clear out buffer: in case we only partially populate this, 907669Ssteve.reinhardt@amd.com // and then do a copyOut(), we want to make sure we don't 917669Ssteve.reinhardt@amd.com // introduce any random junk into the simulated address space 924903SN/A memset(bufPtr, 0, size); 934903SN/A } 945318SN/A 954908SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 965318SN/A 979543Ssascha.bischoff@arm.com // 989543Ssascha.bischoff@arm.com // copy data into simulator space (read from target memory) 999543Ssascha.bischoff@arm.com // 1009543Ssascha.bischoff@arm.com virtual bool copyIn(FunctionalMemory *mem) 1014908SN/A { 1024908SN/A mem->access(Read, addr, bufPtr, size); 1034908SN/A return true; // no EFAULT detection for now 1044908SN/A } 1054903SN/A 1064903SN/A // 10710766Sandreas.hansson@arm.com // copy data out of simulator space (write to target memory) 1084903SN/A // 1094903SN/A virtual bool copyOut(FunctionalMemory *mem) 1104903SN/A { 1117667Ssteve.reinhardt@amd.com mem->access(Write, addr, bufPtr, size); 1127667Ssteve.reinhardt@amd.com return true; // no EFAULT detection for now 1137667Ssteve.reinhardt@amd.com } 1147667Ssteve.reinhardt@amd.com 1157667Ssteve.reinhardt@amd.com protected: 1167667Ssteve.reinhardt@amd.com Addr addr; 1177667Ssteve.reinhardt@amd.com int size; 1187667Ssteve.reinhardt@amd.com uint8_t *bufPtr; 1197667Ssteve.reinhardt@amd.com}; 1207669Ssteve.reinhardt@amd.com 1217669Ssteve.reinhardt@amd.com 1227669Ssteve.reinhardt@amd.comclass BufferArg : public BaseBufferArg 1237667Ssteve.reinhardt@amd.com{ 1247667Ssteve.reinhardt@amd.com public: 1257667Ssteve.reinhardt@amd.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1267667Ssteve.reinhardt@amd.com void *bufferPtr() { return bufPtr; } 1274903SN/A}; 1284903SN/A 1294903SN/Atemplate <class T> 1304903SN/Aclass TypedBufferArg : public BaseBufferArg 1314903SN/A{ 1324903SN/A public: 13310766Sandreas.hansson@arm.com // user can optionally specify a specific number of bytes to 13410766Sandreas.hansson@arm.com // allocate to deal with those structs that have variable-size 1354903SN/A // arrays at the end 1364903SN/A TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1374903SN/A : BaseBufferArg(_addr, _size) 1384903SN/A { } 1394903SN/A 1404903SN/A // type case 1412810SN/A operator T*() { return (T *)bufPtr; } 1424908SN/A 1434908SN/A // dereference operators 14410766Sandreas.hansson@arm.com T& operator*() { return *((T *)bufPtr); } 14510766Sandreas.hansson@arm.com T* operator->() { return (T *)bufPtr; } 1469543Ssascha.bischoff@arm.com T& operator[](int i) { return ((T *)bufPtr)[i]; } 1479543Ssascha.bischoff@arm.com}; 1489543Ssascha.bischoff@arm.com 1499543Ssascha.bischoff@arm.com////////////////////////////////////////////////////////////////////// 1509543Ssascha.bischoff@arm.com// 1519543Ssascha.bischoff@arm.com// The following emulation functions are generic enough that they 15210766Sandreas.hansson@arm.com// don't need to be recompiled for different emulated OS's. They are 1535318SN/A// defined in sim/syscall_emul.cc. 1545318SN/A// 1555318SN/A////////////////////////////////////////////////////////////////////// 1564908SN/A 1574908SN/A 1584908SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1594908SN/Aint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1604908SN/A 1614920SN/A/// Handler for unimplemented syscalls that we never intend to 1624920SN/A/// implement (signal handling, etc.) and should not affect the correct 1634920SN/A/// behavior of the program. Print a warning only if the appropriate 16410766Sandreas.hansson@arm.com/// trace flag is enabled. Return success to the target program. 16510766Sandreas.hansson@arm.comint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1664920SN/A 1674920SN/A/// Target exit() handler: terminate simulation. 1684920SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1694920SN/A 1704920SN/A/// Target getpagesize() handler. 1714920SN/Aint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1724920SN/A 1734920SN/A/// Target obreak() handler: set brk address. 1744908SN/Aint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 17510766Sandreas.hansson@arm.com 17610766Sandreas.hansson@arm.com/// Target close() handler. 1775314SN/Aint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 17810766Sandreas.hansson@arm.com 1795875Ssteve.reinhardt@amd.com/// Target read() handler. 18010766Sandreas.hansson@arm.comint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1818988SAli.Saidi@ARM.com 1828988SAli.Saidi@ARM.com/// Target write() handler. 1838988SAli.Saidi@ARM.comint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1848988SAli.Saidi@ARM.com 1858988SAli.Saidi@ARM.com/// Target lseek() handler. 1868988SAli.Saidi@ARM.comint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1878988SAli.Saidi@ARM.com 1888988SAli.Saidi@ARM.com/// Target munmap() handler. 1898988SAli.Saidi@ARM.comint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1908988SAli.Saidi@ARM.com 1918988SAli.Saidi@ARM.com/// Target gethostname() handler. 1928988SAli.Saidi@ARM.comint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1935875Ssteve.reinhardt@amd.com 1945875Ssteve.reinhardt@amd.com////////////////////////////////////////////////////////////////////// 19510766Sandreas.hansson@arm.com// 1965314SN/A// The following emulation functions are generic, but need to be 1975314SN/A// templated to account for differences in types, constants, etc. 1985314SN/A// 1995314SN/A////////////////////////////////////////////////////////////////////// 2005314SN/A 20110764Sandreas.hansson@arm.com/// Target ioctl() handler. For the most part, programs call ioctl() 20210764Sandreas.hansson@arm.com/// only to find out if their stdout is a tty, to determine whether to 2032810SN/A/// do line or block buffering. 20410764Sandreas.hansson@arm.comtemplate <class OS> 20510764Sandreas.hansson@arm.comint 20610028SGiacomo.Gabrielli@arm.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 20710764Sandreas.hansson@arm.com ExecContext *xc) 2084666SN/A{ 2094626SN/A int fd = xc->getSyscallArg(0); 2105730SSteve.Reinhardt@amd.com unsigned req = xc->getSyscallArg(1); 2114626SN/A 2124626SN/A // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 2134908SN/A 2144626SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 2159725Sandreas.hansson@arm.com // doesn't map to any simulator fd: not a valid target fd 2164626SN/A return -EBADF; 2175875Ssteve.reinhardt@amd.com } 2185875Ssteve.reinhardt@amd.com 2195875Ssteve.reinhardt@amd.com switch (req) { 22010764Sandreas.hansson@arm.com case OS::TIOCISATTY: 2219725Sandreas.hansson@arm.com case OS::TIOCGETP: 2224668SN/A case OS::TIOCSETP: 2232810SN/A case OS::TIOCSETN: 2242810SN/A case OS::TIOCSETC: 2254908SN/A case OS::TIOCGETC: 2265318SN/A return -ENOTTY; 2275318SN/A 2285318SN/A default: 2295318SN/A fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req); 2305318SN/A } 2315318SN/A} 2325318SN/A 2339725Sandreas.hansson@arm.com/// This struct is used to build an target-OS-dependent table that 2345318SN/A/// maps the target's open() flags to the host open() flags. 2355318SN/Astruct OpenFlagTransTable { 2364908SN/A int tgtFlag; //!< Target system flag value. 23710679Sandreas.hansson@arm.com int hostFlag; //!< Corresponding host system flag value. 2384908SN/A}; 2394908SN/A 2405730SSteve.Reinhardt@amd.com 2414908SN/A/// Target open() handler. 2424908SN/Atemplate <class OS> 2434908SN/Aint 2444908SN/AopenFunc(SyscallDesc *desc, int callnum, Process *process, 2454908SN/A ExecContext *xc) 2464908SN/A{ 24710424Sandreas.hansson@arm.com std::string path; 2484908SN/A 24910679Sandreas.hansson@arm.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 2507667Ssteve.reinhardt@amd.com return -EFAULT; 2517667Ssteve.reinhardt@amd.com 2524908SN/A if (path == "/dev/sysdev0") { 2534908SN/A // This is a memory-mapped high-resolution timer device on Alpha. 2544908SN/A // We don't support it, so just punt. 2559725Sandreas.hansson@arm.com DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl; 2564908SN/A return -ENOENT; 2574908SN/A } 2584908SN/A 2594908SN/A int tgtFlags = xc->getSyscallArg(1); 2604908SN/A int mode = xc->getSyscallArg(2); 2612810SN/A int hostFlags = 0; 2622810SN/A 2632810SN/A // translate open flags 2649725Sandreas.hansson@arm.com for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 2659725Sandreas.hansson@arm.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 2669725Sandreas.hansson@arm.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 2672810SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 2682810SN/A } 2692810SN/A } 2702810SN/A 2712810SN/A // any target flags left? 2722810SN/A if (tgtFlags != 0) 2732810SN/A cerr << "Syscall: open: cannot decode flags: " << tgtFlags << endl; 2744903SN/A 2752810SN/A#ifdef __CYGWIN32__ 2764903SN/A hostFlags |= O_BINARY; 2774903SN/A#endif 2784903SN/A 2794903SN/A // open the file 2804903SN/A int fd = open(path.c_str(), hostFlags, mode); 2814903SN/A 2827667Ssteve.reinhardt@amd.com return (fd == -1) ? -errno : process->open_fd(fd); 2837667Ssteve.reinhardt@amd.com} 2847667Ssteve.reinhardt@amd.com 2857667Ssteve.reinhardt@amd.com 2865875Ssteve.reinhardt@amd.com/// Target stat() handler. 2875875Ssteve.reinhardt@amd.comtemplate <class OS> 2885875Ssteve.reinhardt@amd.comint 2895875Ssteve.reinhardt@amd.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 2905875Ssteve.reinhardt@amd.com ExecContext *xc) 2914903SN/A{ 2929725Sandreas.hansson@arm.com std::string path; 2937667Ssteve.reinhardt@amd.com 2947667Ssteve.reinhardt@amd.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 2954903SN/A return -EFAULT; 2967667Ssteve.reinhardt@amd.com 2977667Ssteve.reinhardt@amd.com struct stat hostBuf; 2989725Sandreas.hansson@arm.com int result = stat(path.c_str(), &hostBuf); 2994665SN/A 3005318SN/A if (result < 0) 3015318SN/A return -errno; 3025318SN/A 3035318SN/A OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 3049725Sandreas.hansson@arm.com 3052810SN/A return 0; 3064665SN/A} 3074665SN/A 3084902SN/A 3094902SN/A/// Target lstat() handler. 3104665SN/Atemplate <class OS> 31110725Sandreas.hansson@arm.comint 3129663Suri.wiener@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 3134910SN/A ExecContext *xc) 3144903SN/A{ 3154903SN/A std::string path; 3164903SN/A 3174903SN/A if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 3184903SN/A return -EFAULT; 3194903SN/A 3204903SN/A struct stat hostBuf; 3214903SN/A int result = lstat(path.c_str(), &hostBuf); 3224903SN/A 3234903SN/A if (result < 0) 3244903SN/A return -errno; 3254903SN/A 3264903SN/A OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 3274903SN/A 3289725Sandreas.hansson@arm.com return 0; 3299725Sandreas.hansson@arm.com} 3304903SN/A 3314903SN/A/// Target fstat() handler. 3324902SN/Atemplate <class OS> 3334902SN/Aint 3344665SN/AfstatFunc(SyscallDesc *desc, int callnum, Process *process, 3354903SN/A ExecContext *xc) 3364903SN/A{ 3374903SN/A int fd = process->sim_fd(xc->getSyscallArg(0)); 3384903SN/A 3394903SN/A // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd); 3409725Sandreas.hansson@arm.com 3414903SN/A if (fd < 0) 3424903SN/A return -EBADF; 3437667Ssteve.reinhardt@amd.com 3444665SN/A struct stat hostBuf; 3454903SN/A int result = fstat(fd, &hostBuf); 3464903SN/A 3474902SN/A if (result < 0) 3484665SN/A return -errno; 3494665SN/A 3507667Ssteve.reinhardt@amd.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 3517667Ssteve.reinhardt@amd.com 3527667Ssteve.reinhardt@amd.com return 0; 3537667Ssteve.reinhardt@amd.com} 3547667Ssteve.reinhardt@amd.com 3557667Ssteve.reinhardt@amd.com 3567667Ssteve.reinhardt@amd.com/// Target mmap() handler. 3577667Ssteve.reinhardt@amd.com/// 3588931Sandreas.hansson@arm.com/// We don't really handle mmap(). If the target is mmaping an 3597667Ssteve.reinhardt@amd.com/// anonymous region or /dev/zero, we can get away with doing basically 36010571Sandreas.hansson@arm.com/// nothing (since memory is initialized to zero and the simulator 36110571Sandreas.hansson@arm.com/// doesn't really check addresses anyway). Always print a warning, 36210571Sandreas.hansson@arm.com/// since this could be seriously broken if we're not mapping 36310571Sandreas.hansson@arm.com/// /dev/zero. 36410571Sandreas.hansson@arm.com// 3659725Sandreas.hansson@arm.com/// Someday we should explicitly check for /dev/zero in open, flag the 3669725Sandreas.hansson@arm.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to 3674670SN/A/// anything else. 36810582SCurtis.Dunham@arm.comtemplate <class OS> 3694670SN/Aint 3704916SN/AmmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 3714670SN/A{ 3724670SN/A Addr start = xc->getSyscallArg(0); 3734670SN/A uint64_t length = xc->getSyscallArg(1); 3744670SN/A // int prot = xc->getSyscallArg(2); 3757667Ssteve.reinhardt@amd.com int flags = xc->getSyscallArg(3); 3764670SN/A // int fd = p->sim_fd(xc->getSyscallArg(4)); 3777667Ssteve.reinhardt@amd.com // int offset = xc->getSyscallArg(5); 3787667Ssteve.reinhardt@amd.com 3797667Ssteve.reinhardt@amd.com if (start == 0) { 3807667Ssteve.reinhardt@amd.com // user didn't give an address... pick one from our "mmap region" 3817667Ssteve.reinhardt@amd.com start = p->mmap_base; 3827667Ssteve.reinhardt@amd.com p->mmap_base += RoundUp<Addr>(length, VMPageSize); 3834670SN/A } 3844667SN/A 3854902SN/A if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 3864902SN/A DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d. " 3874665SN/A "This will break if not /dev/zero.", xc->getSyscallArg(4)); 3884665SN/A } 3894665SN/A 3904665SN/A return start; 3914665SN/A} 3924665SN/A 3939725Sandreas.hansson@arm.com/// Target getrlimit() handler. 3949725Sandreas.hansson@arm.comtemplate <class OS> 3954665SN/Aint 3964665SN/AgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 3974665SN/A ExecContext *xc) 3984903SN/A{ 3999725Sandreas.hansson@arm.com unsigned resource = xc->getSyscallArg(0); 4004903SN/A TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 4014903SN/A 4029725Sandreas.hansson@arm.com switch (resource) { 4034903SN/A case OS::RLIMIT_STACK: 4049725Sandreas.hansson@arm.com // max stack size in bytes: make up a number (2MB for now) 4059725Sandreas.hansson@arm.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 4064665SN/A break; 4074665SN/A 4082810SN/A default: 4092810SN/A cerr << "getrlimitFunc: unimplemented resource " << resource << endl; 4102810SN/A abort(); 4112810SN/A break; 41210766Sandreas.hansson@arm.com } 4134668SN/A 4147667Ssteve.reinhardt@amd.com rlp.copyOut(xc->mem); 4157667Ssteve.reinhardt@amd.com return 0; 4169725Sandreas.hansson@arm.com} 4175270SN/A 4185270SN/A/// A readable name for 1,000,000, for converting microseconds to seconds. 4195270SN/Aconst int one_million = 1000000; 4205270SN/A 4215270SN/A/// Approximate seconds since the epoch (1/1/1970). About a billion, 4225270SN/A/// by my reckoning. We want to keep this a constant (not use the 4235270SN/A/// real-world time) to keep simulations repeatable. 4245270SN/Aconst unsigned seconds_since_epoch = 1000000000; 4259725Sandreas.hansson@arm.com 4269725Sandreas.hansson@arm.com/// Helper function to convert current elapsed time to seconds and 4275318SN/A/// microseconds. 4285318SN/Atemplate <class T1, class T2> 4295318SN/Avoid 4309725Sandreas.hansson@arm.comgetElapsedTime(T1 &sec, T2 &usec) 4315270SN/A{ 4329725Sandreas.hansson@arm.com int cycles_per_usec = ticksPerSecond / one_million; 4339725Sandreas.hansson@arm.com 4345270SN/A int elapsed_usecs = curTick / cycles_per_usec; 4354668SN/A sec = elapsed_usecs / one_million; 4364668SN/A usec = elapsed_usecs % one_million; 4374668SN/A} 4385314SN/A 4395314SN/A 4405314SN/A/// Target gettimeofday() handler. 4415314SN/Atemplate <class OS> 4425314SN/Aint 4435314SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 4445314SN/A ExecContext *xc) 44510764Sandreas.hansson@arm.com{ 4465314SN/A TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 4475314SN/A 4489725Sandreas.hansson@arm.com getElapsedTime(tp->tv_sec, tp->tv_usec); 4499725Sandreas.hansson@arm.com tp->tv_sec += seconds_since_epoch; 4505314SN/A 4515314SN/A tp.copyOut(xc->mem); 4525314SN/A 4535314SN/A return 0; 4544668SN/A} 4555314SN/A 4562810SN/A 45710725Sandreas.hansson@arm.com/// Target getrusage() function. 45810764Sandreas.hansson@arm.comtemplate <class OS> 45910028SGiacomo.Gabrielli@arm.comint 4605730SSteve.Reinhardt@amd.comgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 4615730SSteve.Reinhardt@amd.com ExecContext *xc) 4625314SN/A{ 4635314SN/A int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 4645314SN/A TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 4655314SN/A 4667667Ssteve.reinhardt@amd.com if (who != OS::RUSAGE_SELF) { 4677667Ssteve.reinhardt@amd.com // don't really handle THREAD or CHILDREN, but just warn and 4682810SN/A // plow ahead 4695314SN/A DCOUT(SyscallWarnings) 4709725Sandreas.hansson@arm.com << "Warning: getrusage() only supports RUSAGE_SELF." 4719725Sandreas.hansson@arm.com << " Parameter " << who << " ignored." << endl; 4725314SN/A } 4739725Sandreas.hansson@arm.com 4742810SN/A getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 4752810SN/A rup->ru_stime.tv_sec = 0; 4762810SN/A rup->ru_stime.tv_usec = 0; 4779663Suri.wiener@arm.com rup->ru_maxrss = 0; 4789663Suri.wiener@arm.com rup->ru_ixrss = 0; 4799663Suri.wiener@arm.com rup->ru_idrss = 0; 4809663Suri.wiener@arm.com rup->ru_isrss = 0; 4819663Suri.wiener@arm.com rup->ru_minflt = 0; 4829663Suri.wiener@arm.com rup->ru_majflt = 0; 4839663Suri.wiener@arm.com rup->ru_nswap = 0; 484 rup->ru_inblock = 0; 485 rup->ru_oublock = 0; 486 rup->ru_msgsnd = 0; 487 rup->ru_msgrcv = 0; 488 rup->ru_nsignals = 0; 489 rup->ru_nvcsw = 0; 490 rup->ru_nivcsw = 0; 491 492 rup.copyOut(xc->mem); 493 494 return 0; 495} 496 497 498 499#endif // __SYSCALL_EMUL_HH__ 500