syscall_emul.hh revision 10486:9b848f3813c5
17170Sgblack@eecs.umich.edu/* 210339Smitch.hayenga@arm.com * Copyright (c) 2012-2013 ARM Limited 37170Sgblack@eecs.umich.edu * All rights reserved 47170Sgblack@eecs.umich.edu * 57170Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67170Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77170Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87170Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97170Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107170Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117170Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127170Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137170Sgblack@eecs.umich.edu * 147170Sgblack@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 157170Sgblack@eecs.umich.edu * All rights reserved. 167170Sgblack@eecs.umich.edu * 177170Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 187170Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 197170Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 207170Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 217170Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 227170Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237170Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 247170Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 257170Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 267170Sgblack@eecs.umich.edu * this software without specific prior written permission. 277170Sgblack@eecs.umich.edu * 287170Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297170Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307170Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317170Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327170Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337170Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 347170Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357170Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 367170Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 377170Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 387170Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397170Sgblack@eecs.umich.edu * 407170Sgblack@eecs.umich.edu * Authors: Steve Reinhardt 417170Sgblack@eecs.umich.edu * Kevin Lim 427170Sgblack@eecs.umich.edu */ 438229Snate@binkert.org 448229Snate@binkert.org#ifndef __SIM_SYSCALL_EMUL_HH__ 457170Sgblack@eecs.umich.edu#define __SIM_SYSCALL_EMUL_HH__ 4610037SARM gem5 Developers 478961Sgblack@eecs.umich.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 4810037SARM gem5 Developers defined(__FreeBSD__) || defined(__CYGWIN__) || \ 497170Sgblack@eecs.umich.edu defined(__NetBSD__)) 507853SMatt.Horsnell@ARM.com 517170Sgblack@eecs.umich.edu/// 527170Sgblack@eecs.umich.edu/// @file syscall_emul.hh 537170Sgblack@eecs.umich.edu/// 547170Sgblack@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target 557170Sgblack@eecs.umich.edu/// application on the host machine. 567170Sgblack@eecs.umich.edu 577170Sgblack@eecs.umich.edu#ifdef __CYGWIN32__ 587170Sgblack@eecs.umich.edu#include <sys/fcntl.h> // for O_BINARY 597170Sgblack@eecs.umich.edu#endif 607170Sgblack@eecs.umich.edu#include <sys/stat.h> 617170Sgblack@eecs.umich.edu#include <sys/time.h> 627170Sgblack@eecs.umich.edu#include <sys/uio.h> 637170Sgblack@eecs.umich.edu#include <fcntl.h> 6410346Smitch.hayenga@arm.com 658148SAli.Saidi@ARM.com#include <cerrno> 6610346Smitch.hayenga@arm.com#include <string> 6710346Smitch.hayenga@arm.com 6810346Smitch.hayenga@arm.com#include "base/chunk_generator.hh" 6910346Smitch.hayenga@arm.com#include "base/intmath.hh" // for RoundUp 7010346Smitch.hayenga@arm.com#include "base/misc.hh" 7110346Smitch.hayenga@arm.com#include "base/trace.hh" 7210346Smitch.hayenga@arm.com#include "base/types.hh" 7310346Smitch.hayenga@arm.com#include "config/the_isa.hh" 748148SAli.Saidi@ARM.com#include "cpu/base.hh" 7510346Smitch.hayenga@arm.com#include "cpu/thread_context.hh" 7610346Smitch.hayenga@arm.com#include "debug/SyscallVerbose.hh" 7710346Smitch.hayenga@arm.com#include "mem/page_table.hh" 7810346Smitch.hayenga@arm.com#include "mem/se_translating_port_proxy.hh" 7910346Smitch.hayenga@arm.com#include "sim/byteswap.hh" 8010346Smitch.hayenga@arm.com#include "sim/process.hh" 8110346Smitch.hayenga@arm.com#include "sim/syscallreturn.hh" 8210346Smitch.hayenga@arm.com#include "sim/system.hh" 8310346Smitch.hayenga@arm.com 848148SAli.Saidi@ARM.com/// 857170Sgblack@eecs.umich.edu/// System call descriptor. 8610346Smitch.hayenga@arm.com/// 877170Sgblack@eecs.umich.educlass SyscallDesc { 887170Sgblack@eecs.umich.edu 897170Sgblack@eecs.umich.edu public: 907170Sgblack@eecs.umich.edu 917170Sgblack@eecs.umich.edu /// Typedef for target syscall handler functions. 927170Sgblack@eecs.umich.edu typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 937170Sgblack@eecs.umich.edu LiveProcess *, ThreadContext *); 947170Sgblack@eecs.umich.edu 957190Sgblack@eecs.umich.edu const char *name; //!< Syscall name (e.g., "open"). 967190Sgblack@eecs.umich.edu FuncPtr funcPtr; //!< Pointer to emulation function. 977170Sgblack@eecs.umich.edu int flags; //!< Flags (see Flags enum). 987170Sgblack@eecs.umich.edu 9910346Smitch.hayenga@arm.com /// Flag values for controlling syscall behavior. 10010346Smitch.hayenga@arm.com enum Flags { 1017190Sgblack@eecs.umich.edu /// Don't set return regs according to funcPtr return value. 1027170Sgblack@eecs.umich.edu /// Used for syscalls with non-standard return conventions 10310346Smitch.hayenga@arm.com /// that explicitly set the ThreadContext regs (e.g., 10410346Smitch.hayenga@arm.com /// sigreturn). 10510346Smitch.hayenga@arm.com SuppressReturnValue = 1 10610346Smitch.hayenga@arm.com }; 10710346Smitch.hayenga@arm.com 10810346Smitch.hayenga@arm.com /// Constructor. 10910346Smitch.hayenga@arm.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 11010346Smitch.hayenga@arm.com : name(_name), funcPtr(_funcPtr), flags(_flags) 1117170Sgblack@eecs.umich.edu { 11210346Smitch.hayenga@arm.com } 11310346Smitch.hayenga@arm.com 11410346Smitch.hayenga@arm.com /// Emulate the syscall. Public interface for calling through funcPtr. 11510346Smitch.hayenga@arm.com void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1167170Sgblack@eecs.umich.edu}; 11710346Smitch.hayenga@arm.com 11810346Smitch.hayenga@arm.com 11910346Smitch.hayenga@arm.comclass BaseBufferArg { 12010346Smitch.hayenga@arm.com 1217170Sgblack@eecs.umich.edu public: 12210346Smitch.hayenga@arm.com 12310346Smitch.hayenga@arm.com BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 12410346Smitch.hayenga@arm.com { 12510346Smitch.hayenga@arm.com bufPtr = new uint8_t[size]; 12610346Smitch.hayenga@arm.com // clear out buffer: in case we only partially populate this, 12710346Smitch.hayenga@arm.com // and then do a copyOut(), we want to make sure we don't 12810346Smitch.hayenga@arm.com // introduce any random junk into the simulated address space 12910346Smitch.hayenga@arm.com memset(bufPtr, 0, size); 13010346Smitch.hayenga@arm.com } 13110346Smitch.hayenga@arm.com 13210346Smitch.hayenga@arm.com virtual ~BaseBufferArg() { delete [] bufPtr; } 13310346Smitch.hayenga@arm.com 13410346Smitch.hayenga@arm.com // 13510346Smitch.hayenga@arm.com // copy data into simulator space (read from target memory) 13610346Smitch.hayenga@arm.com // 13710346Smitch.hayenga@arm.com virtual bool copyIn(SETranslatingPortProxy &memproxy) 13810346Smitch.hayenga@arm.com { 13910346Smitch.hayenga@arm.com memproxy.readBlob(addr, bufPtr, size); 14010346Smitch.hayenga@arm.com return true; // no EFAULT detection for now 14110346Smitch.hayenga@arm.com } 14210346Smitch.hayenga@arm.com 14310346Smitch.hayenga@arm.com // 14410346Smitch.hayenga@arm.com // copy data out of simulator space (write to target memory) 14510346Smitch.hayenga@arm.com // 14610346Smitch.hayenga@arm.com virtual bool copyOut(SETranslatingPortProxy &memproxy) 14710346Smitch.hayenga@arm.com { 14811321Ssteve.reinhardt@amd.com memproxy.writeBlob(addr, bufPtr, size); 14910346Smitch.hayenga@arm.com return true; // no EFAULT detection for now 15010346Smitch.hayenga@arm.com } 15110346Smitch.hayenga@arm.com 15210346Smitch.hayenga@arm.com protected: 15310346Smitch.hayenga@arm.com Addr addr; 15410346Smitch.hayenga@arm.com int size; 15510346Smitch.hayenga@arm.com uint8_t *bufPtr; 15610346Smitch.hayenga@arm.com}; 15710346Smitch.hayenga@arm.com 15810346Smitch.hayenga@arm.com 15910346Smitch.hayenga@arm.comclass BufferArg : public BaseBufferArg 16010346Smitch.hayenga@arm.com{ 16110346Smitch.hayenga@arm.com public: 16210346Smitch.hayenga@arm.com BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 16310346Smitch.hayenga@arm.com void *bufferPtr() { return bufPtr; } 16410346Smitch.hayenga@arm.com}; 16510346Smitch.hayenga@arm.com 16610346Smitch.hayenga@arm.comtemplate <class T> 16710346Smitch.hayenga@arm.comclass TypedBufferArg : public BaseBufferArg 16810346Smitch.hayenga@arm.com{ 16910346Smitch.hayenga@arm.com public: 17010346Smitch.hayenga@arm.com // user can optionally specify a specific number of bytes to 17110346Smitch.hayenga@arm.com // allocate to deal with those structs that have variable-size 17210346Smitch.hayenga@arm.com // arrays at the end 17310346Smitch.hayenga@arm.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1749640Snathanael.premillieu@irisa.fr : BaseBufferArg(_addr, _size) 1759640Snathanael.premillieu@irisa.fr { } 1769640Snathanael.premillieu@irisa.fr 1779640Snathanael.premillieu@irisa.fr // type case 1788148SAli.Saidi@ARM.com operator T*() { return (T *)bufPtr; } 17910346Smitch.hayenga@arm.com 18010346Smitch.hayenga@arm.com // dereference operators 1817170Sgblack@eecs.umich.edu T &operator*() { return *((T *)bufPtr); } 18210346Smitch.hayenga@arm.com T* operator->() { return (T *)bufPtr; } 18310346Smitch.hayenga@arm.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 18410346Smitch.hayenga@arm.com}; 18510346Smitch.hayenga@arm.com 1867170Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 1877170Sgblack@eecs.umich.edu// 18810346Smitch.hayenga@arm.com// The following emulation functions are generic enough that they 18910346Smitch.hayenga@arm.com// don't need to be recompiled for different emulated OS's. They are 1907170Sgblack@eecs.umich.edu// defined in sim/syscall_emul.cc. 1917170Sgblack@eecs.umich.edu// 1928148SAli.Saidi@ARM.com////////////////////////////////////////////////////////////////////// 19310346Smitch.hayenga@arm.com 1948148SAli.Saidi@ARM.com 19510346Smitch.hayenga@arm.com/// Handler for unimplemented syscalls that we haven't thought about. 1968148SAli.Saidi@ARM.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 19710346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 1988148SAli.Saidi@ARM.com 19910346Smitch.hayenga@arm.com/// Handler for unimplemented syscalls that we never intend to 20010346Smitch.hayenga@arm.com/// implement (signal handling, etc.) and should not affect the correct 20110346Smitch.hayenga@arm.com/// behavior of the program. Print a warning only if the appropriate 20210346Smitch.hayenga@arm.com/// trace flag is enabled. Return success to the target program. 20310346Smitch.hayenga@arm.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 20410346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 20510346Smitch.hayenga@arm.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 20610346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 20710346Smitch.hayenga@arm.com 20810346Smitch.hayenga@arm.com/// Target exit() handler: terminate current context. 2099368Snathanael.premillieu@irisa.frSyscallReturn exitFunc(SyscallDesc *desc, int num, 2109368Snathanael.premillieu@irisa.fr LiveProcess *p, ThreadContext *tc); 2119368Snathanael.premillieu@irisa.fr 2129368Snathanael.premillieu@irisa.fr/// Target exit_group() handler: terminate simulation. (exit all threads) 2138148SAli.Saidi@ARM.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 21410346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 21510346Smitch.hayenga@arm.com 21610346Smitch.hayenga@arm.com/// Target getpagesize() handler. 21710346Smitch.hayenga@arm.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 2188148SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 2197170Sgblack@eecs.umich.edu 2207190Sgblack@eecs.umich.edu/// Target brk() handler: set brk address. 22110346Smitch.hayenga@arm.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 2227190Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 22310666SAli.Saidi@ARM.com 2247343Sgblack@eecs.umich.edu/// Target close() handler. 22510199SAndrew.Bardsley@arm.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 22610199SAndrew.Bardsley@arm.com LiveProcess *p, ThreadContext *tc); 22710199SAndrew.Bardsley@arm.com 22810199SAndrew.Bardsley@arm.com/// Target read() handler. 22910199SAndrew.Bardsley@arm.comSyscallReturn readFunc(SyscallDesc *desc, int num, 23010346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 23110346Smitch.hayenga@arm.com 23210199SAndrew.Bardsley@arm.com/// Target write() handler. 23310199SAndrew.Bardsley@arm.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 23410199SAndrew.Bardsley@arm.com LiveProcess *p, ThreadContext *tc); 23510199SAndrew.Bardsley@arm.com 23610199SAndrew.Bardsley@arm.com/// Target lseek() handler. 23710346Smitch.hayenga@arm.comSyscallReturn lseekFunc(SyscallDesc *desc, int num, 23810346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 2397343Sgblack@eecs.umich.edu 2407170Sgblack@eecs.umich.edu/// Target _llseek() handler. 2417170Sgblack@eecs.umich.eduSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 24210037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24310037SARM gem5 Developers 24410037SARM gem5 Developers/// Target munmap() handler. 24510037SARM gem5 DevelopersSyscallReturn munmapFunc(SyscallDesc *desc, int num, 24610037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 24710037SARM gem5 Developers 24810037SARM gem5 Developers/// Target gethostname() handler. 24910346Smitch.hayenga@arm.comSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 25010037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 25110346Smitch.hayenga@arm.com 25210346Smitch.hayenga@arm.com/// Target getcwd() handler. 25310346Smitch.hayenga@arm.comSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 25410346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 25510346Smitch.hayenga@arm.com 25610346Smitch.hayenga@arm.com/// Target readlink() handler. 25710346Smitch.hayenga@arm.comSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 25810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc, 25910037SARM gem5 Developers int index = 0); 26010037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 26110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 26210037SARM gem5 Developers 26310037SARM gem5 Developers/// Target unlink() handler. 26410346Smitch.hayenga@arm.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 26510346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 26610346Smitch.hayenga@arm.com 26710346Smitch.hayenga@arm.com/// Target mkdir() handler. 26810037SARM gem5 DevelopersSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 26910037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 27010037SARM gem5 Developers 27110037SARM gem5 Developers/// Target rename() handler. 27210346Smitch.hayenga@arm.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 27310346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 27410346Smitch.hayenga@arm.com 27510346Smitch.hayenga@arm.com 27610037SARM gem5 Developers/// Target truncate() handler. 27710346Smitch.hayenga@arm.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 27810346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 27910346Smitch.hayenga@arm.com 28010346Smitch.hayenga@arm.com 28110346Smitch.hayenga@arm.com/// Target ftruncate() handler. 28210346Smitch.hayenga@arm.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 28310346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 28410346Smitch.hayenga@arm.com 28510037SARM gem5 Developers 28610037SARM gem5 Developers/// Target truncate64() handler. 28710037SARM gem5 DevelopersSyscallReturn truncate64Func(SyscallDesc *desc, int num, 28810346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 28910346Smitch.hayenga@arm.com 29010037SARM gem5 Developers/// Target ftruncate64() handler. 29110346Smitch.hayenga@arm.comSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 29210346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 29310346Smitch.hayenga@arm.com 29410346Smitch.hayenga@arm.com 29510037SARM gem5 Developers/// Target umask() handler. 29610037SARM gem5 DevelopersSyscallReturn umaskFunc(SyscallDesc *desc, int num, 29710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 29810346Smitch.hayenga@arm.com 29910346Smitch.hayenga@arm.com 30010037SARM gem5 Developers/// Target chown() handler. 30110346Smitch.hayenga@arm.comSyscallReturn chownFunc(SyscallDesc *desc, int num, 30210346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 30310037SARM gem5 Developers 30410037SARM gem5 Developers 30510037SARM gem5 Developers/// Target fchown() handler. 30610037SARM gem5 DevelopersSyscallReturn fchownFunc(SyscallDesc *desc, int num, 30710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 30810346Smitch.hayenga@arm.com 30910346Smitch.hayenga@arm.com/// Target dup() handler. 31010346Smitch.hayenga@arm.comSyscallReturn dupFunc(SyscallDesc *desc, int num, 31110346Smitch.hayenga@arm.com LiveProcess *process, ThreadContext *tc); 31210037SARM gem5 Developers 31310346Smitch.hayenga@arm.com/// Target fnctl() handler. 31410037SARM gem5 DevelopersSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 31510037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 31610037SARM gem5 Developers 31710037SARM gem5 Developers/// Target fcntl64() handler. 31810037SARM gem5 DevelopersSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 31910346Smitch.hayenga@arm.com LiveProcess *process, ThreadContext *tc); 32010346Smitch.hayenga@arm.com 32110037SARM gem5 Developers/// Target setuid() handler. 32210346Smitch.hayenga@arm.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 32310346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 32410037SARM gem5 Developers 32510037SARM gem5 Developers/// Target getpid() handler. 32610346Smitch.hayenga@arm.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 32710346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 32810037SARM gem5 Developers 32910037SARM gem5 Developers/// Target getuid() handler. 33010037SARM gem5 DevelopersSyscallReturn getuidFunc(SyscallDesc *desc, int num, 33110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 33210037SARM gem5 Developers 33310346Smitch.hayenga@arm.com/// Target getgid() handler. 33410037SARM gem5 DevelopersSyscallReturn getgidFunc(SyscallDesc *desc, int num, 33510037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 33610037SARM gem5 Developers 33710346Smitch.hayenga@arm.com/// Target getppid() handler. 33810346Smitch.hayenga@arm.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 33910666SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 34010037SARM gem5 Developers 34110037SARM gem5 Developers/// Target geteuid() handler. 34210037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 34310037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 34410037SARM gem5 Developers 34510037SARM gem5 Developers/// Target getegid() handler. 34610037SARM gem5 DevelopersSyscallReturn getegidFunc(SyscallDesc *desc, int num, 34710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 34810037SARM gem5 Developers 34910037SARM gem5 Developers/// Target clone() handler. 35010037SARM gem5 DevelopersSyscallReturn cloneFunc(SyscallDesc *desc, int num, 35110037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 35210346Smitch.hayenga@arm.com 35310037SARM gem5 Developers/// Target access() handler 35410037SARM gem5 DevelopersSyscallReturn accessFunc(SyscallDesc *desc, int num, 35510346Smitch.hayenga@arm.com LiveProcess *p, ThreadContext *tc); 35610346Smitch.hayenga@arm.comSyscallReturn accessFunc(SyscallDesc *desc, int num, 35710037SARM gem5 Developers LiveProcess *p, ThreadContext *tc, 35810346Smitch.hayenga@arm.com int index); 35910037SARM gem5 Developers 36010346Smitch.hayenga@arm.com/// Futex system call 36110346Smitch.hayenga@arm.com/// Implemented by Daniel Sanchez 36210346Smitch.hayenga@arm.com/// Used by printf's in multi-threaded apps 36310037SARM gem5 Developerstemplate <class OS> 36410346Smitch.hayenga@arm.comSyscallReturn 36510666SAli.Saidi@ARM.comfutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 36610037SARM gem5 Developers ThreadContext *tc) 36710037SARM gem5 Developers{ 36810037SARM gem5 Developers int index_uaddr = 0; 36910037SARM gem5 Developers int index_op = 1; 37010037SARM gem5 Developers int index_val = 2; 37110037SARM gem5 Developers int index_timeout = 3; 37210037SARM gem5 Developers 37310346Smitch.hayenga@arm.com uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 37410037SARM gem5 Developers int op = process->getSyscallArg(tc, index_op); 37510037SARM gem5 Developers int val = process->getSyscallArg(tc, index_val); 37610346Smitch.hayenga@arm.com uint64_t timeout = process->getSyscallArg(tc, index_timeout); 37710346Smitch.hayenga@arm.com 37810037SARM gem5 Developers std::map<uint64_t, std::list<ThreadContext *> * > 37910346Smitch.hayenga@arm.com &futex_map = tc->getSystemPtr()->futexMap; 38010037SARM gem5 Developers 38110346Smitch.hayenga@arm.com DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 38210346Smitch.hayenga@arm.com uaddr, op, val); 38310037SARM gem5 Developers 38410346Smitch.hayenga@arm.com op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 38510346Smitch.hayenga@arm.com 38610666SAli.Saidi@ARM.com if (op == OS::TGT_FUTEX_WAIT) { 38710037SARM gem5 Developers if (timeout != 0) { 38810346Smitch.hayenga@arm.com warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 38910346Smitch.hayenga@arm.com "we'll wait indefinitely"); 39010346Smitch.hayenga@arm.com } 39110346Smitch.hayenga@arm.com 39210037SARM gem5 Developers uint8_t *buf = new uint8_t[sizeof(int)]; 39310037SARM gem5 Developers tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 39410037SARM gem5 Developers int mem_val = *((int *)buf); 39510037SARM gem5 Developers delete buf; 39610037SARM gem5 Developers 39710037SARM gem5 Developers if(val != mem_val) { 39810037SARM gem5 Developers DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 39910346Smitch.hayenga@arm.com "expected: %d\n", mem_val, val); 40010037SARM gem5 Developers return -OS::TGT_EWOULDBLOCK; 40110037SARM gem5 Developers } 40210346Smitch.hayenga@arm.com 40310346Smitch.hayenga@arm.com // Queue the thread context 40410037SARM gem5 Developers std::list<ThreadContext *> * tcWaitList; 40510346Smitch.hayenga@arm.com if (futex_map.count(uaddr)) { 40610037SARM gem5 Developers tcWaitList = futex_map.find(uaddr)->second; 40710346Smitch.hayenga@arm.com } else { 40810346Smitch.hayenga@arm.com tcWaitList = new std::list<ThreadContext *>(); 40910037SARM gem5 Developers futex_map.insert(std::pair< uint64_t, 41010346Smitch.hayenga@arm.com std::list<ThreadContext *> * >(uaddr, tcWaitList)); 41110346Smitch.hayenga@arm.com } 41210666SAli.Saidi@ARM.com tcWaitList->push_back(tc); 41310037SARM gem5 Developers DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 41410346Smitch.hayenga@arm.com "thread context\n"); 41510346Smitch.hayenga@arm.com tc->suspend(); 41610346Smitch.hayenga@arm.com return 0; 41710346Smitch.hayenga@arm.com } else if (op == OS::TGT_FUTEX_WAKE){ 41810037SARM gem5 Developers int wokenUp = 0; 41910037SARM gem5 Developers std::list<ThreadContext *> * tcWaitList; 42010037SARM gem5 Developers if (futex_map.count(uaddr)) { 42110037SARM gem5 Developers tcWaitList = futex_map.find(uaddr)->second; 42210037SARM gem5 Developers while (tcWaitList->size() > 0 && wokenUp < val) { 42310037SARM gem5 Developers tcWaitList->front()->activate(); 42410037SARM gem5 Developers tcWaitList->pop_front(); 42510037SARM gem5 Developers wokenUp++; 42610346Smitch.hayenga@arm.com } 42710037SARM gem5 Developers if(tcWaitList->empty()) { 42810037SARM gem5 Developers futex_map.erase(uaddr); 42910346Smitch.hayenga@arm.com delete tcWaitList; 43010346Smitch.hayenga@arm.com } 43110037SARM gem5 Developers } 43210346Smitch.hayenga@arm.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 43310346Smitch.hayenga@arm.com "thread contexts\n", wokenUp); 43410037SARM gem5 Developers return wokenUp; 43510346Smitch.hayenga@arm.com } else { 43610346Smitch.hayenga@arm.com warn("sys_futex: op %d is not implemented, just returning...", op); 43710346Smitch.hayenga@arm.com return 0; 43810346Smitch.hayenga@arm.com } 43910346Smitch.hayenga@arm.com 44010037SARM gem5 Developers} 44110037SARM gem5 Developers 44210346Smitch.hayenga@arm.com/// Target getdents() handler. 44310666SAli.Saidi@ARM.comSyscallReturn getdentsFunc(SyscallDesc *desc, int num, 44410037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 44510037SARM gem5 Developers 44610037SARM gem5 Developers/// Target getdents64() handler. 44710037SARM gem5 DevelopersSyscallReturn getdents64Func(SyscallDesc *desc, int num, 44810037SARM gem5 Developers LiveProcess *process, ThreadContext *tc); 44910037SARM gem5 Developers 45010037SARM gem5 Developers 45110346Smitch.hayenga@arm.com/// Pseudo Funcs - These functions use a different return convension, 45210037SARM gem5 Developers/// returning a second value in a register other than the normal return register 45310037SARM gem5 DevelopersSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 45410346Smitch.hayenga@arm.com LiveProcess *process, ThreadContext *tc); 45510346Smitch.hayenga@arm.com 45610666SAli.Saidi@ARM.com/// Target getpidPseudo() handler. 45710037SARM gem5 DevelopersSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 45810037SARM gem5 Developers LiveProcess *p, ThreadContext *tc); 4597639Sgblack@eecs.umich.edu 4607639Sgblack@eecs.umich.edu/// Target getuidPseudo() handler. 4617639Sgblack@eecs.umich.eduSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 4627639Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4637639Sgblack@eecs.umich.edu 4647639Sgblack@eecs.umich.edu/// Target getgidPseudo() handler. 4657639Sgblack@eecs.umich.eduSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4667639Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4677639Sgblack@eecs.umich.edu 4687639Sgblack@eecs.umich.edu 4697639Sgblack@eecs.umich.edu/// A readable name for 1,000,000, for converting microseconds to seconds. 4707639Sgblack@eecs.umich.educonst int one_million = 1000000; 4717639Sgblack@eecs.umich.edu 4727639Sgblack@eecs.umich.edu/// Approximate seconds since the epoch (1/1/1970). About a billion, 4737639Sgblack@eecs.umich.edu/// by my reckoning. We want to keep this a constant (not use the 4747639Sgblack@eecs.umich.edu/// real-world time) to keep simulations repeatable. 47510037SARM gem5 Developersconst unsigned seconds_since_epoch = 1000000000; 4767639Sgblack@eecs.umich.edu 4777639Sgblack@eecs.umich.edu/// Helper function to convert current elapsed time to seconds and 4787639Sgblack@eecs.umich.edu/// microseconds. 4797639Sgblack@eecs.umich.edutemplate <class T1, class T2> 4807639Sgblack@eecs.umich.eduvoid 4817639Sgblack@eecs.umich.edugetElapsedTime(T1 &sec, T2 &usec) 4827639Sgblack@eecs.umich.edu{ 4837639Sgblack@eecs.umich.edu int elapsed_usecs = curTick() / SimClock::Int::us; 4847639Sgblack@eecs.umich.edu sec = elapsed_usecs / one_million; 4857639Sgblack@eecs.umich.edu usec = elapsed_usecs % one_million; 4867639Sgblack@eecs.umich.edu} 4877639Sgblack@eecs.umich.edu 4887639Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4897639Sgblack@eecs.umich.edu// 4907639Sgblack@eecs.umich.edu// The following emulation functions are generic, but need to be 4917639Sgblack@eecs.umich.edu// templated to account for differences in types, constants, etc. 4927639Sgblack@eecs.umich.edu// 4937639Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4947639Sgblack@eecs.umich.edu 4957639Sgblack@eecs.umich.edu#if NO_STAT64 4967639Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4977639Sgblack@eecs.umich.edu typedef struct stat hst_stat64; 4987639Sgblack@eecs.umich.edu#else 4997639Sgblack@eecs.umich.edu typedef struct stat hst_stat; 5007639Sgblack@eecs.umich.edu typedef struct stat64 hst_stat64; 5017639Sgblack@eecs.umich.edu#endif 5027853SMatt.Horsnell@ARM.com 5037853SMatt.Horsnell@ARM.com//// Helper function to convert a host stat buffer to a target stat 5047639Sgblack@eecs.umich.edu//// buffer. Also copies the target buffer out to the simulated 5057639Sgblack@eecs.umich.edu//// memory space. Used by stat(), fstat(), and lstat(). 5067639Sgblack@eecs.umich.edu 5077639Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat> 5087646Sgene.wu@arm.comstatic void 5097639Sgblack@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 5107639Sgblack@eecs.umich.edu{ 5117639Sgblack@eecs.umich.edu using namespace TheISA; 5127639Sgblack@eecs.umich.edu 5137639Sgblack@eecs.umich.edu if (fakeTTY) 5147639Sgblack@eecs.umich.edu tgt->st_dev = 0xA; 5157639Sgblack@eecs.umich.edu else 5167639Sgblack@eecs.umich.edu tgt->st_dev = host->st_dev; 5177639Sgblack@eecs.umich.edu tgt->st_dev = TheISA::htog(tgt->st_dev); 5187639Sgblack@eecs.umich.edu tgt->st_ino = host->st_ino; 5197639Sgblack@eecs.umich.edu tgt->st_ino = TheISA::htog(tgt->st_ino); 5207639Sgblack@eecs.umich.edu tgt->st_mode = host->st_mode; 5217639Sgblack@eecs.umich.edu if (fakeTTY) { 5227639Sgblack@eecs.umich.edu // Claim to be a character device 5237639Sgblack@eecs.umich.edu tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 5247639Sgblack@eecs.umich.edu tgt->st_mode |= S_IFCHR; // Set S_IFCHR 5257639Sgblack@eecs.umich.edu } 5267639Sgblack@eecs.umich.edu tgt->st_mode = TheISA::htog(tgt->st_mode); 5277639Sgblack@eecs.umich.edu tgt->st_nlink = host->st_nlink; 5287639Sgblack@eecs.umich.edu tgt->st_nlink = TheISA::htog(tgt->st_nlink); 5297639Sgblack@eecs.umich.edu tgt->st_uid = host->st_uid; 5307639Sgblack@eecs.umich.edu tgt->st_uid = TheISA::htog(tgt->st_uid); 5317639Sgblack@eecs.umich.edu tgt->st_gid = host->st_gid; 5327639Sgblack@eecs.umich.edu tgt->st_gid = TheISA::htog(tgt->st_gid); 5337639Sgblack@eecs.umich.edu if (fakeTTY) 5347639Sgblack@eecs.umich.edu tgt->st_rdev = 0x880d; 5357639Sgblack@eecs.umich.edu else 5367639Sgblack@eecs.umich.edu tgt->st_rdev = host->st_rdev; 5377639Sgblack@eecs.umich.edu tgt->st_rdev = TheISA::htog(tgt->st_rdev); 5387639Sgblack@eecs.umich.edu tgt->st_size = host->st_size; 5397853SMatt.Horsnell@ARM.com tgt->st_size = TheISA::htog(tgt->st_size); 5407853SMatt.Horsnell@ARM.com tgt->st_atimeX = host->st_atime; 5417639Sgblack@eecs.umich.edu tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5427639Sgblack@eecs.umich.edu tgt->st_mtimeX = host->st_mtime; 5437639Sgblack@eecs.umich.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5447639Sgblack@eecs.umich.edu tgt->st_ctimeX = host->st_ctime; 5457639Sgblack@eecs.umich.edu tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5467639Sgblack@eecs.umich.edu // Force the block size to be 8k. This helps to ensure buffered io works 5477639Sgblack@eecs.umich.edu // consistently across different hosts. 5487639Sgblack@eecs.umich.edu tgt->st_blksize = 0x2000; 5497639Sgblack@eecs.umich.edu tgt->st_blksize = TheISA::htog(tgt->st_blksize); 55010666SAli.Saidi@ARM.com tgt->st_blocks = host->st_blocks; 5517639Sgblack@eecs.umich.edu tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5527639Sgblack@eecs.umich.edu} 5537639Sgblack@eecs.umich.edu 5547639Sgblack@eecs.umich.edu// Same for stat64 5557639Sgblack@eecs.umich.edu 5567639Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat64> 5577639Sgblack@eecs.umich.edustatic void 5587639Sgblack@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5597639Sgblack@eecs.umich.edu{ 5607639Sgblack@eecs.umich.edu using namespace TheISA; 5617639Sgblack@eecs.umich.edu 5627639Sgblack@eecs.umich.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5637639Sgblack@eecs.umich.edu#if defined(STAT_HAVE_NSEC) 5647639Sgblack@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5657639Sgblack@eecs.umich.edu tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5667639Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5677639Sgblack@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5687639Sgblack@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5697639Sgblack@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5707639Sgblack@eecs.umich.edu#else 5717639Sgblack@eecs.umich.edu tgt->st_atime_nsec = 0; 5727639Sgblack@eecs.umich.edu tgt->st_mtime_nsec = 0; 5737639Sgblack@eecs.umich.edu tgt->st_ctime_nsec = 0; 5747639Sgblack@eecs.umich.edu#endif 5757639Sgblack@eecs.umich.edu} 5767639Sgblack@eecs.umich.edu 5777639Sgblack@eecs.umich.edu//Here are a couple convenience functions 57810037SARM gem5 Developerstemplate<class OS> 5797639Sgblack@eecs.umich.edustatic void 5807639Sgblack@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5817639Sgblack@eecs.umich.edu hst_stat *host, bool fakeTTY = false) 5827639Sgblack@eecs.umich.edu{ 5837639Sgblack@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5847639Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5857639Sgblack@eecs.umich.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5867639Sgblack@eecs.umich.edu tgt.copyOut(mem); 5877639Sgblack@eecs.umich.edu} 5887639Sgblack@eecs.umich.edu 5897639Sgblack@eecs.umich.edutemplate<class OS> 5907639Sgblack@eecs.umich.edustatic void 5917639Sgblack@eecs.umich.educopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5927639Sgblack@eecs.umich.edu hst_stat64 *host, bool fakeTTY = false) 5937639Sgblack@eecs.umich.edu{ 5947639Sgblack@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5957639Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5967639Sgblack@eecs.umich.edu convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5977639Sgblack@eecs.umich.edu tgt.copyOut(mem); 5987639Sgblack@eecs.umich.edu} 5997639Sgblack@eecs.umich.edu 6007639Sgblack@eecs.umich.edu/// Target ioctl() handler. For the most part, programs call ioctl() 6017639Sgblack@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to 6027639Sgblack@eecs.umich.edu/// do line or block buffering. We always claim that output fds are 6037639Sgblack@eecs.umich.edu/// not TTYs to provide repeatable results. 6047639Sgblack@eecs.umich.edutemplate <class OS> 6057639Sgblack@eecs.umich.eduSyscallReturn 6067639Sgblack@eecs.umich.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6077639Sgblack@eecs.umich.edu ThreadContext *tc) 6087639Sgblack@eecs.umich.edu{ 6097639Sgblack@eecs.umich.edu int index = 0; 6107639Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 6117639Sgblack@eecs.umich.edu unsigned req = process->getSyscallArg(tc, index); 6127639Sgblack@eecs.umich.edu 6137639Sgblack@eecs.umich.edu DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 6147639Sgblack@eecs.umich.edu 6157639Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 6167639Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 6177639Sgblack@eecs.umich.edu return -EBADF; 6187639Sgblack@eecs.umich.edu } 6197639Sgblack@eecs.umich.edu 6207639Sgblack@eecs.umich.edu if (OS::isTtyReq(req)) { 6217639Sgblack@eecs.umich.edu return -ENOTTY; 6227639Sgblack@eecs.umich.edu } 6237639Sgblack@eecs.umich.edu 6247639Sgblack@eecs.umich.edu warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 6257639Sgblack@eecs.umich.edu fd, req, tc->pcState()); 6267639Sgblack@eecs.umich.edu return -ENOTTY; 6277639Sgblack@eecs.umich.edu} 6287639Sgblack@eecs.umich.edu 6297639Sgblack@eecs.umich.edutemplate <class OS> 6307639Sgblack@eecs.umich.edustatic SyscallReturn 6317639Sgblack@eecs.umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6327639Sgblack@eecs.umich.edu ThreadContext *tc, int index) 6337639Sgblack@eecs.umich.edu{ 6347639Sgblack@eecs.umich.edu std::string path; 6357639Sgblack@eecs.umich.edu 6367639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 6377639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) 6387639Sgblack@eecs.umich.edu return -EFAULT; 6397639Sgblack@eecs.umich.edu 6407853SMatt.Horsnell@ARM.com if (path == "/dev/sysdev0") { 6417853SMatt.Horsnell@ARM.com // This is a memory-mapped high-resolution timer device on Alpha. 6427639Sgblack@eecs.umich.edu // We don't support it, so just punt. 6437639Sgblack@eecs.umich.edu warn("Ignoring open(%s, ...)\n", path); 6447639Sgblack@eecs.umich.edu return -ENOENT; 6457639Sgblack@eecs.umich.edu } 6467646Sgene.wu@arm.com 6477639Sgblack@eecs.umich.edu int tgtFlags = process->getSyscallArg(tc, index); 6487639Sgblack@eecs.umich.edu int mode = process->getSyscallArg(tc, index); 6497639Sgblack@eecs.umich.edu int hostFlags = 0; 6507639Sgblack@eecs.umich.edu 6517639Sgblack@eecs.umich.edu // translate open flags 6527639Sgblack@eecs.umich.edu for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 6537639Sgblack@eecs.umich.edu if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 6547639Sgblack@eecs.umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 6557639Sgblack@eecs.umich.edu hostFlags |= OS::openFlagTable[i].hostFlag; 6567639Sgblack@eecs.umich.edu } 6577639Sgblack@eecs.umich.edu } 6587639Sgblack@eecs.umich.edu 6597639Sgblack@eecs.umich.edu // any target flags left? 6607639Sgblack@eecs.umich.edu if (tgtFlags != 0) 6617639Sgblack@eecs.umich.edu warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 6627639Sgblack@eecs.umich.edu 6637639Sgblack@eecs.umich.edu#ifdef __CYGWIN32__ 6647639Sgblack@eecs.umich.edu hostFlags |= O_BINARY; 6657639Sgblack@eecs.umich.edu#endif 6667639Sgblack@eecs.umich.edu 6677639Sgblack@eecs.umich.edu // Adjust path for current working directory 6687639Sgblack@eecs.umich.edu path = process->fullPath(path); 6697639Sgblack@eecs.umich.edu 6707639Sgblack@eecs.umich.edu DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 6717639Sgblack@eecs.umich.edu 6727639Sgblack@eecs.umich.edu int fd; 6737639Sgblack@eecs.umich.edu int local_errno; 6747639Sgblack@eecs.umich.edu if (startswith(path, "/proc/") || startswith(path, "/system/") || 6757639Sgblack@eecs.umich.edu startswith(path, "/platform/") || startswith(path, "/sys/")) { 6767639Sgblack@eecs.umich.edu // It's a proc/sys entry and requires special handling 6777639Sgblack@eecs.umich.edu fd = OS::openSpecialFile(path, process, tc); 6787639Sgblack@eecs.umich.edu local_errno = ENOENT; 6797639Sgblack@eecs.umich.edu } else { 6807639Sgblack@eecs.umich.edu // open the file 6817639Sgblack@eecs.umich.edu fd = open(path.c_str(), hostFlags, mode); 6827639Sgblack@eecs.umich.edu local_errno = errno; 6837639Sgblack@eecs.umich.edu } 6847853SMatt.Horsnell@ARM.com 6857853SMatt.Horsnell@ARM.com if (fd == -1) 6867639Sgblack@eecs.umich.edu return -local_errno; 6877639Sgblack@eecs.umich.edu 6887639Sgblack@eecs.umich.edu return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false); 6897639Sgblack@eecs.umich.edu} 6907639Sgblack@eecs.umich.edu 6917639Sgblack@eecs.umich.edu/// Target open() handler. 6927639Sgblack@eecs.umich.edutemplate <class OS> 6937639Sgblack@eecs.umich.eduSyscallReturn 6947639Sgblack@eecs.umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6957639Sgblack@eecs.umich.edu ThreadContext *tc) 6967639Sgblack@eecs.umich.edu{ 6977639Sgblack@eecs.umich.edu return openFunc<OS>(desc, callnum, process, tc, 0); 6987639Sgblack@eecs.umich.edu} 6997639Sgblack@eecs.umich.edu 7007639Sgblack@eecs.umich.edu/// Target openat() handler. 7017639Sgblack@eecs.umich.edutemplate <class OS> 7027639Sgblack@eecs.umich.eduSyscallReturn 7037639Sgblack@eecs.umich.eduopenatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7047639Sgblack@eecs.umich.edu ThreadContext *tc) 7057639Sgblack@eecs.umich.edu{ 7067639Sgblack@eecs.umich.edu int index = 0; 7077639Sgblack@eecs.umich.edu int dirfd = process->getSyscallArg(tc, index); 7087639Sgblack@eecs.umich.edu if (dirfd != OS::TGT_AT_FDCWD) 7097639Sgblack@eecs.umich.edu warn("openat: first argument not AT_FDCWD; unlikely to work"); 7107639Sgblack@eecs.umich.edu return openFunc<OS>(desc, callnum, process, tc, 1); 7117639Sgblack@eecs.umich.edu} 7127639Sgblack@eecs.umich.edu 7137639Sgblack@eecs.umich.edu/// Target facessat() handler 7147639Sgblack@eecs.umich.edutemplate <class OS> 7157639Sgblack@eecs.umich.eduSyscallReturn 7167639Sgblack@eecs.umich.edufaccessatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7177639Sgblack@eecs.umich.edu ThreadContext *tc) 7187639Sgblack@eecs.umich.edu{ 7197639Sgblack@eecs.umich.edu int index = 0; 7207853SMatt.Horsnell@ARM.com int dirfd = process->getSyscallArg(tc, index); 7217853SMatt.Horsnell@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 7227639Sgblack@eecs.umich.edu warn("faccessat: first argument not AT_FDCWD; unlikely to work"); 7237639Sgblack@eecs.umich.edu return accessFunc(desc, callnum, process, tc, 1); 7247639Sgblack@eecs.umich.edu} 7257639Sgblack@eecs.umich.edu 7267639Sgblack@eecs.umich.edu/// Target readlinkat() handler 7277639Sgblack@eecs.umich.edutemplate <class OS> 7287639Sgblack@eecs.umich.eduSyscallReturn 7297639Sgblack@eecs.umich.edureadlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7307639Sgblack@eecs.umich.edu ThreadContext *tc) 7317639Sgblack@eecs.umich.edu{ 7327639Sgblack@eecs.umich.edu int index = 0; 7337639Sgblack@eecs.umich.edu int dirfd = process->getSyscallArg(tc, index); 7347639Sgblack@eecs.umich.edu if (dirfd != OS::TGT_AT_FDCWD) 7357639Sgblack@eecs.umich.edu warn("openat: first argument not AT_FDCWD; unlikely to work"); 7367639Sgblack@eecs.umich.edu return readlinkFunc(desc, callnum, process, tc, 1); 7377639Sgblack@eecs.umich.edu} 7387639Sgblack@eecs.umich.edu 7397639Sgblack@eecs.umich.edu/// Target sysinfo() handler. 7407639Sgblack@eecs.umich.edutemplate <class OS> 7417639Sgblack@eecs.umich.eduSyscallReturn 7427639Sgblack@eecs.umich.edusysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7437639Sgblack@eecs.umich.edu ThreadContext *tc) 7447639Sgblack@eecs.umich.edu{ 7457639Sgblack@eecs.umich.edu 7467639Sgblack@eecs.umich.edu int index = 0; 7477639Sgblack@eecs.umich.edu TypedBufferArg<typename OS::tgt_sysinfo> 7487639Sgblack@eecs.umich.edu sysinfo(process->getSyscallArg(tc, index)); 7497639Sgblack@eecs.umich.edu 7507639Sgblack@eecs.umich.edu sysinfo->uptime=seconds_since_epoch; 7517639Sgblack@eecs.umich.edu sysinfo->totalram=process->system->memSize(); 7527639Sgblack@eecs.umich.edu 7537639Sgblack@eecs.umich.edu sysinfo.copyOut(tc->getMemProxy()); 7547639Sgblack@eecs.umich.edu 7557639Sgblack@eecs.umich.edu return 0; 7567639Sgblack@eecs.umich.edu} 7577853SMatt.Horsnell@ARM.com 7587853SMatt.Horsnell@ARM.com/// Target chmod() handler. 7597639Sgblack@eecs.umich.edutemplate <class OS> 7607639Sgblack@eecs.umich.eduSyscallReturn 7617639Sgblack@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7627639Sgblack@eecs.umich.edu ThreadContext *tc) 7637639Sgblack@eecs.umich.edu{ 7647639Sgblack@eecs.umich.edu std::string path; 7657639Sgblack@eecs.umich.edu 7667639Sgblack@eecs.umich.edu int index = 0; 7677639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 7687639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 7697639Sgblack@eecs.umich.edu return -EFAULT; 7707639Sgblack@eecs.umich.edu } 7717639Sgblack@eecs.umich.edu 7727639Sgblack@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 7737639Sgblack@eecs.umich.edu mode_t hostMode = 0; 7747639Sgblack@eecs.umich.edu 7757639Sgblack@eecs.umich.edu // XXX translate mode flags via OS::something??? 7767639Sgblack@eecs.umich.edu hostMode = mode; 7777639Sgblack@eecs.umich.edu 7787639Sgblack@eecs.umich.edu // Adjust path for current working directory 7797639Sgblack@eecs.umich.edu path = process->fullPath(path); 7807639Sgblack@eecs.umich.edu 7817639Sgblack@eecs.umich.edu // do the chmod 7827639Sgblack@eecs.umich.edu int result = chmod(path.c_str(), hostMode); 7837639Sgblack@eecs.umich.edu if (result < 0) 7847639Sgblack@eecs.umich.edu return -errno; 7857639Sgblack@eecs.umich.edu 7867639Sgblack@eecs.umich.edu return 0; 7877639Sgblack@eecs.umich.edu} 7887639Sgblack@eecs.umich.edu 7897639Sgblack@eecs.umich.edu 7907639Sgblack@eecs.umich.edu/// Target fchmod() handler. 7917639Sgblack@eecs.umich.edutemplate <class OS> 7927639Sgblack@eecs.umich.eduSyscallReturn 7937639Sgblack@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7947639Sgblack@eecs.umich.edu ThreadContext *tc) 7957639Sgblack@eecs.umich.edu{ 7967639Sgblack@eecs.umich.edu int index = 0; 7977639Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 7987639Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 7997639Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 8007639Sgblack@eecs.umich.edu return -EBADF; 8017853SMatt.Horsnell@ARM.com } 8027853SMatt.Horsnell@ARM.com 8037639Sgblack@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 8047639Sgblack@eecs.umich.edu mode_t hostMode = 0; 8057639Sgblack@eecs.umich.edu 8067639Sgblack@eecs.umich.edu // XXX translate mode flags via OS::someting??? 8077639Sgblack@eecs.umich.edu hostMode = mode; 8087853SMatt.Horsnell@ARM.com 8097853SMatt.Horsnell@ARM.com // do the fchmod 8107639Sgblack@eecs.umich.edu int result = fchmod(process->sim_fd(fd), hostMode); 8117639Sgblack@eecs.umich.edu if (result < 0) 8127639Sgblack@eecs.umich.edu return -errno; 8137639Sgblack@eecs.umich.edu 8147639Sgblack@eecs.umich.edu return 0; 8157639Sgblack@eecs.umich.edu} 8167639Sgblack@eecs.umich.edu 8177639Sgblack@eecs.umich.edu/// Target mremap() handler. 81810666SAli.Saidi@ARM.comtemplate <class OS> 8197639Sgblack@eecs.umich.eduSyscallReturn 8207639Sgblack@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 8217639Sgblack@eecs.umich.edu{ 8227639Sgblack@eecs.umich.edu int index = 0; 8237639Sgblack@eecs.umich.edu Addr start = process->getSyscallArg(tc, index); 8247639Sgblack@eecs.umich.edu uint64_t old_length = process->getSyscallArg(tc, index); 8257639Sgblack@eecs.umich.edu uint64_t new_length = process->getSyscallArg(tc, index); 8267639Sgblack@eecs.umich.edu uint64_t flags = process->getSyscallArg(tc, index); 8277639Sgblack@eecs.umich.edu uint64_t provided_address = 0; 8287639Sgblack@eecs.umich.edu bool use_provided_address = flags & OS::TGT_MREMAP_FIXED; 8297639Sgblack@eecs.umich.edu 8307639Sgblack@eecs.umich.edu if (use_provided_address) 8317639Sgblack@eecs.umich.edu provided_address = process->getSyscallArg(tc, index); 8327639Sgblack@eecs.umich.edu 8337639Sgblack@eecs.umich.edu if ((start % TheISA::PageBytes != 0) || 8347639Sgblack@eecs.umich.edu (provided_address % TheISA::PageBytes != 0)) { 8357639Sgblack@eecs.umich.edu warn("mremap failing: arguments not page aligned"); 8367639Sgblack@eecs.umich.edu return -EINVAL; 8377639Sgblack@eecs.umich.edu } 8387639Sgblack@eecs.umich.edu 8397639Sgblack@eecs.umich.edu new_length = roundUp(new_length, TheISA::PageBytes); 84010037SARM gem5 Developers 8417639Sgblack@eecs.umich.edu if (new_length > old_length) { 8427639Sgblack@eecs.umich.edu if ((start + old_length) == process->mmap_end && 8437639Sgblack@eecs.umich.edu (!use_provided_address || provided_address == start)) { 8447639Sgblack@eecs.umich.edu uint64_t diff = new_length - old_length; 8457639Sgblack@eecs.umich.edu process->allocateMem(process->mmap_end, diff); 8467639Sgblack@eecs.umich.edu process->mmap_end += diff; 8477639Sgblack@eecs.umich.edu return start; 8487639Sgblack@eecs.umich.edu } else { 8497639Sgblack@eecs.umich.edu if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { 8507639Sgblack@eecs.umich.edu warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 8517639Sgblack@eecs.umich.edu return -ENOMEM; 8527639Sgblack@eecs.umich.edu } else { 8537639Sgblack@eecs.umich.edu uint64_t new_start = use_provided_address ? 8547639Sgblack@eecs.umich.edu provided_address : process->mmap_end; 8557639Sgblack@eecs.umich.edu process->pTable->remap(start, old_length, new_start); 8567639Sgblack@eecs.umich.edu warn("mremapping to new vaddr %08p-%08p, adding %d\n", 8577639Sgblack@eecs.umich.edu new_start, new_start + new_length, 8587639Sgblack@eecs.umich.edu new_length - old_length); 8597639Sgblack@eecs.umich.edu // add on the remaining unallocated pages 8607639Sgblack@eecs.umich.edu process->allocateMem(new_start + old_length, 8617639Sgblack@eecs.umich.edu new_length - old_length, 8627639Sgblack@eecs.umich.edu use_provided_address /* clobber */); 8637639Sgblack@eecs.umich.edu if (!use_provided_address) 8647639Sgblack@eecs.umich.edu process->mmap_end += new_length; 8657639Sgblack@eecs.umich.edu if (use_provided_address && 8667639Sgblack@eecs.umich.edu new_start + new_length > process->mmap_end) { 8677639Sgblack@eecs.umich.edu // something fishy going on here, at least notify the user 8687853SMatt.Horsnell@ARM.com // @todo: increase mmap_end? 8697853SMatt.Horsnell@ARM.com warn("mmap region limit exceeded with MREMAP_FIXED\n"); 8707639Sgblack@eecs.umich.edu } 8717639Sgblack@eecs.umich.edu warn("returning %08p as start\n", new_start); 8727639Sgblack@eecs.umich.edu return new_start; 8737639Sgblack@eecs.umich.edu } 8747639Sgblack@eecs.umich.edu } 8757639Sgblack@eecs.umich.edu } else { 8767639Sgblack@eecs.umich.edu if (use_provided_address && provided_address != start) 8777639Sgblack@eecs.umich.edu process->pTable->remap(start, new_length, provided_address); 8787639Sgblack@eecs.umich.edu process->pTable->unmap(start + new_length, old_length - new_length); 8797639Sgblack@eecs.umich.edu return use_provided_address ? provided_address : start; 8807639Sgblack@eecs.umich.edu } 8817639Sgblack@eecs.umich.edu} 8827639Sgblack@eecs.umich.edu 8837639Sgblack@eecs.umich.edu/// Target stat() handler. 8847639Sgblack@eecs.umich.edutemplate <class OS> 8857639Sgblack@eecs.umich.eduSyscallReturn 8867639Sgblack@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8877639Sgblack@eecs.umich.edu ThreadContext *tc) 8887639Sgblack@eecs.umich.edu{ 8897639Sgblack@eecs.umich.edu std::string path; 8907639Sgblack@eecs.umich.edu 8917639Sgblack@eecs.umich.edu int index = 0; 8927639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 8937639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 8947853SMatt.Horsnell@ARM.com return -EFAULT; 8957853SMatt.Horsnell@ARM.com } 8967639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8977639Sgblack@eecs.umich.edu 8987639Sgblack@eecs.umich.edu // Adjust path for current working directory 8997639Sgblack@eecs.umich.edu path = process->fullPath(path); 9007646Sgene.wu@arm.com 9017639Sgblack@eecs.umich.edu struct stat hostBuf; 9027639Sgblack@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 9037639Sgblack@eecs.umich.edu 9047639Sgblack@eecs.umich.edu if (result < 0) 9057639Sgblack@eecs.umich.edu return -errno; 9067639Sgblack@eecs.umich.edu 9077639Sgblack@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9087639Sgblack@eecs.umich.edu 9097639Sgblack@eecs.umich.edu return 0; 9107639Sgblack@eecs.umich.edu} 9117639Sgblack@eecs.umich.edu 9127639Sgblack@eecs.umich.edu 91310666SAli.Saidi@ARM.com/// Target stat64() handler. 9147639Sgblack@eecs.umich.edutemplate <class OS> 9157639Sgblack@eecs.umich.eduSyscallReturn 9167639Sgblack@eecs.umich.edustat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9177639Sgblack@eecs.umich.edu ThreadContext *tc) 9187639Sgblack@eecs.umich.edu{ 9197639Sgblack@eecs.umich.edu std::string path; 9207639Sgblack@eecs.umich.edu 9217639Sgblack@eecs.umich.edu int index = 0; 9227639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 9237639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) 9247639Sgblack@eecs.umich.edu return -EFAULT; 9257639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9267639Sgblack@eecs.umich.edu 9277639Sgblack@eecs.umich.edu // Adjust path for current working directory 9287639Sgblack@eecs.umich.edu path = process->fullPath(path); 9297639Sgblack@eecs.umich.edu 9307639Sgblack@eecs.umich.edu#if NO_STAT64 9317639Sgblack@eecs.umich.edu struct stat hostBuf; 9327639Sgblack@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 9337639Sgblack@eecs.umich.edu#else 9347639Sgblack@eecs.umich.edu struct stat64 hostBuf; 9357639Sgblack@eecs.umich.edu int result = stat64(path.c_str(), &hostBuf); 9367639Sgblack@eecs.umich.edu#endif 9377639Sgblack@eecs.umich.edu 9387639Sgblack@eecs.umich.edu if (result < 0) 9397639Sgblack@eecs.umich.edu return -errno; 9407639Sgblack@eecs.umich.edu 9417639Sgblack@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 94210037SARM gem5 Developers 9437639Sgblack@eecs.umich.edu return 0; 9447639Sgblack@eecs.umich.edu} 9457639Sgblack@eecs.umich.edu 9467639Sgblack@eecs.umich.edu 9477639Sgblack@eecs.umich.edu/// Target fstatat64() handler. 9487639Sgblack@eecs.umich.edutemplate <class OS> 9497639Sgblack@eecs.umich.eduSyscallReturn 9507639Sgblack@eecs.umich.edufstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9517639Sgblack@eecs.umich.edu ThreadContext *tc) 9527639Sgblack@eecs.umich.edu{ 9537639Sgblack@eecs.umich.edu int index = 0; 9547639Sgblack@eecs.umich.edu int dirfd = process->getSyscallArg(tc, index); 9557639Sgblack@eecs.umich.edu if (dirfd != OS::TGT_AT_FDCWD) 9567639Sgblack@eecs.umich.edu warn("openat: first argument not AT_FDCWD; unlikely to work"); 9577639Sgblack@eecs.umich.edu 9587639Sgblack@eecs.umich.edu std::string path; 9597639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 9607639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) 9617639Sgblack@eecs.umich.edu return -EFAULT; 9627853SMatt.Horsnell@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 9637853SMatt.Horsnell@ARM.com 9647639Sgblack@eecs.umich.edu // Adjust path for current working directory 9657639Sgblack@eecs.umich.edu path = process->fullPath(path); 9667639Sgblack@eecs.umich.edu 9677639Sgblack@eecs.umich.edu#if NO_STAT64 9687639Sgblack@eecs.umich.edu struct stat hostBuf; 9697639Sgblack@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 9707639Sgblack@eecs.umich.edu#else 9717639Sgblack@eecs.umich.edu struct stat64 hostBuf; 9727639Sgblack@eecs.umich.edu int result = stat64(path.c_str(), &hostBuf); 9737639Sgblack@eecs.umich.edu#endif 9747639Sgblack@eecs.umich.edu 9757639Sgblack@eecs.umich.edu if (result < 0) 9767639Sgblack@eecs.umich.edu return -errno; 9777639Sgblack@eecs.umich.edu 9787639Sgblack@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9797639Sgblack@eecs.umich.edu 9807639Sgblack@eecs.umich.edu return 0; 9817639Sgblack@eecs.umich.edu} 9827639Sgblack@eecs.umich.edu 9837853SMatt.Horsnell@ARM.com 9847853SMatt.Horsnell@ARM.com/// Target fstat64() handler. 9857639Sgblack@eecs.umich.edutemplate <class OS> 9867639Sgblack@eecs.umich.eduSyscallReturn 9877639Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9887639Sgblack@eecs.umich.edu ThreadContext *tc) 9897639Sgblack@eecs.umich.edu{ 9907639Sgblack@eecs.umich.edu int index = 0; 9917639Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 9927639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9937639Sgblack@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 9947639Sgblack@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 9957639Sgblack@eecs.umich.edu return -EBADF; 9967639Sgblack@eecs.umich.edu } 9977639Sgblack@eecs.umich.edu 9987639Sgblack@eecs.umich.edu#if NO_STAT64 9997639Sgblack@eecs.umich.edu struct stat hostBuf; 10007639Sgblack@eecs.umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 10017639Sgblack@eecs.umich.edu#else 10027639Sgblack@eecs.umich.edu struct stat64 hostBuf; 10037639Sgblack@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 10047639Sgblack@eecs.umich.edu#endif 10057853SMatt.Horsnell@ARM.com 10067853SMatt.Horsnell@ARM.com if (result < 0) 10077639Sgblack@eecs.umich.edu return -errno; 10087639Sgblack@eecs.umich.edu 10097639Sgblack@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 10107639Sgblack@eecs.umich.edu 10117639Sgblack@eecs.umich.edu return 0; 10127639Sgblack@eecs.umich.edu} 10137639Sgblack@eecs.umich.edu 10147639Sgblack@eecs.umich.edu 10157639Sgblack@eecs.umich.edu/// Target lstat() handler. 10167639Sgblack@eecs.umich.edutemplate <class OS> 10177639Sgblack@eecs.umich.eduSyscallReturn 10187639Sgblack@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10197639Sgblack@eecs.umich.edu ThreadContext *tc) 10207639Sgblack@eecs.umich.edu{ 10217639Sgblack@eecs.umich.edu std::string path; 10227639Sgblack@eecs.umich.edu 10237639Sgblack@eecs.umich.edu int index = 0; 10247639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 10257639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 10267639Sgblack@eecs.umich.edu return -EFAULT; 10277639Sgblack@eecs.umich.edu } 10287853SMatt.Horsnell@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 10297853SMatt.Horsnell@ARM.com 10307639Sgblack@eecs.umich.edu // Adjust path for current working directory 10317639Sgblack@eecs.umich.edu path = process->fullPath(path); 10327639Sgblack@eecs.umich.edu 10337639Sgblack@eecs.umich.edu struct stat hostBuf; 10347639Sgblack@eecs.umich.edu int result = lstat(path.c_str(), &hostBuf); 10357853SMatt.Horsnell@ARM.com 10367853SMatt.Horsnell@ARM.com if (result < 0) 10377639Sgblack@eecs.umich.edu return -errno; 10387639Sgblack@eecs.umich.edu 10397639Sgblack@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10407639Sgblack@eecs.umich.edu 10417639Sgblack@eecs.umich.edu return 0; 10427639Sgblack@eecs.umich.edu} 10437639Sgblack@eecs.umich.edu 10447639Sgblack@eecs.umich.edu/// Target lstat64() handler. 10457639Sgblack@eecs.umich.edutemplate <class OS> 10467639Sgblack@eecs.umich.eduSyscallReturn 10477639Sgblack@eecs.umich.edulstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 10487639Sgblack@eecs.umich.edu ThreadContext *tc) 10497639Sgblack@eecs.umich.edu{ 10507639Sgblack@eecs.umich.edu std::string path; 10517639Sgblack@eecs.umich.edu 10527639Sgblack@eecs.umich.edu int index = 0; 10537639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 10547639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 10557639Sgblack@eecs.umich.edu return -EFAULT; 10567639Sgblack@eecs.umich.edu } 10577639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 10587639Sgblack@eecs.umich.edu 10597639Sgblack@eecs.umich.edu // Adjust path for current working directory 10607639Sgblack@eecs.umich.edu path = process->fullPath(path); 10617639Sgblack@eecs.umich.edu 10627639Sgblack@eecs.umich.edu#if NO_STAT64 10637639Sgblack@eecs.umich.edu struct stat hostBuf; 10647639Sgblack@eecs.umich.edu int result = lstat(path.c_str(), &hostBuf); 10657639Sgblack@eecs.umich.edu#else 10667639Sgblack@eecs.umich.edu struct stat64 hostBuf; 10677639Sgblack@eecs.umich.edu int result = lstat64(path.c_str(), &hostBuf); 10687639Sgblack@eecs.umich.edu#endif 10697639Sgblack@eecs.umich.edu 10707639Sgblack@eecs.umich.edu if (result < 0) 10717639Sgblack@eecs.umich.edu return -errno; 10727639Sgblack@eecs.umich.edu 10737639Sgblack@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10747639Sgblack@eecs.umich.edu 10757639Sgblack@eecs.umich.edu return 0; 10767639Sgblack@eecs.umich.edu} 10777639Sgblack@eecs.umich.edu 10787639Sgblack@eecs.umich.edu/// Target fstat() handler. 10797639Sgblack@eecs.umich.edutemplate <class OS> 10807639Sgblack@eecs.umich.eduSyscallReturn 10817639Sgblack@eecs.umich.edufstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10827639Sgblack@eecs.umich.edu ThreadContext *tc) 10837639Sgblack@eecs.umich.edu{ 10847639Sgblack@eecs.umich.edu int index = 0; 10857639Sgblack@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 10867639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 10877639Sgblack@eecs.umich.edu 10887639Sgblack@eecs.umich.edu DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 10897639Sgblack@eecs.umich.edu 10907639Sgblack@eecs.umich.edu if (fd < 0) 10917639Sgblack@eecs.umich.edu return -EBADF; 10927639Sgblack@eecs.umich.edu 10937639Sgblack@eecs.umich.edu struct stat hostBuf; 10947639Sgblack@eecs.umich.edu int result = fstat(fd, &hostBuf); 10957639Sgblack@eecs.umich.edu 10967639Sgblack@eecs.umich.edu if (result < 0) 10977853SMatt.Horsnell@ARM.com return -errno; 10987853SMatt.Horsnell@ARM.com 10997639Sgblack@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 11007639Sgblack@eecs.umich.edu 11017639Sgblack@eecs.umich.edu return 0; 11027639Sgblack@eecs.umich.edu} 11037646Sgene.wu@arm.com 11047639Sgblack@eecs.umich.edu 11057639Sgblack@eecs.umich.edu/// Target statfs() handler. 11067639Sgblack@eecs.umich.edutemplate <class OS> 11077639Sgblack@eecs.umich.eduSyscallReturn 11087639Sgblack@eecs.umich.edustatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11097639Sgblack@eecs.umich.edu ThreadContext *tc) 11107639Sgblack@eecs.umich.edu{ 11117639Sgblack@eecs.umich.edu std::string path; 11127639Sgblack@eecs.umich.edu 11137639Sgblack@eecs.umich.edu int index = 0; 11147639Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 11157639Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 111610666SAli.Saidi@ARM.com return -EFAULT; 11177639Sgblack@eecs.umich.edu } 11187639Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 11197639Sgblack@eecs.umich.edu 112010037SARM gem5 Developers // Adjust path for current working directory 112110037SARM gem5 Developers path = process->fullPath(path); 112210037SARM gem5 Developers 112310037SARM gem5 Developers struct statfs hostBuf; 112410037SARM gem5 Developers int result = statfs(path.c_str(), &hostBuf); 112510037SARM gem5 Developers 112610037SARM gem5 Developers if (result < 0) 112710037SARM gem5 Developers return -errno; 112810037SARM gem5 Developers 112910037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 113010037SARM gem5 Developers 113110037SARM gem5 Developers return 0; 113210037SARM gem5 Developers} 113310037SARM gem5 Developers 113410037SARM gem5 Developers 113510037SARM gem5 Developers/// Target fstatfs() handler. 113610037SARM gem5 Developerstemplate <class OS> 113710037SARM gem5 DevelopersSyscallReturn 113810037SARM gem5 DevelopersfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 113910037SARM gem5 Developers ThreadContext *tc) 114010037SARM gem5 Developers{ 114110037SARM gem5 Developers int index = 0; 114210037SARM gem5 Developers int fd = process->sim_fd(process->getSyscallArg(tc, index)); 114310037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 114410037SARM gem5 Developers 114510037SARM gem5 Developers if (fd < 0) 114610037SARM gem5 Developers return -EBADF; 114710037SARM gem5 Developers 114810037SARM gem5 Developers struct statfs hostBuf; 114910037SARM gem5 Developers int result = fstatfs(fd, &hostBuf); 115010037SARM gem5 Developers 115110037SARM gem5 Developers if (result < 0) 115211321Ssteve.reinhardt@amd.com return -errno; 115310037SARM gem5 Developers 115410037SARM gem5 Developers OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 115510037SARM gem5 Developers 115610037SARM gem5 Developers return 0; 115710037SARM gem5 Developers} 115810037SARM gem5 Developers 115910037SARM gem5 Developers 116010037SARM gem5 Developers/// Target writev() handler. 116110037SARM gem5 Developerstemplate <class OS> 116210037SARM gem5 DevelopersSyscallReturn 116310037SARM gem5 DeveloperswritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 116410037SARM gem5 Developers ThreadContext *tc) 116510037SARM gem5 Developers{ 116610037SARM gem5 Developers int index = 0; 116710037SARM gem5 Developers int fd = process->getSyscallArg(tc, index); 116810037SARM gem5 Developers if (fd < 0 || process->sim_fd(fd) < 0) { 116910037SARM gem5 Developers // doesn't map to any simulator fd: not a valid target fd 117010037SARM gem5 Developers return -EBADF; 117110037SARM gem5 Developers } 117210037SARM gem5 Developers 117310037SARM gem5 Developers SETranslatingPortProxy &p = tc->getMemProxy(); 117410037SARM gem5 Developers uint64_t tiov_base = process->getSyscallArg(tc, index); 117510339Smitch.hayenga@arm.com size_t count = process->getSyscallArg(tc, index); 117610339Smitch.hayenga@arm.com struct iovec hiov[count]; 117710339Smitch.hayenga@arm.com for (size_t i = 0; i < count; ++i) { 117810339Smitch.hayenga@arm.com typename OS::tgt_iovec tiov; 117910339Smitch.hayenga@arm.com 118010339Smitch.hayenga@arm.com p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 118110339Smitch.hayenga@arm.com (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 118210339Smitch.hayenga@arm.com hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 118310339Smitch.hayenga@arm.com hiov[i].iov_base = new char [hiov[i].iov_len]; 118410339Smitch.hayenga@arm.com p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 118510339Smitch.hayenga@arm.com hiov[i].iov_len); 118610339Smitch.hayenga@arm.com } 118710339Smitch.hayenga@arm.com 118810339Smitch.hayenga@arm.com int result = writev(process->sim_fd(fd), hiov, count); 118910339Smitch.hayenga@arm.com 119010339Smitch.hayenga@arm.com for (size_t i = 0; i < count; ++i) 119110339Smitch.hayenga@arm.com delete [] (char *)hiov[i].iov_base; 119210339Smitch.hayenga@arm.com 119310339Smitch.hayenga@arm.com if (result < 0) 119410339Smitch.hayenga@arm.com return -errno; 119510037SARM gem5 Developers 119610037SARM gem5 Developers return 0; 119710037SARM gem5 Developers} 119810037SARM gem5 Developers 119910037SARM gem5 Developers 120010037SARM gem5 Developers/// Target mmap() handler. 120110037SARM gem5 Developers/// 120210037SARM gem5 Developers/// We don't really handle mmap(). If the target is mmaping an 120310037SARM gem5 Developers/// anonymous region or /dev/zero, we can get away with doing basically 120410037SARM gem5 Developers/// nothing (since memory is initialized to zero and the simulator 120510037SARM gem5 Developers/// doesn't really check addresses anyway). 120610037SARM gem5 Developers/// 120710037SARM gem5 Developerstemplate <class OS> 120810037SARM gem5 DevelopersSyscallReturn 120910037SARM gem5 DevelopersmmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 121010037SARM gem5 Developers{ 121110037SARM gem5 Developers int index = 0; 121210037SARM gem5 Developers Addr start = p->getSyscallArg(tc, index); 121310037SARM gem5 Developers uint64_t length = p->getSyscallArg(tc, index); 121410037SARM gem5 Developers index++; // int prot = p->getSyscallArg(tc, index); 121510037SARM gem5 Developers int flags = p->getSyscallArg(tc, index); 121610037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 121710037SARM gem5 Developers int offset = p->getSyscallArg(tc, index); 121810037SARM gem5 Developers 121910037SARM gem5 Developers if (length > 0x100000000ULL) 122010037SARM gem5 Developers warn("mmap length argument %#x is unreasonably large.\n", length); 122110037SARM gem5 Developers 122210037SARM gem5 Developers if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 122310037SARM gem5 Developers Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 122410037SARM gem5 Developers if (!fd_map || fd_map->fd < 0) { 122510037SARM gem5 Developers warn("mmap failing: target fd %d is not valid\n", tgt_fd); 122610037SARM gem5 Developers return -EBADF; 122710037SARM gem5 Developers } 122810037SARM gem5 Developers 122910037SARM gem5 Developers if (fd_map->filename != "/dev/zero") { 123010037SARM gem5 Developers // This is very likely broken, but leave a warning here 123110037SARM gem5 Developers // (rather than panic) in case /dev/zero is known by 123210037SARM gem5 Developers // another name on some platform 123310037SARM gem5 Developers warn("allowing mmap of file %s; mmap not supported on files" 123411321Ssteve.reinhardt@amd.com " other than /dev/zero\n", fd_map->filename); 123510339Smitch.hayenga@arm.com } 123610339Smitch.hayenga@arm.com } 123710339Smitch.hayenga@arm.com 123810339Smitch.hayenga@arm.com length = roundUp(length, TheISA::PageBytes); 123910339Smitch.hayenga@arm.com 124010339Smitch.hayenga@arm.com if ((start % TheISA::PageBytes) != 0 || 124110339Smitch.hayenga@arm.com (offset % TheISA::PageBytes) != 0) { 124210339Smitch.hayenga@arm.com warn("mmap failing: arguments not page-aligned: " 124310339Smitch.hayenga@arm.com "start 0x%x offset 0x%x", 124410339Smitch.hayenga@arm.com start, offset); 124510339Smitch.hayenga@arm.com return -EINVAL; 124610339Smitch.hayenga@arm.com } 124710339Smitch.hayenga@arm.com 124810339Smitch.hayenga@arm.com // are we ok with clobbering existing mappings? only set this to 124910339Smitch.hayenga@arm.com // true if the user has been warned. 125010339Smitch.hayenga@arm.com bool clobber = false; 125110339Smitch.hayenga@arm.com 125210339Smitch.hayenga@arm.com // try to use the caller-provided address if there is one 125310339Smitch.hayenga@arm.com bool use_provided_address = (start != 0); 125410037SARM gem5 Developers 125510037SARM gem5 Developers if (use_provided_address) { 125610037SARM gem5 Developers // check to see if the desired address is already in use 125710037SARM gem5 Developers if (!p->pTable->isUnmapped(start, length)) { 125810037SARM gem5 Developers // there are existing mappings in the desired range 125910037SARM gem5 Developers // whether we clobber them or not depends on whether the caller 126011321Ssteve.reinhardt@amd.com // specified MAP_FIXED 126110037SARM gem5 Developers if (flags & OS::TGT_MAP_FIXED) { 126210037SARM gem5 Developers // MAP_FIXED specified: map attempt fails 126310037SARM gem5 Developers return -EINVAL; 126410037SARM gem5 Developers } else { 126510037SARM gem5 Developers // MAP_FIXED not specified: ignore suggested start address 126610037SARM gem5 Developers warn("mmap: ignoring suggested map address 0x%x\n", start); 126710037SARM gem5 Developers use_provided_address = false; 126810037SARM gem5 Developers } 126910037SARM gem5 Developers } 127010037SARM gem5 Developers } 127110037SARM gem5 Developers 127210037SARM gem5 Developers if (!use_provided_address) { 127310037SARM gem5 Developers // no address provided, or provided address unusable: 127410037SARM gem5 Developers // pick next address from our "mmap region" 127510037SARM gem5 Developers if (OS::mmapGrowsDown()) { 127610037SARM gem5 Developers start = p->mmap_end - length; 127710037SARM gem5 Developers p->mmap_end = start; 127810037SARM gem5 Developers } else { 127910037SARM gem5 Developers start = p->mmap_end; 128010037SARM gem5 Developers p->mmap_end += length; 128110037SARM gem5 Developers } 128210037SARM gem5 Developers } 128310037SARM gem5 Developers 128410037SARM gem5 Developers p->allocateMem(start, length, clobber); 128510037SARM gem5 Developers 128610037SARM gem5 Developers return start; 128710037SARM gem5 Developers} 128810037SARM gem5 Developers 128910037SARM gem5 Developers/// Target getrlimit() handler. 129010037SARM gem5 Developerstemplate <class OS> 129110037SARM gem5 DevelopersSyscallReturn 129210037SARM gem5 DevelopersgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 129310037SARM gem5 Developers ThreadContext *tc) 129410037SARM gem5 Developers{ 129510537Sandreas.hansson@arm.com int index = 0; 129610537Sandreas.hansson@arm.com unsigned resource = process->getSyscallArg(tc, index); 129710537Sandreas.hansson@arm.com TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 129810537Sandreas.hansson@arm.com 129910037SARM gem5 Developers switch (resource) { 130010037SARM gem5 Developers case OS::TGT_RLIMIT_STACK: 130110037SARM gem5 Developers // max stack size in bytes: make up a number (8MB for now) 130210037SARM gem5 Developers rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 130310037SARM gem5 Developers rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 130410037SARM gem5 Developers rlp->rlim_max = TheISA::htog(rlp->rlim_max); 130510037SARM gem5 Developers break; 130610037SARM gem5 Developers 130710037SARM gem5 Developers case OS::TGT_RLIMIT_DATA: 130810037SARM gem5 Developers // max data segment size in bytes: make up a number 130910037SARM gem5 Developers rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 131010037SARM gem5 Developers rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 131110037SARM gem5 Developers rlp->rlim_max = TheISA::htog(rlp->rlim_max); 131210037SARM gem5 Developers break; 131310037SARM gem5 Developers 131410037SARM gem5 Developers default: 131510037SARM gem5 Developers std::cerr << "getrlimitFunc: unimplemented resource " << resource 131610037SARM gem5 Developers << std::endl; 131710037SARM gem5 Developers abort(); 131810037SARM gem5 Developers break; 131910037SARM gem5 Developers } 132010037SARM gem5 Developers 132110037SARM gem5 Developers rlp.copyOut(tc->getMemProxy()); 132210037SARM gem5 Developers return 0; 132310037SARM gem5 Developers} 132410037SARM gem5 Developers 132510037SARM gem5 Developers/// Target gettimeofday() handler. 132610037SARM gem5 Developerstemplate <class OS> 132710037SARM gem5 DevelopersSyscallReturn 132810037SARM gem5 DevelopersgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 132910037SARM gem5 Developers ThreadContext *tc) 133010037SARM gem5 Developers{ 133110037SARM gem5 Developers int index = 0; 133210037SARM gem5 Developers TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 133310037SARM gem5 Developers 133410037SARM gem5 Developers getElapsedTime(tp->tv_sec, tp->tv_usec); 133510037SARM gem5 Developers tp->tv_sec += seconds_since_epoch; 133610037SARM gem5 Developers tp->tv_sec = TheISA::htog(tp->tv_sec); 133710037SARM gem5 Developers tp->tv_usec = TheISA::htog(tp->tv_usec); 133810037SARM gem5 Developers 133910037SARM gem5 Developers tp.copyOut(tc->getMemProxy()); 134010037SARM gem5 Developers 134110037SARM gem5 Developers return 0; 134210037SARM gem5 Developers} 134310037SARM gem5 Developers 134410037SARM gem5 Developers 134510037SARM gem5 Developers/// Target utimes() handler. 134610037SARM gem5 Developerstemplate <class OS> 134710037SARM gem5 DevelopersSyscallReturn 134810037SARM gem5 DevelopersutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 134910037SARM gem5 Developers ThreadContext *tc) 135011321Ssteve.reinhardt@amd.com{ 135110037SARM gem5 Developers std::string path; 135210037SARM gem5 Developers 135310037SARM gem5 Developers int index = 0; 135410037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 135510037SARM gem5 Developers process->getSyscallArg(tc, index))) { 135610037SARM gem5 Developers return -EFAULT; 135710037SARM gem5 Developers } 135810037SARM gem5 Developers 135910037SARM gem5 Developers TypedBufferArg<typename OS::timeval [2]> 136010037SARM gem5 Developers tp(process->getSyscallArg(tc, index)); 136110037SARM gem5 Developers tp.copyIn(tc->getMemProxy()); 136210037SARM gem5 Developers 136310037SARM gem5 Developers struct timeval hostTimeval[2]; 136410037SARM gem5 Developers for (int i = 0; i < 2; ++i) 136510037SARM gem5 Developers { 136610037SARM gem5 Developers hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 136710037SARM gem5 Developers hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 136810037SARM gem5 Developers } 136910537Sandreas.hansson@arm.com 137010537Sandreas.hansson@arm.com // Adjust path for current working directory 137110537Sandreas.hansson@arm.com path = process->fullPath(path); 137210037SARM gem5 Developers 137310037SARM gem5 Developers int result = utimes(path.c_str(), hostTimeval); 137410037SARM gem5 Developers 137510037SARM gem5 Developers if (result < 0) 137610037SARM gem5 Developers return -errno; 137710037SARM gem5 Developers 137810037SARM gem5 Developers return 0; 137910037SARM gem5 Developers} 138010037SARM gem5 Developers/// Target getrusage() function. 138110037SARM gem5 Developerstemplate <class OS> 138210037SARM gem5 DevelopersSyscallReturn 138310037SARM gem5 DevelopersgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 138410037SARM gem5 Developers ThreadContext *tc) 138510037SARM gem5 Developers{ 138610037SARM gem5 Developers int index = 0; 138710037SARM gem5 Developers int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 138810037SARM gem5 Developers TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 138910037SARM gem5 Developers 139010037SARM gem5 Developers rup->ru_utime.tv_sec = 0; 139110037SARM gem5 Developers rup->ru_utime.tv_usec = 0; 139210037SARM gem5 Developers rup->ru_stime.tv_sec = 0; 139310037SARM gem5 Developers rup->ru_stime.tv_usec = 0; 139410037SARM gem5 Developers rup->ru_maxrss = 0; 139510037SARM gem5 Developers rup->ru_ixrss = 0; 139610037SARM gem5 Developers rup->ru_idrss = 0; 139711321Ssteve.reinhardt@amd.com rup->ru_isrss = 0; 139810037SARM gem5 Developers rup->ru_minflt = 0; 139910037SARM gem5 Developers rup->ru_majflt = 0; 140010037SARM gem5 Developers rup->ru_nswap = 0; 140110037SARM gem5 Developers rup->ru_inblock = 0; 140210037SARM gem5 Developers rup->ru_oublock = 0; 140310037SARM gem5 Developers rup->ru_msgsnd = 0; 140410037SARM gem5 Developers rup->ru_msgrcv = 0; 140510037SARM gem5 Developers rup->ru_nsignals = 0; 140610037SARM gem5 Developers rup->ru_nvcsw = 0; 140711321Ssteve.reinhardt@amd.com rup->ru_nivcsw = 0; 140810037SARM gem5 Developers 140910037SARM gem5 Developers switch (who) { 141010037SARM gem5 Developers case OS::TGT_RUSAGE_SELF: 141110037SARM gem5 Developers getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 141210037SARM gem5 Developers rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 141310037SARM gem5 Developers rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 141410037SARM gem5 Developers break; 141510037SARM gem5 Developers 141610037SARM gem5 Developers case OS::TGT_RUSAGE_CHILDREN: 141710037SARM gem5 Developers // do nothing. We have no child processes, so they take no time. 141810037SARM gem5 Developers break; 141910037SARM gem5 Developers 142010037SARM gem5 Developers default: 142110037SARM gem5 Developers // don't really handle THREAD or CHILDREN, but just warn and 142210037SARM gem5 Developers // plow ahead 142310037SARM gem5 Developers warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 142410037SARM gem5 Developers who); 142510037SARM gem5 Developers } 142610037SARM gem5 Developers 142710037SARM gem5 Developers rup.copyOut(tc->getMemProxy()); 142810037SARM gem5 Developers 142910037SARM gem5 Developers return 0; 143010037SARM gem5 Developers} 143110037SARM gem5 Developers 143210037SARM gem5 Developers/// Target times() function. 143310037SARM gem5 Developerstemplate <class OS> 143410037SARM gem5 DevelopersSyscallReturn 143510037SARM gem5 DeveloperstimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 143610037SARM gem5 Developers ThreadContext *tc) 14377175Sgblack@eecs.umich.edu{ 14387175Sgblack@eecs.umich.edu int index = 0; 14397175Sgblack@eecs.umich.edu TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 14407175Sgblack@eecs.umich.edu 14417175Sgblack@eecs.umich.edu // Fill in the time structure (in clocks) 14427175Sgblack@eecs.umich.edu int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 14437175Sgblack@eecs.umich.edu bufp->tms_utime = clocks; 14447175Sgblack@eecs.umich.edu bufp->tms_stime = 0; 14457175Sgblack@eecs.umich.edu bufp->tms_cutime = 0; 14467175Sgblack@eecs.umich.edu bufp->tms_cstime = 0; 14477175Sgblack@eecs.umich.edu 14487175Sgblack@eecs.umich.edu // Convert to host endianness 144910037SARM gem5 Developers bufp->tms_utime = TheISA::htog(bufp->tms_utime); 14507175Sgblack@eecs.umich.edu 14517175Sgblack@eecs.umich.edu // Write back 14527175Sgblack@eecs.umich.edu bufp.copyOut(tc->getMemProxy()); 14537175Sgblack@eecs.umich.edu 14547175Sgblack@eecs.umich.edu // Return clock ticks since system boot 145510037SARM gem5 Developers return clocks; 145610037SARM gem5 Developers} 14577175Sgblack@eecs.umich.edu 14587342Sgblack@eecs.umich.edu/// Target time() function. 14597342Sgblack@eecs.umich.edutemplate <class OS> 14607342Sgblack@eecs.umich.eduSyscallReturn 14617395Sgblack@eecs.umich.edutimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 14627175Sgblack@eecs.umich.edu ThreadContext *tc) 14637342Sgblack@eecs.umich.edu{ 14647342Sgblack@eecs.umich.edu typename OS::time_t sec, usec; 14657175Sgblack@eecs.umich.edu getElapsedTime(sec, usec); 14667342Sgblack@eecs.umich.edu sec += seconds_since_epoch; 14677175Sgblack@eecs.umich.edu 14687175Sgblack@eecs.umich.edu int index = 0; 14697639Sgblack@eecs.umich.edu Addr taddr = (Addr)process->getSyscallArg(tc, index); 14707639Sgblack@eecs.umich.edu if(taddr != 0) { 14717639Sgblack@eecs.umich.edu typename OS::time_t t = sec; 14727639Sgblack@eecs.umich.edu t = TheISA::htog(t); 14737639Sgblack@eecs.umich.edu SETranslatingPortProxy &p = tc->getMemProxy(); 14747639Sgblack@eecs.umich.edu p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 14757639Sgblack@eecs.umich.edu } 14767639Sgblack@eecs.umich.edu return sec; 14777639Sgblack@eecs.umich.edu} 14787175Sgblack@eecs.umich.edu 14797639Sgblack@eecs.umich.edu 14807639Sgblack@eecs.umich.edu#endif // __SIM_SYSCALL_EMUL_HH__ 14817639Sgblack@eecs.umich.edu