syscall_emul.hh revision 360
11689SN/A/* 214025Sgiacomo.gabrielli@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 312109SRekai.GonzalezAlberquilla@arm.com * All rights reserved. 412109SRekai.GonzalezAlberquilla@arm.com * 512109SRekai.GonzalezAlberquilla@arm.com * Redistribution and use in source and binary forms, with or without 612109SRekai.GonzalezAlberquilla@arm.com * modification, are permitted provided that the following conditions are 712109SRekai.GonzalezAlberquilla@arm.com * met: redistributions of source code must retain the above copyright 812109SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer; 912109SRekai.GonzalezAlberquilla@arm.com * redistributions in binary form must reproduce the above copyright 1012109SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer in the 1112109SRekai.GonzalezAlberquilla@arm.com * documentation and/or other materials provided with the distribution; 1212109SRekai.GonzalezAlberquilla@arm.com * neither the name of the copyright holders nor the names of its 1312109SRekai.GonzalezAlberquilla@arm.com * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 159919Ssteve.reinhardt@amd.com * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A */ 281689SN/A 291689SN/A#ifndef __SYSCALL_EMUL_HH__ 301689SN/A#define __SYSCALL_EMUL_HH__ 311689SN/A 321689SN/A/// 331689SN/A/// @file syscall_emul.hh 341689SN/A/// 351689SN/A/// This file defines objects used to emulate syscalls from the target 361689SN/A/// application on the host machine. 371689SN/A 381689SN/A#include <string> 391689SN/A 402665Ssaidi@eecs.umich.edu#include "base/intmath.hh" // for RoundUp 412665Ssaidi@eecs.umich.edu#include "targetarch/isa_traits.hh" // for Addr 421689SN/A#include "mem/functional_mem/functional_memory.hh" 431689SN/A 442292SN/Aclass Process; 452292SN/Aclass ExecContext; 461060SN/A 471060SN/A/// 481060SN/A/// System call descriptor. 4912105Snathanael.premillieu@arm.com/// 501060SN/Aclass SyscallDesc { 5112334Sgabeblack@google.com 521684SN/A public: 531717SN/A 549919Ssteve.reinhardt@amd.com typedef int (*FuncPtr)(SyscallDesc *, int num, 558232Snate@binkert.org Process *, ExecContext *); 561060SN/A 571060SN/A const char *name; //!< Syscall name (e.g., "open"). 589919Ssteve.reinhardt@amd.com FuncPtr funcPtr; //!< Pointer to emulation function. 599919Ssteve.reinhardt@amd.com int flags; //!< Flags (see Flags enum). 609919Ssteve.reinhardt@amd.com 619919Ssteve.reinhardt@amd.com 629919Ssteve.reinhardt@amd.com /// Flag values for controlling syscall behavior. 639919Ssteve.reinhardt@amd.com enum Flags { 649919Ssteve.reinhardt@amd.com /// Don't set return regs according to funcPtr return value. 659919Ssteve.reinhardt@amd.com /// Used for syscalls with non-standard return conventions 669919Ssteve.reinhardt@amd.com /// that explicitly set the ExecContext regs (e.g., 679919Ssteve.reinhardt@amd.com /// sigreturn). 689919Ssteve.reinhardt@amd.com SuppressReturnValue = 1 6912105Snathanael.premillieu@arm.com }; 709919Ssteve.reinhardt@amd.com 719919Ssteve.reinhardt@amd.com /// Constructor. 729919Ssteve.reinhardt@amd.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 739919Ssteve.reinhardt@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 749919Ssteve.reinhardt@amd.com { 759919Ssteve.reinhardt@amd.com } 7612105Snathanael.premillieu@arm.com 779919Ssteve.reinhardt@amd.com /// Emulate the syscall. Public interface for calling through funcPtr. 7812109SRekai.GonzalezAlberquilla@arm.com void doSyscall(int callnum, Process *proc, ExecContext *xc); 7912109SRekai.GonzalezAlberquilla@arm.com}; 8012109SRekai.GonzalezAlberquilla@arm.com 8112109SRekai.GonzalezAlberquilla@arm.com 8214025Sgiacomo.gabrielli@arm.comclass BaseBufferArg { 8314025Sgiacomo.gabrielli@arm.com 8414025Sgiacomo.gabrielli@arm.com public: 8512109SRekai.GonzalezAlberquilla@arm.com 8612109SRekai.GonzalezAlberquilla@arm.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 879919Ssteve.reinhardt@amd.com { 8812105Snathanael.premillieu@arm.com bufPtr = new uint8_t[size]; 899919Ssteve.reinhardt@amd.com // clear out buffer: in case we only partially populate this, 909919Ssteve.reinhardt@amd.com // and then do a copyOut(), we want to make sure we don't 9112105Snathanael.premillieu@arm.com // introduce any random junk into the simulated address space 929919Ssteve.reinhardt@amd.com memset(bufPtr, 0, size); 939919Ssteve.reinhardt@amd.com } 949919Ssteve.reinhardt@amd.com 959919Ssteve.reinhardt@amd.com virtual ~BaseBufferArg() { delete [] bufPtr; } 969919Ssteve.reinhardt@amd.com 979919Ssteve.reinhardt@amd.com // 989919Ssteve.reinhardt@amd.com // copy data into simulator space (read from target memory) 999919Ssteve.reinhardt@amd.com // 1009919Ssteve.reinhardt@amd.com virtual bool copyIn(FunctionalMemory *mem) 1019919Ssteve.reinhardt@amd.com { 1029919Ssteve.reinhardt@amd.com mem->access(Read, addr, bufPtr, size); 1039919Ssteve.reinhardt@amd.com return true; // no EFAULT detection for now 1049919Ssteve.reinhardt@amd.com } 1051060SN/A 1061060SN/A // 1071060SN/A // copy data out of simulator space (write to target memory) 1081060SN/A // 1091060SN/A virtual bool copyOut(FunctionalMemory *mem) 1101060SN/A { 1111060SN/A mem->access(Write, addr, bufPtr, size); 1122292SN/A return true; // no EFAULT detection for now 1132292SN/A } 1142292SN/A 1151060SN/A protected: 1161060SN/A Addr addr; 1179919Ssteve.reinhardt@amd.com int size; 1181060SN/A uint8_t *bufPtr; 1191060SN/A}; 1209919Ssteve.reinhardt@amd.com 1219919Ssteve.reinhardt@amd.com 1229919Ssteve.reinhardt@amd.comclass BufferArg : public BaseBufferArg 1239919Ssteve.reinhardt@amd.com{ 1249919Ssteve.reinhardt@amd.com public: 1251060SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1269919Ssteve.reinhardt@amd.com void *bufferPtr() { return bufPtr; } 1271060SN/A}; 1281060SN/A 1299919Ssteve.reinhardt@amd.comtemplate <class T> 1301060SN/Aclass TypedBufferArg : public BaseBufferArg 13112109SRekai.GonzalezAlberquilla@arm.com{ 13212109SRekai.GonzalezAlberquilla@arm.com public: 13312109SRekai.GonzalezAlberquilla@arm.com // user can optionally specify a specific number of bytes to 13412109SRekai.GonzalezAlberquilla@arm.com // allocate to deal with those structs that have variable-size 13512109SRekai.GonzalezAlberquilla@arm.com // arrays at the end 13612109SRekai.GonzalezAlberquilla@arm.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 13712109SRekai.GonzalezAlberquilla@arm.com : BaseBufferArg(_addr, _size) 13812109SRekai.GonzalezAlberquilla@arm.com { } 13912109SRekai.GonzalezAlberquilla@arm.com 14013610Sgiacomo.gabrielli@arm.com // type case 14113610Sgiacomo.gabrielli@arm.com operator T*() { return (T *)bufPtr; } 14213610Sgiacomo.gabrielli@arm.com 1439920Syasuko.eckert@amd.com // dereference operators 1449920Syasuko.eckert@amd.com T& operator*() { return *((T *)bufPtr); } 1459920Syasuko.eckert@amd.com T* operator->() { return (T *)bufPtr; } 1469919Ssteve.reinhardt@amd.com T& operator[](int i) { return ((T *)bufPtr)[i]; } 1479919Ssteve.reinhardt@amd.com}; 1489919Ssteve.reinhardt@amd.com 1499919Ssteve.reinhardt@amd.com////////////////////////////////////////////////////////////////////// 1509919Ssteve.reinhardt@amd.com// 1511060SN/A// The following emulation functions are generic enough that they 1529919Ssteve.reinhardt@amd.com// don't need to be recompiled for different emulated OS's. They are 1539919Ssteve.reinhardt@amd.com// defined in sim/syscall_emul.cc. 1549919Ssteve.reinhardt@amd.com// 1559919Ssteve.reinhardt@amd.com////////////////////////////////////////////////////////////////////// 1569919Ssteve.reinhardt@amd.com 1579919Ssteve.reinhardt@amd.com 1581060SN/Aint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1591060SN/Aint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1602292SN/A 1612292SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1629919Ssteve.reinhardt@amd.comint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1639919Ssteve.reinhardt@amd.comint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1642292SN/Aint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1659919Ssteve.reinhardt@amd.comint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1669919Ssteve.reinhardt@amd.comint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1672292SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1689919Ssteve.reinhardt@amd.comint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1691060SN/Aint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1702292SN/A 1719919Ssteve.reinhardt@amd.com////////////////////////////////////////////////////////////////////// 1722292SN/A// 1739920Syasuko.eckert@amd.com// The following emulation functions are generic, but need to be 1749920Syasuko.eckert@amd.com// templated to account for differences in types, constants, etc. 1759920Syasuko.eckert@amd.com// 1762292SN/A////////////////////////////////////////////////////////////////////// 17712105Snathanael.premillieu@arm.com 1781060SN/Atemplate <class OS> 1792292SN/Aint 18012105Snathanael.premillieu@arm.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 1811060SN/A ExecContext *xc) 18212109SRekai.GonzalezAlberquilla@arm.com{ 18312109SRekai.GonzalezAlberquilla@arm.com int fd = xc->getSyscallArg(0); 18412109SRekai.GonzalezAlberquilla@arm.com unsigned req = xc->getSyscallArg(1); 18512109SRekai.GonzalezAlberquilla@arm.com 18612109SRekai.GonzalezAlberquilla@arm.com // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 18712109SRekai.GonzalezAlberquilla@arm.com 18813610Sgiacomo.gabrielli@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 18913610Sgiacomo.gabrielli@arm.com // doesn't map to any simulator fd: not a valid target fd 19013610Sgiacomo.gabrielli@arm.com return -EBADF; 1919920Syasuko.eckert@amd.com } 19212105Snathanael.premillieu@arm.com 1939920Syasuko.eckert@amd.com switch (req) { 1942292SN/A case OS::TIOCISATTY: 19512105Snathanael.premillieu@arm.com case OS::TIOCGETP: 1961060SN/A case OS::TIOCSETP: 19712109SRekai.GonzalezAlberquilla@arm.com case OS::TIOCSETN: 19812109SRekai.GonzalezAlberquilla@arm.com case OS::TIOCSETC: 19912109SRekai.GonzalezAlberquilla@arm.com case OS::TIOCGETC: 20012109SRekai.GonzalezAlberquilla@arm.com return -ENOTTY; 2012292SN/A 20212105Snathanael.premillieu@arm.com default: 2031060SN/A fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req); 2042292SN/A } 20512105Snathanael.premillieu@arm.com} 2061060SN/A 20712109SRekai.GonzalezAlberquilla@arm.comstruct OpenFlagTransTable { 20812109SRekai.GonzalezAlberquilla@arm.com int tgtFlag; 20912109SRekai.GonzalezAlberquilla@arm.com int hostFlag; 21012109SRekai.GonzalezAlberquilla@arm.com}; 21112109SRekai.GonzalezAlberquilla@arm.com 21212109SRekai.GonzalezAlberquilla@arm.com 21312109SRekai.GonzalezAlberquilla@arm.comtemplate <class OS> 21412109SRekai.GonzalezAlberquilla@arm.comint 21513610Sgiacomo.gabrielli@arm.comopenFunc(SyscallDesc *desc, int callnum, Process *process, 21613610Sgiacomo.gabrielli@arm.com ExecContext *xc) 21713610Sgiacomo.gabrielli@arm.com{ 2189920Syasuko.eckert@amd.com std::string path; 21912105Snathanael.premillieu@arm.com 2209920Syasuko.eckert@amd.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 2212292SN/A return -EFAULT; 2229919Ssteve.reinhardt@amd.com 2231060SN/A if (path == "/dev/sysdev0") { 2242292SN/A // This is a memory-mapped high-resolution timer device on Alpha. 2259919Ssteve.reinhardt@amd.com // We don't support it, so just punt. 2261060SN/A DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl; 22712109SRekai.GonzalezAlberquilla@arm.com return -ENOENT; 22812109SRekai.GonzalezAlberquilla@arm.com } 22912109SRekai.GonzalezAlberquilla@arm.com 23012109SRekai.GonzalezAlberquilla@arm.com int tgtFlags = xc->getSyscallArg(1); 23112109SRekai.GonzalezAlberquilla@arm.com int mode = xc->getSyscallArg(2); 23212109SRekai.GonzalezAlberquilla@arm.com int hostFlags = 0; 23313610Sgiacomo.gabrielli@arm.com 23413610Sgiacomo.gabrielli@arm.com // translate open flags 23513610Sgiacomo.gabrielli@arm.com for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 2369920Syasuko.eckert@amd.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 2379920Syasuko.eckert@amd.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 2389920Syasuko.eckert@amd.com hostFlags |= OS::openFlagTable[i].hostFlag; 2392292SN/A } 2409919Ssteve.reinhardt@amd.com } 2411060SN/A 2422292SN/A // any target flags left? 2439919Ssteve.reinhardt@amd.com if (tgtFlags != 0) 2449920Syasuko.eckert@amd.com cerr << "Syscall: open: cannot decode flags: " << tgtFlags << endl; 24512109SRekai.GonzalezAlberquilla@arm.com 24612109SRekai.GonzalezAlberquilla@arm.com#ifdef __CYGWIN32__ 24712109SRekai.GonzalezAlberquilla@arm.com hostFlags |= O_BINARY; 24813598Sgiacomo.travaglini@arm.com#endif 24913598Sgiacomo.travaglini@arm.com 25013598Sgiacomo.travaglini@arm.com // open the file 25113610Sgiacomo.gabrielli@arm.com int fd = open(path.c_str(), hostFlags, mode); 25213610Sgiacomo.gabrielli@arm.com 25313610Sgiacomo.gabrielli@arm.com return (fd == -1) ? -errno : process->open_fd(fd); 2549920Syasuko.eckert@amd.com} 2559920Syasuko.eckert@amd.com 2561060SN/A 2571060SN/Atemplate <class OS> 25812109SRekai.GonzalezAlberquilla@arm.comint 25912109SRekai.GonzalezAlberquilla@arm.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 26012109SRekai.GonzalezAlberquilla@arm.com ExecContext *xc) 26112109SRekai.GonzalezAlberquilla@arm.com{ 26212109SRekai.GonzalezAlberquilla@arm.com std::string path; 26312109SRekai.GonzalezAlberquilla@arm.com 26412109SRekai.GonzalezAlberquilla@arm.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 26512109SRekai.GonzalezAlberquilla@arm.com return -EFAULT; 26612109SRekai.GonzalezAlberquilla@arm.com 26712109SRekai.GonzalezAlberquilla@arm.com struct stat hostBuf; 26812109SRekai.GonzalezAlberquilla@arm.com int result = stat(path.c_str(), &hostBuf); 26912109SRekai.GonzalezAlberquilla@arm.com 27012109SRekai.GonzalezAlberquilla@arm.com if (result < 0) 27112109SRekai.GonzalezAlberquilla@arm.com return -errno; 27212109SRekai.GonzalezAlberquilla@arm.com 27312109SRekai.GonzalezAlberquilla@arm.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 27412109SRekai.GonzalezAlberquilla@arm.com 27512109SRekai.GonzalezAlberquilla@arm.com return 0; 27612109SRekai.GonzalezAlberquilla@arm.com} 27712109SRekai.GonzalezAlberquilla@arm.com 27812109SRekai.GonzalezAlberquilla@arm.com 27912109SRekai.GonzalezAlberquilla@arm.comtemplate <class OS> 28012109SRekai.GonzalezAlberquilla@arm.comint 28112109SRekai.GonzalezAlberquilla@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 28212109SRekai.GonzalezAlberquilla@arm.com ExecContext *xc) 28312109SRekai.GonzalezAlberquilla@arm.com{ 28413610Sgiacomo.gabrielli@arm.com std::string path; 28513610Sgiacomo.gabrielli@arm.com 28613610Sgiacomo.gabrielli@arm.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 28712109SRekai.GonzalezAlberquilla@arm.com return -EFAULT; 28812109SRekai.GonzalezAlberquilla@arm.com 28912109SRekai.GonzalezAlberquilla@arm.com struct stat hostBuf; 29012109SRekai.GonzalezAlberquilla@arm.com int result = lstat(path.c_str(), &hostBuf); 29112109SRekai.GonzalezAlberquilla@arm.com 29212109SRekai.GonzalezAlberquilla@arm.com if (result < 0) 29312109SRekai.GonzalezAlberquilla@arm.com return -errno; 29412109SRekai.GonzalezAlberquilla@arm.com 29512109SRekai.GonzalezAlberquilla@arm.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 29612109SRekai.GonzalezAlberquilla@arm.com 2971060SN/A return 0; 29812105Snathanael.premillieu@arm.com} 2991060SN/A 30012106SRekai.GonzalezAlberquilla@arm.comtemplate <class OS> 30112106SRekai.GonzalezAlberquilla@arm.comint 3021060SN/AfstatFunc(SyscallDesc *desc, int callnum, Process *process, 3031060SN/A ExecContext *xc) 30412106SRekai.GonzalezAlberquilla@arm.com{ 30512105Snathanael.premillieu@arm.com int fd = process->sim_fd(xc->getSyscallArg(0)); 30612105Snathanael.premillieu@arm.com 30712105Snathanael.premillieu@arm.com // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd); 30812105Snathanael.premillieu@arm.com 30912105Snathanael.premillieu@arm.com if (fd < 0) 31012105Snathanael.premillieu@arm.com return -EBADF; 31112109SRekai.GonzalezAlberquilla@arm.com 31212109SRekai.GonzalezAlberquilla@arm.com struct stat hostBuf; 31312109SRekai.GonzalezAlberquilla@arm.com int result = fstat(fd, &hostBuf); 31412109SRekai.GonzalezAlberquilla@arm.com 31512109SRekai.GonzalezAlberquilla@arm.com if (result < 0) 31612109SRekai.GonzalezAlberquilla@arm.com return -errno; 31713610Sgiacomo.gabrielli@arm.com 31813610Sgiacomo.gabrielli@arm.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 31913610Sgiacomo.gabrielli@arm.com 32012105Snathanael.premillieu@arm.com return 0; 32112105Snathanael.premillieu@arm.com} 32212105Snathanael.premillieu@arm.com 32312105Snathanael.premillieu@arm.com 32412105Snathanael.premillieu@arm.com// 32512106SRekai.GonzalezAlberquilla@arm.com// We don't really handle mmap(). If the target is mmaping an 3261060SN/A// anonymous region or /dev/zero, we can get away with doing basically 3275362Sksewell@umich.edu// nothing (since memory is initialized to zero and the simulator 3285364Sksewell@umich.edu// doesn't really check addresses anyway). Always print a warning, 3295364Sksewell@umich.edu// since this could be seriously broken if we're not mapping 3305364Sksewell@umich.edu// /dev/zero. 3315364Sksewell@umich.edu// 3325364Sksewell@umich.edu// Someday we should explicitly check for /dev/zero in open, flag the 3335364Sksewell@umich.edu// file descriptor, and fail (or implement!) a non-anonymous mmap to 3345364Sksewell@umich.edu// anything else. 3355364Sksewell@umich.edu// 3365364Sksewell@umich.edutemplate <class OS> 3375364Sksewell@umich.eduint 3385364Sksewell@umich.edummapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 3391060SN/A{ 3401060SN/A Addr start = xc->getSyscallArg(0); 3411060SN/A uint64_t length = xc->getSyscallArg(1); 3422292SN/A // int prot = xc->getSyscallArg(2); 343 int flags = xc->getSyscallArg(3); 344 int fd = p->sim_fd(xc->getSyscallArg(4)); 345 // int offset = xc->getSyscallArg(5); 346 347 if (start == 0) { 348 // user didn't give an address... pick one from our "mmap region" 349 start = p->mmap_base; 350 p->mmap_base += RoundUp<Addr>(length, VMPageSize); 351 } 352 353 if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 354 DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d. " 355 "This will break if not /dev/zero.", fd); 356 } 357 358 return start; 359} 360 361 362template <class OS> 363int 364getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 365 ExecContext *xc) 366{ 367 unsigned resource = xc->getSyscallArg(0); 368 TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 369 370 switch (resource) { 371 case OS::RLIMIT_STACK: 372 // max stack size in bytes: make up a number (2MB for now) 373 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 374 break; 375 376 default: 377 cerr << "getrlimitFunc: unimplemented resource " << resource << endl; 378 abort(); 379 break; 380 } 381 382 rlp.copyOut(xc->mem); 383 return 0; 384} 385 386// 1M usecs in 1 sec, for readability 387const int one_million = 1000000; 388 389// seconds since the epoch (1/1/1970)... about a billion, by my reckoning 390const unsigned seconds_since_epoch = 1000000000; 391 392// 393// helper function: populate struct timeval with approximation of 394// current elapsed time 395// 396template <class T1, class T2> 397void 398getElapsedTime(T1 &sec, T2 &usec) 399{ 400 int cycles_per_usec = ticksPerSecond / one_million; 401 402 int elapsed_usecs = curTick / cycles_per_usec; 403 sec = elapsed_usecs / one_million; 404 usec = elapsed_usecs % one_million; 405} 406 407 408template <class OS> 409int 410gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 411 ExecContext *xc) 412{ 413 TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 414 415 getElapsedTime(tp->tv_sec, tp->tv_usec); 416 tp->tv_sec += seconds_since_epoch; 417 418 tp.copyOut(xc->mem); 419 420 return 0; 421} 422 423 424template <class OS> 425int 426getrusageFunc(SyscallDesc *desc, int callnum, Process *process, 427 ExecContext *xc) 428{ 429 int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 430 TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 431 432 if (who != OS::RUSAGE_SELF) { 433 // don't really handle THREAD or CHILDREN, but just warn and 434 // plow ahead 435 DCOUT(SyscallWarnings) 436 << "Warning: getrusage() only supports RUSAGE_SELF." 437 << " Parameter " << who << " ignored." << endl; 438 } 439 440 getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 441 rup->ru_stime.tv_sec = 0; 442 rup->ru_stime.tv_usec = 0; 443 rup->ru_maxrss = 0; 444 rup->ru_ixrss = 0; 445 rup->ru_idrss = 0; 446 rup->ru_isrss = 0; 447 rup->ru_minflt = 0; 448 rup->ru_majflt = 0; 449 rup->ru_nswap = 0; 450 rup->ru_inblock = 0; 451 rup->ru_oublock = 0; 452 rup->ru_msgsnd = 0; 453 rup->ru_msgrcv = 0; 454 rup->ru_nsignals = 0; 455 rup->ru_nvcsw = 0; 456 rup->ru_nivcsw = 0; 457 458 rup.copyOut(xc->mem); 459 460 return 0; 461} 462 463 464 465#endif // __SYSCALL_EMUL_HH__ 466