syscall_emul.hh revision 11380
12623SN/A/* 22623SN/A * Copyright (c) 2012-2013, 2015 ARM Limited 32623SN/A * Copyright (c) 2015 Advanced Micro Devices, Inc. 42623SN/A * All rights reserved 52623SN/A * 62623SN/A * The license below extends only to copyright in the software and shall 72623SN/A * not be construed as granting a license to any other intellectual 82623SN/A * property including but not limited to intellectual property relating 92623SN/A * to a hardware implementation of the functionality of the software 102623SN/A * licensed hereunder. You may use the software subject to the license 112623SN/A * terms below provided that you ensure that this notice is replicated 122623SN/A * unmodified and in its entirety in all distributions of the software, 132623SN/A * modified or unmodified, in source code or in binary form. 142623SN/A * 152623SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 162623SN/A * All rights reserved. 172623SN/A * 182623SN/A * Redistribution and use in source and binary forms, with or without 192623SN/A * modification, are permitted provided that the following conditions are 202623SN/A * met: redistributions of source code must retain the above copyright 212623SN/A * notice, this list of conditions and the following disclaimer; 222623SN/A * redistributions in binary form must reproduce the above copyright 232623SN/A * notice, this list of conditions and the following disclaimer in the 242623SN/A * documentation and/or other materials provided with the distribution; 252623SN/A * neither the name of the copyright holders nor the names of its 262623SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 313170Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325103Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 344040Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 373348Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 383348Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 394762Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402901Ssaidi@eecs.umich.edu * 412623SN/A * Authors: Steve Reinhardt 422623SN/A * Kevin Lim 432623SN/A */ 442623SN/A 452856Srdreslin@umich.edu#ifndef __SIM_SYSCALL_EMUL_HH__ 462856Srdreslin@umich.edu#define __SIM_SYSCALL_EMUL_HH__ 472856Srdreslin@umich.edu 482856Srdreslin@umich.edu#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 492856Srdreslin@umich.edu defined(__FreeBSD__) || defined(__CYGWIN__) || \ 502856Srdreslin@umich.edu defined(__NetBSD__)) 512856Srdreslin@umich.edu 522856Srdreslin@umich.edu/// 532856Srdreslin@umich.edu/// @file syscall_emul.hh 542856Srdreslin@umich.edu/// 552623SN/A/// This file defines objects used to emulate syscalls from the target 562623SN/A/// application on the host machine. 572623SN/A 582623SN/A#ifdef __CYGWIN32__ 592623SN/A#include <sys/fcntl.h> // for O_BINARY 602623SN/A#endif 612680Sktlim@umich.edu#include <sys/stat.h> 622680Sktlim@umich.edu#include <sys/time.h> 632623SN/A#include <sys/uio.h> 642623SN/A#include <fcntl.h> 652680Sktlim@umich.edu 662623SN/A#include <cerrno> 672623SN/A#include <string> 682623SN/A 692623SN/A#include "base/chunk_generator.hh" 702623SN/A#include "base/intmath.hh" // for RoundUp 713349Sbinkertn@umich.edu#include "base/misc.hh" 722623SN/A#include "base/trace.hh" 732623SN/A#include "base/types.hh" 742623SN/A#include "config/the_isa.hh" 752623SN/A#include "cpu/base.hh" 762623SN/A#include "cpu/thread_context.hh" 772623SN/A#include "debug/SyscallBase.hh" 783349Sbinkertn@umich.edu#include "debug/SyscallVerbose.hh" 792623SN/A#include "mem/page_table.hh" 803184Srdreslin@umich.edu#include "sim/byteswap.hh" 813184Srdreslin@umich.edu#include "sim/emul_driver.hh" 822623SN/A#include "sim/process.hh" 832623SN/A#include "sim/syscall_emul_buf.hh" 842623SN/A#include "sim/syscallreturn.hh" 852623SN/A#include "sim/system.hh" 862623SN/A 873647Srdreslin@umich.edu// This wrapper macro helps out with readability a bit. FLAGEXT specifies 883647Srdreslin@umich.edu// the verbosity and FMT is the message to be appended to the syscall 893647Srdreslin@umich.edu// header information. The syscall header information contains the cpuid 903647Srdreslin@umich.edu// and thread id. 913647Srdreslin@umich.edu#define DPRINTF_SYSCALL(FLAGEXT, FMT, ...) \ 922631SN/A DPRINTFS(Syscall##FLAGEXT, tc->getCpuPtr(), "T%d : syscall " FMT, \ 933647Srdreslin@umich.edu tc->threadId(), __VA_ARGS__) 942631SN/A 952623SN/A/// 962623SN/A/// System call descriptor. 972623SN/A/// 982948Ssaidi@eecs.umich.educlass SyscallDesc { 992948Ssaidi@eecs.umich.edu 1003349Sbinkertn@umich.edu public: 1012948Ssaidi@eecs.umich.edu 1022948Ssaidi@eecs.umich.edu /// Typedef for target syscall handler functions. 1032948Ssaidi@eecs.umich.edu typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 1042948Ssaidi@eecs.umich.edu LiveProcess *, ThreadContext *); 1052948Ssaidi@eecs.umich.edu 1062623SN/A const char *name; //!< Syscall name (e.g., "open"). 1075169Ssaidi@eecs.umich.edu FuncPtr funcPtr; //!< Pointer to emulation function. 1082623SN/A int flags; //!< Flags (see Flags enum). 1092623SN/A bool warned; //!< Have we warned about unimplemented syscall? 1103647Srdreslin@umich.edu 1113647Srdreslin@umich.edu /// Flag values for controlling syscall behavior. 1123647Srdreslin@umich.edu enum Flags { 1133647Srdreslin@umich.edu /// Don't set return regs according to funcPtr return value. 1142623SN/A /// Used for syscalls with non-standard return conventions 1152839Sktlim@umich.edu /// that explicitly set the ThreadContext regs (e.g., 1162867Sktlim@umich.edu /// sigreturn). 1173222Sktlim@umich.edu SuppressReturnValue = 1, 1182901Ssaidi@eecs.umich.edu WarnOnce = 2 1192623SN/A }; 1202623SN/A 1212623SN/A /// Constructor. 1222623SN/A SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 1232623SN/A : name(_name), funcPtr(_funcPtr), flags(_flags), warned(false) 1242623SN/A { 1252623SN/A } 1262623SN/A 1272623SN/A /// Emulate the syscall. Public interface for calling through funcPtr. 1282623SN/A void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1292915Sktlim@umich.edu 1302915Sktlim@umich.edu /// Is the WarnOnce flag set? 1312623SN/A bool warnOnce() const { return (flags & WarnOnce); } 1322623SN/A}; 1332623SN/A 1342623SN/A 1352623SN/A////////////////////////////////////////////////////////////////////// 1362623SN/A// 1372915Sktlim@umich.edu// The following emulation functions are generic enough that they 1382915Sktlim@umich.edu// don't need to be recompiled for different emulated OS's. They are 1392623SN/A// defined in sim/syscall_emul.cc. 1402798Sktlim@umich.edu// 1412798Sktlim@umich.edu////////////////////////////////////////////////////////////////////// 1422901Ssaidi@eecs.umich.edu 1432839Sktlim@umich.edu 1442798Sktlim@umich.edu/// Handler for unimplemented syscalls that we haven't thought about. 1452839Sktlim@umich.eduSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1462798Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1472798Sktlim@umich.edu 1482901Ssaidi@eecs.umich.edu/// Handler for unimplemented syscalls that we never intend to 1492901Ssaidi@eecs.umich.edu/// implement (signal handling, etc.) and should not affect the correct 1502798Sktlim@umich.edu/// behavior of the program. Print a warning only if the appropriate 1512839Sktlim@umich.edu/// trace flag is enabled. Return success to the target program. 1522839Sktlim@umich.eduSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1532901Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 1542798Sktlim@umich.edu 1552623SN/A/// Target exit() handler: terminate current context. 1562623SN/ASyscallReturn exitFunc(SyscallDesc *desc, int num, 1572623SN/A LiveProcess *p, ThreadContext *tc); 1582798Sktlim@umich.edu 1592623SN/A/// Target exit_group() handler: terminate simulation. (exit all threads) 1605221Ssaidi@eecs.umich.eduSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 1612798Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1624762Snate@binkert.org 1633201Shsul@eecs.umich.edu/// Target getpagesize() handler. 1642867Sktlim@umich.eduSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 1652867Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1662915Sktlim@umich.edu 1672915Sktlim@umich.edu/// Target brk() handler: set brk address. 1682915Sktlim@umich.eduSyscallReturn brkFunc(SyscallDesc *desc, int num, 1692867Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1702867Sktlim@umich.edu 1712867Sktlim@umich.edu/// Target close() handler. 1724471Sstever@eecs.umich.eduSyscallReturn closeFunc(SyscallDesc *desc, int num, 1732623SN/A LiveProcess *p, ThreadContext *tc); 1742798Sktlim@umich.edu 1752901Ssaidi@eecs.umich.edu/// Target read() handler. 1762798Sktlim@umich.eduSyscallReturn readFunc(SyscallDesc *desc, int num, 1772798Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1782798Sktlim@umich.edu 1792798Sktlim@umich.edu/// Target write() handler. 1802798Sktlim@umich.eduSyscallReturn writeFunc(SyscallDesc *desc, int num, 1812798Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1822798Sktlim@umich.edu 1835099Ssaidi@eecs.umich.edu/// Target lseek() handler. 1842867Sktlim@umich.eduSyscallReturn lseekFunc(SyscallDesc *desc, int num, 1852867Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1862867Sktlim@umich.edu 1872867Sktlim@umich.edu/// Target _llseek() handler. 1882867Sktlim@umich.eduSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 1892623SN/A LiveProcess *p, ThreadContext *tc); 1902623SN/A 1912623SN/A/// Target munmap() handler. 1922623SN/ASyscallReturn munmapFunc(SyscallDesc *desc, int num, 1932623SN/A LiveProcess *p, ThreadContext *tc); 1942623SN/A 1954192Sktlim@umich.edu/// Target gethostname() handler. 1962623SN/ASyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 1972680Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 1982623SN/A 1992680Sktlim@umich.edu/// Target getcwd() handler. 2002680Sktlim@umich.eduSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2012680Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 2022623SN/A 2032623SN/A/// Target readlink() handler. 2042623SN/ASyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2052623SN/A LiveProcess *p, ThreadContext *tc, 2063201Shsul@eecs.umich.edu int index = 0); 2073201Shsul@eecs.umich.eduSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2083201Shsul@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2093201Shsul@eecs.umich.edu 2105169Ssaidi@eecs.umich.edu/// Target unlink() handler. 2115169Ssaidi@eecs.umich.eduSyscallReturn unlinkHelper(SyscallDesc *desc, int num, 2125101Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc, 2132623SN/A int index); 2142623SN/ASyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2152623SN/A LiveProcess *p, ThreadContext *tc); 2162623SN/A 2172623SN/A/// Target mkdir() handler. 2182623SN/ASyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2195221Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2205221Ssaidi@eecs.umich.edu 2212623SN/A/// Target rename() handler. 2222683Sktlim@umich.eduSyscallReturn renameFunc(SyscallDesc *desc, int num, 2232623SN/A LiveProcess *p, ThreadContext *tc); 2242623SN/A 2252623SN/A 2262623SN/A/// Target truncate() handler. 2272623SN/ASyscallReturn truncateFunc(SyscallDesc *desc, int num, 2283686Sktlim@umich.edu LiveProcess *p, ThreadContext *tc); 2292623SN/A 2305100Ssaidi@eecs.umich.edu 2312623SN/A/// Target ftruncate() handler. 2322623SN/ASyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2332623SN/A LiveProcess *p, ThreadContext *tc); 2342623SN/A 2352623SN/A 2362623SN/A/// Target truncate64() handler. 2375221Ssaidi@eecs.umich.eduSyscallReturn truncate64Func(SyscallDesc *desc, int num, 2385221Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2392623SN/A 2402683Sktlim@umich.edu/// Target ftruncate64() handler. 2412623SN/ASyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2422644Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2432623SN/A 2442644Sstever@eecs.umich.edu 2452644Sstever@eecs.umich.edu/// Target umask() handler. 2462623SN/ASyscallReturn umaskFunc(SyscallDesc *desc, int num, 2472623SN/A LiveProcess *p, ThreadContext *tc); 2482623SN/A 2492623SN/A 2502623SN/A/// Target chown() handler. 2512623SN/ASyscallReturn chownFunc(SyscallDesc *desc, int num, 2522623SN/A LiveProcess *p, ThreadContext *tc); 2532623SN/A 2542623SN/A 2552623SN/A/// Target fchown() handler. 2563169Sstever@eecs.umich.eduSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2573169Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2585169Ssaidi@eecs.umich.edu 2592623SN/A/// Target dup() handler. 2602623SN/ASyscallReturn dupFunc(SyscallDesc *desc, int num, 2613169Sstever@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 2622623SN/A 2632623SN/A/// Target fnctl() handler. 2642623SN/ASyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2653169Sstever@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 2662623SN/A 2672623SN/A/// Target fcntl64() handler. 2682623SN/ASyscallReturn fcntl64Func(SyscallDesc *desc, int num, 2693349Sbinkertn@umich.edu LiveProcess *process, ThreadContext *tc); 2704878Sstever@eecs.umich.edu 2714878Sstever@eecs.umich.edu/// Target setuid() handler. 2724878Sstever@eecs.umich.eduSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2734878Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2743169Sstever@eecs.umich.edu 2752623SN/A/// Target getpid() handler. 2765103Ssaidi@eecs.umich.eduSyscallReturn getpidFunc(SyscallDesc *desc, int num, 2775103Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2785103Ssaidi@eecs.umich.edu 2795103Ssaidi@eecs.umich.edu/// Target getuid() handler. 2805103Ssaidi@eecs.umich.eduSyscallReturn getuidFunc(SyscallDesc *desc, int num, 2815103Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2825103Ssaidi@eecs.umich.edu 2832623SN/A/// Target getgid() handler. 2843169Sstever@eecs.umich.eduSyscallReturn getgidFunc(SyscallDesc *desc, int num, 2852623SN/A LiveProcess *p, ThreadContext *tc); 2862623SN/A 2873169Sstever@eecs.umich.edu/// Target getppid() handler. 2882623SN/ASyscallReturn getppidFunc(SyscallDesc *desc, int num, 2892623SN/A LiveProcess *p, ThreadContext *tc); 2904200Ssaidi@eecs.umich.edu 2914200Ssaidi@eecs.umich.edu/// Target geteuid() handler. 2924200Ssaidi@eecs.umich.eduSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 2934200Ssaidi@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 2943658Sktlim@umich.edu 2953658Sktlim@umich.edu/// Target getegid() handler. 2962623SN/ASyscallReturn getegidFunc(SyscallDesc *desc, int num, 2972623SN/A LiveProcess *p, ThreadContext *tc); 2982623SN/A 2992623SN/A/// Target clone() handler. 3002623SN/ASyscallReturn cloneFunc(SyscallDesc *desc, int num, 3015177Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3025177Sgblack@eecs.umich.edu 3035177Sgblack@eecs.umich.edu/// Target access() handler 3045177Sgblack@eecs.umich.eduSyscallReturn accessFunc(SyscallDesc *desc, int num, 3055177Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 3065177Sgblack@eecs.umich.eduSyscallReturn accessFunc(SyscallDesc *desc, int num, 3075177Sgblack@eecs.umich.edu LiveProcess *p, ThreadContext *tc, 3085177Sgblack@eecs.umich.edu int index); 3095177Sgblack@eecs.umich.edu 3105177Sgblack@eecs.umich.edu/// Futex system call 3115177Sgblack@eecs.umich.edu/// Implemented by Daniel Sanchez 3125177Sgblack@eecs.umich.edu/// Used by printf's in multi-threaded apps 3135177Sgblack@eecs.umich.edutemplate <class OS> 3145177Sgblack@eecs.umich.eduSyscallReturn 3155177Sgblack@eecs.umich.edufutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3165177Sgblack@eecs.umich.edu ThreadContext *tc) 3175177Sgblack@eecs.umich.edu{ 3185177Sgblack@eecs.umich.edu int index_uaddr = 0; 3195177Sgblack@eecs.umich.edu int index_op = 1; 3205177Sgblack@eecs.umich.edu int index_val = 2; 3212623SN/A int index_timeout = 3; 3222623SN/A 3232623SN/A uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3242623SN/A int op = process->getSyscallArg(tc, index_op); 3254040Ssaidi@eecs.umich.edu int val = process->getSyscallArg(tc, index_val); 3264040Ssaidi@eecs.umich.edu uint64_t timeout = process->getSyscallArg(tc, index_timeout); 3274040Ssaidi@eecs.umich.edu 3284040Ssaidi@eecs.umich.edu std::map<uint64_t, std::list<ThreadContext *> * > 3294115Ssaidi@eecs.umich.edu &futex_map = tc->getSystemPtr()->futexMap; 3304115Ssaidi@eecs.umich.edu 3314115Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 3324115Ssaidi@eecs.umich.edu uaddr, op, val); 3332623SN/A 3342623SN/A op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 3352623SN/A 3362623SN/A if (op == OS::TGT_FUTEX_WAIT) { 3372623SN/A if (timeout != 0) { 3382623SN/A warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 3392623SN/A "we'll wait indefinitely"); 3402623SN/A } 3412623SN/A 3422623SN/A uint8_t *buf = new uint8_t[sizeof(int)]; 3432623SN/A tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3442623SN/A int mem_val = *((int *)buf); 3452623SN/A delete[] buf; 3462623SN/A 3472623SN/A if (val != mem_val) { 3482623SN/A DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 3492623SN/A "expected: %d\n", mem_val, val); 3502623SN/A return -OS::TGT_EWOULDBLOCK; 3512623SN/A } 3522623SN/A 3532623SN/A // Queue the thread context 3542623SN/A std::list<ThreadContext *> * tcWaitList; 3552623SN/A if (futex_map.count(uaddr)) { 3562623SN/A tcWaitList = futex_map.find(uaddr)->second; 3572623SN/A } else { 3582623SN/A tcWaitList = new std::list<ThreadContext *>(); 3592623SN/A futex_map.insert(std::pair< uint64_t, 3602623SN/A std::list<ThreadContext *> * >(uaddr, tcWaitList)); 3612623SN/A } 3622623SN/A tcWaitList->push_back(tc); 3632623SN/A DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 3642623SN/A "thread context\n"); 3652623SN/A tc->suspend(); 3662623SN/A return 0; 3672623SN/A } else if (op == OS::TGT_FUTEX_WAKE){ 3682623SN/A int wokenUp = 0; 3692623SN/A std::list<ThreadContext *> * tcWaitList; 3702623SN/A if (futex_map.count(uaddr)) { 3712623SN/A tcWaitList = futex_map.find(uaddr)->second; 3722623SN/A while (tcWaitList->size() > 0 && wokenUp < val) { 3732623SN/A tcWaitList->front()->activate(); 3742623SN/A tcWaitList->pop_front(); 3752623SN/A wokenUp++; 3763169Sstever@eecs.umich.edu } 3773169Sstever@eecs.umich.edu if (tcWaitList->empty()) { 3785169Ssaidi@eecs.umich.edu futex_map.erase(uaddr); 3792623SN/A delete tcWaitList; 3804040Ssaidi@eecs.umich.edu } 3814040Ssaidi@eecs.umich.edu } 3824040Ssaidi@eecs.umich.edu DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 3834040Ssaidi@eecs.umich.edu "thread contexts\n", wokenUp); 3842623SN/A return wokenUp; 3853169Sstever@eecs.umich.edu } else { 3863169Sstever@eecs.umich.edu warn("sys_futex: op %d is not implemented, just returning...", op); 3872623SN/A return 0; 3882623SN/A } 3894878Sstever@eecs.umich.edu 3903170Sstever@eecs.umich.edu} 3913170Sstever@eecs.umich.edu 3923170Sstever@eecs.umich.edu 3934878Sstever@eecs.umich.edu/// Pseudo Funcs - These functions use a different return convension, 3943170Sstever@eecs.umich.edu/// returning a second value in a register other than the normal return register 3954878Sstever@eecs.umich.eduSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 3964878Sstever@eecs.umich.edu LiveProcess *process, ThreadContext *tc); 3974878Sstever@eecs.umich.edu 3984878Sstever@eecs.umich.edu/// Target getpidPseudo() handler. 3994878Sstever@eecs.umich.eduSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 4004878Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4013170Sstever@eecs.umich.edu 4024584Ssaidi@eecs.umich.edu/// Target getuidPseudo() handler. 4034881Sstever@eecs.umich.eduSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 4044881Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4054881Sstever@eecs.umich.edu 4064881Sstever@eecs.umich.edu/// Target getgidPseudo() handler. 4074881Sstever@eecs.umich.eduSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4084881Sstever@eecs.umich.edu LiveProcess *p, ThreadContext *tc); 4093170Sstever@eecs.umich.edu 4103170Sstever@eecs.umich.edu 4115103Ssaidi@eecs.umich.edu/// A readable name for 1,000,000, for converting microseconds to seconds. 4125103Ssaidi@eecs.umich.educonst int one_million = 1000000; 4135103Ssaidi@eecs.umich.edu/// A readable name for 1,000,000,000, for converting nanoseconds to seconds. 4145103Ssaidi@eecs.umich.educonst int one_billion = 1000000000; 4155103Ssaidi@eecs.umich.edu 4165103Ssaidi@eecs.umich.edu/// Approximate seconds since the epoch (1/1/1970). About a billion, 4175103Ssaidi@eecs.umich.edu/// by my reckoning. We want to keep this a constant (not use the 4185103Ssaidi@eecs.umich.edu/// real-world time) to keep simulations repeatable. 4193170Sstever@eecs.umich.educonst unsigned seconds_since_epoch = 1000000000; 4203170Sstever@eecs.umich.edu 4213170Sstever@eecs.umich.edu/// Helper function to convert current elapsed time to seconds and 4223170Sstever@eecs.umich.edu/// microseconds. 4233170Sstever@eecs.umich.edutemplate <class T1, class T2> 4243170Sstever@eecs.umich.eduvoid 4252623SN/AgetElapsedTimeMicro(T1 &sec, T2 &usec) 4264200Ssaidi@eecs.umich.edu{ 4274200Ssaidi@eecs.umich.edu uint64_t elapsed_usecs = curTick() / SimClock::Int::us; 4284200Ssaidi@eecs.umich.edu sec = elapsed_usecs / one_million; 4293658Sktlim@umich.edu usec = elapsed_usecs % one_million; 4303658Sktlim@umich.edu} 4312623SN/A 4322623SN/A/// Helper function to convert current elapsed time to seconds and 4332623SN/A/// nanoseconds. 4342623SN/Atemplate <class T1, class T2> 4352623SN/Avoid 4362623SN/AgetElapsedTimeNano(T1 &sec, T2 &nsec) 4372623SN/A{ 4382623SN/A uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns; 4395177Sgblack@eecs.umich.edu sec = elapsed_nsecs / one_billion; 4405177Sgblack@eecs.umich.edu nsec = elapsed_nsecs % one_billion; 4415177Sgblack@eecs.umich.edu} 4425177Sgblack@eecs.umich.edu 4435177Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4445177Sgblack@eecs.umich.edu// 4455177Sgblack@eecs.umich.edu// The following emulation functions are generic, but need to be 4465177Sgblack@eecs.umich.edu// templated to account for differences in types, constants, etc. 4475177Sgblack@eecs.umich.edu// 4485177Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////// 4495177Sgblack@eecs.umich.edu 4505177Sgblack@eecs.umich.edu#if NO_STAT64 4515177Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4525177Sgblack@eecs.umich.edu typedef struct stat hst_stat64; 4535177Sgblack@eecs.umich.edu#else 4545177Sgblack@eecs.umich.edu typedef struct stat hst_stat; 4555177Sgblack@eecs.umich.edu typedef struct stat64 hst_stat64; 4565177Sgblack@eecs.umich.edu#endif 4575177Sgblack@eecs.umich.edu 4585177Sgblack@eecs.umich.edu//// Helper function to convert a host stat buffer to a target stat 4592623SN/A//// buffer. Also copies the target buffer out to the simulated 4602623SN/A//// memory space. Used by stat(), fstat(), and lstat(). 4612623SN/A 4622623SN/Atemplate <typename target_stat, typename host_stat> 4634224Sgblack@eecs.umich.edustatic void 4644224Sgblack@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4654224Sgblack@eecs.umich.edu{ 4664224Sgblack@eecs.umich.edu using namespace TheISA; 4674224Sgblack@eecs.umich.edu 4684224Sgblack@eecs.umich.edu if (fakeTTY) 4694224Sgblack@eecs.umich.edu tgt->st_dev = 0xA; 4704224Sgblack@eecs.umich.edu else 4714224Sgblack@eecs.umich.edu tgt->st_dev = host->st_dev; 4724224Sgblack@eecs.umich.edu tgt->st_dev = TheISA::htog(tgt->st_dev); 4732623SN/A tgt->st_ino = host->st_ino; 4742623SN/A tgt->st_ino = TheISA::htog(tgt->st_ino); 4752623SN/A tgt->st_mode = host->st_mode; 4762623SN/A if (fakeTTY) { 4772623SN/A // Claim to be a character device 4782623SN/A tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4792623SN/A tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4802623SN/A } 4812623SN/A tgt->st_mode = TheISA::htog(tgt->st_mode); 4822623SN/A tgt->st_nlink = host->st_nlink; 4832623SN/A tgt->st_nlink = TheISA::htog(tgt->st_nlink); 4842623SN/A tgt->st_uid = host->st_uid; 4852623SN/A tgt->st_uid = TheISA::htog(tgt->st_uid); 4862623SN/A tgt->st_gid = host->st_gid; 4872623SN/A tgt->st_gid = TheISA::htog(tgt->st_gid); 4882623SN/A if (fakeTTY) 4892623SN/A tgt->st_rdev = 0x880d; 4902623SN/A else 4912623SN/A tgt->st_rdev = host->st_rdev; 4922623SN/A tgt->st_rdev = TheISA::htog(tgt->st_rdev); 4932623SN/A tgt->st_size = host->st_size; 4942623SN/A tgt->st_size = TheISA::htog(tgt->st_size); 4952623SN/A tgt->st_atimeX = host->st_atime; 4962623SN/A tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 4972623SN/A tgt->st_mtimeX = host->st_mtime; 4982623SN/A tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 4992623SN/A tgt->st_ctimeX = host->st_ctime; 5002623SN/A tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5012623SN/A // Force the block size to be 8k. This helps to ensure buffered io works 5022623SN/A // consistently across different hosts. 5032623SN/A tgt->st_blksize = 0x2000; 5042623SN/A tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5052623SN/A tgt->st_blocks = host->st_blocks; 5062623SN/A tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5072623SN/A} 5082623SN/A 5092623SN/A// Same for stat64 5102623SN/A 5112623SN/Atemplate <typename target_stat, typename host_stat64> 5122623SN/Astatic void 5132623SN/AconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5142623SN/A{ 5152623SN/A using namespace TheISA; 5162623SN/A 5172623SN/A convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5182623SN/A#if defined(STAT_HAVE_NSEC) 5195221Ssaidi@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5205221Ssaidi@eecs.umich.edu tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5213387Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5223387Sgblack@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5232631SN/A tgt->st_ctime_nsec = host->st_ctime_nsec; 5242663Sstever@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5255169Ssaidi@eecs.umich.edu#else 5262662Sstever@eecs.umich.edu tgt->st_atime_nsec = 0; 5272623SN/A tgt->st_mtime_nsec = 0; 5284022Sstever@eecs.umich.edu tgt->st_ctime_nsec = 0; 5292623SN/A#endif 5302623SN/A} 5312623SN/A 5322630SN/A//Here are a couple convenience functions 5332623SN/Atemplate<class OS> 5342623SN/Astatic void 5352623SN/AcopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5362623SN/A hst_stat *host, bool fakeTTY = false) 5372623SN/A{ 5382623SN/A typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5392623SN/A tgt_stat_buf tgt(addr); 5402623SN/A convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5412623SN/A tgt.copyOut(mem); 5423658Sktlim@umich.edu} 5433658Sktlim@umich.edu 5442644Sstever@eecs.umich.edutemplate<class OS> 5452644Sstever@eecs.umich.edustatic void 5462623SN/AcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5473222Sktlim@umich.edu hst_stat64 *host, bool fakeTTY = false) 5485099Ssaidi@eecs.umich.edu{ 5493222Sktlim@umich.edu typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5502623SN/A tgt_stat_buf tgt(addr); 5512623SN/A convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5522623SN/A tgt.copyOut(mem); 5532623SN/A} 5542644Sstever@eecs.umich.edu 5552623SN/A/// Target ioctl() handler. For the most part, programs call ioctl() 5562623SN/A/// only to find out if their stdout is a tty, to determine whether to 5572623SN/A/// do line or block buffering. We always claim that output fds are 5582631SN/A/// not TTYs to provide repeatable results. 5592631SN/Atemplate <class OS> 5602631SN/ASyscallReturn 5612631SN/AioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5622631SN/A ThreadContext *tc) 5632631SN/A{ 5642623SN/A int index = 0; 5652623SN/A int tgt_fd = process->getSyscallArg(tc, index); 5662623SN/A unsigned req = process->getSyscallArg(tc, index); 5672623SN/A 5683349Sbinkertn@umich.edu DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req); 5692623SN/A 5705221Ssaidi@eecs.umich.edu FDEntry *fde = process->getFDEntry(tgt_fd); 5715221Ssaidi@eecs.umich.edu 5722623SN/A if (fde == NULL) { 5732623SN/A // doesn't map to any simulator fd: not a valid target fd 5744870Sstever@eecs.umich.edu return -EBADF; 5752623SN/A } 5762798Sktlim@umich.edu 5772623SN/A if (fde->driver != NULL) { 5782644Sstever@eecs.umich.edu return fde->driver->ioctl(process, tc, req); 5795099Ssaidi@eecs.umich.edu } 5803222Sktlim@umich.edu 5813222Sktlim@umich.edu if (OS::isTtyReq(req)) { 5822839Sktlim@umich.edu return -ENOTTY; 5833658Sktlim@umich.edu } 5843658Sktlim@umich.edu 5853658Sktlim@umich.edu warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 5862839Sktlim@umich.edu tgt_fd, req, tc->pcState()); 5872798Sktlim@umich.edu return -ENOTTY; 5882798Sktlim@umich.edu} 5892798Sktlim@umich.edu 5902623SN/Atemplate <class OS> 5912644Sstever@eecs.umich.edustatic SyscallReturn 5922623SN/AopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5932623SN/A ThreadContext *tc, int index) 5943170Sstever@eecs.umich.edu{ 5953170Sstever@eecs.umich.edu std::string path; 5963170Sstever@eecs.umich.edu 5973170Sstever@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 5982644Sstever@eecs.umich.edu process->getSyscallArg(tc, index))) 5993170Sstever@eecs.umich.edu return -EFAULT; 6003170Sstever@eecs.umich.edu 6013170Sstever@eecs.umich.edu int tgtFlags = process->getSyscallArg(tc, index); 6023170Sstever@eecs.umich.edu int mode = process->getSyscallArg(tc, index); 6033170Sstever@eecs.umich.edu int hostFlags = 0; 6043170Sstever@eecs.umich.edu 6053170Sstever@eecs.umich.edu // translate open flags 6063170Sstever@eecs.umich.edu for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 6074998Sgblack@eecs.umich.edu if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 6084998Sgblack@eecs.umich.edu tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 6094998Sgblack@eecs.umich.edu hostFlags |= OS::openFlagTable[i].hostFlag; 6104998Sgblack@eecs.umich.edu } 6115001Sgblack@eecs.umich.edu } 6125001Sgblack@eecs.umich.edu 6135001Sgblack@eecs.umich.edu // any target flags left? 6145001Sgblack@eecs.umich.edu if (tgtFlags != 0) 6153170Sstever@eecs.umich.edu warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 6164998Sgblack@eecs.umich.edu 6172644Sstever@eecs.umich.edu#ifdef __CYGWIN32__ 6185103Ssaidi@eecs.umich.edu hostFlags |= O_BINARY; 6195103Ssaidi@eecs.umich.edu#endif 6205103Ssaidi@eecs.umich.edu 6215103Ssaidi@eecs.umich.edu // Adjust path for current working directory 6222644Sstever@eecs.umich.edu path = process->fullPath(path); 6232644Sstever@eecs.umich.edu 6242623SN/A DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 6252623SN/A 6262623SN/A if (startswith(path, "/dev/")) { 6274998Sgblack@eecs.umich.edu std::string filename = path.substr(strlen("/dev/")); 6284998Sgblack@eecs.umich.edu if (filename == "sysdev0") { 6294998Sgblack@eecs.umich.edu // This is a memory-mapped high-resolution timer device on Alpha. 6304998Sgblack@eecs.umich.edu // We don't support it, so just punt. 6315001Sgblack@eecs.umich.edu warn("Ignoring open(%s, ...)\n", path); 6325001Sgblack@eecs.umich.edu return -ENOENT; 6335001Sgblack@eecs.umich.edu } 6345001Sgblack@eecs.umich.edu 6355001Sgblack@eecs.umich.edu EmulatedDriver *drv = process->findDriver(filename); 6364998Sgblack@eecs.umich.edu if (drv != NULL) { 6372644Sstever@eecs.umich.edu // the driver's open method will allocate a fd from the 6385103Ssaidi@eecs.umich.edu // process if necessary. 6395103Ssaidi@eecs.umich.edu return drv->open(process, tc, mode, hostFlags); 6405103Ssaidi@eecs.umich.edu } 6415103Ssaidi@eecs.umich.edu 6422644Sstever@eecs.umich.edu // fall through here for pass through to host devices, such as 6432623SN/A // /dev/zero 6443658Sktlim@umich.edu } 6453658Sktlim@umich.edu 6463658Sktlim@umich.edu int fd; 6472623SN/A int local_errno; 6482623SN/A if (startswith(path, "/proc/") || startswith(path, "/system/") || 6492948Ssaidi@eecs.umich.edu startswith(path, "/platform/") || startswith(path, "/sys/")) { 6502948Ssaidi@eecs.umich.edu // It's a proc/sys entry and requires special handling 6512948Ssaidi@eecs.umich.edu fd = OS::openSpecialFile(path, process, tc); 6522948Ssaidi@eecs.umich.edu local_errno = ENOENT; 6532948Ssaidi@eecs.umich.edu } else { 6542623SN/A // open the file 6552623SN/A fd = open(path.c_str(), hostFlags, mode); 6563349Sbinkertn@umich.edu local_errno = errno; 6572623SN/A } 6584986Ssaidi@eecs.umich.edu 6593310Srdreslin@umich.edu if (fd == -1) 6604584Ssaidi@eecs.umich.edu return -local_errno; 6612948Ssaidi@eecs.umich.edu 6623495Sktlim@umich.edu return process->allocFD(fd, path.c_str(), hostFlags, mode, false); 6633310Srdreslin@umich.edu} 6643310Srdreslin@umich.edu 6653495Sktlim@umich.edu/// Target open() handler. 6662948Ssaidi@eecs.umich.edutemplate <class OS> 6673310Srdreslin@umich.eduSyscallReturn 6683310Srdreslin@umich.eduopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6694870Sstever@eecs.umich.edu ThreadContext *tc) 6704433Ssaidi@eecs.umich.edu{ 6714433Ssaidi@eecs.umich.edu return openFunc<OS>(desc, callnum, process, tc, 0); 6724433Ssaidi@eecs.umich.edu} 6734433Ssaidi@eecs.umich.edu 6744433Ssaidi@eecs.umich.edu/// Target openat() handler. 6754433Ssaidi@eecs.umich.edutemplate <class OS> 6763310Srdreslin@umich.eduSyscallReturn 6774433Ssaidi@eecs.umich.eduopenatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6784433Ssaidi@eecs.umich.edu ThreadContext *tc) 6792623SN/A{ 6802623SN/A int index = 0; 6812657Ssaidi@eecs.umich.edu int dirfd = process->getSyscallArg(tc, index); 6822623SN/A if (dirfd != OS::TGT_AT_FDCWD) 6832623SN/A warn("openat: first argument not AT_FDCWD; unlikely to work"); 6842623SN/A return openFunc<OS>(desc, callnum, process, tc, 1); 6852623SN/A} 6862623SN/A 6872623SN/A/// Target unlinkat() handler. 6883349Sbinkertn@umich.edutemplate <class OS> 6892657Ssaidi@eecs.umich.eduSyscallReturn 6902657Ssaidi@eecs.umich.eduunlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6912657Ssaidi@eecs.umich.edu ThreadContext *tc) 6922657Ssaidi@eecs.umich.edu{ 6932623SN/A int index = 0; 6942623SN/A int dirfd = process->getSyscallArg(tc, index); 6952623SN/A if (dirfd != OS::TGT_AT_FDCWD) 6963349Sbinkertn@umich.edu warn("unlinkat: first argument not AT_FDCWD; unlikely to work"); 6972623SN/A 6982623SN/A return unlinkHelper(desc, callnum, process, tc, 1); 6992623SN/A} 7004870Sstever@eecs.umich.edu 7012623SN/A/// Target facessat() handler 7022623SN/Atemplate <class OS> 7032623SN/ASyscallReturn 7045099Ssaidi@eecs.umich.edufaccessatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7053222Sktlim@umich.edu ThreadContext *tc) 7063184Srdreslin@umich.edu{ 7072623SN/A int index = 0; 7082623SN/A int dirfd = process->getSyscallArg(tc, index); 7094998Sgblack@eecs.umich.edu if (dirfd != OS::TGT_AT_FDCWD) 7104998Sgblack@eecs.umich.edu warn("faccessat: first argument not AT_FDCWD; unlikely to work"); 7114998Sgblack@eecs.umich.edu return accessFunc(desc, callnum, process, tc, 1); 7125001Sgblack@eecs.umich.edu} 7135001Sgblack@eecs.umich.edu 7145001Sgblack@eecs.umich.edu/// Target readlinkat() handler 7155001Sgblack@eecs.umich.edutemplate <class OS> 7165001Sgblack@eecs.umich.eduSyscallReturn 7174998Sgblack@eecs.umich.edureadlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7184878Sstever@eecs.umich.edu ThreadContext *tc) 7193170Sstever@eecs.umich.edu{ 7203170Sstever@eecs.umich.edu int index = 0; 7213170Sstever@eecs.umich.edu int dirfd = process->getSyscallArg(tc, index); 7222644Sstever@eecs.umich.edu if (dirfd != OS::TGT_AT_FDCWD) 7232644Sstever@eecs.umich.edu warn("openat: first argument not AT_FDCWD; unlikely to work"); 7242644Sstever@eecs.umich.edu return readlinkFunc(desc, callnum, process, tc, 1); 7253184Srdreslin@umich.edu} 7263227Sktlim@umich.edu 7273201Shsul@eecs.umich.edu/// Target renameat() handler. 7283201Shsul@eecs.umich.edutemplate <class OS> 7293201Shsul@eecs.umich.eduSyscallReturn 7303201Shsul@eecs.umich.edurenameatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7313201Shsul@eecs.umich.edu ThreadContext *tc) 7323201Shsul@eecs.umich.edu{ 7333201Shsul@eecs.umich.edu int index = 0; 7342644Sstever@eecs.umich.edu 7352623SN/A int olddirfd = process->getSyscallArg(tc, index); 7362623SN/A if (olddirfd != OS::TGT_AT_FDCWD) 7372623SN/A warn("renameat: first argument not AT_FDCWD; unlikely to work"); 7382798Sktlim@umich.edu 7392839Sktlim@umich.edu std::string old_name; 7402798Sktlim@umich.edu 7412839Sktlim@umich.edu if (!tc->getMemProxy().tryReadString(old_name, 7422901Ssaidi@eecs.umich.edu process->getSyscallArg(tc, index))) 7432839Sktlim@umich.edu return -EFAULT; 7442798Sktlim@umich.edu 7452623SN/A int newdirfd = process->getSyscallArg(tc, index); 7464192Sktlim@umich.edu if (newdirfd != OS::TGT_AT_FDCWD) 7474192Sktlim@umich.edu warn("renameat: third argument not AT_FDCWD; unlikely to work"); 7484192Sktlim@umich.edu 7494192Sktlim@umich.edu std::string new_name; 7504192Sktlim@umich.edu 7514192Sktlim@umich.edu if (!tc->getMemProxy().tryReadString(new_name, 7524192Sktlim@umich.edu process->getSyscallArg(tc, index))) 7534192Sktlim@umich.edu return -EFAULT; 7544192Sktlim@umich.edu 7554192Sktlim@umich.edu // Adjust path for current working directory 7564192Sktlim@umich.edu old_name = process->fullPath(old_name); 7574192Sktlim@umich.edu new_name = process->fullPath(new_name); 7582623SN/A 7593349Sbinkertn@umich.edu int result = rename(old_name.c_str(), new_name.c_str()); 7602623SN/A return (result == -1) ? -errno : result; 7614986Ssaidi@eecs.umich.edu} 7623310Srdreslin@umich.edu 7634584Ssaidi@eecs.umich.edu/// Target sysinfo() handler. 7642948Ssaidi@eecs.umich.edutemplate <class OS> 7653495Sktlim@umich.eduSyscallReturn 7663310Srdreslin@umich.edusysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7673310Srdreslin@umich.edu ThreadContext *tc) 7683495Sktlim@umich.edu{ 7692948Ssaidi@eecs.umich.edu 7703310Srdreslin@umich.edu int index = 0; 7713310Srdreslin@umich.edu TypedBufferArg<typename OS::tgt_sysinfo> 7724870Sstever@eecs.umich.edu sysinfo(process->getSyscallArg(tc, index)); 7734433Ssaidi@eecs.umich.edu 7744433Ssaidi@eecs.umich.edu sysinfo->uptime=seconds_since_epoch; 7754433Ssaidi@eecs.umich.edu sysinfo->totalram=process->system->memSize(); 7764433Ssaidi@eecs.umich.edu 7774433Ssaidi@eecs.umich.edu sysinfo.copyOut(tc->getMemProxy()); 7784433Ssaidi@eecs.umich.edu 7793310Srdreslin@umich.edu return 0; 7804433Ssaidi@eecs.umich.edu} 7814433Ssaidi@eecs.umich.edu 7822948Ssaidi@eecs.umich.edu/// Target chmod() handler. 7832948Ssaidi@eecs.umich.edutemplate <class OS> 7842948Ssaidi@eecs.umich.eduSyscallReturn 7852948Ssaidi@eecs.umich.educhmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7862948Ssaidi@eecs.umich.edu ThreadContext *tc) 7872630SN/A{ 7882623SN/A std::string path; 7892623SN/A 7902657Ssaidi@eecs.umich.edu int index = 0; 7912623SN/A if (!tc->getMemProxy().tryReadString(path, 7922623SN/A process->getSyscallArg(tc, index))) { 7932623SN/A return -EFAULT; 7942623SN/A } 7952623SN/A 7962623SN/A uint32_t mode = process->getSyscallArg(tc, index); 7973349Sbinkertn@umich.edu mode_t hostMode = 0; 7982657Ssaidi@eecs.umich.edu 7992657Ssaidi@eecs.umich.edu // XXX translate mode flags via OS::something??? 8003170Sstever@eecs.umich.edu hostMode = mode; 8012657Ssaidi@eecs.umich.edu 8022657Ssaidi@eecs.umich.edu // Adjust path for current working directory 8032623SN/A path = process->fullPath(path); 8042623SN/A 8055103Ssaidi@eecs.umich.edu // do the chmod 8065103Ssaidi@eecs.umich.edu int result = chmod(path.c_str(), hostMode); 8075103Ssaidi@eecs.umich.edu if (result < 0) 8085103Ssaidi@eecs.umich.edu return -errno; 8095103Ssaidi@eecs.umich.edu 8105103Ssaidi@eecs.umich.edu return 0; 8115103Ssaidi@eecs.umich.edu} 8125103Ssaidi@eecs.umich.edu 8135103Ssaidi@eecs.umich.edu 8145103Ssaidi@eecs.umich.edu/// Target fchmod() handler. 8155103Ssaidi@eecs.umich.edutemplate <class OS> 8165103Ssaidi@eecs.umich.eduSyscallReturn 8175103Ssaidi@eecs.umich.edufchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8185103Ssaidi@eecs.umich.edu ThreadContext *tc) 8195103Ssaidi@eecs.umich.edu{ 8205103Ssaidi@eecs.umich.edu int index = 0; 8215103Ssaidi@eecs.umich.edu int tgt_fd = process->getSyscallArg(tc, index); 8225103Ssaidi@eecs.umich.edu uint32_t mode = process->getSyscallArg(tc, index); 8232623SN/A 8242623SN/A int sim_fd = process->getSimFD(tgt_fd); 8252623SN/A if (sim_fd < 0) 8262623SN/A return -EBADF; 8272623SN/A 8284762Snate@binkert.org mode_t hostMode = 0; 8294762Snate@binkert.org 8302623SN/A // XXX translate mode flags via OS::someting??? 8312623SN/A hostMode = mode; 8324762Snate@binkert.org 8332623SN/A // do the fchmod 8342623SN/A int result = fchmod(sim_fd, hostMode); 8352623SN/A if (result < 0) 8362623SN/A return -errno; 8372623SN/A 8383119Sktlim@umich.edu return 0; 8392623SN/A} 8402623SN/A 8413661Srdreslin@umich.edu/// Target mremap() handler. 8422623SN/Atemplate <class OS> 8432623SN/ASyscallReturn 8442901Ssaidi@eecs.umich.edumremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 8453170Sstever@eecs.umich.edu{ 8464776Sgblack@eecs.umich.edu int index = 0; 8472623SN/A Addr start = process->getSyscallArg(tc, index); 8482623SN/A uint64_t old_length = process->getSyscallArg(tc, index); 8492623SN/A uint64_t new_length = process->getSyscallArg(tc, index); 8504997Sgblack@eecs.umich.edu uint64_t flags = process->getSyscallArg(tc, index); 8512623SN/A uint64_t provided_address = 0; 8523617Sbinkertn@umich.edu bool use_provided_address = flags & OS::TGT_MREMAP_FIXED; 8533617Sbinkertn@umich.edu 8543617Sbinkertn@umich.edu if (use_provided_address) 8552623SN/A provided_address = process->getSyscallArg(tc, index); 8564762Snate@binkert.org 8574762Snate@binkert.org if ((start % TheISA::PageBytes != 0) || 8584762Snate@binkert.org (provided_address % TheISA::PageBytes != 0)) { 8592623SN/A warn("mremap failing: arguments not page aligned"); 8602623SN/A return -EINVAL; 8612623SN/A } 8622623SN/A 8632623SN/A new_length = roundUp(new_length, TheISA::PageBytes); 864 865 if (new_length > old_length) { 866 if ((start + old_length) == process->mmap_end && 867 (!use_provided_address || provided_address == start)) { 868 uint64_t diff = new_length - old_length; 869 process->allocateMem(process->mmap_end, diff); 870 process->mmap_end += diff; 871 return start; 872 } else { 873 if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { 874 warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 875 return -ENOMEM; 876 } else { 877 uint64_t new_start = use_provided_address ? 878 provided_address : process->mmap_end; 879 process->pTable->remap(start, old_length, new_start); 880 warn("mremapping to new vaddr %08p-%08p, adding %d\n", 881 new_start, new_start + new_length, 882 new_length - old_length); 883 // add on the remaining unallocated pages 884 process->allocateMem(new_start + old_length, 885 new_length - old_length, 886 use_provided_address /* clobber */); 887 if (!use_provided_address) 888 process->mmap_end += new_length; 889 if (use_provided_address && 890 new_start + new_length > process->mmap_end) { 891 // something fishy going on here, at least notify the user 892 // @todo: increase mmap_end? 893 warn("mmap region limit exceeded with MREMAP_FIXED\n"); 894 } 895 warn("returning %08p as start\n", new_start); 896 return new_start; 897 } 898 } 899 } else { 900 if (use_provided_address && provided_address != start) 901 process->pTable->remap(start, new_length, provided_address); 902 process->pTable->unmap(start + new_length, old_length - new_length); 903 return use_provided_address ? provided_address : start; 904 } 905} 906 907/// Target stat() handler. 908template <class OS> 909SyscallReturn 910statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 911 ThreadContext *tc) 912{ 913 std::string path; 914 915 int index = 0; 916 if (!tc->getMemProxy().tryReadString(path, 917 process->getSyscallArg(tc, index))) { 918 return -EFAULT; 919 } 920 Addr bufPtr = process->getSyscallArg(tc, index); 921 922 // Adjust path for current working directory 923 path = process->fullPath(path); 924 925 struct stat hostBuf; 926 int result = stat(path.c_str(), &hostBuf); 927 928 if (result < 0) 929 return -errno; 930 931 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 932 933 return 0; 934} 935 936 937/// Target stat64() handler. 938template <class OS> 939SyscallReturn 940stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 941 ThreadContext *tc) 942{ 943 std::string path; 944 945 int index = 0; 946 if (!tc->getMemProxy().tryReadString(path, 947 process->getSyscallArg(tc, index))) 948 return -EFAULT; 949 Addr bufPtr = process->getSyscallArg(tc, index); 950 951 // Adjust path for current working directory 952 path = process->fullPath(path); 953 954#if NO_STAT64 955 struct stat hostBuf; 956 int result = stat(path.c_str(), &hostBuf); 957#else 958 struct stat64 hostBuf; 959 int result = stat64(path.c_str(), &hostBuf); 960#endif 961 962 if (result < 0) 963 return -errno; 964 965 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 966 967 return 0; 968} 969 970 971/// Target fstatat64() handler. 972template <class OS> 973SyscallReturn 974fstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 975 ThreadContext *tc) 976{ 977 int index = 0; 978 int dirfd = process->getSyscallArg(tc, index); 979 if (dirfd != OS::TGT_AT_FDCWD) 980 warn("fstatat64: first argument not AT_FDCWD; unlikely to work"); 981 982 std::string path; 983 if (!tc->getMemProxy().tryReadString(path, 984 process->getSyscallArg(tc, index))) 985 return -EFAULT; 986 Addr bufPtr = process->getSyscallArg(tc, index); 987 988 // Adjust path for current working directory 989 path = process->fullPath(path); 990 991#if NO_STAT64 992 struct stat hostBuf; 993 int result = stat(path.c_str(), &hostBuf); 994#else 995 struct stat64 hostBuf; 996 int result = stat64(path.c_str(), &hostBuf); 997#endif 998 999 if (result < 0) 1000 return -errno; 1001 1002 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 1003 1004 return 0; 1005} 1006 1007 1008/// Target fstat64() handler. 1009template <class OS> 1010SyscallReturn 1011fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 1012 ThreadContext *tc) 1013{ 1014 int index = 0; 1015 int tgt_fd = process->getSyscallArg(tc, index); 1016 Addr bufPtr = process->getSyscallArg(tc, index); 1017 1018 int sim_fd = process->getSimFD(tgt_fd); 1019 if (sim_fd < 0) 1020 return -EBADF; 1021 1022#if NO_STAT64 1023 struct stat hostBuf; 1024 int result = fstat(sim_fd, &hostBuf); 1025#else 1026 struct stat64 hostBuf; 1027 int result = fstat64(sim_fd, &hostBuf); 1028#endif 1029 1030 if (result < 0) 1031 return -errno; 1032 1033 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 1034 1035 return 0; 1036} 1037 1038 1039/// Target lstat() handler. 1040template <class OS> 1041SyscallReturn 1042lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1043 ThreadContext *tc) 1044{ 1045 std::string path; 1046 1047 int index = 0; 1048 if (!tc->getMemProxy().tryReadString(path, 1049 process->getSyscallArg(tc, index))) { 1050 return -EFAULT; 1051 } 1052 Addr bufPtr = process->getSyscallArg(tc, index); 1053 1054 // Adjust path for current working directory 1055 path = process->fullPath(path); 1056 1057 struct stat hostBuf; 1058 int result = lstat(path.c_str(), &hostBuf); 1059 1060 if (result < 0) 1061 return -errno; 1062 1063 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 1064 1065 return 0; 1066} 1067 1068/// Target lstat64() handler. 1069template <class OS> 1070SyscallReturn 1071lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 1072 ThreadContext *tc) 1073{ 1074 std::string path; 1075 1076 int index = 0; 1077 if (!tc->getMemProxy().tryReadString(path, 1078 process->getSyscallArg(tc, index))) { 1079 return -EFAULT; 1080 } 1081 Addr bufPtr = process->getSyscallArg(tc, index); 1082 1083 // Adjust path for current working directory 1084 path = process->fullPath(path); 1085 1086#if NO_STAT64 1087 struct stat hostBuf; 1088 int result = lstat(path.c_str(), &hostBuf); 1089#else 1090 struct stat64 hostBuf; 1091 int result = lstat64(path.c_str(), &hostBuf); 1092#endif 1093 1094 if (result < 0) 1095 return -errno; 1096 1097 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 1098 1099 return 0; 1100} 1101 1102/// Target fstat() handler. 1103template <class OS> 1104SyscallReturn 1105fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1106 ThreadContext *tc) 1107{ 1108 int index = 0; 1109 int tgt_fd = process->getSyscallArg(tc, index); 1110 Addr bufPtr = process->getSyscallArg(tc, index); 1111 1112 DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd); 1113 1114 int sim_fd = process->getSimFD(tgt_fd); 1115 if (sim_fd < 0) 1116 return -EBADF; 1117 1118 struct stat hostBuf; 1119 int result = fstat(sim_fd, &hostBuf); 1120 1121 if (result < 0) 1122 return -errno; 1123 1124 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 1125 1126 return 0; 1127} 1128 1129 1130/// Target statfs() handler. 1131template <class OS> 1132SyscallReturn 1133statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1134 ThreadContext *tc) 1135{ 1136 std::string path; 1137 1138 int index = 0; 1139 if (!tc->getMemProxy().tryReadString(path, 1140 process->getSyscallArg(tc, index))) { 1141 return -EFAULT; 1142 } 1143 Addr bufPtr = process->getSyscallArg(tc, index); 1144 1145 // Adjust path for current working directory 1146 path = process->fullPath(path); 1147 1148 struct statfs hostBuf; 1149 int result = statfs(path.c_str(), &hostBuf); 1150 1151 if (result < 0) 1152 return -errno; 1153 1154 OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 1155 1156 return 0; 1157} 1158 1159 1160/// Target fstatfs() handler. 1161template <class OS> 1162SyscallReturn 1163fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1164 ThreadContext *tc) 1165{ 1166 int index = 0; 1167 int tgt_fd = process->getSyscallArg(tc, index); 1168 Addr bufPtr = process->getSyscallArg(tc, index); 1169 1170 int sim_fd = process->getSimFD(tgt_fd); 1171 if (sim_fd < 0) 1172 return -EBADF; 1173 1174 struct statfs hostBuf; 1175 int result = fstatfs(sim_fd, &hostBuf); 1176 1177 if (result < 0) 1178 return -errno; 1179 1180 OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 1181 1182 return 0; 1183} 1184 1185 1186/// Target writev() handler. 1187template <class OS> 1188SyscallReturn 1189writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1190 ThreadContext *tc) 1191{ 1192 int index = 0; 1193 int tgt_fd = process->getSyscallArg(tc, index); 1194 1195 int sim_fd = process->getSimFD(tgt_fd); 1196 if (sim_fd < 0) 1197 return -EBADF; 1198 1199 SETranslatingPortProxy &p = tc->getMemProxy(); 1200 uint64_t tiov_base = process->getSyscallArg(tc, index); 1201 size_t count = process->getSyscallArg(tc, index); 1202 struct iovec hiov[count]; 1203 for (size_t i = 0; i < count; ++i) { 1204 typename OS::tgt_iovec tiov; 1205 1206 p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 1207 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 1208 hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 1209 hiov[i].iov_base = new char [hiov[i].iov_len]; 1210 p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 1211 hiov[i].iov_len); 1212 } 1213 1214 int result = writev(sim_fd, hiov, count); 1215 1216 for (size_t i = 0; i < count; ++i) 1217 delete [] (char *)hiov[i].iov_base; 1218 1219 if (result < 0) 1220 return -errno; 1221 1222 return result; 1223} 1224 1225 1226/// Target mmap() handler. 1227/// 1228/// We don't really handle mmap(). If the target is mmaping an 1229/// anonymous region or /dev/zero, we can get away with doing basically 1230/// nothing (since memory is initialized to zero and the simulator 1231/// doesn't really check addresses anyway). 1232/// 1233template <class OS> 1234SyscallReturn 1235mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1236{ 1237 int index = 0; 1238 Addr start = p->getSyscallArg(tc, index); 1239 uint64_t length = p->getSyscallArg(tc, index); 1240 index++; // int prot = p->getSyscallArg(tc, index); 1241 int flags = p->getSyscallArg(tc, index); 1242 int tgt_fd = p->getSyscallArg(tc, index); 1243 int offset = p->getSyscallArg(tc, index); 1244 1245 if (length > 0x100000000ULL) 1246 warn("mmap length argument %#x is unreasonably large.\n", length); 1247 1248 if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 1249 FDEntry *fde = p->getFDEntry(tgt_fd); 1250 if (!fde || fde->fd < 0) { 1251 warn("mmap failing: target fd %d is not valid\n", tgt_fd); 1252 return -EBADF; 1253 } 1254 1255 if (fde->filename != "/dev/zero") { 1256 // This is very likely broken, but leave a warning here 1257 // (rather than panic) in case /dev/zero is known by 1258 // another name on some platform 1259 warn("allowing mmap of file %s; mmap not supported on files" 1260 " other than /dev/zero\n", fde->filename); 1261 } 1262 } 1263 1264 length = roundUp(length, TheISA::PageBytes); 1265 1266 if ((start % TheISA::PageBytes) != 0 || 1267 (offset % TheISA::PageBytes) != 0) { 1268 warn("mmap failing: arguments not page-aligned: " 1269 "start 0x%x offset 0x%x", 1270 start, offset); 1271 return -EINVAL; 1272 } 1273 1274 // are we ok with clobbering existing mappings? only set this to 1275 // true if the user has been warned. 1276 bool clobber = false; 1277 1278 // try to use the caller-provided address if there is one 1279 bool use_provided_address = (start != 0); 1280 1281 if (use_provided_address) { 1282 // check to see if the desired address is already in use 1283 if (!p->pTable->isUnmapped(start, length)) { 1284 // there are existing mappings in the desired range 1285 // whether we clobber them or not depends on whether the caller 1286 // specified MAP_FIXED 1287 if (flags & OS::TGT_MAP_FIXED) { 1288 // MAP_FIXED specified: map attempt fails 1289 return -EINVAL; 1290 } else { 1291 // MAP_FIXED not specified: ignore suggested start address 1292 warn("mmap: ignoring suggested map address 0x%x\n", start); 1293 use_provided_address = false; 1294 } 1295 } 1296 } 1297 1298 if (!use_provided_address) { 1299 // no address provided, or provided address unusable: 1300 // pick next address from our "mmap region" 1301 if (OS::mmapGrowsDown()) { 1302 start = p->mmap_end - length; 1303 p->mmap_end = start; 1304 } else { 1305 start = p->mmap_end; 1306 p->mmap_end += length; 1307 } 1308 } 1309 1310 p->allocateMem(start, length, clobber); 1311 1312 return start; 1313} 1314 1315/// Target getrlimit() handler. 1316template <class OS> 1317SyscallReturn 1318getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1319 ThreadContext *tc) 1320{ 1321 int index = 0; 1322 unsigned resource = process->getSyscallArg(tc, index); 1323 TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1324 1325 switch (resource) { 1326 case OS::TGT_RLIMIT_STACK: 1327 // max stack size in bytes: make up a number (8MB for now) 1328 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 1329 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1330 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1331 break; 1332 1333 case OS::TGT_RLIMIT_DATA: 1334 // max data segment size in bytes: make up a number 1335 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 1336 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1337 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1338 break; 1339 1340 default: 1341 warn("getrlimit: unimplemented resource %d", resource); 1342 return -EINVAL; 1343 break; 1344 } 1345 1346 rlp.copyOut(tc->getMemProxy()); 1347 return 0; 1348} 1349 1350/// Target clock_gettime() function. 1351template <class OS> 1352SyscallReturn 1353clock_gettimeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1354{ 1355 int index = 1; 1356 //int clk_id = p->getSyscallArg(tc, index); 1357 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1358 1359 getElapsedTimeNano(tp->tv_sec, tp->tv_nsec); 1360 tp->tv_sec += seconds_since_epoch; 1361 tp->tv_sec = TheISA::htog(tp->tv_sec); 1362 tp->tv_nsec = TheISA::htog(tp->tv_nsec); 1363 1364 tp.copyOut(tc->getMemProxy()); 1365 1366 return 0; 1367} 1368 1369/// Target clock_getres() function. 1370template <class OS> 1371SyscallReturn 1372clock_getresFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1373{ 1374 int index = 1; 1375 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1376 1377 // Set resolution at ns, which is what clock_gettime() returns 1378 tp->tv_sec = 0; 1379 tp->tv_nsec = 1; 1380 1381 tp.copyOut(tc->getMemProxy()); 1382 1383 return 0; 1384} 1385 1386/// Target gettimeofday() handler. 1387template <class OS> 1388SyscallReturn 1389gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1390 ThreadContext *tc) 1391{ 1392 int index = 0; 1393 TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1394 1395 getElapsedTimeMicro(tp->tv_sec, tp->tv_usec); 1396 tp->tv_sec += seconds_since_epoch; 1397 tp->tv_sec = TheISA::htog(tp->tv_sec); 1398 tp->tv_usec = TheISA::htog(tp->tv_usec); 1399 1400 tp.copyOut(tc->getMemProxy()); 1401 1402 return 0; 1403} 1404 1405 1406/// Target utimes() handler. 1407template <class OS> 1408SyscallReturn 1409utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1410 ThreadContext *tc) 1411{ 1412 std::string path; 1413 1414 int index = 0; 1415 if (!tc->getMemProxy().tryReadString(path, 1416 process->getSyscallArg(tc, index))) { 1417 return -EFAULT; 1418 } 1419 1420 TypedBufferArg<typename OS::timeval [2]> 1421 tp(process->getSyscallArg(tc, index)); 1422 tp.copyIn(tc->getMemProxy()); 1423 1424 struct timeval hostTimeval[2]; 1425 for (int i = 0; i < 2; ++i) 1426 { 1427 hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 1428 hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 1429 } 1430 1431 // Adjust path for current working directory 1432 path = process->fullPath(path); 1433 1434 int result = utimes(path.c_str(), hostTimeval); 1435 1436 if (result < 0) 1437 return -errno; 1438 1439 return 0; 1440} 1441/// Target getrusage() function. 1442template <class OS> 1443SyscallReturn 1444getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1445 ThreadContext *tc) 1446{ 1447 int index = 0; 1448 int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 1449 TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1450 1451 rup->ru_utime.tv_sec = 0; 1452 rup->ru_utime.tv_usec = 0; 1453 rup->ru_stime.tv_sec = 0; 1454 rup->ru_stime.tv_usec = 0; 1455 rup->ru_maxrss = 0; 1456 rup->ru_ixrss = 0; 1457 rup->ru_idrss = 0; 1458 rup->ru_isrss = 0; 1459 rup->ru_minflt = 0; 1460 rup->ru_majflt = 0; 1461 rup->ru_nswap = 0; 1462 rup->ru_inblock = 0; 1463 rup->ru_oublock = 0; 1464 rup->ru_msgsnd = 0; 1465 rup->ru_msgrcv = 0; 1466 rup->ru_nsignals = 0; 1467 rup->ru_nvcsw = 0; 1468 rup->ru_nivcsw = 0; 1469 1470 switch (who) { 1471 case OS::TGT_RUSAGE_SELF: 1472 getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 1473 rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 1474 rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 1475 break; 1476 1477 case OS::TGT_RUSAGE_CHILDREN: 1478 // do nothing. We have no child processes, so they take no time. 1479 break; 1480 1481 default: 1482 // don't really handle THREAD or CHILDREN, but just warn and 1483 // plow ahead 1484 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 1485 who); 1486 } 1487 1488 rup.copyOut(tc->getMemProxy()); 1489 1490 return 0; 1491} 1492 1493/// Target times() function. 1494template <class OS> 1495SyscallReturn 1496timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1497 ThreadContext *tc) 1498{ 1499 int index = 0; 1500 TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 1501 1502 // Fill in the time structure (in clocks) 1503 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 1504 bufp->tms_utime = clocks; 1505 bufp->tms_stime = 0; 1506 bufp->tms_cutime = 0; 1507 bufp->tms_cstime = 0; 1508 1509 // Convert to host endianness 1510 bufp->tms_utime = TheISA::htog(bufp->tms_utime); 1511 1512 // Write back 1513 bufp.copyOut(tc->getMemProxy()); 1514 1515 // Return clock ticks since system boot 1516 return clocks; 1517} 1518 1519/// Target time() function. 1520template <class OS> 1521SyscallReturn 1522timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1523 ThreadContext *tc) 1524{ 1525 typename OS::time_t sec, usec; 1526 getElapsedTimeMicro(sec, usec); 1527 sec += seconds_since_epoch; 1528 1529 int index = 0; 1530 Addr taddr = (Addr)process->getSyscallArg(tc, index); 1531 if (taddr != 0) { 1532 typename OS::time_t t = sec; 1533 t = TheISA::htog(t); 1534 SETranslatingPortProxy &p = tc->getMemProxy(); 1535 p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 1536 } 1537 return sec; 1538} 1539 1540 1541#endif // __SIM_SYSCALL_EMUL_HH__ 1542