syscall_emul.hh revision 9141
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 310796Sbrandon.potter@amd.com * All rights reserved. 410027SChris.Adeniyi-Jones@arm.com * 510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without 610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are 710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright 810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer; 910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright 1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the 1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution; 1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its 1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from 1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission. 151458SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27360SN/A * 28360SN/A * Authors: Steve Reinhardt 29360SN/A * Kevin Lim 30360SN/A */ 31360SN/A 32360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__ 33360SN/A#define __SIM_SYSCALL_EMUL_HH__ 34360SN/A 35360SN/A#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 36360SN/A defined(__FreeBSD__) || defined(__CYGWIN__)) 37360SN/A 38360SN/A/// 39360SN/A/// @file syscall_emul.hh 402665Ssaidi@eecs.umich.edu/// 412665Ssaidi@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target 422665Ssaidi@eecs.umich.edu/// application on the host machine. 43360SN/A 44360SN/A#ifdef __CYGWIN32__ 451354SN/A#include <sys/fcntl.h> // for O_BINARY 461354SN/A#endif 47360SN/A#include <sys/stat.h> 482764Sstever@eecs.umich.edu#include <sys/time.h> 499202Spalle@lyckegaard.dk#include <sys/uio.h> 509202Spalle@lyckegaard.dk#include <fcntl.h> 512064SN/A 52360SN/A#include <cerrno> 53360SN/A#include <string> 54360SN/A 55360SN/A#include "base/chunk_generator.hh" 56360SN/A#include "base/intmath.hh" // for RoundUp 57360SN/A#include "base/misc.hh" 581809SN/A#include "base/trace.hh" 595543Ssaidi@eecs.umich.edu#include "base/types.hh" 6011392Sbrandon.potter@amd.com#include "config/the_isa.hh" 611809SN/A#include "cpu/base.hh" 6211392Sbrandon.potter@amd.com#include "cpu/thread_context.hh" 6311383Sbrandon.potter@amd.com#include "debug/SyscallVerbose.hh" 643113Sgblack@eecs.umich.edu#include "mem/page_table.hh" 658229Snate@binkert.org#include "mem/se_translating_port_proxy.hh" 668229Snate@binkert.org#include "sim/byteswap.hh" 677075Snate@binkert.org#include "sim/process.hh" 688229Snate@binkert.org#include "sim/syscallreturn.hh" 697075Snate@binkert.org#include "sim/system.hh" 70360SN/A 712474SN/A/// 725543Ssaidi@eecs.umich.edu/// System call descriptor. 7311392Sbrandon.potter@amd.com/// 742462SN/Aclass SyscallDesc { 751354SN/A 766216Snate@binkert.org public: 776658Snate@binkert.org 782474SN/A /// Typedef for target syscall handler functions. 792680Sktlim@umich.edu typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 8011380Salexandru.dutu@amd.com LiveProcess *, ThreadContext *); 818232Snate@binkert.org 828229Snate@binkert.org const char *name; //!< Syscall name (e.g., "open"). 837678Sgblack@eecs.umich.edu FuncPtr funcPtr; //!< Pointer to emulation function. 8410496Ssteve.reinhardt@amd.com int flags; //!< Flags (see Flags enum). 858229Snate@binkert.org 8610497Ssteve.reinhardt@amd.com /// Flag values for controlling syscall behavior. 878766Sgblack@eecs.umich.edu enum Flags { 886640Svince@csl.cornell.edu /// Don't set return regs according to funcPtr return value. 89360SN/A /// Used for syscalls with non-standard return conventions 9011380Salexandru.dutu@amd.com /// that explicitly set the ThreadContext regs (e.g., 9111380Salexandru.dutu@amd.com /// sigreturn). 9211380Salexandru.dutu@amd.com SuppressReturnValue = 1 9311380Salexandru.dutu@amd.com }; 9411380Salexandru.dutu@amd.com 9511380Salexandru.dutu@amd.com /// Constructor. 9611380Salexandru.dutu@amd.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 9711380Salexandru.dutu@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 98360SN/A { 99360SN/A } 100360SN/A 101360SN/A /// Emulate the syscall. Public interface for calling through funcPtr. 102360SN/A void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 103360SN/A}; 104360SN/A 105378SN/A 1061450SN/Aclass BaseBufferArg { 1073114Sgblack@eecs.umich.edu 108360SN/A public: 1095543Ssaidi@eecs.umich.edu 1105543Ssaidi@eecs.umich.edu BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 1115543Ssaidi@eecs.umich.edu { 11210831Ssteve.reinhardt@amd.com bufPtr = new uint8_t[size]; 113360SN/A // clear out buffer: in case we only partially populate this, 114360SN/A // and then do a copyOut(), we want to make sure we don't 115360SN/A // introduce any random junk into the simulated address space 116360SN/A memset(bufPtr, 0, size); 117360SN/A } 1182680Sktlim@umich.edu 119360SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 12010831Ssteve.reinhardt@amd.com 12110831Ssteve.reinhardt@amd.com // 122360SN/A // copy data into simulator space (read from target memory) 123360SN/A // 124360SN/A virtual bool copyIn(SETranslatingPortProxy &memproxy) 125360SN/A { 12610831Ssteve.reinhardt@amd.com memproxy.readBlob(addr, bufPtr, size); 127360SN/A return true; // no EFAULT detection for now 128360SN/A } 129360SN/A 130360SN/A // 1313114Sgblack@eecs.umich.edu // copy data out of simulator space (write to target memory) 13210831Ssteve.reinhardt@amd.com // 13310831Ssteve.reinhardt@amd.com virtual bool copyOut(SETranslatingPortProxy &memproxy) 13410831Ssteve.reinhardt@amd.com { 135360SN/A memproxy.writeBlob(addr, bufPtr, size); 136360SN/A return true; // no EFAULT detection for now 137360SN/A } 138360SN/A 139360SN/A protected: 140360SN/A Addr addr; 141360SN/A int size; 142360SN/A uint8_t *bufPtr; 143360SN/A}; 144360SN/A 145360SN/A 146360SN/Aclass BufferArg : public BaseBufferArg 147378SN/A{ 1481706SN/A public: 1493114Sgblack@eecs.umich.edu BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 150378SN/A void *bufferPtr() { return bufPtr; } 151378SN/A}; 152378SN/A 153378SN/Atemplate <class T> 154378SN/Aclass TypedBufferArg : public BaseBufferArg 1551706SN/A{ 1563114Sgblack@eecs.umich.edu public: 157360SN/A // user can optionally specify a specific number of bytes to 1586109Ssanchezd@stanford.edu // allocate to deal with those structs that have variable-size 1591706SN/A // arrays at the end 1603114Sgblack@eecs.umich.edu TypedBufferArg(Addr _addr, int _size = sizeof(T)) 161378SN/A : BaseBufferArg(_addr, _size) 1626109Ssanchezd@stanford.edu { } 1636109Ssanchezd@stanford.edu 1646109Ssanchezd@stanford.edu // type case 1656109Ssanchezd@stanford.edu operator T*() { return (T *)bufPtr; } 166378SN/A 1671706SN/A // dereference operators 1683114Sgblack@eecs.umich.edu T &operator*() { return *((T *)bufPtr); } 169378SN/A T* operator->() { return (T *)bufPtr; } 1705748SSteve.Reinhardt@amd.com T &operator[](int i) { return ((T *)bufPtr)[i]; } 1715748SSteve.Reinhardt@amd.com}; 1725748SSteve.Reinhardt@amd.com 173378SN/A////////////////////////////////////////////////////////////////////// 174378SN/A// 1751706SN/A// The following emulation functions are generic enough that they 1763114Sgblack@eecs.umich.edu// don't need to be recompiled for different emulated OS's. They are 177378SN/A// defined in sim/syscall_emul.cc. 178378SN/A// 1791706SN/A////////////////////////////////////////////////////////////////////// 1803114Sgblack@eecs.umich.edu 181378SN/A 182378SN/A/// Handler for unimplemented syscalls that we haven't thought about. 1831706SN/ASyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1843114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 185378SN/A 186378SN/A/// Handler for unimplemented syscalls that we never intend to 1871706SN/A/// implement (signal handling, etc.) and should not affect the correct 1883114Sgblack@eecs.umich.edu/// behavior of the program. Print a warning only if the appropriate 189378SN/A/// trace flag is enabled. Return success to the target program. 1904118Sgblack@eecs.umich.eduSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1914118Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1924118Sgblack@eecs.umich.eduSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 1934118Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 194378SN/A 1951706SN/A/// Target exit() handler: terminate current context. 1963114Sgblack@eecs.umich.eduSyscallReturn exitFunc(SyscallDesc *desc, int num, 197378SN/A LiveProcess *p, ThreadContext *tc); 198378SN/A 1991706SN/A/// Target exit_group() handler: terminate simulation. (exit all threads) 2003114Sgblack@eecs.umich.eduSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 201360SN/A LiveProcess *p, ThreadContext *tc); 2025513SMichael.Adler@intel.com 2035513SMichael.Adler@intel.com/// Target getpagesize() handler. 2045513SMichael.Adler@intel.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 2055513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 20610203SAli.Saidi@ARM.com 20710203SAli.Saidi@ARM.com/// Target brk() handler: set brk address. 20810203SAli.Saidi@ARM.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 20910203SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 2105513SMichael.Adler@intel.com 2115513SMichael.Adler@intel.com/// Target close() handler. 2125513SMichael.Adler@intel.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 213511SN/A LiveProcess *p, ThreadContext *tc); 21410633Smichaelupton@gmail.com 21510633Smichaelupton@gmail.com/// Target read() handler. 21610633Smichaelupton@gmail.comSyscallReturn readFunc(SyscallDesc *desc, int num, 2171706SN/A LiveProcess *p, ThreadContext *tc); 2183114Sgblack@eecs.umich.edu 219511SN/A/// Target write() handler. 2205513SMichael.Adler@intel.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 2215513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2225513SMichael.Adler@intel.com 2235513SMichael.Adler@intel.com/// Target lseek() handler. 224511SN/ASyscallReturn lseekFunc(SyscallDesc *desc, int num, 2251706SN/A LiveProcess *p, ThreadContext *tc); 2263114Sgblack@eecs.umich.edu 2271706SN/A/// Target _llseek() handler. 2281706SN/ASyscallReturn _llseekFunc(SyscallDesc *desc, int num, 2291706SN/A LiveProcess *p, ThreadContext *tc); 2301706SN/A 2313114Sgblack@eecs.umich.edu/// Target munmap() handler. 2321706SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num, 2331706SN/A LiveProcess *p, ThreadContext *tc); 2341706SN/A 2351706SN/A/// Target gethostname() handler. 2363114Sgblack@eecs.umich.eduSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2371706SN/A LiveProcess *p, ThreadContext *tc); 238511SN/A 2396703Svince@csl.cornell.edu/// Target getcwd() handler. 2406703Svince@csl.cornell.eduSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2416703Svince@csl.cornell.edu LiveProcess *p, ThreadContext *tc); 2426703Svince@csl.cornell.edu 2436685Stjones1@inf.ed.ac.uk/// Target unlink() handler. 2446685Stjones1@inf.ed.ac.ukSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2456685Stjones1@inf.ed.ac.uk LiveProcess *p, ThreadContext *tc); 2466685Stjones1@inf.ed.ac.uk 2476685Stjones1@inf.ed.ac.uk/// Target unlink() handler. 2485513SMichael.Adler@intel.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2495513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 2505513SMichael.Adler@intel.com 2515513SMichael.Adler@intel.com/// Target mkdir() handler. 2525513SMichael.Adler@intel.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2531999SN/A LiveProcess *p, ThreadContext *tc); 2541999SN/A 2553114Sgblack@eecs.umich.edu/// Target rename() handler. 2561999SN/ASyscallReturn renameFunc(SyscallDesc *desc, int num, 2571999SN/A LiveProcess *p, ThreadContext *tc); 2581999SN/A 2591999SN/A 2603114Sgblack@eecs.umich.edu/// Target truncate() handler. 2611999SN/ASyscallReturn truncateFunc(SyscallDesc *desc, int num, 2623079Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2633079Sstever@eecs.umich.edu 2643114Sgblack@eecs.umich.edu 2653079Sstever@eecs.umich.edu/// Target ftruncate() handler. 2662093SN/ASyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2672093SN/A LiveProcess *p, ThreadContext *tc); 2683114Sgblack@eecs.umich.edu 2692093SN/A 2702687Sksewell@umich.edu/// Target truncate64() handler. 2712687Sksewell@umich.eduSyscallReturn truncate64Func(SyscallDesc *desc, int num, 2723114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2732687Sksewell@umich.edu 2742238SN/A/// Target ftruncate64() handler. 2752238SN/ASyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2763114Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2772238SN/A 2782238SN/A 2792238SN/A/// Target umask() handler. 2803114Sgblack@eecs.umich.eduSyscallReturn umaskFunc(SyscallDesc *desc, int num, 2812238SN/A LiveProcess *p, ThreadContext *tc); 2822238SN/A 2832238SN/A 2843114Sgblack@eecs.umich.edu/// Target chown() handler. 2852238SN/ASyscallReturn chownFunc(SyscallDesc *desc, int num, 2862238SN/A LiveProcess *p, ThreadContext *tc); 2872238SN/A 2883114Sgblack@eecs.umich.edu 2892238SN/A/// Target fchown() handler. 2902238SN/ASyscallReturn fchownFunc(SyscallDesc *desc, int num, 2912238SN/A LiveProcess *p, ThreadContext *tc); 2923114Sgblack@eecs.umich.edu 2932238SN/A/// Target dup() handler. 2942238SN/ASyscallReturn dupFunc(SyscallDesc *desc, int num, 2952238SN/A LiveProcess *process, ThreadContext *tc); 2963114Sgblack@eecs.umich.edu 2972238SN/A/// Target fnctl() handler. 2982238SN/ASyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2992238SN/A LiveProcess *process, ThreadContext *tc); 3003114Sgblack@eecs.umich.edu 3012238SN/A/// Target fcntl64() handler. 3026109Ssanchezd@stanford.eduSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 3036109Ssanchezd@stanford.edu LiveProcess *process, ThreadContext *tc); 3046109Ssanchezd@stanford.edu 3052238SN/A/// Target setuid() handler. 3069455Smitch.hayenga+gem5@gmail.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 3079455Smitch.hayenga+gem5@gmail.com LiveProcess *p, ThreadContext *tc); 3089455Smitch.hayenga+gem5@gmail.com 30910203SAli.Saidi@ARM.com/// Target getpid() handler. 31010203SAli.Saidi@ARM.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 31110203SAli.Saidi@ARM.com LiveProcess *p, ThreadContext *tc); 3129455Smitch.hayenga+gem5@gmail.com 3139112Smarc.orr@gmail.com/// Target getuid() handler. 3149112Smarc.orr@gmail.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 3159112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3169112Smarc.orr@gmail.com 3179112Smarc.orr@gmail.com/// Target getgid() handler. 3189112Smarc.orr@gmail.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 3199112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3209112Smarc.orr@gmail.com 3219112Smarc.orr@gmail.com/// Target getppid() handler. 3229112Smarc.orr@gmail.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 3239112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3249112Smarc.orr@gmail.com 3259112Smarc.orr@gmail.com/// Target geteuid() handler. 3269112Smarc.orr@gmail.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 3279112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3289112Smarc.orr@gmail.com 3299112Smarc.orr@gmail.com/// Target getegid() handler. 3309112Smarc.orr@gmail.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 3319112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3329112Smarc.orr@gmail.com 3339112Smarc.orr@gmail.com/// Target clone() handler. 3349112Smarc.orr@gmail.comSyscallReturn cloneFunc(SyscallDesc *desc, int num, 3359112Smarc.orr@gmail.com LiveProcess *p, ThreadContext *tc); 3369112Smarc.orr@gmail.com 3379238Slluc.alvarez@bsc.es/// Futex system call 3389112Smarc.orr@gmail.com/// Implemented by Daniel Sanchez 3399112Smarc.orr@gmail.com/// Used by printf's in multi-threaded apps 3409112Smarc.orr@gmail.comtemplate <class OS> 3419112Smarc.orr@gmail.comSyscallReturn 3429112Smarc.orr@gmail.comfutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3439112Smarc.orr@gmail.com ThreadContext *tc) 3449112Smarc.orr@gmail.com{ 3459112Smarc.orr@gmail.com int index_uaddr = 0; 3469112Smarc.orr@gmail.com int index_op = 1; 3479112Smarc.orr@gmail.com int index_val = 2; 34811367Sandreas.hansson@arm.com int index_timeout = 3; 3499112Smarc.orr@gmail.com 35011321Ssteve.reinhardt@amd.com uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3519112Smarc.orr@gmail.com int op = process->getSyscallArg(tc, index_op); 3529112Smarc.orr@gmail.com int val = process->getSyscallArg(tc, index_val); 3539112Smarc.orr@gmail.com uint64_t timeout = process->getSyscallArg(tc, index_timeout); 3549112Smarc.orr@gmail.com 3559112Smarc.orr@gmail.com std::map<uint64_t, std::list<ThreadContext *> * > 3569112Smarc.orr@gmail.com &futex_map = tc->getSystemPtr()->futexMap; 3579112Smarc.orr@gmail.com 3589112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 3599112Smarc.orr@gmail.com uaddr, op, val); 3609112Smarc.orr@gmail.com 3619112Smarc.orr@gmail.com 3629112Smarc.orr@gmail.com if (op == OS::TGT_FUTEX_WAIT) { 3639112Smarc.orr@gmail.com if (timeout != 0) { 3649112Smarc.orr@gmail.com warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 3659112Smarc.orr@gmail.com "we'll wait indefinitely"); 3669112Smarc.orr@gmail.com } 3679112Smarc.orr@gmail.com 3689112Smarc.orr@gmail.com uint8_t *buf = new uint8_t[sizeof(int)]; 3699112Smarc.orr@gmail.com tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3709112Smarc.orr@gmail.com int mem_val = *((int *)buf); 3719112Smarc.orr@gmail.com delete buf; 3729112Smarc.orr@gmail.com 3739112Smarc.orr@gmail.com if(val != mem_val) { 3749112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 3759112Smarc.orr@gmail.com "expected: %d\n", mem_val, val); 3769112Smarc.orr@gmail.com return -OS::TGT_EWOULDBLOCK; 3779112Smarc.orr@gmail.com } 3789112Smarc.orr@gmail.com 3799112Smarc.orr@gmail.com // Queue the thread context 38011321Ssteve.reinhardt@amd.com std::list<ThreadContext *> * tcWaitList; 3819112Smarc.orr@gmail.com if (futex_map.count(uaddr)) { 3829112Smarc.orr@gmail.com tcWaitList = futex_map.find(uaddr)->second; 3839112Smarc.orr@gmail.com } else { 3849112Smarc.orr@gmail.com tcWaitList = new std::list<ThreadContext *>(); 3859112Smarc.orr@gmail.com futex_map.insert(std::pair< uint64_t, 3869112Smarc.orr@gmail.com std::list<ThreadContext *> * >(uaddr, tcWaitList)); 3879112Smarc.orr@gmail.com } 3889112Smarc.orr@gmail.com tcWaitList->push_back(tc); 3899238Slluc.alvarez@bsc.es DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 3909112Smarc.orr@gmail.com "thread context\n"); 3919112Smarc.orr@gmail.com tc->suspend(); 3929112Smarc.orr@gmail.com return 0; 3939112Smarc.orr@gmail.com } else if (op == OS::TGT_FUTEX_WAKE){ 3949112Smarc.orr@gmail.com int wokenUp = 0; 3952238SN/A std::list<ThreadContext *> * tcWaitList; 3962238SN/A if (futex_map.count(uaddr)) { 3972238SN/A tcWaitList = futex_map.find(uaddr)->second; 3982238SN/A while (tcWaitList->size() > 0 && wokenUp < val) { 3993114Sgblack@eecs.umich.edu tcWaitList->front()->activate(); 4002238SN/A tcWaitList->pop_front(); 4012238SN/A wokenUp++; 4022238SN/A } 4033114Sgblack@eecs.umich.edu if(tcWaitList->empty()) { 4042238SN/A futex_map.erase(uaddr); 4052238SN/A delete tcWaitList; 4062238SN/A } 4073114Sgblack@eecs.umich.edu } 4082238SN/A DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 4092238SN/A "thread contexts\n", wokenUp); 4102238SN/A return wokenUp; 4113114Sgblack@eecs.umich.edu } else { 4122238SN/A warn("sys_futex: op %d is not implemented, just returning..."); 4132238SN/A return 0; 4141354SN/A } 4151354SN/A 41610796Sbrandon.potter@amd.com} 41710796Sbrandon.potter@amd.com 4181354SN/A 4191354SN/A/// Pseudo Funcs - These functions use a different return convension, 4201354SN/A/// returning a second value in a register other than the normal return register 4211354SN/ASyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 4221354SN/A LiveProcess *process, ThreadContext *tc); 4231354SN/A 4241354SN/A/// Target getpidPseudo() handler. 4251354SN/ASyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 4261354SN/A LiveProcess *p, ThreadContext *tc); 4271354SN/A 42810796Sbrandon.potter@amd.com/// Target getuidPseudo() handler. 4291354SN/ASyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 43010796Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 4311354SN/A 4321354SN/A/// Target getgidPseudo() handler. 4331354SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4341354SN/A LiveProcess *p, ThreadContext *tc); 43510796Sbrandon.potter@amd.com 43610796Sbrandon.potter@amd.com 43710796Sbrandon.potter@amd.com/// A readable name for 1,000,000, for converting microseconds to seconds. 43810796Sbrandon.potter@amd.comconst int one_million = 1000000; 43910796Sbrandon.potter@amd.com 44010796Sbrandon.potter@amd.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 44110796Sbrandon.potter@amd.com/// by my reckoning. We want to keep this a constant (not use the 44210796Sbrandon.potter@amd.com/// real-world time) to keep simulations repeatable. 44310796Sbrandon.potter@amd.comconst unsigned seconds_since_epoch = 1000000000; 44410796Sbrandon.potter@amd.com 44510796Sbrandon.potter@amd.com/// Helper function to convert current elapsed time to seconds and 446360SN/A/// microseconds. 447360SN/Atemplate <class T1, class T2> 448360SN/Avoid 449360SN/AgetElapsedTime(T1 &sec, T2 &usec) 450360SN/A{ 451360SN/A int elapsed_usecs = curTick() / SimClock::Int::us; 452360SN/A sec = elapsed_usecs / one_million; 4533113Sgblack@eecs.umich.edu usec = elapsed_usecs % one_million; 4543113Sgblack@eecs.umich.edu} 4553113Sgblack@eecs.umich.edu 4563113Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4573113Sgblack@eecs.umich.edu// 4583113Sgblack@eecs.umich.edu// The following emulation functions are generic, but need to be 4593113Sgblack@eecs.umich.edu// templated to account for differences in types, constants, etc. 4603113Sgblack@eecs.umich.edu// 4613113Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4623113Sgblack@eecs.umich.edu 4633113Sgblack@eecs.umich.edu#if NO_STAT64 4643113Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4653113Sgblack@eecs.umich.edu typedef struct stat hst_stat64; 4663113Sgblack@eecs.umich.edu#else 4673113Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4683113Sgblack@eecs.umich.edu typedef struct stat64 hst_stat64; 4694189Sgblack@eecs.umich.edu#endif 4704189Sgblack@eecs.umich.edu 4713113Sgblack@eecs.umich.edu//// Helper function to convert a host stat buffer to a target stat 4723113Sgblack@eecs.umich.edu//// buffer. Also copies the target buffer out to the simulated 4733113Sgblack@eecs.umich.edu//// memory space. Used by stat(), fstat(), and lstat(). 4743113Sgblack@eecs.umich.edu 4758737Skoansin.tan@gmail.comtemplate <typename target_stat, typename host_stat> 4763113Sgblack@eecs.umich.edustatic void 4778737Skoansin.tan@gmail.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4783277Sgblack@eecs.umich.edu{ 4795515SMichael.Adler@intel.com using namespace TheISA; 4805515SMichael.Adler@intel.com 4815515SMichael.Adler@intel.com if (fakeTTY) 4825515SMichael.Adler@intel.com tgt->st_dev = 0xA; 4835515SMichael.Adler@intel.com else 4848737Skoansin.tan@gmail.com tgt->st_dev = host->st_dev; 4853277Sgblack@eecs.umich.edu tgt->st_dev = TheISA::htog(tgt->st_dev); 4868737Skoansin.tan@gmail.com tgt->st_ino = host->st_ino; 4873277Sgblack@eecs.umich.edu tgt->st_ino = TheISA::htog(tgt->st_ino); 4888737Skoansin.tan@gmail.com tgt->st_mode = host->st_mode; 4893277Sgblack@eecs.umich.edu if (fakeTTY) { 4908737Skoansin.tan@gmail.com // Claim to be a character device 4913113Sgblack@eecs.umich.edu tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4923113Sgblack@eecs.umich.edu tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4933113Sgblack@eecs.umich.edu } 4943113Sgblack@eecs.umich.edu tgt->st_mode = TheISA::htog(tgt->st_mode); 4958737Skoansin.tan@gmail.com tgt->st_nlink = host->st_nlink; 4963113Sgblack@eecs.umich.edu tgt->st_nlink = TheISA::htog(tgt->st_nlink); 4978737Skoansin.tan@gmail.com tgt->st_uid = host->st_uid; 4983114Sgblack@eecs.umich.edu tgt->st_uid = TheISA::htog(tgt->st_uid); 4998737Skoansin.tan@gmail.com tgt->st_gid = host->st_gid; 5003114Sgblack@eecs.umich.edu tgt->st_gid = TheISA::htog(tgt->st_gid); 5018737Skoansin.tan@gmail.com if (fakeTTY) 5023114Sgblack@eecs.umich.edu tgt->st_rdev = 0x880d; 5038737Skoansin.tan@gmail.com else 5044061Sgblack@eecs.umich.edu tgt->st_rdev = host->st_rdev; 5054061Sgblack@eecs.umich.edu tgt->st_rdev = TheISA::htog(tgt->st_rdev); 5064061Sgblack@eecs.umich.edu tgt->st_size = host->st_size; 5078737Skoansin.tan@gmail.com tgt->st_size = TheISA::htog(tgt->st_size); 5083113Sgblack@eecs.umich.edu tgt->st_atimeX = host->st_atime; 5098737Skoansin.tan@gmail.com tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5103113Sgblack@eecs.umich.edu tgt->st_mtimeX = host->st_mtime; 5113113Sgblack@eecs.umich.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5123113Sgblack@eecs.umich.edu tgt->st_ctimeX = host->st_ctime; 5133113Sgblack@eecs.umich.edu tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5143113Sgblack@eecs.umich.edu // Force the block size to be 8k. This helps to ensure buffered io works 5153113Sgblack@eecs.umich.edu // consistently across different hosts. 5163113Sgblack@eecs.umich.edu tgt->st_blksize = 0x2000; 5173113Sgblack@eecs.umich.edu tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5184189Sgblack@eecs.umich.edu tgt->st_blocks = host->st_blocks; 5194189Sgblack@eecs.umich.edu tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5203113Sgblack@eecs.umich.edu} 5213113Sgblack@eecs.umich.edu 5223113Sgblack@eecs.umich.edu// Same for stat64 5238737Skoansin.tan@gmail.com 5243113Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat64> 5258737Skoansin.tan@gmail.comstatic void 5263113Sgblack@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5278737Skoansin.tan@gmail.com{ 5283113Sgblack@eecs.umich.edu using namespace TheISA; 5293113Sgblack@eecs.umich.edu 5303113Sgblack@eecs.umich.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5313113Sgblack@eecs.umich.edu#if defined(STAT_HAVE_NSEC) 5323113Sgblack@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5333113Sgblack@eecs.umich.edu tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5343113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5353113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5363113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5373113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5388852Sandreas.hansson@arm.com#else 5393113Sgblack@eecs.umich.edu tgt->st_atime_nsec = 0; 5403113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = 0; 5413113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = 0; 5423113Sgblack@eecs.umich.edu#endif 5433113Sgblack@eecs.umich.edu} 5443113Sgblack@eecs.umich.edu 5453113Sgblack@eecs.umich.edu//Here are a couple convenience functions 5463113Sgblack@eecs.umich.edutemplate<class OS> 5473113Sgblack@eecs.umich.edustatic void 5483113Sgblack@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5498852Sandreas.hansson@arm.com hst_stat *host, bool fakeTTY = false) 5503113Sgblack@eecs.umich.edu{ 5513113Sgblack@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5523113Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5533113Sgblack@eecs.umich.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5546686Stjones1@inf.ed.ac.uk tgt.copyOut(mem); 5553113Sgblack@eecs.umich.edu} 5563113Sgblack@eecs.umich.edu 5573113Sgblack@eecs.umich.edutemplate<class OS> 558378SN/Astatic void 559378SN/AcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5609141Smarc.orr@gmail.com hst_stat64 *host, bool fakeTTY = false) 5619141Smarc.orr@gmail.com{ 562360SN/A typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5631450SN/A tgt_stat_buf tgt(addr); 5643114Sgblack@eecs.umich.edu convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5652680Sktlim@umich.edu tgt.copyOut(mem); 566360SN/A} 5676701Sgblack@eecs.umich.edu 56810930Sbrandon.potter@amd.com/// Target ioctl() handler. For the most part, programs call ioctl() 5696701Sgblack@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to 570360SN/A/// do line or block buffering. We always claim that output fds are 57110930Sbrandon.potter@amd.com/// not TTYs to provide repeatable results. 572360SN/Atemplate <class OS> 57310932Sbrandon.potter@amd.comSyscallReturn 57410496Ssteve.reinhardt@amd.comioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 57510930Sbrandon.potter@amd.com ThreadContext *tc) 576360SN/A{ 5771458SN/A int index = 0; 578360SN/A int fd = process->getSyscallArg(tc, index); 579360SN/A unsigned req = process->getSyscallArg(tc, index); 58010930Sbrandon.potter@amd.com 58110930Sbrandon.potter@amd.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 58210496Ssteve.reinhardt@amd.com 58310496Ssteve.reinhardt@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 5849141Smarc.orr@gmail.com // doesn't map to any simulator fd: not a valid target fd 5851458SN/A return -EBADF; 5869141Smarc.orr@gmail.com } 587360SN/A 5889141Smarc.orr@gmail.com if (OS::isTtyReq(req)) { 58910930Sbrandon.potter@amd.com return -ENOTTY; 5909141Smarc.orr@gmail.com } 591360SN/A 592360SN/A warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 593360SN/A fd, req, tc->pcState()); 59410027SChris.Adeniyi-Jones@arm.com return -ENOTTY; 5953114Sgblack@eecs.umich.edu} 59610027SChris.Adeniyi-Jones@arm.com 597360SN/A/// Target open() handler. 598360SN/Atemplate <class OS> 599360SN/ASyscallReturn 6008852Sandreas.hansson@arm.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6016701Sgblack@eecs.umich.edu ThreadContext *tc) 6021458SN/A{ 603360SN/A std::string path; 6046701Sgblack@eecs.umich.edu 6056701Sgblack@eecs.umich.edu int index = 0; 606360SN/A if (!tc->getMemProxy().tryReadString(path, 607360SN/A process->getSyscallArg(tc, index))) 608360SN/A return -EFAULT; 609360SN/A 610360SN/A if (path == "/dev/sysdev0") { 611360SN/A // This is a memory-mapped high-resolution timer device on Alpha. 612360SN/A // We don't support it, so just punt. 613360SN/A warn("Ignoring open(%s, ...)\n", path); 614360SN/A return -ENOENT; 615360SN/A } 616360SN/A 617360SN/A int tgtFlags = process->getSyscallArg(tc, index); 6181706SN/A int mode = process->getSyscallArg(tc, index); 619360SN/A int hostFlags = 0; 620360SN/A 621360SN/A // translate open flags 622360SN/A for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 623360SN/A if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 6243669Sbinkertn@umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 6253669Sbinkertn@umich.edu hostFlags |= OS::openFlagTable[i].hostFlag; 6263669Sbinkertn@umich.edu } 6271706SN/A } 6281706SN/A 62910496Ssteve.reinhardt@amd.com // any target flags left? 63010496Ssteve.reinhardt@amd.com if (tgtFlags != 0) 63110496Ssteve.reinhardt@amd.com warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 63210496Ssteve.reinhardt@amd.com 63310496Ssteve.reinhardt@amd.com#ifdef __CYGWIN32__ 63410496Ssteve.reinhardt@amd.com hostFlags |= O_BINARY; 63510496Ssteve.reinhardt@amd.com#endif 63610496Ssteve.reinhardt@amd.com 63710496Ssteve.reinhardt@amd.com // Adjust path for current working directory 63810496Ssteve.reinhardt@amd.com path = process->fullPath(path); 63910496Ssteve.reinhardt@amd.com 64010496Ssteve.reinhardt@amd.com DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 64110496Ssteve.reinhardt@amd.com 64210496Ssteve.reinhardt@amd.com int fd; 64310496Ssteve.reinhardt@amd.com if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 64410496Ssteve.reinhardt@amd.com !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 64510496Ssteve.reinhardt@amd.com // It's a proc/sys entery and requires special handling 64610496Ssteve.reinhardt@amd.com fd = OS::openSpecialFile(path, process, tc); 64710496Ssteve.reinhardt@amd.com return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 64810496Ssteve.reinhardt@amd.com } else { 6495795Ssaidi@eecs.umich.edu // open the file 6509143Ssteve.reinhardt@amd.com fd = open(path.c_str(), hostFlags, mode); 6519142Ssteve.reinhardt@amd.com return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 6529142Ssteve.reinhardt@amd.com } 6539143Ssteve.reinhardt@amd.com 6545795Ssaidi@eecs.umich.edu} 6559143Ssteve.reinhardt@amd.com 6565795Ssaidi@eecs.umich.edu/// Target sysinfo() handler. 6575795Ssaidi@eecs.umich.edutemplate <class OS> 6585795Ssaidi@eecs.umich.eduSyscallReturn 6599143Ssteve.reinhardt@amd.comsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6605795Ssaidi@eecs.umich.edu ThreadContext *tc) 661360SN/A{ 6629143Ssteve.reinhardt@amd.com 6639143Ssteve.reinhardt@amd.com int index = 0; 6649143Ssteve.reinhardt@amd.com TypedBufferArg<typename OS::tgt_sysinfo> 66510932Sbrandon.potter@amd.com sysinfo(process->getSyscallArg(tc, index)); 666360SN/A 667360SN/A sysinfo->uptime=seconds_since_epoch; 66810027SChris.Adeniyi-Jones@arm.com sysinfo->totalram=process->system->memSize(); 66910027SChris.Adeniyi-Jones@arm.com 67010027SChris.Adeniyi-Jones@arm.com sysinfo.copyOut(tc->getMemProxy()); 67110027SChris.Adeniyi-Jones@arm.com 67210027SChris.Adeniyi-Jones@arm.com return 0; 67310027SChris.Adeniyi-Jones@arm.com} 67410027SChris.Adeniyi-Jones@arm.com 67510027SChris.Adeniyi-Jones@arm.com/// Target chmod() handler. 67610027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 67710027SChris.Adeniyi-Jones@arm.comSyscallReturn 67810027SChris.Adeniyi-Jones@arm.comchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 67910027SChris.Adeniyi-Jones@arm.com ThreadContext *tc) 68010027SChris.Adeniyi-Jones@arm.com{ 68110027SChris.Adeniyi-Jones@arm.com std::string path; 68210027SChris.Adeniyi-Jones@arm.com 68310027SChris.Adeniyi-Jones@arm.com int index = 0; 68410027SChris.Adeniyi-Jones@arm.com if (!tc->getMemProxy().tryReadString(path, 68510027SChris.Adeniyi-Jones@arm.com process->getSyscallArg(tc, index))) { 68610027SChris.Adeniyi-Jones@arm.com return -EFAULT; 68710027SChris.Adeniyi-Jones@arm.com } 68810027SChris.Adeniyi-Jones@arm.com 68910027SChris.Adeniyi-Jones@arm.com uint32_t mode = process->getSyscallArg(tc, index); 69010633Smichaelupton@gmail.com mode_t hostMode = 0; 69110633Smichaelupton@gmail.com 69210633Smichaelupton@gmail.com // XXX translate mode flags via OS::something??? 69310633Smichaelupton@gmail.com hostMode = mode; 69410633Smichaelupton@gmail.com 69510633Smichaelupton@gmail.com // Adjust path for current working directory 69610633Smichaelupton@gmail.com path = process->fullPath(path); 69710633Smichaelupton@gmail.com 69810633Smichaelupton@gmail.com // do the chmod 69910633Smichaelupton@gmail.com int result = chmod(path.c_str(), hostMode); 70010633Smichaelupton@gmail.com if (result < 0) 70110633Smichaelupton@gmail.com return -errno; 70210633Smichaelupton@gmail.com 70310633Smichaelupton@gmail.com return 0; 70410203SAli.Saidi@ARM.com} 70510203SAli.Saidi@ARM.com 70610203SAli.Saidi@ARM.com 70710203SAli.Saidi@ARM.com/// Target fchmod() handler. 70810203SAli.Saidi@ARM.comtemplate <class OS> 70910203SAli.Saidi@ARM.comSyscallReturn 71010203SAli.Saidi@ARM.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 71110203SAli.Saidi@ARM.com ThreadContext *tc) 71210203SAli.Saidi@ARM.com{ 71310203SAli.Saidi@ARM.com int index = 0; 71410203SAli.Saidi@ARM.com int fd = process->getSyscallArg(tc, index); 71510203SAli.Saidi@ARM.com if (fd < 0 || process->sim_fd(fd) < 0) { 71610203SAli.Saidi@ARM.com // doesn't map to any simulator fd: not a valid target fd 71710203SAli.Saidi@ARM.com return -EBADF; 71810203SAli.Saidi@ARM.com } 71910203SAli.Saidi@ARM.com 72010203SAli.Saidi@ARM.com uint32_t mode = process->getSyscallArg(tc, index); 72110203SAli.Saidi@ARM.com mode_t hostMode = 0; 72210203SAli.Saidi@ARM.com 72310203SAli.Saidi@ARM.com // XXX translate mode flags via OS::someting??? 72410203SAli.Saidi@ARM.com hostMode = mode; 72510203SAli.Saidi@ARM.com 72610203SAli.Saidi@ARM.com // do the fchmod 72710203SAli.Saidi@ARM.com int result = fchmod(process->sim_fd(fd), hostMode); 72810203SAli.Saidi@ARM.com if (result < 0) 72910203SAli.Saidi@ARM.com return -errno; 73010850SGiacomo.Gabrielli@arm.com 73110850SGiacomo.Gabrielli@arm.com return 0; 73210850SGiacomo.Gabrielli@arm.com} 73310850SGiacomo.Gabrielli@arm.com 73410850SGiacomo.Gabrielli@arm.com/// Target mremap() handler. 73510850SGiacomo.Gabrielli@arm.comtemplate <class OS> 73610850SGiacomo.Gabrielli@arm.comSyscallReturn 73710850SGiacomo.Gabrielli@arm.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 73810850SGiacomo.Gabrielli@arm.com{ 73910850SGiacomo.Gabrielli@arm.com int index = 0; 74010850SGiacomo.Gabrielli@arm.com Addr start = process->getSyscallArg(tc, index); 74110850SGiacomo.Gabrielli@arm.com uint64_t old_length = process->getSyscallArg(tc, index); 74210850SGiacomo.Gabrielli@arm.com uint64_t new_length = process->getSyscallArg(tc, index); 74310850SGiacomo.Gabrielli@arm.com uint64_t flags = process->getSyscallArg(tc, index); 74410850SGiacomo.Gabrielli@arm.com 74510850SGiacomo.Gabrielli@arm.com if ((start % TheISA::VMPageSize != 0) || 74610850SGiacomo.Gabrielli@arm.com (new_length % TheISA::VMPageSize != 0)) { 74710850SGiacomo.Gabrielli@arm.com warn("mremap failing: arguments not page aligned"); 74810850SGiacomo.Gabrielli@arm.com return -EINVAL; 74910850SGiacomo.Gabrielli@arm.com } 75010850SGiacomo.Gabrielli@arm.com 75110850SGiacomo.Gabrielli@arm.com if (new_length > old_length) { 75210850SGiacomo.Gabrielli@arm.com if ((start + old_length) == process->mmap_end) { 75310850SGiacomo.Gabrielli@arm.com uint64_t diff = new_length - old_length; 75410850SGiacomo.Gabrielli@arm.com process->allocateMem(process->mmap_end, diff); 75510850SGiacomo.Gabrielli@arm.com process->mmap_end += diff; 75610850SGiacomo.Gabrielli@arm.com return start; 75710850SGiacomo.Gabrielli@arm.com } else { 75810850SGiacomo.Gabrielli@arm.com // sys/mman.h defined MREMAP_MAYMOVE 75910850SGiacomo.Gabrielli@arm.com if (!(flags & 1)) { 76010850SGiacomo.Gabrielli@arm.com warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 76110850SGiacomo.Gabrielli@arm.com return -ENOMEM; 76210850SGiacomo.Gabrielli@arm.com } else { 76310850SGiacomo.Gabrielli@arm.com process->pTable->remap(start, old_length, process->mmap_end); 76410850SGiacomo.Gabrielli@arm.com warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 76510850SGiacomo.Gabrielli@arm.com process->mmap_end, process->mmap_end + new_length, new_length); 7666640Svince@csl.cornell.edu start = process->mmap_end; 7676640Svince@csl.cornell.edu // add on the remaining unallocated pages 7686640Svince@csl.cornell.edu process->allocateMem(start + old_length, 7696640Svince@csl.cornell.edu new_length - old_length); 7706640Svince@csl.cornell.edu process->mmap_end += new_length; 7716640Svince@csl.cornell.edu warn("returning %08p as start\n", start); 7726640Svince@csl.cornell.edu return start; 7736701Sgblack@eecs.umich.edu } 7746701Sgblack@eecs.umich.edu } 77510793Sbrandon.potter@amd.com } else { 7766640Svince@csl.cornell.edu process->pTable->unmap(start + new_length, old_length - new_length); 7776701Sgblack@eecs.umich.edu return start; 7786701Sgblack@eecs.umich.edu } 7796640Svince@csl.cornell.edu} 7808706Sandreas.hansson@arm.com 7816640Svince@csl.cornell.edu/// Target stat() handler. 7826701Sgblack@eecs.umich.edutemplate <class OS> 7836640Svince@csl.cornell.eduSyscallReturn 784360SN/AstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7851999SN/A ThreadContext *tc) 7861999SN/A{ 7871999SN/A std::string path; 7883114Sgblack@eecs.umich.edu 7892680Sktlim@umich.edu int index = 0; 7901999SN/A if (!tc->getMemProxy().tryReadString(path, 7911999SN/A process->getSyscallArg(tc, index))) { 7921999SN/A return -EFAULT; 7936701Sgblack@eecs.umich.edu } 7948852Sandreas.hansson@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 7956701Sgblack@eecs.umich.edu 7961999SN/A // Adjust path for current working directory 7976701Sgblack@eecs.umich.edu path = process->fullPath(path); 7981999SN/A 7996701Sgblack@eecs.umich.edu struct stat hostBuf; 8001999SN/A int result = stat(path.c_str(), &hostBuf); 8011999SN/A 8021999SN/A if (result < 0) 8031999SN/A return -errno; 8041999SN/A 8053669Sbinkertn@umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 8063669Sbinkertn@umich.edu 8073669Sbinkertn@umich.edu return 0; 8081999SN/A} 8091999SN/A 8101999SN/A 8112218SN/A/// Target stat64() handler. 8121999SN/Atemplate <class OS> 8131999SN/ASyscallReturn 8141999SN/Astat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8151999SN/A ThreadContext *tc) 8161999SN/A{ 8171999SN/A std::string path; 8181999SN/A 8191999SN/A int index = 0; 8203114Sgblack@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 8212680Sktlim@umich.edu process->getSyscallArg(tc, index))) 8221999SN/A return -EFAULT; 8236701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 82410931Sbrandon.potter@amd.com 82510931Sbrandon.potter@amd.com // Adjust path for current working directory 82610931Sbrandon.potter@amd.com path = process->fullPath(path); 82710932Sbrandon.potter@amd.com 82810931Sbrandon.potter@amd.com#if NO_STAT64 8291999SN/A struct stat hostBuf; 8301999SN/A int result = stat(path.c_str(), &hostBuf); 8311999SN/A#else 8321999SN/A struct stat64 hostBuf; 8331999SN/A int result = stat64(path.c_str(), &hostBuf); 8341999SN/A#endif 8351999SN/A 8361999SN/A if (result < 0) 83710931Sbrandon.potter@amd.com return -errno; 8381999SN/A 8392218SN/A copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 8401999SN/A 8411999SN/A return 0; 8421999SN/A} 8431999SN/A 8445877Shsul@eecs.umich.edu 8455877Shsul@eecs.umich.edu/// Target fstat64() handler. 8465877Shsul@eecs.umich.edutemplate <class OS> 8475877Shsul@eecs.umich.eduSyscallReturn 8485877Shsul@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8496701Sgblack@eecs.umich.edu ThreadContext *tc) 8506701Sgblack@eecs.umich.edu{ 8516701Sgblack@eecs.umich.edu int index = 0; 8526701Sgblack@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 8536701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 85410027SChris.Adeniyi-Jones@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 85510027SChris.Adeniyi-Jones@arm.com // doesn't map to any simulator fd: not a valid target fd 85610027SChris.Adeniyi-Jones@arm.com return -EBADF; 85710027SChris.Adeniyi-Jones@arm.com } 85810027SChris.Adeniyi-Jones@arm.com 8595877Shsul@eecs.umich.edu#if NO_STAT64 86010318Sandreas.hansson@arm.com struct stat hostBuf; 86110318Sandreas.hansson@arm.com int result = fstat(process->sim_fd(fd), &hostBuf); 8625877Shsul@eecs.umich.edu#else 8635877Shsul@eecs.umich.edu struct stat64 hostBuf; 8645877Shsul@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 8655877Shsul@eecs.umich.edu#endif 86610486Stjablin@gmail.com 86710486Stjablin@gmail.com if (result < 0) 8685877Shsul@eecs.umich.edu return -errno; 86910027SChris.Adeniyi-Jones@arm.com 87010027SChris.Adeniyi-Jones@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 8715877Shsul@eecs.umich.edu 8728601Ssteve.reinhardt@amd.com return 0; 8735877Shsul@eecs.umich.edu} 8745877Shsul@eecs.umich.edu 8755877Shsul@eecs.umich.edu 87610027SChris.Adeniyi-Jones@arm.com/// Target lstat() handler. 8775877Shsul@eecs.umich.edutemplate <class OS> 8785877Shsul@eecs.umich.eduSyscallReturn 8795877Shsul@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 88010027SChris.Adeniyi-Jones@arm.com ThreadContext *tc) 88110027SChris.Adeniyi-Jones@arm.com{ 88210027SChris.Adeniyi-Jones@arm.com std::string path; 88310027SChris.Adeniyi-Jones@arm.com 88410027SChris.Adeniyi-Jones@arm.com int index = 0; 88510027SChris.Adeniyi-Jones@arm.com if (!tc->getMemProxy().tryReadString(path, 8865877Shsul@eecs.umich.edu process->getSyscallArg(tc, index))) { 88710027SChris.Adeniyi-Jones@arm.com return -EFAULT; 88810027SChris.Adeniyi-Jones@arm.com } 88910027SChris.Adeniyi-Jones@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 89010027SChris.Adeniyi-Jones@arm.com 89110027SChris.Adeniyi-Jones@arm.com // Adjust path for current working directory 89210027SChris.Adeniyi-Jones@arm.com path = process->fullPath(path); 89310027SChris.Adeniyi-Jones@arm.com 89410027SChris.Adeniyi-Jones@arm.com struct stat hostBuf; 89510027SChris.Adeniyi-Jones@arm.com int result = lstat(path.c_str(), &hostBuf); 89610027SChris.Adeniyi-Jones@arm.com 89710027SChris.Adeniyi-Jones@arm.com if (result < 0) 89810027SChris.Adeniyi-Jones@arm.com return -errno; 89910027SChris.Adeniyi-Jones@arm.com 9005877Shsul@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9015877Shsul@eecs.umich.edu 9025877Shsul@eecs.umich.edu return 0; 90310027SChris.Adeniyi-Jones@arm.com} 90410027SChris.Adeniyi-Jones@arm.com 9058601Ssteve.reinhardt@amd.com/// Target lstat64() handler. 90610027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 9075877Shsul@eecs.umich.eduSyscallReturn 9085877Shsul@eecs.umich.edulstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9091999SN/A ThreadContext *tc) 910378SN/A{ 911360SN/A std::string path; 9121450SN/A 9133114Sgblack@eecs.umich.edu int index = 0; 9142680Sktlim@umich.edu if (!tc->getMemProxy().tryReadString(path, 915360SN/A process->getSyscallArg(tc, index))) { 916360SN/A return -EFAULT; 917360SN/A } 9186701Sgblack@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9198852Sandreas.hansson@arm.com 9206701Sgblack@eecs.umich.edu // Adjust path for current working directory 9216701Sgblack@eecs.umich.edu path = process->fullPath(path); 9226701Sgblack@eecs.umich.edu 9236701Sgblack@eecs.umich.edu#if NO_STAT64 924360SN/A struct stat hostBuf; 9253669Sbinkertn@umich.edu int result = lstat(path.c_str(), &hostBuf); 9263669Sbinkertn@umich.edu#else 9273669Sbinkertn@umich.edu struct stat64 hostBuf; 928360SN/A int result = lstat64(path.c_str(), &hostBuf); 929360SN/A#endif 930360SN/A 931360SN/A if (result < 0) 9322218SN/A return -errno; 933360SN/A 9348706Sandreas.hansson@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 935360SN/A 9361458SN/A return 0; 937360SN/A} 938360SN/A 939360SN/A/// Target fstat() handler. 9405074Ssaidi@eecs.umich.edutemplate <class OS> 9415074Ssaidi@eecs.umich.eduSyscallReturn 9425074Ssaidi@eecs.umich.edufstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9435074Ssaidi@eecs.umich.edu ThreadContext *tc) 9445074Ssaidi@eecs.umich.edu{ 9455074Ssaidi@eecs.umich.edu int index = 0; 9465074Ssaidi@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 9475074Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9486701Sgblack@eecs.umich.edu 9498852Sandreas.hansson@arm.com DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 9506701Sgblack@eecs.umich.edu 9515074Ssaidi@eecs.umich.edu if (fd < 0) 9526701Sgblack@eecs.umich.edu return -EBADF; 9535074Ssaidi@eecs.umich.edu 9545074Ssaidi@eecs.umich.edu struct stat hostBuf; 9555074Ssaidi@eecs.umich.edu int result = fstat(fd, &hostBuf); 9565074Ssaidi@eecs.umich.edu 9575208Ssaidi@eecs.umich.edu if (result < 0) 9585208Ssaidi@eecs.umich.edu return -errno; 9595208Ssaidi@eecs.umich.edu 9605208Ssaidi@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 9615074Ssaidi@eecs.umich.edu 9625074Ssaidi@eecs.umich.edu return 0; 9635208Ssaidi@eecs.umich.edu} 9645074Ssaidi@eecs.umich.edu 9655074Ssaidi@eecs.umich.edu 9665074Ssaidi@eecs.umich.edu/// Target statfs() handler. 9675074Ssaidi@eecs.umich.edutemplate <class OS> 9688706Sandreas.hansson@arm.comSyscallReturn 9695074Ssaidi@eecs.umich.edustatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9705074Ssaidi@eecs.umich.edu ThreadContext *tc) 9715074Ssaidi@eecs.umich.edu{ 9725074Ssaidi@eecs.umich.edu std::string path; 9735074Ssaidi@eecs.umich.edu 97410027SChris.Adeniyi-Jones@arm.com int index = 0; 97510027SChris.Adeniyi-Jones@arm.com if (!tc->getMemProxy().tryReadString(path, 97610027SChris.Adeniyi-Jones@arm.com process->getSyscallArg(tc, index))) { 97710027SChris.Adeniyi-Jones@arm.com return -EFAULT; 97810027SChris.Adeniyi-Jones@arm.com } 97910027SChris.Adeniyi-Jones@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 98010027SChris.Adeniyi-Jones@arm.com 98110027SChris.Adeniyi-Jones@arm.com // Adjust path for current working directory 98210027SChris.Adeniyi-Jones@arm.com path = process->fullPath(path); 98310793Sbrandon.potter@amd.com 98410027SChris.Adeniyi-Jones@arm.com struct statfs hostBuf; 98510027SChris.Adeniyi-Jones@arm.com int result = statfs(path.c_str(), &hostBuf); 98610027SChris.Adeniyi-Jones@arm.com 98710027SChris.Adeniyi-Jones@arm.com if (result < 0) 98810027SChris.Adeniyi-Jones@arm.com return -errno; 98910027SChris.Adeniyi-Jones@arm.com 99010027SChris.Adeniyi-Jones@arm.com OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 99110027SChris.Adeniyi-Jones@arm.com 99210027SChris.Adeniyi-Jones@arm.com return 0; 99310027SChris.Adeniyi-Jones@arm.com} 99410027SChris.Adeniyi-Jones@arm.com 99510027SChris.Adeniyi-Jones@arm.com 99610027SChris.Adeniyi-Jones@arm.com/// Target fstatfs() handler. 99710027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 99810027SChris.Adeniyi-Jones@arm.comSyscallReturn 99910027SChris.Adeniyi-Jones@arm.comfstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 100010027SChris.Adeniyi-Jones@arm.com ThreadContext *tc) 100110027SChris.Adeniyi-Jones@arm.com{ 100210027SChris.Adeniyi-Jones@arm.com int index = 0; 100310027SChris.Adeniyi-Jones@arm.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 100410027SChris.Adeniyi-Jones@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 100510027SChris.Adeniyi-Jones@arm.com 100610027SChris.Adeniyi-Jones@arm.com if (fd < 0) 100710027SChris.Adeniyi-Jones@arm.com return -EBADF; 100810027SChris.Adeniyi-Jones@arm.com 100910027SChris.Adeniyi-Jones@arm.com struct statfs hostBuf; 101010027SChris.Adeniyi-Jones@arm.com int result = fstatfs(fd, &hostBuf); 10111999SN/A 10121999SN/A if (result < 0) 10131999SN/A return -errno; 10143114Sgblack@eecs.umich.edu 10152680Sktlim@umich.edu OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 10161999SN/A 10176701Sgblack@eecs.umich.edu return 0; 101810931Sbrandon.potter@amd.com} 10196701Sgblack@eecs.umich.edu 102010931Sbrandon.potter@amd.com 102110932Sbrandon.potter@amd.com/// Target writev() handler. 102210931Sbrandon.potter@amd.comtemplate <class OS> 10231999SN/ASyscallReturn 10241999SN/AwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10252764Sstever@eecs.umich.edu ThreadContext *tc) 10262064SN/A{ 102710931Sbrandon.potter@amd.com int index = 0; 10282064SN/A int fd = process->getSyscallArg(tc, index); 10292064SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 103010931Sbrandon.potter@amd.com // doesn't map to any simulator fd: not a valid target fd 10312064SN/A return -EBADF; 10321999SN/A } 10331999SN/A 10342218SN/A SETranslatingPortProxy &p = tc->getMemProxy(); 10351999SN/A uint64_t tiov_base = process->getSyscallArg(tc, index); 103610931Sbrandon.potter@amd.com size_t count = process->getSyscallArg(tc, index); 10371999SN/A struct iovec hiov[count]; 10381999SN/A for (size_t i = 0; i < count; ++i) { 10391999SN/A typename OS::tgt_iovec tiov; 10401999SN/A 10411999SN/A p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 1042378SN/A (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 1043360SN/A hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 10441450SN/A hiov[i].iov_base = new char [hiov[i].iov_len]; 10453114Sgblack@eecs.umich.edu p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 10462680Sktlim@umich.edu hiov[i].iov_len); 1047360SN/A } 1048360SN/A 1049360SN/A int result = writev(process->sim_fd(fd), hiov, count); 10506701Sgblack@eecs.umich.edu 10518852Sandreas.hansson@arm.com for (size_t i = 0; i < count; ++i) 10526701Sgblack@eecs.umich.edu delete [] (char *)hiov[i].iov_base; 10536701Sgblack@eecs.umich.edu 10546701Sgblack@eecs.umich.edu if (result < 0) 10556701Sgblack@eecs.umich.edu return -errno; 1056360SN/A 10573669Sbinkertn@umich.edu return 0; 10583669Sbinkertn@umich.edu} 10593669Sbinkertn@umich.edu 1060360SN/A 1061360SN/A/// Target mmap() handler. 1062360SN/A/// 1063360SN/A/// We don't really handle mmap(). If the target is mmaping an 10641458SN/A/// anonymous region or /dev/zero, we can get away with doing basically 1065360SN/A/// nothing (since memory is initialized to zero and the simulator 10668706Sandreas.hansson@arm.com/// doesn't really check addresses anyway). 1067360SN/A/// 10681458SN/Atemplate <class OS> 1069360SN/ASyscallReturn 1070360SN/AmmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 10711999SN/A{ 10721999SN/A int index = 0; 10731999SN/A Addr start = p->getSyscallArg(tc, index); 10743114Sgblack@eecs.umich.edu uint64_t length = p->getSyscallArg(tc, index); 10752680Sktlim@umich.edu index++; // int prot = p->getSyscallArg(tc, index); 10761999SN/A int flags = p->getSyscallArg(tc, index); 10771999SN/A int tgt_fd = p->getSyscallArg(tc, index); 10781999SN/A // int offset = p->getSyscallArg(tc, index); 10796701Sgblack@eecs.umich.edu 10808852Sandreas.hansson@arm.com if (length > 0x100000000ULL) 10816701Sgblack@eecs.umich.edu warn("mmap length argument %#x is unreasonably large.\n", length); 10826701Sgblack@eecs.umich.edu 10836701Sgblack@eecs.umich.edu if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 10846701Sgblack@eecs.umich.edu Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 10851999SN/A if (!fd_map || fd_map->fd < 0) { 10863669Sbinkertn@umich.edu warn("mmap failing: target fd %d is not valid\n", tgt_fd); 10873669Sbinkertn@umich.edu return -EBADF; 10883669Sbinkertn@umich.edu } 10892764Sstever@eecs.umich.edu 10902064SN/A if (fd_map->filename != "/dev/zero") { 10912064SN/A // This is very likely broken, but leave a warning here 10922064SN/A // (rather than panic) in case /dev/zero is known by 10931999SN/A // another name on some platform 10941999SN/A warn("allowing mmap of file %s; mmap not supported on files" 10952064SN/A " other than /dev/zero\n", fd_map->filename); 10961999SN/A } 10971999SN/A } 10981999SN/A 10991999SN/A if ((start % TheISA::VMPageSize) != 0 || 11008706Sandreas.hansson@arm.com (length % TheISA::VMPageSize) != 0) { 11011999SN/A warn("mmap failing: arguments not page-aligned: " 11021999SN/A "start 0x%x length 0x%x", 11031999SN/A start, length); 11041999SN/A return -EINVAL; 1105378SN/A } 1106360SN/A 11071450SN/A // are we ok with clobbering existing mappings? only set this to 11083114Sgblack@eecs.umich.edu // true if the user has been warned. 11092680Sktlim@umich.edu bool clobber = false; 1110360SN/A 11116701Sgblack@eecs.umich.edu // try to use the caller-provided address if there is one 111210931Sbrandon.potter@amd.com bool use_provided_address = (start != 0); 11136701Sgblack@eecs.umich.edu 1114360SN/A if (use_provided_address) { 111511380Salexandru.dutu@amd.com // check to see if the desired address is already in use 1116360SN/A if (!p->pTable->isUnmapped(start, length)) { 111710932Sbrandon.potter@amd.com // there are existing mappings in the desired range 111810931Sbrandon.potter@amd.com // whether we clobber them or not depends on whether the caller 11191458SN/A // specified MAP_FIXED 1120360SN/A if (flags & OS::TGT_MAP_FIXED) { 1121360SN/A // MAP_FIXED specified: clobber existing mappings 112210931Sbrandon.potter@amd.com warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 1123360SN/A start); 1124360SN/A clobber = true; 11251458SN/A } else { 1126360SN/A // MAP_FIXED not specified: ignore suggested start address 112710931Sbrandon.potter@amd.com warn("mmap: ignoring suggested map address 0x%x\n", start); 11282021SN/A use_provided_address = false; 11291458SN/A } 1130360SN/A } 1131360SN/A } 1132360SN/A 11331706SN/A if (!use_provided_address) { 11341706SN/A // no address provided, or provided address unusable: 11351706SN/A // pick next address from our "mmap region" 11363114Sgblack@eecs.umich.edu if (OS::mmapGrowsDown()) { 11372680Sktlim@umich.edu start = p->mmap_end - length; 11381706SN/A p->mmap_end = start; 11391706SN/A } else { 11401706SN/A start = p->mmap_end; 11416701Sgblack@eecs.umich.edu p->mmap_end += length; 11428852Sandreas.hansson@arm.com } 11436701Sgblack@eecs.umich.edu } 11446701Sgblack@eecs.umich.edu 11456701Sgblack@eecs.umich.edu p->allocateMem(start, length, clobber); 11466701Sgblack@eecs.umich.edu 11471706SN/A return start; 11483669Sbinkertn@umich.edu} 11493669Sbinkertn@umich.edu 11503669Sbinkertn@umich.edu/// Target getrlimit() handler. 11511706SN/Atemplate <class OS> 11521706SN/ASyscallReturn 11531706SN/AgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11541706SN/A ThreadContext *tc) 11552218SN/A{ 11561706SN/A int index = 0; 11578706Sandreas.hansson@arm.com unsigned resource = process->getSyscallArg(tc, index); 11581706SN/A TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 11591706SN/A 11601706SN/A switch (resource) { 11611706SN/A case OS::TGT_RLIMIT_STACK: 11621706SN/A // max stack size in bytes: make up a number (8MB for now) 11631706SN/A rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 11641706SN/A rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11651706SN/A rlp->rlim_max = TheISA::htog(rlp->rlim_max); 11663114Sgblack@eecs.umich.edu break; 11672680Sktlim@umich.edu 11681706SN/A case OS::TGT_RLIMIT_DATA: 11696701Sgblack@eecs.umich.edu // max data segment size in bytes: make up a number 117010931Sbrandon.potter@amd.com rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 11716701Sgblack@eecs.umich.edu rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11721706SN/A rlp->rlim_max = TheISA::htog(rlp->rlim_max); 117310932Sbrandon.potter@amd.com break; 117410931Sbrandon.potter@amd.com 11751706SN/A default: 11761706SN/A std::cerr << "getrlimitFunc: unimplemented resource " << resource 11771706SN/A << std::endl; 117810931Sbrandon.potter@amd.com abort(); 11791706SN/A break; 11801706SN/A } 11812218SN/A 11821706SN/A rlp.copyOut(tc->getMemProxy()); 11838706Sandreas.hansson@arm.com return 0; 11841706SN/A} 11851706SN/A 11861706SN/A/// Target gettimeofday() handler. 11871706SN/Atemplate <class OS> 11881706SN/ASyscallReturn 11891999SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11901999SN/A ThreadContext *tc) 11911999SN/A{ 11923114Sgblack@eecs.umich.edu int index = 0; 11932680Sktlim@umich.edu TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 11941999SN/A 11956701Sgblack@eecs.umich.edu getElapsedTime(tp->tv_sec, tp->tv_usec); 119610931Sbrandon.potter@amd.com tp->tv_sec += seconds_since_epoch; 119710931Sbrandon.potter@amd.com tp->tv_sec = TheISA::htog(tp->tv_sec); 119810932Sbrandon.potter@amd.com tp->tv_usec = TheISA::htog(tp->tv_usec); 119910931Sbrandon.potter@amd.com 12001999SN/A tp.copyOut(tc->getMemProxy()); 12011999SN/A 12028852Sandreas.hansson@arm.com return 0; 12036701Sgblack@eecs.umich.edu} 12046701Sgblack@eecs.umich.edu 12051999SN/A 12066227Snate@binkert.org/// Target utimes() handler. 12071999SN/Atemplate <class OS> 12082461SN/ASyscallReturn 12098852Sandreas.hansson@arm.comutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12108852Sandreas.hansson@arm.com ThreadContext *tc) 12118737Skoansin.tan@gmail.com{ 12121999SN/A std::string path; 12138852Sandreas.hansson@arm.com 12148852Sandreas.hansson@arm.com int index = 0; 12151999SN/A if (!tc->getMemProxy().tryReadString(path, 12161999SN/A process->getSyscallArg(tc, index))) { 121710931Sbrandon.potter@amd.com return -EFAULT; 12181999SN/A } 12196227Snate@binkert.org 12201999SN/A TypedBufferArg<typename OS::timeval [2]> 12211999SN/A tp(process->getSyscallArg(tc, index)); 12221999SN/A tp.copyIn(tc->getMemProxy()); 12232218SN/A 12241999SN/A struct timeval hostTimeval[2]; 122510629Sjthestness@gmail.com for (int i = 0; i < 2; ++i) 12261999SN/A { 12271999SN/A hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 122811385Sbrandon.potter@amd.com hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 1229360SN/A } 12301450SN/A 123111385Sbrandon.potter@amd.com // Adjust path for current working directory 123211385Sbrandon.potter@amd.com path = process->fullPath(path); 1233360SN/A 12346701Sgblack@eecs.umich.edu int result = utimes(path.c_str(), hostTimeval); 12356701Sgblack@eecs.umich.edu 12366701Sgblack@eecs.umich.edu if (result < 0) 123711383Sbrandon.potter@amd.com return -errno; 123811383Sbrandon.potter@amd.com 12398324Ssteve.reinhardt@amd.com return 0; 124010486Stjablin@gmail.com} 1241360SN/A/// Target getrusage() function. 124211385Sbrandon.potter@amd.comtemplate <class OS> 124311385Sbrandon.potter@amd.comSyscallReturn 12449008Sgblack@eecs.umich.edugetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 124511383Sbrandon.potter@amd.com ThreadContext *tc) 124611383Sbrandon.potter@amd.com{ 124711383Sbrandon.potter@amd.com int index = 0; 124811383Sbrandon.potter@amd.com int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 124911383Sbrandon.potter@amd.com TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 125011383Sbrandon.potter@amd.com 125111383Sbrandon.potter@amd.com rup->ru_utime.tv_sec = 0; 125211383Sbrandon.potter@amd.com rup->ru_utime.tv_usec = 0; 125311383Sbrandon.potter@amd.com rup->ru_stime.tv_sec = 0; 12548324Ssteve.reinhardt@amd.com rup->ru_stime.tv_usec = 0; 125511383Sbrandon.potter@amd.com rup->ru_maxrss = 0; 125611383Sbrandon.potter@amd.com rup->ru_ixrss = 0; 125711383Sbrandon.potter@amd.com rup->ru_idrss = 0; 125811383Sbrandon.potter@amd.com rup->ru_isrss = 0; 125911383Sbrandon.potter@amd.com rup->ru_minflt = 0; 126011383Sbrandon.potter@amd.com rup->ru_majflt = 0; 126111383Sbrandon.potter@amd.com rup->ru_nswap = 0; 126211383Sbrandon.potter@amd.com rup->ru_inblock = 0; 126311383Sbrandon.potter@amd.com rup->ru_oublock = 0; 126411383Sbrandon.potter@amd.com rup->ru_msgsnd = 0; 126511383Sbrandon.potter@amd.com rup->ru_msgrcv = 0; 126611383Sbrandon.potter@amd.com rup->ru_nsignals = 0; 126711383Sbrandon.potter@amd.com rup->ru_nvcsw = 0; 126811383Sbrandon.potter@amd.com rup->ru_nivcsw = 0; 126911383Sbrandon.potter@amd.com 127011383Sbrandon.potter@amd.com switch (who) { 127111383Sbrandon.potter@amd.com case OS::TGT_RUSAGE_SELF: 127211383Sbrandon.potter@amd.com getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 127311383Sbrandon.potter@amd.com rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 127411383Sbrandon.potter@amd.com rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 127511383Sbrandon.potter@amd.com break; 127611383Sbrandon.potter@amd.com 127711383Sbrandon.potter@amd.com case OS::TGT_RUSAGE_CHILDREN: 127811383Sbrandon.potter@amd.com // do nothing. We have no child processes, so they take no time. 12798324Ssteve.reinhardt@amd.com break; 12805877Shsul@eecs.umich.edu 128110486Stjablin@gmail.com default: 128210486Stjablin@gmail.com // don't really handle THREAD or CHILDREN, but just warn and 128311383Sbrandon.potter@amd.com // plow ahead 128411383Sbrandon.potter@amd.com warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 128511383Sbrandon.potter@amd.com who); 128611383Sbrandon.potter@amd.com } 128711383Sbrandon.potter@amd.com 128811383Sbrandon.potter@amd.com rup.copyOut(tc->getMemProxy()); 1289360SN/A 129011383Sbrandon.potter@amd.com return 0; 129111383Sbrandon.potter@amd.com} 12928600Ssteve.reinhardt@amd.com 129311383Sbrandon.potter@amd.com/// Target times() function. 129411383Sbrandon.potter@amd.comtemplate <class OS> 129511383Sbrandon.potter@amd.comSyscallReturn 12968600Ssteve.reinhardt@amd.comtimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12972544SN/A ThreadContext *tc) 12982544SN/A{ 129911383Sbrandon.potter@amd.com int index = 0; 130011383Sbrandon.potter@amd.com TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 130111383Sbrandon.potter@amd.com 130211386Ssteve.reinhardt@amd.com // Fill in the time structure (in clocks) 130311386Ssteve.reinhardt@amd.com int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 130411383Sbrandon.potter@amd.com bufp->tms_utime = clocks; 130511383Sbrandon.potter@amd.com bufp->tms_stime = 0; 130611383Sbrandon.potter@amd.com bufp->tms_cutime = 0; 130711383Sbrandon.potter@amd.com bufp->tms_cstime = 0; 130811383Sbrandon.potter@amd.com 130911383Sbrandon.potter@amd.com // Convert to host endianness 131011383Sbrandon.potter@amd.com bufp->tms_utime = TheISA::htog(bufp->tms_utime); 131111383Sbrandon.potter@amd.com 131211383Sbrandon.potter@amd.com // Write back 131311383Sbrandon.potter@amd.com bufp.copyOut(tc->getMemProxy()); 131411383Sbrandon.potter@amd.com 131511383Sbrandon.potter@amd.com // Return clock ticks since system boot 131611383Sbrandon.potter@amd.com return clocks; 131711383Sbrandon.potter@amd.com} 131811383Sbrandon.potter@amd.com 13198600Ssteve.reinhardt@amd.com/// Target time() function. 13206672Sgblack@eecs.umich.edutemplate <class OS> 13218600Ssteve.reinhardt@amd.comSyscallReturn 132211383Sbrandon.potter@amd.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 132311383Sbrandon.potter@amd.com ThreadContext *tc) 132411383Sbrandon.potter@amd.com{ 13258601Ssteve.reinhardt@amd.com typename OS::time_t sec, usec; 13262544SN/A getElapsedTime(sec, usec); 132711383Sbrandon.potter@amd.com sec += seconds_since_epoch; 132811383Sbrandon.potter@amd.com 132911383Sbrandon.potter@amd.com int index = 0; 133011383Sbrandon.potter@amd.com Addr taddr = (Addr)process->getSyscallArg(tc, index); 133111383Sbrandon.potter@amd.com if(taddr != 0) { 133211383Sbrandon.potter@amd.com typename OS::time_t t = sec; 133311383Sbrandon.potter@amd.com t = TheISA::htog(t); 133411383Sbrandon.potter@amd.com SETranslatingPortProxy &p = tc->getMemProxy(); 133511383Sbrandon.potter@amd.com p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 133611383Sbrandon.potter@amd.com } 133711383Sbrandon.potter@amd.com return sec; 133811383Sbrandon.potter@amd.com} 133911383Sbrandon.potter@amd.com 134011383Sbrandon.potter@amd.com 134111383Sbrandon.potter@amd.com#endif // __SIM_SYSCALL_EMUL_HH__ 134211383Sbrandon.potter@amd.com