syscall_emul.hh revision 10027
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2012-2013 ARM Limited 310796Sbrandon.potter@amd.com * All rights reserved 410027SChris.Adeniyi-Jones@arm.com * 510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall 610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual 710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating 810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software 910027SChris.Adeniyi-Jones@arm.com * licensed hereunder. You may use the software subject to the license 1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated 1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software, 1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form. 1310027SChris.Adeniyi-Jones@arm.com * 1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 151458SN/A * All rights reserved. 16360SN/A * 17360SN/A * Redistribution and use in source and binary forms, with or without 18360SN/A * modification, are permitted provided that the following conditions are 19360SN/A * met: redistributions of source code must retain the above copyright 20360SN/A * notice, this list of conditions and the following disclaimer; 21360SN/A * redistributions in binary form must reproduce the above copyright 22360SN/A * notice, this list of conditions and the following disclaimer in the 23360SN/A * documentation and/or other materials provided with the distribution; 24360SN/A * neither the name of the copyright holders nor the names of its 25360SN/A * contributors may be used to endorse or promote products derived from 26360SN/A * this software without specific prior written permission. 27360SN/A * 28360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39360SN/A * 402665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 412665Ssaidi@eecs.umich.edu * Kevin Lim 422665Ssaidi@eecs.umich.edu */ 43360SN/A 44360SN/A#ifndef __SIM_SYSCALL_EMUL_HH__ 451354SN/A#define __SIM_SYSCALL_EMUL_HH__ 461354SN/A 47360SN/A#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 4812018Sandreas.sandberg@arm.com defined(__FreeBSD__) || defined(__CYGWIN__) || \ 4912018Sandreas.sandberg@arm.com defined(__NetBSD__)) 5012018Sandreas.sandberg@arm.com 5112018Sandreas.sandberg@arm.com/// 5212018Sandreas.sandberg@arm.com/// @file syscall_emul.hh 5312018Sandreas.sandberg@arm.com/// 5412018Sandreas.sandberg@arm.com/// This file defines objects used to emulate syscalls from the target 552064SN/A/// application on the host machine. 5612018Sandreas.sandberg@arm.com 5712018Sandreas.sandberg@arm.com#ifdef __CYGWIN32__ 5812018Sandreas.sandberg@arm.com#include <sys/fcntl.h> // for O_BINARY 5912018Sandreas.sandberg@arm.com#endif 6012018Sandreas.sandberg@arm.com#include <sys/stat.h> 6112018Sandreas.sandberg@arm.com#include <sys/time.h> 6211799Sbrandon.potter@amd.com#include <sys/uio.h> 6312018Sandreas.sandberg@arm.com#include <fcntl.h> 6412018Sandreas.sandberg@arm.com 6512018Sandreas.sandberg@arm.com#include <cerrno> 6612018Sandreas.sandberg@arm.com#include <string> 6712018Sandreas.sandberg@arm.com 6812018Sandreas.sandberg@arm.com#include "base/chunk_generator.hh" 6911799Sbrandon.potter@amd.com#include "base/intmath.hh" // for RoundUp 70360SN/A#include "base/misc.hh" 71360SN/A#include "base/trace.hh" 72360SN/A#include "base/types.hh" 73360SN/A#include "config/the_isa.hh" 74360SN/A#include "cpu/base.hh" 75360SN/A#include "cpu/thread_context.hh" 761809SN/A#include "debug/SyscallVerbose.hh" 7711800Sbrandon.potter@amd.com#include "mem/page_table.hh" 7811392Sbrandon.potter@amd.com#include "mem/se_translating_port_proxy.hh" 791809SN/A#include "sim/byteswap.hh" 8011392Sbrandon.potter@amd.com#include "sim/process.hh" 8113570Sbrandon.potter@amd.com#include "sim/syscallreturn.hh" 8211383Sbrandon.potter@amd.com#include "sim/system.hh" 8313568Sbrandon.potter@amd.com 843113Sgblack@eecs.umich.edu/// 8511799Sbrandon.potter@amd.com/// System call descriptor. 8611759Sbrandon.potter@amd.com/// 8711812Sbaz21@cam.ac.ukclass SyscallDesc { 8811812Sbaz21@cam.ac.uk 8911799Sbrandon.potter@amd.com public: 908229Snate@binkert.org 9113570Sbrandon.potter@amd.com /// Typedef for target syscall handler functions. 928229Snate@binkert.org typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 9311594Santhony.gutierrez@amd.com LiveProcess *, ThreadContext *); 947075Snate@binkert.org 958229Snate@binkert.org const char *name; //!< Syscall name (e.g., "open"). 9611856Sbrandon.potter@amd.com FuncPtr funcPtr; //!< Pointer to emulation function. 977075Snate@binkert.org int flags; //!< Flags (see Flags enum). 98360SN/A 9912461Sgabeblack@google.com /// Flag values for controlling syscall behavior. 10011886Sbrandon.potter@amd.com enum Flags { 10111800Sbrandon.potter@amd.com /// Don't set return regs according to funcPtr return value. 10211392Sbrandon.potter@amd.com /// Used for syscalls with non-standard return conventions 10312334Sgabeblack@google.com /// that explicitly set the ThreadContext regs (e.g., 1041354SN/A /// sigreturn). 1056216Snate@binkert.org SuppressReturnValue = 1 1066658Snate@binkert.org }; 1072474SN/A 1082680Sktlim@umich.edu /// Constructor. 1098229Snate@binkert.org SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 11011886Sbrandon.potter@amd.com : name(_name), funcPtr(_funcPtr), flags(_flags) 11110496Ssteve.reinhardt@amd.com { 11211911SBrandon.Potter@amd.com } 1138229Snate@binkert.org 11411794Sbrandon.potter@amd.com /// Emulate the syscall. Public interface for calling through funcPtr. 11511886Sbrandon.potter@amd.com void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 11610497Ssteve.reinhardt@amd.com}; 11711794Sbrandon.potter@amd.com 118360SN/A 119360SN/Aclass BaseBufferArg { 120360SN/A 121360SN/A public: 122360SN/A 123360SN/A BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 124360SN/A { 125360SN/A bufPtr = new uint8_t[size]; 126360SN/A // clear out buffer: in case we only partially populate this, 127360SN/A // and then do a copyOut(), we want to make sure we don't 128378SN/A // introduce any random junk into the simulated address space 1291706SN/A memset(bufPtr, 0, size); 13011851Sbrandon.potter@amd.com } 131378SN/A 132378SN/A virtual ~BaseBufferArg() { delete [] bufPtr; } 133378SN/A 134378SN/A // 135378SN/A // copy data into simulator space (read from target memory) 1361706SN/A // 13711851Sbrandon.potter@amd.com virtual bool copyIn(SETranslatingPortProxy &memproxy) 138360SN/A { 13911760Sbrandon.potter@amd.com memproxy.readBlob(addr, bufPtr, size); 14011760Sbrandon.potter@amd.com return true; // no EFAULT detection for now 14111851Sbrandon.potter@amd.com } 14211760Sbrandon.potter@amd.com 1436109Ssanchezd@stanford.edu // 1441706SN/A // copy data out of simulator space (write to target memory) 14511851Sbrandon.potter@amd.com // 146378SN/A virtual bool copyOut(SETranslatingPortProxy &memproxy) 1476109Ssanchezd@stanford.edu { 1486109Ssanchezd@stanford.edu memproxy.writeBlob(addr, bufPtr, size); 14911851Sbrandon.potter@amd.com return true; // no EFAULT detection for now 1506109Ssanchezd@stanford.edu } 15111886Sbrandon.potter@amd.com 15211886Sbrandon.potter@amd.com protected: 15311886Sbrandon.potter@amd.com Addr addr; 15411886Sbrandon.potter@amd.com int size; 155378SN/A uint8_t *bufPtr; 1561706SN/A}; 15711851Sbrandon.potter@amd.com 158378SN/A 1595748SSteve.Reinhardt@amd.comclass BufferArg : public BaseBufferArg 1605748SSteve.Reinhardt@amd.com{ 16111851Sbrandon.potter@amd.com public: 162378SN/A BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 163378SN/A void *bufferPtr() { return bufPtr; } 1641706SN/A}; 16511851Sbrandon.potter@amd.com 166378SN/Atemplate <class T> 167378SN/Aclass TypedBufferArg : public BaseBufferArg 1681706SN/A{ 16911851Sbrandon.potter@amd.com public: 170378SN/A // user can optionally specify a specific number of bytes to 1714118Sgblack@eecs.umich.edu // allocate to deal with those structs that have variable-size 1724118Sgblack@eecs.umich.edu // arrays at the end 17311851Sbrandon.potter@amd.com TypedBufferArg(Addr _addr, int _size = sizeof(T)) 1744118Sgblack@eecs.umich.edu : BaseBufferArg(_addr, _size) 175378SN/A { } 1761706SN/A 17711851Sbrandon.potter@amd.com // type case 178378SN/A operator T*() { return (T *)bufPtr; } 17913568Sbrandon.potter@amd.com 18013568Sbrandon.potter@amd.com // dereference operators 18113568Sbrandon.potter@amd.com T &operator*() { return *((T *)bufPtr); } 18213568Sbrandon.potter@amd.com T* operator->() { return (T *)bufPtr; } 183378SN/A T &operator[](int i) { return ((T *)bufPtr)[i]; } 1841706SN/A}; 18511851Sbrandon.potter@amd.com 186360SN/A////////////////////////////////////////////////////////////////////// 1875513SMichael.Adler@intel.com// 1885513SMichael.Adler@intel.com// The following emulation functions are generic enough that they 18911851Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's. They are 1905513SMichael.Adler@intel.com// defined in sim/syscall_emul.cc. 19110203SAli.Saidi@ARM.com// 19210203SAli.Saidi@ARM.com////////////////////////////////////////////////////////////////////// 19311851Sbrandon.potter@amd.com 19410203SAli.Saidi@ARM.com 1955513SMichael.Adler@intel.com/// Handler for unimplemented syscalls that we haven't thought about. 19611851Sbrandon.potter@amd.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1975513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 198511SN/A 19910633Smichaelupton@gmail.com/// Handler for unimplemented syscalls that we never intend to 20011851Sbrandon.potter@amd.com/// implement (signal handling, etc.) and should not affect the correct 20110633Smichaelupton@gmail.com/// behavior of the program. Print a warning only if the appropriate 2021706SN/A/// trace flag is enabled. Return success to the target program. 20311851Sbrandon.potter@amd.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 204511SN/A LiveProcess *p, ThreadContext *tc); 20512795Smattdsinclair@gmail.comSyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 20612795Smattdsinclair@gmail.com LiveProcess *p, ThreadContext *tc); 20712795Smattdsinclair@gmail.com 20812795Smattdsinclair@gmail.com/// Target exit() handler: terminate current context. 20912796Smattdsinclair@gmail.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 21012796Smattdsinclair@gmail.com LiveProcess *p, ThreadContext *tc); 21112796Smattdsinclair@gmail.com 21212796Smattdsinclair@gmail.com/// Target exit_group() handler: terminate simulation. (exit all threads) 2135513SMichael.Adler@intel.comSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 2145513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 21511851Sbrandon.potter@amd.com 2165513SMichael.Adler@intel.com/// Target getpagesize() handler. 21713031Sbrandon.potter@amd.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 21813031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 21913031Sbrandon.potter@amd.com 22013031Sbrandon.potter@amd.com/// Target brk() handler: set brk address. 22113031Sbrandon.potter@amd.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 22213031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 22313031Sbrandon.potter@amd.com 22413031Sbrandon.potter@amd.com/// Target close() handler. 22513031Sbrandon.potter@amd.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 22613031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 22713031Sbrandon.potter@amd.com 22813031Sbrandon.potter@amd.com/// Target read() handler. 229511SN/ASyscallReturn readFunc(SyscallDesc *desc, int num, 2301706SN/A LiveProcess *p, ThreadContext *tc); 23111851Sbrandon.potter@amd.com 2321706SN/A/// Target write() handler. 2331706SN/ASyscallReturn writeFunc(SyscallDesc *desc, int num, 2341706SN/A LiveProcess *p, ThreadContext *tc); 2351706SN/A 23611851Sbrandon.potter@amd.com/// Target lseek() handler. 2371706SN/ASyscallReturn lseekFunc(SyscallDesc *desc, int num, 2381706SN/A LiveProcess *p, ThreadContext *tc); 2391706SN/A 2401706SN/A/// Target _llseek() handler. 24111851Sbrandon.potter@amd.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 2421706SN/A LiveProcess *p, ThreadContext *tc); 243511SN/A 2446703Svince@csl.cornell.edu/// Target munmap() handler. 2456703Svince@csl.cornell.eduSyscallReturn munmapFunc(SyscallDesc *desc, int num, 24611851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2476703Svince@csl.cornell.edu 2486685Stjones1@inf.ed.ac.uk/// Target gethostname() handler. 2496685Stjones1@inf.ed.ac.ukSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 25011851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2516685Stjones1@inf.ed.ac.uk 2526685Stjones1@inf.ed.ac.uk/// Target getcwd() handler. 2535513SMichael.Adler@intel.comSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2545513SMichael.Adler@intel.com LiveProcess *p, ThreadContext *tc); 25511851Sbrandon.potter@amd.com 2565513SMichael.Adler@intel.com/// Target unlink() handler. 25711885Sbrandon.potter@amd.comSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 25811885Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 25911885Sbrandon.potter@amd.com 2605513SMichael.Adler@intel.com/// Target unlink() handler. 2611999SN/ASyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2621999SN/A LiveProcess *p, ThreadContext *tc); 26311851Sbrandon.potter@amd.com 2641999SN/A/// Target mkdir() handler. 26511885Sbrandon.potter@amd.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 26611885Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 26711885Sbrandon.potter@amd.com 2681999SN/A/// Target rename() handler. 2691999SN/ASyscallReturn renameFunc(SyscallDesc *desc, int num, 2701999SN/A LiveProcess *p, ThreadContext *tc); 27111851Sbrandon.potter@amd.com 2721999SN/A 2733079Sstever@eecs.umich.edu/// Target truncate() handler. 2743079Sstever@eecs.umich.eduSyscallReturn truncateFunc(SyscallDesc *desc, int num, 27511851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 2763079Sstever@eecs.umich.edu 27711908SBrandon.Potter@amd.com 27811908SBrandon.Potter@amd.com/// Target ftruncate() handler. 27911908SBrandon.Potter@amd.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 28011908SBrandon.Potter@amd.com LiveProcess *p, ThreadContext *tc); 28111875Sbrandon.potter@amd.com 2822093SN/A 28311851Sbrandon.potter@amd.com/// Target truncate64() handler. 2842093SN/ASyscallReturn truncate64Func(SyscallDesc *desc, int num, 2852687Sksewell@umich.edu LiveProcess *p, ThreadContext *tc); 2862687Sksewell@umich.edu 28711851Sbrandon.potter@amd.com/// Target ftruncate64() handler. 2882687Sksewell@umich.eduSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2892238SN/A LiveProcess *p, ThreadContext *tc); 2902238SN/A 29111851Sbrandon.potter@amd.com 2922238SN/A/// Target umask() handler. 29311908SBrandon.Potter@amd.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 29411908SBrandon.Potter@amd.com LiveProcess *p, ThreadContext *tc); 29511908SBrandon.Potter@amd.com 29611908SBrandon.Potter@amd.com 29711908SBrandon.Potter@amd.com/// Target chown() handler. 29811908SBrandon.Potter@amd.comSyscallReturn chownFunc(SyscallDesc *desc, int num, 29911908SBrandon.Potter@amd.com LiveProcess *p, ThreadContext *tc); 30011908SBrandon.Potter@amd.com 3012238SN/A 3022238SN/A/// Target fchown() handler. 30311851Sbrandon.potter@amd.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 3042238SN/A LiveProcess *p, ThreadContext *tc); 30513571Sbrandon.potter@amd.com 30613571Sbrandon.potter@amd.com/// Target dup() handler. 30713571Sbrandon.potter@amd.comSyscallReturn dupFunc(SyscallDesc *desc, int num, 30813571Sbrandon.potter@amd.com LiveProcess *process, ThreadContext *tc); 30913568Sbrandon.potter@amd.com 31013568Sbrandon.potter@amd.com/// Target fnctl() handler. 31113568Sbrandon.potter@amd.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 31213568Sbrandon.potter@amd.com LiveProcess *process, ThreadContext *tc); 31313568Sbrandon.potter@amd.com 31413568Sbrandon.potter@amd.com/// Target fcntl64() handler. 31513568Sbrandon.potter@amd.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 31613568Sbrandon.potter@amd.com LiveProcess *process, ThreadContext *tc); 31713568Sbrandon.potter@amd.com 31813568Sbrandon.potter@amd.com/// Target setuid() handler. 31913568Sbrandon.potter@amd.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 32013568Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 32113448Sciro.santilli@arm.com 32213031Sbrandon.potter@amd.com/// Target getpid() handler. 32313031Sbrandon.potter@amd.comSyscallReturn getpidFunc(SyscallDesc *desc, int num, 32413031Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 32513448Sciro.santilli@arm.com 32613031Sbrandon.potter@amd.com/// Target getuid() handler. 32713539Sjavier.setoain@arm.comSyscallReturn getuidFunc(SyscallDesc *desc, int num, 32813539Sjavier.setoain@arm.com LiveProcess *p, ThreadContext *tc); 32913539Sjavier.setoain@arm.com 33013539Sjavier.setoain@arm.com/// Target getgid() handler. 33113539Sjavier.setoain@arm.comSyscallReturn getgidFunc(SyscallDesc *desc, int num, 33213539Sjavier.setoain@arm.com LiveProcess *p, ThreadContext *tc); 33313569Sbrandon.potter@amd.com 33413569Sbrandon.potter@amd.com/// Target getppid() handler. 33513569Sbrandon.potter@amd.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 33613569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 33713569Sbrandon.potter@amd.com 33813569Sbrandon.potter@amd.com/// Target geteuid() handler. 33913569Sbrandon.potter@amd.comSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 34013569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 34113569Sbrandon.potter@amd.com 34213569Sbrandon.potter@amd.com/// Target getegid() handler. 34313569Sbrandon.potter@amd.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 34413569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 34513569Sbrandon.potter@amd.com 34613569Sbrandon.potter@amd.com/// Target clone() handler. 34713569Sbrandon.potter@amd.comSyscallReturn cloneFunc(SyscallDesc *desc, int num, 34813569Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 34913031Sbrandon.potter@amd.com 3502238SN/A/// Target access() handler 35111851Sbrandon.potter@amd.comSyscallReturn accessFunc(SyscallDesc *desc, int num, 3522238SN/A LiveProcess *p, ThreadContext *tc); 3532238SN/A 3542238SN/A/// Futex system call 35511851Sbrandon.potter@amd.com/// Implemented by Daniel Sanchez 3562238SN/A/// Used by printf's in multi-threaded apps 3572238SN/Atemplate <class OS> 3582238SN/ASyscallReturn 35911851Sbrandon.potter@amd.comfutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3602238SN/A ThreadContext *tc) 3612238SN/A{ 3622238SN/A int index_uaddr = 0; 36311851Sbrandon.potter@amd.com int index_op = 1; 3642238SN/A int index_val = 2; 3652238SN/A int index_timeout = 3; 3662238SN/A 36711851Sbrandon.potter@amd.com uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3682238SN/A int op = process->getSyscallArg(tc, index_op); 3699455Smitch.hayenga+gem5@gmail.com int val = process->getSyscallArg(tc, index_val); 3709455Smitch.hayenga+gem5@gmail.com uint64_t timeout = process->getSyscallArg(tc, index_timeout); 37111851Sbrandon.potter@amd.com 37210203SAli.Saidi@ARM.com std::map<uint64_t, std::list<ThreadContext *> * > 37311851Sbrandon.potter@amd.com &futex_map = tc->getSystemPtr()->futexMap; 37411851Sbrandon.potter@amd.com 3759455Smitch.hayenga+gem5@gmail.com DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 37613571Sbrandon.potter@amd.com uaddr, op, val); 37713571Sbrandon.potter@amd.com 37813571Sbrandon.potter@amd.com op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 37913571Sbrandon.potter@amd.com 38013571Sbrandon.potter@amd.com if (op == OS::TGT_FUTEX_WAIT) { 38113571Sbrandon.potter@amd.com if (timeout != 0) { 38213571Sbrandon.potter@amd.com warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 38313571Sbrandon.potter@amd.com "we'll wait indefinitely"); 38413571Sbrandon.potter@amd.com } 38513571Sbrandon.potter@amd.com 38613571Sbrandon.potter@amd.com uint8_t *buf = new uint8_t[sizeof(int)]; 38713571Sbrandon.potter@amd.com tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3889112Smarc.orr@gmail.com int mem_val = *((int *)buf); 38911906SBrandon.Potter@amd.com delete buf; 39011906SBrandon.Potter@amd.com 3919112Smarc.orr@gmail.com if(val != mem_val) { 3929112Smarc.orr@gmail.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 39311851Sbrandon.potter@amd.com "expected: %d\n", mem_val, val); 3949112Smarc.orr@gmail.com return -OS::TGT_EWOULDBLOCK; 3959112Smarc.orr@gmail.com } 39611911SBrandon.Potter@amd.com 3979112Smarc.orr@gmail.com // Queue the thread context 39811911SBrandon.Potter@amd.com std::list<ThreadContext *> * tcWaitList; 39911911SBrandon.Potter@amd.com if (futex_map.count(uaddr)) { 40011911SBrandon.Potter@amd.com tcWaitList = futex_map.find(uaddr)->second; 40111911SBrandon.Potter@amd.com } else { 4029112Smarc.orr@gmail.com tcWaitList = new std::list<ThreadContext *>(); 40311911SBrandon.Potter@amd.com futex_map.insert(std::pair< uint64_t, 40411911SBrandon.Potter@amd.com std::list<ThreadContext *> * >(uaddr, tcWaitList)); 40511911SBrandon.Potter@amd.com } 40611911SBrandon.Potter@amd.com tcWaitList->push_back(tc); 4079238Slluc.alvarez@bsc.es DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 4089112Smarc.orr@gmail.com "thread context\n"); 40911911SBrandon.Potter@amd.com tc->suspend(); 4109112Smarc.orr@gmail.com return 0; 41111911SBrandon.Potter@amd.com } else if (op == OS::TGT_FUTEX_WAKE){ 41211911SBrandon.Potter@amd.com int wokenUp = 0; 41311911SBrandon.Potter@amd.com std::list<ThreadContext *> * tcWaitList; 41411911SBrandon.Potter@amd.com if (futex_map.count(uaddr)) { 41511911SBrandon.Potter@amd.com tcWaitList = futex_map.find(uaddr)->second; 4169112Smarc.orr@gmail.com while (tcWaitList->size() > 0 && wokenUp < val) { 41711911SBrandon.Potter@amd.com tcWaitList->front()->activate(); 41811911SBrandon.Potter@amd.com tcWaitList->pop_front(); 41911911SBrandon.Potter@amd.com wokenUp++; 42011911SBrandon.Potter@amd.com } 42111911SBrandon.Potter@amd.com if(tcWaitList->empty()) { 42211911SBrandon.Potter@amd.com futex_map.erase(uaddr); 4239112Smarc.orr@gmail.com delete tcWaitList; 4249112Smarc.orr@gmail.com } 42511911SBrandon.Potter@amd.com } 42611911SBrandon.Potter@amd.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 4279112Smarc.orr@gmail.com "thread contexts\n", wokenUp); 42811911SBrandon.Potter@amd.com return wokenUp; 42911911SBrandon.Potter@amd.com } else { 4309112Smarc.orr@gmail.com warn("sys_futex: op %d is not implemented, just returning...", op); 4319112Smarc.orr@gmail.com return 0; 43211911SBrandon.Potter@amd.com } 43311911SBrandon.Potter@amd.com 4349112Smarc.orr@gmail.com} 4359112Smarc.orr@gmail.com 4362238SN/A 4372238SN/A/// Pseudo Funcs - These functions use a different return convension, 4382238SN/A/// returning a second value in a register other than the normal return register 4392238SN/ASyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 44011851Sbrandon.potter@amd.com LiveProcess *process, ThreadContext *tc); 4412238SN/A 4422238SN/A/// Target getpidPseudo() handler. 4432238SN/ASyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 44411851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 4452238SN/A 4462238SN/A/// Target getuidPseudo() handler. 4472238SN/ASyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 44811851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 4492238SN/A 4502238SN/A/// Target getgidPseudo() handler. 4512238SN/ASyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 45211851Sbrandon.potter@amd.com LiveProcess *p, ThreadContext *tc); 4532238SN/A 4542238SN/A 4551354SN/A/// A readable name for 1,000,000, for converting microseconds to seconds. 4561354SN/Aconst int one_million = 1000000; 45710796Sbrandon.potter@amd.com 45810796Sbrandon.potter@amd.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 4591354SN/A/// by my reckoning. We want to keep this a constant (not use the 4601354SN/A/// real-world time) to keep simulations repeatable. 4611354SN/Aconst unsigned seconds_since_epoch = 1000000000; 4621354SN/A 4631354SN/A/// Helper function to convert current elapsed time to seconds and 4641354SN/A/// microseconds. 4651354SN/Atemplate <class T1, class T2> 4661354SN/Avoid 4671354SN/AgetElapsedTime(T1 &sec, T2 &usec) 4681354SN/A{ 46910796Sbrandon.potter@amd.com int elapsed_usecs = curTick() / SimClock::Int::us; 4701354SN/A sec = elapsed_usecs / one_million; 47110796Sbrandon.potter@amd.com usec = elapsed_usecs % one_million; 4721354SN/A} 4731354SN/A 4741354SN/A////////////////////////////////////////////////////////////////////// 4751354SN/A// 47610796Sbrandon.potter@amd.com// The following emulation functions are generic, but need to be 47710796Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc. 47810796Sbrandon.potter@amd.com// 47910796Sbrandon.potter@amd.com////////////////////////////////////////////////////////////////////// 48010796Sbrandon.potter@amd.com 48110796Sbrandon.potter@amd.com#if NO_STAT64 48210796Sbrandon.potter@amd.com typedef struct stat hst_stat; 48310796Sbrandon.potter@amd.com typedef struct stat hst_stat64; 48410796Sbrandon.potter@amd.com#else 48510796Sbrandon.potter@amd.com typedef struct stat hst_stat; 48610796Sbrandon.potter@amd.com typedef struct stat64 hst_stat64; 487360SN/A#endif 488360SN/A 489360SN/A//// Helper function to convert a host stat buffer to a target stat 490360SN/A//// buffer. Also copies the target buffer out to the simulated 491360SN/A//// memory space. Used by stat(), fstat(), and lstat(). 492360SN/A 493360SN/Atemplate <typename target_stat, typename host_stat> 49411759Sbrandon.potter@amd.comstatic void 4953113Sgblack@eecs.umich.educonvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4963113Sgblack@eecs.umich.edu{ 4973113Sgblack@eecs.umich.edu using namespace TheISA; 4983113Sgblack@eecs.umich.edu 4993113Sgblack@eecs.umich.edu if (fakeTTY) 5003113Sgblack@eecs.umich.edu tgt->st_dev = 0xA; 5013113Sgblack@eecs.umich.edu else 5023113Sgblack@eecs.umich.edu tgt->st_dev = host->st_dev; 5033113Sgblack@eecs.umich.edu tgt->st_dev = TheISA::htog(tgt->st_dev); 5043113Sgblack@eecs.umich.edu tgt->st_ino = host->st_ino; 5053113Sgblack@eecs.umich.edu tgt->st_ino = TheISA::htog(tgt->st_ino); 5063113Sgblack@eecs.umich.edu tgt->st_mode = host->st_mode; 5073113Sgblack@eecs.umich.edu if (fakeTTY) { 50812032Sandreas.sandberg@arm.com // Claim to be a character device 5093113Sgblack@eecs.umich.edu tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 5103113Sgblack@eecs.umich.edu tgt->st_mode |= S_IFCHR; // Set S_IFCHR 5114189Sgblack@eecs.umich.edu } 5124189Sgblack@eecs.umich.edu tgt->st_mode = TheISA::htog(tgt->st_mode); 5133113Sgblack@eecs.umich.edu tgt->st_nlink = host->st_nlink; 5143113Sgblack@eecs.umich.edu tgt->st_nlink = TheISA::htog(tgt->st_nlink); 5153113Sgblack@eecs.umich.edu tgt->st_uid = host->st_uid; 5163113Sgblack@eecs.umich.edu tgt->st_uid = TheISA::htog(tgt->st_uid); 5178737Skoansin.tan@gmail.com tgt->st_gid = host->st_gid; 5183113Sgblack@eecs.umich.edu tgt->st_gid = TheISA::htog(tgt->st_gid); 5198737Skoansin.tan@gmail.com if (fakeTTY) 5203277Sgblack@eecs.umich.edu tgt->st_rdev = 0x880d; 5215515SMichael.Adler@intel.com else 5225515SMichael.Adler@intel.com tgt->st_rdev = host->st_rdev; 5235515SMichael.Adler@intel.com tgt->st_rdev = TheISA::htog(tgt->st_rdev); 5245515SMichael.Adler@intel.com tgt->st_size = host->st_size; 5255515SMichael.Adler@intel.com tgt->st_size = TheISA::htog(tgt->st_size); 5268737Skoansin.tan@gmail.com tgt->st_atimeX = host->st_atime; 5273277Sgblack@eecs.umich.edu tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5288737Skoansin.tan@gmail.com tgt->st_mtimeX = host->st_mtime; 5293277Sgblack@eecs.umich.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5308737Skoansin.tan@gmail.com tgt->st_ctimeX = host->st_ctime; 5313277Sgblack@eecs.umich.edu tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5328737Skoansin.tan@gmail.com // Force the block size to be 8k. This helps to ensure buffered io works 5333113Sgblack@eecs.umich.edu // consistently across different hosts. 5343113Sgblack@eecs.umich.edu tgt->st_blksize = 0x2000; 5353113Sgblack@eecs.umich.edu tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5363113Sgblack@eecs.umich.edu tgt->st_blocks = host->st_blocks; 5378737Skoansin.tan@gmail.com tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5383113Sgblack@eecs.umich.edu} 5398737Skoansin.tan@gmail.com 5403114Sgblack@eecs.umich.edu// Same for stat64 5418737Skoansin.tan@gmail.com 5423114Sgblack@eecs.umich.edutemplate <typename target_stat, typename host_stat64> 5438737Skoansin.tan@gmail.comstatic void 5443114Sgblack@eecs.umich.educonvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5458737Skoansin.tan@gmail.com{ 54611906SBrandon.Potter@amd.com using namespace TheISA; 5474061Sgblack@eecs.umich.edu 5484061Sgblack@eecs.umich.edu convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5498737Skoansin.tan@gmail.com#if defined(STAT_HAVE_NSEC) 5503113Sgblack@eecs.umich.edu tgt->st_atime_nsec = host->st_atime_nsec; 5518737Skoansin.tan@gmail.com tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5523113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5533113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5543113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5553113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5563113Sgblack@eecs.umich.edu#else 55712032Sandreas.sandberg@arm.com tgt->st_atime_nsec = 0; 5583113Sgblack@eecs.umich.edu tgt->st_mtime_nsec = 0; 5593113Sgblack@eecs.umich.edu tgt->st_ctime_nsec = 0; 5604189Sgblack@eecs.umich.edu#endif 5614189Sgblack@eecs.umich.edu} 5623113Sgblack@eecs.umich.edu 5633113Sgblack@eecs.umich.edu//Here are a couple convenience functions 5643113Sgblack@eecs.umich.edutemplate<class OS> 5658737Skoansin.tan@gmail.comstatic void 5663113Sgblack@eecs.umich.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5678737Skoansin.tan@gmail.com hst_stat *host, bool fakeTTY = false) 5683113Sgblack@eecs.umich.edu{ 5698737Skoansin.tan@gmail.com typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5703113Sgblack@eecs.umich.edu tgt_stat_buf tgt(addr); 5713113Sgblack@eecs.umich.edu convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5723113Sgblack@eecs.umich.edu tgt.copyOut(mem); 5733113Sgblack@eecs.umich.edu} 5743113Sgblack@eecs.umich.edu 5753113Sgblack@eecs.umich.edutemplate<class OS> 5763113Sgblack@eecs.umich.edustatic void 57711906SBrandon.Potter@amd.comcopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5783113Sgblack@eecs.umich.edu hst_stat64 *host, bool fakeTTY = false) 57912032Sandreas.sandberg@arm.com{ 5808852Sandreas.hansson@arm.com typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 58111906SBrandon.Potter@amd.com tgt_stat_buf tgt(addr); 5823113Sgblack@eecs.umich.edu convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5833113Sgblack@eecs.umich.edu tgt.copyOut(mem); 5843113Sgblack@eecs.umich.edu} 5853113Sgblack@eecs.umich.edu 5863113Sgblack@eecs.umich.edu/// Target ioctl() handler. For the most part, programs call ioctl() 5873113Sgblack@eecs.umich.edu/// only to find out if their stdout is a tty, to determine whether to 5883113Sgblack@eecs.umich.edu/// do line or block buffering. We always claim that output fds are 5893113Sgblack@eecs.umich.edu/// not TTYs to provide repeatable results. 59012032Sandreas.sandberg@arm.comtemplate <class OS> 5918852Sandreas.hansson@arm.comSyscallReturn 59211906SBrandon.Potter@amd.comioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5933113Sgblack@eecs.umich.edu ThreadContext *tc) 5943113Sgblack@eecs.umich.edu{ 5953113Sgblack@eecs.umich.edu int index = 0; 5966686Stjones1@inf.ed.ac.uk int fd = process->getSyscallArg(tc, index); 5973113Sgblack@eecs.umich.edu unsigned req = process->getSyscallArg(tc, index); 5983113Sgblack@eecs.umich.edu 5993113Sgblack@eecs.umich.edu DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 60011759Sbrandon.potter@amd.com 60112032Sandreas.sandberg@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 60211759Sbrandon.potter@amd.com // doesn't map to any simulator fd: not a valid target fd 60311759Sbrandon.potter@amd.com return -EBADF; 60411759Sbrandon.potter@amd.com } 60511759Sbrandon.potter@amd.com 60611759Sbrandon.potter@amd.com if (OS::isTtyReq(req)) { 60711812Sbaz21@cam.ac.uk return -ENOTTY; 60811812Sbaz21@cam.ac.uk } 60911812Sbaz21@cam.ac.uk 61011759Sbrandon.potter@amd.com warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 61111812Sbaz21@cam.ac.uk fd, req, tc->pcState()); 61211759Sbrandon.potter@amd.com return -ENOTTY; 61311759Sbrandon.potter@amd.com} 61411759Sbrandon.potter@amd.com 61511759Sbrandon.potter@amd.comtemplate <class OS> 61611759Sbrandon.potter@amd.comstatic SyscallReturn 61711759Sbrandon.potter@amd.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 61811759Sbrandon.potter@amd.com ThreadContext *tc, int index) 61911812Sbaz21@cam.ac.uk{ 62011812Sbaz21@cam.ac.uk std::string path; 62111812Sbaz21@cam.ac.uk 62211812Sbaz21@cam.ac.uk if (!tc->getMemProxy().tryReadString(path, 62311812Sbaz21@cam.ac.uk process->getSyscallArg(tc, index))) 62411812Sbaz21@cam.ac.uk return -EFAULT; 62511812Sbaz21@cam.ac.uk 62611759Sbrandon.potter@amd.com if (path == "/dev/sysdev0") { 62711759Sbrandon.potter@amd.com // This is a memory-mapped high-resolution timer device on Alpha. 62811812Sbaz21@cam.ac.uk // We don't support it, so just punt. 62911812Sbaz21@cam.ac.uk warn("Ignoring open(%s, ...)\n", path); 63011759Sbrandon.potter@amd.com return -ENOENT; 63111812Sbaz21@cam.ac.uk } 63211812Sbaz21@cam.ac.uk 63311812Sbaz21@cam.ac.uk int tgtFlags = process->getSyscallArg(tc, index); 63411812Sbaz21@cam.ac.uk int mode = process->getSyscallArg(tc, index); 63511812Sbaz21@cam.ac.uk int hostFlags = 0; 63611812Sbaz21@cam.ac.uk 63711812Sbaz21@cam.ac.uk // translate open flags 63811759Sbrandon.potter@amd.com for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 63911759Sbrandon.potter@amd.com if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 64011759Sbrandon.potter@amd.com tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 64111759Sbrandon.potter@amd.com hostFlags |= OS::openFlagTable[i].hostFlag; 642378SN/A } 643378SN/A } 6449141Smarc.orr@gmail.com 6459141Smarc.orr@gmail.com // any target flags left? 646360SN/A if (tgtFlags != 0) 6471450SN/A warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 64811856Sbrandon.potter@amd.com 649360SN/A#ifdef __CYGWIN32__ 6506701Sgblack@eecs.umich.edu hostFlags |= O_BINARY; 65111856Sbrandon.potter@amd.com#endif 65211856Sbrandon.potter@amd.com 653360SN/A // Adjust path for current working directory 65410930Sbrandon.potter@amd.com path = process->fullPath(path); 655360SN/A 65611856Sbrandon.potter@amd.com DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 65711856Sbrandon.potter@amd.com 65810496Ssteve.reinhardt@amd.com int fd; 65911856Sbrandon.potter@amd.com int local_errno; 66011856Sbrandon.potter@amd.com if (startswith(path, "/proc/") || startswith(path, "/system/") || 6611458SN/A startswith(path, "/platform/") || startswith(path, "/sys/")) { 662360SN/A // It's a proc/sys entry and requires special handling 66311856Sbrandon.potter@amd.com fd = OS::openSpecialFile(path, process, tc); 66411856Sbrandon.potter@amd.com local_errno = ENOENT; 66511856Sbrandon.potter@amd.com } else { 66611856Sbrandon.potter@amd.com // open the file 66711856Sbrandon.potter@amd.com fd = open(path.c_str(), hostFlags, mode); 66811856Sbrandon.potter@amd.com local_errno = errno; 66911856Sbrandon.potter@amd.com } 67011856Sbrandon.potter@amd.com 67110496Ssteve.reinhardt@amd.com if (fd == -1) 67211856Sbrandon.potter@amd.com return -local_errno; 67311856Sbrandon.potter@amd.com 67411856Sbrandon.potter@amd.com return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false); 67511856Sbrandon.potter@amd.com} 67611856Sbrandon.potter@amd.com 67710930Sbrandon.potter@amd.com/// Target open() handler. 6789141Smarc.orr@gmail.comtemplate <class OS> 679360SN/ASyscallReturn 680360SN/AopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 681360SN/A ThreadContext *tc) 68211907SBrandon.Potter@amd.com{ 68311907SBrandon.Potter@amd.com return openFunc<OS>(desc, callnum, process, tc, 0); 68411907SBrandon.Potter@amd.com} 685360SN/A 68611907SBrandon.Potter@amd.com/// Target openat() handler. 68711907SBrandon.Potter@amd.comtemplate <class OS> 68811907SBrandon.Potter@amd.comSyscallReturn 68911907SBrandon.Potter@amd.comopenatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 69011907SBrandon.Potter@amd.com ThreadContext *tc) 69111907SBrandon.Potter@amd.com{ 69211907SBrandon.Potter@amd.com int index = 0; 69311907SBrandon.Potter@amd.com int dirfd = process->getSyscallArg(tc, index); 69411907SBrandon.Potter@amd.com if (dirfd != OS::TGT_AT_FDCWD) 69511907SBrandon.Potter@amd.com warn("openat: first argument not AT_FDCWD; unlikely to work"); 69611907SBrandon.Potter@amd.com return openFunc<OS>(desc, callnum, process, tc, 1); 69711907SBrandon.Potter@amd.com} 69811907SBrandon.Potter@amd.com 69911907SBrandon.Potter@amd.com/// Target sysinfo() handler. 700360SN/Atemplate <class OS> 70111907SBrandon.Potter@amd.comSyscallReturn 7021458SN/AsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 703360SN/A ThreadContext *tc) 70411907SBrandon.Potter@amd.com{ 70511907SBrandon.Potter@amd.com 70611907SBrandon.Potter@amd.com int index = 0; 70711907SBrandon.Potter@amd.com TypedBufferArg<typename OS::tgt_sysinfo> 70811907SBrandon.Potter@amd.com sysinfo(process->getSyscallArg(tc, index)); 70911907SBrandon.Potter@amd.com 71011907SBrandon.Potter@amd.com sysinfo->uptime=seconds_since_epoch; 71111907SBrandon.Potter@amd.com sysinfo->totalram=process->system->memSize(); 71211907SBrandon.Potter@amd.com 71311907SBrandon.Potter@amd.com sysinfo.copyOut(tc->getMemProxy()); 714360SN/A 71511907SBrandon.Potter@amd.com return 0; 71611907SBrandon.Potter@amd.com} 71711907SBrandon.Potter@amd.com 718360SN/A/// Target chmod() handler. 719360SN/Atemplate <class OS> 72011907SBrandon.Potter@amd.comSyscallReturn 72111907SBrandon.Potter@amd.comchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 72211907SBrandon.Potter@amd.com ThreadContext *tc) 72311907SBrandon.Potter@amd.com{ 724360SN/A std::string path; 72511907SBrandon.Potter@amd.com 726360SN/A int index = 0; 727360SN/A if (!tc->getMemProxy().tryReadString(path, 72811907SBrandon.Potter@amd.com process->getSyscallArg(tc, index))) { 7293669Sbinkertn@umich.edu return -EFAULT; 73011907SBrandon.Potter@amd.com } 73111907SBrandon.Potter@amd.com 73211907SBrandon.Potter@amd.com uint32_t mode = process->getSyscallArg(tc, index); 73311907SBrandon.Potter@amd.com mode_t hostMode = 0; 73411907SBrandon.Potter@amd.com 73511907SBrandon.Potter@amd.com // XXX translate mode flags via OS::something??? 73611907SBrandon.Potter@amd.com hostMode = mode; 73711907SBrandon.Potter@amd.com 73811907SBrandon.Potter@amd.com // Adjust path for current working directory 73911907SBrandon.Potter@amd.com path = process->fullPath(path); 74011907SBrandon.Potter@amd.com 74111907SBrandon.Potter@amd.com // do the chmod 74211907SBrandon.Potter@amd.com int result = chmod(path.c_str(), hostMode); 74311907SBrandon.Potter@amd.com if (result < 0) 74411907SBrandon.Potter@amd.com return -errno; 74511907SBrandon.Potter@amd.com 74611907SBrandon.Potter@amd.com return 0; 74711907SBrandon.Potter@amd.com} 74811907SBrandon.Potter@amd.com 74913371Sciro.santilli@arm.com 75011907SBrandon.Potter@amd.com/// Target fchmod() handler. 7511706SN/Atemplate <class OS> 75211907SBrandon.Potter@amd.comSyscallReturn 75311907SBrandon.Potter@amd.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 75411907SBrandon.Potter@amd.com ThreadContext *tc) 75511907SBrandon.Potter@amd.com{ 75611907SBrandon.Potter@amd.com int index = 0; 75711907SBrandon.Potter@amd.com int fd = process->getSyscallArg(tc, index); 75810496Ssteve.reinhardt@amd.com if (fd < 0 || process->sim_fd(fd) < 0) { 75910496Ssteve.reinhardt@amd.com // doesn't map to any simulator fd: not a valid target fd 76011907SBrandon.Potter@amd.com return -EBADF; 76111907SBrandon.Potter@amd.com } 76211907SBrandon.Potter@amd.com 76311907SBrandon.Potter@amd.com uint32_t mode = process->getSyscallArg(tc, index); 76411907SBrandon.Potter@amd.com mode_t hostMode = 0; 76511907SBrandon.Potter@amd.com 76610496Ssteve.reinhardt@amd.com // XXX translate mode flags via OS::someting??? 76711907SBrandon.Potter@amd.com hostMode = mode; 76811907SBrandon.Potter@amd.com 76911907SBrandon.Potter@amd.com // do the fchmod 77011907SBrandon.Potter@amd.com int result = fchmod(process->sim_fd(fd), hostMode); 77110496Ssteve.reinhardt@amd.com if (result < 0) 77210496Ssteve.reinhardt@amd.com return -errno; 77311907SBrandon.Potter@amd.com 77411907SBrandon.Potter@amd.com return 0; 77511907SBrandon.Potter@amd.com} 77611907SBrandon.Potter@amd.com 77711907SBrandon.Potter@amd.com/// Target mremap() handler. 77811907SBrandon.Potter@amd.comtemplate <class OS> 77911907SBrandon.Potter@amd.comSyscallReturn 78011907SBrandon.Potter@amd.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 78111907SBrandon.Potter@amd.com{ 78211907SBrandon.Potter@amd.com int index = 0; 78311907SBrandon.Potter@amd.com Addr start = process->getSyscallArg(tc, index); 78411907SBrandon.Potter@amd.com uint64_t old_length = process->getSyscallArg(tc, index); 78511907SBrandon.Potter@amd.com uint64_t new_length = process->getSyscallArg(tc, index); 78611907SBrandon.Potter@amd.com uint64_t flags = process->getSyscallArg(tc, index); 78711907SBrandon.Potter@amd.com uint64_t provided_address = 0; 78811907SBrandon.Potter@amd.com bool use_provided_address = flags & OS::TGT_MREMAP_FIXED; 78911907SBrandon.Potter@amd.com 79011907SBrandon.Potter@amd.com if (use_provided_address) 79111907SBrandon.Potter@amd.com provided_address = process->getSyscallArg(tc, index); 79211907SBrandon.Potter@amd.com 79311907SBrandon.Potter@amd.com if ((start % TheISA::VMPageSize != 0) || 79411907SBrandon.Potter@amd.com (new_length % TheISA::VMPageSize != 0) || 79511907SBrandon.Potter@amd.com (provided_address % TheISA::VMPageSize != 0)) { 79611907SBrandon.Potter@amd.com warn("mremap failing: arguments not page aligned"); 79711907SBrandon.Potter@amd.com return -EINVAL; 798360SN/A } 79911907SBrandon.Potter@amd.com 80011907SBrandon.Potter@amd.com if (new_length > old_length) { 80111907SBrandon.Potter@amd.com if ((start + old_length) == process->mmap_end && 80211907SBrandon.Potter@amd.com (!use_provided_address || provided_address == start)) { 80311907SBrandon.Potter@amd.com uint64_t diff = new_length - old_length; 80411907SBrandon.Potter@amd.com process->allocateMem(process->mmap_end, diff); 80511907SBrandon.Potter@amd.com process->mmap_end += diff; 80611907SBrandon.Potter@amd.com return start; 80711907SBrandon.Potter@amd.com } else { 80811907SBrandon.Potter@amd.com if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { 80911907SBrandon.Potter@amd.com warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 81011907SBrandon.Potter@amd.com return -ENOMEM; 81111907SBrandon.Potter@amd.com } else { 812360SN/A uint64_t new_start = use_provided_address ? 813360SN/A provided_address : process->mmap_end; 81410027SChris.Adeniyi-Jones@arm.com process->pTable->remap(start, old_length, new_start); 81510027SChris.Adeniyi-Jones@arm.com warn("mremapping to new vaddr %08p-%08p, adding %d\n", 81610027SChris.Adeniyi-Jones@arm.com new_start, new_start + new_length, 81711851Sbrandon.potter@amd.com new_length - old_length); 81810027SChris.Adeniyi-Jones@arm.com // add on the remaining unallocated pages 81910027SChris.Adeniyi-Jones@arm.com process->allocateMem(new_start + old_length, 82011907SBrandon.Potter@amd.com new_length - old_length, 82110027SChris.Adeniyi-Jones@arm.com use_provided_address /* clobber */); 82210027SChris.Adeniyi-Jones@arm.com if (!use_provided_address) 82310027SChris.Adeniyi-Jones@arm.com process->mmap_end += new_length; 82410027SChris.Adeniyi-Jones@arm.com if (use_provided_address && 82510027SChris.Adeniyi-Jones@arm.com new_start + new_length > process->mmap_end) { 82611851Sbrandon.potter@amd.com // something fishy going on here, at least notify the user 82711851Sbrandon.potter@amd.com // @todo: increase mmap_end? 82810027SChris.Adeniyi-Jones@arm.com warn("mmap region limit exceeded with MREMAP_FIXED\n"); 82911907SBrandon.Potter@amd.com } 83010027SChris.Adeniyi-Jones@arm.com warn("returning %08p as start\n", new_start); 83110027SChris.Adeniyi-Jones@arm.com return new_start; 83210633Smichaelupton@gmail.com } 83310633Smichaelupton@gmail.com } 83410633Smichaelupton@gmail.com } else { 83511851Sbrandon.potter@amd.com if (use_provided_address && provided_address != start) 83610633Smichaelupton@gmail.com process->pTable->remap(start, new_length, provided_address); 83710633Smichaelupton@gmail.com process->pTable->unmap(start + new_length, old_length - new_length); 83810633Smichaelupton@gmail.com return use_provided_address ? provided_address : start; 83910633Smichaelupton@gmail.com } 84010633Smichaelupton@gmail.com} 84110633Smichaelupton@gmail.com 84210633Smichaelupton@gmail.com/// Target stat() handler. 84310633Smichaelupton@gmail.comtemplate <class OS> 84410633Smichaelupton@gmail.comSyscallReturn 84510633Smichaelupton@gmail.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 84610203SAli.Saidi@ARM.com ThreadContext *tc) 84710203SAli.Saidi@ARM.com{ 84810203SAli.Saidi@ARM.com std::string path; 84911851Sbrandon.potter@amd.com 85011851Sbrandon.potter@amd.com int index = 0; 85110203SAli.Saidi@ARM.com if (!tc->getMemProxy().tryReadString(path, 85210203SAli.Saidi@ARM.com process->getSyscallArg(tc, index))) { 85310203SAli.Saidi@ARM.com return -EFAULT; 85410203SAli.Saidi@ARM.com } 85510203SAli.Saidi@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 85610203SAli.Saidi@ARM.com 85710203SAli.Saidi@ARM.com // Adjust path for current working directory 85810203SAli.Saidi@ARM.com path = process->fullPath(path); 85910203SAli.Saidi@ARM.com 86010203SAli.Saidi@ARM.com struct stat hostBuf; 86110203SAli.Saidi@ARM.com int result = stat(path.c_str(), &hostBuf); 86211851Sbrandon.potter@amd.com 86311851Sbrandon.potter@amd.com if (result < 0) 86410203SAli.Saidi@ARM.com return -errno; 86510203SAli.Saidi@ARM.com 86610203SAli.Saidi@ARM.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 86710203SAli.Saidi@ARM.com 86810203SAli.Saidi@ARM.com return 0; 86910203SAli.Saidi@ARM.com} 87010203SAli.Saidi@ARM.com 87110203SAli.Saidi@ARM.com 87210850SGiacomo.Gabrielli@arm.com/// Target stat64() handler. 87310850SGiacomo.Gabrielli@arm.comtemplate <class OS> 87410850SGiacomo.Gabrielli@arm.comSyscallReturn 87511851Sbrandon.potter@amd.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 87610850SGiacomo.Gabrielli@arm.com ThreadContext *tc) 87710850SGiacomo.Gabrielli@arm.com{ 87810850SGiacomo.Gabrielli@arm.com std::string path; 87910850SGiacomo.Gabrielli@arm.com 88010850SGiacomo.Gabrielli@arm.com int index = 0; 88110850SGiacomo.Gabrielli@arm.com if (!tc->getMemProxy().tryReadString(path, 88210850SGiacomo.Gabrielli@arm.com process->getSyscallArg(tc, index))) 88310850SGiacomo.Gabrielli@arm.com return -EFAULT; 88410850SGiacomo.Gabrielli@arm.com Addr bufPtr = process->getSyscallArg(tc, index); 88510850SGiacomo.Gabrielli@arm.com 88610850SGiacomo.Gabrielli@arm.com // Adjust path for current working directory 88710850SGiacomo.Gabrielli@arm.com path = process->fullPath(path); 88810850SGiacomo.Gabrielli@arm.com 88910850SGiacomo.Gabrielli@arm.com#if NO_STAT64 89010850SGiacomo.Gabrielli@arm.com struct stat hostBuf; 89110850SGiacomo.Gabrielli@arm.com int result = stat(path.c_str(), &hostBuf); 89210850SGiacomo.Gabrielli@arm.com#else 89310850SGiacomo.Gabrielli@arm.com struct stat64 hostBuf; 89410850SGiacomo.Gabrielli@arm.com int result = stat64(path.c_str(), &hostBuf); 89510850SGiacomo.Gabrielli@arm.com#endif 89610850SGiacomo.Gabrielli@arm.com 89710850SGiacomo.Gabrielli@arm.com if (result < 0) 89810850SGiacomo.Gabrielli@arm.com return -errno; 89910850SGiacomo.Gabrielli@arm.com 90010850SGiacomo.Gabrielli@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 90110850SGiacomo.Gabrielli@arm.com 90210850SGiacomo.Gabrielli@arm.com return 0; 90310850SGiacomo.Gabrielli@arm.com} 90410850SGiacomo.Gabrielli@arm.com 90510850SGiacomo.Gabrielli@arm.com 90610850SGiacomo.Gabrielli@arm.com/// Target fstatat64() handler. 90710850SGiacomo.Gabrielli@arm.comtemplate <class OS> 9086640Svince@csl.cornell.eduSyscallReturn 9096640Svince@csl.cornell.edufstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9106640Svince@csl.cornell.edu ThreadContext *tc) 91111851Sbrandon.potter@amd.com{ 91211851Sbrandon.potter@amd.com int index = 0; 9136640Svince@csl.cornell.edu int dirfd = process->getSyscallArg(tc, index); 9146640Svince@csl.cornell.edu if (dirfd != OS::TGT_AT_FDCWD) 9156701Sgblack@eecs.umich.edu warn("openat: first argument not AT_FDCWD; unlikely to work"); 9166701Sgblack@eecs.umich.edu 91710793Sbrandon.potter@amd.com std::string path; 9186640Svince@csl.cornell.edu if (!tc->getMemProxy().tryReadString(path, 91911758Sbrandon.potter@amd.com process->getSyscallArg(tc, index))) 92011758Sbrandon.potter@amd.com return -EFAULT; 92111758Sbrandon.potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 9226640Svince@csl.cornell.edu 9238706Sandreas.hansson@arm.com // Adjust path for current working directory 9246640Svince@csl.cornell.edu path = process->fullPath(path); 9256701Sgblack@eecs.umich.edu 9266640Svince@csl.cornell.edu#if NO_STAT64 927360SN/A struct stat hostBuf; 9281999SN/A int result = stat(path.c_str(), &hostBuf); 9291999SN/A#else 9301999SN/A struct stat64 hostBuf; 93111851Sbrandon.potter@amd.com int result = stat64(path.c_str(), &hostBuf); 9322680Sktlim@umich.edu#endif 9331999SN/A 9341999SN/A if (result < 0) 9351999SN/A return -errno; 9366701Sgblack@eecs.umich.edu 9378852Sandreas.hansson@arm.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9386701Sgblack@eecs.umich.edu 9391999SN/A return 0; 9406701Sgblack@eecs.umich.edu} 9411999SN/A 9426701Sgblack@eecs.umich.edu 9431999SN/A/// Target fstat64() handler. 9441999SN/Atemplate <class OS> 9451999SN/ASyscallReturn 9461999SN/Afstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9471999SN/A ThreadContext *tc) 9483669Sbinkertn@umich.edu{ 9493669Sbinkertn@umich.edu int index = 0; 9503669Sbinkertn@umich.edu int fd = process->getSyscallArg(tc, index); 9511999SN/A Addr bufPtr = process->getSyscallArg(tc, index); 9521999SN/A if (fd < 0 || process->sim_fd(fd) < 0) { 9531999SN/A // doesn't map to any simulator fd: not a valid target fd 9542218SN/A return -EBADF; 9551999SN/A } 9561999SN/A 9571999SN/A#if NO_STAT64 9581999SN/A struct stat hostBuf; 95913570Sbrandon.potter@amd.com int result = fstat(process->sim_fd(fd), &hostBuf); 96013570Sbrandon.potter@amd.com#else 96113570Sbrandon.potter@amd.com struct stat64 hostBuf; 96213570Sbrandon.potter@amd.com int result = fstat64(process->sim_fd(fd), &hostBuf); 96313570Sbrandon.potter@amd.com#endif 96413570Sbrandon.potter@amd.com 96513570Sbrandon.potter@amd.com if (result < 0) 96613570Sbrandon.potter@amd.com return -errno; 96713570Sbrandon.potter@amd.com 96813570Sbrandon.potter@amd.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 96913570Sbrandon.potter@amd.com 97013570Sbrandon.potter@amd.com return 0; 97113570Sbrandon.potter@amd.com} 97213570Sbrandon.potter@amd.com 97313570Sbrandon.potter@amd.com 97413570Sbrandon.potter@amd.com/// Target lstat() handler. 97513570Sbrandon.potter@amd.comtemplate <class OS> 97613570Sbrandon.potter@amd.comSyscallReturn 97713570Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 97813570Sbrandon.potter@amd.com ThreadContext *tc) 97913570Sbrandon.potter@amd.com{ 98013570Sbrandon.potter@amd.com std::string path; 98113570Sbrandon.potter@amd.com 98213570Sbrandon.potter@amd.com int index = 0; 98313570Sbrandon.potter@amd.com if (!tc->getMemProxy().tryReadString(path, 98413570Sbrandon.potter@amd.com process->getSyscallArg(tc, index))) { 98513570Sbrandon.potter@amd.com return -EFAULT; 98613570Sbrandon.potter@amd.com } 98713570Sbrandon.potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 98813570Sbrandon.potter@amd.com 98913570Sbrandon.potter@amd.com // Adjust path for current working directory 99013570Sbrandon.potter@amd.com path = process->fullPath(path); 99113570Sbrandon.potter@amd.com 99213570Sbrandon.potter@amd.com struct stat hostBuf; 99313570Sbrandon.potter@amd.com int result = lstat(path.c_str(), &hostBuf); 99413570Sbrandon.potter@amd.com 99513570Sbrandon.potter@amd.com if (result < 0) 99613570Sbrandon.potter@amd.com return -errno; 99713570Sbrandon.potter@amd.com 99813570Sbrandon.potter@amd.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 99913570Sbrandon.potter@amd.com 100013570Sbrandon.potter@amd.com return 0; 100113570Sbrandon.potter@amd.com} 100213570Sbrandon.potter@amd.com 100313570Sbrandon.potter@amd.com/// Target lstat64() handler. 100413570Sbrandon.potter@amd.comtemplate <class OS> 100513570Sbrandon.potter@amd.comSyscallReturn 100613570Sbrandon.potter@amd.comlstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 100713570Sbrandon.potter@amd.com ThreadContext *tc) 100813570Sbrandon.potter@amd.com{ 100913570Sbrandon.potter@amd.com std::string path; 101013570Sbrandon.potter@amd.com 101113570Sbrandon.potter@amd.com int index = 0; 101213570Sbrandon.potter@amd.com if (!tc->getMemProxy().tryReadString(path, 101313570Sbrandon.potter@amd.com process->getSyscallArg(tc, index))) { 101413570Sbrandon.potter@amd.com return -EFAULT; 101513570Sbrandon.potter@amd.com } 101613570Sbrandon.potter@amd.com Addr bufPtr = process->getSyscallArg(tc, index); 101713570Sbrandon.potter@amd.com 101813570Sbrandon.potter@amd.com // Adjust path for current working directory 101913570Sbrandon.potter@amd.com path = process->fullPath(path); 102013570Sbrandon.potter@amd.com 102113570Sbrandon.potter@amd.com#if NO_STAT64 102213570Sbrandon.potter@amd.com struct stat hostBuf; 102313570Sbrandon.potter@amd.com int result = lstat(path.c_str(), &hostBuf); 102413570Sbrandon.potter@amd.com#else 102513570Sbrandon.potter@amd.com struct stat64 hostBuf; 102613570Sbrandon.potter@amd.com int result = lstat64(path.c_str(), &hostBuf); 102713570Sbrandon.potter@amd.com#endif 102813570Sbrandon.potter@amd.com 102913570Sbrandon.potter@amd.com if (result < 0) 103013570Sbrandon.potter@amd.com return -errno; 103113570Sbrandon.potter@amd.com 103213570Sbrandon.potter@amd.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10331999SN/A 10341999SN/A return 0; 10351999SN/A} 10361999SN/A 103711856Sbrandon.potter@amd.com/// Target fstat() handler. 10381999SN/Atemplate <class OS> 10396701Sgblack@eecs.umich.eduSyscallReturn 104011856Sbrandon.potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 104111856Sbrandon.potter@amd.com ThreadContext *tc) 104210931Sbrandon.potter@amd.com{ 104311856Sbrandon.potter@amd.com int index = 0; 104411856Sbrandon.potter@amd.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 10451999SN/A Addr bufPtr = process->getSyscallArg(tc, index); 104611856Sbrandon.potter@amd.com 10471999SN/A DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 104811856Sbrandon.potter@amd.com 10491999SN/A if (fd < 0) 105011856Sbrandon.potter@amd.com return -EBADF; 10511999SN/A 105211856Sbrandon.potter@amd.com struct stat hostBuf; 10531999SN/A int result = fstat(fd, &hostBuf); 10541999SN/A 10555877Shsul@eecs.umich.edu if (result < 0) 10565877Shsul@eecs.umich.edu return -errno; 10575877Shsul@eecs.umich.edu 105811851Sbrandon.potter@amd.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); 10595877Shsul@eecs.umich.edu 10606701Sgblack@eecs.umich.edu return 0; 10616701Sgblack@eecs.umich.edu} 10626701Sgblack@eecs.umich.edu 10636701Sgblack@eecs.umich.edu 10646701Sgblack@eecs.umich.edu/// Target statfs() handler. 106510027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 106610027SChris.Adeniyi-Jones@arm.comSyscallReturn 106710027SChris.Adeniyi-Jones@arm.comstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 106810027SChris.Adeniyi-Jones@arm.com ThreadContext *tc) 106910027SChris.Adeniyi-Jones@arm.com{ 10705877Shsul@eecs.umich.edu std::string path; 107110318Sandreas.hansson@arm.com 107210318Sandreas.hansson@arm.com int index = 0; 10735877Shsul@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 10745877Shsul@eecs.umich.edu process->getSyscallArg(tc, index))) { 10755877Shsul@eecs.umich.edu return -EFAULT; 10765877Shsul@eecs.umich.edu } 107710486Stjablin@gmail.com Addr bufPtr = process->getSyscallArg(tc, index); 107810486Stjablin@gmail.com 10795877Shsul@eecs.umich.edu // Adjust path for current working directory 108011905SBrandon.Potter@amd.com path = process->fullPath(path); 108111905SBrandon.Potter@amd.com 108211905SBrandon.Potter@amd.com struct statfs hostBuf; 108311905SBrandon.Potter@amd.com int result = statfs(path.c_str(), &hostBuf); 108410027SChris.Adeniyi-Jones@arm.com 108512206Srico.amslinger@informatik.uni-augsburg.de if (result < 0) 108612206Srico.amslinger@informatik.uni-augsburg.de return -errno; 10875877Shsul@eecs.umich.edu 108811905SBrandon.Potter@amd.com OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 108911905SBrandon.Potter@amd.com 10905877Shsul@eecs.umich.edu return 0; 10915877Shsul@eecs.umich.edu} 109210027SChris.Adeniyi-Jones@arm.com 10935877Shsul@eecs.umich.edu 10945877Shsul@eecs.umich.edu/// Target fstatfs() handler. 10955877Shsul@eecs.umich.edutemplate <class OS> 109612206Srico.amslinger@informatik.uni-augsburg.deSyscallReturn 109712206Srico.amslinger@informatik.uni-augsburg.defstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 109812206Srico.amslinger@informatik.uni-augsburg.de ThreadContext *tc) 109912206Srico.amslinger@informatik.uni-augsburg.de{ 110012206Srico.amslinger@informatik.uni-augsburg.de int index = 0; 110112206Srico.amslinger@informatik.uni-augsburg.de int fd = process->sim_fd(process->getSyscallArg(tc, index)); 110212206Srico.amslinger@informatik.uni-augsburg.de Addr bufPtr = process->getSyscallArg(tc, index); 110312206Srico.amslinger@informatik.uni-augsburg.de 110412206Srico.amslinger@informatik.uni-augsburg.de if (fd < 0) 110510027SChris.Adeniyi-Jones@arm.com return -EBADF; 110610027SChris.Adeniyi-Jones@arm.com 110710027SChris.Adeniyi-Jones@arm.com struct statfs hostBuf; 110810027SChris.Adeniyi-Jones@arm.com int result = fstatfs(fd, &hostBuf); 11095877Shsul@eecs.umich.edu 111010027SChris.Adeniyi-Jones@arm.com if (result < 0) 111110027SChris.Adeniyi-Jones@arm.com return -errno; 111210027SChris.Adeniyi-Jones@arm.com 111310027SChris.Adeniyi-Jones@arm.com OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 111412206Srico.amslinger@informatik.uni-augsburg.de 111512206Srico.amslinger@informatik.uni-augsburg.de return 0; 111612206Srico.amslinger@informatik.uni-augsburg.de} 111712206Srico.amslinger@informatik.uni-augsburg.de 111810027SChris.Adeniyi-Jones@arm.com 111910027SChris.Adeniyi-Jones@arm.com/// Target writev() handler. 112010027SChris.Adeniyi-Jones@arm.comtemplate <class OS> 112110027SChris.Adeniyi-Jones@arm.comSyscallReturn 112210027SChris.Adeniyi-Jones@arm.comwritevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 112310027SChris.Adeniyi-Jones@arm.com ThreadContext *tc) 11245877Shsul@eecs.umich.edu{ 11255877Shsul@eecs.umich.edu int index = 0; 11265877Shsul@eecs.umich.edu int fd = process->getSyscallArg(tc, index); 112710027SChris.Adeniyi-Jones@arm.com if (fd < 0 || process->sim_fd(fd) < 0) { 112810027SChris.Adeniyi-Jones@arm.com // doesn't map to any simulator fd: not a valid target fd 11298601Ssteve.reinhardt@amd.com return -EBADF; 113010027SChris.Adeniyi-Jones@arm.com } 11315877Shsul@eecs.umich.edu 11325877Shsul@eecs.umich.edu SETranslatingPortProxy &p = tc->getMemProxy(); 11331999SN/A uint64_t tiov_base = process->getSyscallArg(tc, index); 1134378SN/A size_t count = process->getSyscallArg(tc, index); 1135360SN/A struct iovec hiov[count]; 11361450SN/A for (size_t i = 0; i < count; ++i) { 113711851Sbrandon.potter@amd.com typename OS::tgt_iovec tiov; 11382680Sktlim@umich.edu 1139360SN/A p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 1140360SN/A (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 1141360SN/A hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 11426701Sgblack@eecs.umich.edu hiov[i].iov_base = new char [hiov[i].iov_len]; 11438852Sandreas.hansson@arm.com p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 11446701Sgblack@eecs.umich.edu hiov[i].iov_len); 11456701Sgblack@eecs.umich.edu } 11466701Sgblack@eecs.umich.edu 11476701Sgblack@eecs.umich.edu int result = writev(process->sim_fd(fd), hiov, count); 1148360SN/A 11493669Sbinkertn@umich.edu for (size_t i = 0; i < count; ++i) 11503669Sbinkertn@umich.edu delete [] (char *)hiov[i].iov_base; 11513669Sbinkertn@umich.edu 1152360SN/A if (result < 0) 1153360SN/A return -errno; 1154360SN/A 1155360SN/A return 0; 11562218SN/A} 1157360SN/A 11588706Sandreas.hansson@arm.com 1159360SN/A/// Target mmap() handler. 11601458SN/A/// 1161360SN/A/// We don't really handle mmap(). If the target is mmaping an 1162360SN/A/// anonymous region or /dev/zero, we can get away with doing basically 1163360SN/A/// nothing (since memory is initialized to zero and the simulator 11645074Ssaidi@eecs.umich.edu/// doesn't really check addresses anyway). 11655074Ssaidi@eecs.umich.edu/// 11665074Ssaidi@eecs.umich.edutemplate <class OS> 116711851Sbrandon.potter@amd.comSyscallReturn 11685074Ssaidi@eecs.umich.edummapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 11695074Ssaidi@eecs.umich.edu{ 11705074Ssaidi@eecs.umich.edu int index = 0; 11715074Ssaidi@eecs.umich.edu Addr start = p->getSyscallArg(tc, index); 11726701Sgblack@eecs.umich.edu uint64_t length = p->getSyscallArg(tc, index); 11738852Sandreas.hansson@arm.com index++; // int prot = p->getSyscallArg(tc, index); 11746701Sgblack@eecs.umich.edu int flags = p->getSyscallArg(tc, index); 11755074Ssaidi@eecs.umich.edu int tgt_fd = p->getSyscallArg(tc, index); 11766701Sgblack@eecs.umich.edu // int offset = p->getSyscallArg(tc, index); 11775074Ssaidi@eecs.umich.edu 11785074Ssaidi@eecs.umich.edu if (length > 0x100000000ULL) 11795074Ssaidi@eecs.umich.edu warn("mmap length argument %#x is unreasonably large.\n", length); 11805074Ssaidi@eecs.umich.edu 11815208Ssaidi@eecs.umich.edu if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 11825208Ssaidi@eecs.umich.edu Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 11835208Ssaidi@eecs.umich.edu if (!fd_map || fd_map->fd < 0) { 11845208Ssaidi@eecs.umich.edu warn("mmap failing: target fd %d is not valid\n", tgt_fd); 11855074Ssaidi@eecs.umich.edu return -EBADF; 11865074Ssaidi@eecs.umich.edu } 11875208Ssaidi@eecs.umich.edu 11885074Ssaidi@eecs.umich.edu if (fd_map->filename != "/dev/zero") { 11895074Ssaidi@eecs.umich.edu // This is very likely broken, but leave a warning here 11905074Ssaidi@eecs.umich.edu // (rather than panic) in case /dev/zero is known by 11915074Ssaidi@eecs.umich.edu // another name on some platform 11928706Sandreas.hansson@arm.com warn("allowing mmap of file %s; mmap not supported on files" 11935074Ssaidi@eecs.umich.edu " other than /dev/zero\n", fd_map->filename); 11945074Ssaidi@eecs.umich.edu } 11955074Ssaidi@eecs.umich.edu } 11965074Ssaidi@eecs.umich.edu 11975074Ssaidi@eecs.umich.edu if ((start % TheISA::VMPageSize) != 0 || 119810027SChris.Adeniyi-Jones@arm.com (length % TheISA::VMPageSize) != 0) { 119910027SChris.Adeniyi-Jones@arm.com warn("mmap failing: arguments not page-aligned: " 120010027SChris.Adeniyi-Jones@arm.com "start 0x%x length 0x%x", 120111851Sbrandon.potter@amd.com start, length); 120210027SChris.Adeniyi-Jones@arm.com return -EINVAL; 120310027SChris.Adeniyi-Jones@arm.com } 120410027SChris.Adeniyi-Jones@arm.com 120510027SChris.Adeniyi-Jones@arm.com // are we ok with clobbering existing mappings? only set this to 120610027SChris.Adeniyi-Jones@arm.com // true if the user has been warned. 120710793Sbrandon.potter@amd.com bool clobber = false; 120810027SChris.Adeniyi-Jones@arm.com 120910027SChris.Adeniyi-Jones@arm.com // try to use the caller-provided address if there is one 121010027SChris.Adeniyi-Jones@arm.com bool use_provided_address = (start != 0); 121110027SChris.Adeniyi-Jones@arm.com 121210027SChris.Adeniyi-Jones@arm.com if (use_provided_address) { 121310027SChris.Adeniyi-Jones@arm.com // check to see if the desired address is already in use 121410027SChris.Adeniyi-Jones@arm.com if (!p->pTable->isUnmapped(start, length)) { 121510027SChris.Adeniyi-Jones@arm.com // there are existing mappings in the desired range 121610027SChris.Adeniyi-Jones@arm.com // whether we clobber them or not depends on whether the caller 121710027SChris.Adeniyi-Jones@arm.com // specified MAP_FIXED 121810027SChris.Adeniyi-Jones@arm.com if (flags & OS::TGT_MAP_FIXED) { 121910027SChris.Adeniyi-Jones@arm.com // MAP_FIXED specified: clobber existing mappings 122010027SChris.Adeniyi-Jones@arm.com warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 122110027SChris.Adeniyi-Jones@arm.com start); 122210027SChris.Adeniyi-Jones@arm.com clobber = true; 122310027SChris.Adeniyi-Jones@arm.com } else { 122410027SChris.Adeniyi-Jones@arm.com // MAP_FIXED not specified: ignore suggested start address 122510027SChris.Adeniyi-Jones@arm.com warn("mmap: ignoring suggested map address 0x%x\n", start); 122610027SChris.Adeniyi-Jones@arm.com use_provided_address = false; 122710027SChris.Adeniyi-Jones@arm.com } 122810027SChris.Adeniyi-Jones@arm.com } 122910027SChris.Adeniyi-Jones@arm.com } 123010027SChris.Adeniyi-Jones@arm.com 123110027SChris.Adeniyi-Jones@arm.com if (!use_provided_address) { 123210027SChris.Adeniyi-Jones@arm.com // no address provided, or provided address unusable: 123310027SChris.Adeniyi-Jones@arm.com // pick next address from our "mmap region" 123410027SChris.Adeniyi-Jones@arm.com if (OS::mmapGrowsDown()) { 12351999SN/A start = p->mmap_end - length; 12361999SN/A p->mmap_end = start; 12371999SN/A } else { 123811856Sbrandon.potter@amd.com start = p->mmap_end; 12391999SN/A p->mmap_end += length; 12406701Sgblack@eecs.umich.edu } 124111856Sbrandon.potter@amd.com } 124211856Sbrandon.potter@amd.com 124310931Sbrandon.potter@amd.com p->allocateMem(start, length, clobber); 124411856Sbrandon.potter@amd.com 124511856Sbrandon.potter@amd.com return start; 12461999SN/A} 124711856Sbrandon.potter@amd.com 12481999SN/A/// Target getrlimit() handler. 12492764Sstever@eecs.umich.edutemplate <class OS> 12502064SN/ASyscallReturn 125110931Sbrandon.potter@amd.comgetrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12522064SN/A ThreadContext *tc) 12532064SN/A{ 125410931Sbrandon.potter@amd.com int index = 0; 12552064SN/A unsigned resource = process->getSyscallArg(tc, index); 12561999SN/A TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 12571999SN/A 12582218SN/A switch (resource) { 12591999SN/A case OS::TGT_RLIMIT_STACK: 126010931Sbrandon.potter@amd.com // max stack size in bytes: make up a number (8MB for now) 12611999SN/A rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 12621999SN/A rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 12631999SN/A rlp->rlim_max = TheISA::htog(rlp->rlim_max); 12641999SN/A break; 12651999SN/A 1266378SN/A case OS::TGT_RLIMIT_DATA: 1267360SN/A // max data segment size in bytes: make up a number 12681450SN/A rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 126911851Sbrandon.potter@amd.com rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 12702680Sktlim@umich.edu rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1271360SN/A break; 1272360SN/A 1273360SN/A default: 12746701Sgblack@eecs.umich.edu std::cerr << "getrlimitFunc: unimplemented resource " << resource 12758852Sandreas.hansson@arm.com << std::endl; 12766701Sgblack@eecs.umich.edu abort(); 12776701Sgblack@eecs.umich.edu break; 12786701Sgblack@eecs.umich.edu } 12796701Sgblack@eecs.umich.edu 1280360SN/A rlp.copyOut(tc->getMemProxy()); 12813669Sbinkertn@umich.edu return 0; 12823669Sbinkertn@umich.edu} 12833669Sbinkertn@umich.edu 1284360SN/A/// Target gettimeofday() handler. 1285360SN/Atemplate <class OS> 1286360SN/ASyscallReturn 1287360SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 12881458SN/A ThreadContext *tc) 1289360SN/A{ 12908706Sandreas.hansson@arm.com int index = 0; 1291360SN/A TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 12921458SN/A 1293360SN/A getElapsedTime(tp->tv_sec, tp->tv_usec); 1294360SN/A tp->tv_sec += seconds_since_epoch; 12951999SN/A tp->tv_sec = TheISA::htog(tp->tv_sec); 12961999SN/A tp->tv_usec = TheISA::htog(tp->tv_usec); 12971999SN/A 129811851Sbrandon.potter@amd.com tp.copyOut(tc->getMemProxy()); 12992680Sktlim@umich.edu 13001999SN/A return 0; 13011999SN/A} 13021999SN/A 13036701Sgblack@eecs.umich.edu 13048852Sandreas.hansson@arm.com/// Target utimes() handler. 13056701Sgblack@eecs.umich.edutemplate <class OS> 13066701Sgblack@eecs.umich.eduSyscallReturn 13076701Sgblack@eecs.umich.eduutimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 13086701Sgblack@eecs.umich.edu ThreadContext *tc) 13091999SN/A{ 13103669Sbinkertn@umich.edu std::string path; 13113669Sbinkertn@umich.edu 13123669Sbinkertn@umich.edu int index = 0; 13132764Sstever@eecs.umich.edu if (!tc->getMemProxy().tryReadString(path, 13142064SN/A process->getSyscallArg(tc, index))) { 13152064SN/A return -EFAULT; 13162064SN/A } 13171999SN/A 13181999SN/A TypedBufferArg<typename OS::timeval [2]> 13192064SN/A tp(process->getSyscallArg(tc, index)); 13201999SN/A tp.copyIn(tc->getMemProxy()); 13211999SN/A 13221999SN/A struct timeval hostTimeval[2]; 13231999SN/A for (int i = 0; i < 2; ++i) 13248706Sandreas.hansson@arm.com { 13251999SN/A hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 13261999SN/A hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 13271999SN/A } 13281999SN/A 1329378SN/A // Adjust path for current working directory 1330360SN/A path = process->fullPath(path); 13311450SN/A 133211856Sbrandon.potter@amd.com int result = utimes(path.c_str(), hostTimeval); 1333360SN/A 13346701Sgblack@eecs.umich.edu if (result < 0) 133511856Sbrandon.potter@amd.com return -errno; 133611856Sbrandon.potter@amd.com 1337360SN/A return 0; 133811380Salexandru.dutu@amd.com} 1339360SN/A/// Target getrusage() function. 134011856Sbrandon.potter@amd.comtemplate <class OS> 134111856Sbrandon.potter@amd.comSyscallReturn 13421458SN/AgetrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 134311856Sbrandon.potter@amd.com ThreadContext *tc) 1344360SN/A{ 1345360SN/A int index = 0; 134610931Sbrandon.potter@amd.com int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 1347360SN/A TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1348360SN/A 13491458SN/A rup->ru_utime.tv_sec = 0; 1350360SN/A rup->ru_utime.tv_usec = 0; 135110931Sbrandon.potter@amd.com rup->ru_stime.tv_sec = 0; 13522021SN/A rup->ru_stime.tv_usec = 0; 13531458SN/A rup->ru_maxrss = 0; 1354360SN/A rup->ru_ixrss = 0; 1355360SN/A rup->ru_idrss = 0; 13561706SN/A rup->ru_isrss = 0; 13571706SN/A rup->ru_minflt = 0; 13581706SN/A rup->ru_majflt = 0; 135911851Sbrandon.potter@amd.com rup->ru_nswap = 0; 13602680Sktlim@umich.edu rup->ru_inblock = 0; 13611706SN/A rup->ru_oublock = 0; 136211799Sbrandon.potter@amd.com rup->ru_msgsnd = 0; 136311799Sbrandon.potter@amd.com rup->ru_msgrcv = 0; 136411799Sbrandon.potter@amd.com rup->ru_nsignals = 0; 13651706SN/A rup->ru_nvcsw = 0; 13661706SN/A rup->ru_nivcsw = 0; 13676701Sgblack@eecs.umich.edu 13688852Sandreas.hansson@arm.com switch (who) { 13696701Sgblack@eecs.umich.edu case OS::TGT_RUSAGE_SELF: 13706701Sgblack@eecs.umich.edu getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 13716701Sgblack@eecs.umich.edu rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 13726701Sgblack@eecs.umich.edu rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 13731706SN/A break; 13743669Sbinkertn@umich.edu 13753669Sbinkertn@umich.edu case OS::TGT_RUSAGE_CHILDREN: 13763669Sbinkertn@umich.edu // do nothing. We have no child processes, so they take no time. 13771706SN/A break; 13781706SN/A 13791706SN/A default: 13801706SN/A // don't really handle THREAD or CHILDREN, but just warn and 13812218SN/A // plow ahead 13821706SN/A warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 138311759Sbrandon.potter@amd.com who); 138411799Sbrandon.potter@amd.com } 13851706SN/A 13861706SN/A rup.copyOut(tc->getMemProxy()); 13871706SN/A 138811886Sbrandon.potter@amd.com return 0; 138911886Sbrandon.potter@amd.com} 139011886Sbrandon.potter@amd.com 139111886Sbrandon.potter@amd.com/// Target times() function. 139211886Sbrandon.potter@amd.comtemplate <class OS> 139312426Sqtt2@cornell.eduSyscallReturn 139413557Sgabeblack@google.comtimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 139513557Sgabeblack@google.com ThreadContext *tc) 139611886Sbrandon.potter@amd.com{ 139712426Sqtt2@cornell.edu int index = 0; 139813534Sandreas.sandberg@arm.com TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 139912426Sqtt2@cornell.edu 140013534Sandreas.sandberg@arm.com // Fill in the time structure (in clocks) 140112426Sqtt2@cornell.edu int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 140212426Sqtt2@cornell.edu bufp->tms_utime = clocks; 140312426Sqtt2@cornell.edu bufp->tms_stime = 0; 140413536Sandreas.sandberg@arm.com bufp->tms_cutime = 0; 140512426Sqtt2@cornell.edu bufp->tms_cstime = 0; 140612426Sqtt2@cornell.edu 140711886Sbrandon.potter@amd.com // Convert to host endianness 140813536Sandreas.sandberg@arm.com bufp->tms_utime = TheISA::htog(bufp->tms_utime); 140912426Sqtt2@cornell.edu 141011886Sbrandon.potter@amd.com // Write back 141111886Sbrandon.potter@amd.com bufp.copyOut(tc->getMemProxy()); 141211886Sbrandon.potter@amd.com 141311886Sbrandon.potter@amd.com // Return clock ticks since system boot 141411886Sbrandon.potter@amd.com return clocks; 141511886Sbrandon.potter@amd.com} 141611886Sbrandon.potter@amd.com 141711886Sbrandon.potter@amd.com/// Target time() function. 141811886Sbrandon.potter@amd.comtemplate <class OS> 141911886Sbrandon.potter@amd.comSyscallReturn 142011886Sbrandon.potter@amd.comtimeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 142111886Sbrandon.potter@amd.com ThreadContext *tc) 142211886Sbrandon.potter@amd.com{ 142311886Sbrandon.potter@amd.com typename OS::time_t sec, usec; 142411886Sbrandon.potter@amd.com getElapsedTime(sec, usec); 142511886Sbrandon.potter@amd.com sec += seconds_since_epoch; 142611886Sbrandon.potter@amd.com 142711886Sbrandon.potter@amd.com int index = 0; 142811886Sbrandon.potter@amd.com Addr taddr = (Addr)process->getSyscallArg(tc, index); 142911886Sbrandon.potter@amd.com if(taddr != 0) { 143011886Sbrandon.potter@amd.com typename OS::time_t t = sec; 143111886Sbrandon.potter@amd.com t = TheISA::htog(t); 143211886Sbrandon.potter@amd.com SETranslatingPortProxy &p = tc->getMemProxy(); 143311886Sbrandon.potter@amd.com p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 143411886Sbrandon.potter@amd.com } 143511886Sbrandon.potter@amd.com return sec; 143611886Sbrandon.potter@amd.com} 143711886Sbrandon.potter@amd.com 143811886Sbrandon.potter@amd.com 143911886Sbrandon.potter@amd.com#endif // __SIM_SYSCALL_EMUL_HH__ 144011886Sbrandon.potter@amd.com