syscall_emul.hh revision 9238
15952Ssaidi@eecs.umich.edu/* 25952Ssaidi@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 35952Ssaidi@eecs.umich.edu * All rights reserved. 45952Ssaidi@eecs.umich.edu * 55952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 75952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145952Ssaidi@eecs.umich.edu * this software without specific prior written permission. 155952Ssaidi@eecs.umich.edu * 165952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185952Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205952Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215952Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255952Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275952Ssaidi@eecs.umich.edu * 285952Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 295952Ssaidi@eecs.umich.edu * Kevin Lim 305952Ssaidi@eecs.umich.edu */ 318229Snate@binkert.org 325952Ssaidi@eecs.umich.edu#ifndef __SIM_SYSCALL_EMUL_HH__ 338229Snate@binkert.org#define __SIM_SYSCALL_EMUL_HH__ 348229Snate@binkert.org 355952Ssaidi@eecs.umich.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 365952Ssaidi@eecs.umich.edu defined(__FreeBSD__) || defined(__CYGWIN__) || \ 375952Ssaidi@eecs.umich.edu defined(__NetBSD__)) 386658Snate@binkert.org 395952Ssaidi@eecs.umich.edu/// 405952Ssaidi@eecs.umich.edu/// @file syscall_emul.hh 415952Ssaidi@eecs.umich.edu/// 425952Ssaidi@eecs.umich.edu/// This file defines objects used to emulate syscalls from the target 435952Ssaidi@eecs.umich.edu/// application on the host machine. 445952Ssaidi@eecs.umich.edu 455952Ssaidi@eecs.umich.edu#ifdef __CYGWIN32__ 465952Ssaidi@eecs.umich.edu#include <sys/fcntl.h> // for O_BINARY 475952Ssaidi@eecs.umich.edu#endif 485952Ssaidi@eecs.umich.edu#include <sys/stat.h> 495952Ssaidi@eecs.umich.edu#include <sys/time.h> 505952Ssaidi@eecs.umich.edu#include <sys/uio.h> 515952Ssaidi@eecs.umich.edu#include <fcntl.h> 525952Ssaidi@eecs.umich.edu 535952Ssaidi@eecs.umich.edu#include <cerrno> 545952Ssaidi@eecs.umich.edu#include <string> 555952Ssaidi@eecs.umich.edu 565952Ssaidi@eecs.umich.edu#include "base/chunk_generator.hh" 575952Ssaidi@eecs.umich.edu#include "base/intmath.hh" // for RoundUp 585952Ssaidi@eecs.umich.edu#include "base/misc.hh" 595952Ssaidi@eecs.umich.edu#include "base/trace.hh" 605952Ssaidi@eecs.umich.edu#include "base/types.hh" 615952Ssaidi@eecs.umich.edu#include "config/the_isa.hh" 625952Ssaidi@eecs.umich.edu#include "cpu/base.hh" 635952Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh" 645952Ssaidi@eecs.umich.edu#include "debug/SyscallVerbose.hh" 655952Ssaidi@eecs.umich.edu#include "mem/page_table.hh" 665952Ssaidi@eecs.umich.edu#include "mem/se_translating_port_proxy.hh" 675952Ssaidi@eecs.umich.edu#include "sim/byteswap.hh" 685952Ssaidi@eecs.umich.edu#include "sim/process.hh" 695952Ssaidi@eecs.umich.edu#include "sim/syscallreturn.hh" 705952Ssaidi@eecs.umich.edu#include "sim/system.hh" 715952Ssaidi@eecs.umich.edu 725952Ssaidi@eecs.umich.edu/// 735952Ssaidi@eecs.umich.edu/// System call descriptor. 745952Ssaidi@eecs.umich.edu/// 755952Ssaidi@eecs.umich.educlass SyscallDesc { 765952Ssaidi@eecs.umich.edu 775952Ssaidi@eecs.umich.edu public: 785952Ssaidi@eecs.umich.edu 795952Ssaidi@eecs.umich.edu /// Typedef for target syscall handler functions. 805952Ssaidi@eecs.umich.edu typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 815952Ssaidi@eecs.umich.edu LiveProcess *, ThreadContext *); 825952Ssaidi@eecs.umich.edu 835952Ssaidi@eecs.umich.edu const char *name; //!< Syscall name (e.g., "open"). 845952Ssaidi@eecs.umich.edu FuncPtr funcPtr; //!< Pointer to emulation function. 855952Ssaidi@eecs.umich.edu int flags; //!< Flags (see Flags enum). 865952Ssaidi@eecs.umich.edu 875952Ssaidi@eecs.umich.edu /// Flag values for controlling syscall behavior. 885952Ssaidi@eecs.umich.edu enum Flags { 895952Ssaidi@eecs.umich.edu /// Don't set return regs according to funcPtr return value. 905952Ssaidi@eecs.umich.edu /// Used for syscalls with non-standard return conventions 915952Ssaidi@eecs.umich.edu /// that explicitly set the ThreadContext regs (e.g., 925952Ssaidi@eecs.umich.edu /// sigreturn). 935952Ssaidi@eecs.umich.edu SuppressReturnValue = 1 945952Ssaidi@eecs.umich.edu }; 955952Ssaidi@eecs.umich.edu 965952Ssaidi@eecs.umich.edu /// Constructor. 975952Ssaidi@eecs.umich.edu SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 985952Ssaidi@eecs.umich.edu : name(_name), funcPtr(_funcPtr), flags(_flags) 995952Ssaidi@eecs.umich.edu { 1005952Ssaidi@eecs.umich.edu } 1015952Ssaidi@eecs.umich.edu 1025952Ssaidi@eecs.umich.edu /// Emulate the syscall. Public interface for calling through funcPtr. 1035952Ssaidi@eecs.umich.edu void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1045952Ssaidi@eecs.umich.edu}; 1055952Ssaidi@eecs.umich.edu 1065952Ssaidi@eecs.umich.edu 1075952Ssaidi@eecs.umich.educlass BaseBufferArg { 1085952Ssaidi@eecs.umich.edu 1095952Ssaidi@eecs.umich.edu public: 1105952Ssaidi@eecs.umich.edu 1115952Ssaidi@eecs.umich.edu BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 1125952Ssaidi@eecs.umich.edu { 1135952Ssaidi@eecs.umich.edu bufPtr = new uint8_t[size]; 1145952Ssaidi@eecs.umich.edu // clear out buffer: in case we only partially populate this, 1155952Ssaidi@eecs.umich.edu // and then do a copyOut(), we want to make sure we don't 1165952Ssaidi@eecs.umich.edu // introduce any random junk into the simulated address space 1175952Ssaidi@eecs.umich.edu memset(bufPtr, 0, size); 1185952Ssaidi@eecs.umich.edu } 1195952Ssaidi@eecs.umich.edu 1205952Ssaidi@eecs.umich.edu virtual ~BaseBufferArg() { delete [] bufPtr; } 1215952Ssaidi@eecs.umich.edu 1225952Ssaidi@eecs.umich.edu // 1235952Ssaidi@eecs.umich.edu // copy data into simulator space (read from target memory) 1245952Ssaidi@eecs.umich.edu // 1255952Ssaidi@eecs.umich.edu virtual bool copyIn(SETranslatingPortProxy &memproxy) 1265952Ssaidi@eecs.umich.edu { 1275952Ssaidi@eecs.umich.edu memproxy.readBlob(addr, bufPtr, size); 1285952Ssaidi@eecs.umich.edu return true; // no EFAULT detection for now 1295952Ssaidi@eecs.umich.edu } 1305952Ssaidi@eecs.umich.edu 1315952Ssaidi@eecs.umich.edu // 1325952Ssaidi@eecs.umich.edu // copy data out of simulator space (write to target memory) 1335952Ssaidi@eecs.umich.edu // 1345952Ssaidi@eecs.umich.edu virtual bool copyOut(SETranslatingPortProxy &memproxy) 1355952Ssaidi@eecs.umich.edu { 1365952Ssaidi@eecs.umich.edu memproxy.writeBlob(addr, bufPtr, size); 1375952Ssaidi@eecs.umich.edu return true; // no EFAULT detection for now 1385952Ssaidi@eecs.umich.edu } 1395952Ssaidi@eecs.umich.edu 1405952Ssaidi@eecs.umich.edu protected: 1415952Ssaidi@eecs.umich.edu Addr addr; 1425952Ssaidi@eecs.umich.edu int size; 1435952Ssaidi@eecs.umich.edu uint8_t *bufPtr; 1445952Ssaidi@eecs.umich.edu}; 1455952Ssaidi@eecs.umich.edu 1465952Ssaidi@eecs.umich.edu 1475952Ssaidi@eecs.umich.educlass BufferArg : public BaseBufferArg 1485952Ssaidi@eecs.umich.edu{ 1495952Ssaidi@eecs.umich.edu public: 1505952Ssaidi@eecs.umich.edu BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 1515952Ssaidi@eecs.umich.edu void *bufferPtr() { return bufPtr; } 1525952Ssaidi@eecs.umich.edu}; 1535952Ssaidi@eecs.umich.edu 1545952Ssaidi@eecs.umich.edutemplate <class T> 1555952Ssaidi@eecs.umich.educlass TypedBufferArg : public BaseBufferArg 1565952Ssaidi@eecs.umich.edu{ 1575952Ssaidi@eecs.umich.edu public: 1585952Ssaidi@eecs.umich.edu // user can optionally specify a specific number of bytes to 1595952Ssaidi@eecs.umich.edu // allocate to deal with those structs that have variable-size 1605952Ssaidi@eecs.umich.edu // arrays at the end 1615952Ssaidi@eecs.umich.edu TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1625952Ssaidi@eecs.umich.edu : BaseBufferArg(_addr, _size) 1635952Ssaidi@eecs.umich.edu { } 1647823Ssteve.reinhardt@amd.com 1655952Ssaidi@eecs.umich.edu // type case 1665952Ssaidi@eecs.umich.edu operator T*() { return (T *)bufPtr; } 1675952Ssaidi@eecs.umich.edu 1685952Ssaidi@eecs.umich.edu // dereference operators 1695952Ssaidi@eecs.umich.edu T &operator*() { return *((T *)bufPtr); } 1705952Ssaidi@eecs.umich.edu T* operator->() { return (T *)bufPtr; } 1715952Ssaidi@eecs.umich.edu T &operator[](int i) { return ((T *)bufPtr)[i]; } 1725952Ssaidi@eecs.umich.edu}; 1735952Ssaidi@eecs.umich.edu 1745952Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////// 1755952Ssaidi@eecs.umich.edu// 1765952Ssaidi@eecs.umich.edu// The following emulation functions are generic enough that they 1775952Ssaidi@eecs.umich.edu// don't need to be recompiled for different emulated OS's. They are 1785952Ssaidi@eecs.umich.edu// defined in sim/syscall_emul.cc. 1795952Ssaidi@eecs.umich.edu// 1805952Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////// 1815952Ssaidi@eecs.umich.edu 1825952Ssaidi@eecs.umich.edu 1835952Ssaidi@eecs.umich.edu/// Handler for unimplemented syscalls that we haven't thought about. 1845952Ssaidi@eecs.umich.eduSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1855952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1865952Ssaidi@eecs.umich.edu 1875952Ssaidi@eecs.umich.edu/// Handler for unimplemented syscalls that we never intend to 1885952Ssaidi@eecs.umich.edu/// implement (signal handling, etc.) and should not affect the correct 1895952Ssaidi@eecs.umich.edu/// behavior of the program. Print a warning only if the appropriate 1905952Ssaidi@eecs.umich.edu/// trace flag is enabled. Return success to the target program. 1915952Ssaidi@eecs.umich.eduSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1925952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1935952Ssaidi@eecs.umich.eduSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 1945952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1955952Ssaidi@eecs.umich.edu 1965952Ssaidi@eecs.umich.edu/// Target exit() handler: terminate current context. 1975952Ssaidi@eecs.umich.eduSyscallReturn exitFunc(SyscallDesc *desc, int num, 1985952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1995952Ssaidi@eecs.umich.edu 2005952Ssaidi@eecs.umich.edu/// Target exit_group() handler: terminate simulation. (exit all threads) 2015952Ssaidi@eecs.umich.eduSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 2025952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2035952Ssaidi@eecs.umich.edu 2045952Ssaidi@eecs.umich.edu/// Target getpagesize() handler. 2055952Ssaidi@eecs.umich.eduSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 2065952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2075952Ssaidi@eecs.umich.edu 2085952Ssaidi@eecs.umich.edu/// Target brk() handler: set brk address. 2095952Ssaidi@eecs.umich.eduSyscallReturn brkFunc(SyscallDesc *desc, int num, 2105952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2115952Ssaidi@eecs.umich.edu 2125952Ssaidi@eecs.umich.edu/// Target close() handler. 2135952Ssaidi@eecs.umich.eduSyscallReturn closeFunc(SyscallDesc *desc, int num, 2145952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2155952Ssaidi@eecs.umich.edu 2165952Ssaidi@eecs.umich.edu/// Target read() handler. 2175952Ssaidi@eecs.umich.eduSyscallReturn readFunc(SyscallDesc *desc, int num, 2185952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2195952Ssaidi@eecs.umich.edu 2205952Ssaidi@eecs.umich.edu/// Target write() handler. 2215952Ssaidi@eecs.umich.eduSyscallReturn writeFunc(SyscallDesc *desc, int num, 2225952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2235952Ssaidi@eecs.umich.edu 2245952Ssaidi@eecs.umich.edu/// Target lseek() handler. 2255952Ssaidi@eecs.umich.eduSyscallReturn lseekFunc(SyscallDesc *desc, int num, 2265952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2275952Ssaidi@eecs.umich.edu 2285952Ssaidi@eecs.umich.edu/// Target _llseek() handler. 2295952Ssaidi@eecs.umich.eduSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 2305952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2315952Ssaidi@eecs.umich.edu 2325952Ssaidi@eecs.umich.edu/// Target munmap() handler. 2335952Ssaidi@eecs.umich.eduSyscallReturn munmapFunc(SyscallDesc *desc, int num, 2345952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2355952Ssaidi@eecs.umich.edu 2365952Ssaidi@eecs.umich.edu/// Target gethostname() handler. 2375952Ssaidi@eecs.umich.eduSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 2385952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2395952Ssaidi@eecs.umich.edu 2405952Ssaidi@eecs.umich.edu/// Target getcwd() handler. 2415952Ssaidi@eecs.umich.eduSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2425952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2435952Ssaidi@eecs.umich.edu 2445952Ssaidi@eecs.umich.edu/// Target unlink() handler. 2455952Ssaidi@eecs.umich.eduSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2465952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2475952Ssaidi@eecs.umich.edu 2485952Ssaidi@eecs.umich.edu/// Target unlink() handler. 2495952Ssaidi@eecs.umich.eduSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2505952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2515952Ssaidi@eecs.umich.edu 2525952Ssaidi@eecs.umich.edu/// Target mkdir() handler. 2535952Ssaidi@eecs.umich.eduSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2545952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2555952Ssaidi@eecs.umich.edu 2565952Ssaidi@eecs.umich.edu/// Target rename() handler. 2575952Ssaidi@eecs.umich.eduSyscallReturn renameFunc(SyscallDesc *desc, int num, 2585952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2595952Ssaidi@eecs.umich.edu 2605952Ssaidi@eecs.umich.edu 2615952Ssaidi@eecs.umich.edu/// Target truncate() handler. 2625952Ssaidi@eecs.umich.eduSyscallReturn truncateFunc(SyscallDesc *desc, int num, 2635952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2645952Ssaidi@eecs.umich.edu 2655952Ssaidi@eecs.umich.edu 2665952Ssaidi@eecs.umich.edu/// Target ftruncate() handler. 2675952Ssaidi@eecs.umich.eduSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2685952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2695952Ssaidi@eecs.umich.edu 2705952Ssaidi@eecs.umich.edu 2715952Ssaidi@eecs.umich.edu/// Target truncate64() handler. 2725952Ssaidi@eecs.umich.eduSyscallReturn truncate64Func(SyscallDesc *desc, int num, 2735952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2745952Ssaidi@eecs.umich.edu 2755952Ssaidi@eecs.umich.edu/// Target ftruncate64() handler. 2767823Ssteve.reinhardt@amd.comSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2775952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2785952Ssaidi@eecs.umich.edu 2795952Ssaidi@eecs.umich.edu 2805952Ssaidi@eecs.umich.edu/// Target umask() handler. 2815952Ssaidi@eecs.umich.eduSyscallReturn umaskFunc(SyscallDesc *desc, int num, 2825952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2835952Ssaidi@eecs.umich.edu 2845952Ssaidi@eecs.umich.edu 2855952Ssaidi@eecs.umich.edu/// Target chown() handler. 2865952Ssaidi@eecs.umich.eduSyscallReturn chownFunc(SyscallDesc *desc, int num, 2875952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2885952Ssaidi@eecs.umich.edu 2895952Ssaidi@eecs.umich.edu 2905952Ssaidi@eecs.umich.edu/// Target fchown() handler. 2915952Ssaidi@eecs.umich.eduSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2925952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2935952Ssaidi@eecs.umich.edu 2945952Ssaidi@eecs.umich.edu/// Target dup() handler. 2955952Ssaidi@eecs.umich.eduSyscallReturn dupFunc(SyscallDesc *desc, int num, 2965952Ssaidi@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 2975952Ssaidi@eecs.umich.edu 2985952Ssaidi@eecs.umich.edu/// Target fnctl() handler. 2995952Ssaidi@eecs.umich.eduSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 3005952Ssaidi@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3015952Ssaidi@eecs.umich.edu 3025952Ssaidi@eecs.umich.edu/// Target fcntl64() handler. 3035952Ssaidi@eecs.umich.eduSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 3045952Ssaidi@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3055952Ssaidi@eecs.umich.edu 3065952Ssaidi@eecs.umich.edu/// Target setuid() handler. 3075952Ssaidi@eecs.umich.eduSyscallReturn setuidFunc(SyscallDesc *desc, int num, 3085952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3095952Ssaidi@eecs.umich.edu 3105952Ssaidi@eecs.umich.edu/// Target getpid() handler. 3115952Ssaidi@eecs.umich.eduSyscallReturn getpidFunc(SyscallDesc *desc, int num, 3125952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3135952Ssaidi@eecs.umich.edu 3145952Ssaidi@eecs.umich.edu/// Target getuid() handler. 3155952Ssaidi@eecs.umich.eduSyscallReturn getuidFunc(SyscallDesc *desc, int num, 3165952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3175952Ssaidi@eecs.umich.edu 3185952Ssaidi@eecs.umich.edu/// Target getgid() handler. 3197823Ssteve.reinhardt@amd.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 3205952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3215952Ssaidi@eecs.umich.edu 3225952Ssaidi@eecs.umich.edu/// Target getppid() handler. 3235952Ssaidi@eecs.umich.eduSyscallReturn getppidFunc(SyscallDesc *desc, int num, 3245952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3255952Ssaidi@eecs.umich.edu 3265952Ssaidi@eecs.umich.edu/// Target geteuid() handler. 3275952Ssaidi@eecs.umich.eduSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 3285952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3295952Ssaidi@eecs.umich.edu 3305952Ssaidi@eecs.umich.edu/// Target getegid() handler. 3315952Ssaidi@eecs.umich.eduSyscallReturn getegidFunc(SyscallDesc *desc, int num, 3325952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3335952Ssaidi@eecs.umich.edu 3345952Ssaidi@eecs.umich.edu/// Target clone() handler. 3355952Ssaidi@eecs.umich.eduSyscallReturn cloneFunc(SyscallDesc *desc, int num, 3365952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3375952Ssaidi@eecs.umich.edu 3385952Ssaidi@eecs.umich.edu/// Futex system call 3395952Ssaidi@eecs.umich.edu/// Implemented by Daniel Sanchez 3405952Ssaidi@eecs.umich.edu/// Used by printf's in multi-threaded apps 3415952Ssaidi@eecs.umich.edutemplate <class OS> 3425952Ssaidi@eecs.umich.eduSyscallReturn 3435952Ssaidi@eecs.umich.edufutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3445952Ssaidi@eecs.umich.edu ThreadContext *tc) 3455952Ssaidi@eecs.umich.edu{ 3465952Ssaidi@eecs.umich.edu int index_uaddr = 0; 3475952Ssaidi@eecs.umich.edu int index_op = 1; 3485952Ssaidi@eecs.umich.edu int index_val = 2; 3495952Ssaidi@eecs.umich.edu int index_timeout = 3; 3505952Ssaidi@eecs.umich.edu 3515952Ssaidi@eecs.umich.edu uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3525952Ssaidi@eecs.umich.edu int op = process->getSyscallArg(tc, index_op); 3535952Ssaidi@eecs.umich.edu int val = process->getSyscallArg(tc, index_val); 3545952Ssaidi@eecs.umich.edu uint64_t timeout = process->getSyscallArg(tc, index_timeout); 3555952Ssaidi@eecs.umich.edu 3565952Ssaidi@eecs.umich.edu std::map<uint64_t, std::list<ThreadContext *> * > 3575952Ssaidi@eecs.umich.edu &futex_map = tc->getSystemPtr()->futexMap; 3585952Ssaidi@eecs.umich.edu 3595952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 3605952Ssaidi@eecs.umich.edu uaddr, op, val); 3615952Ssaidi@eecs.umich.edu 3625952Ssaidi@eecs.umich.edu op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 3635952Ssaidi@eecs.umich.edu 3645952Ssaidi@eecs.umich.edu if (op == OS::TGT_FUTEX_WAIT) { 3655952Ssaidi@eecs.umich.edu if (timeout != 0) { 3665952Ssaidi@eecs.umich.edu warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 3675952Ssaidi@eecs.umich.edu "we'll wait indefinitely"); 3685952Ssaidi@eecs.umich.edu } 3695952Ssaidi@eecs.umich.edu 3705952Ssaidi@eecs.umich.edu uint8_t *buf = new uint8_t[sizeof(int)]; 3715952Ssaidi@eecs.umich.edu tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3725952Ssaidi@eecs.umich.edu int mem_val = *((int *)buf); 3735952Ssaidi@eecs.umich.edu delete buf; 3745952Ssaidi@eecs.umich.edu 3755952Ssaidi@eecs.umich.edu if(val != mem_val) { 3765952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 3775952Ssaidi@eecs.umich.edu "expected: %d\n", mem_val, val); 3785952Ssaidi@eecs.umich.edu return -OS::TGT_EWOULDBLOCK; 3795952Ssaidi@eecs.umich.edu } 3805952Ssaidi@eecs.umich.edu 3815952Ssaidi@eecs.umich.edu // Queue the thread context 3825952Ssaidi@eecs.umich.edu std::list<ThreadContext *> * tcWaitList; 3835952Ssaidi@eecs.umich.edu if (futex_map.count(uaddr)) { 3845952Ssaidi@eecs.umich.edu tcWaitList = futex_map.find(uaddr)->second; 3855952Ssaidi@eecs.umich.edu } else { 3865952Ssaidi@eecs.umich.edu tcWaitList = new std::list<ThreadContext *>(); 3875952Ssaidi@eecs.umich.edu futex_map.insert(std::pair< uint64_t, 3885952Ssaidi@eecs.umich.edu std::list<ThreadContext *> * >(uaddr, tcWaitList)); 3895952Ssaidi@eecs.umich.edu } 3905952Ssaidi@eecs.umich.edu tcWaitList->push_back(tc); 3915952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 3925952Ssaidi@eecs.umich.edu "thread context\n"); 3935952Ssaidi@eecs.umich.edu tc->suspend(); 3945952Ssaidi@eecs.umich.edu return 0; 3955952Ssaidi@eecs.umich.edu } else if (op == OS::TGT_FUTEX_WAKE){ 3965952Ssaidi@eecs.umich.edu int wokenUp = 0; 3975952Ssaidi@eecs.umich.edu std::list<ThreadContext *> * tcWaitList; 3985952Ssaidi@eecs.umich.edu if (futex_map.count(uaddr)) { 3995952Ssaidi@eecs.umich.edu tcWaitList = futex_map.find(uaddr)->second; 4005952Ssaidi@eecs.umich.edu while (tcWaitList->size() > 0 && wokenUp < val) { 4015952Ssaidi@eecs.umich.edu tcWaitList->front()->activate(); 4025952Ssaidi@eecs.umich.edu tcWaitList->pop_front(); 4035952Ssaidi@eecs.umich.edu wokenUp++; 4045952Ssaidi@eecs.umich.edu } 4055952Ssaidi@eecs.umich.edu if(tcWaitList->empty()) { 4065952Ssaidi@eecs.umich.edu futex_map.erase(uaddr); 4075952Ssaidi@eecs.umich.edu delete tcWaitList; 4085952Ssaidi@eecs.umich.edu } 4095952Ssaidi@eecs.umich.edu } 4105952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 4115952Ssaidi@eecs.umich.edu "thread contexts\n", wokenUp); 4125952Ssaidi@eecs.umich.edu return wokenUp; 4135952Ssaidi@eecs.umich.edu } else { 4145952Ssaidi@eecs.umich.edu warn("sys_futex: op %d is not implemented, just returning...", op); 4155952Ssaidi@eecs.umich.edu return 0; 4165952Ssaidi@eecs.umich.edu } 4175952Ssaidi@eecs.umich.edu 4185952Ssaidi@eecs.umich.edu} 4195952Ssaidi@eecs.umich.edu 4205952Ssaidi@eecs.umich.edu 4215952Ssaidi@eecs.umich.edu/// Pseudo Funcs - These functions use a different return convension, 4225952Ssaidi@eecs.umich.edu/// returning a second value in a register other than the normal return register 4235952Ssaidi@eecs.umich.eduSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 4245952Ssaidi@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 4255952Ssaidi@eecs.umich.edu 4265952Ssaidi@eecs.umich.edu/// Target getpidPseudo() handler. 4275952Ssaidi@eecs.umich.eduSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 4285952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4295952Ssaidi@eecs.umich.edu 4305952Ssaidi@eecs.umich.edu/// Target getuidPseudo() handler. 4315952Ssaidi@eecs.umich.eduSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 4325952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4335952Ssaidi@eecs.umich.edu 4345952Ssaidi@eecs.umich.edu/// Target getgidPseudo() handler. 4355952Ssaidi@eecs.umich.eduSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4365952Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4375952Ssaidi@eecs.umich.edu 4385952Ssaidi@eecs.umich.edu 4395952Ssaidi@eecs.umich.edu/// A readable name for 1,000,000, for converting microseconds to seconds. 4405952Ssaidi@eecs.umich.educonst int one_million = 1000000; 4415952Ssaidi@eecs.umich.edu 4425952Ssaidi@eecs.umich.edu/// Approximate seconds since the epoch (1/1/1970). About a billion, 4435952Ssaidi@eecs.umich.edu/// by my reckoning. We want to keep this a constant (not use the 4445952Ssaidi@eecs.umich.edu/// real-world time) to keep simulations repeatable. 4455952Ssaidi@eecs.umich.educonst unsigned seconds_since_epoch = 1000000000; 4465952Ssaidi@eecs.umich.edu 4475952Ssaidi@eecs.umich.edu/// Helper function to convert current elapsed time to seconds and 4485952Ssaidi@eecs.umich.edu/// microseconds. 4495952Ssaidi@eecs.umich.edutemplate <class T1, class T2> 4505952Ssaidi@eecs.umich.eduvoid 4515952Ssaidi@eecs.umich.edugetElapsedTime(T1 &sec, T2 &usec) 4525952Ssaidi@eecs.umich.edu{ 4535952Ssaidi@eecs.umich.edu int elapsed_usecs = curTick() / SimClock::Int::us; 4545952Ssaidi@eecs.umich.edu sec = elapsed_usecs / one_million; 4555952Ssaidi@eecs.umich.edu usec = elapsed_usecs % one_million; 4565952Ssaidi@eecs.umich.edu} 4575952Ssaidi@eecs.umich.edu 4585952Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4595952Ssaidi@eecs.umich.edu// 4605952Ssaidi@eecs.umich.edu// The following emulation functions are generic, but need to be 4615952Ssaidi@eecs.umich.edu// templated to account for differences in types, constants, etc. 4625952Ssaidi@eecs.umich.edu// 4635952Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4645952Ssaidi@eecs.umich.edu 4655952Ssaidi@eecs.umich.edu#if NO_STAT64 4665952Ssaidi@eecs.umich.edu typedef struct stat hst_stat; 4675952Ssaidi@eecs.umich.edu typedef struct stat hst_stat64; 4685952Ssaidi@eecs.umich.edu#else 4695952Ssaidi@eecs.umich.edu typedef struct stat hst_stat; 4705952Ssaidi@eecs.umich.edu typedef struct stat64 hst_stat64; 4715952Ssaidi@eecs.umich.edu#endif 4725952Ssaidi@eecs.umich.edu 4735952Ssaidi@eecs.umich.edu//// Helper function to convert a host stat buffer to a target stat 4745952Ssaidi@eecs.umich.edu//// buffer. Also copies the target buffer out to the simulated 4755952Ssaidi@eecs.umich.edu//// memory space. Used by stat(), fstat(), and lstat(). 4765952Ssaidi@eecs.umich.edu 4775952Ssaidi@eecs.umich.edutemplate <typename target_stat, typename host_stat> 4785952Ssaidi@eecs.umich.edustatic void 4795952Ssaidi@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4805952Ssaidi@eecs.umich.edu{ 4815952Ssaidi@eecs.umich.edu using namespace TheISA; 4825952Ssaidi@eecs.umich.edu 4835952Ssaidi@eecs.umich.edu if (fakeTTY) 4845952Ssaidi@eecs.umich.edu tgt->st_dev = 0xA; 4855952Ssaidi@eecs.umich.edu else 4865952Ssaidi@eecs.umich.edu tgt->st_dev = host->st_dev; 4875952Ssaidi@eecs.umich.edu tgt->st_dev = TheISA::htog(tgt->st_dev); 4885952Ssaidi@eecs.umich.edu tgt->st_ino = host->st_ino; 4895952Ssaidi@eecs.umich.edu tgt->st_ino = TheISA::htog(tgt->st_ino); 4905952Ssaidi@eecs.umich.edu tgt->st_mode = host->st_mode; 4915952Ssaidi@eecs.umich.edu if (fakeTTY) { 4925952Ssaidi@eecs.umich.edu // Claim to be a character device 4935952Ssaidi@eecs.umich.edu tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4945952Ssaidi@eecs.umich.edu tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4955952Ssaidi@eecs.umich.edu } 4965952Ssaidi@eecs.umich.edu tgt->st_mode = TheISA::htog(tgt->st_mode); 4975952Ssaidi@eecs.umich.edu tgt->st_nlink = host->st_nlink; 4985952Ssaidi@eecs.umich.edu tgt->st_nlink = TheISA::htog(tgt->st_nlink); 4995952Ssaidi@eecs.umich.edu tgt->st_uid = host->st_uid; 5005952Ssaidi@eecs.umich.edu tgt->st_uid = TheISA::htog(tgt->st_uid); 5015952Ssaidi@eecs.umich.edu tgt->st_gid = host->st_gid; 5025952Ssaidi@eecs.umich.edu tgt->st_gid = TheISA::htog(tgt->st_gid); 5035952Ssaidi@eecs.umich.edu if (fakeTTY) 5045952Ssaidi@eecs.umich.edu tgt->st_rdev = 0x880d; 5055952Ssaidi@eecs.umich.edu else 5065952Ssaidi@eecs.umich.edu tgt->st_rdev = host->st_rdev; 5075952Ssaidi@eecs.umich.edu tgt->st_rdev = TheISA::htog(tgt->st_rdev); 5085952Ssaidi@eecs.umich.edu tgt->st_size = host->st_size; 5095952Ssaidi@eecs.umich.edu tgt->st_size = TheISA::htog(tgt->st_size); 5105952Ssaidi@eecs.umich.edu tgt->st_atimeX = host->st_atime; 5115952Ssaidi@eecs.umich.edu tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5125952Ssaidi@eecs.umich.edu tgt->st_mtimeX = host->st_mtime; 5135952Ssaidi@eecs.umich.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5145952Ssaidi@eecs.umich.edu tgt->st_ctimeX = host->st_ctime; 5155952Ssaidi@eecs.umich.edu tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5165952Ssaidi@eecs.umich.edu // Force the block size to be 8k. This helps to ensure buffered io works 5175952Ssaidi@eecs.umich.edu // consistently across different hosts. 5185952Ssaidi@eecs.umich.edu tgt->st_blksize = 0x2000; 5195952Ssaidi@eecs.umich.edu tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5205952Ssaidi@eecs.umich.edu tgt->st_blocks = host->st_blocks; 5215952Ssaidi@eecs.umich.edu tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5225952Ssaidi@eecs.umich.edu} 5235952Ssaidi@eecs.umich.edu 5245952Ssaidi@eecs.umich.edu// Same for stat64 5255952Ssaidi@eecs.umich.edu 5265952Ssaidi@eecs.umich.edutemplate <typename target_stat, typename host_stat64> 5275952Ssaidi@eecs.umich.edustatic void 5285952Ssaidi@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5295952Ssaidi@eecs.umich.edu{ 5305952Ssaidi@eecs.umich.edu using namespace TheISA; 5315952Ssaidi@eecs.umich.edu 5325952Ssaidi@eecs.umich.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5335952Ssaidi@eecs.umich.edu#if defined(STAT_HAVE_NSEC) 5345952Ssaidi@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5355952Ssaidi@eecs.umich.edu tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5365952Ssaidi@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5375952Ssaidi@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5385952Ssaidi@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5395952Ssaidi@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5405952Ssaidi@eecs.umich.edu#else 5415952Ssaidi@eecs.umich.edu tgt->st_atime_nsec = 0; 5425952Ssaidi@eecs.umich.edu tgt->st_mtime_nsec = 0; 5435952Ssaidi@eecs.umich.edu tgt->st_ctime_nsec = 0; 5445952Ssaidi@eecs.umich.edu#endif 5455952Ssaidi@eecs.umich.edu} 5465952Ssaidi@eecs.umich.edu 5475952Ssaidi@eecs.umich.edu//Here are a couple convenience functions 5485952Ssaidi@eecs.umich.edutemplate<class OS> 5495952Ssaidi@eecs.umich.edustatic void 5505952Ssaidi@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5515952Ssaidi@eecs.umich.edu hst_stat *host, bool fakeTTY = false) 5525952Ssaidi@eecs.umich.edu{ 5535952Ssaidi@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5545952Ssaidi@eecs.umich.edu tgt_stat_buf tgt(addr); 5555952Ssaidi@eecs.umich.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5565952Ssaidi@eecs.umich.edu tgt.copyOut(mem); 5575952Ssaidi@eecs.umich.edu} 5585952Ssaidi@eecs.umich.edu 5595952Ssaidi@eecs.umich.edutemplate<class OS> 5605952Ssaidi@eecs.umich.edustatic void 5615952Ssaidi@eecs.umich.educopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5625952Ssaidi@eecs.umich.edu hst_stat64 *host, bool fakeTTY = false) 5635952Ssaidi@eecs.umich.edu{ 5645952Ssaidi@eecs.umich.edu typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5655952Ssaidi@eecs.umich.edu tgt_stat_buf tgt(addr); 5665952Ssaidi@eecs.umich.edu convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5675952Ssaidi@eecs.umich.edu tgt.copyOut(mem); 5685952Ssaidi@eecs.umich.edu} 5695952Ssaidi@eecs.umich.edu 5705952Ssaidi@eecs.umich.edu/// Target ioctl() handler. For the most part, programs call ioctl() 5715952Ssaidi@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to 5725952Ssaidi@eecs.umich.edu/// do line or block buffering. We always claim that output fds are 5735952Ssaidi@eecs.umich.edu/// not TTYs to provide repeatable results. 5745952Ssaidi@eecs.umich.edutemplate <class OS> 5755952Ssaidi@eecs.umich.eduSyscallReturn 5765952Ssaidi@eecs.umich.eduioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5775952Ssaidi@eecs.umich.edu ThreadContext *tc) 5785952Ssaidi@eecs.umich.edu{ 5795952Ssaidi@eecs.umich.edu int index = 0; 5805952Ssaidi@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 5815952Ssaidi@eecs.umich.edu unsigned req = process->getSyscallArg(tc, index); 5825952Ssaidi@eecs.umich.edu 5835952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 5845952Ssaidi@eecs.umich.edu 5855952Ssaidi@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 5865952Ssaidi@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 5875952Ssaidi@eecs.umich.edu return -EBADF; 5885952Ssaidi@eecs.umich.edu } 5895952Ssaidi@eecs.umich.edu 5905952Ssaidi@eecs.umich.edu if (OS::isTtyReq(req)) { 5915952Ssaidi@eecs.umich.edu return -ENOTTY; 5925952Ssaidi@eecs.umich.edu } 5935952Ssaidi@eecs.umich.edu 5945952Ssaidi@eecs.umich.edu warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 5955952Ssaidi@eecs.umich.edu fd, req, tc->pcState()); 5965952Ssaidi@eecs.umich.edu return -ENOTTY; 5975952Ssaidi@eecs.umich.edu} 5985952Ssaidi@eecs.umich.edu 5995952Ssaidi@eecs.umich.edu/// Target open() handler. 6005952Ssaidi@eecs.umich.edutemplate <class OS> 6015952Ssaidi@eecs.umich.eduSyscallReturn 6025952Ssaidi@eecs.umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6035952Ssaidi@eecs.umich.edu ThreadContext *tc) 6045952Ssaidi@eecs.umich.edu{ 6055952Ssaidi@eecs.umich.edu std::string path; 6065952Ssaidi@eecs.umich.edu 6075952Ssaidi@eecs.umich.edu int index = 0; 6085952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 6095952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) 6105952Ssaidi@eecs.umich.edu return -EFAULT; 6115952Ssaidi@eecs.umich.edu 6125952Ssaidi@eecs.umich.edu if (path == "/dev/sysdev0") { 6135952Ssaidi@eecs.umich.edu // This is a memory-mapped high-resolution timer device on Alpha. 6145952Ssaidi@eecs.umich.edu // We don't support it, so just punt. 6155952Ssaidi@eecs.umich.edu warn("Ignoring open(%s, ...)\n", path); 6165952Ssaidi@eecs.umich.edu return -ENOENT; 6175952Ssaidi@eecs.umich.edu } 6185952Ssaidi@eecs.umich.edu 6195952Ssaidi@eecs.umich.edu int tgtFlags = process->getSyscallArg(tc, index); 6205952Ssaidi@eecs.umich.edu int mode = process->getSyscallArg(tc, index); 6215952Ssaidi@eecs.umich.edu int hostFlags = 0; 6225952Ssaidi@eecs.umich.edu 6235952Ssaidi@eecs.umich.edu // translate open flags 6245952Ssaidi@eecs.umich.edu for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 6255952Ssaidi@eecs.umich.edu if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 6265952Ssaidi@eecs.umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 6275952Ssaidi@eecs.umich.edu hostFlags |= OS::openFlagTable[i].hostFlag; 6285952Ssaidi@eecs.umich.edu } 6295952Ssaidi@eecs.umich.edu } 6305952Ssaidi@eecs.umich.edu 6315952Ssaidi@eecs.umich.edu // any target flags left? 6325952Ssaidi@eecs.umich.edu if (tgtFlags != 0) 6335952Ssaidi@eecs.umich.edu warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 6345952Ssaidi@eecs.umich.edu 6355952Ssaidi@eecs.umich.edu#ifdef __CYGWIN32__ 6365952Ssaidi@eecs.umich.edu hostFlags |= O_BINARY; 6375952Ssaidi@eecs.umich.edu#endif 6385952Ssaidi@eecs.umich.edu 6395952Ssaidi@eecs.umich.edu // Adjust path for current working directory 6405952Ssaidi@eecs.umich.edu path = process->fullPath(path); 6415952Ssaidi@eecs.umich.edu 6425952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 6435952Ssaidi@eecs.umich.edu 6445952Ssaidi@eecs.umich.edu int fd; 6455952Ssaidi@eecs.umich.edu int local_errno; 6465952Ssaidi@eecs.umich.edu if (startswith(path, "/proc/") || startswith(path, "/system/") || 6475952Ssaidi@eecs.umich.edu startswith(path, "/platform/") || startswith(path, "/sys/")) { 6485952Ssaidi@eecs.umich.edu // It's a proc/sys entry and requires special handling 6495952Ssaidi@eecs.umich.edu fd = OS::openSpecialFile(path, process, tc); 6505952Ssaidi@eecs.umich.edu local_errno = ENOENT; 6515952Ssaidi@eecs.umich.edu } else { 6525952Ssaidi@eecs.umich.edu // open the file 6535952Ssaidi@eecs.umich.edu fd = open(path.c_str(), hostFlags, mode); 6545952Ssaidi@eecs.umich.edu local_errno = errno; 6555952Ssaidi@eecs.umich.edu } 6565952Ssaidi@eecs.umich.edu 6575952Ssaidi@eecs.umich.edu if (fd == -1) 6585952Ssaidi@eecs.umich.edu return -local_errno; 6595952Ssaidi@eecs.umich.edu 6605952Ssaidi@eecs.umich.edu return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false); 6615952Ssaidi@eecs.umich.edu} 6625952Ssaidi@eecs.umich.edu 6635952Ssaidi@eecs.umich.edu/// Target sysinfo() handler. 6645952Ssaidi@eecs.umich.edutemplate <class OS> 6655952Ssaidi@eecs.umich.eduSyscallReturn 6665952Ssaidi@eecs.umich.edusysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6675952Ssaidi@eecs.umich.edu ThreadContext *tc) 6685952Ssaidi@eecs.umich.edu{ 6695952Ssaidi@eecs.umich.edu 6705952Ssaidi@eecs.umich.edu int index = 0; 6715952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::tgt_sysinfo> 6725952Ssaidi@eecs.umich.edu sysinfo(process->getSyscallArg(tc, index)); 6735952Ssaidi@eecs.umich.edu 6745952Ssaidi@eecs.umich.edu sysinfo->uptime=seconds_since_epoch; 6755952Ssaidi@eecs.umich.edu sysinfo->totalram=process->system->memSize(); 6765952Ssaidi@eecs.umich.edu 6775952Ssaidi@eecs.umich.edu sysinfo.copyOut(tc->getMemProxy()); 6785952Ssaidi@eecs.umich.edu 6795952Ssaidi@eecs.umich.edu return 0; 6805952Ssaidi@eecs.umich.edu} 6815952Ssaidi@eecs.umich.edu 6825952Ssaidi@eecs.umich.edu/// Target chmod() handler. 6835952Ssaidi@eecs.umich.edutemplate <class OS> 6845952Ssaidi@eecs.umich.eduSyscallReturn 6855952Ssaidi@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6865952Ssaidi@eecs.umich.edu ThreadContext *tc) 6875952Ssaidi@eecs.umich.edu{ 6885952Ssaidi@eecs.umich.edu std::string path; 6895952Ssaidi@eecs.umich.edu 6905952Ssaidi@eecs.umich.edu int index = 0; 6917823Ssteve.reinhardt@amd.com if (!tc->getMemProxy().tryReadString(path, 6925952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 6935952Ssaidi@eecs.umich.edu return -EFAULT; 6947823Ssteve.reinhardt@amd.com } 6955952Ssaidi@eecs.umich.edu 6965952Ssaidi@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 6975952Ssaidi@eecs.umich.edu mode_t hostMode = 0; 6985952Ssaidi@eecs.umich.edu 6995952Ssaidi@eecs.umich.edu // XXX translate mode flags via OS::something??? 7005952Ssaidi@eecs.umich.edu hostMode = mode; 7015952Ssaidi@eecs.umich.edu 7025952Ssaidi@eecs.umich.edu // Adjust path for current working directory 7035952Ssaidi@eecs.umich.edu path = process->fullPath(path); 7045952Ssaidi@eecs.umich.edu 7055952Ssaidi@eecs.umich.edu // do the chmod 7065952Ssaidi@eecs.umich.edu int result = chmod(path.c_str(), hostMode); 7075952Ssaidi@eecs.umich.edu if (result < 0) 7085952Ssaidi@eecs.umich.edu return -errno; 7095952Ssaidi@eecs.umich.edu 7105952Ssaidi@eecs.umich.edu return 0; 7115952Ssaidi@eecs.umich.edu} 7125952Ssaidi@eecs.umich.edu 7135952Ssaidi@eecs.umich.edu 7145952Ssaidi@eecs.umich.edu/// Target fchmod() handler. 7155952Ssaidi@eecs.umich.edutemplate <class OS> 7165952Ssaidi@eecs.umich.eduSyscallReturn 7175952Ssaidi@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7185952Ssaidi@eecs.umich.edu ThreadContext *tc) 7195952Ssaidi@eecs.umich.edu{ 7205952Ssaidi@eecs.umich.edu int index = 0; 7215952Ssaidi@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 7225952Ssaidi@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 7235952Ssaidi@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 7245952Ssaidi@eecs.umich.edu return -EBADF; 7255952Ssaidi@eecs.umich.edu } 7265952Ssaidi@eecs.umich.edu 7275952Ssaidi@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 7285952Ssaidi@eecs.umich.edu mode_t hostMode = 0; 7295952Ssaidi@eecs.umich.edu 7305952Ssaidi@eecs.umich.edu // XXX translate mode flags via OS::someting??? 7315952Ssaidi@eecs.umich.edu hostMode = mode; 7325952Ssaidi@eecs.umich.edu 7335952Ssaidi@eecs.umich.edu // do the fchmod 7345952Ssaidi@eecs.umich.edu int result = fchmod(process->sim_fd(fd), hostMode); 7355952Ssaidi@eecs.umich.edu if (result < 0) 7365952Ssaidi@eecs.umich.edu return -errno; 7375952Ssaidi@eecs.umich.edu 7385952Ssaidi@eecs.umich.edu return 0; 7395952Ssaidi@eecs.umich.edu} 7405952Ssaidi@eecs.umich.edu 7415952Ssaidi@eecs.umich.edu/// Target mremap() handler. 7425952Ssaidi@eecs.umich.edutemplate <class OS> 7435952Ssaidi@eecs.umich.eduSyscallReturn 7445952Ssaidi@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 7455952Ssaidi@eecs.umich.edu{ 7465952Ssaidi@eecs.umich.edu int index = 0; 7475952Ssaidi@eecs.umich.edu Addr start = process->getSyscallArg(tc, index); 7485952Ssaidi@eecs.umich.edu uint64_t old_length = process->getSyscallArg(tc, index); 7495952Ssaidi@eecs.umich.edu uint64_t new_length = process->getSyscallArg(tc, index); 7505952Ssaidi@eecs.umich.edu uint64_t flags = process->getSyscallArg(tc, index); 7515952Ssaidi@eecs.umich.edu 7525952Ssaidi@eecs.umich.edu if ((start % TheISA::VMPageSize != 0) || 7535952Ssaidi@eecs.umich.edu (new_length % TheISA::VMPageSize != 0)) { 7545952Ssaidi@eecs.umich.edu warn("mremap failing: arguments not page aligned"); 7555952Ssaidi@eecs.umich.edu return -EINVAL; 7565952Ssaidi@eecs.umich.edu } 7575952Ssaidi@eecs.umich.edu 7585952Ssaidi@eecs.umich.edu if (new_length > old_length) { 7595952Ssaidi@eecs.umich.edu if ((start + old_length) == process->mmap_end) { 7605952Ssaidi@eecs.umich.edu uint64_t diff = new_length - old_length; 7615952Ssaidi@eecs.umich.edu process->allocateMem(process->mmap_end, diff); 7625952Ssaidi@eecs.umich.edu process->mmap_end += diff; 7635952Ssaidi@eecs.umich.edu return start; 7645952Ssaidi@eecs.umich.edu } else { 7655952Ssaidi@eecs.umich.edu // sys/mman.h defined MREMAP_MAYMOVE 7665952Ssaidi@eecs.umich.edu if (!(flags & 1)) { 7675952Ssaidi@eecs.umich.edu warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 7685952Ssaidi@eecs.umich.edu return -ENOMEM; 7695952Ssaidi@eecs.umich.edu } else { 7705952Ssaidi@eecs.umich.edu process->pTable->remap(start, old_length, process->mmap_end); 7715952Ssaidi@eecs.umich.edu warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 7725952Ssaidi@eecs.umich.edu process->mmap_end, process->mmap_end + new_length, new_length); 7735952Ssaidi@eecs.umich.edu start = process->mmap_end; 7745952Ssaidi@eecs.umich.edu // add on the remaining unallocated pages 7755952Ssaidi@eecs.umich.edu process->allocateMem(start + old_length, 7765952Ssaidi@eecs.umich.edu new_length - old_length); 7775952Ssaidi@eecs.umich.edu process->mmap_end += new_length; 7785952Ssaidi@eecs.umich.edu warn("returning %08p as start\n", start); 7795952Ssaidi@eecs.umich.edu return start; 7805952Ssaidi@eecs.umich.edu } 7815952Ssaidi@eecs.umich.edu } 7825952Ssaidi@eecs.umich.edu } else { 7835952Ssaidi@eecs.umich.edu process->pTable->unmap(start + new_length, old_length - new_length); 7845952Ssaidi@eecs.umich.edu return start; 7855952Ssaidi@eecs.umich.edu } 7865952Ssaidi@eecs.umich.edu} 7875952Ssaidi@eecs.umich.edu 7885952Ssaidi@eecs.umich.edu/// Target stat() handler. 7895952Ssaidi@eecs.umich.edutemplate <class OS> 7905952Ssaidi@eecs.umich.eduSyscallReturn 7915952Ssaidi@eecs.umich.edustatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7925952Ssaidi@eecs.umich.edu ThreadContext *tc) 7935952Ssaidi@eecs.umich.edu{ 7945952Ssaidi@eecs.umich.edu std::string path; 7955952Ssaidi@eecs.umich.edu 7965952Ssaidi@eecs.umich.edu int index = 0; 7975952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 7985952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 7995952Ssaidi@eecs.umich.edu return -EFAULT; 8005952Ssaidi@eecs.umich.edu } 8015952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8025952Ssaidi@eecs.umich.edu 8035952Ssaidi@eecs.umich.edu // Adjust path for current working directory 8045952Ssaidi@eecs.umich.edu path = process->fullPath(path); 8055952Ssaidi@eecs.umich.edu 8065952Ssaidi@eecs.umich.edu struct stat hostBuf; 8075952Ssaidi@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 8085952Ssaidi@eecs.umich.edu 8095952Ssaidi@eecs.umich.edu if (result < 0) 8105952Ssaidi@eecs.umich.edu return -errno; 8115952Ssaidi@eecs.umich.edu 8125952Ssaidi@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 8135952Ssaidi@eecs.umich.edu 8145952Ssaidi@eecs.umich.edu return 0; 8155952Ssaidi@eecs.umich.edu} 8167823Ssteve.reinhardt@amd.com 8175952Ssaidi@eecs.umich.edu 8185952Ssaidi@eecs.umich.edu/// Target stat64() handler. 8195952Ssaidi@eecs.umich.edutemplate <class OS> 8205952Ssaidi@eecs.umich.eduSyscallReturn 8215952Ssaidi@eecs.umich.edustat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8225952Ssaidi@eecs.umich.edu ThreadContext *tc) 8235952Ssaidi@eecs.umich.edu{ 8245952Ssaidi@eecs.umich.edu std::string path; 8255952Ssaidi@eecs.umich.edu 8265952Ssaidi@eecs.umich.edu int index = 0; 8275952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 8285952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) 8295952Ssaidi@eecs.umich.edu return -EFAULT; 8305952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8315952Ssaidi@eecs.umich.edu 8325952Ssaidi@eecs.umich.edu // Adjust path for current working directory 8335952Ssaidi@eecs.umich.edu path = process->fullPath(path); 8345952Ssaidi@eecs.umich.edu 8355952Ssaidi@eecs.umich.edu#if NO_STAT64 8365952Ssaidi@eecs.umich.edu struct stat hostBuf; 8375952Ssaidi@eecs.umich.edu int result = stat(path.c_str(), &hostBuf); 8385952Ssaidi@eecs.umich.edu#else 8395952Ssaidi@eecs.umich.edu struct stat64 hostBuf; 8405952Ssaidi@eecs.umich.edu int result = stat64(path.c_str(), &hostBuf); 8415952Ssaidi@eecs.umich.edu#endif 8425952Ssaidi@eecs.umich.edu 8435952Ssaidi@eecs.umich.edu if (result < 0) 8445952Ssaidi@eecs.umich.edu return -errno; 8455952Ssaidi@eecs.umich.edu 8465952Ssaidi@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 8475952Ssaidi@eecs.umich.edu 8485952Ssaidi@eecs.umich.edu return 0; 8495952Ssaidi@eecs.umich.edu} 8505952Ssaidi@eecs.umich.edu 8515952Ssaidi@eecs.umich.edu 8525952Ssaidi@eecs.umich.edu/// Target fstat64() handler. 8535952Ssaidi@eecs.umich.edutemplate <class OS> 8545952Ssaidi@eecs.umich.eduSyscallReturn 8555952Ssaidi@eecs.umich.edufstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 8565952Ssaidi@eecs.umich.edu ThreadContext *tc) 8575952Ssaidi@eecs.umich.edu{ 8585952Ssaidi@eecs.umich.edu int index = 0; 8595952Ssaidi@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 8605952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8615952Ssaidi@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 8625952Ssaidi@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 8635952Ssaidi@eecs.umich.edu return -EBADF; 8645952Ssaidi@eecs.umich.edu } 8655952Ssaidi@eecs.umich.edu 8665952Ssaidi@eecs.umich.edu#if NO_STAT64 8675952Ssaidi@eecs.umich.edu struct stat hostBuf; 8685952Ssaidi@eecs.umich.edu int result = fstat(process->sim_fd(fd), &hostBuf); 8695952Ssaidi@eecs.umich.edu#else 8705952Ssaidi@eecs.umich.edu struct stat64 hostBuf; 8715952Ssaidi@eecs.umich.edu int result = fstat64(process->sim_fd(fd), &hostBuf); 8725952Ssaidi@eecs.umich.edu#endif 8735952Ssaidi@eecs.umich.edu 8745952Ssaidi@eecs.umich.edu if (result < 0) 8755952Ssaidi@eecs.umich.edu return -errno; 8765952Ssaidi@eecs.umich.edu 8775952Ssaidi@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 8785952Ssaidi@eecs.umich.edu 8795952Ssaidi@eecs.umich.edu return 0; 8805952Ssaidi@eecs.umich.edu} 8815952Ssaidi@eecs.umich.edu 8825952Ssaidi@eecs.umich.edu 8835952Ssaidi@eecs.umich.edu/// Target lstat() handler. 8845952Ssaidi@eecs.umich.edutemplate <class OS> 8855952Ssaidi@eecs.umich.eduSyscallReturn 8865952Ssaidi@eecs.umich.edulstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8875952Ssaidi@eecs.umich.edu ThreadContext *tc) 8885952Ssaidi@eecs.umich.edu{ 8895952Ssaidi@eecs.umich.edu std::string path; 8905952Ssaidi@eecs.umich.edu 8915952Ssaidi@eecs.umich.edu int index = 0; 8925952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 8935952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 8945952Ssaidi@eecs.umich.edu return -EFAULT; 8955952Ssaidi@eecs.umich.edu } 8965952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 8975952Ssaidi@eecs.umich.edu 8985952Ssaidi@eecs.umich.edu // Adjust path for current working directory 8995952Ssaidi@eecs.umich.edu path = process->fullPath(path); 9005952Ssaidi@eecs.umich.edu 9015952Ssaidi@eecs.umich.edu struct stat hostBuf; 9025952Ssaidi@eecs.umich.edu int result = lstat(path.c_str(), &hostBuf); 9035952Ssaidi@eecs.umich.edu 9045952Ssaidi@eecs.umich.edu if (result < 0) 9055952Ssaidi@eecs.umich.edu return -errno; 9065952Ssaidi@eecs.umich.edu 9075952Ssaidi@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9085952Ssaidi@eecs.umich.edu 9095952Ssaidi@eecs.umich.edu return 0; 9105952Ssaidi@eecs.umich.edu} 9115952Ssaidi@eecs.umich.edu 9125952Ssaidi@eecs.umich.edu/// Target lstat64() handler. 9135952Ssaidi@eecs.umich.edutemplate <class OS> 9145952Ssaidi@eecs.umich.eduSyscallReturn 9155952Ssaidi@eecs.umich.edulstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9165952Ssaidi@eecs.umich.edu ThreadContext *tc) 9175952Ssaidi@eecs.umich.edu{ 9185952Ssaidi@eecs.umich.edu std::string path; 9195952Ssaidi@eecs.umich.edu 9205952Ssaidi@eecs.umich.edu int index = 0; 9215952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 9225952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 9235952Ssaidi@eecs.umich.edu return -EFAULT; 9245952Ssaidi@eecs.umich.edu } 9255952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9265952Ssaidi@eecs.umich.edu 9275952Ssaidi@eecs.umich.edu // Adjust path for current working directory 9285952Ssaidi@eecs.umich.edu path = process->fullPath(path); 9295952Ssaidi@eecs.umich.edu 9305952Ssaidi@eecs.umich.edu#if NO_STAT64 9315952Ssaidi@eecs.umich.edu struct stat hostBuf; 9325952Ssaidi@eecs.umich.edu int result = lstat(path.c_str(), &hostBuf); 9335952Ssaidi@eecs.umich.edu#else 9345952Ssaidi@eecs.umich.edu struct stat64 hostBuf; 9355952Ssaidi@eecs.umich.edu int result = lstat64(path.c_str(), &hostBuf); 9365952Ssaidi@eecs.umich.edu#endif 9375952Ssaidi@eecs.umich.edu 9385952Ssaidi@eecs.umich.edu if (result < 0) 9395952Ssaidi@eecs.umich.edu return -errno; 9405952Ssaidi@eecs.umich.edu 9415952Ssaidi@eecs.umich.edu copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9425952Ssaidi@eecs.umich.edu 9435952Ssaidi@eecs.umich.edu return 0; 9445952Ssaidi@eecs.umich.edu} 9455952Ssaidi@eecs.umich.edu 9465952Ssaidi@eecs.umich.edu/// Target fstat() handler. 9475952Ssaidi@eecs.umich.edutemplate <class OS> 9485952Ssaidi@eecs.umich.eduSyscallReturn 9495952Ssaidi@eecs.umich.edufstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9505952Ssaidi@eecs.umich.edu ThreadContext *tc) 9515952Ssaidi@eecs.umich.edu{ 9525952Ssaidi@eecs.umich.edu int index = 0; 9535952Ssaidi@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 9545952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9555952Ssaidi@eecs.umich.edu 9565952Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 9575952Ssaidi@eecs.umich.edu 9585952Ssaidi@eecs.umich.edu if (fd < 0) 9595952Ssaidi@eecs.umich.edu return -EBADF; 9605952Ssaidi@eecs.umich.edu 9615952Ssaidi@eecs.umich.edu struct stat hostBuf; 9625952Ssaidi@eecs.umich.edu int result = fstat(fd, &hostBuf); 9635952Ssaidi@eecs.umich.edu 9645952Ssaidi@eecs.umich.edu if (result < 0) 9655952Ssaidi@eecs.umich.edu return -errno; 9665952Ssaidi@eecs.umich.edu 9675952Ssaidi@eecs.umich.edu copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 9685952Ssaidi@eecs.umich.edu 9695952Ssaidi@eecs.umich.edu return 0; 9705952Ssaidi@eecs.umich.edu} 9715952Ssaidi@eecs.umich.edu 9725952Ssaidi@eecs.umich.edu 9735952Ssaidi@eecs.umich.edu/// Target statfs() handler. 9745952Ssaidi@eecs.umich.edutemplate <class OS> 9755952Ssaidi@eecs.umich.eduSyscallReturn 9765952Ssaidi@eecs.umich.edustatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9775952Ssaidi@eecs.umich.edu ThreadContext *tc) 9785952Ssaidi@eecs.umich.edu{ 9795952Ssaidi@eecs.umich.edu std::string path; 9805952Ssaidi@eecs.umich.edu 9815952Ssaidi@eecs.umich.edu int index = 0; 9825952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 9835952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 9845952Ssaidi@eecs.umich.edu return -EFAULT; 9855952Ssaidi@eecs.umich.edu } 9865952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 9875952Ssaidi@eecs.umich.edu 9885952Ssaidi@eecs.umich.edu // Adjust path for current working directory 9895952Ssaidi@eecs.umich.edu path = process->fullPath(path); 9905952Ssaidi@eecs.umich.edu 9915952Ssaidi@eecs.umich.edu struct statfs hostBuf; 9925952Ssaidi@eecs.umich.edu int result = statfs(path.c_str(), &hostBuf); 9935952Ssaidi@eecs.umich.edu 9945952Ssaidi@eecs.umich.edu if (result < 0) 9955952Ssaidi@eecs.umich.edu return -errno; 9965952Ssaidi@eecs.umich.edu 9975952Ssaidi@eecs.umich.edu OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 9985952Ssaidi@eecs.umich.edu 9995952Ssaidi@eecs.umich.edu return 0; 10005952Ssaidi@eecs.umich.edu} 10015952Ssaidi@eecs.umich.edu 10025952Ssaidi@eecs.umich.edu 10035952Ssaidi@eecs.umich.edu/// Target fstatfs() handler. 10045952Ssaidi@eecs.umich.edutemplate <class OS> 10055952Ssaidi@eecs.umich.eduSyscallReturn 10065952Ssaidi@eecs.umich.edufstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10075952Ssaidi@eecs.umich.edu ThreadContext *tc) 10085952Ssaidi@eecs.umich.edu{ 10095952Ssaidi@eecs.umich.edu int index = 0; 10105952Ssaidi@eecs.umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 10115952Ssaidi@eecs.umich.edu Addr bufPtr = process->getSyscallArg(tc, index); 10125952Ssaidi@eecs.umich.edu 10135952Ssaidi@eecs.umich.edu if (fd < 0) 10145952Ssaidi@eecs.umich.edu return -EBADF; 10155952Ssaidi@eecs.umich.edu 10165952Ssaidi@eecs.umich.edu struct statfs hostBuf; 10175952Ssaidi@eecs.umich.edu int result = fstatfs(fd, &hostBuf); 10185952Ssaidi@eecs.umich.edu 10195952Ssaidi@eecs.umich.edu if (result < 0) 10205952Ssaidi@eecs.umich.edu return -errno; 10215952Ssaidi@eecs.umich.edu 10225952Ssaidi@eecs.umich.edu OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 10235952Ssaidi@eecs.umich.edu 10245952Ssaidi@eecs.umich.edu return 0; 10255952Ssaidi@eecs.umich.edu} 10265952Ssaidi@eecs.umich.edu 10275952Ssaidi@eecs.umich.edu 10285952Ssaidi@eecs.umich.edu/// Target writev() handler. 10295952Ssaidi@eecs.umich.edutemplate <class OS> 10305952Ssaidi@eecs.umich.eduSyscallReturn 10315952Ssaidi@eecs.umich.eduwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10325952Ssaidi@eecs.umich.edu ThreadContext *tc) 10335952Ssaidi@eecs.umich.edu{ 10345952Ssaidi@eecs.umich.edu int index = 0; 10355952Ssaidi@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 10365952Ssaidi@eecs.umich.edu if (fd < 0 || process->sim_fd(fd) < 0) { 10375952Ssaidi@eecs.umich.edu // doesn't map to any simulator fd: not a valid target fd 10385952Ssaidi@eecs.umich.edu return -EBADF; 10395952Ssaidi@eecs.umich.edu } 10405952Ssaidi@eecs.umich.edu 10415952Ssaidi@eecs.umich.edu SETranslatingPortProxy &p = tc->getMemProxy(); 10425952Ssaidi@eecs.umich.edu uint64_t tiov_base = process->getSyscallArg(tc, index); 10435952Ssaidi@eecs.umich.edu size_t count = process->getSyscallArg(tc, index); 10445952Ssaidi@eecs.umich.edu struct iovec hiov[count]; 10455952Ssaidi@eecs.umich.edu for (size_t i = 0; i < count; ++i) { 10465952Ssaidi@eecs.umich.edu typename OS::tgt_iovec tiov; 10475952Ssaidi@eecs.umich.edu 10485952Ssaidi@eecs.umich.edu p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 10495952Ssaidi@eecs.umich.edu (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 10505952Ssaidi@eecs.umich.edu hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 10515952Ssaidi@eecs.umich.edu hiov[i].iov_base = new char [hiov[i].iov_len]; 10525952Ssaidi@eecs.umich.edu p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 10535952Ssaidi@eecs.umich.edu hiov[i].iov_len); 10545952Ssaidi@eecs.umich.edu } 10555952Ssaidi@eecs.umich.edu 10565952Ssaidi@eecs.umich.edu int result = writev(process->sim_fd(fd), hiov, count); 10575952Ssaidi@eecs.umich.edu 10585952Ssaidi@eecs.umich.edu for (size_t i = 0; i < count; ++i) 10595952Ssaidi@eecs.umich.edu delete [] (char *)hiov[i].iov_base; 10605952Ssaidi@eecs.umich.edu 10615952Ssaidi@eecs.umich.edu if (result < 0) 10625952Ssaidi@eecs.umich.edu return -errno; 10635952Ssaidi@eecs.umich.edu 10645952Ssaidi@eecs.umich.edu return 0; 10655952Ssaidi@eecs.umich.edu} 10665952Ssaidi@eecs.umich.edu 10675952Ssaidi@eecs.umich.edu 10685952Ssaidi@eecs.umich.edu/// Target mmap() handler. 10695952Ssaidi@eecs.umich.edu/// 10705952Ssaidi@eecs.umich.edu/// We don't really handle mmap(). If the target is mmaping an 10715952Ssaidi@eecs.umich.edu/// anonymous region or /dev/zero, we can get away with doing basically 10725952Ssaidi@eecs.umich.edu/// nothing (since memory is initialized to zero and the simulator 10735952Ssaidi@eecs.umich.edu/// doesn't really check addresses anyway). 10745952Ssaidi@eecs.umich.edu/// 10755952Ssaidi@eecs.umich.edutemplate <class OS> 10765952Ssaidi@eecs.umich.eduSyscallReturn 10775952Ssaidi@eecs.umich.edummapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 10785952Ssaidi@eecs.umich.edu{ 10795952Ssaidi@eecs.umich.edu int index = 0; 10805952Ssaidi@eecs.umich.edu Addr start = p->getSyscallArg(tc, index); 10815952Ssaidi@eecs.umich.edu uint64_t length = p->getSyscallArg(tc, index); 10825952Ssaidi@eecs.umich.edu index++; // int prot = p->getSyscallArg(tc, index); 10835952Ssaidi@eecs.umich.edu int flags = p->getSyscallArg(tc, index); 10845952Ssaidi@eecs.umich.edu int tgt_fd = p->getSyscallArg(tc, index); 10855952Ssaidi@eecs.umich.edu // int offset = p->getSyscallArg(tc, index); 10865952Ssaidi@eecs.umich.edu 10875952Ssaidi@eecs.umich.edu if (length > 0x100000000ULL) 10885952Ssaidi@eecs.umich.edu warn("mmap length argument %#x is unreasonably large.\n", length); 10895952Ssaidi@eecs.umich.edu 10905952Ssaidi@eecs.umich.edu if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 10915952Ssaidi@eecs.umich.edu Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 10925952Ssaidi@eecs.umich.edu if (!fd_map || fd_map->fd < 0) { 10935952Ssaidi@eecs.umich.edu warn("mmap failing: target fd %d is not valid\n", tgt_fd); 10945952Ssaidi@eecs.umich.edu return -EBADF; 10955952Ssaidi@eecs.umich.edu } 10965952Ssaidi@eecs.umich.edu 10975952Ssaidi@eecs.umich.edu if (fd_map->filename != "/dev/zero") { 10985952Ssaidi@eecs.umich.edu // This is very likely broken, but leave a warning here 10995952Ssaidi@eecs.umich.edu // (rather than panic) in case /dev/zero is known by 11005952Ssaidi@eecs.umich.edu // another name on some platform 11015952Ssaidi@eecs.umich.edu warn("allowing mmap of file %s; mmap not supported on files" 11025952Ssaidi@eecs.umich.edu " other than /dev/zero\n", fd_map->filename); 11035952Ssaidi@eecs.umich.edu } 11045952Ssaidi@eecs.umich.edu } 11055952Ssaidi@eecs.umich.edu 11065952Ssaidi@eecs.umich.edu if ((start % TheISA::VMPageSize) != 0 || 11075952Ssaidi@eecs.umich.edu (length % TheISA::VMPageSize) != 0) { 11085952Ssaidi@eecs.umich.edu warn("mmap failing: arguments not page-aligned: " 11095952Ssaidi@eecs.umich.edu "start 0x%x length 0x%x", 11105952Ssaidi@eecs.umich.edu start, length); 11115952Ssaidi@eecs.umich.edu return -EINVAL; 11125952Ssaidi@eecs.umich.edu } 11135952Ssaidi@eecs.umich.edu 11145952Ssaidi@eecs.umich.edu // are we ok with clobbering existing mappings? only set this to 11155952Ssaidi@eecs.umich.edu // true if the user has been warned. 11165952Ssaidi@eecs.umich.edu bool clobber = false; 11175952Ssaidi@eecs.umich.edu 11185952Ssaidi@eecs.umich.edu // try to use the caller-provided address if there is one 11195952Ssaidi@eecs.umich.edu bool use_provided_address = (start != 0); 11205952Ssaidi@eecs.umich.edu 11215952Ssaidi@eecs.umich.edu if (use_provided_address) { 11225952Ssaidi@eecs.umich.edu // check to see if the desired address is already in use 11235952Ssaidi@eecs.umich.edu if (!p->pTable->isUnmapped(start, length)) { 11245952Ssaidi@eecs.umich.edu // there are existing mappings in the desired range 11255952Ssaidi@eecs.umich.edu // whether we clobber them or not depends on whether the caller 11265952Ssaidi@eecs.umich.edu // specified MAP_FIXED 11275952Ssaidi@eecs.umich.edu if (flags & OS::TGT_MAP_FIXED) { 11285952Ssaidi@eecs.umich.edu // MAP_FIXED specified: clobber existing mappings 11295952Ssaidi@eecs.umich.edu warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 11305952Ssaidi@eecs.umich.edu start); 11315952Ssaidi@eecs.umich.edu clobber = true; 11325952Ssaidi@eecs.umich.edu } else { 11335952Ssaidi@eecs.umich.edu // MAP_FIXED not specified: ignore suggested start address 11345952Ssaidi@eecs.umich.edu warn("mmap: ignoring suggested map address 0x%x\n", start); 11355952Ssaidi@eecs.umich.edu use_provided_address = false; 11365952Ssaidi@eecs.umich.edu } 11375952Ssaidi@eecs.umich.edu } 11385952Ssaidi@eecs.umich.edu } 11395952Ssaidi@eecs.umich.edu 11405952Ssaidi@eecs.umich.edu if (!use_provided_address) { 11415952Ssaidi@eecs.umich.edu // no address provided, or provided address unusable: 11425952Ssaidi@eecs.umich.edu // pick next address from our "mmap region" 11435952Ssaidi@eecs.umich.edu if (OS::mmapGrowsDown()) { 11445952Ssaidi@eecs.umich.edu start = p->mmap_end - length; 11455952Ssaidi@eecs.umich.edu p->mmap_end = start; 11465952Ssaidi@eecs.umich.edu } else { 11475952Ssaidi@eecs.umich.edu start = p->mmap_end; 11485952Ssaidi@eecs.umich.edu p->mmap_end += length; 11495952Ssaidi@eecs.umich.edu } 11505952Ssaidi@eecs.umich.edu } 11515952Ssaidi@eecs.umich.edu 11525952Ssaidi@eecs.umich.edu p->allocateMem(start, length, clobber); 11535952Ssaidi@eecs.umich.edu 11545952Ssaidi@eecs.umich.edu return start; 11555952Ssaidi@eecs.umich.edu} 11565952Ssaidi@eecs.umich.edu 11575952Ssaidi@eecs.umich.edu/// Target getrlimit() handler. 11585952Ssaidi@eecs.umich.edutemplate <class OS> 11595952Ssaidi@eecs.umich.eduSyscallReturn 11605952Ssaidi@eecs.umich.edugetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11615952Ssaidi@eecs.umich.edu ThreadContext *tc) 11625952Ssaidi@eecs.umich.edu{ 11635952Ssaidi@eecs.umich.edu int index = 0; 11645952Ssaidi@eecs.umich.edu unsigned resource = process->getSyscallArg(tc, index); 11655952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 11665952Ssaidi@eecs.umich.edu 11675952Ssaidi@eecs.umich.edu switch (resource) { 11685952Ssaidi@eecs.umich.edu case OS::TGT_RLIMIT_STACK: 11695952Ssaidi@eecs.umich.edu // max stack size in bytes: make up a number (8MB for now) 11705952Ssaidi@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 11715952Ssaidi@eecs.umich.edu rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11725952Ssaidi@eecs.umich.edu rlp->rlim_max = TheISA::htog(rlp->rlim_max); 11735952Ssaidi@eecs.umich.edu break; 11745952Ssaidi@eecs.umich.edu 11755952Ssaidi@eecs.umich.edu case OS::TGT_RLIMIT_DATA: 11765952Ssaidi@eecs.umich.edu // max data segment size in bytes: make up a number 11775952Ssaidi@eecs.umich.edu rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 11785952Ssaidi@eecs.umich.edu rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 11795952Ssaidi@eecs.umich.edu rlp->rlim_max = TheISA::htog(rlp->rlim_max); 11805952Ssaidi@eecs.umich.edu break; 11815952Ssaidi@eecs.umich.edu 11825952Ssaidi@eecs.umich.edu default: 11835952Ssaidi@eecs.umich.edu std::cerr << "getrlimitFunc: unimplemented resource " << resource 11845952Ssaidi@eecs.umich.edu << std::endl; 11855952Ssaidi@eecs.umich.edu abort(); 11865952Ssaidi@eecs.umich.edu break; 11875952Ssaidi@eecs.umich.edu } 11885952Ssaidi@eecs.umich.edu 11895952Ssaidi@eecs.umich.edu rlp.copyOut(tc->getMemProxy()); 11905952Ssaidi@eecs.umich.edu return 0; 11915952Ssaidi@eecs.umich.edu} 11925952Ssaidi@eecs.umich.edu 11935952Ssaidi@eecs.umich.edu/// Target gettimeofday() handler. 11945952Ssaidi@eecs.umich.edutemplate <class OS> 11955952Ssaidi@eecs.umich.eduSyscallReturn 11965952Ssaidi@eecs.umich.edugettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11975952Ssaidi@eecs.umich.edu ThreadContext *tc) 11985952Ssaidi@eecs.umich.edu{ 11995952Ssaidi@eecs.umich.edu int index = 0; 12005952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 12015952Ssaidi@eecs.umich.edu 12025952Ssaidi@eecs.umich.edu getElapsedTime(tp->tv_sec, tp->tv_usec); 12035952Ssaidi@eecs.umich.edu tp->tv_sec += seconds_since_epoch; 12045952Ssaidi@eecs.umich.edu tp->tv_sec = TheISA::htog(tp->tv_sec); 12055952Ssaidi@eecs.umich.edu tp->tv_usec = TheISA::htog(tp->tv_usec); 12065952Ssaidi@eecs.umich.edu 12075952Ssaidi@eecs.umich.edu tp.copyOut(tc->getMemProxy()); 12085952Ssaidi@eecs.umich.edu 12095952Ssaidi@eecs.umich.edu return 0; 12105952Ssaidi@eecs.umich.edu} 12115952Ssaidi@eecs.umich.edu 12125952Ssaidi@eecs.umich.edu 12135952Ssaidi@eecs.umich.edu/// Target utimes() handler. 12145952Ssaidi@eecs.umich.edutemplate <class OS> 12155952Ssaidi@eecs.umich.eduSyscallReturn 12165952Ssaidi@eecs.umich.eduutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12175952Ssaidi@eecs.umich.edu ThreadContext *tc) 12185952Ssaidi@eecs.umich.edu{ 12195952Ssaidi@eecs.umich.edu std::string path; 12205952Ssaidi@eecs.umich.edu 12215952Ssaidi@eecs.umich.edu int index = 0; 12225952Ssaidi@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 12235952Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) { 12245952Ssaidi@eecs.umich.edu return -EFAULT; 12255952Ssaidi@eecs.umich.edu } 12265952Ssaidi@eecs.umich.edu 12275952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::timeval [2]> 12285952Ssaidi@eecs.umich.edu tp(process->getSyscallArg(tc, index)); 12295952Ssaidi@eecs.umich.edu tp.copyIn(tc->getMemProxy()); 12305952Ssaidi@eecs.umich.edu 12315952Ssaidi@eecs.umich.edu struct timeval hostTimeval[2]; 12325952Ssaidi@eecs.umich.edu for (int i = 0; i < 2; ++i) 12335952Ssaidi@eecs.umich.edu { 12345952Ssaidi@eecs.umich.edu hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 12355952Ssaidi@eecs.umich.edu hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 12365952Ssaidi@eecs.umich.edu } 12375952Ssaidi@eecs.umich.edu 12385952Ssaidi@eecs.umich.edu // Adjust path for current working directory 12395952Ssaidi@eecs.umich.edu path = process->fullPath(path); 12405952Ssaidi@eecs.umich.edu 12415952Ssaidi@eecs.umich.edu int result = utimes(path.c_str(), hostTimeval); 12425952Ssaidi@eecs.umich.edu 12435952Ssaidi@eecs.umich.edu if (result < 0) 12445952Ssaidi@eecs.umich.edu return -errno; 12455952Ssaidi@eecs.umich.edu 12465952Ssaidi@eecs.umich.edu return 0; 12475952Ssaidi@eecs.umich.edu} 12485952Ssaidi@eecs.umich.edu/// Target getrusage() function. 12495952Ssaidi@eecs.umich.edutemplate <class OS> 12505952Ssaidi@eecs.umich.eduSyscallReturn 12515952Ssaidi@eecs.umich.edugetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12525952Ssaidi@eecs.umich.edu ThreadContext *tc) 12535952Ssaidi@eecs.umich.edu{ 12545952Ssaidi@eecs.umich.edu int index = 0; 12555952Ssaidi@eecs.umich.edu int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 12565952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 12575952Ssaidi@eecs.umich.edu 12585952Ssaidi@eecs.umich.edu rup->ru_utime.tv_sec = 0; 12595952Ssaidi@eecs.umich.edu rup->ru_utime.tv_usec = 0; 12605952Ssaidi@eecs.umich.edu rup->ru_stime.tv_sec = 0; 12615952Ssaidi@eecs.umich.edu rup->ru_stime.tv_usec = 0; 12625952Ssaidi@eecs.umich.edu rup->ru_maxrss = 0; 12635952Ssaidi@eecs.umich.edu rup->ru_ixrss = 0; 12645952Ssaidi@eecs.umich.edu rup->ru_idrss = 0; 12655952Ssaidi@eecs.umich.edu rup->ru_isrss = 0; 12665952Ssaidi@eecs.umich.edu rup->ru_minflt = 0; 12675952Ssaidi@eecs.umich.edu rup->ru_majflt = 0; 12685952Ssaidi@eecs.umich.edu rup->ru_nswap = 0; 12695952Ssaidi@eecs.umich.edu rup->ru_inblock = 0; 12705952Ssaidi@eecs.umich.edu rup->ru_oublock = 0; 12715952Ssaidi@eecs.umich.edu rup->ru_msgsnd = 0; 12725952Ssaidi@eecs.umich.edu rup->ru_msgrcv = 0; 12735952Ssaidi@eecs.umich.edu rup->ru_nsignals = 0; 12745952Ssaidi@eecs.umich.edu rup->ru_nvcsw = 0; 12755952Ssaidi@eecs.umich.edu rup->ru_nivcsw = 0; 12765952Ssaidi@eecs.umich.edu 12775952Ssaidi@eecs.umich.edu switch (who) { 12785952Ssaidi@eecs.umich.edu case OS::TGT_RUSAGE_SELF: 12795952Ssaidi@eecs.umich.edu getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 12805952Ssaidi@eecs.umich.edu rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 12815952Ssaidi@eecs.umich.edu rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 12825952Ssaidi@eecs.umich.edu break; 12835952Ssaidi@eecs.umich.edu 12845952Ssaidi@eecs.umich.edu case OS::TGT_RUSAGE_CHILDREN: 12855952Ssaidi@eecs.umich.edu // do nothing. We have no child processes, so they take no time. 12865952Ssaidi@eecs.umich.edu break; 12875952Ssaidi@eecs.umich.edu 12885952Ssaidi@eecs.umich.edu default: 12895952Ssaidi@eecs.umich.edu // don't really handle THREAD or CHILDREN, but just warn and 12905952Ssaidi@eecs.umich.edu // plow ahead 12915952Ssaidi@eecs.umich.edu warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 12925952Ssaidi@eecs.umich.edu who); 12935952Ssaidi@eecs.umich.edu } 12945952Ssaidi@eecs.umich.edu 12955952Ssaidi@eecs.umich.edu rup.copyOut(tc->getMemProxy()); 12965952Ssaidi@eecs.umich.edu 12975952Ssaidi@eecs.umich.edu return 0; 12985952Ssaidi@eecs.umich.edu} 12995952Ssaidi@eecs.umich.edu 13005952Ssaidi@eecs.umich.edu/// Target times() function. 13015952Ssaidi@eecs.umich.edutemplate <class OS> 13025952Ssaidi@eecs.umich.eduSyscallReturn 13035952Ssaidi@eecs.umich.edutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 13045952Ssaidi@eecs.umich.edu ThreadContext *tc) 13055952Ssaidi@eecs.umich.edu{ 13065952Ssaidi@eecs.umich.edu int index = 0; 13075952Ssaidi@eecs.umich.edu TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 13085952Ssaidi@eecs.umich.edu 13095952Ssaidi@eecs.umich.edu // Fill in the time structure (in clocks) 13105952Ssaidi@eecs.umich.edu int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 13115952Ssaidi@eecs.umich.edu bufp->tms_utime = clocks; 13125952Ssaidi@eecs.umich.edu bufp->tms_stime = 0; 13135952Ssaidi@eecs.umich.edu bufp->tms_cutime = 0; 13145952Ssaidi@eecs.umich.edu bufp->tms_cstime = 0; 13155952Ssaidi@eecs.umich.edu 13165952Ssaidi@eecs.umich.edu // Convert to host endianness 13175952Ssaidi@eecs.umich.edu bufp->tms_utime = TheISA::htog(bufp->tms_utime); 13185952Ssaidi@eecs.umich.edu 13195952Ssaidi@eecs.umich.edu // Write back 13205952Ssaidi@eecs.umich.edu bufp.copyOut(tc->getMemProxy()); 13215952Ssaidi@eecs.umich.edu 13225952Ssaidi@eecs.umich.edu // Return clock ticks since system boot 13235952Ssaidi@eecs.umich.edu return clocks; 13245952Ssaidi@eecs.umich.edu} 13255952Ssaidi@eecs.umich.edu 13265952Ssaidi@eecs.umich.edu/// Target time() function. 13275952Ssaidi@eecs.umich.edutemplate <class OS> 13285952Ssaidi@eecs.umich.eduSyscallReturn 13295952Ssaidi@eecs.umich.edutimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 13305952Ssaidi@eecs.umich.edu ThreadContext *tc) 13315952Ssaidi@eecs.umich.edu{ 13325952Ssaidi@eecs.umich.edu typename OS::time_t sec, usec; 13335952Ssaidi@eecs.umich.edu getElapsedTime(sec, usec); 13345952Ssaidi@eecs.umich.edu sec += seconds_since_epoch; 13355952Ssaidi@eecs.umich.edu 13365952Ssaidi@eecs.umich.edu int index = 0; 13375952Ssaidi@eecs.umich.edu Addr taddr = (Addr)process->getSyscallArg(tc, index); 13385952Ssaidi@eecs.umich.edu if(taddr != 0) { 13395952Ssaidi@eecs.umich.edu typename OS::time_t t = sec; 13405952Ssaidi@eecs.umich.edu t = TheISA::htog(t); 13415952Ssaidi@eecs.umich.edu SETranslatingPortProxy &p = tc->getMemProxy(); 13425952Ssaidi@eecs.umich.edu p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 13435952Ssaidi@eecs.umich.edu } 13445952Ssaidi@eecs.umich.edu return sec; 13455952Ssaidi@eecs.umich.edu} 13465952Ssaidi@eecs.umich.edu 13475952Ssaidi@eecs.umich.edu 13485952Ssaidi@eecs.umich.edu#endif // __SIM_SYSCALL_EMUL_HH__ 13495952Ssaidi@eecs.umich.edu