syscall_emul.hh revision 9455
1360SN/A/* 21458SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 3360SN/A * All rights reserved. 4360SN/A * 5360SN/A * Redistribution and use in source and binary forms, with or without 6360SN/A * modification, are permitted provided that the following conditions are 7360SN/A * met: redistributions of source code must retain the above copyright 8360SN/A * notice, this list of conditions and the following disclaimer; 9360SN/A * redistributions in binary form must reproduce the above copyright 10360SN/A * notice, this list of conditions and the following disclaimer in the 11360SN/A * documentation and/or other materials provided with the distribution; 12360SN/A * neither the name of the copyright holders nor the names of its 13360SN/A * contributors may be used to endorse or promote products derived from 14360SN/A * this software without specific prior written permission. 15360SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 292665Ssaidi@eecs.umich.edu * Kevin Lim 30360SN/A */ 31360SN/A 321354SN/A#ifndef __SIM_SYSCALL_EMUL_HH__ 331354SN/A#define __SIM_SYSCALL_EMUL_HH__ 34360SN/A 352764Sstever@eecs.umich.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 369202Spalle@lyckegaard.dk defined(__FreeBSD__) || defined(__CYGWIN__) || \ 379202Spalle@lyckegaard.dk defined(__NetBSD__)) 382064SN/A 39360SN/A/// 40360SN/A/// @file syscall_emul.hh 41360SN/A/// 42360SN/A/// This file defines objects used to emulate syscalls from the target 43360SN/A/// application on the host machine. 44360SN/A 451809SN/A#ifdef __CYGWIN32__ 465543Ssaidi@eecs.umich.edu#include <sys/fcntl.h> // for O_BINARY 471809SN/A#endif 483113Sgblack@eecs.umich.edu#include <sys/stat.h> 498229Snate@binkert.org#include <sys/time.h> 508229Snate@binkert.org#include <sys/uio.h> 513113Sgblack@eecs.umich.edu#include <fcntl.h> 527075Snate@binkert.org 538229Snate@binkert.org#include <cerrno> 547075Snate@binkert.org#include <string> 55360SN/A 562474SN/A#include "base/chunk_generator.hh" 575543Ssaidi@eecs.umich.edu#include "base/intmath.hh" // for RoundUp 582462SN/A#include "base/misc.hh" 591354SN/A#include "base/trace.hh" 606216Snate@binkert.org#include "base/types.hh" 616658Snate@binkert.org#include "config/the_isa.hh" 622474SN/A#include "cpu/base.hh" 632680Sktlim@umich.edu#include "cpu/thread_context.hh" 648232Snate@binkert.org#include "debug/SyscallVerbose.hh" 658229Snate@binkert.org#include "mem/page_table.hh" 668706Sandreas.hansson@arm.com#include "mem/se_translating_port_proxy.hh" 677678Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 688229Snate@binkert.org#include "sim/process.hh" 698766Sgblack@eecs.umich.edu#include "sim/syscallreturn.hh" 706640Svince@csl.cornell.edu#include "sim/system.hh" 71360SN/A 72360SN/A/// 73360SN/A/// System call descriptor. 74360SN/A/// 75360SN/Aclass SyscallDesc { 76360SN/A 77360SN/A public: 78360SN/A 79378SN/A /// Typedef for target syscall handler functions. 801450SN/A typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 813114Sgblack@eecs.umich.edu LiveProcess *, ThreadContext *); 82360SN/A 835543Ssaidi@eecs.umich.edu const char *name; //!< Syscall name (e.g., "open"). 845543Ssaidi@eecs.umich.edu FuncPtr funcPtr; //!< Pointer to emulation function. 855543Ssaidi@eecs.umich.edu int flags; //!< Flags (see Flags enum). 86360SN/A 87360SN/A /// Flag values for controlling syscall behavior. 88360SN/A enum Flags { 89360SN/A /// Don't set return regs according to funcPtr return value. 90360SN/A /// Used for syscalls with non-standard return conventions 912680Sktlim@umich.edu /// that explicitly set the ThreadContext regs (e.g., 92360SN/A /// sigreturn). 93360SN/A SuppressReturnValue = 1 94360SN/A }; 95360SN/A 96360SN/A /// Constructor. 97360SN/A SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 98360SN/A : name(_name), funcPtr(_funcPtr), flags(_flags) 99360SN/A { 100360SN/A } 101360SN/A 102360SN/A /// Emulate the syscall. Public interface for calling through funcPtr. 1033114Sgblack@eecs.umich.edu void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 104360SN/A}; 105360SN/A 106360SN/A 107360SN/Aclass BaseBufferArg { 108360SN/A 109360SN/A public: 110360SN/A 111360SN/A BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 112360SN/A { 113360SN/A bufPtr = new uint8_t[size]; 114360SN/A // clear out buffer: in case we only partially populate this, 115360SN/A // and then do a copyOut(), we want to make sure we don't 116360SN/A // introduce any random junk into the simulated address space 117360SN/A memset(bufPtr, 0, size); 118360SN/A } 119360SN/A 120360SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 121360SN/A 122360SN/A // 123360SN/A // copy data into simulator space (read from target memory) 124360SN/A // 1258852Sandreas.hansson@arm.com virtual bool copyIn(SETranslatingPortProxy &memproxy) 126360SN/A { 1278852Sandreas.hansson@arm.com memproxy.readBlob(addr, bufPtr, size); 1285543Ssaidi@eecs.umich.edu return true; // no EFAULT detection for now 129360SN/A } 130360SN/A 131360SN/A // 132360SN/A // copy data out of simulator space (write to target memory) 133360SN/A // 1348852Sandreas.hansson@arm.com virtual bool copyOut(SETranslatingPortProxy &memproxy) 135360SN/A { 1368852Sandreas.hansson@arm.com memproxy.writeBlob(addr, bufPtr, size); 1375543Ssaidi@eecs.umich.edu return true; // no EFAULT detection for now 138360SN/A } 139360SN/A 140360SN/A protected: 141360SN/A Addr addr; 142360SN/A int size; 143360SN/A uint8_t *bufPtr; 144360SN/A}; 145360SN/A 146360SN/A 147360SN/Aclass BufferArg : public BaseBufferArg 148360SN/A{ 149360SN/A public: 150360SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1515543Ssaidi@eecs.umich.edu void *bufferPtr() { return bufPtr; } 152360SN/A}; 153360SN/A 154360SN/Atemplate <class T> 155360SN/Aclass TypedBufferArg : public BaseBufferArg 156360SN/A{ 157360SN/A public: 158360SN/A // user can optionally specify a specific number of bytes to 159360SN/A // allocate to deal with those structs that have variable-size 160360SN/A // arrays at the end 161360SN/A TypedBufferArg(Addr _addr, int _size = sizeof(T)) 162360SN/A : BaseBufferArg(_addr, _size) 163360SN/A { } 164360SN/A 165360SN/A // type case 166360SN/A operator T*() { return (T *)bufPtr; } 167360SN/A 168360SN/A // dereference operators 1695543Ssaidi@eecs.umich.edu T &operator*() { return *((T *)bufPtr); } 1705543Ssaidi@eecs.umich.edu T* operator->() { return (T *)bufPtr; } 171502SN/A T &operator[](int i) { return ((T *)bufPtr)[i]; } 172360SN/A}; 173360SN/A 174360SN/A////////////////////////////////////////////////////////////////////// 175360SN/A// 176360SN/A// The following emulation functions are generic enough that they 177360SN/A// don't need to be recompiled for different emulated OS's. They are 178360SN/A// defined in sim/syscall_emul.cc. 179360SN/A// 180360SN/A////////////////////////////////////////////////////////////////////// 181360SN/A 182360SN/A 183378SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1841706SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1853114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 186378SN/A 187378SN/A/// Handler for unimplemented syscalls that we never intend to 188378SN/A/// implement (signal handling, etc.) and should not affect the correct 189378SN/A/// behavior of the program. Print a warning only if the appropriate 190378SN/A/// trace flag is enabled. Return success to the target program. 1911706SN/ASyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1923114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1938149SChris.Emmons@ARM.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 1948149SChris.Emmons@ARM.com LiveProcess *p, ThreadContext *tc); 195360SN/A 1966109Ssanchezd@stanford.edu/// Target exit() handler: terminate current context. 1971706SN/ASyscallReturn exitFunc(SyscallDesc *desc, int num, 1983114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 199378SN/A 2006109Ssanchezd@stanford.edu/// Target exit_group() handler: terminate simulation. (exit all threads) 2016109Ssanchezd@stanford.eduSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 2026109Ssanchezd@stanford.edu LiveProcess *p, ThreadContext *tc); 2036109Ssanchezd@stanford.edu 204378SN/A/// Target getpagesize() handler. 2051706SN/ASyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 2063114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 207378SN/A 2085748SSteve.Reinhardt@amd.com/// Target brk() handler: set brk address. 2095748SSteve.Reinhardt@amd.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 2105748SSteve.Reinhardt@amd.com LiveProcess *p, ThreadContext *tc); 211378SN/A 212378SN/A/// Target close() handler. 2131706SN/ASyscallReturn closeFunc(SyscallDesc *desc, int num, 2143114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 215378SN/A 216378SN/A/// Target read() handler. 2171706SN/ASyscallReturn readFunc(SyscallDesc *desc, int num, 2183114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 219378SN/A 220378SN/A/// Target write() handler. 2211706SN/ASyscallReturn writeFunc(SyscallDesc *desc, int num, 2223114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 223378SN/A 224378SN/A/// Target lseek() handler. 2251706SN/ASyscallReturn lseekFunc(SyscallDesc *desc, int num, 2263114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 227378SN/A 2284118Sgblack@eecs.umich.edu/// Target _llseek() handler. 2294118Sgblack@eecs.umich.eduSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 2304118Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2314118Sgblack@eecs.umich.edu 232378SN/A/// Target munmap() handler. 2331706SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num, 2343114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 235378SN/A 236378SN/A/// Target gethostname() handler. 2371706SN/ASyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2383114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 239360SN/A 2405513SMichael.Adler@intel.com/// Target getcwd() handler. 2415513SMichael.Adler@intel.comSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2425513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2435513SMichael.Adler@intel.com 2445513SMichael.Adler@intel.com/// Target unlink() handler. 2455513SMichael.Adler@intel.comSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2465513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2475513SMichael.Adler@intel.com 248511SN/A/// Target unlink() handler. 2491706SN/ASyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2503114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 251511SN/A 2525513SMichael.Adler@intel.com/// Target mkdir() handler. 2535513SMichael.Adler@intel.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2545513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2555513SMichael.Adler@intel.com 256511SN/A/// Target rename() handler. 2571706SN/ASyscallReturn renameFunc(SyscallDesc *desc, int num, 2583114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2591706SN/A 2601706SN/A 2611706SN/A/// Target truncate() handler. 2621706SN/ASyscallReturn truncateFunc(SyscallDesc *desc, int num, 2633114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2641706SN/A 2651706SN/A 2661706SN/A/// Target ftruncate() handler. 2671706SN/ASyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2683114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2691706SN/A 270511SN/A 2716703Svince@csl.cornell.edu/// Target truncate64() handler. 2726703Svince@csl.cornell.eduSyscallReturn truncate64Func(SyscallDesc *desc, int num, 2736703Svince@csl.cornell.edu LiveProcess *p, ThreadContext *tc); 2746703Svince@csl.cornell.edu 2756685Stjones1@inf.ed.ac.uk/// Target ftruncate64() handler. 2766685Stjones1@inf.ed.ac.ukSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2776685Stjones1@inf.ed.ac.uk LiveProcess *p, ThreadContext *tc); 2786685Stjones1@inf.ed.ac.uk 2796685Stjones1@inf.ed.ac.uk 2805513SMichael.Adler@intel.com/// Target umask() handler. 2815513SMichael.Adler@intel.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 2825513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2835513SMichael.Adler@intel.com 2845513SMichael.Adler@intel.com 2851999SN/A/// Target chown() handler. 2861999SN/ASyscallReturn chownFunc(SyscallDesc *desc, int num, 2873114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2881999SN/A 2891999SN/A 2901999SN/A/// Target fchown() handler. 2911999SN/ASyscallReturn fchownFunc(SyscallDesc *desc, int num, 2923114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2931999SN/A 2943079Sstever@eecs.umich.edu/// Target dup() handler. 2953079Sstever@eecs.umich.eduSyscallReturn dupFunc(SyscallDesc *desc, int num, 2963114Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 2973079Sstever@eecs.umich.edu 2982093SN/A/// Target fnctl() handler. 2992093SN/ASyscallReturn fcntlFunc(SyscallDesc *desc, int num, 3003114Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3012093SN/A 3022687Sksewell@umich.edu/// Target fcntl64() handler. 3032687Sksewell@umich.eduSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 3043114Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3052687Sksewell@umich.edu 3062238SN/A/// Target setuid() handler. 3072238SN/ASyscallReturn setuidFunc(SyscallDesc *desc, int num, 3083114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3092238SN/A 3102238SN/A/// Target getpid() handler. 3112238SN/ASyscallReturn getpidFunc(SyscallDesc *desc, int num, 3123114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3132238SN/A 3142238SN/A/// Target getuid() handler. 3152238SN/ASyscallReturn getuidFunc(SyscallDesc *desc, int num, 3163114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3172238SN/A 3182238SN/A/// Target getgid() handler. 3192238SN/ASyscallReturn getgidFunc(SyscallDesc *desc, int num, 3203114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3212238SN/A 3222238SN/A/// Target getppid() handler. 3232238SN/ASyscallReturn getppidFunc(SyscallDesc *desc, int num, 3243114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3252238SN/A 3262238SN/A/// Target geteuid() handler. 3272238SN/ASyscallReturn geteuidFunc(SyscallDesc *desc, int num, 3283114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3292238SN/A 3302238SN/A/// Target getegid() handler. 3312238SN/ASyscallReturn getegidFunc(SyscallDesc *desc, int num, 3323114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3332238SN/A 3346109Ssanchezd@stanford.edu/// Target clone() handler. 3356109Ssanchezd@stanford.eduSyscallReturn cloneFunc(SyscallDesc *desc, int num, 3366109Ssanchezd@stanford.edu LiveProcess *p, ThreadContext *tc); 3372238SN/A 3389455Smitch.hayenga+gem5@gmail.com/// Target access() handler 3399455Smitch.hayenga+gem5@gmail.comSyscallReturn accessFunc(SyscallDesc *desc, int num, 3409455Smitch.hayenga+gem5@gmail.com LiveProcess *p, ThreadContext *tc); 3419455Smitch.hayenga+gem5@gmail.com 3429112Smarc.orr@gmail.com/// Futex system call 3439112Smarc.orr@gmail.com/// Implemented by Daniel Sanchez 3449112Smarc.orr@gmail.com/// Used by printf's in multi-threaded apps 3459112Smarc.orr@gmail.comtemplate <class OS> 3469112Smarc.orr@gmail.comSyscallReturn 3479112Smarc.orr@gmail.comfutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3489112Smarc.orr@gmail.com ThreadContext *tc) 3499112Smarc.orr@gmail.com{ 3509112Smarc.orr@gmail.com int index_uaddr = 0; 3519112Smarc.orr@gmail.com int index_op = 1; 3529112Smarc.orr@gmail.com int index_val = 2; 3539112Smarc.orr@gmail.com int index_timeout = 3; 3549112Smarc.orr@gmail.com 3559112Smarc.orr@gmail.com uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3569112Smarc.orr@gmail.com int op = process->getSyscallArg(tc, index_op); 3579112Smarc.orr@gmail.com int val = process->getSyscallArg(tc, index_val); 3589112Smarc.orr@gmail.com uint64_t timeout = process->getSyscallArg(tc, index_timeout); 3599112Smarc.orr@gmail.com 3609112Smarc.orr@gmail.com std::map<uint64_t, std::list<ThreadContext *> * > 3619112Smarc.orr@gmail.com &futex_map = tc->getSystemPtr()->futexMap; 3629112Smarc.orr@gmail.com 3639112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 3649112Smarc.orr@gmail.com uaddr, op, val); 3659112Smarc.orr@gmail.com 3669238Slluc.alvarez@bsc.es op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 3679112Smarc.orr@gmail.com 3689112Smarc.orr@gmail.com if (op == OS::TGT_FUTEX_WAIT) { 3699112Smarc.orr@gmail.com if (timeout != 0) { 3709112Smarc.orr@gmail.com warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 3719112Smarc.orr@gmail.com "we'll wait indefinitely"); 3729112Smarc.orr@gmail.com } 3739112Smarc.orr@gmail.com 3749112Smarc.orr@gmail.com uint8_t *buf = new uint8_t[sizeof(int)]; 3759112Smarc.orr@gmail.com tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3769112Smarc.orr@gmail.com int mem_val = *((int *)buf); 3779112Smarc.orr@gmail.com delete buf; 3789112Smarc.orr@gmail.com 3799112Smarc.orr@gmail.com if(val != mem_val) { 3809112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 3819112Smarc.orr@gmail.com "expected: %d\n", mem_val, val); 3829112Smarc.orr@gmail.com return -OS::TGT_EWOULDBLOCK; 3839112Smarc.orr@gmail.com } 3849112Smarc.orr@gmail.com 3859112Smarc.orr@gmail.com // Queue the thread context 3869112Smarc.orr@gmail.com std::list<ThreadContext *> * tcWaitList; 3879112Smarc.orr@gmail.com if (futex_map.count(uaddr)) { 3889112Smarc.orr@gmail.com tcWaitList = futex_map.find(uaddr)->second; 3899112Smarc.orr@gmail.com } else { 3909112Smarc.orr@gmail.com tcWaitList = new std::list<ThreadContext *>(); 3919112Smarc.orr@gmail.com futex_map.insert(std::pair< uint64_t, 3929112Smarc.orr@gmail.com std::list<ThreadContext *> * >(uaddr, tcWaitList)); 3939112Smarc.orr@gmail.com } 3949112Smarc.orr@gmail.com tcWaitList->push_back(tc); 3959112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 3969112Smarc.orr@gmail.com "thread context\n"); 3979112Smarc.orr@gmail.com tc->suspend(); 3989112Smarc.orr@gmail.com return 0; 3999112Smarc.orr@gmail.com } else if (op == OS::TGT_FUTEX_WAKE){ 4009112Smarc.orr@gmail.com int wokenUp = 0; 4019112Smarc.orr@gmail.com std::list<ThreadContext *> * tcWaitList; 4029112Smarc.orr@gmail.com if (futex_map.count(uaddr)) { 4039112Smarc.orr@gmail.com tcWaitList = futex_map.find(uaddr)->second; 4049112Smarc.orr@gmail.com while (tcWaitList->size() > 0 && wokenUp < val) { 4059112Smarc.orr@gmail.com tcWaitList->front()->activate(); 4069112Smarc.orr@gmail.com tcWaitList->pop_front(); 4079112Smarc.orr@gmail.com wokenUp++; 4089112Smarc.orr@gmail.com } 4099112Smarc.orr@gmail.com if(tcWaitList->empty()) { 4109112Smarc.orr@gmail.com futex_map.erase(uaddr); 4119112Smarc.orr@gmail.com delete tcWaitList; 4129112Smarc.orr@gmail.com } 4139112Smarc.orr@gmail.com } 4149112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 4159112Smarc.orr@gmail.com "thread contexts\n", wokenUp); 4169112Smarc.orr@gmail.com return wokenUp; 4179112Smarc.orr@gmail.com } else { 4189238Slluc.alvarez@bsc.es warn("sys_futex: op %d is not implemented, just returning...", op); 4199112Smarc.orr@gmail.com return 0; 4209112Smarc.orr@gmail.com } 4219112Smarc.orr@gmail.com 4229112Smarc.orr@gmail.com} 4239112Smarc.orr@gmail.com 4242238SN/A 4252238SN/A/// Pseudo Funcs - These functions use a different return convension, 4262238SN/A/// returning a second value in a register other than the normal return register 4272238SN/ASyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 4283114Sgblack@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 4292238SN/A 4302238SN/A/// Target getpidPseudo() handler. 4312238SN/ASyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 4323114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4332238SN/A 4342238SN/A/// Target getuidPseudo() handler. 4352238SN/ASyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 4363114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4372238SN/A 4382238SN/A/// Target getgidPseudo() handler. 4392238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4403114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4412238SN/A 4422238SN/A 4431354SN/A/// A readable name for 1,000,000, for converting microseconds to seconds. 4441354SN/Aconst int one_million = 1000000; 4451354SN/A 4461354SN/A/// Approximate seconds since the epoch (1/1/1970). About a billion, 4471354SN/A/// by my reckoning. We want to keep this a constant (not use the 4481354SN/A/// real-world time) to keep simulations repeatable. 4491354SN/Aconst unsigned seconds_since_epoch = 1000000000; 4501354SN/A 4511354SN/A/// Helper function to convert current elapsed time to seconds and 4521354SN/A/// microseconds. 4531354SN/Atemplate <class T1, class T2> 4541354SN/Avoid 4551354SN/AgetElapsedTime(T1 &sec, T2 &usec) 4561354SN/A{ 4577823Ssteve.reinhardt@amd.com int elapsed_usecs = curTick() / SimClock::Int::us; 4581354SN/A sec = elapsed_usecs / one_million; 4591354SN/A usec = elapsed_usecs % one_million; 4601354SN/A} 4611354SN/A 462360SN/A////////////////////////////////////////////////////////////////////// 463360SN/A// 464360SN/A// The following emulation functions are generic, but need to be 465360SN/A// templated to account for differences in types, constants, etc. 466360SN/A// 467360SN/A////////////////////////////////////////////////////////////////////// 468360SN/A 4693113Sgblack@eecs.umich.edu#if NO_STAT64 4703113Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4713113Sgblack@eecs.umich.edu typedef struct stat hst_stat64; 4723113Sgblack@eecs.umich.edu#else 4733113Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4743113Sgblack@eecs.umich.edu typedef struct stat64 hst_stat64; 4753113Sgblack@eecs.umich.edu#endif 4763113Sgblack@eecs.umich.edu 4773113Sgblack@eecs.umich.edu//// Helper function to convert a host stat buffer to a target stat 4783113Sgblack@eecs.umich.edu//// buffer. Also copies the target buffer out to the simulated 4793113Sgblack@eecs.umich.edu//// memory space. Used by stat(), fstat(), and lstat(). 4803113Sgblack@eecs.umich.edu 4813113Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat> 4823113Sgblack@eecs.umich.edustatic void 4833113Sgblack@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4843113Sgblack@eecs.umich.edu{ 4854189Sgblack@eecs.umich.edu using namespace TheISA; 4864189Sgblack@eecs.umich.edu 4873113Sgblack@eecs.umich.edu if (fakeTTY) 4883113Sgblack@eecs.umich.edu tgt->st_dev = 0xA; 4893113Sgblack@eecs.umich.edu else 4903113Sgblack@eecs.umich.edu tgt->st_dev = host->st_dev; 4918737Skoansin.tan@gmail.com tgt->st_dev = TheISA::htog(tgt->st_dev); 4923113Sgblack@eecs.umich.edu tgt->st_ino = host->st_ino; 4938737Skoansin.tan@gmail.com tgt->st_ino = TheISA::htog(tgt->st_ino); 4943277Sgblack@eecs.umich.edu tgt->st_mode = host->st_mode; 4955515SMichael.Adler@intel.com if (fakeTTY) { 4965515SMichael.Adler@intel.com // Claim to be a character device 4975515SMichael.Adler@intel.com tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4985515SMichael.Adler@intel.com tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4995515SMichael.Adler@intel.com } 5008737Skoansin.tan@gmail.com tgt->st_mode = TheISA::htog(tgt->st_mode); 5013277Sgblack@eecs.umich.edu tgt->st_nlink = host->st_nlink; 5028737Skoansin.tan@gmail.com tgt->st_nlink = TheISA::htog(tgt->st_nlink); 5033277Sgblack@eecs.umich.edu tgt->st_uid = host->st_uid; 5048737Skoansin.tan@gmail.com tgt->st_uid = TheISA::htog(tgt->st_uid); 5053277Sgblack@eecs.umich.edu tgt->st_gid = host->st_gid; 5068737Skoansin.tan@gmail.com tgt->st_gid = TheISA::htog(tgt->st_gid); 5073113Sgblack@eecs.umich.edu if (fakeTTY) 5083113Sgblack@eecs.umich.edu tgt->st_rdev = 0x880d; 5093113Sgblack@eecs.umich.edu else 5103113Sgblack@eecs.umich.edu tgt->st_rdev = host->st_rdev; 5118737Skoansin.tan@gmail.com tgt->st_rdev = TheISA::htog(tgt->st_rdev); 5123113Sgblack@eecs.umich.edu tgt->st_size = host->st_size; 5138737Skoansin.tan@gmail.com tgt->st_size = TheISA::htog(tgt->st_size); 5143114Sgblack@eecs.umich.edu tgt->st_atimeX = host->st_atime; 5158737Skoansin.tan@gmail.com tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5163114Sgblack@eecs.umich.edu tgt->st_mtimeX = host->st_mtime; 5178737Skoansin.tan@gmail.com tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5183114Sgblack@eecs.umich.edu tgt->st_ctimeX = host->st_ctime; 5198737Skoansin.tan@gmail.com tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5204061Sgblack@eecs.umich.edu // Force the block size to be 8k. This helps to ensure buffered io works 5214061Sgblack@eecs.umich.edu // consistently across different hosts. 5224061Sgblack@eecs.umich.edu tgt->st_blksize = 0x2000; 5238737Skoansin.tan@gmail.com tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5243113Sgblack@eecs.umich.edu tgt->st_blocks = host->st_blocks; 5258737Skoansin.tan@gmail.com tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5263113Sgblack@eecs.umich.edu} 5273113Sgblack@eecs.umich.edu 5283113Sgblack@eecs.umich.edu// Same for stat64 5293113Sgblack@eecs.umich.edu 5303113Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat64> 5313113Sgblack@eecs.umich.edustatic void 5323113Sgblack@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5333113Sgblack@eecs.umich.edu{ 5344189Sgblack@eecs.umich.edu using namespace TheISA; 5354189Sgblack@eecs.umich.edu 5363113Sgblack@eecs.umich.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5373113Sgblack@eecs.umich.edu#if defined(STAT_HAVE_NSEC) 5383113Sgblack@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5398737Skoansin.tan@gmail.com tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5403113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5418737Skoansin.tan@gmail.com tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5423113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5438737Skoansin.tan@gmail.com tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5443113Sgblack@eecs.umich.edu#else 5453113Sgblack@eecs.umich.edu tgt->st_atime_nsec = 0; 5463113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = 0; 5473113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = 0; 5483113Sgblack@eecs.umich.edu#endif 5493113Sgblack@eecs.umich.edu} 5503113Sgblack@eecs.umich.edu 5513113Sgblack@eecs.umich.edu//Here are a couple convenience functions 5523113Sgblack@eecs.umich.edutemplate<class OS> 5533113Sgblack@eecs.umich.edustatic void 5548852Sandreas.hansson@arm.comcopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5553113Sgblack@eecs.umich.edu hst_stat *host, bool fakeTTY = false) 5563113Sgblack@eecs.umich.edu{ 5573113Sgblack@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5583113Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5593113Sgblack@eecs.umich.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5603113Sgblack@eecs.umich.edu tgt.copyOut(mem); 5613113Sgblack@eecs.umich.edu} 5623113Sgblack@eecs.umich.edu 5633113Sgblack@eecs.umich.edutemplate<class OS> 5643113Sgblack@eecs.umich.edustatic void 5658852Sandreas.hansson@arm.comcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5663113Sgblack@eecs.umich.edu hst_stat64 *host, bool fakeTTY = false) 5673113Sgblack@eecs.umich.edu{ 5683113Sgblack@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5693113Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5706686Stjones1@inf.ed.ac.uk convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5713113Sgblack@eecs.umich.edu tgt.copyOut(mem); 5723113Sgblack@eecs.umich.edu} 5733113Sgblack@eecs.umich.edu 574378SN/A/// Target ioctl() handler. For the most part, programs call ioctl() 575378SN/A/// only to find out if their stdout is a tty, to determine whether to 5769141Smarc.orr@gmail.com/// do line or block buffering. We always claim that output fds are 5779141Smarc.orr@gmail.com/// not TTYs to provide repeatable results. 578360SN/Atemplate <class OS> 5791450SN/ASyscallReturn 5803114Sgblack@eecs.umich.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5812680Sktlim@umich.edu ThreadContext *tc) 582360SN/A{ 5836701Sgblack@eecs.umich.edu int index = 0; 5846701Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 5856701Sgblack@eecs.umich.edu unsigned req = process->getSyscallArg(tc, index); 586360SN/A 5871969SN/A DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 588360SN/A 589360SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 590360SN/A // doesn't map to any simulator fd: not a valid target fd 5911458SN/A return -EBADF; 592360SN/A } 593360SN/A 5949141Smarc.orr@gmail.com if (OS::isTtyReq(req)) { 5951458SN/A return -ENOTTY; 5969141Smarc.orr@gmail.com } 597360SN/A 5989141Smarc.orr@gmail.com warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 5999141Smarc.orr@gmail.com fd, req, tc->pcState()); 6009141Smarc.orr@gmail.com return -ENOTTY; 601360SN/A} 602360SN/A 603378SN/A/// Target open() handler. 604360SN/Atemplate <class OS> 6051450SN/ASyscallReturn 6063114Sgblack@eecs.umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6072680Sktlim@umich.edu ThreadContext *tc) 608360SN/A{ 609360SN/A std::string path; 610360SN/A 6116701Sgblack@eecs.umich.edu int index = 0; 6128852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 6136701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) 6141458SN/A return -EFAULT; 615360SN/A 616360SN/A if (path == "/dev/sysdev0") { 617360SN/A // This is a memory-mapped high-resolution timer device on Alpha. 618360SN/A // We don't support it, so just punt. 6191706SN/A warn("Ignoring open(%s, ...)\n", path); 6201458SN/A return -ENOENT; 621360SN/A } 622360SN/A 6236701Sgblack@eecs.umich.edu int tgtFlags = process->getSyscallArg(tc, index); 6246701Sgblack@eecs.umich.edu int mode = process->getSyscallArg(tc, index); 625360SN/A int hostFlags = 0; 626360SN/A 627360SN/A // translate open flags 628360SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 629360SN/A if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 630360SN/A tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 631360SN/A hostFlags |= OS::openFlagTable[i].hostFlag; 632360SN/A } 633360SN/A } 634360SN/A 635360SN/A // any target flags left? 636360SN/A if (tgtFlags != 0) 6371706SN/A warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 638360SN/A 639360SN/A#ifdef __CYGWIN32__ 640360SN/A hostFlags |= O_BINARY; 641360SN/A#endif 642360SN/A 6433669Sbinkertn@umich.edu // Adjust path for current working directory 6443669Sbinkertn@umich.edu path = process->fullPath(path); 6453669Sbinkertn@umich.edu 6461706SN/A DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 6471706SN/A 6485795Ssaidi@eecs.umich.edu int fd; 6499143Ssteve.reinhardt@amd.com int local_errno; 6509142Ssteve.reinhardt@amd.com if (startswith(path, "/proc/") || startswith(path, "/system/") || 6519142Ssteve.reinhardt@amd.com startswith(path, "/platform/") || startswith(path, "/sys/")) { 6529143Ssteve.reinhardt@amd.com // It's a proc/sys entry and requires special handling 6535795Ssaidi@eecs.umich.edu fd = OS::openSpecialFile(path, process, tc); 6549143Ssteve.reinhardt@amd.com local_errno = ENOENT; 6555795Ssaidi@eecs.umich.edu } else { 6565795Ssaidi@eecs.umich.edu // open the file 6575795Ssaidi@eecs.umich.edu fd = open(path.c_str(), hostFlags, mode); 6589143Ssteve.reinhardt@amd.com local_errno = errno; 6595795Ssaidi@eecs.umich.edu } 660360SN/A 6619143Ssteve.reinhardt@amd.com if (fd == -1) 6629143Ssteve.reinhardt@amd.com return -local_errno; 6639143Ssteve.reinhardt@amd.com 6649143Ssteve.reinhardt@amd.com return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false); 665360SN/A} 666360SN/A 6676640Svince@csl.cornell.edu/// Target sysinfo() handler. 6686640Svince@csl.cornell.edutemplate <class OS> 6696640Svince@csl.cornell.eduSyscallReturn 6706640Svince@csl.cornell.edusysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6716640Svince@csl.cornell.edu ThreadContext *tc) 6726640Svince@csl.cornell.edu{ 6736640Svince@csl.cornell.edu 6746701Sgblack@eecs.umich.edu int index = 0; 6756701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::tgt_sysinfo> 6766701Sgblack@eecs.umich.edu sysinfo(process->getSyscallArg(tc, index)); 6776640Svince@csl.cornell.edu 6786701Sgblack@eecs.umich.edu sysinfo->uptime=seconds_since_epoch; 6796701Sgblack@eecs.umich.edu sysinfo->totalram=process->system->memSize(); 6806640Svince@csl.cornell.edu 6818706Sandreas.hansson@arm.com sysinfo.copyOut(tc->getMemProxy()); 6826640Svince@csl.cornell.edu 6836701Sgblack@eecs.umich.edu return 0; 6846640Svince@csl.cornell.edu} 685360SN/A 6861999SN/A/// Target chmod() handler. 6871999SN/Atemplate <class OS> 6881999SN/ASyscallReturn 6893114Sgblack@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6902680Sktlim@umich.edu ThreadContext *tc) 6911999SN/A{ 6921999SN/A std::string path; 6931999SN/A 6946701Sgblack@eecs.umich.edu int index = 0; 6958852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 6966701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 6971999SN/A return -EFAULT; 6986701Sgblack@eecs.umich.edu } 6991999SN/A 7006701Sgblack@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 7011999SN/A mode_t hostMode = 0; 7021999SN/A 7031999SN/A // XXX translate mode flags via OS::something??? 7041999SN/A hostMode = mode; 7051999SN/A 7063669Sbinkertn@umich.edu // Adjust path for current working directory 7073669Sbinkertn@umich.edu path = process->fullPath(path); 7083669Sbinkertn@umich.edu 7091999SN/A // do the chmod 7101999SN/A int result = chmod(path.c_str(), hostMode); 7111999SN/A if (result < 0) 7122218SN/A return -errno; 7131999SN/A 7141999SN/A return 0; 7151999SN/A} 7161999SN/A 7171999SN/A 7181999SN/A/// Target fchmod() handler. 7191999SN/Atemplate <class OS> 7201999SN/ASyscallReturn 7213114Sgblack@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7222680Sktlim@umich.edu ThreadContext *tc) 7231999SN/A{ 7246701Sgblack@eecs.umich.edu int index = 0; 7256701Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 7261999SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 7271999SN/A // doesn't map to any simulator fd: not a valid target fd 7281999SN/A return -EBADF; 7291999SN/A } 7301999SN/A 7316701Sgblack@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 7321999SN/A mode_t hostMode = 0; 7331999SN/A 7341999SN/A // XXX translate mode flags via OS::someting??? 7351999SN/A hostMode = mode; 7361999SN/A 7371999SN/A // do the fchmod 7381999SN/A int result = fchmod(process->sim_fd(fd), hostMode); 7391999SN/A if (result < 0) 7402218SN/A return -errno; 7411999SN/A 7421999SN/A return 0; 7431999SN/A} 7441999SN/A 7455877Shsul@eecs.umich.edu/// Target mremap() handler. 7465877Shsul@eecs.umich.edutemplate <class OS> 7475877Shsul@eecs.umich.eduSyscallReturn 7485877Shsul@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 7495877Shsul@eecs.umich.edu{ 7506701Sgblack@eecs.umich.edu int index = 0; 7516701Sgblack@eecs.umich.edu Addr start = process->getSyscallArg(tc, index); 7526701Sgblack@eecs.umich.edu uint64_t old_length = process->getSyscallArg(tc, index); 7536701Sgblack@eecs.umich.edu uint64_t new_length = process->getSyscallArg(tc, index); 7546701Sgblack@eecs.umich.edu uint64_t flags = process->getSyscallArg(tc, index); 7555877Shsul@eecs.umich.edu 7565877Shsul@eecs.umich.edu if ((start % TheISA::VMPageSize != 0) || 7575877Shsul@eecs.umich.edu (new_length % TheISA::VMPageSize != 0)) { 7585877Shsul@eecs.umich.edu warn("mremap failing: arguments not page aligned"); 7595877Shsul@eecs.umich.edu return -EINVAL; 7605877Shsul@eecs.umich.edu } 7615877Shsul@eecs.umich.edu 7625877Shsul@eecs.umich.edu if (new_length > old_length) { 7635877Shsul@eecs.umich.edu if ((start + old_length) == process->mmap_end) { 7645877Shsul@eecs.umich.edu uint64_t diff = new_length - old_length; 7658601Ssteve.reinhardt@amd.com process->allocateMem(process->mmap_end, diff); 7665877Shsul@eecs.umich.edu process->mmap_end += diff; 7675877Shsul@eecs.umich.edu return start; 7685877Shsul@eecs.umich.edu } else { 7695877Shsul@eecs.umich.edu // sys/mman.h defined MREMAP_MAYMOVE 7705877Shsul@eecs.umich.edu if (!(flags & 1)) { 7715877Shsul@eecs.umich.edu warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 7725877Shsul@eecs.umich.edu return -ENOMEM; 7735877Shsul@eecs.umich.edu } else { 7745877Shsul@eecs.umich.edu process->pTable->remap(start, old_length, process->mmap_end); 7755877Shsul@eecs.umich.edu warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 7765877Shsul@eecs.umich.edu process->mmap_end, process->mmap_end + new_length, new_length); 7775877Shsul@eecs.umich.edu start = process->mmap_end; 7785877Shsul@eecs.umich.edu // add on the remaining unallocated pages 7798601Ssteve.reinhardt@amd.com process->allocateMem(start + old_length, 7808601Ssteve.reinhardt@amd.com new_length - old_length); 7815877Shsul@eecs.umich.edu process->mmap_end += new_length; 7825877Shsul@eecs.umich.edu warn("returning %08p as start\n", start); 7835877Shsul@eecs.umich.edu return start; 7845877Shsul@eecs.umich.edu } 7855877Shsul@eecs.umich.edu } 7865877Shsul@eecs.umich.edu } else { 7878601Ssteve.reinhardt@amd.com process->pTable->unmap(start + new_length, old_length - new_length); 7885877Shsul@eecs.umich.edu return start; 7895877Shsul@eecs.umich.edu } 7905877Shsul@eecs.umich.edu} 7911999SN/A 792378SN/A/// Target stat() handler. 793360SN/Atemplate <class OS> 7941450SN/ASyscallReturn 7953114Sgblack@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7962680Sktlim@umich.edu ThreadContext *tc) 797360SN/A{ 798360SN/A std::string path; 799360SN/A 8006701Sgblack@eecs.umich.edu int index = 0; 8018852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 8026701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 8036701Sgblack@eecs.umich.edu return -EFAULT; 8046701Sgblack@eecs.umich.edu } 8056701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 806360SN/A 8073669Sbinkertn@umich.edu // Adjust path for current working directory 8083669Sbinkertn@umich.edu path = process->fullPath(path); 8093669Sbinkertn@umich.edu 810360SN/A struct stat hostBuf; 811360SN/A int result = stat(path.c_str(), &hostBuf); 812360SN/A 813360SN/A if (result < 0) 8142218SN/A return -errno; 815360SN/A 8168706Sandreas.hansson@arm.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 817360SN/A 8181458SN/A return 0; 819360SN/A} 820360SN/A 821360SN/A 8225074Ssaidi@eecs.umich.edu/// Target stat64() handler. 8235074Ssaidi@eecs.umich.edutemplate <class OS> 8245074Ssaidi@eecs.umich.eduSyscallReturn 8255074Ssaidi@eecs.umich.edustat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8265074Ssaidi@eecs.umich.edu ThreadContext *tc) 8275074Ssaidi@eecs.umich.edu{ 8285074Ssaidi@eecs.umich.edu std::string path; 8295074Ssaidi@eecs.umich.edu 8306701Sgblack@eecs.umich.edu int index = 0; 8318852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 8326701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) 8335074Ssaidi@eecs.umich.edu return -EFAULT; 8346701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8355074Ssaidi@eecs.umich.edu 8365074Ssaidi@eecs.umich.edu // Adjust path for current working directory 8375074Ssaidi@eecs.umich.edu path = process->fullPath(path); 8385074Ssaidi@eecs.umich.edu 8395208Ssaidi@eecs.umich.edu#if NO_STAT64 8405208Ssaidi@eecs.umich.edu struct stat hostBuf; 8415208Ssaidi@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 8425208Ssaidi@eecs.umich.edu#else 8435074Ssaidi@eecs.umich.edu struct stat64 hostBuf; 8445074Ssaidi@eecs.umich.edu int result = stat64(path.c_str(), &hostBuf); 8455208Ssaidi@eecs.umich.edu#endif 8465074Ssaidi@eecs.umich.edu 8475074Ssaidi@eecs.umich.edu if (result < 0) 8485074Ssaidi@eecs.umich.edu return -errno; 8495074Ssaidi@eecs.umich.edu 8508706Sandreas.hansson@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 8515074Ssaidi@eecs.umich.edu 8525074Ssaidi@eecs.umich.edu return 0; 8535074Ssaidi@eecs.umich.edu} 8545074Ssaidi@eecs.umich.edu 8555074Ssaidi@eecs.umich.edu 8561999SN/A/// Target fstat64() handler. 8571999SN/Atemplate <class OS> 8581999SN/ASyscallReturn 8593114Sgblack@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8602680Sktlim@umich.edu ThreadContext *tc) 8611999SN/A{ 8626701Sgblack@eecs.umich.edu int index = 0; 8636701Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 8646701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8651999SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 8661999SN/A // doesn't map to any simulator fd: not a valid target fd 8671999SN/A return -EBADF; 8681999SN/A } 8691999SN/A 8702764Sstever@eecs.umich.edu#if NO_STAT64 8712064SN/A struct stat hostBuf; 8722064SN/A int result = fstat(process->sim_fd(fd), &hostBuf); 8732064SN/A#else 8742064SN/A struct stat64 hostBuf; 8751999SN/A int result = fstat64(process->sim_fd(fd), &hostBuf); 8762064SN/A#endif 8771999SN/A 8781999SN/A if (result < 0) 8792218SN/A return -errno; 8801999SN/A 8818706Sandreas.hansson@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 8821999SN/A 8831999SN/A return 0; 8841999SN/A} 8851999SN/A 8861999SN/A 887378SN/A/// Target lstat() handler. 888360SN/Atemplate <class OS> 8891450SN/ASyscallReturn 8903114Sgblack@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8912680Sktlim@umich.edu ThreadContext *tc) 892360SN/A{ 893360SN/A std::string path; 894360SN/A 8956701Sgblack@eecs.umich.edu int index = 0; 8968852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 8976701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 8986701Sgblack@eecs.umich.edu return -EFAULT; 8996701Sgblack@eecs.umich.edu } 9006701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 901360SN/A 9023669Sbinkertn@umich.edu // Adjust path for current working directory 9033669Sbinkertn@umich.edu path = process->fullPath(path); 9043669Sbinkertn@umich.edu 905360SN/A struct stat hostBuf; 906360SN/A int result = lstat(path.c_str(), &hostBuf); 907360SN/A 908360SN/A if (result < 0) 9091458SN/A return -errno; 910360SN/A 9118706Sandreas.hansson@arm.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 912360SN/A 9131458SN/A return 0; 914360SN/A} 915360SN/A 9161999SN/A/// Target lstat64() handler. 9171999SN/Atemplate <class OS> 9181999SN/ASyscallReturn 9193114Sgblack@eecs.umich.edulstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9202680Sktlim@umich.edu ThreadContext *tc) 9211999SN/A{ 9221999SN/A std::string path; 9231999SN/A 9246701Sgblack@eecs.umich.edu int index = 0; 9258852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 9266701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 9276701Sgblack@eecs.umich.edu return -EFAULT; 9286701Sgblack@eecs.umich.edu } 9296701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9301999SN/A 9313669Sbinkertn@umich.edu // Adjust path for current working directory 9323669Sbinkertn@umich.edu path = process->fullPath(path); 9333669Sbinkertn@umich.edu 9342764Sstever@eecs.umich.edu#if NO_STAT64 9352064SN/A struct stat hostBuf; 9362064SN/A int result = lstat(path.c_str(), &hostBuf); 9372064SN/A#else 9381999SN/A struct stat64 hostBuf; 9391999SN/A int result = lstat64(path.c_str(), &hostBuf); 9402064SN/A#endif 9411999SN/A 9421999SN/A if (result < 0) 9431999SN/A return -errno; 9441999SN/A 9458706Sandreas.hansson@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9461999SN/A 9471999SN/A return 0; 9481999SN/A} 9491999SN/A 950378SN/A/// Target fstat() handler. 951360SN/Atemplate <class OS> 9521450SN/ASyscallReturn 9533114Sgblack@eecs.umich.edufstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9542680Sktlim@umich.edu ThreadContext *tc) 955360SN/A{ 9566701Sgblack@eecs.umich.edu int index = 0; 9576701Sgblack@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 9586701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 959360SN/A 9601969SN/A DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 961360SN/A 962360SN/A if (fd < 0) 9631458SN/A return -EBADF; 964360SN/A 965360SN/A struct stat hostBuf; 966360SN/A int result = fstat(fd, &hostBuf); 967360SN/A 968360SN/A if (result < 0) 9691458SN/A return -errno; 970360SN/A 9718706Sandreas.hansson@arm.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 9722021SN/A 9731458SN/A return 0; 974360SN/A} 975360SN/A 976360SN/A 9771706SN/A/// Target statfs() handler. 9781706SN/Atemplate <class OS> 9791706SN/ASyscallReturn 9803114Sgblack@eecs.umich.edustatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9812680Sktlim@umich.edu ThreadContext *tc) 9821706SN/A{ 9831706SN/A std::string path; 9841706SN/A 9856701Sgblack@eecs.umich.edu int index = 0; 9868852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 9876701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 9886701Sgblack@eecs.umich.edu return -EFAULT; 9896701Sgblack@eecs.umich.edu } 9906701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9911706SN/A 9923669Sbinkertn@umich.edu // Adjust path for current working directory 9933669Sbinkertn@umich.edu path = process->fullPath(path); 9943669Sbinkertn@umich.edu 9951706SN/A struct statfs hostBuf; 9961706SN/A int result = statfs(path.c_str(), &hostBuf); 9971706SN/A 9981706SN/A if (result < 0) 9992218SN/A return -errno; 10001706SN/A 10018706Sandreas.hansson@arm.com OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 10021706SN/A 10031706SN/A return 0; 10041706SN/A} 10051706SN/A 10061706SN/A 10071706SN/A/// Target fstatfs() handler. 10081706SN/Atemplate <class OS> 10091706SN/ASyscallReturn 10103114Sgblack@eecs.umich.edufstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10112680Sktlim@umich.edu ThreadContext *tc) 10121706SN/A{ 10136701Sgblack@eecs.umich.edu int index = 0; 10146701Sgblack@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 10156701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 10161706SN/A 10171706SN/A if (fd < 0) 10181706SN/A return -EBADF; 10191706SN/A 10201706SN/A struct statfs hostBuf; 10211706SN/A int result = fstatfs(fd, &hostBuf); 10221706SN/A 10231706SN/A if (result < 0) 10242218SN/A return -errno; 10251706SN/A 10268706Sandreas.hansson@arm.com OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 10271706SN/A 10281706SN/A return 0; 10291706SN/A} 10301706SN/A 10311706SN/A 10321999SN/A/// Target writev() handler. 10331999SN/Atemplate <class OS> 10341999SN/ASyscallReturn 10353114Sgblack@eecs.umich.eduwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10362680Sktlim@umich.edu ThreadContext *tc) 10371999SN/A{ 10386701Sgblack@eecs.umich.edu int index = 0; 10396701Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 10401999SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 10411999SN/A // doesn't map to any simulator fd: not a valid target fd 10421999SN/A return -EBADF; 10431999SN/A } 10441999SN/A 10458852Sandreas.hansson@arm.com SETranslatingPortProxy &p = tc->getMemProxy(); 10466701Sgblack@eecs.umich.edu uint64_t tiov_base = process->getSyscallArg(tc, index); 10476701Sgblack@eecs.umich.edu size_t count = process->getSyscallArg(tc, index); 10481999SN/A struct iovec hiov[count]; 10496227Snate@binkert.org for (size_t i = 0; i < count; ++i) { 10501999SN/A typename OS::tgt_iovec tiov; 10512461SN/A 10528852Sandreas.hansson@arm.com p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 10538852Sandreas.hansson@arm.com (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 10548737Skoansin.tan@gmail.com hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 10551999SN/A hiov[i].iov_base = new char [hiov[i].iov_len]; 10568852Sandreas.hansson@arm.com p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 10578852Sandreas.hansson@arm.com hiov[i].iov_len); 10581999SN/A } 10591999SN/A 10601999SN/A int result = writev(process->sim_fd(fd), hiov, count); 10611999SN/A 10626227Snate@binkert.org for (size_t i = 0; i < count; ++i) 10631999SN/A delete [] (char *)hiov[i].iov_base; 10641999SN/A 10651999SN/A if (result < 0) 10662218SN/A return -errno; 10671999SN/A 10681999SN/A return 0; 10691999SN/A} 10701999SN/A 10711999SN/A 1072378SN/A/// Target mmap() handler. 1073378SN/A/// 1074378SN/A/// We don't really handle mmap(). If the target is mmaping an 1075378SN/A/// anonymous region or /dev/zero, we can get away with doing basically 1076378SN/A/// nothing (since memory is initialized to zero and the simulator 10778324Ssteve.reinhardt@amd.com/// doesn't really check addresses anyway). 10788324Ssteve.reinhardt@amd.com/// 1079360SN/Atemplate <class OS> 10801450SN/ASyscallReturn 10813114Sgblack@eecs.umich.edummapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1082360SN/A{ 10836701Sgblack@eecs.umich.edu int index = 0; 10846701Sgblack@eecs.umich.edu Addr start = p->getSyscallArg(tc, index); 10856701Sgblack@eecs.umich.edu uint64_t length = p->getSyscallArg(tc, index); 10866701Sgblack@eecs.umich.edu index++; // int prot = p->getSyscallArg(tc, index); 10876701Sgblack@eecs.umich.edu int flags = p->getSyscallArg(tc, index); 10888324Ssteve.reinhardt@amd.com int tgt_fd = p->getSyscallArg(tc, index); 10896701Sgblack@eecs.umich.edu // int offset = p->getSyscallArg(tc, index); 1090360SN/A 10919008Sgblack@eecs.umich.edu if (length > 0x100000000ULL) 10929008Sgblack@eecs.umich.edu warn("mmap length argument %#x is unreasonably large.\n", length); 10939008Sgblack@eecs.umich.edu 10948324Ssteve.reinhardt@amd.com if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 10958324Ssteve.reinhardt@amd.com Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 10968324Ssteve.reinhardt@amd.com if (!fd_map || fd_map->fd < 0) { 10978324Ssteve.reinhardt@amd.com warn("mmap failing: target fd %d is not valid\n", tgt_fd); 10988324Ssteve.reinhardt@amd.com return -EBADF; 10998324Ssteve.reinhardt@amd.com } 11008324Ssteve.reinhardt@amd.com 11018324Ssteve.reinhardt@amd.com if (fd_map->filename != "/dev/zero") { 11028324Ssteve.reinhardt@amd.com // This is very likely broken, but leave a warning here 11038324Ssteve.reinhardt@amd.com // (rather than panic) in case /dev/zero is known by 11048324Ssteve.reinhardt@amd.com // another name on some platform 11058324Ssteve.reinhardt@amd.com warn("allowing mmap of file %s; mmap not supported on files" 11068324Ssteve.reinhardt@amd.com " other than /dev/zero\n", fd_map->filename); 11078324Ssteve.reinhardt@amd.com } 11088324Ssteve.reinhardt@amd.com } 11095877Shsul@eecs.umich.edu 11102544SN/A if ((start % TheISA::VMPageSize) != 0 || 11112544SN/A (length % TheISA::VMPageSize) != 0) { 11122544SN/A warn("mmap failing: arguments not page-aligned: " 11132544SN/A "start 0x%x length 0x%x", 11142544SN/A start, length); 11152544SN/A return -EINVAL; 1116360SN/A } 1117360SN/A 11188600Ssteve.reinhardt@amd.com // are we ok with clobbering existing mappings? only set this to 11198600Ssteve.reinhardt@amd.com // true if the user has been warned. 11208600Ssteve.reinhardt@amd.com bool clobber = false; 11218600Ssteve.reinhardt@amd.com 11228600Ssteve.reinhardt@amd.com // try to use the caller-provided address if there is one 11238600Ssteve.reinhardt@amd.com bool use_provided_address = (start != 0); 11248600Ssteve.reinhardt@amd.com 11258600Ssteve.reinhardt@amd.com if (use_provided_address) { 11268600Ssteve.reinhardt@amd.com // check to see if the desired address is already in use 11278600Ssteve.reinhardt@amd.com if (!p->pTable->isUnmapped(start, length)) { 11288600Ssteve.reinhardt@amd.com // there are existing mappings in the desired range 11298600Ssteve.reinhardt@amd.com // whether we clobber them or not depends on whether the caller 11308600Ssteve.reinhardt@amd.com // specified MAP_FIXED 11318600Ssteve.reinhardt@amd.com if (flags & OS::TGT_MAP_FIXED) { 11328600Ssteve.reinhardt@amd.com // MAP_FIXED specified: clobber existing mappings 11338600Ssteve.reinhardt@amd.com warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 11348600Ssteve.reinhardt@amd.com start); 11358600Ssteve.reinhardt@amd.com clobber = true; 11368600Ssteve.reinhardt@amd.com } else { 11378600Ssteve.reinhardt@amd.com // MAP_FIXED not specified: ignore suggested start address 11388600Ssteve.reinhardt@amd.com warn("mmap: ignoring suggested map address 0x%x\n", start); 11398600Ssteve.reinhardt@amd.com use_provided_address = false; 11408600Ssteve.reinhardt@amd.com } 11418600Ssteve.reinhardt@amd.com } 11422544SN/A } 11432544SN/A 11448600Ssteve.reinhardt@amd.com if (!use_provided_address) { 11458600Ssteve.reinhardt@amd.com // no address provided, or provided address unusable: 11468600Ssteve.reinhardt@amd.com // pick next address from our "mmap region" 11478600Ssteve.reinhardt@amd.com if (OS::mmapGrowsDown()) { 11488600Ssteve.reinhardt@amd.com start = p->mmap_end - length; 11498600Ssteve.reinhardt@amd.com p->mmap_end = start; 11508600Ssteve.reinhardt@amd.com } else { 11518600Ssteve.reinhardt@amd.com start = p->mmap_end; 11528600Ssteve.reinhardt@amd.com p->mmap_end += length; 11538600Ssteve.reinhardt@amd.com } 11546672Sgblack@eecs.umich.edu } 11558600Ssteve.reinhardt@amd.com 11568601Ssteve.reinhardt@amd.com p->allocateMem(start, length, clobber); 11572544SN/A 11581458SN/A return start; 1159360SN/A} 1160360SN/A 1161378SN/A/// Target getrlimit() handler. 1162360SN/Atemplate <class OS> 11631450SN/ASyscallReturn 11643114Sgblack@eecs.umich.edugetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11652680Sktlim@umich.edu ThreadContext *tc) 1166360SN/A{ 11676701Sgblack@eecs.umich.edu int index = 0; 11686701Sgblack@eecs.umich.edu unsigned resource = process->getSyscallArg(tc, index); 11696701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1170360SN/A 1171360SN/A switch (resource) { 11722064SN/A case OS::TGT_RLIMIT_STACK: 11735877Shsul@eecs.umich.edu // max stack size in bytes: make up a number (8MB for now) 11742064SN/A rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 11758737Skoansin.tan@gmail.com rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11768737Skoansin.tan@gmail.com rlp->rlim_max = TheISA::htog(rlp->rlim_max); 11772064SN/A break; 1178360SN/A 11795877Shsul@eecs.umich.edu case OS::TGT_RLIMIT_DATA: 11805877Shsul@eecs.umich.edu // max data segment size in bytes: make up a number 11815877Shsul@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 11828737Skoansin.tan@gmail.com rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11838737Skoansin.tan@gmail.com rlp->rlim_max = TheISA::htog(rlp->rlim_max); 11845877Shsul@eecs.umich.edu break; 11855877Shsul@eecs.umich.edu 11862064SN/A default: 11872064SN/A std::cerr << "getrlimitFunc: unimplemented resource " << resource 11882064SN/A << std::endl; 11892064SN/A abort(); 11902064SN/A break; 1191360SN/A } 1192360SN/A 11938706Sandreas.hansson@arm.com rlp.copyOut(tc->getMemProxy()); 11941458SN/A return 0; 1195360SN/A} 1196360SN/A 1197378SN/A/// Target gettimeofday() handler. 1198360SN/Atemplate <class OS> 11991450SN/ASyscallReturn 12003114Sgblack@eecs.umich.edugettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12012680Sktlim@umich.edu ThreadContext *tc) 1202360SN/A{ 12036701Sgblack@eecs.umich.edu int index = 0; 12046701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1205360SN/A 1206360SN/A getElapsedTime(tp->tv_sec, tp->tv_usec); 1207360SN/A tp->tv_sec += seconds_since_epoch; 12086109Ssanchezd@stanford.edu tp->tv_sec = TheISA::htog(tp->tv_sec); 12096109Ssanchezd@stanford.edu tp->tv_usec = TheISA::htog(tp->tv_usec); 1210360SN/A 12118706Sandreas.hansson@arm.com tp.copyOut(tc->getMemProxy()); 1212360SN/A 12131458SN/A return 0; 1214360SN/A} 1215360SN/A 1216360SN/A 12171999SN/A/// Target utimes() handler. 12181999SN/Atemplate <class OS> 12191999SN/ASyscallReturn 12203114Sgblack@eecs.umich.eduutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12212680Sktlim@umich.edu ThreadContext *tc) 12221999SN/A{ 12231999SN/A std::string path; 12241999SN/A 12256701Sgblack@eecs.umich.edu int index = 0; 12268852Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, 12276701Sgblack@eecs.umich.edu process->getSyscallArg(tc, index))) { 12286701Sgblack@eecs.umich.edu return -EFAULT; 12296701Sgblack@eecs.umich.edu } 12301999SN/A 12316701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::timeval [2]> 12326701Sgblack@eecs.umich.edu tp(process->getSyscallArg(tc, index)); 12338706Sandreas.hansson@arm.com tp.copyIn(tc->getMemProxy()); 12341999SN/A 12351999SN/A struct timeval hostTimeval[2]; 12361999SN/A for (int i = 0; i < 2; ++i) 12371999SN/A { 12388737Skoansin.tan@gmail.com hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 12398737Skoansin.tan@gmail.com hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 12401999SN/A } 12413669Sbinkertn@umich.edu 12423669Sbinkertn@umich.edu // Adjust path for current working directory 12433669Sbinkertn@umich.edu path = process->fullPath(path); 12443669Sbinkertn@umich.edu 12451999SN/A int result = utimes(path.c_str(), hostTimeval); 12461999SN/A 12471999SN/A if (result < 0) 12481999SN/A return -errno; 12491999SN/A 12501999SN/A return 0; 12511999SN/A} 1252378SN/A/// Target getrusage() function. 1253360SN/Atemplate <class OS> 12541450SN/ASyscallReturn 12553114Sgblack@eecs.umich.edugetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12562680Sktlim@umich.edu ThreadContext *tc) 1257360SN/A{ 12586701Sgblack@eecs.umich.edu int index = 0; 12596701Sgblack@eecs.umich.edu int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 12606701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1261360SN/A 12623670Sbinkertn@umich.edu rup->ru_utime.tv_sec = 0; 12633670Sbinkertn@umich.edu rup->ru_utime.tv_usec = 0; 1264360SN/A rup->ru_stime.tv_sec = 0; 1265360SN/A rup->ru_stime.tv_usec = 0; 1266360SN/A rup->ru_maxrss = 0; 1267360SN/A rup->ru_ixrss = 0; 1268360SN/A rup->ru_idrss = 0; 1269360SN/A rup->ru_isrss = 0; 1270360SN/A rup->ru_minflt = 0; 1271360SN/A rup->ru_majflt = 0; 1272360SN/A rup->ru_nswap = 0; 1273360SN/A rup->ru_inblock = 0; 1274360SN/A rup->ru_oublock = 0; 1275360SN/A rup->ru_msgsnd = 0; 1276360SN/A rup->ru_msgrcv = 0; 1277360SN/A rup->ru_nsignals = 0; 1278360SN/A rup->ru_nvcsw = 0; 1279360SN/A rup->ru_nivcsw = 0; 1280360SN/A 12813670Sbinkertn@umich.edu switch (who) { 12823670Sbinkertn@umich.edu case OS::TGT_RUSAGE_SELF: 12833670Sbinkertn@umich.edu getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 12848737Skoansin.tan@gmail.com rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 12858737Skoansin.tan@gmail.com rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 12863670Sbinkertn@umich.edu break; 12873670Sbinkertn@umich.edu 12883670Sbinkertn@umich.edu case OS::TGT_RUSAGE_CHILDREN: 12893670Sbinkertn@umich.edu // do nothing. We have no child processes, so they take no time. 12903670Sbinkertn@umich.edu break; 12913670Sbinkertn@umich.edu 12923670Sbinkertn@umich.edu default: 12933670Sbinkertn@umich.edu // don't really handle THREAD or CHILDREN, but just warn and 12943670Sbinkertn@umich.edu // plow ahead 12953670Sbinkertn@umich.edu warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 12963670Sbinkertn@umich.edu who); 12973670Sbinkertn@umich.edu } 12983670Sbinkertn@umich.edu 12998706Sandreas.hansson@arm.com rup.copyOut(tc->getMemProxy()); 1300360SN/A 13011458SN/A return 0; 1302360SN/A} 1303360SN/A 13046683Stjones1@inf.ed.ac.uk/// Target times() function. 13056683Stjones1@inf.ed.ac.uktemplate <class OS> 13066683Stjones1@inf.ed.ac.ukSyscallReturn 13076683Stjones1@inf.ed.ac.uktimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 13086683Stjones1@inf.ed.ac.uk ThreadContext *tc) 13096683Stjones1@inf.ed.ac.uk{ 13106701Sgblack@eecs.umich.edu int index = 0; 13116701Sgblack@eecs.umich.edu TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 13126683Stjones1@inf.ed.ac.uk 13136683Stjones1@inf.ed.ac.uk // Fill in the time structure (in clocks) 13147823Ssteve.reinhardt@amd.com int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 13156683Stjones1@inf.ed.ac.uk bufp->tms_utime = clocks; 13166683Stjones1@inf.ed.ac.uk bufp->tms_stime = 0; 13176683Stjones1@inf.ed.ac.uk bufp->tms_cutime = 0; 13186683Stjones1@inf.ed.ac.uk bufp->tms_cstime = 0; 13196683Stjones1@inf.ed.ac.uk 13206683Stjones1@inf.ed.ac.uk // Convert to host endianness 13218737Skoansin.tan@gmail.com bufp->tms_utime = TheISA::htog(bufp->tms_utime); 13226683Stjones1@inf.ed.ac.uk 13236683Stjones1@inf.ed.ac.uk // Write back 13248706Sandreas.hansson@arm.com bufp.copyOut(tc->getMemProxy()); 13256683Stjones1@inf.ed.ac.uk 13266683Stjones1@inf.ed.ac.uk // Return clock ticks since system boot 13276683Stjones1@inf.ed.ac.uk return clocks; 13286683Stjones1@inf.ed.ac.uk} 13292553SN/A 13306684Stjones1@inf.ed.ac.uk/// Target time() function. 13316684Stjones1@inf.ed.ac.uktemplate <class OS> 13326684Stjones1@inf.ed.ac.ukSyscallReturn 13336684Stjones1@inf.ed.ac.uktimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 13346684Stjones1@inf.ed.ac.uk ThreadContext *tc) 13356684Stjones1@inf.ed.ac.uk{ 13366684Stjones1@inf.ed.ac.uk typename OS::time_t sec, usec; 13376684Stjones1@inf.ed.ac.uk getElapsedTime(sec, usec); 13386684Stjones1@inf.ed.ac.uk sec += seconds_since_epoch; 13396684Stjones1@inf.ed.ac.uk 13406701Sgblack@eecs.umich.edu int index = 0; 13416701Sgblack@eecs.umich.edu Addr taddr = (Addr)process->getSyscallArg(tc, index); 13426684Stjones1@inf.ed.ac.uk if(taddr != 0) { 13436684Stjones1@inf.ed.ac.uk typename OS::time_t t = sec; 13448737Skoansin.tan@gmail.com t = TheISA::htog(t); 13458852Sandreas.hansson@arm.com SETranslatingPortProxy &p = tc->getMemProxy(); 13468852Sandreas.hansson@arm.com p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 13476684Stjones1@inf.ed.ac.uk } 13486684Stjones1@inf.ed.ac.uk return sec; 13496684Stjones1@inf.ed.ac.uk} 13502553SN/A 13512553SN/A 13521354SN/A#endif // __SIM_SYSCALL_EMUL_HH__ 1353