syscall_emul.hh revision 2764
17405SAli.Saidi@ARM.com/* 212667Schuan.zhu@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147405SAli.Saidi@ARM.com * this software without specific prior written permission. 157405SAli.Saidi@ARM.com * 167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277405SAli.Saidi@ARM.com * 287405SAli.Saidi@ARM.com * Authors: Steve Reinhardt 297405SAli.Saidi@ARM.com * Kevin Lim 307405SAli.Saidi@ARM.com * Korey Sewell 317405SAli.Saidi@ARM.com */ 327405SAli.Saidi@ARM.com 337405SAli.Saidi@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__ 347405SAli.Saidi@ARM.com#define __SIM_SYSCALL_EMUL_HH__ 357405SAli.Saidi@ARM.com 367405SAli.Saidi@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 377405SAli.Saidi@ARM.com defined(__FreeBSD__) || defined(__CYGWIN__)) 387405SAli.Saidi@ARM.com 397405SAli.Saidi@ARM.com/// 407405SAli.Saidi@ARM.com/// @file syscall_emul.hh 417405SAli.Saidi@ARM.com/// 4210461SAndreas.Sandberg@ARM.com/// This file defines objects used to emulate syscalls from the target 439050Schander.sudanthi@arm.com/// application on the host machine. 4412406Sgabeblack@google.com 4512605Sgiacomo.travaglini@arm.com#include <errno.h> 4611793Sbrandon.potter@amd.com#include <string> 478887Sgeoffrey.blake@arm.com#ifdef __CYGWIN32__ 488232Snate@binkert.org#include <sys/fcntl.h> // for O_BINARY 498232Snate@binkert.org#endif 5010844Sandreas.sandberg@arm.com#include <sys/uio.h> 519384SAndreas.Sandberg@arm.com 527678Sgblack@eecs.umich.edu#include "arch/isa_traits.hh" // for Addr 538059SAli.Saidi@ARM.com#include "base/chunk_generator.hh" 548284SAli.Saidi@ARM.com#include "base/intmath.hh" // for RoundUp 557405SAli.Saidi@ARM.com#include "base/misc.hh" 567405SAli.Saidi@ARM.com#include "base/trace.hh" 577405SAli.Saidi@ARM.com#include "cpu/base.hh" 587405SAli.Saidi@ARM.com#include "cpu/thread_context.hh" 599384SAndreas.Sandberg@arm.com#include "mem/translating_port.hh" 6010461SAndreas.Sandberg@ARM.com#include "mem/page_table.hh" 6110461SAndreas.Sandberg@ARM.com#include "sim/process.hh" 6211165SRekai.GonzalezAlberquilla@arm.com 6312109SRekai.GonzalezAlberquilla@arm.com/// 6412714Sgiacomo.travaglini@arm.com/// System call descriptor. 6512714Sgiacomo.travaglini@arm.com/// 669384SAndreas.Sandberg@arm.comclass SyscallDesc { 6711770SCurtis.Dunham@arm.com 6810037SARM gem5 Developers public: 6910461SAndreas.Sandberg@ARM.com 7010461SAndreas.Sandberg@ARM.com /// Typedef for target syscall handler functions. 7110461SAndreas.Sandberg@ARM.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 7210461SAndreas.Sandberg@ARM.com Process *, ThreadContext *); 7310461SAndreas.Sandberg@ARM.com 7410461SAndreas.Sandberg@ARM.com const char *name; //!< Syscall name (e.g., "open"). 7510609Sandreas.sandberg@arm.com FuncPtr funcPtr; //!< Pointer to emulation function. 7610609Sandreas.sandberg@arm.com int flags; //!< Flags (see Flags enum). 7710609Sandreas.sandberg@arm.com 7810037SARM gem5 Developers /// Flag values for controlling syscall behavior. 7910037SARM gem5 Developers enum Flags { 8010037SARM gem5 Developers /// Don't set return regs according to funcPtr return value. 8110037SARM gem5 Developers /// Used for syscalls with non-standard return conventions 8211771SCurtis.Dunham@arm.com /// that explicitly set the ThreadContext regs (e.g., 8310037SARM gem5 Developers /// sigreturn). 8410037SARM gem5 Developers SuppressReturnValue = 1 8513173Sgiacomo.travaglini@arm.com }; 8610037SARM gem5 Developers 8710037SARM gem5 Developers /// Constructor. 8813114Sgiacomo.travaglini@arm.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 8910037SARM gem5 Developers : name(_name), funcPtr(_funcPtr), flags(_flags) 9011771SCurtis.Dunham@arm.com { 9110037SARM gem5 Developers } 9213173Sgiacomo.travaglini@arm.com 9310037SARM gem5 Developers /// Emulate the syscall. Public interface for calling through funcPtr. 9413114Sgiacomo.travaglini@arm.com void doSyscall(int callnum, Process *proc, ThreadContext *tc); 9510037SARM gem5 Developers}; 9610037SARM gem5 Developers 9712477SCurtis.Dunham@arm.com 9810037SARM gem5 Developersclass BaseBufferArg { 9910037SARM gem5 Developers 1009384SAndreas.Sandberg@arm.com public: 1019384SAndreas.Sandberg@arm.com 1029384SAndreas.Sandberg@arm.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 10312479SCurtis.Dunham@arm.com { 10412479SCurtis.Dunham@arm.com bufPtr = new uint8_t[size]; 1059384SAndreas.Sandberg@arm.com // clear out buffer: in case we only partially populate this, 1069384SAndreas.Sandberg@arm.com // and then do a copyOut(), we want to make sure we don't 1079384SAndreas.Sandberg@arm.com // introduce any random junk into the simulated address space 1089384SAndreas.Sandberg@arm.com memset(bufPtr, 0, size); 1099384SAndreas.Sandberg@arm.com } 1109384SAndreas.Sandberg@arm.com 1117427Sgblack@eecs.umich.edu virtual ~BaseBufferArg() { delete [] bufPtr; } 1127427Sgblack@eecs.umich.edu 1137427Sgblack@eecs.umich.edu // 1149385SAndreas.Sandberg@arm.com // copy data into simulator space (read from target memory) 1159385SAndreas.Sandberg@arm.com // 1167427Sgblack@eecs.umich.edu virtual bool copyIn(TranslatingPort *memport) 1177427Sgblack@eecs.umich.edu { 11810037SARM gem5 Developers memport->readBlob(addr, bufPtr, size); 11913114Sgiacomo.travaglini@arm.com return true; // no EFAULT detection for now 12010037SARM gem5 Developers } 12113114Sgiacomo.travaglini@arm.com 12213114Sgiacomo.travaglini@arm.com // 12313114Sgiacomo.travaglini@arm.com // copy data out of simulator space (write to target memory) 12413114Sgiacomo.travaglini@arm.com // 12513114Sgiacomo.travaglini@arm.com virtual bool copyOut(TranslatingPort *memport) 12612690Sgiacomo.travaglini@arm.com { 12710037SARM gem5 Developers memport->writeBlob(addr, bufPtr, size); 1287427Sgblack@eecs.umich.edu return true; // no EFAULT detection for now 1297427Sgblack@eecs.umich.edu } 13010037SARM gem5 Developers 1317427Sgblack@eecs.umich.edu protected: 1327427Sgblack@eecs.umich.edu Addr addr; 1337427Sgblack@eecs.umich.edu int size; 1347427Sgblack@eecs.umich.edu uint8_t *bufPtr; 1357427Sgblack@eecs.umich.edu}; 1367427Sgblack@eecs.umich.edu 1377427Sgblack@eecs.umich.edu 1387427Sgblack@eecs.umich.educlass BufferArg : public BaseBufferArg 1397427Sgblack@eecs.umich.edu{ 1407427Sgblack@eecs.umich.edu public: 1417427Sgblack@eecs.umich.edu BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1427427Sgblack@eecs.umich.edu void *bufferPtr() { return bufPtr; } 1437427Sgblack@eecs.umich.edu}; 1447427Sgblack@eecs.umich.edu 1457427Sgblack@eecs.umich.edutemplate <class T> 1467427Sgblack@eecs.umich.educlass TypedBufferArg : public BaseBufferArg 1477427Sgblack@eecs.umich.edu{ 1487427Sgblack@eecs.umich.edu public: 1497427Sgblack@eecs.umich.edu // user can optionally specify a specific number of bytes to 1507427Sgblack@eecs.umich.edu // allocate to deal with those structs that have variable-size 1517427Sgblack@eecs.umich.edu // arrays at the end 1527427Sgblack@eecs.umich.edu TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1537427Sgblack@eecs.umich.edu : BaseBufferArg(_addr, _size) 1547436Sdam.sunwoo@arm.com { } 1557436Sdam.sunwoo@arm.com 15610037SARM gem5 Developers // type case 15710037SARM gem5 Developers operator T*() { return (T *)bufPtr; } 1587436Sdam.sunwoo@arm.com 1597436Sdam.sunwoo@arm.com // dereference operators 1607436Sdam.sunwoo@arm.com T &operator*() { return *((T *)bufPtr); } 1617436Sdam.sunwoo@arm.com T* operator->() { return (T *)bufPtr; } 1627436Sdam.sunwoo@arm.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 1637436Sdam.sunwoo@arm.com}; 1647436Sdam.sunwoo@arm.com 1657436Sdam.sunwoo@arm.com////////////////////////////////////////////////////////////////////// 1667436Sdam.sunwoo@arm.com// 1677436Sdam.sunwoo@arm.com// The following emulation functions are generic enough that they 1687436Sdam.sunwoo@arm.com// don't need to be recompiled for different emulated OS's. They are 1697436Sdam.sunwoo@arm.com// defined in sim/syscall_emul.cc. 17013393Sgiacomo.travaglini@arm.com// 17110037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 1727436Sdam.sunwoo@arm.com 1737436Sdam.sunwoo@arm.com 1747436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we haven't thought about. 1757436Sdam.sunwoo@arm.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1767436Sdam.sunwoo@arm.com Process *p, ThreadContext *tc); 1777436Sdam.sunwoo@arm.com 1787436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we never intend to 1797436Sdam.sunwoo@arm.com/// implement (signal handling, etc.) and should not affect the correct 1807436Sdam.sunwoo@arm.com/// behavior of the program. Print a warning only if the appropriate 1817436Sdam.sunwoo@arm.com/// trace flag is enabled. Return success to the target program. 1827436Sdam.sunwoo@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1837436Sdam.sunwoo@arm.com Process *p, ThreadContext *tc); 1847436Sdam.sunwoo@arm.com 1857436Sdam.sunwoo@arm.com/// Target exit() handler: terminate simulation. 1867436Sdam.sunwoo@arm.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 1877436Sdam.sunwoo@arm.com Process *p, ThreadContext *tc); 18813393Sgiacomo.travaglini@arm.com 18913393Sgiacomo.travaglini@arm.com/// Target getpagesize() handler. 19013393Sgiacomo.travaglini@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 19113393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 19213393Sgiacomo.travaglini@arm.com 19313393Sgiacomo.travaglini@arm.com/// Target obreak() handler: set brk address. 19413393Sgiacomo.travaglini@arm.comSyscallReturn obreakFunc(SyscallDesc *desc, int num, 19513393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 19613393Sgiacomo.travaglini@arm.com 19713393Sgiacomo.travaglini@arm.com/// Target close() handler. 19813393Sgiacomo.travaglini@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 19913393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 20013393Sgiacomo.travaglini@arm.com 20113393Sgiacomo.travaglini@arm.com/// Target read() handler. 20213393Sgiacomo.travaglini@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num, 20313393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 20413396Sgiacomo.travaglini@arm.com 20513396Sgiacomo.travaglini@arm.com/// Target write() handler. 20613396Sgiacomo.travaglini@arm.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 20713396Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 20813393Sgiacomo.travaglini@arm.com 20913393Sgiacomo.travaglini@arm.com/// Target lseek() handler. 21013393Sgiacomo.travaglini@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 21113393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 21213393Sgiacomo.travaglini@arm.com 21313393Sgiacomo.travaglini@arm.com/// Target munmap() handler. 21413393Sgiacomo.travaglini@arm.comSyscallReturn munmapFunc(SyscallDesc *desc, int num, 21513393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 21613393Sgiacomo.travaglini@arm.com 21713393Sgiacomo.travaglini@arm.com/// Target gethostname() handler. 21813393Sgiacomo.travaglini@arm.comSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 21913393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 22013393Sgiacomo.travaglini@arm.com 22113393Sgiacomo.travaglini@arm.com/// Target unlink() handler. 22213393Sgiacomo.travaglini@arm.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 22313393Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 22413393Sgiacomo.travaglini@arm.com 22513393Sgiacomo.travaglini@arm.com/// Target rename() handler. 2267644Sali.saidi@arm.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 2278147SAli.Saidi@ARM.com Process *p, ThreadContext *tc); 2289385SAndreas.Sandberg@arm.com 2299385SAndreas.Sandberg@arm.com 23010037SARM gem5 Developers/// Target truncate() handler. 23110037SARM gem5 DevelopersSyscallReturn truncateFunc(SyscallDesc *desc, int num, 23210037SARM gem5 Developers Process *p, ThreadContext *tc); 23310037SARM gem5 Developers 23410037SARM gem5 Developers 23510037SARM gem5 Developers/// Target ftruncate() handler. 23610037SARM gem5 DevelopersSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 23710037SARM gem5 Developers Process *p, ThreadContext *tc); 23810037SARM gem5 Developers 23910037SARM gem5 Developers 24010037SARM gem5 Developers/// Target chown() handler. 24110037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num, 24210037SARM gem5 Developers Process *p, ThreadContext *tc); 24310037SARM gem5 Developers 24410037SARM gem5 Developers 24510037SARM gem5 Developers/// Target fchown() handler. 2468147SAli.Saidi@ARM.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2477427Sgblack@eecs.umich.edu Process *p, ThreadContext *tc); 2487427Sgblack@eecs.umich.edu 2497427Sgblack@eecs.umich.edu/// Target fnctl() handler. 25010037SARM gem5 DevelopersSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 25110037SARM gem5 Developers Process *process, ThreadContext *tc); 25210037SARM gem5 Developers 25310037SARM gem5 Developers/// Target fcntl64() handler. 25413396Sgiacomo.travaglini@arm.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 25510037SARM gem5 Developers Process *process, ThreadContext *tc); 25610037SARM gem5 Developers 25710037SARM gem5 Developers/// Target setuid() handler. 25810037SARM gem5 DevelopersSyscallReturn setuidFunc(SyscallDesc *desc, int num, 25910037SARM gem5 Developers Process *p, ThreadContext *tc); 26010037SARM gem5 Developers 26110037SARM gem5 Developers/// Target getpid() handler. 26210037SARM gem5 DevelopersSyscallReturn getpidFunc(SyscallDesc *desc, int num, 26310037SARM gem5 Developers Process *p, ThreadContext *tc); 26410037SARM gem5 Developers 26510037SARM gem5 Developers/// Target getuid() handler. 26610037SARM gem5 DevelopersSyscallReturn getuidFunc(SyscallDesc *desc, int num, 26710037SARM gem5 Developers Process *p, ThreadContext *tc); 26810037SARM gem5 Developers 26910037SARM gem5 Developers/// Target getgid() handler. 27010037SARM gem5 DevelopersSyscallReturn getgidFunc(SyscallDesc *desc, int num, 27110037SARM gem5 Developers Process *p, ThreadContext *tc); 27210037SARM gem5 Developers 27310037SARM gem5 Developers/// Target getppid() handler. 27410037SARM gem5 DevelopersSyscallReturn getppidFunc(SyscallDesc *desc, int num, 27510037SARM gem5 Developers Process *p, ThreadContext *tc); 27610037SARM gem5 Developers 27710037SARM gem5 Developers/// Target geteuid() handler. 27810037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 27910037SARM gem5 Developers Process *p, ThreadContext *tc); 28010037SARM gem5 Developers 28110037SARM gem5 Developers/// Target getegid() handler. 28210037SARM gem5 DevelopersSyscallReturn getegidFunc(SyscallDesc *desc, int num, 28310037SARM gem5 Developers Process *p, ThreadContext *tc); 28410037SARM gem5 Developers 28510037SARM gem5 Developers 28611770SCurtis.Dunham@arm.com 28710037SARM gem5 Developers/// Pseudo Funcs - These functions use a different return convension, 28811574SCurtis.Dunham@arm.com/// returning a second value in a register other than the normal return register 28911770SCurtis.Dunham@arm.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 29011770SCurtis.Dunham@arm.com Process *process, ThreadContext *tc); 29110037SARM gem5 Developers 29211770SCurtis.Dunham@arm.com/// Target getpidPseudo() handler. 29311770SCurtis.Dunham@arm.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 29410037SARM gem5 Developers Process *p, ThreadContext *tc); 29510037SARM gem5 Developers 29610037SARM gem5 Developers/// Target getuidPseudo() handler. 29713114Sgiacomo.travaglini@arm.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 29810037SARM gem5 Developers Process *p, ThreadContext *tc); 29913114Sgiacomo.travaglini@arm.com 30013114Sgiacomo.travaglini@arm.com/// Target getgidPseudo() handler. 30113114Sgiacomo.travaglini@arm.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 30213114Sgiacomo.travaglini@arm.com Process *p, ThreadContext *tc); 30313114Sgiacomo.travaglini@arm.com 30413114Sgiacomo.travaglini@arm.com 30513114Sgiacomo.travaglini@arm.com/// This struct is used to build an target-OS-dependent table that 30613114Sgiacomo.travaglini@arm.com/// maps the target's open() flags to the host open() flags. 30713114Sgiacomo.travaglini@arm.comstruct OpenFlagTransTable { 30813114Sgiacomo.travaglini@arm.com int tgtFlag; //!< Target system flag value. 30913114Sgiacomo.travaglini@arm.com int hostFlag; //!< Corresponding host system flag value. 31013114Sgiacomo.travaglini@arm.com}; 31113114Sgiacomo.travaglini@arm.com 31213114Sgiacomo.travaglini@arm.com 31313114Sgiacomo.travaglini@arm.com 31413114Sgiacomo.travaglini@arm.com/// A readable name for 1,000,000, for converting microseconds to seconds. 31513114Sgiacomo.travaglini@arm.comconst int one_million = 1000000; 31613114Sgiacomo.travaglini@arm.com 31713114Sgiacomo.travaglini@arm.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 31813114Sgiacomo.travaglini@arm.com/// by my reckoning. We want to keep this a constant (not use the 31913114Sgiacomo.travaglini@arm.com/// real-world time) to keep simulations repeatable. 32013114Sgiacomo.travaglini@arm.comconst unsigned seconds_since_epoch = 1000000000; 32113114Sgiacomo.travaglini@arm.com 32213114Sgiacomo.travaglini@arm.com/// Helper function to convert current elapsed time to seconds and 32310037SARM gem5 Developers/// microseconds. 32410037SARM gem5 Developerstemplate <class T1, class T2> 32510037SARM gem5 Developersvoid 32610461SAndreas.Sandberg@ARM.comgetElapsedTime(T1 &sec, T2 &usec) 32710461SAndreas.Sandberg@ARM.com{ 32810461SAndreas.Sandberg@ARM.com int elapsed_usecs = curTick / Clock::Int::us; 32910461SAndreas.Sandberg@ARM.com sec = elapsed_usecs / one_million; 33010037SARM gem5 Developers usec = elapsed_usecs % one_million; 33110037SARM gem5 Developers} 33210037SARM gem5 Developers 33310037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 33410037SARM gem5 Developers// 33513116Sgiacomo.travaglini@arm.com// The following emulation functions are generic, but need to be 33610037SARM gem5 Developers// templated to account for differences in types, constants, etc. 33710461SAndreas.Sandberg@ARM.com// 33810461SAndreas.Sandberg@ARM.com////////////////////////////////////////////////////////////////////// 33910461SAndreas.Sandberg@ARM.com 34010461SAndreas.Sandberg@ARM.com/// Target ioctl() handler. For the most part, programs call ioctl() 34110461SAndreas.Sandberg@ARM.com/// only to find out if their stdout is a tty, to determine whether to 34210037SARM gem5 Developers/// do line or block buffering. 34310037SARM gem5 Developerstemplate <class OS> 34410037SARM gem5 DevelopersSyscallReturn 34510037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, Process *process, 34610037SARM gem5 Developers ThreadContext *tc) 34711574SCurtis.Dunham@arm.com{ 34810037SARM gem5 Developers int fd = tc->getSyscallArg(0); 34910037SARM gem5 Developers unsigned req = tc->getSyscallArg(1); 35010037SARM gem5 Developers 35111574SCurtis.Dunham@arm.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 35210037SARM gem5 Developers 35310037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 35410037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 35510037SARM gem5 Developers return -EBADF; 35610037SARM gem5 Developers } 35710037SARM gem5 Developers 35810037SARM gem5 Developers switch (req) { 35913114Sgiacomo.travaglini@arm.com case OS::TIOCISATTY: 36013173Sgiacomo.travaglini@arm.com case OS::TIOCGETP: 36113173Sgiacomo.travaglini@arm.com case OS::TIOCSETP: 36213173Sgiacomo.travaglini@arm.com case OS::TIOCSETN: 36313173Sgiacomo.travaglini@arm.com case OS::TIOCSETC: 36410037SARM gem5 Developers case OS::TIOCGETC: 36510037SARM gem5 Developers case OS::TIOCGETS: 36612972Sandreas.sandberg@arm.com case OS::TIOCGETA: 36712972Sandreas.sandberg@arm.com return -ENOTTY; 36812972Sandreas.sandberg@arm.com 36912972Sandreas.sandberg@arm.com default: 37012972Sandreas.sandberg@arm.com fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 37112972Sandreas.sandberg@arm.com fd, req, tc->readPC()); 37212972Sandreas.sandberg@arm.com } 37312972Sandreas.sandberg@arm.com} 3747405SAli.Saidi@ARM.com 37510035Sandreas.hansson@arm.com/// Target open() handler. 3767405SAli.Saidi@ARM.comtemplate <class OS> 3777405SAli.Saidi@ARM.comSyscallReturn 3787614Sminkyu.jeong@arm.comopenFunc(SyscallDesc *desc, int callnum, Process *process, 37912478SCurtis.Dunham@arm.com ThreadContext *tc) 38012478SCurtis.Dunham@arm.com{ 38112478SCurtis.Dunham@arm.com std::string path; 38212478SCurtis.Dunham@arm.com 38312478SCurtis.Dunham@arm.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 38412478SCurtis.Dunham@arm.com return -EFAULT; 38512478SCurtis.Dunham@arm.com 38612478SCurtis.Dunham@arm.com if (path == "/dev/sysdev0") { 38712478SCurtis.Dunham@arm.com // This is a memory-mapped high-resolution timer device on Alpha. 38812478SCurtis.Dunham@arm.com // We don't support it, so just punt. 38912478SCurtis.Dunham@arm.com warn("Ignoring open(%s, ...)\n", path); 39012478SCurtis.Dunham@arm.com return -ENOENT; 39112478SCurtis.Dunham@arm.com } 39212478SCurtis.Dunham@arm.com 39312478SCurtis.Dunham@arm.com int tgtFlags = tc->getSyscallArg(1); 39412478SCurtis.Dunham@arm.com int mode = tc->getSyscallArg(2); 3957405SAli.Saidi@ARM.com int hostFlags = 0; 3967405SAli.Saidi@ARM.com 3977405SAli.Saidi@ARM.com // translate open flags 3987405SAli.Saidi@ARM.com for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 3997405SAli.Saidi@ARM.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 4007405SAli.Saidi@ARM.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 40110037SARM gem5 Developers hostFlags |= OS::openFlagTable[i].hostFlag; 40210037SARM gem5 Developers } 40310037SARM gem5 Developers } 4049050Schander.sudanthi@arm.com 4057405SAli.Saidi@ARM.com // any target flags left? 40610037SARM gem5 Developers if (tgtFlags != 0) 40710037SARM gem5 Developers warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 4087720Sgblack@eecs.umich.edu 4097720Sgblack@eecs.umich.edu#ifdef __CYGWIN32__ 4107405SAli.Saidi@ARM.com hostFlags |= O_BINARY; 4117405SAli.Saidi@ARM.com#endif 4127757SAli.Saidi@ARM.com 41310037SARM gem5 Developers DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 41410037SARM gem5 Developers 41510037SARM gem5 Developers // open the file 41610037SARM gem5 Developers int fd = open(path.c_str(), hostFlags, mode); 41710037SARM gem5 Developers 41810037SARM gem5 Developers return (fd == -1) ? -errno : process->alloc_fd(fd); 41910037SARM gem5 Developers} 42010037SARM gem5 Developers 42110037SARM gem5 Developers 42210037SARM gem5 Developers/// Target chmod() handler. 42310037SARM gem5 Developerstemplate <class OS> 42410037SARM gem5 DevelopersSyscallReturn 42510037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, Process *process, 42610037SARM gem5 Developers ThreadContext *tc) 42710037SARM gem5 Developers{ 42810037SARM gem5 Developers std::string path; 42910037SARM gem5 Developers 43010037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 43110037SARM gem5 Developers return -EFAULT; 43210037SARM gem5 Developers 43310037SARM gem5 Developers uint32_t mode = tc->getSyscallArg(1); 43410037SARM gem5 Developers mode_t hostMode = 0; 43510037SARM gem5 Developers 43610037SARM gem5 Developers // XXX translate mode flags via OS::something??? 43710037SARM gem5 Developers hostMode = mode; 43810037SARM gem5 Developers 43910037SARM gem5 Developers // do the chmod 44010037SARM gem5 Developers int result = chmod(path.c_str(), hostMode); 44110037SARM gem5 Developers if (result < 0) 44210037SARM gem5 Developers return -errno; 44310037SARM gem5 Developers 44410037SARM gem5 Developers return 0; 44510037SARM gem5 Developers} 44612667Schuan.zhu@arm.com 44710037SARM gem5 Developers 44810037SARM gem5 Developers/// Target fchmod() handler. 44910037SARM gem5 Developerstemplate <class OS> 45010037SARM gem5 DevelopersSyscallReturn 45110037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, Process *process, 45210037SARM gem5 Developers ThreadContext *tc) 45310037SARM gem5 Developers{ 45410037SARM gem5 Developers int fd = tc->getSyscallArg(0); 45510037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 45610037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 45710037SARM gem5 Developers return -EBADF; 45810037SARM gem5 Developers } 4598284SAli.Saidi@ARM.com 46010037SARM gem5 Developers uint32_t mode = tc->getSyscallArg(1); 46110037SARM gem5 Developers mode_t hostMode = 0; 46210037SARM gem5 Developers 46310037SARM gem5 Developers // XXX translate mode flags via OS::someting??? 4649050Schander.sudanthi@arm.com hostMode = mode; 46510037SARM gem5 Developers 46610037SARM gem5 Developers // do the fchmod 46710037SARM gem5 Developers int result = fchmod(process->sim_fd(fd), hostMode); 46810037SARM gem5 Developers if (result < 0) 46910037SARM gem5 Developers return -errno; 47010037SARM gem5 Developers 47110037SARM gem5 Developers return 0; 47210037SARM gem5 Developers} 47310037SARM gem5 Developers 47410037SARM gem5 Developers 47510037SARM gem5 Developers/// Target stat() handler. 47610037SARM gem5 Developerstemplate <class OS> 47710037SARM gem5 DevelopersSyscallReturn 47810037SARM gem5 DevelopersstatFunc(SyscallDesc *desc, int callnum, Process *process, 47910037SARM gem5 Developers ThreadContext *tc) 48010037SARM gem5 Developers{ 48110037SARM gem5 Developers std::string path; 48210037SARM gem5 Developers 4839050Schander.sudanthi@arm.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 4848284SAli.Saidi@ARM.com return -EFAULT; 48510037SARM gem5 Developers 48610037SARM gem5 Developers struct stat hostBuf; 48710037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 48810037SARM gem5 Developers 48910037SARM gem5 Developers if (result < 0) 49010037SARM gem5 Developers return -errno; 49110037SARM gem5 Developers 4927405SAli.Saidi@ARM.com OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 4937731SAli.Saidi@ARM.com 4948468Swade.walker@arm.com return 0; 4958468Swade.walker@arm.com} 4968468Swade.walker@arm.com 4977405SAli.Saidi@ARM.com 4987731SAli.Saidi@ARM.com/// Target fstat64() handler. 4997405SAli.Saidi@ARM.comtemplate <class OS> 5007405SAli.Saidi@ARM.comSyscallReturn 50111809Sbaz21@cam.ac.ukfstat64Func(SyscallDesc *desc, int callnum, Process *process, 50211809Sbaz21@cam.ac.uk ThreadContext *tc) 5039130Satgutier@umich.edu{ 5049130Satgutier@umich.edu int fd = tc->getSyscallArg(0); 5059130Satgutier@umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 5069130Satgutier@umich.edu // doesn't map to any simulator fd: not a valid target fd 5079814Sandreas.hansson@arm.com return -EBADF; 5089130Satgutier@umich.edu } 5099130Satgutier@umich.edu 5109130Satgutier@umich.edu#if NO_STAT64 5119130Satgutier@umich.edu struct stat hostBuf; 5129130Satgutier@umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 5139130Satgutier@umich.edu#else 5149130Satgutier@umich.edu struct stat64 hostBuf; 5159130Satgutier@umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 5169130Satgutier@umich.edu#endif 5179130Satgutier@umich.edu 5189130Satgutier@umich.edu if (result < 0) 5199130Satgutier@umich.edu return -errno; 5209130Satgutier@umich.edu 5219130Satgutier@umich.edu OS::copyOutStat64Buf(tc->getMemPort(), fd, tc->getSyscallArg(1), &hostBuf); 5229130Satgutier@umich.edu 5239130Satgutier@umich.edu return 0; 5249130Satgutier@umich.edu} 5259130Satgutier@umich.edu 5269130Satgutier@umich.edu 5279130Satgutier@umich.edu/// Target lstat() handler. 5289130Satgutier@umich.edutemplate <class OS> 5299130Satgutier@umich.eduSyscallReturn 5307583SAli.Saidi@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process, 5317583SAli.Saidi@arm.com ThreadContext *tc) 5327583SAli.Saidi@arm.com{ 53310461SAndreas.Sandberg@ARM.com std::string path; 53410461SAndreas.Sandberg@ARM.com 53510461SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 53610461SAndreas.Sandberg@ARM.com return -EFAULT; 53710461SAndreas.Sandberg@ARM.com 53810461SAndreas.Sandberg@ARM.com struct stat hostBuf; 53910461SAndreas.Sandberg@ARM.com int result = lstat(path.c_str(), &hostBuf); 5408302SAli.Saidi@ARM.com 5418302SAli.Saidi@ARM.com if (result < 0) 5427783SGiacomo.Gabrielli@arm.com return -errno; 5437783SGiacomo.Gabrielli@arm.com 5447783SGiacomo.Gabrielli@arm.com OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 5457783SGiacomo.Gabrielli@arm.com 54610037SARM gem5 Developers return 0; 54710037SARM gem5 Developers} 54810037SARM gem5 Developers 54910037SARM gem5 Developers/// Target lstat64() handler. 55010037SARM gem5 Developerstemplate <class OS> 55110037SARM gem5 DevelopersSyscallReturn 55210037SARM gem5 Developerslstat64Func(SyscallDesc *desc, int callnum, Process *process, 55310037SARM gem5 Developers ThreadContext *tc) 55410037SARM gem5 Developers{ 55510037SARM gem5 Developers std::string path; 55610037SARM gem5 Developers 55710037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 55810037SARM gem5 Developers return -EFAULT; 55910037SARM gem5 Developers 56010037SARM gem5 Developers#if NO_STAT64 56110037SARM gem5 Developers struct stat hostBuf; 56210037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 56310037SARM gem5 Developers#else 56410037SARM gem5 Developers struct stat64 hostBuf; 56510037SARM gem5 Developers int result = lstat64(path.c_str(), &hostBuf); 56610037SARM gem5 Developers#endif 56710037SARM gem5 Developers 56810037SARM gem5 Developers if (result < 0) 56910037SARM gem5 Developers return -errno; 57010037SARM gem5 Developers 57110037SARM gem5 Developers OS::copyOutStat64Buf(tc->getMemPort(), -1, tc->getSyscallArg(1), &hostBuf); 57210037SARM gem5 Developers 57310037SARM gem5 Developers return 0; 57410037SARM gem5 Developers} 57510037SARM gem5 Developers 57610037SARM gem5 Developers/// Target fstat() handler. 57710037SARM gem5 Developerstemplate <class OS> 57810338SCurtis.Dunham@arm.comSyscallReturn 57910338SCurtis.Dunham@arm.comfstatFunc(SyscallDesc *desc, int callnum, Process *process, 58010338SCurtis.Dunham@arm.com ThreadContext *tc) 58110037SARM gem5 Developers{ 58210037SARM gem5 Developers int fd = process->sim_fd(tc->getSyscallArg(0)); 58310037SARM gem5 Developers 58410037SARM gem5 Developers DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 58510037SARM gem5 Developers 58610037SARM gem5 Developers if (fd < 0) 58710037SARM gem5 Developers return -EBADF; 58810037SARM gem5 Developers 58910037SARM gem5 Developers struct stat hostBuf; 59010037SARM gem5 Developers int result = fstat(fd, &hostBuf); 59110037SARM gem5 Developers 59210037SARM gem5 Developers if (result < 0) 59310037SARM gem5 Developers return -errno; 59410037SARM gem5 Developers 59510037SARM gem5 Developers OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 59610037SARM gem5 Developers 59710037SARM gem5 Developers return 0; 59810037SARM gem5 Developers} 59910037SARM gem5 Developers 60010037SARM gem5 Developers 60110037SARM gem5 Developers/// Target statfs() handler. 60210037SARM gem5 Developerstemplate <class OS> 60310037SARM gem5 DevelopersSyscallReturn 60410037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 60510037SARM gem5 Developers ThreadContext *tc) 60610037SARM gem5 Developers{ 60710037SARM gem5 Developers std::string path; 60810037SARM gem5 Developers 6098549Sdaniel.johnson@arm.com if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 6108868SMatt.Horsnell@arm.com return -EFAULT; 6118868SMatt.Horsnell@arm.com 6128868SMatt.Horsnell@arm.com struct statfs hostBuf; 6138868SMatt.Horsnell@arm.com int result = statfs(path.c_str(), &hostBuf); 6148868SMatt.Horsnell@arm.com 6158868SMatt.Horsnell@arm.com if (result < 0) 6168868SMatt.Horsnell@arm.com return -errno; 6178868SMatt.Horsnell@arm.com 6188868SMatt.Horsnell@arm.com OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 61910461SAndreas.Sandberg@ARM.com 6208868SMatt.Horsnell@arm.com return 0; 62110461SAndreas.Sandberg@ARM.com} 62210037SARM gem5 Developers 6238868SMatt.Horsnell@arm.com 62410037SARM gem5 Developers/// Target fstatfs() handler. 62511150Smitch.hayenga@arm.comtemplate <class OS> 62610037SARM gem5 DevelopersSyscallReturn 62710037SARM gem5 DevelopersfstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 62810037SARM gem5 Developers ThreadContext *tc) 62910037SARM gem5 Developers{ 63011150Smitch.hayenga@arm.com int fd = process->sim_fd(tc->getSyscallArg(0)); 63110037SARM gem5 Developers 63210037SARM gem5 Developers if (fd < 0) 63310037SARM gem5 Developers return -EBADF; 63410037SARM gem5 Developers 63510037SARM gem5 Developers struct statfs hostBuf; 63610037SARM gem5 Developers int result = fstatfs(fd, &hostBuf); 63710037SARM gem5 Developers 63810037SARM gem5 Developers if (result < 0) 63910037SARM gem5 Developers return -errno; 64010037SARM gem5 Developers 64110037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); 64210037SARM gem5 Developers 64310037SARM gem5 Developers return 0; 64410037SARM gem5 Developers} 64510037SARM gem5 Developers 64610037SARM gem5 Developers 64710037SARM gem5 Developers/// Target writev() handler. 64810037SARM gem5 Developerstemplate <class OS> 64910037SARM gem5 DevelopersSyscallReturn 65010037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, Process *process, 65110037SARM gem5 Developers ThreadContext *tc) 65210037SARM gem5 Developers{ 65310037SARM gem5 Developers int fd = tc->getSyscallArg(0); 65410037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 65510037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 65610037SARM gem5 Developers return -EBADF; 65710037SARM gem5 Developers } 65810037SARM gem5 Developers 65910037SARM gem5 Developers TranslatingPort *p = tc->getMemPort(); 66011769SCurtis.Dunham@arm.com uint64_t tiov_base = tc->getSyscallArg(1); 66111769SCurtis.Dunham@arm.com size_t count = tc->getSyscallArg(2); 66210037SARM gem5 Developers struct iovec hiov[count]; 66311770SCurtis.Dunham@arm.com for (int i = 0; i < count; ++i) 66411770SCurtis.Dunham@arm.com { 66510037SARM gem5 Developers typename OS::tgt_iovec tiov; 66611770SCurtis.Dunham@arm.com 66711769SCurtis.Dunham@arm.com p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 66810844Sandreas.sandberg@arm.com (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 66911772SCurtis.Dunham@arm.com hiov[i].iov_len = gtoh(tiov.iov_len); 67011772SCurtis.Dunham@arm.com hiov[i].iov_base = new char [hiov[i].iov_len]; 67111772SCurtis.Dunham@arm.com p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 67211772SCurtis.Dunham@arm.com hiov[i].iov_len); 67311774SCurtis.Dunham@arm.com } 67411774SCurtis.Dunham@arm.com 67511774SCurtis.Dunham@arm.com int result = writev(process->sim_fd(fd), hiov, count); 67611774SCurtis.Dunham@arm.com 67711774SCurtis.Dunham@arm.com for (int i = 0; i < count; ++i) 67811774SCurtis.Dunham@arm.com { 67911774SCurtis.Dunham@arm.com delete [] (char *)hiov[i].iov_base; 68011773SCurtis.Dunham@arm.com } 68111773SCurtis.Dunham@arm.com 68211773SCurtis.Dunham@arm.com if (result < 0) 68311773SCurtis.Dunham@arm.com return -errno; 68411773SCurtis.Dunham@arm.com 68511773SCurtis.Dunham@arm.com return 0; 68611773SCurtis.Dunham@arm.com} 68711772SCurtis.Dunham@arm.com 68810037SARM gem5 Developers 68912816Sgiacomo.travaglini@arm.com/// Target mmap() handler. 69012816Sgiacomo.travaglini@arm.com/// 69112816Sgiacomo.travaglini@arm.com/// We don't really handle mmap(). If the target is mmaping an 69210844Sandreas.sandberg@arm.com/// anonymous region or /dev/zero, we can get away with doing basically 69310844Sandreas.sandberg@arm.com/// nothing (since memory is initialized to zero and the simulator 69410844Sandreas.sandberg@arm.com/// doesn't really check addresses anyway). Always print a warning, 69510844Sandreas.sandberg@arm.com/// since this could be seriously broken if we're not mapping 69610844Sandreas.sandberg@arm.com/// /dev/zero. 69710844Sandreas.sandberg@arm.com// 69810188Sgeoffrey.blake@arm.com/// Someday we should explicitly check for /dev/zero in open, flag the 69910037SARM gem5 Developers/// file descriptor, and fail (or implement!) a non-anonymous mmap to 70010037SARM gem5 Developers/// anything else. 7017405SAli.Saidi@ARM.comtemplate <class OS> 7027405SAli.Saidi@ARM.comSyscallReturn 7037405SAli.Saidi@ARM.commmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 7047405SAli.Saidi@ARM.com{ 7057405SAli.Saidi@ARM.com Addr start = tc->getSyscallArg(0); 7067405SAli.Saidi@ARM.com uint64_t length = tc->getSyscallArg(1); 7077405SAli.Saidi@ARM.com // int prot = tc->getSyscallArg(2); 7087405SAli.Saidi@ARM.com int flags = tc->getSyscallArg(3); 7097614Sminkyu.jeong@arm.com // int fd = p->sim_fd(tc->getSyscallArg(4)); 71012478SCurtis.Dunham@arm.com // int offset = tc->getSyscallArg(5); 71112478SCurtis.Dunham@arm.com 71212478SCurtis.Dunham@arm.com if ((start % TheISA::VMPageSize) != 0 || 71312478SCurtis.Dunham@arm.com (length % TheISA::VMPageSize) != 0) { 71412478SCurtis.Dunham@arm.com warn("mmap failing: arguments not page-aligned: " 71511771SCurtis.Dunham@arm.com "start 0x%x length 0x%x", 71612478SCurtis.Dunham@arm.com start, length); 71712478SCurtis.Dunham@arm.com return -EINVAL; 71810037SARM gem5 Developers } 71912478SCurtis.Dunham@arm.com 72010037SARM gem5 Developers if (start != 0) { 72112478SCurtis.Dunham@arm.com warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 72210037SARM gem5 Developers start, p->mmap_end); 72312478SCurtis.Dunham@arm.com } 72410037SARM gem5 Developers 7257405SAli.Saidi@ARM.com // pick next address from our "mmap region" 7267405SAli.Saidi@ARM.com start = p->mmap_end; 7277405SAli.Saidi@ARM.com p->pTable->allocate(start, length); 7287405SAli.Saidi@ARM.com p->mmap_end += length; 7297405SAli.Saidi@ARM.com 7307749SAli.Saidi@ARM.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 7317405SAli.Saidi@ARM.com warn("allowing mmap of file @ fd %d. " 73210037SARM gem5 Developers "This will break if not /dev/zero.", tc->getSyscallArg(4)); 73310037SARM gem5 Developers } 7348284SAli.Saidi@ARM.com 7357405SAli.Saidi@ARM.com return start; 7367405SAli.Saidi@ARM.com} 7377749SAli.Saidi@ARM.com 7387749SAli.Saidi@ARM.com/// Target getrlimit() handler. 7397749SAli.Saidi@ARM.comtemplate <class OS> 7407749SAli.Saidi@ARM.comSyscallReturn 7417405SAli.Saidi@ARM.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 74212510Sgiacomo.travaglini@arm.com ThreadContext *tc) 74312406Sgabeblack@google.com{ 74412406Sgabeblack@google.com unsigned resource = tc->getSyscallArg(0); 7457749SAli.Saidi@ARM.com TypedBufferArg<typename OS::rlimit> rlp(tc->getSyscallArg(1)); 7467749SAli.Saidi@ARM.com 7477614Sminkyu.jeong@arm.com switch (resource) { 7487614Sminkyu.jeong@arm.com case OS::TGT_RLIMIT_STACK: 7497720Sgblack@eecs.umich.edu // max stack size in bytes: make up a number (2MB for now) 7507720Sgblack@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 7517720Sgblack@eecs.umich.edu rlp->rlim_cur = htog(rlp->rlim_cur); 75212763Sgiacomo.travaglini@arm.com rlp->rlim_max = htog(rlp->rlim_max); 7538887Sgeoffrey.blake@arm.com break; 7548887Sgeoffrey.blake@arm.com 7558887Sgeoffrey.blake@arm.com default: 7568887Sgeoffrey.blake@arm.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 7578887Sgeoffrey.blake@arm.com << std::endl; 7588887Sgeoffrey.blake@arm.com abort(); 7598887Sgeoffrey.blake@arm.com break; 7608887Sgeoffrey.blake@arm.com } 7618887Sgeoffrey.blake@arm.com 7627408Sgblack@eecs.umich.edu rlp.copyOut(tc->getMemPort()); 76310037SARM gem5 Developers return 0; 76410037SARM gem5 Developers} 76510037SARM gem5 Developers 76610037SARM gem5 Developers/// Target gettimeofday() handler. 76710037SARM gem5 Developerstemplate <class OS> 76810037SARM gem5 DevelopersSyscallReturn 76910037SARM gem5 DevelopersgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 77010037SARM gem5 Developers ThreadContext *tc) 77110037SARM gem5 Developers{ 77210037SARM gem5 Developers TypedBufferArg<typename OS::timeval> tp(tc->getSyscallArg(0)); 77310037SARM gem5 Developers 7747408Sgblack@eecs.umich.edu getElapsedTime(tp->tv_sec, tp->tv_usec); 7757408Sgblack@eecs.umich.edu tp->tv_sec += seconds_since_epoch; 7768206SWilliam.Wang@arm.com tp->tv_sec = htog(tp->tv_sec); 7778206SWilliam.Wang@arm.com tp->tv_usec = htog(tp->tv_usec); 7788206SWilliam.Wang@arm.com 7798206SWilliam.Wang@arm.com tp.copyOut(tc->getMemPort()); 7808206SWilliam.Wang@arm.com 7818206SWilliam.Wang@arm.com return 0; 7828206SWilliam.Wang@arm.com} 7838206SWilliam.Wang@arm.com 78410037SARM gem5 Developers 78510037SARM gem5 Developers/// Target utimes() handler. 78610037SARM gem5 Developerstemplate <class OS> 78710037SARM gem5 DevelopersSyscallReturn 78810037SARM gem5 DevelopersutimesFunc(SyscallDesc *desc, int callnum, Process *process, 78912667Schuan.zhu@arm.com ThreadContext *tc) 79010037SARM gem5 Developers{ 79110037SARM gem5 Developers std::string path; 79210037SARM gem5 Developers 79310037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) 79410037SARM gem5 Developers return -EFAULT; 79510037SARM gem5 Developers 79610037SARM gem5 Developers TypedBufferArg<typename OS::timeval [2]> tp(tc->getSyscallArg(1)); 79710037SARM gem5 Developers tp.copyIn(tc->getMemPort()); 7988206SWilliam.Wang@arm.com 79910037SARM gem5 Developers struct timeval hostTimeval[2]; 80010037SARM gem5 Developers for (int i = 0; i < 2; ++i) 80110037SARM gem5 Developers { 80210037SARM gem5 Developers hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 80310037SARM gem5 Developers hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 80410037SARM gem5 Developers } 80510037SARM gem5 Developers int result = utimes(path.c_str(), hostTimeval); 80610037SARM gem5 Developers 80710037SARM gem5 Developers if (result < 0) 80810037SARM gem5 Developers return -errno; 80910037SARM gem5 Developers 81010037SARM gem5 Developers return 0; 81110037SARM gem5 Developers} 81210037SARM gem5 Developers/// Target getrusage() function. 81310037SARM gem5 Developerstemplate <class OS> 81410037SARM gem5 DevelopersSyscallReturn 81510037SARM gem5 DevelopersgetrusageFunc(SyscallDesc *desc, int callnum, Process *process, 81610037SARM gem5 Developers ThreadContext *tc) 81710037SARM gem5 Developers{ 81810037SARM gem5 Developers int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 81910037SARM gem5 Developers TypedBufferArg<typename OS::rusage> rup(tc->getSyscallArg(1)); 82010037SARM gem5 Developers 82110037SARM gem5 Developers if (who != OS::TGT_RUSAGE_SELF) { 82210037SARM gem5 Developers // don't really handle THREAD or CHILDREN, but just warn and 82310037SARM gem5 Developers // plow ahead 82410037SARM gem5 Developers warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 82510037SARM gem5 Developers who); 82610037SARM gem5 Developers } 82710037SARM gem5 Developers 8288206SWilliam.Wang@arm.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 8298206SWilliam.Wang@arm.com rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 8307408Sgblack@eecs.umich.edu rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 8317408Sgblack@eecs.umich.edu 8327408Sgblack@eecs.umich.edu rup->ru_stime.tv_sec = 0; 8337731SAli.Saidi@ARM.com rup->ru_stime.tv_usec = 0; 8348206SWilliam.Wang@arm.com rup->ru_maxrss = 0; 83510037SARM gem5 Developers rup->ru_ixrss = 0; 83610037SARM gem5 Developers rup->ru_idrss = 0; 83710037SARM gem5 Developers rup->ru_isrss = 0; 83810037SARM gem5 Developers rup->ru_minflt = 0; 83910037SARM gem5 Developers rup->ru_majflt = 0; 8407408Sgblack@eecs.umich.edu rup->ru_nswap = 0; 8417408Sgblack@eecs.umich.edu rup->ru_inblock = 0; 8427408Sgblack@eecs.umich.edu rup->ru_oublock = 0; 8437408Sgblack@eecs.umich.edu rup->ru_msgsnd = 0; 8447408Sgblack@eecs.umich.edu rup->ru_msgrcv = 0; 8457408Sgblack@eecs.umich.edu rup->ru_nsignals = 0; 8467408Sgblack@eecs.umich.edu rup->ru_nvcsw = 0; 8477408Sgblack@eecs.umich.edu rup->ru_nivcsw = 0; 8487408Sgblack@eecs.umich.edu 8497408Sgblack@eecs.umich.edu rup.copyOut(tc->getMemPort()); 85010037SARM gem5 Developers 85110037SARM gem5 Developers return 0; 85210037SARM gem5 Developers} 85310037SARM gem5 Developers 85410037SARM gem5 Developers 85510037SARM gem5 Developers 8567408Sgblack@eecs.umich.edu 8577408Sgblack@eecs.umich.edu#endif // __SIM_SYSCALL_EMUL_HH__ 8587408Sgblack@eecs.umich.edu