syscall_emul.hh revision 511
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 for target syscall handler functions. 552064SN/A typedef int (*FuncPtr)(SyscallDesc *, int num, 5612018Sandreas.sandberg@arm.com Process *, ExecContext *); 5712018Sandreas.sandberg@arm.com 5812018Sandreas.sandberg@arm.com const char *name; //!< Syscall name (e.g., "open"). 5912018Sandreas.sandberg@arm.com FuncPtr funcPtr; //!< Pointer to emulation function. 6012018Sandreas.sandberg@arm.com int flags; //!< Flags (see Flags enum). 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 8113570Sbrandon.potter@amd.com 8211383Sbrandon.potter@amd.comclass BaseBufferArg { 8313568Sbrandon.potter@amd.com 843113Sgblack@eecs.umich.edu public: 8511799Sbrandon.potter@amd.com 8611759Sbrandon.potter@amd.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 8711812Sbaz21@cam.ac.uk { 8811812Sbaz21@cam.ac.uk bufPtr = new uint8_t[size]; 8911799Sbrandon.potter@amd.com // clear out buffer: in case we only partially populate this, 908229Snate@binkert.org // and then do a copyOut(), we want to make sure we don't 9113570Sbrandon.potter@amd.com // introduce any random junk into the simulated address space 928229Snate@binkert.org memset(bufPtr, 0, size); 9311594Santhony.gutierrez@amd.com } 947075Snate@binkert.org 958229Snate@binkert.org virtual ~BaseBufferArg() { delete [] bufPtr; } 9611856Sbrandon.potter@amd.com 977075Snate@binkert.org // 98360SN/A // copy data into simulator space (read from target memory) 9912461Sgabeblack@google.com // 10011886Sbrandon.potter@amd.com virtual bool copyIn(FunctionalMemory *mem) 10111800Sbrandon.potter@amd.com { 10211392Sbrandon.potter@amd.com mem->access(Read, addr, bufPtr, size); 10312334Sgabeblack@google.com return true; // no EFAULT detection for now 1041354SN/A } 1056216Snate@binkert.org 1066658Snate@binkert.org // 1072474SN/A // copy data out of simulator space (write to target memory) 1082680Sktlim@umich.edu // 1098229Snate@binkert.org virtual bool copyOut(FunctionalMemory *mem) 11011886Sbrandon.potter@amd.com { 11110496Ssteve.reinhardt@amd.com mem->access(Write, addr, bufPtr, size); 11211911SBrandon.Potter@amd.com return true; // no EFAULT detection for now 1138229Snate@binkert.org } 11411794Sbrandon.potter@amd.com 11511886Sbrandon.potter@amd.com protected: 11610497Ssteve.reinhardt@amd.com Addr addr; 11711794Sbrandon.potter@amd.com int size; 118360SN/A uint8_t *bufPtr; 119360SN/A}; 120360SN/A 121360SN/A 122360SN/Aclass BufferArg : public BaseBufferArg 123360SN/A{ 124360SN/A public: 125360SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 126360SN/A void *bufferPtr() { return bufPtr; } 127360SN/A}; 128378SN/A 1291706SN/Atemplate <class T> 13011851Sbrandon.potter@amd.comclass TypedBufferArg : public BaseBufferArg 131378SN/A{ 132378SN/A public: 133378SN/A // user can optionally specify a specific number of bytes to 134378SN/A // allocate to deal with those structs that have variable-size 135378SN/A // arrays at the end 1361706SN/A TypedBufferArg(Addr _addr, int _size = sizeof(T)) 13711851Sbrandon.potter@amd.com : BaseBufferArg(_addr, _size) 138360SN/A { } 13911760Sbrandon.potter@amd.com 14011760Sbrandon.potter@amd.com // type case 14111851Sbrandon.potter@amd.com operator T*() { return (T *)bufPtr; } 14211760Sbrandon.potter@amd.com 1436109Ssanchezd@stanford.edu // dereference operators 1441706SN/A T &operator*() { return *((T *)bufPtr); } 14511851Sbrandon.potter@amd.com T* operator->() { return (T *)bufPtr; } 146378SN/A T &operator[](int i) { return ((T *)bufPtr)[i]; } 1476109Ssanchezd@stanford.edu}; 1486109Ssanchezd@stanford.edu 14911851Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 1506109Ssanchezd@stanford.edu// 15111886Sbrandon.potter@amd.com// The following emulation functions are generic enough that they 15211886Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's. They are 15311886Sbrandon.potter@amd.com// defined in sim/syscall_emul.cc. 15411886Sbrandon.potter@amd.com// 155378SN/A////////////////////////////////////////////////////////////////////// 1561706SN/A 15711851Sbrandon.potter@amd.com 158378SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1595748SSteve.Reinhardt@amd.comint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1605748SSteve.Reinhardt@amd.com 16111851Sbrandon.potter@amd.com/// Handler for unimplemented syscalls that we never intend to 162378SN/A/// implement (signal handling, etc.) and should not affect the correct 163378SN/A/// behavior of the program. Print a warning only if the appropriate 1641706SN/A/// trace flag is enabled. Return success to the target program. 16511851Sbrandon.potter@amd.comint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 166378SN/A 167378SN/A/// Target exit() handler: terminate simulation. 1681706SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 16911851Sbrandon.potter@amd.com 170378SN/A/// Target getpagesize() handler. 1714118Sgblack@eecs.umich.eduint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1724118Sgblack@eecs.umich.edu 17311851Sbrandon.potter@amd.com/// Target obreak() handler: set brk address. 1744118Sgblack@eecs.umich.eduint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 175378SN/A 1761706SN/A/// Target close() handler. 17711851Sbrandon.potter@amd.comint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 178378SN/A 17913568Sbrandon.potter@amd.com/// Target read() handler. 18013568Sbrandon.potter@amd.comint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 18113568Sbrandon.potter@amd.com 18213568Sbrandon.potter@amd.com/// Target write() handler. 183378SN/Aint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1841706SN/A 18511851Sbrandon.potter@amd.com/// Target lseek() handler. 186360SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1875513SMichael.Adler@intel.com 1885513SMichael.Adler@intel.com/// Target munmap() handler. 18911851Sbrandon.potter@amd.comint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 1905513SMichael.Adler@intel.com 19110203SAli.Saidi@ARM.com/// Target gethostname() handler. 19210203SAli.Saidi@ARM.comint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 19311851Sbrandon.potter@amd.com 19410203SAli.Saidi@ARM.com/// Target unlink() handler. 1955513SMichael.Adler@intel.comint unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 19611851Sbrandon.potter@amd.com 1975513SMichael.Adler@intel.com/// Target rename() handler. 198511SN/Aint renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); 19910633Smichaelupton@gmail.com 20011851Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 20110633Smichaelupton@gmail.com// 2021706SN/A// The following emulation functions are generic, but need to be 20311851Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc. 204511SN/A// 20512795Smattdsinclair@gmail.com////////////////////////////////////////////////////////////////////// 20612795Smattdsinclair@gmail.com 20712795Smattdsinclair@gmail.com/// Target ioctl() handler. For the most part, programs call ioctl() 20812795Smattdsinclair@gmail.com/// only to find out if their stdout is a tty, to determine whether to 20912796Smattdsinclair@gmail.com/// do line or block buffering. 21012796Smattdsinclair@gmail.comtemplate <class OS> 21112796Smattdsinclair@gmail.comint 21212796Smattdsinclair@gmail.comioctlFunc(SyscallDesc *desc, int callnum, Process *process, 2135513SMichael.Adler@intel.com ExecContext *xc) 2145513SMichael.Adler@intel.com{ 21511851Sbrandon.potter@amd.com int fd = xc->getSyscallArg(0); 2165513SMichael.Adler@intel.com unsigned req = xc->getSyscallArg(1); 21713031Sbrandon.potter@amd.com 21813031Sbrandon.potter@amd.com // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 21913031Sbrandon.potter@amd.com 22013031Sbrandon.potter@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 22113031Sbrandon.potter@amd.com // doesn't map to any simulator fd: not a valid target fd 22213031Sbrandon.potter@amd.com return -EBADF; 22313031Sbrandon.potter@amd.com } 22413031Sbrandon.potter@amd.com 22513031Sbrandon.potter@amd.com switch (req) { 22613031Sbrandon.potter@amd.com case OS::TIOCISATTY: 22713031Sbrandon.potter@amd.com case OS::TIOCGETP: 22813031Sbrandon.potter@amd.com case OS::TIOCSETP: 229511SN/A case OS::TIOCSETN: 2301706SN/A case OS::TIOCSETC: 23111851Sbrandon.potter@amd.com case OS::TIOCGETC: 2321706SN/A case OS::TIOCGETS: 2331706SN/A case OS::TIOCGETA: 2341706SN/A return -ENOTTY; 2351706SN/A 23611851Sbrandon.potter@amd.com default: 2371706SN/A fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", fd, req, xc->readPC()); 2381706SN/A } 2391706SN/A} 2401706SN/A 24111851Sbrandon.potter@amd.com/// This struct is used to build an target-OS-dependent table that 2421706SN/A/// maps the target's open() flags to the host open() flags. 243511SN/Astruct OpenFlagTransTable { 2446703Svince@csl.cornell.edu int tgtFlag; //!< Target system flag value. 2456703Svince@csl.cornell.edu int hostFlag; //!< Corresponding host system flag value. 24611851Sbrandon.potter@amd.com}; 2476703Svince@csl.cornell.edu 2486685Stjones1@inf.ed.ac.uk 2496685Stjones1@inf.ed.ac.uk/// Target open() handler. 25011851Sbrandon.potter@amd.comtemplate <class OS> 2516685Stjones1@inf.ed.ac.ukint 2526685Stjones1@inf.ed.ac.ukopenFunc(SyscallDesc *desc, int callnum, Process *process, 2535513SMichael.Adler@intel.com ExecContext *xc) 2545513SMichael.Adler@intel.com{ 25511851Sbrandon.potter@amd.com std::string path; 2565513SMichael.Adler@intel.com 25711885Sbrandon.potter@amd.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 25811885Sbrandon.potter@amd.com return -EFAULT; 25911885Sbrandon.potter@amd.com 2605513SMichael.Adler@intel.com if (path == "/dev/sysdev0") { 2611999SN/A // This is a memory-mapped high-resolution timer device on Alpha. 2621999SN/A // We don't support it, so just punt. 26311851Sbrandon.potter@amd.com DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl; 2641999SN/A return -ENOENT; 26511885Sbrandon.potter@amd.com } 26611885Sbrandon.potter@amd.com 26711885Sbrandon.potter@amd.com int tgtFlags = xc->getSyscallArg(1); 2681999SN/A int mode = xc->getSyscallArg(2); 2691999SN/A int hostFlags = 0; 2701999SN/A 27111851Sbrandon.potter@amd.com // translate open flags 2721999SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 2733079Sstever@eecs.umich.edu if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 2743079Sstever@eecs.umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 27511851Sbrandon.potter@amd.com hostFlags |= OS::openFlagTable[i].hostFlag; 2763079Sstever@eecs.umich.edu } 27711908SBrandon.Potter@amd.com } 27811908SBrandon.Potter@amd.com 27911908SBrandon.Potter@amd.com // any target flags left? 28011908SBrandon.Potter@amd.com if (tgtFlags != 0) 28111875Sbrandon.potter@amd.com cerr << "Syscall: open: cannot decode flags: " << tgtFlags << endl; 2822093SN/A 28311851Sbrandon.potter@amd.com#ifdef __CYGWIN32__ 2842093SN/A hostFlags |= O_BINARY; 2852687Sksewell@umich.edu#endif 2862687Sksewell@umich.edu 28711851Sbrandon.potter@amd.com // open the file 2882687Sksewell@umich.edu int fd = open(path.c_str(), hostFlags, mode); 2892238SN/A 2902238SN/A return (fd == -1) ? -errno : process->open_fd(fd); 29111851Sbrandon.potter@amd.com} 2922238SN/A 29311908SBrandon.Potter@amd.com 29411908SBrandon.Potter@amd.com/// Target stat() handler. 29511908SBrandon.Potter@amd.comtemplate <class OS> 29611908SBrandon.Potter@amd.comint 29711908SBrandon.Potter@amd.comstatFunc(SyscallDesc *desc, int callnum, Process *process, 29811908SBrandon.Potter@amd.com ExecContext *xc) 29911908SBrandon.Potter@amd.com{ 30011908SBrandon.Potter@amd.com std::string path; 3012238SN/A 3022238SN/A if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 30311851Sbrandon.potter@amd.com return -EFAULT; 3042238SN/A 30513571Sbrandon.potter@amd.com struct stat hostBuf; 30613571Sbrandon.potter@amd.com int result = stat(path.c_str(), &hostBuf); 30713571Sbrandon.potter@amd.com 30813571Sbrandon.potter@amd.com if (result < 0) 30913568Sbrandon.potter@amd.com return -errno; 31013568Sbrandon.potter@amd.com 31113568Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 31213568Sbrandon.potter@amd.com 31313568Sbrandon.potter@amd.com return 0; 31413568Sbrandon.potter@amd.com} 31513568Sbrandon.potter@amd.com 31613568Sbrandon.potter@amd.com 31713568Sbrandon.potter@amd.com/// Target lstat() handler. 31813568Sbrandon.potter@amd.comtemplate <class OS> 31913568Sbrandon.potter@amd.comint 32013568Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 32113448Sciro.santilli@arm.com ExecContext *xc) 32213031Sbrandon.potter@amd.com{ 32313031Sbrandon.potter@amd.com std::string path; 32413031Sbrandon.potter@amd.com 32513448Sciro.santilli@arm.com if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) 32613031Sbrandon.potter@amd.com return -EFAULT; 32713539Sjavier.setoain@arm.com 32813539Sjavier.setoain@arm.com struct stat hostBuf; 32913539Sjavier.setoain@arm.com int result = lstat(path.c_str(), &hostBuf); 33013539Sjavier.setoain@arm.com 33113539Sjavier.setoain@arm.com if (result < 0) 33213539Sjavier.setoain@arm.com return -errno; 33313569Sbrandon.potter@amd.com 33413569Sbrandon.potter@amd.com OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 33513569Sbrandon.potter@amd.com 33613569Sbrandon.potter@amd.com return 0; 33713569Sbrandon.potter@amd.com} 33813569Sbrandon.potter@amd.com 33913569Sbrandon.potter@amd.com/// Target fstat() handler. 34013569Sbrandon.potter@amd.comtemplate <class OS> 34113569Sbrandon.potter@amd.comint 34213569Sbrandon.potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, Process *process, 34313569Sbrandon.potter@amd.com ExecContext *xc) 34413569Sbrandon.potter@amd.com{ 34513569Sbrandon.potter@amd.com int fd = process->sim_fd(xc->getSyscallArg(0)); 34613569Sbrandon.potter@amd.com 34713569Sbrandon.potter@amd.com // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd); 34813569Sbrandon.potter@amd.com 34913031Sbrandon.potter@amd.com if (fd < 0) 3502238SN/A return -EBADF; 35111851Sbrandon.potter@amd.com 3522238SN/A struct stat hostBuf; 3532238SN/A int result = fstat(fd, &hostBuf); 3542238SN/A 35511851Sbrandon.potter@amd.com if (result < 0) 3562238SN/A return -errno; 3572238SN/A 3582238SN/A OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 35911851Sbrandon.potter@amd.com 3602238SN/A return 0; 3612238SN/A} 3622238SN/A 36311851Sbrandon.potter@amd.com 3642238SN/A/// Target mmap() handler. 3652238SN/A/// 3662238SN/A/// We don't really handle mmap(). If the target is mmaping an 36711851Sbrandon.potter@amd.com/// anonymous region or /dev/zero, we can get away with doing basically 3682238SN/A/// nothing (since memory is initialized to zero and the simulator 3699455Smitch.hayenga+gem5@gmail.com/// doesn't really check addresses anyway). Always print a warning, 3709455Smitch.hayenga+gem5@gmail.com/// since this could be seriously broken if we're not mapping 37111851Sbrandon.potter@amd.com/// /dev/zero. 37210203SAli.Saidi@ARM.com// 37311851Sbrandon.potter@amd.com/// Someday we should explicitly check for /dev/zero in open, flag the 37411851Sbrandon.potter@amd.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to 3759455Smitch.hayenga+gem5@gmail.com/// anything else. 37613571Sbrandon.potter@amd.comtemplate <class OS> 37713571Sbrandon.potter@amd.comint 37813571Sbrandon.potter@amd.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 37913571Sbrandon.potter@amd.com{ 38013571Sbrandon.potter@amd.com Addr start = xc->getSyscallArg(0); 38113571Sbrandon.potter@amd.com uint64_t length = xc->getSyscallArg(1); 38213571Sbrandon.potter@amd.com // int prot = xc->getSyscallArg(2); 38313571Sbrandon.potter@amd.com int flags = xc->getSyscallArg(3); 38413571Sbrandon.potter@amd.com // int fd = p->sim_fd(xc->getSyscallArg(4)); 38513571Sbrandon.potter@amd.com // int offset = xc->getSyscallArg(5); 38613571Sbrandon.potter@amd.com 38713571Sbrandon.potter@amd.com if (start == 0) { 3889112Smarc.orr@gmail.com // user didn't give an address... pick one from our "mmap region" 38911906SBrandon.Potter@amd.com start = p->mmap_base; 39011906SBrandon.Potter@amd.com p->mmap_base += RoundUp<Addr>(length, VMPageSize); 3919112Smarc.orr@gmail.com } 3929112Smarc.orr@gmail.com 39311851Sbrandon.potter@amd.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 3949112Smarc.orr@gmail.com DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d. " 3959112Smarc.orr@gmail.com "This will break if not /dev/zero.", xc->getSyscallArg(4)); 39611911SBrandon.Potter@amd.com } 3979112Smarc.orr@gmail.com 39811911SBrandon.Potter@amd.com return start; 39911911SBrandon.Potter@amd.com} 40011911SBrandon.Potter@amd.com 40111911SBrandon.Potter@amd.com/// Target getrlimit() handler. 4029112Smarc.orr@gmail.comtemplate <class OS> 40311911SBrandon.Potter@amd.comint 40411911SBrandon.Potter@amd.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 40511911SBrandon.Potter@amd.com ExecContext *xc) 40611911SBrandon.Potter@amd.com{ 4079238Slluc.alvarez@bsc.es unsigned resource = xc->getSyscallArg(0); 4089112Smarc.orr@gmail.com TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 40911911SBrandon.Potter@amd.com 4109112Smarc.orr@gmail.com switch (resource) { 41111911SBrandon.Potter@amd.com case OS::RLIMIT_STACK: 41211911SBrandon.Potter@amd.com // max stack size in bytes: make up a number (2MB for now) 41311911SBrandon.Potter@amd.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 41411911SBrandon.Potter@amd.com break; 41511911SBrandon.Potter@amd.com 4169112Smarc.orr@gmail.com default: 41711911SBrandon.Potter@amd.com cerr << "getrlimitFunc: unimplemented resource " << resource << endl; 41811911SBrandon.Potter@amd.com abort(); 41911911SBrandon.Potter@amd.com break; 42011911SBrandon.Potter@amd.com } 42111911SBrandon.Potter@amd.com 42211911SBrandon.Potter@amd.com rlp.copyOut(xc->mem); 4239112Smarc.orr@gmail.com return 0; 4249112Smarc.orr@gmail.com} 42511911SBrandon.Potter@amd.com 42611911SBrandon.Potter@amd.com/// A readable name for 1,000,000, for converting microseconds to seconds. 4279112Smarc.orr@gmail.comconst int one_million = 1000000; 42811911SBrandon.Potter@amd.com 42911911SBrandon.Potter@amd.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 4309112Smarc.orr@gmail.com/// by my reckoning. We want to keep this a constant (not use the 4319112Smarc.orr@gmail.com/// real-world time) to keep simulations repeatable. 43211911SBrandon.Potter@amd.comconst unsigned seconds_since_epoch = 1000000000; 43311911SBrandon.Potter@amd.com 4349112Smarc.orr@gmail.com/// Helper function to convert current elapsed time to seconds and 4359112Smarc.orr@gmail.com/// microseconds. 4362238SN/Atemplate <class T1, class T2> 4372238SN/Avoid 4382238SN/AgetElapsedTime(T1 &sec, T2 &usec) 4392238SN/A{ 44011851Sbrandon.potter@amd.com int cycles_per_usec = ticksPerSecond / one_million; 4412238SN/A 4422238SN/A int elapsed_usecs = curTick / cycles_per_usec; 4432238SN/A sec = elapsed_usecs / one_million; 44411851Sbrandon.potter@amd.com usec = elapsed_usecs % one_million; 4452238SN/A} 4462238SN/A 4472238SN/A 44811851Sbrandon.potter@amd.com/// Target gettimeofday() handler. 4492238SN/Atemplate <class OS> 4502238SN/Aint 4512238SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 45211851Sbrandon.potter@amd.com ExecContext *xc) 4532238SN/A{ 4542238SN/A TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 4551354SN/A 4561354SN/A getElapsedTime(tp->tv_sec, tp->tv_usec); 45710796Sbrandon.potter@amd.com tp->tv_sec += seconds_since_epoch; 45810796Sbrandon.potter@amd.com 4591354SN/A tp.copyOut(xc->mem); 4601354SN/A 4611354SN/A return 0; 4621354SN/A} 4631354SN/A 4641354SN/A 4651354SN/A/// Target getrusage() function. 4661354SN/Atemplate <class OS> 4671354SN/Aint 4681354SN/AgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 46910796Sbrandon.potter@amd.com ExecContext *xc) 4701354SN/A{ 47110796Sbrandon.potter@amd.com int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 4721354SN/A TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 4731354SN/A 4741354SN/A if (who != OS::RUSAGE_SELF) { 4751354SN/A // don't really handle THREAD or CHILDREN, but just warn and 47610796Sbrandon.potter@amd.com // plow ahead 47710796Sbrandon.potter@amd.com DCOUT(SyscallWarnings) 47810796Sbrandon.potter@amd.com << "Warning: getrusage() only supports RUSAGE_SELF." 47910796Sbrandon.potter@amd.com << " Parameter " << who << " ignored." << endl; 48010796Sbrandon.potter@amd.com } 48110796Sbrandon.potter@amd.com 48210796Sbrandon.potter@amd.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 48310796Sbrandon.potter@amd.com rup->ru_stime.tv_sec = 0; 48410796Sbrandon.potter@amd.com rup->ru_stime.tv_usec = 0; 48510796Sbrandon.potter@amd.com rup->ru_maxrss = 0; 48610796Sbrandon.potter@amd.com rup->ru_ixrss = 0; 487360SN/A rup->ru_idrss = 0; 488360SN/A rup->ru_isrss = 0; 489360SN/A rup->ru_minflt = 0; 490360SN/A rup->ru_majflt = 0; 491360SN/A rup->ru_nswap = 0; 492360SN/A rup->ru_inblock = 0; 493360SN/A rup->ru_oublock = 0; 49411759Sbrandon.potter@amd.com rup->ru_msgsnd = 0; 4953113Sgblack@eecs.umich.edu rup->ru_msgrcv = 0; 4963113Sgblack@eecs.umich.edu rup->ru_nsignals = 0; 4973113Sgblack@eecs.umich.edu rup->ru_nvcsw = 0; 4983113Sgblack@eecs.umich.edu rup->ru_nivcsw = 0; 4993113Sgblack@eecs.umich.edu 5003113Sgblack@eecs.umich.edu rup.copyOut(xc->mem); 5013113Sgblack@eecs.umich.edu 5023113Sgblack@eecs.umich.edu return 0; 5033113Sgblack@eecs.umich.edu} 5043113Sgblack@eecs.umich.edu 5053113Sgblack@eecs.umich.edu 5063113Sgblack@eecs.umich.edu 5073113Sgblack@eecs.umich.edu#endif // __SYSCALL_EMUL_HH__ 50812032Sandreas.sandberg@arm.com