syscall_emul.hh revision 8601
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 */ 317405SAli.Saidi@ARM.com 327405SAli.Saidi@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__ 337405SAli.Saidi@ARM.com#define __SIM_SYSCALL_EMUL_HH__ 347405SAli.Saidi@ARM.com 357405SAli.Saidi@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 367405SAli.Saidi@ARM.com defined(__FreeBSD__) || defined(__CYGWIN__)) 377405SAli.Saidi@ARM.com 387405SAli.Saidi@ARM.com/// 397405SAli.Saidi@ARM.com/// @file syscall_emul.hh 407405SAli.Saidi@ARM.com/// 417405SAli.Saidi@ARM.com/// This file defines objects used to emulate syscalls from the target 4210461SAndreas.Sandberg@ARM.com/// application on the host machine. 439050Schander.sudanthi@arm.com 4412406Sgabeblack@google.com#ifdef __CYGWIN32__ 4512605Sgiacomo.travaglini@arm.com#include <sys/fcntl.h> // for O_BINARY 4611793Sbrandon.potter@amd.com#endif 478887Sgeoffrey.blake@arm.com#include <sys/stat.h> 488232Snate@binkert.org#include <sys/time.h> 498232Snate@binkert.org#include <sys/uio.h> 5010844Sandreas.sandberg@arm.com#include <fcntl.h> 519384SAndreas.Sandberg@arm.com 527678Sgblack@eecs.umich.edu#include <cerrno> 538059SAli.Saidi@ARM.com#include <string> 548284SAli.Saidi@ARM.com 557405SAli.Saidi@ARM.com#include "base/chunk_generator.hh" 567405SAli.Saidi@ARM.com#include "base/intmath.hh" // for RoundUp 577405SAli.Saidi@ARM.com#include "base/misc.hh" 587405SAli.Saidi@ARM.com#include "base/trace.hh" 599384SAndreas.Sandberg@arm.com#include "base/types.hh" 6010461SAndreas.Sandberg@ARM.com#include "config/the_isa.hh" 6110461SAndreas.Sandberg@ARM.com#include "cpu/base.hh" 6211165SRekai.GonzalezAlberquilla@arm.com#include "cpu/thread_context.hh" 6312109SRekai.GonzalezAlberquilla@arm.com#include "debug/SyscallVerbose.hh" 6412714Sgiacomo.travaglini@arm.com#include "mem/page_table.hh" 6512714Sgiacomo.travaglini@arm.com#include "mem/translating_port.hh" 669384SAndreas.Sandberg@arm.com#include "sim/byteswap.hh" 6711770SCurtis.Dunham@arm.com#include "sim/process.hh" 6810037SARM gem5 Developers#include "sim/system.hh" 6910461SAndreas.Sandberg@ARM.com 7010461SAndreas.Sandberg@ARM.com/// 7110461SAndreas.Sandberg@ARM.com/// System call descriptor. 7210461SAndreas.Sandberg@ARM.com/// 7310461SAndreas.Sandberg@ARM.comclass SyscallDesc { 7410461SAndreas.Sandberg@ARM.com 7510609Sandreas.sandberg@arm.com public: 7610609Sandreas.sandberg@arm.com 7710609Sandreas.sandberg@arm.com /// Typedef for target syscall handler functions. 7810037SARM gem5 Developers typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 7910037SARM gem5 Developers LiveProcess *, ThreadContext *); 8010037SARM gem5 Developers 8110037SARM gem5 Developers const char *name; //!< Syscall name (e.g., "open"). 8211771SCurtis.Dunham@arm.com FuncPtr funcPtr; //!< Pointer to emulation function. 8310037SARM gem5 Developers int flags; //!< Flags (see Flags enum). 8410037SARM gem5 Developers 8513173Sgiacomo.travaglini@arm.com /// Flag values for controlling syscall behavior. 8610037SARM gem5 Developers enum Flags { 8710037SARM gem5 Developers /// Don't set return regs according to funcPtr return value. 8813114Sgiacomo.travaglini@arm.com /// Used for syscalls with non-standard return conventions 8910037SARM gem5 Developers /// that explicitly set the ThreadContext regs (e.g., 9011771SCurtis.Dunham@arm.com /// sigreturn). 9110037SARM gem5 Developers SuppressReturnValue = 1 9213173Sgiacomo.travaglini@arm.com }; 9310037SARM gem5 Developers 9413114Sgiacomo.travaglini@arm.com /// Constructor. 9510037SARM gem5 Developers SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9610037SARM gem5 Developers : name(_name), funcPtr(_funcPtr), flags(_flags) 9712477SCurtis.Dunham@arm.com { 9810037SARM gem5 Developers } 9910037SARM gem5 Developers 1009384SAndreas.Sandberg@arm.com /// Emulate the syscall. Public interface for calling through funcPtr. 1019384SAndreas.Sandberg@arm.com void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1029384SAndreas.Sandberg@arm.com}; 10312479SCurtis.Dunham@arm.com 10412479SCurtis.Dunham@arm.com 1059384SAndreas.Sandberg@arm.comclass BaseBufferArg { 1069384SAndreas.Sandberg@arm.com 1079384SAndreas.Sandberg@arm.com public: 1089384SAndreas.Sandberg@arm.com 1099384SAndreas.Sandberg@arm.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 1109384SAndreas.Sandberg@arm.com { 1117427Sgblack@eecs.umich.edu bufPtr = new uint8_t[size]; 1127427Sgblack@eecs.umich.edu // clear out buffer: in case we only partially populate this, 1137427Sgblack@eecs.umich.edu // and then do a copyOut(), we want to make sure we don't 1149385SAndreas.Sandberg@arm.com // introduce any random junk into the simulated address space 1159385SAndreas.Sandberg@arm.com memset(bufPtr, 0, size); 1167427Sgblack@eecs.umich.edu } 1177427Sgblack@eecs.umich.edu 11810037SARM gem5 Developers virtual ~BaseBufferArg() { delete [] bufPtr; } 11913114Sgiacomo.travaglini@arm.com 12010037SARM gem5 Developers // 12113114Sgiacomo.travaglini@arm.com // copy data into simulator space (read from target memory) 12213114Sgiacomo.travaglini@arm.com // 12313114Sgiacomo.travaglini@arm.com virtual bool copyIn(TranslatingPort *memport) 12413114Sgiacomo.travaglini@arm.com { 12513114Sgiacomo.travaglini@arm.com memport->readBlob(addr, bufPtr, size); 12612690Sgiacomo.travaglini@arm.com return true; // no EFAULT detection for now 12710037SARM gem5 Developers } 1287427Sgblack@eecs.umich.edu 1297427Sgblack@eecs.umich.edu // 13010037SARM gem5 Developers // copy data out of simulator space (write to target memory) 1317427Sgblack@eecs.umich.edu // 1327427Sgblack@eecs.umich.edu virtual bool copyOut(TranslatingPort *memport) 1337427Sgblack@eecs.umich.edu { 1347427Sgblack@eecs.umich.edu memport->writeBlob(addr, bufPtr, size); 1357427Sgblack@eecs.umich.edu return true; // no EFAULT detection for now 1367427Sgblack@eecs.umich.edu } 1377427Sgblack@eecs.umich.edu 1387427Sgblack@eecs.umich.edu protected: 1397427Sgblack@eecs.umich.edu Addr addr; 1407427Sgblack@eecs.umich.edu int size; 1417427Sgblack@eecs.umich.edu uint8_t *bufPtr; 1427427Sgblack@eecs.umich.edu}; 1437427Sgblack@eecs.umich.edu 1447427Sgblack@eecs.umich.edu 1457427Sgblack@eecs.umich.educlass BufferArg : public BaseBufferArg 1467427Sgblack@eecs.umich.edu{ 1477427Sgblack@eecs.umich.edu public: 1487427Sgblack@eecs.umich.edu BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1497427Sgblack@eecs.umich.edu void *bufferPtr() { return bufPtr; } 1507427Sgblack@eecs.umich.edu}; 1517427Sgblack@eecs.umich.edu 1527427Sgblack@eecs.umich.edutemplate <class T> 1537427Sgblack@eecs.umich.educlass TypedBufferArg : public BaseBufferArg 1547436Sdam.sunwoo@arm.com{ 1557436Sdam.sunwoo@arm.com public: 15610037SARM gem5 Developers // user can optionally specify a specific number of bytes to 15710037SARM gem5 Developers // allocate to deal with those structs that have variable-size 1587436Sdam.sunwoo@arm.com // arrays at the end 1597436Sdam.sunwoo@arm.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1607436Sdam.sunwoo@arm.com : BaseBufferArg(_addr, _size) 1617436Sdam.sunwoo@arm.com { } 1627436Sdam.sunwoo@arm.com 1637436Sdam.sunwoo@arm.com // type case 1647436Sdam.sunwoo@arm.com operator T*() { return (T *)bufPtr; } 1657436Sdam.sunwoo@arm.com 1667436Sdam.sunwoo@arm.com // dereference operators 1677436Sdam.sunwoo@arm.com T &operator*() { return *((T *)bufPtr); } 1687436Sdam.sunwoo@arm.com T* operator->() { return (T *)bufPtr; } 1697436Sdam.sunwoo@arm.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 17013393Sgiacomo.travaglini@arm.com}; 17110037SARM gem5 Developers 1727436Sdam.sunwoo@arm.com////////////////////////////////////////////////////////////////////// 1737436Sdam.sunwoo@arm.com// 1747436Sdam.sunwoo@arm.com// The following emulation functions are generic enough that they 1757436Sdam.sunwoo@arm.com// don't need to be recompiled for different emulated OS's. They are 1767436Sdam.sunwoo@arm.com// defined in sim/syscall_emul.cc. 1777436Sdam.sunwoo@arm.com// 1787436Sdam.sunwoo@arm.com////////////////////////////////////////////////////////////////////// 1797436Sdam.sunwoo@arm.com 1807436Sdam.sunwoo@arm.com 1817436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we haven't thought about. 1827436Sdam.sunwoo@arm.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1837436Sdam.sunwoo@arm.com LiveProcess *p, ThreadContext *tc); 1847436Sdam.sunwoo@arm.com 1857436Sdam.sunwoo@arm.com/// Handler for unimplemented syscalls that we never intend to 1867436Sdam.sunwoo@arm.com/// implement (signal handling, etc.) and should not affect the correct 1877436Sdam.sunwoo@arm.com/// behavior of the program. Print a warning only if the appropriate 18813393Sgiacomo.travaglini@arm.com/// trace flag is enabled. Return success to the target program. 18913393Sgiacomo.travaglini@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 19013393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 19113393Sgiacomo.travaglini@arm.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 19213393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 19313393Sgiacomo.travaglini@arm.com 19413393Sgiacomo.travaglini@arm.com/// Target exit() handler: terminate current context. 19513393Sgiacomo.travaglini@arm.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 19613393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 19713393Sgiacomo.travaglini@arm.com 19813393Sgiacomo.travaglini@arm.com/// Target exit_group() handler: terminate simulation. (exit all threads) 19913393Sgiacomo.travaglini@arm.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 20013393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 20113393Sgiacomo.travaglini@arm.com 20213393Sgiacomo.travaglini@arm.com/// Target getpagesize() handler. 20313393Sgiacomo.travaglini@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 20413396Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 20513396Sgiacomo.travaglini@arm.com 20613396Sgiacomo.travaglini@arm.com/// Target brk() handler: set brk address. 20713396Sgiacomo.travaglini@arm.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 20813393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 20913393Sgiacomo.travaglini@arm.com 21013393Sgiacomo.travaglini@arm.com/// Target close() handler. 21113393Sgiacomo.travaglini@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 21213393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 21313393Sgiacomo.travaglini@arm.com 21413393Sgiacomo.travaglini@arm.com/// Target read() handler. 21513393Sgiacomo.travaglini@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num, 21613393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 21713393Sgiacomo.travaglini@arm.com 21813393Sgiacomo.travaglini@arm.com/// Target write() handler. 21913393Sgiacomo.travaglini@arm.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 22013393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 22113393Sgiacomo.travaglini@arm.com 22213393Sgiacomo.travaglini@arm.com/// Target lseek() handler. 22313393Sgiacomo.travaglini@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 22413393Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 22513393Sgiacomo.travaglini@arm.com 2267644Sali.saidi@arm.com/// Target _llseek() handler. 2278147SAli.Saidi@ARM.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 2289385SAndreas.Sandberg@arm.com LiveProcess *p, ThreadContext *tc); 2299385SAndreas.Sandberg@arm.com 23010037SARM gem5 Developers/// Target munmap() handler. 23110037SARM gem5 DevelopersSyscallReturn munmapFunc(SyscallDesc *desc, int num, 23210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23310037SARM gem5 Developers 23410037SARM gem5 Developers/// Target gethostname() handler. 23510037SARM gem5 DevelopersSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 23610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 23710037SARM gem5 Developers 23810037SARM gem5 Developers/// Target getcwd() handler. 23910037SARM gem5 DevelopersSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 24010037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24110037SARM gem5 Developers 24210037SARM gem5 Developers/// Target unlink() handler. 24310037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 24410037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24510037SARM gem5 Developers 2468147SAli.Saidi@ARM.com/// Target unlink() handler. 2477427Sgblack@eecs.umich.eduSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2487427Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2497427Sgblack@eecs.umich.edu 25010037SARM gem5 Developers/// Target mkdir() handler. 25110037SARM gem5 DevelopersSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 25210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25310037SARM gem5 Developers 25413396Sgiacomo.travaglini@arm.com/// Target rename() handler. 25510037SARM gem5 DevelopersSyscallReturn renameFunc(SyscallDesc *desc, int num, 25610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25710037SARM gem5 Developers 25810037SARM gem5 Developers 25910037SARM gem5 Developers/// Target truncate() handler. 26010037SARM gem5 DevelopersSyscallReturn truncateFunc(SyscallDesc *desc, int num, 26110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26210037SARM gem5 Developers 26310037SARM gem5 Developers 26410037SARM gem5 Developers/// Target ftruncate() handler. 26510037SARM gem5 DevelopersSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 26610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26710037SARM gem5 Developers 26810037SARM gem5 Developers 26910037SARM gem5 Developers/// Target truncate64() handler. 27010037SARM gem5 DevelopersSyscallReturn truncate64Func(SyscallDesc *desc, int num, 27110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27210037SARM gem5 Developers 27310037SARM gem5 Developers/// Target ftruncate64() handler. 27410037SARM gem5 DevelopersSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 27510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27610037SARM gem5 Developers 27710037SARM gem5 Developers 27810037SARM gem5 Developers/// Target umask() handler. 27910037SARM gem5 DevelopersSyscallReturn umaskFunc(SyscallDesc *desc, int num, 28010037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 28110037SARM gem5 Developers 28210037SARM gem5 Developers 28310037SARM gem5 Developers/// Target chown() handler. 28410037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num, 28510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 28611770SCurtis.Dunham@arm.com 28710037SARM gem5 Developers 28811574SCurtis.Dunham@arm.com/// Target fchown() handler. 28911770SCurtis.Dunham@arm.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 29011770SCurtis.Dunham@arm.com LiveProcess *p, ThreadContext *tc); 29110037SARM gem5 Developers 29211770SCurtis.Dunham@arm.com/// Target dup() handler. 29311770SCurtis.Dunham@arm.comSyscallReturn dupFunc(SyscallDesc *desc, int num, 29410037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 29510037SARM gem5 Developers 29610037SARM gem5 Developers/// Target fnctl() handler. 29713114Sgiacomo.travaglini@arm.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 29810037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 29913114Sgiacomo.travaglini@arm.com 30013114Sgiacomo.travaglini@arm.com/// Target fcntl64() handler. 30113114Sgiacomo.travaglini@arm.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 30213114Sgiacomo.travaglini@arm.com LiveProcess *process, ThreadContext *tc); 30313114Sgiacomo.travaglini@arm.com 30413114Sgiacomo.travaglini@arm.com/// Target setuid() handler. 30513114Sgiacomo.travaglini@arm.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 30613114Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 30713114Sgiacomo.travaglini@arm.com 30813114Sgiacomo.travaglini@arm.com/// Target getpid() handler. 30913114Sgiacomo.travaglini@arm.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 31013114Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 31113114Sgiacomo.travaglini@arm.com 31213114Sgiacomo.travaglini@arm.com/// Target getuid() handler. 31313114Sgiacomo.travaglini@arm.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 31413114Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 31513114Sgiacomo.travaglini@arm.com 31613114Sgiacomo.travaglini@arm.com/// Target getgid() handler. 31713114Sgiacomo.travaglini@arm.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 31813114Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 31913114Sgiacomo.travaglini@arm.com 32013114Sgiacomo.travaglini@arm.com/// Target getppid() handler. 32113114Sgiacomo.travaglini@arm.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 32213114Sgiacomo.travaglini@arm.com LiveProcess *p, ThreadContext *tc); 32310037SARM gem5 Developers 32410037SARM gem5 Developers/// Target geteuid() handler. 32510037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 32610461SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 32710461SAndreas.Sandberg@ARM.com 32810461SAndreas.Sandberg@ARM.com/// Target getegid() handler. 32910461SAndreas.Sandberg@ARM.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 33010037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 33110037SARM gem5 Developers 33210037SARM gem5 Developers/// Target clone() handler. 33310037SARM gem5 DevelopersSyscallReturn cloneFunc(SyscallDesc *desc, int num, 33410037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 33513116Sgiacomo.travaglini@arm.com 33610037SARM gem5 Developers 33710461SAndreas.Sandberg@ARM.com/// Pseudo Funcs - These functions use a different return convension, 33810461SAndreas.Sandberg@ARM.com/// returning a second value in a register other than the normal return register 33910461SAndreas.Sandberg@ARM.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 34010461SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc); 34110461SAndreas.Sandberg@ARM.com 34210037SARM gem5 Developers/// Target getpidPseudo() handler. 34310037SARM gem5 DevelopersSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 34410037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 34510037SARM gem5 Developers 34610037SARM gem5 Developers/// Target getuidPseudo() handler. 34711574SCurtis.Dunham@arm.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 34810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 34910037SARM gem5 Developers 35010037SARM gem5 Developers/// Target getgidPseudo() handler. 35111574SCurtis.Dunham@arm.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 35210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 35310037SARM gem5 Developers 35410037SARM gem5 Developers 35510037SARM gem5 Developers/// A readable name for 1,000,000, for converting microseconds to seconds. 35610037SARM gem5 Developersconst int one_million = 1000000; 35710037SARM gem5 Developers 35810037SARM gem5 Developers/// Approximate seconds since the epoch (1/1/1970). About a billion, 35913114Sgiacomo.travaglini@arm.com/// by my reckoning. We want to keep this a constant (not use the 36013173Sgiacomo.travaglini@arm.com/// real-world time) to keep simulations repeatable. 36113173Sgiacomo.travaglini@arm.comconst unsigned seconds_since_epoch = 1000000000; 36213173Sgiacomo.travaglini@arm.com 36313173Sgiacomo.travaglini@arm.com/// Helper function to convert current elapsed time to seconds and 36410037SARM gem5 Developers/// microseconds. 36510037SARM gem5 Developerstemplate <class T1, class T2> 36612972Sandreas.sandberg@arm.comvoid 36712972Sandreas.sandberg@arm.comgetElapsedTime(T1 &sec, T2 &usec) 36812972Sandreas.sandberg@arm.com{ 36912972Sandreas.sandberg@arm.com int elapsed_usecs = curTick() / SimClock::Int::us; 37012972Sandreas.sandberg@arm.com sec = elapsed_usecs / one_million; 37112972Sandreas.sandberg@arm.com usec = elapsed_usecs % one_million; 37212972Sandreas.sandberg@arm.com} 37312972Sandreas.sandberg@arm.com 3747405SAli.Saidi@ARM.com////////////////////////////////////////////////////////////////////// 37510035Sandreas.hansson@arm.com// 3767405SAli.Saidi@ARM.com// The following emulation functions are generic, but need to be 3777405SAli.Saidi@ARM.com// templated to account for differences in types, constants, etc. 3787614Sminkyu.jeong@arm.com// 37912478SCurtis.Dunham@arm.com////////////////////////////////////////////////////////////////////// 38012478SCurtis.Dunham@arm.com 38112478SCurtis.Dunham@arm.com#if NO_STAT64 38212478SCurtis.Dunham@arm.com typedef struct stat hst_stat; 38312478SCurtis.Dunham@arm.com typedef struct stat hst_stat64; 38412478SCurtis.Dunham@arm.com#else 38512478SCurtis.Dunham@arm.com typedef struct stat hst_stat; 38612478SCurtis.Dunham@arm.com typedef struct stat64 hst_stat64; 38712478SCurtis.Dunham@arm.com#endif 38812478SCurtis.Dunham@arm.com 38912478SCurtis.Dunham@arm.com//// Helper function to convert a host stat buffer to a target stat 39012478SCurtis.Dunham@arm.com//// buffer. Also copies the target buffer out to the simulated 39112478SCurtis.Dunham@arm.com//// memory space. Used by stat(), fstat(), and lstat(). 39212478SCurtis.Dunham@arm.com 39312478SCurtis.Dunham@arm.comtemplate <typename target_stat, typename host_stat> 39412478SCurtis.Dunham@arm.comstatic void 3957405SAli.Saidi@ARM.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 3967405SAli.Saidi@ARM.com{ 3977405SAli.Saidi@ARM.com using namespace TheISA; 3987405SAli.Saidi@ARM.com 3997405SAli.Saidi@ARM.com if (fakeTTY) 4007405SAli.Saidi@ARM.com tgt->st_dev = 0xA; 40110037SARM gem5 Developers else 40210037SARM gem5 Developers tgt->st_dev = host->st_dev; 40310037SARM gem5 Developers tgt->st_dev = htog(tgt->st_dev); 4049050Schander.sudanthi@arm.com tgt->st_ino = host->st_ino; 4057405SAli.Saidi@ARM.com tgt->st_ino = htog(tgt->st_ino); 40610037SARM gem5 Developers tgt->st_mode = host->st_mode; 40710037SARM gem5 Developers if (fakeTTY) { 4087720Sgblack@eecs.umich.edu // Claim to be a character device 4097720Sgblack@eecs.umich.edu tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4107405SAli.Saidi@ARM.com tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4117405SAli.Saidi@ARM.com } 4127757SAli.Saidi@ARM.com tgt->st_mode = htog(tgt->st_mode); 41310037SARM gem5 Developers tgt->st_nlink = host->st_nlink; 41410037SARM gem5 Developers tgt->st_nlink = htog(tgt->st_nlink); 41510037SARM gem5 Developers tgt->st_uid = host->st_uid; 41610037SARM gem5 Developers tgt->st_uid = htog(tgt->st_uid); 41710037SARM gem5 Developers tgt->st_gid = host->st_gid; 41810037SARM gem5 Developers tgt->st_gid = htog(tgt->st_gid); 41910037SARM gem5 Developers if (fakeTTY) 42010037SARM gem5 Developers tgt->st_rdev = 0x880d; 42110037SARM gem5 Developers else 42210037SARM gem5 Developers tgt->st_rdev = host->st_rdev; 42310037SARM gem5 Developers tgt->st_rdev = htog(tgt->st_rdev); 42410037SARM gem5 Developers tgt->st_size = host->st_size; 42510037SARM gem5 Developers tgt->st_size = htog(tgt->st_size); 42610037SARM gem5 Developers tgt->st_atimeX = host->st_atime; 42710037SARM gem5 Developers tgt->st_atimeX = htog(tgt->st_atimeX); 42810037SARM gem5 Developers tgt->st_mtimeX = host->st_mtime; 42910037SARM gem5 Developers tgt->st_mtimeX = htog(tgt->st_mtimeX); 43010037SARM gem5 Developers tgt->st_ctimeX = host->st_ctime; 43110037SARM gem5 Developers tgt->st_ctimeX = htog(tgt->st_ctimeX); 43210037SARM gem5 Developers // Force the block size to be 8k. This helps to ensure buffered io works 43310037SARM gem5 Developers // consistently across different hosts. 43410037SARM gem5 Developers tgt->st_blksize = 0x2000; 43510037SARM gem5 Developers tgt->st_blksize = htog(tgt->st_blksize); 43610037SARM gem5 Developers tgt->st_blocks = host->st_blocks; 43710037SARM gem5 Developers tgt->st_blocks = htog(tgt->st_blocks); 43810037SARM gem5 Developers} 43910037SARM gem5 Developers 44010037SARM gem5 Developers// Same for stat64 44110037SARM gem5 Developers 44210037SARM gem5 Developerstemplate <typename target_stat, typename host_stat64> 44310037SARM gem5 Developersstatic void 44410037SARM gem5 DevelopersconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 44510037SARM gem5 Developers{ 44612667Schuan.zhu@arm.com using namespace TheISA; 44710037SARM gem5 Developers 44810037SARM gem5 Developers convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 44910037SARM gem5 Developers#if defined(STAT_HAVE_NSEC) 45010037SARM gem5 Developers tgt->st_atime_nsec = host->st_atime_nsec; 45110037SARM gem5 Developers tgt->st_atime_nsec = htog(tgt->st_atime_nsec); 45210037SARM gem5 Developers tgt->st_mtime_nsec = host->st_mtime_nsec; 45310037SARM gem5 Developers tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec); 45410037SARM gem5 Developers tgt->st_ctime_nsec = host->st_ctime_nsec; 45510037SARM gem5 Developers tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec); 45610037SARM gem5 Developers#else 45710037SARM gem5 Developers tgt->st_atime_nsec = 0; 45810037SARM gem5 Developers tgt->st_mtime_nsec = 0; 4598284SAli.Saidi@ARM.com tgt->st_ctime_nsec = 0; 46010037SARM gem5 Developers#endif 46110037SARM gem5 Developers} 46210037SARM gem5 Developers 46310037SARM gem5 Developers//Here are a couple convenience functions 4649050Schander.sudanthi@arm.comtemplate<class OS> 46510037SARM gem5 Developersstatic void 46610037SARM gem5 DeveloperscopyOutStatBuf(TranslatingPort * mem, Addr addr, 46710037SARM gem5 Developers hst_stat *host, bool fakeTTY = false) 46810037SARM gem5 Developers{ 46910037SARM gem5 Developers typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 47010037SARM gem5 Developers tgt_stat_buf tgt(addr); 47110037SARM gem5 Developers convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 47210037SARM gem5 Developers tgt.copyOut(mem); 47310037SARM gem5 Developers} 47410037SARM gem5 Developers 47510037SARM gem5 Developerstemplate<class OS> 47610037SARM gem5 Developersstatic void 47710037SARM gem5 DeveloperscopyOutStat64Buf(TranslatingPort * mem, Addr addr, 47810037SARM gem5 Developers hst_stat64 *host, bool fakeTTY = false) 47910037SARM gem5 Developers{ 48010037SARM gem5 Developers typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 48110037SARM gem5 Developers tgt_stat_buf tgt(addr); 48210037SARM gem5 Developers convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 4839050Schander.sudanthi@arm.com tgt.copyOut(mem); 4848284SAli.Saidi@ARM.com} 48510037SARM gem5 Developers 48610037SARM gem5 Developers/// Target ioctl() handler. For the most part, programs call ioctl() 48710037SARM gem5 Developers/// only to find out if their stdout is a tty, to determine whether to 48810037SARM gem5 Developers/// do line or block buffering. 48910037SARM gem5 Developerstemplate <class OS> 49010037SARM gem5 DevelopersSyscallReturn 49110037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 4927405SAli.Saidi@ARM.com ThreadContext *tc) 4937731SAli.Saidi@ARM.com{ 4948468Swade.walker@arm.com int index = 0; 4958468Swade.walker@arm.com int fd = process->getSyscallArg(tc, index); 4968468Swade.walker@arm.com unsigned req = process->getSyscallArg(tc, index); 4977405SAli.Saidi@ARM.com 4987731SAli.Saidi@ARM.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 4997405SAli.Saidi@ARM.com 5007405SAli.Saidi@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 50111809Sbaz21@cam.ac.uk // doesn't map to any simulator fd: not a valid target fd 50211809Sbaz21@cam.ac.uk return -EBADF; 5039130Satgutier@umich.edu } 5049130Satgutier@umich.edu 5059130Satgutier@umich.edu switch (req) { 5069130Satgutier@umich.edu case OS::TIOCISATTY_: 5079814Sandreas.hansson@arm.com case OS::TIOCGETP_: 5089130Satgutier@umich.edu case OS::TIOCSETP_: 5099130Satgutier@umich.edu case OS::TIOCSETN_: 5109130Satgutier@umich.edu case OS::TIOCSETC_: 5119130Satgutier@umich.edu case OS::TIOCGETC_: 5129130Satgutier@umich.edu case OS::TIOCGETS_: 5139130Satgutier@umich.edu case OS::TIOCGETA_: 5149130Satgutier@umich.edu case OS::TCSETAW_: 5159130Satgutier@umich.edu return -ENOTTY; 5169130Satgutier@umich.edu 5179130Satgutier@umich.edu default: 5189130Satgutier@umich.edu fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 5199130Satgutier@umich.edu fd, req, tc->pcState()); 5209130Satgutier@umich.edu } 5219130Satgutier@umich.edu} 5229130Satgutier@umich.edu 5239130Satgutier@umich.edu/// Target open() handler. 5249130Satgutier@umich.edutemplate <class OS> 5259130Satgutier@umich.eduSyscallReturn 5269130Satgutier@umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5279130Satgutier@umich.edu ThreadContext *tc) 5289130Satgutier@umich.edu{ 5299130Satgutier@umich.edu std::string path; 5307583SAli.Saidi@arm.com 5317583SAli.Saidi@arm.com int index = 0; 5327583SAli.Saidi@arm.com if (!tc->getMemPort()->tryReadString(path, 53310461SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) 53410461SAndreas.Sandberg@ARM.com return -EFAULT; 53510461SAndreas.Sandberg@ARM.com 53610461SAndreas.Sandberg@ARM.com if (path == "/dev/sysdev0") { 53710461SAndreas.Sandberg@ARM.com // This is a memory-mapped high-resolution timer device on Alpha. 53810461SAndreas.Sandberg@ARM.com // We don't support it, so just punt. 53910461SAndreas.Sandberg@ARM.com warn("Ignoring open(%s, ...)\n", path); 5408302SAli.Saidi@ARM.com return -ENOENT; 5418302SAli.Saidi@ARM.com } 5427783SGiacomo.Gabrielli@arm.com 5437783SGiacomo.Gabrielli@arm.com int tgtFlags = process->getSyscallArg(tc, index); 5447783SGiacomo.Gabrielli@arm.com int mode = process->getSyscallArg(tc, index); 5457783SGiacomo.Gabrielli@arm.com int hostFlags = 0; 54610037SARM gem5 Developers 54710037SARM gem5 Developers // translate open flags 54810037SARM gem5 Developers for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 54910037SARM gem5 Developers if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 55010037SARM gem5 Developers tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 55110037SARM gem5 Developers hostFlags |= OS::openFlagTable[i].hostFlag; 55210037SARM gem5 Developers } 55310037SARM gem5 Developers } 55410037SARM gem5 Developers 55510037SARM gem5 Developers // any target flags left? 55610037SARM gem5 Developers if (tgtFlags != 0) 55710037SARM gem5 Developers warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 55810037SARM gem5 Developers 55910037SARM gem5 Developers#ifdef __CYGWIN32__ 56010037SARM gem5 Developers hostFlags |= O_BINARY; 56110037SARM gem5 Developers#endif 56210037SARM gem5 Developers 56310037SARM gem5 Developers // Adjust path for current working directory 56410037SARM gem5 Developers path = process->fullPath(path); 56510037SARM gem5 Developers 56610037SARM gem5 Developers DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 56710037SARM gem5 Developers 56810037SARM gem5 Developers int fd; 56910037SARM gem5 Developers if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 57010037SARM gem5 Developers !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 57110037SARM gem5 Developers // It's a proc/sys entery and requires special handling 57210037SARM gem5 Developers fd = OS::openSpecialFile(path, process, tc); 57310037SARM gem5 Developers return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 57410037SARM gem5 Developers } else { 57510037SARM gem5 Developers // open the file 57610037SARM gem5 Developers fd = open(path.c_str(), hostFlags, mode); 57710037SARM gem5 Developers return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 57810338SCurtis.Dunham@arm.com } 57910338SCurtis.Dunham@arm.com 58010338SCurtis.Dunham@arm.com} 58110037SARM gem5 Developers 58210037SARM gem5 Developers/// Target sysinfo() handler. 58310037SARM gem5 Developerstemplate <class OS> 58410037SARM gem5 DevelopersSyscallReturn 58510037SARM gem5 DeveloperssysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 58610037SARM gem5 Developers ThreadContext *tc) 58710037SARM gem5 Developers{ 58810037SARM gem5 Developers 58910037SARM gem5 Developers int index = 0; 59010037SARM gem5 Developers TypedBufferArg<typename OS::tgt_sysinfo> 59110037SARM gem5 Developers sysinfo(process->getSyscallArg(tc, index)); 59210037SARM gem5 Developers 59310037SARM gem5 Developers sysinfo->uptime=seconds_since_epoch; 59410037SARM gem5 Developers sysinfo->totalram=process->system->memSize(); 59510037SARM gem5 Developers 59610037SARM gem5 Developers sysinfo.copyOut(tc->getMemPort()); 59710037SARM gem5 Developers 59810037SARM gem5 Developers return 0; 59910037SARM gem5 Developers} 60010037SARM gem5 Developers 60110037SARM gem5 Developers/// Target chmod() handler. 60210037SARM gem5 Developerstemplate <class OS> 60310037SARM gem5 DevelopersSyscallReturn 60410037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 60510037SARM gem5 Developers ThreadContext *tc) 60610037SARM gem5 Developers{ 60710037SARM gem5 Developers std::string path; 60810037SARM gem5 Developers 6098549Sdaniel.johnson@arm.com int index = 0; 6108868SMatt.Horsnell@arm.com if (!tc->getMemPort()->tryReadString(path, 6118868SMatt.Horsnell@arm.com process->getSyscallArg(tc, index))) { 6128868SMatt.Horsnell@arm.com return -EFAULT; 6138868SMatt.Horsnell@arm.com } 6148868SMatt.Horsnell@arm.com 6158868SMatt.Horsnell@arm.com uint32_t mode = process->getSyscallArg(tc, index); 6168868SMatt.Horsnell@arm.com mode_t hostMode = 0; 6178868SMatt.Horsnell@arm.com 6188868SMatt.Horsnell@arm.com // XXX translate mode flags via OS::something??? 61910461SAndreas.Sandberg@ARM.com hostMode = mode; 6208868SMatt.Horsnell@arm.com 62110461SAndreas.Sandberg@ARM.com // Adjust path for current working directory 62210037SARM gem5 Developers path = process->fullPath(path); 6238868SMatt.Horsnell@arm.com 62410037SARM gem5 Developers // do the chmod 62511150Smitch.hayenga@arm.com int result = chmod(path.c_str(), hostMode); 62610037SARM gem5 Developers if (result < 0) 62710037SARM gem5 Developers return -errno; 62810037SARM gem5 Developers 62910037SARM gem5 Developers return 0; 63011150Smitch.hayenga@arm.com} 63110037SARM gem5 Developers 63210037SARM gem5 Developers 63310037SARM gem5 Developers/// Target fchmod() handler. 63410037SARM gem5 Developerstemplate <class OS> 63510037SARM gem5 DevelopersSyscallReturn 63610037SARM gem5 DevelopersfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 63710037SARM gem5 Developers ThreadContext *tc) 63810037SARM gem5 Developers{ 63910037SARM gem5 Developers int index = 0; 64010037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 64110037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 64210037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 64310037SARM gem5 Developers return -EBADF; 64410037SARM gem5 Developers } 64510037SARM gem5 Developers 64610037SARM gem5 Developers uint32_t mode = process->getSyscallArg(tc, index); 64710037SARM gem5 Developers mode_t hostMode = 0; 64810037SARM gem5 Developers 64910037SARM gem5 Developers // XXX translate mode flags via OS::someting??? 65010037SARM gem5 Developers hostMode = mode; 65110037SARM gem5 Developers 65210037SARM gem5 Developers // do the fchmod 65310037SARM gem5 Developers int result = fchmod(process->sim_fd(fd), hostMode); 65410037SARM gem5 Developers if (result < 0) 65510037SARM gem5 Developers return -errno; 65610037SARM gem5 Developers 65710037SARM gem5 Developers return 0; 65810037SARM gem5 Developers} 65910037SARM gem5 Developers 66011769SCurtis.Dunham@arm.com/// Target mremap() handler. 66111769SCurtis.Dunham@arm.comtemplate <class OS> 66210037SARM gem5 DevelopersSyscallReturn 66311770SCurtis.Dunham@arm.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 66411770SCurtis.Dunham@arm.com{ 66510037SARM gem5 Developers int index = 0; 66611770SCurtis.Dunham@arm.com Addr start = process->getSyscallArg(tc, index); 66711769SCurtis.Dunham@arm.com uint64_t old_length = process->getSyscallArg(tc, index); 66810844Sandreas.sandberg@arm.com uint64_t new_length = process->getSyscallArg(tc, index); 66911772SCurtis.Dunham@arm.com uint64_t flags = process->getSyscallArg(tc, index); 67011772SCurtis.Dunham@arm.com 67111772SCurtis.Dunham@arm.com if ((start % TheISA::VMPageSize != 0) || 67211772SCurtis.Dunham@arm.com (new_length % TheISA::VMPageSize != 0)) { 67311774SCurtis.Dunham@arm.com warn("mremap failing: arguments not page aligned"); 67411774SCurtis.Dunham@arm.com return -EINVAL; 67511774SCurtis.Dunham@arm.com } 67611774SCurtis.Dunham@arm.com 67711774SCurtis.Dunham@arm.com if (new_length > old_length) { 67811774SCurtis.Dunham@arm.com if ((start + old_length) == process->mmap_end) { 67911774SCurtis.Dunham@arm.com uint64_t diff = new_length - old_length; 68011773SCurtis.Dunham@arm.com process->allocateMem(process->mmap_end, diff); 68111773SCurtis.Dunham@arm.com process->mmap_end += diff; 68211773SCurtis.Dunham@arm.com return start; 68311773SCurtis.Dunham@arm.com } else { 68411773SCurtis.Dunham@arm.com // sys/mman.h defined MREMAP_MAYMOVE 68511773SCurtis.Dunham@arm.com if (!(flags & 1)) { 68611773SCurtis.Dunham@arm.com warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 68711772SCurtis.Dunham@arm.com return -ENOMEM; 68810037SARM gem5 Developers } else { 68912816Sgiacomo.travaglini@arm.com process->pTable->remap(start, old_length, process->mmap_end); 69012816Sgiacomo.travaglini@arm.com warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 69112816Sgiacomo.travaglini@arm.com process->mmap_end, process->mmap_end + new_length, new_length); 69210844Sandreas.sandberg@arm.com start = process->mmap_end; 69310844Sandreas.sandberg@arm.com // add on the remaining unallocated pages 69410844Sandreas.sandberg@arm.com process->allocateMem(start + old_length, 69510844Sandreas.sandberg@arm.com new_length - old_length); 69610844Sandreas.sandberg@arm.com process->mmap_end += new_length; 69710844Sandreas.sandberg@arm.com warn("returning %08p as start\n", start); 69810188Sgeoffrey.blake@arm.com return start; 69910037SARM gem5 Developers } 70010037SARM gem5 Developers } 7017405SAli.Saidi@ARM.com } else { 7027405SAli.Saidi@ARM.com process->pTable->unmap(start + new_length, old_length - new_length); 7037405SAli.Saidi@ARM.com return start; 7047405SAli.Saidi@ARM.com } 7057405SAli.Saidi@ARM.com} 7067405SAli.Saidi@ARM.com 7077405SAli.Saidi@ARM.com/// Target stat() handler. 7087405SAli.Saidi@ARM.comtemplate <class OS> 7097614Sminkyu.jeong@arm.comSyscallReturn 71012478SCurtis.Dunham@arm.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 71112478SCurtis.Dunham@arm.com ThreadContext *tc) 71212478SCurtis.Dunham@arm.com{ 71312478SCurtis.Dunham@arm.com std::string path; 71412478SCurtis.Dunham@arm.com 71511771SCurtis.Dunham@arm.com int index = 0; 71612478SCurtis.Dunham@arm.com if (!tc->getMemPort()->tryReadString(path, 71712478SCurtis.Dunham@arm.com process->getSyscallArg(tc, index))) { 71810037SARM gem5 Developers return -EFAULT; 71912478SCurtis.Dunham@arm.com } 72010037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 72112478SCurtis.Dunham@arm.com 72210037SARM gem5 Developers // Adjust path for current working directory 72312478SCurtis.Dunham@arm.com path = process->fullPath(path); 72410037SARM gem5 Developers 7257405SAli.Saidi@ARM.com struct stat hostBuf; 7267405SAli.Saidi@ARM.com int result = stat(path.c_str(), &hostBuf); 7277405SAli.Saidi@ARM.com 7287405SAli.Saidi@ARM.com if (result < 0) 7297405SAli.Saidi@ARM.com return -errno; 7307749SAli.Saidi@ARM.com 7317405SAli.Saidi@ARM.com copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 73210037SARM gem5 Developers 73310037SARM gem5 Developers return 0; 7348284SAli.Saidi@ARM.com} 7357405SAli.Saidi@ARM.com 7367405SAli.Saidi@ARM.com 7377749SAli.Saidi@ARM.com/// Target stat64() handler. 7387749SAli.Saidi@ARM.comtemplate <class OS> 7397749SAli.Saidi@ARM.comSyscallReturn 7407749SAli.Saidi@ARM.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 7417405SAli.Saidi@ARM.com ThreadContext *tc) 74212510Sgiacomo.travaglini@arm.com{ 74312406Sgabeblack@google.com std::string path; 74412406Sgabeblack@google.com 7457749SAli.Saidi@ARM.com int index = 0; 7467749SAli.Saidi@ARM.com if (!tc->getMemPort()->tryReadString(path, 7477614Sminkyu.jeong@arm.com process->getSyscallArg(tc, index))) 7487614Sminkyu.jeong@arm.com return -EFAULT; 7497720Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 7507720Sgblack@eecs.umich.edu 7517720Sgblack@eecs.umich.edu // Adjust path for current working directory 75212763Sgiacomo.travaglini@arm.com path = process->fullPath(path); 7538887Sgeoffrey.blake@arm.com 7548887Sgeoffrey.blake@arm.com#if NO_STAT64 7558887Sgeoffrey.blake@arm.com struct stat hostBuf; 7568887Sgeoffrey.blake@arm.com int result = stat(path.c_str(), &hostBuf); 7578887Sgeoffrey.blake@arm.com#else 7588887Sgeoffrey.blake@arm.com struct stat64 hostBuf; 7598887Sgeoffrey.blake@arm.com int result = stat64(path.c_str(), &hostBuf); 7608887Sgeoffrey.blake@arm.com#endif 7618887Sgeoffrey.blake@arm.com 7627408Sgblack@eecs.umich.edu if (result < 0) 76310037SARM gem5 Developers return -errno; 76410037SARM gem5 Developers 76510037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 76610037SARM gem5 Developers 76710037SARM gem5 Developers return 0; 76810037SARM gem5 Developers} 76910037SARM gem5 Developers 77010037SARM gem5 Developers 77110037SARM gem5 Developers/// Target fstat64() handler. 77210037SARM gem5 Developerstemplate <class OS> 77310037SARM gem5 DevelopersSyscallReturn 7747408Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 7757408Sgblack@eecs.umich.edu ThreadContext *tc) 7768206SWilliam.Wang@arm.com{ 7778206SWilliam.Wang@arm.com int index = 0; 7788206SWilliam.Wang@arm.com int fd = process->getSyscallArg(tc, index); 7798206SWilliam.Wang@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 7808206SWilliam.Wang@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 7818206SWilliam.Wang@arm.com // doesn't map to any simulator fd: not a valid target fd 7828206SWilliam.Wang@arm.com return -EBADF; 7838206SWilliam.Wang@arm.com } 78410037SARM gem5 Developers 78510037SARM gem5 Developers#if NO_STAT64 78610037SARM gem5 Developers struct stat hostBuf; 78710037SARM gem5 Developers int result = fstat(process->sim_fd(fd), &hostBuf); 78810037SARM gem5 Developers#else 78912667Schuan.zhu@arm.com struct stat64 hostBuf; 79010037SARM gem5 Developers int result = fstat64(process->sim_fd(fd), &hostBuf); 79110037SARM gem5 Developers#endif 79210037SARM gem5 Developers 79310037SARM gem5 Developers if (result < 0) 79410037SARM gem5 Developers return -errno; 79510037SARM gem5 Developers 79610037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); 79710037SARM gem5 Developers 7988206SWilliam.Wang@arm.com return 0; 79910037SARM gem5 Developers} 80010037SARM gem5 Developers 80110037SARM gem5 Developers 80210037SARM gem5 Developers/// Target lstat() handler. 80310037SARM gem5 Developerstemplate <class OS> 80410037SARM gem5 DevelopersSyscallReturn 80510037SARM gem5 DeveloperslstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 80610037SARM gem5 Developers ThreadContext *tc) 80710037SARM gem5 Developers{ 80810037SARM gem5 Developers std::string path; 80910037SARM gem5 Developers 81010037SARM gem5 Developers int index = 0; 81110037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, 81210037SARM gem5 Developers process->getSyscallArg(tc, index))) { 81310037SARM gem5 Developers return -EFAULT; 81410037SARM gem5 Developers } 81510037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 81610037SARM gem5 Developers 81710037SARM gem5 Developers // Adjust path for current working directory 81810037SARM gem5 Developers path = process->fullPath(path); 81910037SARM gem5 Developers 82010037SARM gem5 Developers struct stat hostBuf; 82110037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 82210037SARM gem5 Developers 82310037SARM gem5 Developers if (result < 0) 82410037SARM gem5 Developers return -errno; 82510037SARM gem5 Developers 82610037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 82710037SARM gem5 Developers 8288206SWilliam.Wang@arm.com return 0; 8298206SWilliam.Wang@arm.com} 8307408Sgblack@eecs.umich.edu 8317408Sgblack@eecs.umich.edu/// Target lstat64() handler. 8327408Sgblack@eecs.umich.edutemplate <class OS> 8337731SAli.Saidi@ARM.comSyscallReturn 8348206SWilliam.Wang@arm.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 83510037SARM gem5 Developers ThreadContext *tc) 83610037SARM gem5 Developers{ 83710037SARM gem5 Developers std::string path; 83810037SARM gem5 Developers 83910037SARM gem5 Developers int index = 0; 8407408Sgblack@eecs.umich.edu if (!tc->getMemPort()->tryReadString(path, 8417408Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 8427408Sgblack@eecs.umich.edu return -EFAULT; 8437408Sgblack@eecs.umich.edu } 8447408Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8457408Sgblack@eecs.umich.edu 8467408Sgblack@eecs.umich.edu // Adjust path for current working directory 8477408Sgblack@eecs.umich.edu path = process->fullPath(path); 8487408Sgblack@eecs.umich.edu 8497408Sgblack@eecs.umich.edu#if NO_STAT64 85010037SARM gem5 Developers struct stat hostBuf; 85110037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 85210037SARM gem5 Developers#else 85310037SARM gem5 Developers struct stat64 hostBuf; 85410037SARM gem5 Developers int result = lstat64(path.c_str(), &hostBuf); 85510037SARM gem5 Developers#endif 8567408Sgblack@eecs.umich.edu 8577408Sgblack@eecs.umich.edu if (result < 0) 8587408Sgblack@eecs.umich.edu return -errno; 8597408Sgblack@eecs.umich.edu 8607408Sgblack@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); 8617408Sgblack@eecs.umich.edu 8627408Sgblack@eecs.umich.edu return 0; 8637408Sgblack@eecs.umich.edu} 8647408Sgblack@eecs.umich.edu 8657408Sgblack@eecs.umich.edu/// Target fstat() handler. 8667408Sgblack@eecs.umich.edutemplate <class OS> 8677408Sgblack@eecs.umich.eduSyscallReturn 86810037SARM gem5 DevelopersfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 86910037SARM gem5 Developers ThreadContext *tc) 8709377Sgblack@eecs.umich.edu{ 8717408Sgblack@eecs.umich.edu int index = 0; 8727408Sgblack@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 87310037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 87410037SARM gem5 Developers 87510037SARM gem5 Developers DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 87610037SARM gem5 Developers 87710037SARM gem5 Developers if (fd < 0) 87810037SARM gem5 Developers return -EBADF; 87910037SARM gem5 Developers 88010037SARM gem5 Developers struct stat hostBuf; 88110037SARM gem5 Developers int result = fstat(fd, &hostBuf); 88210037SARM gem5 Developers 88310037SARM gem5 Developers if (result < 0) 88410037SARM gem5 Developers return -errno; 88510037SARM gem5 Developers 88610037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); 88710037SARM gem5 Developers 88810037SARM gem5 Developers return 0; 88910037SARM gem5 Developers} 89010037SARM gem5 Developers 89110037SARM gem5 Developers 89210037SARM gem5 Developers/// Target statfs() handler. 89310037SARM gem5 Developerstemplate <class OS> 89410037SARM gem5 DevelopersSyscallReturn 89510037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 89610037SARM gem5 Developers ThreadContext *tc) 89710037SARM gem5 Developers{ 89810037SARM gem5 Developers std::string path; 89910037SARM gem5 Developers 90010037SARM gem5 Developers int index = 0; 90110037SARM gem5 Developers if (!tc->getMemPort()->tryReadString(path, 90210037SARM gem5 Developers process->getSyscallArg(tc, index))) { 90310037SARM gem5 Developers return -EFAULT; 90410037SARM gem5 Developers } 90510037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 90610037SARM gem5 Developers 90710037SARM gem5 Developers // Adjust path for current working directory 90810037SARM gem5 Developers path = process->fullPath(path); 90910037SARM gem5 Developers 9108302SAli.Saidi@ARM.com struct statfs hostBuf; 9118302SAli.Saidi@ARM.com int result = statfs(path.c_str(), &hostBuf); 9128302SAli.Saidi@ARM.com 91310037SARM gem5 Developers if (result < 0) 9148302SAli.Saidi@ARM.com return -errno; 9158302SAli.Saidi@ARM.com 9168302SAli.Saidi@ARM.com OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); 9177783SGiacomo.Gabrielli@arm.com 9187783SGiacomo.Gabrielli@arm.com return 0; 91910037SARM gem5 Developers} 92010037SARM gem5 Developers 9217783SGiacomo.Gabrielli@arm.com 9227783SGiacomo.Gabrielli@arm.com/// Target fstatfs() handler. 9237783SGiacomo.Gabrielli@arm.comtemplate <class OS> 9247783SGiacomo.Gabrielli@arm.comSyscallReturn 9257783SGiacomo.Gabrielli@arm.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 92610037SARM gem5 Developers ThreadContext *tc) 92710037SARM gem5 Developers{ 9287783SGiacomo.Gabrielli@arm.com int index = 0; 9297783SGiacomo.Gabrielli@arm.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 9307783SGiacomo.Gabrielli@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 9317408Sgblack@eecs.umich.edu 9327408Sgblack@eecs.umich.edu if (fd < 0) 9338206SWilliam.Wang@arm.com return -EBADF; 9348206SWilliam.Wang@arm.com 9357408Sgblack@eecs.umich.edu struct statfs hostBuf; 9367408Sgblack@eecs.umich.edu int result = fstatfs(fd, &hostBuf); 93710037SARM gem5 Developers 9387408Sgblack@eecs.umich.edu if (result < 0) 9397408Sgblack@eecs.umich.edu return -errno; 94010037SARM gem5 Developers 94110037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); 94210037SARM gem5 Developers 94310037SARM gem5 Developers return 0; 94410037SARM gem5 Developers} 94510037SARM gem5 Developers 94610037SARM gem5 Developers 94710037SARM gem5 Developers/// Target writev() handler. 94810037SARM gem5 Developerstemplate <class OS> 94910037SARM gem5 DevelopersSyscallReturn 95010037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 95110037SARM gem5 Developers ThreadContext *tc) 95210037SARM gem5 Developers{ 95310037SARM gem5 Developers int index = 0; 95410037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 95510037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 95610037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 95710037SARM gem5 Developers return -EBADF; 95810037SARM gem5 Developers } 95910037SARM gem5 Developers 96010037SARM gem5 Developers TranslatingPort *p = tc->getMemPort(); 96110037SARM gem5 Developers uint64_t tiov_base = process->getSyscallArg(tc, index); 96210037SARM gem5 Developers size_t count = process->getSyscallArg(tc, index); 96310037SARM gem5 Developers struct iovec hiov[count]; 96410037SARM gem5 Developers for (size_t i = 0; i < count; ++i) { 96510037SARM gem5 Developers typename OS::tgt_iovec tiov; 96610037SARM gem5 Developers 96710037SARM gem5 Developers p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 96810037SARM gem5 Developers (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 96910037SARM gem5 Developers hiov[i].iov_len = gtoh(tiov.iov_len); 97010037SARM gem5 Developers hiov[i].iov_base = new char [hiov[i].iov_len]; 97110037SARM gem5 Developers p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 97212406Sgabeblack@google.com hiov[i].iov_len); 97312406Sgabeblack@google.com } 97410037SARM gem5 Developers 9757408Sgblack@eecs.umich.edu int result = writev(process->sim_fd(fd), hiov, count); 9767408Sgblack@eecs.umich.edu 9777408Sgblack@eecs.umich.edu for (size_t i = 0; i < count; ++i) 97810037SARM gem5 Developers delete [] (char *)hiov[i].iov_base; 97912639Sgiacomo.travaglini@arm.com 98012639Sgiacomo.travaglini@arm.com if (result < 0) 98112639Sgiacomo.travaglini@arm.com return -errno; 98212639Sgiacomo.travaglini@arm.com 98312639Sgiacomo.travaglini@arm.com return 0; 98412639Sgiacomo.travaglini@arm.com} 98512639Sgiacomo.travaglini@arm.com 98612639Sgiacomo.travaglini@arm.com 98710037SARM gem5 Developers/// Target mmap() handler. 9887408Sgblack@eecs.umich.edu/// 98910037SARM gem5 Developers/// We don't really handle mmap(). If the target is mmaping an 99010037SARM gem5 Developers/// anonymous region or /dev/zero, we can get away with doing basically 99112406Sgabeblack@google.com/// nothing (since memory is initialized to zero and the simulator 99212406Sgabeblack@google.com/// doesn't really check addresses anyway). 9937408Sgblack@eecs.umich.edu/// 9949385SAndreas.Sandberg@arm.comtemplate <class OS> 9959385SAndreas.Sandberg@arm.comSyscallReturn 9969385SAndreas.Sandberg@arm.commmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 99710461SAndreas.Sandberg@ARM.com{ 9989385SAndreas.Sandberg@arm.com int index = 0; 9999385SAndreas.Sandberg@arm.com Addr start = p->getSyscallArg(tc, index); 10009385SAndreas.Sandberg@arm.com uint64_t length = p->getSyscallArg(tc, index); 10019385SAndreas.Sandberg@arm.com index++; // int prot = p->getSyscallArg(tc, index); 10029385SAndreas.Sandberg@arm.com int flags = p->getSyscallArg(tc, index); 10039385SAndreas.Sandberg@arm.com int tgt_fd = p->getSyscallArg(tc, index); 10049385SAndreas.Sandberg@arm.com // int offset = p->getSyscallArg(tc, index); 10059385SAndreas.Sandberg@arm.com 10069385SAndreas.Sandberg@arm.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 10079385SAndreas.Sandberg@arm.com Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 10089385SAndreas.Sandberg@arm.com if (!fd_map || fd_map->fd < 0) { 10099385SAndreas.Sandberg@arm.com warn("mmap failing: target fd %d is not valid\n", tgt_fd); 10109385SAndreas.Sandberg@arm.com return -EBADF; 10117408Sgblack@eecs.umich.edu } 10127408Sgblack@eecs.umich.edu 10137408Sgblack@eecs.umich.edu if (fd_map->filename != "/dev/zero") { 101410037SARM gem5 Developers // This is very likely broken, but leave a warning here 101510037SARM gem5 Developers // (rather than panic) in case /dev/zero is known by 101610037SARM gem5 Developers // another name on some platform 101710037SARM gem5 Developers warn("allowing mmap of file %s; mmap not supported on files" 101810037SARM gem5 Developers " other than /dev/zero\n", fd_map->filename); 101910037SARM gem5 Developers } 102010037SARM gem5 Developers } 102110037SARM gem5 Developers 102210037SARM gem5 Developers if ((start % TheISA::VMPageSize) != 0 || 102313116Sgiacomo.travaglini@arm.com (length % TheISA::VMPageSize) != 0) { 102410037SARM gem5 Developers warn("mmap failing: arguments not page-aligned: " 102510037SARM gem5 Developers "start 0x%x length 0x%x", 10269385SAndreas.Sandberg@arm.com start, length); 10277408Sgblack@eecs.umich.edu return -EINVAL; 10289385SAndreas.Sandberg@arm.com } 102912605Sgiacomo.travaglini@arm.com 103012605Sgiacomo.travaglini@arm.com // are we ok with clobbering existing mappings? only set this to 103112605Sgiacomo.travaglini@arm.com // true if the user has been warned. 103212605Sgiacomo.travaglini@arm.com bool clobber = false; 103312605Sgiacomo.travaglini@arm.com 103412605Sgiacomo.travaglini@arm.com // try to use the caller-provided address if there is one 103512605Sgiacomo.travaglini@arm.com bool use_provided_address = (start != 0); 103612605Sgiacomo.travaglini@arm.com 103712605Sgiacomo.travaglini@arm.com if (use_provided_address) { 103812605Sgiacomo.travaglini@arm.com // check to see if the desired address is already in use 103912605Sgiacomo.travaglini@arm.com if (!p->pTable->isUnmapped(start, length)) { 10407408Sgblack@eecs.umich.edu // there are existing mappings in the desired range 104112605Sgiacomo.travaglini@arm.com // whether we clobber them or not depends on whether the caller 104212605Sgiacomo.travaglini@arm.com // specified MAP_FIXED 104312605Sgiacomo.travaglini@arm.com if (flags & OS::TGT_MAP_FIXED) { 104412605Sgiacomo.travaglini@arm.com // MAP_FIXED specified: clobber existing mappings 104512605Sgiacomo.travaglini@arm.com warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 104612605Sgiacomo.travaglini@arm.com start); 104712605Sgiacomo.travaglini@arm.com clobber = true; 104812605Sgiacomo.travaglini@arm.com } else { 104912605Sgiacomo.travaglini@arm.com // MAP_FIXED not specified: ignore suggested start address 10507408Sgblack@eecs.umich.edu warn("mmap: ignoring suggested map address 0x%x\n", start); 105112605Sgiacomo.travaglini@arm.com use_provided_address = false; 105212605Sgiacomo.travaglini@arm.com } 105312605Sgiacomo.travaglini@arm.com } 105412605Sgiacomo.travaglini@arm.com } 105512605Sgiacomo.travaglini@arm.com 105612605Sgiacomo.travaglini@arm.com if (!use_provided_address) { 105712605Sgiacomo.travaglini@arm.com // no address provided, or provided address unusable: 105812605Sgiacomo.travaglini@arm.com // pick next address from our "mmap region" 105912605Sgiacomo.travaglini@arm.com if (OS::mmapGrowsDown()) { 10607408Sgblack@eecs.umich.edu start = p->mmap_end - length; 106112605Sgiacomo.travaglini@arm.com p->mmap_end = start; 106212605Sgiacomo.travaglini@arm.com } else { 106312605Sgiacomo.travaglini@arm.com start = p->mmap_end; 106412605Sgiacomo.travaglini@arm.com p->mmap_end += length; 106512605Sgiacomo.travaglini@arm.com } 106612605Sgiacomo.travaglini@arm.com } 106712605Sgiacomo.travaglini@arm.com 106812605Sgiacomo.travaglini@arm.com p->allocateMem(start, length, clobber); 106912605Sgiacomo.travaglini@arm.com 107012605Sgiacomo.travaglini@arm.com return start; 107112605Sgiacomo.travaglini@arm.com} 107212605Sgiacomo.travaglini@arm.com 107312605Sgiacomo.travaglini@arm.com/// Target getrlimit() handler. 107412576Sgiacomo.travaglini@arm.comtemplate <class OS> 107512605Sgiacomo.travaglini@arm.comSyscallReturn 107612605Sgiacomo.travaglini@arm.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 107712605Sgiacomo.travaglini@arm.com ThreadContext *tc) 107812605Sgiacomo.travaglini@arm.com{ 107912605Sgiacomo.travaglini@arm.com int index = 0; 108012605Sgiacomo.travaglini@arm.com unsigned resource = process->getSyscallArg(tc, index); 108112605Sgiacomo.travaglini@arm.com TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 108212605Sgiacomo.travaglini@arm.com 108312605Sgiacomo.travaglini@arm.com switch (resource) { 108412605Sgiacomo.travaglini@arm.com case OS::TGT_RLIMIT_STACK: 108512605Sgiacomo.travaglini@arm.com // max stack size in bytes: make up a number (8MB for now) 108612605Sgiacomo.travaglini@arm.com rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 108712605Sgiacomo.travaglini@arm.com rlp->rlim_cur = htog(rlp->rlim_cur); 108812605Sgiacomo.travaglini@arm.com rlp->rlim_max = htog(rlp->rlim_max); 108912576Sgiacomo.travaglini@arm.com break; 109012605Sgiacomo.travaglini@arm.com 109112605Sgiacomo.travaglini@arm.com case OS::TGT_RLIMIT_DATA: 109212605Sgiacomo.travaglini@arm.com // max data segment size in bytes: make up a number 109312605Sgiacomo.travaglini@arm.com rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 109412605Sgiacomo.travaglini@arm.com rlp->rlim_cur = htog(rlp->rlim_cur); 109512605Sgiacomo.travaglini@arm.com rlp->rlim_max = htog(rlp->rlim_max); 109612605Sgiacomo.travaglini@arm.com break; 109712605Sgiacomo.travaglini@arm.com 109812605Sgiacomo.travaglini@arm.com default: 109912605Sgiacomo.travaglini@arm.com std::cerr << "getrlimitFunc: unimplemented resource " << resource 110012605Sgiacomo.travaglini@arm.com << std::endl; 110112605Sgiacomo.travaglini@arm.com abort(); 110212605Sgiacomo.travaglini@arm.com break; 110312605Sgiacomo.travaglini@arm.com } 110412605Sgiacomo.travaglini@arm.com 110512605Sgiacomo.travaglini@arm.com rlp.copyOut(tc->getMemPort()); 110612605Sgiacomo.travaglini@arm.com return 0; 110712605Sgiacomo.travaglini@arm.com} 110812605Sgiacomo.travaglini@arm.com 110912605Sgiacomo.travaglini@arm.com/// Target gettimeofday() handler. 111012605Sgiacomo.travaglini@arm.comtemplate <class OS> 111112605Sgiacomo.travaglini@arm.comSyscallReturn 111212605Sgiacomo.travaglini@arm.comgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 111312605Sgiacomo.travaglini@arm.com ThreadContext *tc) 111412605Sgiacomo.travaglini@arm.com{ 111512605Sgiacomo.travaglini@arm.com int index = 0; 11167408Sgblack@eecs.umich.edu TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 111712605Sgiacomo.travaglini@arm.com 111812605Sgiacomo.travaglini@arm.com getElapsedTime(tp->tv_sec, tp->tv_usec); 111912605Sgiacomo.travaglini@arm.com tp->tv_sec += seconds_since_epoch; 112012605Sgiacomo.travaglini@arm.com tp->tv_sec = TheISA::htog(tp->tv_sec); 112112605Sgiacomo.travaglini@arm.com tp->tv_usec = TheISA::htog(tp->tv_usec); 112212605Sgiacomo.travaglini@arm.com 112312605Sgiacomo.travaglini@arm.com tp.copyOut(tc->getMemPort()); 112412605Sgiacomo.travaglini@arm.com 112512605Sgiacomo.travaglini@arm.com return 0; 112612605Sgiacomo.travaglini@arm.com} 112712605Sgiacomo.travaglini@arm.com 112812605Sgiacomo.travaglini@arm.com 112912605Sgiacomo.travaglini@arm.com/// Target utimes() handler. 113012605Sgiacomo.travaglini@arm.comtemplate <class OS> 113112605Sgiacomo.travaglini@arm.comSyscallReturn 113212605Sgiacomo.travaglini@arm.comutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 113312576Sgiacomo.travaglini@arm.com ThreadContext *tc) 113412605Sgiacomo.travaglini@arm.com{ 113512605Sgiacomo.travaglini@arm.com std::string path; 113612605Sgiacomo.travaglini@arm.com 113712605Sgiacomo.travaglini@arm.com int index = 0; 113812605Sgiacomo.travaglini@arm.com if (!tc->getMemPort()->tryReadString(path, 113912605Sgiacomo.travaglini@arm.com process->getSyscallArg(tc, index))) { 114012605Sgiacomo.travaglini@arm.com return -EFAULT; 114112605Sgiacomo.travaglini@arm.com } 114212605Sgiacomo.travaglini@arm.com 114312605Sgiacomo.travaglini@arm.com TypedBufferArg<typename OS::timeval [2]> 114412605Sgiacomo.travaglini@arm.com tp(process->getSyscallArg(tc, index)); 114512605Sgiacomo.travaglini@arm.com tp.copyIn(tc->getMemPort()); 114612576Sgiacomo.travaglini@arm.com 114712605Sgiacomo.travaglini@arm.com struct timeval hostTimeval[2]; 114812605Sgiacomo.travaglini@arm.com for (int i = 0; i < 2; ++i) 114912605Sgiacomo.travaglini@arm.com { 115012605Sgiacomo.travaglini@arm.com hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 115112605Sgiacomo.travaglini@arm.com hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 115212605Sgiacomo.travaglini@arm.com } 115312605Sgiacomo.travaglini@arm.com 115412605Sgiacomo.travaglini@arm.com // Adjust path for current working directory 115512605Sgiacomo.travaglini@arm.com path = process->fullPath(path); 115612605Sgiacomo.travaglini@arm.com 115712605Sgiacomo.travaglini@arm.com int result = utimes(path.c_str(), hostTimeval); 115812605Sgiacomo.travaglini@arm.com 115912605Sgiacomo.travaglini@arm.com if (result < 0) 116012605Sgiacomo.travaglini@arm.com return -errno; 116112605Sgiacomo.travaglini@arm.com 116212576Sgiacomo.travaglini@arm.com return 0; 116312605Sgiacomo.travaglini@arm.com} 116412605Sgiacomo.travaglini@arm.com/// Target getrusage() function. 116512605Sgiacomo.travaglini@arm.comtemplate <class OS> 116612605Sgiacomo.travaglini@arm.comSyscallReturn 116712605Sgiacomo.travaglini@arm.comgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 116812605Sgiacomo.travaglini@arm.com ThreadContext *tc) 116912605Sgiacomo.travaglini@arm.com{ 117012605Sgiacomo.travaglini@arm.com int index = 0; 117112605Sgiacomo.travaglini@arm.com int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 117212605Sgiacomo.travaglini@arm.com TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 117312605Sgiacomo.travaglini@arm.com 117412605Sgiacomo.travaglini@arm.com rup->ru_utime.tv_sec = 0; 117512576Sgiacomo.travaglini@arm.com rup->ru_utime.tv_usec = 0; 117612605Sgiacomo.travaglini@arm.com rup->ru_stime.tv_sec = 0; 117712605Sgiacomo.travaglini@arm.com rup->ru_stime.tv_usec = 0; 117812605Sgiacomo.travaglini@arm.com rup->ru_maxrss = 0; 117912605Sgiacomo.travaglini@arm.com rup->ru_ixrss = 0; 118012605Sgiacomo.travaglini@arm.com rup->ru_idrss = 0; 118112605Sgiacomo.travaglini@arm.com rup->ru_isrss = 0; 118212605Sgiacomo.travaglini@arm.com rup->ru_minflt = 0; 118312605Sgiacomo.travaglini@arm.com rup->ru_majflt = 0; 118412605Sgiacomo.travaglini@arm.com rup->ru_nswap = 0; 118512605Sgiacomo.travaglini@arm.com rup->ru_inblock = 0; 118612605Sgiacomo.travaglini@arm.com rup->ru_oublock = 0; 118712605Sgiacomo.travaglini@arm.com rup->ru_msgsnd = 0; 118812605Sgiacomo.travaglini@arm.com rup->ru_msgrcv = 0; 118912605Sgiacomo.travaglini@arm.com rup->ru_nsignals = 0; 119012605Sgiacomo.travaglini@arm.com rup->ru_nvcsw = 0; 119112577Sgiacomo.travaglini@arm.com rup->ru_nivcsw = 0; 119212605Sgiacomo.travaglini@arm.com 119312605Sgiacomo.travaglini@arm.com switch (who) { 119412605Sgiacomo.travaglini@arm.com case OS::TGT_RUSAGE_SELF: 119512605Sgiacomo.travaglini@arm.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 119612605Sgiacomo.travaglini@arm.com rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 119712605Sgiacomo.travaglini@arm.com rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 119812605Sgiacomo.travaglini@arm.com break; 119912605Sgiacomo.travaglini@arm.com 120012605Sgiacomo.travaglini@arm.com case OS::TGT_RUSAGE_CHILDREN: 120112605Sgiacomo.travaglini@arm.com // do nothing. We have no child processes, so they take no time. 120212605Sgiacomo.travaglini@arm.com break; 120312605Sgiacomo.travaglini@arm.com 120412605Sgiacomo.travaglini@arm.com default: 120512605Sgiacomo.travaglini@arm.com // don't really handle THREAD or CHILDREN, but just warn and 120612577Sgiacomo.travaglini@arm.com // plow ahead 120712605Sgiacomo.travaglini@arm.com warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 120812605Sgiacomo.travaglini@arm.com who); 120912605Sgiacomo.travaglini@arm.com } 121012605Sgiacomo.travaglini@arm.com 121112605Sgiacomo.travaglini@arm.com rup.copyOut(tc->getMemPort()); 121212605Sgiacomo.travaglini@arm.com 121312605Sgiacomo.travaglini@arm.com return 0; 121412605Sgiacomo.travaglini@arm.com} 121512605Sgiacomo.travaglini@arm.com 121612605Sgiacomo.travaglini@arm.com/// Target times() function. 121712605Sgiacomo.travaglini@arm.comtemplate <class OS> 121812605Sgiacomo.travaglini@arm.comSyscallReturn 121910037SARM gem5 DeveloperstimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 122012605Sgiacomo.travaglini@arm.com ThreadContext *tc) 122112605Sgiacomo.travaglini@arm.com{ 122212605Sgiacomo.travaglini@arm.com int index = 0; 122312605Sgiacomo.travaglini@arm.com TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 122412605Sgiacomo.travaglini@arm.com 122512605Sgiacomo.travaglini@arm.com // Fill in the time structure (in clocks) 122612605Sgiacomo.travaglini@arm.com int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 122712605Sgiacomo.travaglini@arm.com bufp->tms_utime = clocks; 122812605Sgiacomo.travaglini@arm.com bufp->tms_stime = 0; 122912605Sgiacomo.travaglini@arm.com bufp->tms_cutime = 0; 123012605Sgiacomo.travaglini@arm.com bufp->tms_cstime = 0; 123112605Sgiacomo.travaglini@arm.com 123212605Sgiacomo.travaglini@arm.com // Convert to host endianness 123310037SARM gem5 Developers bufp->tms_utime = htog(bufp->tms_utime); 123412605Sgiacomo.travaglini@arm.com 123512605Sgiacomo.travaglini@arm.com // Write back 123612605Sgiacomo.travaglini@arm.com bufp.copyOut(tc->getMemPort()); 123712605Sgiacomo.travaglini@arm.com 123812605Sgiacomo.travaglini@arm.com // Return clock ticks since system boot 123912605Sgiacomo.travaglini@arm.com return clocks; 124012605Sgiacomo.travaglini@arm.com} 124112605Sgiacomo.travaglini@arm.com 124212605Sgiacomo.travaglini@arm.com/// Target time() function. 124312605Sgiacomo.travaglini@arm.comtemplate <class OS> 124412605Sgiacomo.travaglini@arm.comSyscallReturn 124512605Sgiacomo.travaglini@arm.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 124612605Sgiacomo.travaglini@arm.com ThreadContext *tc) 124710037SARM gem5 Developers{ 124812605Sgiacomo.travaglini@arm.com typename OS::time_t sec, usec; 124912605Sgiacomo.travaglini@arm.com getElapsedTime(sec, usec); 125012605Sgiacomo.travaglini@arm.com sec += seconds_since_epoch; 125112605Sgiacomo.travaglini@arm.com 125212605Sgiacomo.travaglini@arm.com int index = 0; 125312605Sgiacomo.travaglini@arm.com Addr taddr = (Addr)process->getSyscallArg(tc, index); 125412605Sgiacomo.travaglini@arm.com if(taddr != 0) { 125512605Sgiacomo.travaglini@arm.com typename OS::time_t t = sec; 125612605Sgiacomo.travaglini@arm.com t = htog(t); 125712605Sgiacomo.travaglini@arm.com TranslatingPort *p = tc->getMemPort(); 125812605Sgiacomo.travaglini@arm.com p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 125912605Sgiacomo.travaglini@arm.com } 126010037SARM gem5 Developers return sec; 126112605Sgiacomo.travaglini@arm.com} 126212605Sgiacomo.travaglini@arm.com 126312605Sgiacomo.travaglini@arm.com 126412605Sgiacomo.travaglini@arm.com#endif // __SIM_SYSCALL_EMUL_HH__ 126512605Sgiacomo.travaglini@arm.com