syscall_emul.hh revision 13642
16019Shines@cs.fsu.edu/* 212509Schuan.zhu@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited 37093Sgblack@eecs.umich.edu * Copyright (c) 2015 Advanced Micro Devices, Inc. 47093Sgblack@eecs.umich.edu * All rights reserved 57093Sgblack@eecs.umich.edu * 67093Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 77093Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 87093Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 97093Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 107093Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 117093Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 127093Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 137093Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 146019Shines@cs.fsu.edu * 156019Shines@cs.fsu.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 166019Shines@cs.fsu.edu * All rights reserved. 176019Shines@cs.fsu.edu * 186019Shines@cs.fsu.edu * Redistribution and use in source and binary forms, with or without 196019Shines@cs.fsu.edu * modification, are permitted provided that the following conditions are 206019Shines@cs.fsu.edu * met: redistributions of source code must retain the above copyright 216019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer; 226019Shines@cs.fsu.edu * redistributions in binary form must reproduce the above copyright 236019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer in the 246019Shines@cs.fsu.edu * documentation and/or other materials provided with the distribution; 256019Shines@cs.fsu.edu * neither the name of the copyright holders nor the names of its 266019Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from 276019Shines@cs.fsu.edu * this software without specific prior written permission. 286019Shines@cs.fsu.edu * 296019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 306019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 316019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 326019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 336019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 346019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 356019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 366019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 376019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 386019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 396019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 406019Shines@cs.fsu.edu * 416735Sgblack@eecs.umich.edu * Authors: Steve Reinhardt 426735Sgblack@eecs.umich.edu * Kevin Lim 4310037SARM gem5 Developers */ 4410037SARM gem5 Developers 456019Shines@cs.fsu.edu#ifndef __SIM_SYSCALL_EMUL_HH__ 466019Shines@cs.fsu.edu#define __SIM_SYSCALL_EMUL_HH__ 476019Shines@cs.fsu.edu 4811793Sbrandon.potter@amd.com#if (defined(__APPLE__) || defined(__OpenBSD__) || \ 4911793Sbrandon.potter@amd.com defined(__FreeBSD__) || defined(__CYGWIN__) || \ 5010037SARM gem5 Developers defined(__NetBSD__)) 5110037SARM gem5 Developers#define NO_STAT64 1 5210037SARM gem5 Developers#else 538229Snate@binkert.org#define NO_STAT64 0 548229Snate@binkert.org#endif 556019Shines@cs.fsu.edu 568232Snate@binkert.org#if (defined(__APPLE__) || defined(__OpenBSD__) || \ 578782Sgblack@eecs.umich.edu defined(__FreeBSD__) || defined(__NetBSD__)) 586019Shines@cs.fsu.edu#define NO_STATFS 1 596019Shines@cs.fsu.edu#else 606019Shines@cs.fsu.edu#define NO_STATFS 0 616019Shines@cs.fsu.edu#endif 6210037SARM gem5 Developers 6310037SARM gem5 Developers#if (defined(__APPLE__) || defined(__OpenBSD__) || \ 6410037SARM gem5 Developers defined(__FreeBSD__) || defined(__NetBSD__)) 6510037SARM gem5 Developers#define NO_FALLOCATE 1 6610037SARM gem5 Developers#else 6710037SARM gem5 Developers#define NO_FALLOCATE 0 6810037SARM gem5 Developers#endif 6910037SARM gem5 Developers 7010037SARM gem5 Developers/// 7110037SARM gem5 Developers/// @file syscall_emul.hh 7210037SARM gem5 Developers/// 7310037SARM gem5 Developers/// This file defines objects used to emulate syscalls from the target 7410037SARM gem5 Developers/// application on the host machine. 7510037SARM gem5 Developers 7610037SARM gem5 Developers#ifdef __CYGWIN32__ 7710037SARM gem5 Developers#include <sys/fcntl.h> 7810037SARM gem5 Developers 7910037SARM gem5 Developers#endif 8010037SARM gem5 Developers#include <fcntl.h> 8110037SARM gem5 Developers#include <poll.h> 8210037SARM gem5 Developers#include <sys/mman.h> 8310037SARM gem5 Developers#include <sys/socket.h> 8410037SARM gem5 Developers#include <sys/stat.h> 8510037SARM gem5 Developers#if (NO_STATFS == 0) 8610037SARM gem5 Developers#include <sys/statfs.h> 8710037SARM gem5 Developers#else 8810037SARM gem5 Developers#include <sys/mount.h> 8910037SARM gem5 Developers#endif 9010037SARM gem5 Developers#include <sys/time.h> 9110037SARM gem5 Developers#include <sys/types.h> 9210037SARM gem5 Developers#include <sys/uio.h> 9310037SARM gem5 Developers#include <unistd.h> 9410037SARM gem5 Developers 9510037SARM gem5 Developers#include <cerrno> 9610037SARM gem5 Developers#include <memory> 9710037SARM gem5 Developers#include <string> 9810037SARM gem5 Developers 9910037SARM gem5 Developers#include "arch/generic/tlb.hh" 10010037SARM gem5 Developers#include "arch/utility.hh" 10110037SARM gem5 Developers#include "base/intmath.hh" 1026019Shines@cs.fsu.edu#include "base/loader/object_file.hh" 10310037SARM gem5 Developers#include "base/logging.hh" 10410037SARM gem5 Developers#include "base/trace.hh" 10510037SARM gem5 Developers#include "base/types.hh" 1066019Shines@cs.fsu.edu#include "config/the_isa.hh" 10710037SARM gem5 Developers#include "cpu/base.hh" 10810037SARM gem5 Developers#include "cpu/thread_context.hh" 10910037SARM gem5 Developers#include "mem/page_table.hh" 11010037SARM gem5 Developers#include "params/Process.hh" 11110037SARM gem5 Developers#include "sim/emul_driver.hh" 11210037SARM gem5 Developers#include "sim/futex_map.hh" 11310037SARM gem5 Developers#include "sim/process.hh" 11410037SARM gem5 Developers#include "sim/syscall_debug_macros.hh" 11510037SARM gem5 Developers#include "sim/syscall_desc.hh" 11610037SARM gem5 Developers#include "sim/syscall_emul_buf.hh" 11710037SARM gem5 Developers#include "sim/syscall_return.hh" 11810037SARM gem5 Developers 11910037SARM gem5 Developers#if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN) 12010037SARM gem5 Developers#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1)) 12110037SARM gem5 Developers#endif 12210037SARM gem5 Developers 12310037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 12410037SARM gem5 Developers// 12510037SARM gem5 Developers// The following emulation functions are generic enough that they 12610037SARM gem5 Developers// don't need to be recompiled for different emulated OS's. They are 12710037SARM gem5 Developers// defined in sim/syscall_emul.cc. 12810037SARM gem5 Developers// 12910037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 13010037SARM gem5 Developers 13110037SARM gem5 Developers 13210037SARM gem5 Developers/// Handler for unimplemented syscalls that we haven't thought about. 13310037SARM gem5 DevelopersSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 13410037SARM gem5 Developers Process *p, ThreadContext *tc); 13510037SARM gem5 Developers 13610037SARM gem5 Developers/// Handler for unimplemented syscalls that we never intend to 13710037SARM gem5 Developers/// implement (signal handling, etc.) and should not affect the correct 13810037SARM gem5 Developers/// behavior of the program. Print a warning only if the appropriate 13910037SARM gem5 Developers/// trace flag is enabled. Return success to the target program. 14010037SARM gem5 DevelopersSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 14110037SARM gem5 Developers Process *p, ThreadContext *tc); 14210037SARM gem5 Developers 14310037SARM gem5 Developers// Target fallocateFunc() handler. 14410037SARM gem5 DevelopersSyscallReturn fallocateFunc(SyscallDesc *desc, int num, 14510037SARM gem5 Developers Process *p, ThreadContext *tc); 14610037SARM gem5 Developers 1476019Shines@cs.fsu.edu/// Target exit() handler: terminate current context. 14810037SARM gem5 DevelopersSyscallReturn exitFunc(SyscallDesc *desc, int num, 14910037SARM gem5 Developers Process *p, ThreadContext *tc); 15010037SARM gem5 Developers 1516019Shines@cs.fsu.edu/// Target exit_group() handler: terminate simulation. (exit all threads) 15210037SARM gem5 DevelopersSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 15310037SARM gem5 Developers Process *p, ThreadContext *tc); 15410037SARM gem5 Developers 15510037SARM gem5 Developers/// Target set_tid_address() handler. 15610037SARM gem5 DevelopersSyscallReturn setTidAddressFunc(SyscallDesc *desc, int num, 15710037SARM gem5 Developers Process *p, ThreadContext *tc); 15810037SARM gem5 Developers 15910037SARM gem5 Developers/// Target getpagesize() handler. 16010037SARM gem5 DevelopersSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 16110037SARM gem5 Developers Process *p, ThreadContext *tc); 16210037SARM gem5 Developers 16310037SARM gem5 Developers/// Target brk() handler: set brk address. 16410037SARM gem5 DevelopersSyscallReturn brkFunc(SyscallDesc *desc, int num, 16510037SARM gem5 Developers Process *p, ThreadContext *tc); 16610037SARM gem5 Developers 16710037SARM gem5 Developers/// Target close() handler. 16810037SARM gem5 DevelopersSyscallReturn closeFunc(SyscallDesc *desc, int num, 16910037SARM gem5 Developers Process *p, ThreadContext *tc); 17010037SARM gem5 Developers 17110037SARM gem5 Developers/// Target lseek() handler. 17210037SARM gem5 DevelopersSyscallReturn lseekFunc(SyscallDesc *desc, int num, 17310037SARM gem5 Developers Process *p, ThreadContext *tc); 17410037SARM gem5 Developers 17510037SARM gem5 Developers/// Target _llseek() handler. 17610037SARM gem5 DevelopersSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 17710037SARM gem5 Developers Process *p, ThreadContext *tc); 17810037SARM gem5 Developers 17910037SARM gem5 Developers/// Target munmap() handler. 18010037SARM gem5 DevelopersSyscallReturn munmapFunc(SyscallDesc *desc, int num, 18110037SARM gem5 Developers Process *p, ThreadContext *tc); 18210037SARM gem5 Developers 18310037SARM gem5 Developers/// Target shutdown() handler. 18410037SARM gem5 DevelopersSyscallReturn shutdownFunc(SyscallDesc *desc, int num, 18510037SARM gem5 Developers Process *p, ThreadContext *tc); 18610037SARM gem5 Developers 18710037SARM gem5 Developers/// Target gethostname() handler. 18810037SARM gem5 DevelopersSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 18910037SARM gem5 Developers Process *p, ThreadContext *tc); 19010037SARM gem5 Developers 19110037SARM gem5 Developers/// Target getcwd() handler. 19210037SARM gem5 DevelopersSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 1936019Shines@cs.fsu.edu Process *p, ThreadContext *tc); 19410037SARM gem5 Developers 19510037SARM gem5 Developers/// Target readlink() handler. 19610037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 1976019Shines@cs.fsu.edu Process *p, ThreadContext *tc, 19810037SARM gem5 Developers int index = 0); 19910037SARM gem5 DevelopersSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 20010037SARM gem5 Developers Process *p, ThreadContext *tc); 20112517Srekai.gonzalezalberquilla@arm.com 20210037SARM gem5 Developers/// Target unlink() handler. 20310037SARM gem5 DevelopersSyscallReturn unlinkHelper(SyscallDesc *desc, int num, 20410037SARM gem5 Developers Process *p, ThreadContext *tc, 20512517Srekai.gonzalezalberquilla@arm.com int index); 20612517Srekai.gonzalezalberquilla@arm.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 20712517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 20810037SARM gem5 Developers 20912517Srekai.gonzalezalberquilla@arm.com/// Target link() handler 21012517Srekai.gonzalezalberquilla@arm.comSyscallReturn linkFunc(SyscallDesc *desc, int num, Process *p, 21112517Srekai.gonzalezalberquilla@arm.com ThreadContext *tc); 21210037SARM gem5 Developers 21312517Srekai.gonzalezalberquilla@arm.com/// Target symlink() handler. 21412517Srekai.gonzalezalberquilla@arm.comSyscallReturn symlinkFunc(SyscallDesc *desc, int num, Process *p, 21512517Srekai.gonzalezalberquilla@arm.com ThreadContext *tc); 21610037SARM gem5 Developers 21712517Srekai.gonzalezalberquilla@arm.com/// Target mkdir() handler. 21812517Srekai.gonzalezalberquilla@arm.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 21912517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 22010037SARM gem5 Developers 22112517Srekai.gonzalezalberquilla@arm.com/// Target mknod() handler. 22212517Srekai.gonzalezalberquilla@arm.comSyscallReturn mknodFunc(SyscallDesc *desc, int num, 22312517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 22410037SARM gem5 Developers 22512517Srekai.gonzalezalberquilla@arm.com/// Target chdir() handler. 22612517Srekai.gonzalezalberquilla@arm.comSyscallReturn chdirFunc(SyscallDesc *desc, int num, 22712517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 22810037SARM gem5 Developers 22912517Srekai.gonzalezalberquilla@arm.com// Target rmdir() handler. 23012517Srekai.gonzalezalberquilla@arm.comSyscallReturn rmdirFunc(SyscallDesc *desc, int num, 23112517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 23210037SARM gem5 Developers 23312517Srekai.gonzalezalberquilla@arm.com/// Target rename() handler. 23412517Srekai.gonzalezalberquilla@arm.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 23512517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 23610037SARM gem5 Developers 23710037SARM gem5 Developers 23812517Srekai.gonzalezalberquilla@arm.com/// Target truncate() handler. 23912517Srekai.gonzalezalberquilla@arm.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 24012517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 24112512Sgiacomo.travaglini@arm.com 24212517Srekai.gonzalezalberquilla@arm.com 24312517Srekai.gonzalezalberquilla@arm.com/// Target ftruncate() handler. 24412517Srekai.gonzalezalberquilla@arm.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 24510037SARM gem5 Developers Process *p, ThreadContext *tc); 24612517Srekai.gonzalezalberquilla@arm.com 24712517Srekai.gonzalezalberquilla@arm.com 24812517Srekai.gonzalezalberquilla@arm.com/// Target truncate64() handler. 24910037SARM gem5 DevelopersSyscallReturn truncate64Func(SyscallDesc *desc, int num, 25012517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 25112517Srekai.gonzalezalberquilla@arm.com 25212517Srekai.gonzalezalberquilla@arm.com/// Target ftruncate64() handler. 25310037SARM gem5 DevelopersSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 25412517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 25512517Srekai.gonzalezalberquilla@arm.com 25612517Srekai.gonzalezalberquilla@arm.com 25710037SARM gem5 Developers/// Target umask() handler. 25812517Srekai.gonzalezalberquilla@arm.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 25912517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 26012517Srekai.gonzalezalberquilla@arm.com 26110037SARM gem5 Developers/// Target gettid() handler. 26210037SARM gem5 DevelopersSyscallReturn gettidFunc(SyscallDesc *desc, int num, 26312517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 26412517Srekai.gonzalezalberquilla@arm.com 26512517Srekai.gonzalezalberquilla@arm.com/// Target chown() handler. 26610037SARM gem5 DevelopersSyscallReturn chownFunc(SyscallDesc *desc, int num, 26710037SARM gem5 Developers Process *p, ThreadContext *tc); 26812517Srekai.gonzalezalberquilla@arm.com 26912517Srekai.gonzalezalberquilla@arm.com/// Target setpgid() handler. 27012517Srekai.gonzalezalberquilla@arm.comSyscallReturn setpgidFunc(SyscallDesc *desc, int num, 27110037SARM gem5 Developers Process *p, ThreadContext *tc); 27210037SARM gem5 Developers 27312517Srekai.gonzalezalberquilla@arm.com/// Target fchown() handler. 27412517Srekai.gonzalezalberquilla@arm.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 27512517Srekai.gonzalezalberquilla@arm.com Process *p, ThreadContext *tc); 27610037SARM gem5 Developers 27710037SARM gem5 Developers/// Target dup() handler. 27812517Srekai.gonzalezalberquilla@arm.comSyscallReturn dupFunc(SyscallDesc *desc, int num, 27912517Srekai.gonzalezalberquilla@arm.com Process *process, ThreadContext *tc); 28012517Srekai.gonzalezalberquilla@arm.com 28112299Sandreas.sandberg@arm.com/// Target dup2() handler. 28212299Sandreas.sandberg@arm.comSyscallReturn dup2Func(SyscallDesc *desc, int num, 28312517Srekai.gonzalezalberquilla@arm.com Process *process, ThreadContext *tc); 28412517Srekai.gonzalezalberquilla@arm.com 28512517Srekai.gonzalezalberquilla@arm.com/// Target fcntl() handler. 28610037SARM gem5 DevelopersSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 28710037SARM gem5 Developers Process *process, ThreadContext *tc); 28812517Srekai.gonzalezalberquilla@arm.com 28912517Srekai.gonzalezalberquilla@arm.com/// Target fcntl64() handler. 29012517Srekai.gonzalezalberquilla@arm.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 29110037SARM gem5 Developers Process *process, ThreadContext *tc); 29210037SARM gem5 Developers 29312517Srekai.gonzalezalberquilla@arm.com/// Target setuid() handler. 29412517Srekai.gonzalezalberquilla@arm.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2956019Shines@cs.fsu.edu Process *p, ThreadContext *tc); 29610037SARM gem5 Developers 2977362Sgblack@eecs.umich.edu/// Target pipe() handler. 2986735Sgblack@eecs.umich.eduSyscallReturn pipeFunc(SyscallDesc *desc, int num, 29910037SARM gem5 Developers Process *p, ThreadContext *tc); 3006019Shines@cs.fsu.edu 30110037SARM gem5 Developers/// Internal pipe() handler. 30210037SARM gem5 DevelopersSyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p, 3037400SAli.Saidi@ARM.com ThreadContext *tc, bool pseudoPipe); 3046735Sgblack@eecs.umich.edu 3056735Sgblack@eecs.umich.edu/// Target getpid() handler. 30610037SARM gem5 DevelopersSyscallReturn getpidFunc(SyscallDesc *desc, int num, 3076735Sgblack@eecs.umich.edu Process *p, ThreadContext *tc); 30810037SARM gem5 Developers 30910037SARM gem5 Developers// Target getpeername() handler. 31010037SARM gem5 DevelopersSyscallReturn getpeernameFunc(SyscallDesc *desc, int num, 31110037SARM gem5 Developers Process *p, ThreadContext *tc); 3127400SAli.Saidi@ARM.com 31310037SARM gem5 Developers// Target bind() handler. 31410037SARM gem5 DevelopersSyscallReturn bindFunc(SyscallDesc *desc, int num, 31510037SARM gem5 Developers Process *p, ThreadContext *tc); 31610037SARM gem5 Developers 31710037SARM gem5 Developers// Target listen() handler. 31810037SARM gem5 DevelopersSyscallReturn listenFunc(SyscallDesc *desc, int num, 31910037SARM gem5 Developers Process *p, ThreadContext *tc); 32010037SARM gem5 Developers 32110037SARM gem5 Developers// Target connect() handler. 32210037SARM gem5 DevelopersSyscallReturn connectFunc(SyscallDesc *desc, int num, 32310037SARM gem5 Developers Process *p, ThreadContext *tc); 32410037SARM gem5 Developers 32510037SARM gem5 Developers#if defined(SYS_getdents) 32610037SARM gem5 Developers// Target getdents() handler. 32710037SARM gem5 DevelopersSyscallReturn getdentsFunc(SyscallDesc *desc, int num, 32810037SARM gem5 Developers Process *p, ThreadContext *tc); 32910037SARM gem5 Developers#endif 3306019Shines@cs.fsu.edu 3316019Shines@cs.fsu.edu#if defined(SYS_getdents64) 33210037SARM gem5 Developers// Target getdents() handler. 33310037SARM gem5 DevelopersSyscallReturn getdents64Func(SyscallDesc *desc, int num, 33410037SARM gem5 Developers Process *p, ThreadContext *tc); 33510037SARM gem5 Developers#endif 33610037SARM gem5 Developers 33710037SARM gem5 Developers// Target sendto() handler. 33810037SARM gem5 DevelopersSyscallReturn sendtoFunc(SyscallDesc *desc, int num, 33910037SARM gem5 Developers Process *p, ThreadContext *tc); 34010037SARM gem5 Developers 34111574SCurtis.Dunham@arm.com// Target recvfrom() handler. 34211574SCurtis.Dunham@arm.comSyscallReturn recvfromFunc(SyscallDesc *desc, int num, 34311574SCurtis.Dunham@arm.com Process *p, ThreadContext *tc); 34411574SCurtis.Dunham@arm.com 34510037SARM gem5 Developers// Target recvmsg() handler. 34610037SARM gem5 DevelopersSyscallReturn recvmsgFunc(SyscallDesc *desc, int num, 34710037SARM gem5 Developers Process *p, ThreadContext *tc); 34810037SARM gem5 Developers 34910037SARM gem5 Developers// Target sendmsg() handler. 35010037SARM gem5 DevelopersSyscallReturn sendmsgFunc(SyscallDesc *desc, int num, 35110037SARM gem5 Developers Process *p, ThreadContext *tc); 35212511Schuan.zhu@arm.com 35310037SARM gem5 Developers// Target getuid() handler. 35410037SARM gem5 DevelopersSyscallReturn getuidFunc(SyscallDesc *desc, int num, 35510037SARM gem5 Developers Process *p, ThreadContext *tc); 35610037SARM gem5 Developers 35710037SARM gem5 Developers/// Target getgid() handler. 35810037SARM gem5 DevelopersSyscallReturn getgidFunc(SyscallDesc *desc, int num, 35910037SARM gem5 Developers Process *p, ThreadContext *tc); 36010037SARM gem5 Developers 36110037SARM gem5 Developers/// Target getppid() handler. 36210037SARM gem5 DevelopersSyscallReturn getppidFunc(SyscallDesc *desc, int num, 36310037SARM gem5 Developers Process *p, ThreadContext *tc); 36410037SARM gem5 Developers 36510037SARM gem5 Developers/// Target geteuid() handler. 36610037SARM gem5 DevelopersSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 36710037SARM gem5 Developers Process *p, ThreadContext *tc); 36810037SARM gem5 Developers 36910037SARM gem5 Developers/// Target getegid() handler. 37010037SARM gem5 DevelopersSyscallReturn getegidFunc(SyscallDesc *desc, int num, 37110037SARM gem5 Developers Process *p, ThreadContext *tc); 37210037SARM gem5 Developers 37310037SARM gem5 Developers/// Target access() handler 37410037SARM gem5 DevelopersSyscallReturn accessFunc(SyscallDesc *desc, int num, 37510037SARM gem5 Developers Process *p, ThreadContext *tc); 37610037SARM gem5 DevelopersSyscallReturn accessFunc(SyscallDesc *desc, int num, 37710037SARM gem5 Developers Process *p, ThreadContext *tc, 37810037SARM gem5 Developers int index); 37910037SARM gem5 Developers 38010037SARM gem5 Developers// Target getsockopt() handler. 38110037SARM gem5 DevelopersSyscallReturn getsockoptFunc(SyscallDesc *desc, int num, 38210037SARM gem5 Developers Process *p, ThreadContext *tc); 38310037SARM gem5 Developers 38410037SARM gem5 Developers// Target setsockopt() handler. 38510037SARM gem5 DevelopersSyscallReturn setsockoptFunc(SyscallDesc *desc, int num, 38610037SARM gem5 Developers Process *p, ThreadContext *tc); 38710037SARM gem5 Developers 38810037SARM gem5 Developers// Target getsockname() handler. 38910037SARM gem5 DevelopersSyscallReturn getsocknameFunc(SyscallDesc *desc, int num, 39010037SARM gem5 Developers Process *p, ThreadContext *tc); 39110037SARM gem5 Developers 39210037SARM gem5 Developers/// Futex system call 39312402Sgiacomo.travaglini@arm.com/// Implemented by Daniel Sanchez 39410037SARM gem5 Developers/// Used by printf's in multi-threaded apps 39510037SARM gem5 Developerstemplate <class OS> 39610037SARM gem5 DevelopersSyscallReturn 39710037SARM gem5 DevelopersfutexFunc(SyscallDesc *desc, int callnum, Process *process, 39810037SARM gem5 Developers ThreadContext *tc) 39910037SARM gem5 Developers{ 40010037SARM gem5 Developers using namespace std; 40110037SARM gem5 Developers 40210037SARM gem5 Developers int index = 0; 40310037SARM gem5 Developers Addr uaddr = process->getSyscallArg(tc, index); 40410037SARM gem5 Developers int op = process->getSyscallArg(tc, index); 40510037SARM gem5 Developers int val = process->getSyscallArg(tc, index); 40610037SARM gem5 Developers int timeout M5_VAR_USED = process->getSyscallArg(tc, index); 40710037SARM gem5 Developers Addr uaddr2 M5_VAR_USED = process->getSyscallArg(tc, index); 40810037SARM gem5 Developers int val3 = process->getSyscallArg(tc, index); 40910037SARM gem5 Developers 41010037SARM gem5 Developers /* 41110037SARM gem5 Developers * Unsupported option that does not affect the correctness of the 41210037SARM gem5 Developers * application. This is a performance optimization utilized by Linux. 41310037SARM gem5 Developers */ 41410037SARM gem5 Developers op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 41510037SARM gem5 Developers op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG; 41610037SARM gem5 Developers 41710037SARM gem5 Developers FutexMap &futex_map = tc->getSystemPtr()->futexMap; 41810037SARM gem5 Developers 41910037SARM gem5 Developers if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) { 42010037SARM gem5 Developers // Ensure futex system call accessed atomically. 42110037SARM gem5 Developers BufferArg buf(uaddr, sizeof(int)); 42210037SARM gem5 Developers buf.copyIn(tc->getMemProxy()); 42310037SARM gem5 Developers int mem_val = *(int*)buf.bufferPtr(); 42410037SARM gem5 Developers 42510037SARM gem5 Developers /* 42610037SARM gem5 Developers * The value in memory at uaddr is not equal with the expected val 42710037SARM gem5 Developers * (a different thread must have changed it before the system call was 42810037SARM gem5 Developers * invoked). In this case, we need to throw an error. 42910417Sandreas.hansson@arm.com */ 4306019Shines@cs.fsu.edu if (val != mem_val) 43110037SARM gem5 Developers return -OS::TGT_EWOULDBLOCK; 43210037SARM gem5 Developers 43310037SARM gem5 Developers if (OS::TGT_FUTEX_WAIT) { 43410037SARM gem5 Developers futex_map.suspend(uaddr, process->tgid(), tc); 43510037SARM gem5 Developers } else { 43610037SARM gem5 Developers futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3); 43710037SARM gem5 Developers } 43810037SARM gem5 Developers 43910037SARM gem5 Developers return 0; 44010037SARM gem5 Developers } else if (OS::TGT_FUTEX_WAKE == op) { 44112402Sgiacomo.travaglini@arm.com return futex_map.wakeup(uaddr, process->tgid(), val); 44210037SARM gem5 Developers } else if (OS::TGT_FUTEX_WAKE_BITSET == op) { 44312402Sgiacomo.travaglini@arm.com return futex_map.wakeup_bitset(uaddr, process->tgid(), val3); 44411578SDylan.Johnson@ARM.com } 44512402Sgiacomo.travaglini@arm.com 44612402Sgiacomo.travaglini@arm.com warn("futex: op %d not implemented; ignoring.", op); 44710037SARM gem5 Developers return -ENOSYS; 44812402Sgiacomo.travaglini@arm.com} 44912402Sgiacomo.travaglini@arm.com 45010037SARM gem5 Developers 45110037SARM gem5 Developers/// Pseudo Funcs - These functions use a different return convension, 45210037SARM gem5 Developers/// returning a second value in a register other than the normal return register 45310037SARM gem5 DevelopersSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 45410037SARM gem5 Developers Process *process, ThreadContext *tc); 45510037SARM gem5 Developers 45610037SARM gem5 Developers/// Target getpidPseudo() handler. 45710037SARM gem5 DevelopersSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 45810037SARM gem5 Developers Process *p, ThreadContext *tc); 45910037SARM gem5 Developers 46010037SARM gem5 Developers/// Target getuidPseudo() handler. 46110037SARM gem5 DevelopersSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 46210037SARM gem5 Developers Process *p, ThreadContext *tc); 46310037SARM gem5 Developers 46410037SARM gem5 Developers/// Target getgidPseudo() handler. 46510037SARM gem5 DevelopersSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4666735Sgblack@eecs.umich.edu Process *p, ThreadContext *tc); 4678782Sgblack@eecs.umich.edu 4688782Sgblack@eecs.umich.edu 4696735Sgblack@eecs.umich.edu/// A readable name for 1,000,000, for converting microseconds to seconds. 4706019Shines@cs.fsu.educonst int one_million = 1000000; 4716735Sgblack@eecs.umich.edu/// A readable name for 1,000,000,000, for converting nanoseconds to seconds. 47210037SARM gem5 Developersconst int one_billion = 1000000000; 4738303SAli.Saidi@ARM.com 47410338SCurtis.Dunham@arm.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 47510338SCurtis.Dunham@arm.com/// by my reckoning. We want to keep this a constant (not use the 47610338SCurtis.Dunham@arm.com/// real-world time) to keep simulations repeatable. 47710338SCurtis.Dunham@arm.comconst unsigned seconds_since_epoch = 1000000000; 4788303SAli.Saidi@ARM.com 4797720Sgblack@eecs.umich.edu/// Helper function to convert current elapsed time to seconds and 4808205SAli.Saidi@ARM.com/// microseconds. 4818205SAli.Saidi@ARM.comtemplate <class T1, class T2> 4828205SAli.Saidi@ARM.comvoid 4836735Sgblack@eecs.umich.edugetElapsedTimeMicro(T1 &sec, T2 &usec) 48410037SARM gem5 Developers{ 48510037SARM gem5 Developers uint64_t elapsed_usecs = curTick() / SimClock::Int::us; 48610037SARM gem5 Developers sec = elapsed_usecs / one_million; 48710037SARM gem5 Developers usec = elapsed_usecs % one_million; 48812398Sgiacomo.travaglini@arm.com} 48910037SARM gem5 Developers 49010037SARM gem5 Developers/// Helper function to convert current elapsed time to seconds and 49110037SARM gem5 Developers/// nanoseconds. 49212402Sgiacomo.travaglini@arm.comtemplate <class T1, class T2> 49310037SARM gem5 Developersvoid 49412402Sgiacomo.travaglini@arm.comgetElapsedTimeNano(T1 &sec, T2 &nsec) 49510037SARM gem5 Developers{ 49612402Sgiacomo.travaglini@arm.com uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns; 49712402Sgiacomo.travaglini@arm.com sec = elapsed_nsecs / one_billion; 49810037SARM gem5 Developers nsec = elapsed_nsecs % one_billion; 49912402Sgiacomo.travaglini@arm.com} 50010037SARM gem5 Developers 50110037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 50210037SARM gem5 Developers// 50310037SARM gem5 Developers// The following emulation functions are generic, but need to be 50410037SARM gem5 Developers// templated to account for differences in types, constants, etc. 50510037SARM gem5 Developers// 50610037SARM gem5 Developers////////////////////////////////////////////////////////////////////// 50710037SARM gem5 Developers 50810037SARM gem5 Developers typedef struct statfs hst_statfs; 50910037SARM gem5 Developers#if NO_STAT64 51010037SARM gem5 Developers typedef struct stat hst_stat; 51110037SARM gem5 Developers typedef struct stat hst_stat64; 51210037SARM gem5 Developers#else 51310037SARM gem5 Developers typedef struct stat hst_stat; 51410037SARM gem5 Developers typedef struct stat64 hst_stat64; 51510037SARM gem5 Developers#endif 51610037SARM gem5 Developers 51710037SARM gem5 Developers//// Helper function to convert a host stat buffer to a target stat 51810037SARM gem5 Developers//// buffer. Also copies the target buffer out to the simulated 51910037SARM gem5 Developers//// memory space. Used by stat(), fstat(), and lstat(). 52010037SARM gem5 Developers 52110037SARM gem5 Developerstemplate <typename target_stat, typename host_stat> 52210037SARM gem5 Developersvoid 52310037SARM gem5 DevelopersconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 52410037SARM gem5 Developers{ 52510037SARM gem5 Developers using namespace TheISA; 52610037SARM gem5 Developers 52710037SARM gem5 Developers if (fakeTTY) 52810037SARM gem5 Developers tgt->st_dev = 0xA; 52910037SARM gem5 Developers else 53010037SARM gem5 Developers tgt->st_dev = host->st_dev; 53110037SARM gem5 Developers tgt->st_dev = TheISA::htog(tgt->st_dev); 53210037SARM gem5 Developers tgt->st_ino = host->st_ino; 53310037SARM gem5 Developers tgt->st_ino = TheISA::htog(tgt->st_ino); 5346735Sgblack@eecs.umich.edu tgt->st_mode = host->st_mode; 5356735Sgblack@eecs.umich.edu if (fakeTTY) { 5366735Sgblack@eecs.umich.edu // Claim to be a character device 53710037SARM gem5 Developers tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 5388518Sgeoffrey.blake@arm.com tgt->st_mode |= S_IFCHR; // Set S_IFCHR 5398518Sgeoffrey.blake@arm.com } 5406735Sgblack@eecs.umich.edu tgt->st_mode = TheISA::htog(tgt->st_mode); 54110037SARM gem5 Developers tgt->st_nlink = host->st_nlink; 54210037SARM gem5 Developers tgt->st_nlink = TheISA::htog(tgt->st_nlink); 54310037SARM gem5 Developers tgt->st_uid = host->st_uid; 54410037SARM gem5 Developers tgt->st_uid = TheISA::htog(tgt->st_uid); 54510037SARM gem5 Developers tgt->st_gid = host->st_gid; 54610037SARM gem5 Developers tgt->st_gid = TheISA::htog(tgt->st_gid); 54710037SARM gem5 Developers if (fakeTTY) 54810037SARM gem5 Developers tgt->st_rdev = 0x880d; 54910037SARM gem5 Developers else 55010037SARM gem5 Developers tgt->st_rdev = host->st_rdev; 55110037SARM gem5 Developers tgt->st_rdev = TheISA::htog(tgt->st_rdev); 55210037SARM gem5 Developers tgt->st_size = host->st_size; 5536735Sgblack@eecs.umich.edu tgt->st_size = TheISA::htog(tgt->st_size); 5546735Sgblack@eecs.umich.edu tgt->st_atimeX = host->st_atime; 5556735Sgblack@eecs.umich.edu tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 5566735Sgblack@eecs.umich.edu tgt->st_mtimeX = host->st_mtime; 5576735Sgblack@eecs.umich.edu tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5586735Sgblack@eecs.umich.edu tgt->st_ctimeX = host->st_ctime; 5596735Sgblack@eecs.umich.edu tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5606735Sgblack@eecs.umich.edu // Force the block size to be 8KB. This helps to ensure buffered io works 5616735Sgblack@eecs.umich.edu // consistently across different hosts. 56210037SARM gem5 Developers tgt->st_blksize = 0x2000; 56310037SARM gem5 Developers tgt->st_blksize = TheISA::htog(tgt->st_blksize); 56410037SARM gem5 Developers tgt->st_blocks = host->st_blocks; 5656735Sgblack@eecs.umich.edu tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5666735Sgblack@eecs.umich.edu} 5676735Sgblack@eecs.umich.edu 5686735Sgblack@eecs.umich.edu// Same for stat64 56910037SARM gem5 Developers 57010037SARM gem5 Developerstemplate <typename target_stat, typename host_stat64> 57110037SARM gem5 Developersvoid 57210037SARM gem5 DevelopersconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 57310037SARM gem5 Developers{ 57410037SARM gem5 Developers using namespace TheISA; 57510037SARM gem5 Developers 57610037SARM gem5 Developers convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 57710037SARM gem5 Developers#if defined(STAT_HAVE_NSEC) 57810037SARM gem5 Developers tgt->st_atime_nsec = host->st_atime_nsec; 5796735Sgblack@eecs.umich.edu tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5806735Sgblack@eecs.umich.edu tgt->st_mtime_nsec = host->st_mtime_nsec; 5817093Sgblack@eecs.umich.edu tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5827093Sgblack@eecs.umich.edu tgt->st_ctime_nsec = host->st_ctime_nsec; 5837720Sgblack@eecs.umich.edu tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5847585SAli.Saidi@arm.com#else 5857720Sgblack@eecs.umich.edu tgt->st_atime_nsec = 0; 5867720Sgblack@eecs.umich.edu tgt->st_mtime_nsec = 0; 5877720Sgblack@eecs.umich.edu tgt->st_ctime_nsec = 0; 5887720Sgblack@eecs.umich.edu#endif 5897720Sgblack@eecs.umich.edu} 5907720Sgblack@eecs.umich.edu 59110037SARM gem5 Developers// Here are a couple of convenience functions 59210037SARM gem5 Developerstemplate<class OS> 5937720Sgblack@eecs.umich.eduvoid 5946019Shines@cs.fsu.educopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5957189Sgblack@eecs.umich.edu hst_stat *host, bool fakeTTY = false) 5967400SAli.Saidi@ARM.com{ 59710417Sandreas.hansson@arm.com typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 59810037SARM gem5 Developers tgt_stat_buf tgt(addr); 59910037SARM gem5 Developers convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 60010037SARM gem5 Developers tgt.copyOut(mem); 60110037SARM gem5 Developers} 60210037SARM gem5 Developers 60310037SARM gem5 Developerstemplate<class OS> 60410037SARM gem5 Developersvoid 60510037SARM gem5 DeveloperscopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 60611574SCurtis.Dunham@arm.com hst_stat64 *host, bool fakeTTY = false) 60711574SCurtis.Dunham@arm.com{ 60811574SCurtis.Dunham@arm.com typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 60911574SCurtis.Dunham@arm.com tgt_stat_buf tgt(addr); 61011574SCurtis.Dunham@arm.com convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 61110037SARM gem5 Developers tgt.copyOut(mem); 61210037SARM gem5 Developers} 61310037SARM gem5 Developers 61410037SARM gem5 Developerstemplate <class OS> 61510037SARM gem5 Developersvoid 61610037SARM gem5 DeveloperscopyOutStatfsBuf(SETranslatingPortProxy &mem, Addr addr, 61710037SARM gem5 Developers hst_statfs *host) 61810037SARM gem5 Developers{ 61910037SARM gem5 Developers TypedBufferArg<typename OS::tgt_statfs> tgt(addr); 62010037SARM gem5 Developers 62110037SARM gem5 Developers tgt->f_type = TheISA::htog(host->f_type); 62210037SARM gem5 Developers#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 62310037SARM gem5 Developers tgt->f_bsize = TheISA::htog(host->f_iosize); 62410338SCurtis.Dunham@arm.com#else 62510338SCurtis.Dunham@arm.com tgt->f_bsize = TheISA::htog(host->f_bsize); 62610338SCurtis.Dunham@arm.com#endif 62710037SARM gem5 Developers tgt->f_blocks = TheISA::htog(host->f_blocks); 62810037SARM gem5 Developers tgt->f_bfree = TheISA::htog(host->f_bfree); 62910037SARM gem5 Developers tgt->f_bavail = TheISA::htog(host->f_bavail); 63010037SARM gem5 Developers tgt->f_files = TheISA::htog(host->f_files); 63110037SARM gem5 Developers tgt->f_ffree = TheISA::htog(host->f_ffree); 63210037SARM gem5 Developers memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid)); 63310037SARM gem5 Developers#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 63410037SARM gem5 Developers tgt->f_namelen = TheISA::htog(host->f_namemax); 63510037SARM gem5 Developers tgt->f_frsize = TheISA::htog(host->f_bsize); 63610037SARM gem5 Developers#elif defined(__APPLE__) 63710338SCurtis.Dunham@arm.com tgt->f_namelen = 0; 63810037SARM gem5 Developers tgt->f_frsize = 0; 63910037SARM gem5 Developers#else 64010037SARM gem5 Developers tgt->f_namelen = TheISA::htog(host->f_namelen); 64110037SARM gem5 Developers tgt->f_frsize = TheISA::htog(host->f_frsize); 64210037SARM gem5 Developers#endif 64310037SARM gem5 Developers#if defined(__linux__) 64410037SARM gem5 Developers memcpy(&tgt->f_spare, &host->f_spare, sizeof(host->f_spare)); 64510037SARM gem5 Developers#else 64610037SARM gem5 Developers /* 64710037SARM gem5 Developers * The fields are different sizes per OS. Don't bother with 64810037SARM gem5 Developers * f_spare or f_reserved on non-Linux for now. 64910037SARM gem5 Developers */ 65010037SARM gem5 Developers memset(&tgt->f_spare, 0, sizeof(tgt->f_spare)); 65110037SARM gem5 Developers#endif 65210037SARM gem5 Developers 65310037SARM gem5 Developers tgt.copyOut(mem); 65410037SARM gem5 Developers} 65510037SARM gem5 Developers 65612511Schuan.zhu@arm.com/// Target ioctl() handler. For the most part, programs call ioctl() 65712511Schuan.zhu@arm.com/// only to find out if their stdout is a tty, to determine whether to 65810037SARM gem5 Developers/// do line or block buffering. We always claim that output fds are 65910037SARM gem5 Developers/// not TTYs to provide repeatable results. 66010037SARM gem5 Developerstemplate <class OS> 66110037SARM gem5 DevelopersSyscallReturn 66210037SARM gem5 DevelopersioctlFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 66310037SARM gem5 Developers{ 66410037SARM gem5 Developers int index = 0; 66510037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 66610037SARM gem5 Developers unsigned req = p->getSyscallArg(tc, index); 66710037SARM gem5 Developers 66810037SARM gem5 Developers DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req); 66910037SARM gem5 Developers 67012511Schuan.zhu@arm.com if (OS::isTtyReq(req)) 67110037SARM gem5 Developers return -ENOTTY; 67210037SARM gem5 Developers 67310037SARM gem5 Developers auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]); 67410037SARM gem5 Developers if (!dfdp) 67510037SARM gem5 Developers return -EBADF; 67610037SARM gem5 Developers 67710037SARM gem5 Developers /** 67810037SARM gem5 Developers * If the driver is valid, issue the ioctl through it. Otherwise, 67910037SARM gem5 Developers * there's an implicit assumption that the device is a TTY type and we 68010037SARM gem5 Developers * return that we do not have a valid TTY. 68110037SARM gem5 Developers */ 68212398Sgiacomo.travaglini@arm.com EmulatedDriver *emul_driver = dfdp->getDriver(); 68310037SARM gem5 Developers if (emul_driver) 68410037SARM gem5 Developers return emul_driver->ioctl(p, tc, req); 68510037SARM gem5 Developers 68610037SARM gem5 Developers /** 68710037SARM gem5 Developers * For lack of a better return code, return ENOTTY. Ideally, we should 68810037SARM gem5 Developers * return something better here, but at least we issue the warning. 68910417Sandreas.hansson@arm.com */ 6907400SAli.Saidi@ARM.com warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n", 6918782Sgblack@eecs.umich.edu tgt_fd, req, tc->pcState()); 69211150Smitch.hayenga@arm.com return -ENOTTY; 6938782Sgblack@eecs.umich.edu} 6948782Sgblack@eecs.umich.edu 69510037SARM gem5 Developerstemplate <class OS> 69610037SARM gem5 DevelopersSyscallReturn 69710037SARM gem5 DevelopersopenImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, 69810037SARM gem5 Developers bool isopenat) 69910037SARM gem5 Developers{ 70010037SARM gem5 Developers int index = 0; 70110037SARM gem5 Developers int tgt_dirfd = -1; 70210037SARM gem5 Developers 70310037SARM gem5 Developers /** 70410037SARM gem5 Developers * If using the openat variant, read in the target directory file 70510037SARM gem5 Developers * descriptor from the simulated process. 70610037SARM gem5 Developers */ 70710037SARM gem5 Developers if (isopenat) 70810037SARM gem5 Developers tgt_dirfd = p->getSyscallArg(tc, index); 70910037SARM gem5 Developers 71010037SARM gem5 Developers /** 71110037SARM gem5 Developers * Retrieve the simulated process' memory proxy and then read in the path 71210037SARM gem5 Developers * string from that memory space into the host's working memory space. 71310037SARM gem5 Developers */ 7147400SAli.Saidi@ARM.com std::string path; 7157400SAli.Saidi@ARM.com if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 7167189Sgblack@eecs.umich.edu return -EFAULT; 71710417Sandreas.hansson@arm.com 7187189Sgblack@eecs.umich.edu#ifdef __CYGWIN32__ 7198782Sgblack@eecs.umich.edu int host_flags = O_BINARY; 7208782Sgblack@eecs.umich.edu#else 7218806Sgblack@eecs.umich.edu int host_flags = 0; 7228806Sgblack@eecs.umich.edu#endif 7238806Sgblack@eecs.umich.edu /** 7248806Sgblack@eecs.umich.edu * Translate target flags into host flags. Flags exist which are not 7258806Sgblack@eecs.umich.edu * ported between architectures which can cause check failures. 7268806Sgblack@eecs.umich.edu */ 7278806Sgblack@eecs.umich.edu int tgt_flags = p->getSyscallArg(tc, index); 7288806Sgblack@eecs.umich.edu for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 7298806Sgblack@eecs.umich.edu if (tgt_flags & OS::openFlagTable[i].tgtFlag) { 7308806Sgblack@eecs.umich.edu tgt_flags &= ~OS::openFlagTable[i].tgtFlag; 7318806Sgblack@eecs.umich.edu host_flags |= OS::openFlagTable[i].hostFlag; 7327189Sgblack@eecs.umich.edu } 7338806Sgblack@eecs.umich.edu } 7348806Sgblack@eecs.umich.edu if (tgt_flags) { 7357189Sgblack@eecs.umich.edu warn("open%s: cannot decode flags 0x%x", 7367189Sgblack@eecs.umich.edu isopenat ? "at" : "", tgt_flags); 7377189Sgblack@eecs.umich.edu } 73810037SARM gem5 Developers#ifdef __CYGWIN32__ 73910037SARM gem5 Developers host_flags |= O_BINARY; 74010037SARM gem5 Developers#endif 74110037SARM gem5 Developers 74210037SARM gem5 Developers int mode = p->getSyscallArg(tc, index); 74310037SARM gem5 Developers 74410037SARM gem5 Developers /** 74510037SARM gem5 Developers * If the simulated process called open or openat with AT_FDCWD specified, 74610037SARM gem5 Developers * take the current working directory value which was passed into the 74710037SARM gem5 Developers * process class as a Python parameter and append the current path to 74810037SARM gem5 Developers * create a full path. 74910037SARM gem5 Developers * Otherwise, openat with a valid target directory file descriptor has 75010037SARM gem5 Developers * been called. If the path option, which was passed in as a parameter, 75110037SARM gem5 Developers * is not absolute, retrieve the directory file descriptor's path and 75210037SARM gem5 Developers * prepend it to the path passed in as a parameter. 75310037SARM gem5 Developers * In every case, we should have a full path (which is relevant to the 75410037SARM gem5 Developers * host) to work with after this block has been passed. 75510037SARM gem5 Developers */ 75610037SARM gem5 Developers if (!isopenat || (isopenat && tgt_dirfd == OS::TGT_AT_FDCWD)) { 75712402Sgiacomo.travaglini@arm.com path = p->fullPath(path); 75812402Sgiacomo.travaglini@arm.com } else if (!startswith(path, "/")) { 75912402Sgiacomo.travaglini@arm.com std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]); 76012402Sgiacomo.travaglini@arm.com auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep); 76112402Sgiacomo.travaglini@arm.com if (!ffdp) 76212402Sgiacomo.travaglini@arm.com return -EBADF; 76310037SARM gem5 Developers path.insert(0, ffdp->getFileName() + "/"); 76410037SARM gem5 Developers } 76510037SARM gem5 Developers 76610037SARM gem5 Developers /** 76710037SARM gem5 Developers * Since this is an emulated environment, we create pseudo file 76810037SARM gem5 Developers * descriptors for device requests that have been registered with 76910037SARM gem5 Developers * the process class through Python; this allows us to create a file 77010037SARM gem5 Developers * descriptor for subsequent ioctl or mmap calls. 77110037SARM gem5 Developers */ 77210037SARM gem5 Developers if (startswith(path, "/dev/")) { 77310037SARM gem5 Developers std::string filename = path.substr(strlen("/dev/")); 77410037SARM gem5 Developers EmulatedDriver *drv = p->findDriver(filename); 77510037SARM gem5 Developers if (drv) { 77610037SARM gem5 Developers DPRINTF_SYSCALL(Verbose, "open%s: passing call to " 77710037SARM gem5 Developers "driver open with path[%s]\n", 77810037SARM gem5 Developers isopenat ? "at" : "", path.c_str()); 77910037SARM gem5 Developers return drv->open(p, tc, mode, host_flags); 78010037SARM gem5 Developers } 78110037SARM gem5 Developers /** 78210037SARM gem5 Developers * Fall through here for pass through to host devices, such 7837197Sgblack@eecs.umich.edu * as /dev/zero 78410417Sandreas.hansson@arm.com */ 7857197Sgblack@eecs.umich.edu } 7868782Sgblack@eecs.umich.edu 7878782Sgblack@eecs.umich.edu /** 7888806Sgblack@eecs.umich.edu * Some special paths and files cannot be called on the host and need 7898806Sgblack@eecs.umich.edu * to be handled as special cases inside the simulator. 7907197Sgblack@eecs.umich.edu * If the full path that was created above does not match any of the 7918806Sgblack@eecs.umich.edu * special cases, pass it through to the open call on the host to let 7928806Sgblack@eecs.umich.edu * the host open the file on our behalf. 7938806Sgblack@eecs.umich.edu * If the host cannot open the file, return the host's error code back 79410037SARM gem5 Developers * through the system call to the simulated process. 79510037SARM gem5 Developers */ 79610037SARM gem5 Developers int sim_fd = -1; 79710037SARM gem5 Developers std::vector<std::string> special_paths = 79810037SARM gem5 Developers { "/proc/", "/system/", "/sys/", "/platform/", "/etc/passwd" }; 79910037SARM gem5 Developers for (auto entry : special_paths) { 80011877Sbrandon.potter@amd.com if (startswith(path, entry)) 80111877Sbrandon.potter@amd.com sim_fd = OS::openSpecialFile(path, p, tc); 8028806Sgblack@eecs.umich.edu } 8038806Sgblack@eecs.umich.edu if (sim_fd == -1) { 8048806Sgblack@eecs.umich.edu sim_fd = open(path.c_str(), host_flags, mode); 8058806Sgblack@eecs.umich.edu } 8068806Sgblack@eecs.umich.edu if (sim_fd == -1) { 8078806Sgblack@eecs.umich.edu int local = -errno; 8087197Sgblack@eecs.umich.edu DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n", 8097197Sgblack@eecs.umich.edu isopenat ? "at" : "", path.c_str()); 81010037SARM gem5 Developers return local; 81110037SARM gem5 Developers } 81210037SARM gem5 Developers 81310037SARM gem5 Developers /** 81410037SARM gem5 Developers * The file was opened successfully and needs to be recorded in the 81510037SARM gem5 Developers * process' file descriptor array so that it can be retrieved later. 81610037SARM gem5 Developers * The target file descriptor that is chosen will be the lowest unused 81710037SARM gem5 Developers * file descriptor. 81810037SARM gem5 Developers * Return the indirect target file descriptor back to the simulated 81910037SARM gem5 Developers * process to act as a handle for the opened file. 82010037SARM gem5 Developers */ 82110037SARM gem5 Developers auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0); 82210037SARM gem5 Developers int tgt_fd = p->fds->allocFD(ffdp); 82310037SARM gem5 Developers DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n", 82410037SARM gem5 Developers isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str()); 82510037SARM gem5 Developers return tgt_fd; 82610037SARM gem5 Developers} 82710037SARM gem5 Developers 82810037SARM gem5 Developers/// Target open() handler. 82910037SARM gem5 Developerstemplate <class OS> 83010037SARM gem5 DevelopersSyscallReturn 83110037SARM gem5 DevelopersopenFunc(SyscallDesc *desc, int callnum, Process *process, 83210037SARM gem5 Developers ThreadContext *tc) 83310037SARM gem5 Developers{ 83410037SARM gem5 Developers return openImpl<OS>(desc, callnum, process, tc, false); 83510037SARM gem5 Developers} 83610037SARM gem5 Developers 83710037SARM gem5 Developers/// Target openat() handler. 83810037SARM gem5 Developerstemplate <class OS> 83910037SARM gem5 DevelopersSyscallReturn 84010037SARM gem5 DevelopersopenatFunc(SyscallDesc *desc, int callnum, Process *process, 84110037SARM gem5 Developers ThreadContext *tc) 84210037SARM gem5 Developers{ 84310037SARM gem5 Developers return openImpl<OS>(desc, callnum, process, tc, true); 84410037SARM gem5 Developers} 84510037SARM gem5 Developers 84610037SARM gem5 Developers/// Target unlinkat() handler. 84710037SARM gem5 Developerstemplate <class OS> 84810037SARM gem5 DevelopersSyscallReturn 84910037SARM gem5 DevelopersunlinkatFunc(SyscallDesc *desc, int callnum, Process *process, 85010037SARM gem5 Developers ThreadContext *tc) 85110037SARM gem5 Developers{ 85212402Sgiacomo.travaglini@arm.com int index = 0; 85312402Sgiacomo.travaglini@arm.com int dirfd = process->getSyscallArg(tc, index); 85412402Sgiacomo.travaglini@arm.com if (dirfd != OS::TGT_AT_FDCWD) 85512402Sgiacomo.travaglini@arm.com warn("unlinkat: first argument not AT_FDCWD; unlikely to work"); 85612402Sgiacomo.travaglini@arm.com 85712402Sgiacomo.travaglini@arm.com return unlinkHelper(desc, callnum, process, tc, 1); 85810037SARM gem5 Developers} 85910037SARM gem5 Developers 86010037SARM gem5 Developers/// Target facessat() handler 86110037SARM gem5 Developerstemplate <class OS> 86210037SARM gem5 DevelopersSyscallReturn 86310037SARM gem5 DevelopersfaccessatFunc(SyscallDesc *desc, int callnum, Process *process, 86410037SARM gem5 Developers ThreadContext *tc) 86510037SARM gem5 Developers{ 86611576SDylan.Johnson@ARM.com int index = 0; 86711576SDylan.Johnson@ARM.com int dirfd = process->getSyscallArg(tc, index); 86811576SDylan.Johnson@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 86911576SDylan.Johnson@ARM.com warn("faccessat: first argument not AT_FDCWD; unlikely to work"); 87011576SDylan.Johnson@ARM.com return accessFunc(desc, callnum, process, tc, 1); 87111576SDylan.Johnson@ARM.com} 87210037SARM gem5 Developers 87310037SARM gem5 Developers/// Target readlinkat() handler 87410037SARM gem5 Developerstemplate <class OS> 87510037SARM gem5 DevelopersSyscallReturn 87610037SARM gem5 DevelopersreadlinkatFunc(SyscallDesc *desc, int callnum, Process *process, 87710037SARM gem5 Developers ThreadContext *tc) 87810037SARM gem5 Developers{ 87910037SARM gem5 Developers int index = 0; 88010037SARM gem5 Developers int dirfd = process->getSyscallArg(tc, index); 88110037SARM gem5 Developers if (dirfd != OS::TGT_AT_FDCWD) 88210037SARM gem5 Developers warn("openat: first argument not AT_FDCWD; unlikely to work"); 88310037SARM gem5 Developers return readlinkFunc(desc, callnum, process, tc, 1); 88410037SARM gem5 Developers} 88510037SARM gem5 Developers 88610037SARM gem5 Developers/// Target renameat() handler. 88710037SARM gem5 Developerstemplate <class OS> 88810037SARM gem5 DevelopersSyscallReturn 88910037SARM gem5 DevelopersrenameatFunc(SyscallDesc *desc, int callnum, Process *process, 89010037SARM gem5 Developers ThreadContext *tc) 89110037SARM gem5 Developers{ 89210037SARM gem5 Developers int index = 0; 89310037SARM gem5 Developers 89410037SARM gem5 Developers int olddirfd = process->getSyscallArg(tc, index); 89510037SARM gem5 Developers if (olddirfd != OS::TGT_AT_FDCWD) 89610037SARM gem5 Developers warn("renameat: first argument not AT_FDCWD; unlikely to work"); 89712511Schuan.zhu@arm.com 89812511Schuan.zhu@arm.com std::string old_name; 89912511Schuan.zhu@arm.com 90012511Schuan.zhu@arm.com if (!tc->getMemProxy().tryReadString(old_name, 90112511Schuan.zhu@arm.com process->getSyscallArg(tc, index))) 90212511Schuan.zhu@arm.com return -EFAULT; 90312511Schuan.zhu@arm.com 90412511Schuan.zhu@arm.com int newdirfd = process->getSyscallArg(tc, index); 90512511Schuan.zhu@arm.com if (newdirfd != OS::TGT_AT_FDCWD) 90612511Schuan.zhu@arm.com warn("renameat: third argument not AT_FDCWD; unlikely to work"); 90712511Schuan.zhu@arm.com 90812511Schuan.zhu@arm.com std::string new_name; 90912511Schuan.zhu@arm.com 91012511Schuan.zhu@arm.com if (!tc->getMemProxy().tryReadString(new_name, 91112511Schuan.zhu@arm.com process->getSyscallArg(tc, index))) 91212511Schuan.zhu@arm.com return -EFAULT; 91312511Schuan.zhu@arm.com 91412511Schuan.zhu@arm.com // Adjust path for current working directory 91512511Schuan.zhu@arm.com old_name = process->fullPath(old_name); 91612511Schuan.zhu@arm.com new_name = process->fullPath(new_name); 91712511Schuan.zhu@arm.com 91812511Schuan.zhu@arm.com int result = rename(old_name.c_str(), new_name.c_str()); 91912511Schuan.zhu@arm.com return (result == -1) ? -errno : result; 92012511Schuan.zhu@arm.com} 92112511Schuan.zhu@arm.com 92210037SARM gem5 Developers/// Target sysinfo() handler. 92310037SARM gem5 Developerstemplate <class OS> 92410037SARM gem5 DevelopersSyscallReturn 92510037SARM gem5 DeveloperssysinfoFunc(SyscallDesc *desc, int callnum, Process *process, 92610037SARM gem5 Developers ThreadContext *tc) 92710037SARM gem5 Developers{ 92810037SARM gem5 Developers 92910037SARM gem5 Developers int index = 0; 93010037SARM gem5 Developers TypedBufferArg<typename OS::tgt_sysinfo> 93110037SARM gem5 Developers sysinfo(process->getSyscallArg(tc, index)); 93210037SARM gem5 Developers 93310037SARM gem5 Developers sysinfo->uptime = seconds_since_epoch; 93410037SARM gem5 Developers sysinfo->totalram = process->system->memSize(); 93510037SARM gem5 Developers sysinfo->mem_unit = 1; 93610037SARM gem5 Developers 93710037SARM gem5 Developers sysinfo.copyOut(tc->getMemProxy()); 93810417Sandreas.hansson@arm.com 93910037SARM gem5 Developers return 0; 94010037SARM gem5 Developers} 94110037SARM gem5 Developers 94210037SARM gem5 Developers/// Target chmod() handler. 94310037SARM gem5 Developerstemplate <class OS> 94410037SARM gem5 DevelopersSyscallReturn 94510037SARM gem5 DeveloperschmodFunc(SyscallDesc *desc, int callnum, Process *process, 94610037SARM gem5 Developers ThreadContext *tc) 94710037SARM gem5 Developers{ 94810037SARM gem5 Developers std::string path; 94910037SARM gem5 Developers 95010037SARM gem5 Developers int index = 0; 95110037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 95212509Schuan.zhu@arm.com process->getSyscallArg(tc, index))) { 95312509Schuan.zhu@arm.com return -EFAULT; 95412509Schuan.zhu@arm.com } 95512509Schuan.zhu@arm.com 95612509Schuan.zhu@arm.com uint32_t mode = process->getSyscallArg(tc, index); 95712509Schuan.zhu@arm.com mode_t hostMode = 0; 95812509Schuan.zhu@arm.com 95912509Schuan.zhu@arm.com // XXX translate mode flags via OS::something??? 96012509Schuan.zhu@arm.com hostMode = mode; 96112509Schuan.zhu@arm.com 96212509Schuan.zhu@arm.com // Adjust path for current working directory 96312509Schuan.zhu@arm.com path = process->fullPath(path); 96412509Schuan.zhu@arm.com 96512509Schuan.zhu@arm.com // do the chmod 96612509Schuan.zhu@arm.com int result = chmod(path.c_str(), hostMode); 96712509Schuan.zhu@arm.com if (result < 0) 96812509Schuan.zhu@arm.com return -errno; 96912509Schuan.zhu@arm.com 97012509Schuan.zhu@arm.com return 0; 97112509Schuan.zhu@arm.com} 97212509Schuan.zhu@arm.com 97312509Schuan.zhu@arm.comtemplate <class OS> 97412509Schuan.zhu@arm.comSyscallReturn 97512509Schuan.zhu@arm.compollFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 97610037SARM gem5 Developers{ 97710037SARM gem5 Developers int index = 0; 97810037SARM gem5 Developers Addr fdsPtr = p->getSyscallArg(tc, index); 97912509Schuan.zhu@arm.com int nfds = p->getSyscallArg(tc, index); 98012509Schuan.zhu@arm.com int tmout = p->getSyscallArg(tc, index); 98112509Schuan.zhu@arm.com 98212509Schuan.zhu@arm.com BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds); 98310037SARM gem5 Developers fdsBuf.copyIn(tc->getMemProxy()); 98410037SARM gem5 Developers 98510037SARM gem5 Developers /** 98610037SARM gem5 Developers * Record the target file descriptors in a local variable. We need to 98710037SARM gem5 Developers * replace them with host file descriptors but we need a temporary copy 98810037SARM gem5 Developers * for later. Afterwards, replace each target file descriptor in the 98910037SARM gem5 Developers * poll_fd array with its host_fd. 99010037SARM gem5 Developers */ 99110037SARM gem5 Developers int temp_tgt_fds[nfds]; 9927362Sgblack@eecs.umich.edu for (index = 0; index < nfds; index++) { 9937362Sgblack@eecs.umich.edu temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd; 99410417Sandreas.hansson@arm.com auto tgt_fd = temp_tgt_fds[index]; 9957362Sgblack@eecs.umich.edu auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]); 99610037SARM gem5 Developers if (!hbfdp) 99710037SARM gem5 Developers return -EBADF; 99810037SARM gem5 Developers auto host_fd = hbfdp->getSimFD(); 99910037SARM gem5 Developers ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd; 100010037SARM gem5 Developers } 100110037SARM gem5 Developers 100210037SARM gem5 Developers /** 100310037SARM gem5 Developers * We cannot allow an infinite poll to occur or it will inevitably cause 100410037SARM gem5 Developers * a deadlock in the gem5 simulator with clone. We must pass in tmout with 100510037SARM gem5 Developers * a non-negative value, however it also makes no sense to poll on the 100610037SARM gem5 Developers * underlying host for any other time than tmout a zero timeout. 100710037SARM gem5 Developers */ 100810037SARM gem5 Developers int status; 100910037SARM gem5 Developers if (tmout < 0) { 101010037SARM gem5 Developers status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0); 101110037SARM gem5 Developers if (status == 0) { 101210037SARM gem5 Developers /** 101310037SARM gem5 Developers * If blocking indefinitely, check the signal list to see if a 101410037SARM gem5 Developers * signal would break the poll out of the retry cycle and try 101510037SARM gem5 Developers * to return the signal interrupt instead. 101610037SARM gem5 Developers */ 101710037SARM gem5 Developers System *sysh = tc->getSystemPtr(); 101810037SARM gem5 Developers std::list<BasicSignal>::iterator it; 101911150Smitch.hayenga@arm.com for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++) 102010037SARM gem5 Developers if (it->receiver == p) 102110037SARM gem5 Developers return -EINTR; 102210037SARM gem5 Developers return SyscallReturn::retry(); 102310037SARM gem5 Developers } 102410037SARM gem5 Developers } else 102510037SARM gem5 Developers status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0); 102610037SARM gem5 Developers 10278205SAli.Saidi@ARM.com if (status == -1) 102810037SARM gem5 Developers return -errno; 102911496Sandreas.sandberg@arm.com 103010037SARM gem5 Developers /** 103110037SARM gem5 Developers * Replace each host_fd in the returned poll_fd array with its original 103210037SARM gem5 Developers * target file descriptor. 103310037SARM gem5 Developers */ 103410037SARM gem5 Developers for (index = 0; index < nfds; index++) { 103510037SARM gem5 Developers auto tgt_fd = temp_tgt_fds[index]; 103610037SARM gem5 Developers ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd; 103710037SARM gem5 Developers } 103810037SARM gem5 Developers 103910037SARM gem5 Developers /** 104010037SARM gem5 Developers * Copy out the pollfd struct because the host may have updated fields 104110037SARM gem5 Developers * in the structure. 104210037SARM gem5 Developers */ 104310037SARM gem5 Developers fdsBuf.copyOut(tc->getMemProxy()); 104411585SDylan.Johnson@ARM.com 104511585SDylan.Johnson@ARM.com return status; 104611585SDylan.Johnson@ARM.com} 104711585SDylan.Johnson@ARM.com 104811585SDylan.Johnson@ARM.com/// Target fchmod() handler. 104911585SDylan.Johnson@ARM.comtemplate <class OS> 105011585SDylan.Johnson@ARM.comSyscallReturn 105111585SDylan.Johnson@ARM.comfchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 105211585SDylan.Johnson@ARM.com{ 105311585SDylan.Johnson@ARM.com int index = 0; 105411585SDylan.Johnson@ARM.com int tgt_fd = p->getSyscallArg(tc, index); 105510037SARM gem5 Developers uint32_t mode = p->getSyscallArg(tc, index); 105610037SARM gem5 Developers 105710037SARM gem5 Developers auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 105810037SARM gem5 Developers if (!ffdp) 105910037SARM gem5 Developers return -EBADF; 106010037SARM gem5 Developers int sim_fd = ffdp->getSimFD(); 106110037SARM gem5 Developers 10627362Sgblack@eecs.umich.edu mode_t hostMode = mode; 10638314Sgeoffrey.blake@arm.com 106410037SARM gem5 Developers int result = fchmod(sim_fd, hostMode); 106510037SARM gem5 Developers 106610037SARM gem5 Developers return (result < 0) ? -errno : 0; 106710037SARM gem5 Developers} 106810037SARM gem5 Developers 106910037SARM gem5 Developers/// Target mremap() handler. 107010037SARM gem5 Developerstemplate <class OS> 107110037SARM gem5 DevelopersSyscallReturn 107210037SARM gem5 DevelopersmremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) 107310037SARM gem5 Developers{ 107410037SARM gem5 Developers int index = 0; 107510037SARM gem5 Developers Addr start = process->getSyscallArg(tc, index); 107610037SARM gem5 Developers uint64_t old_length = process->getSyscallArg(tc, index); 107710037SARM gem5 Developers uint64_t new_length = process->getSyscallArg(tc, index); 107810037SARM gem5 Developers uint64_t flags = process->getSyscallArg(tc, index); 107910037SARM gem5 Developers uint64_t provided_address = 0; 108010037SARM gem5 Developers bool use_provided_address = flags & OS::TGT_MREMAP_FIXED; 108110037SARM gem5 Developers 108210037SARM gem5 Developers if (use_provided_address) 108310037SARM gem5 Developers provided_address = process->getSyscallArg(tc, index); 108410037SARM gem5 Developers 108510037SARM gem5 Developers if ((start % TheISA::PageBytes != 0) || 108610037SARM gem5 Developers (provided_address % TheISA::PageBytes != 0)) { 108710037SARM gem5 Developers warn("mremap failing: arguments not page aligned"); 108810037SARM gem5 Developers return -EINVAL; 108910037SARM gem5 Developers } 109010037SARM gem5 Developers 109110037SARM gem5 Developers new_length = roundUp(new_length, TheISA::PageBytes); 109210037SARM gem5 Developers 109310037SARM gem5 Developers if (new_length > old_length) { 109410037SARM gem5 Developers std::shared_ptr<MemState> mem_state = process->memState; 109510037SARM gem5 Developers Addr mmap_end = mem_state->getMmapEnd(); 109610037SARM gem5 Developers 109710037SARM gem5 Developers if ((start + old_length) == mmap_end && 109810037SARM gem5 Developers (!use_provided_address || provided_address == start)) { 109910037SARM gem5 Developers // This case cannot occur when growing downward, as 110010037SARM gem5 Developers // start is greater than or equal to mmap_end. 110110037SARM gem5 Developers uint64_t diff = new_length - old_length; 110210037SARM gem5 Developers process->allocateMem(mmap_end, diff); 110310037SARM gem5 Developers mem_state->setMmapEnd(mmap_end + diff); 110410037SARM gem5 Developers return start; 110510037SARM gem5 Developers } else { 110610037SARM gem5 Developers if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { 110710037SARM gem5 Developers warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 110810037SARM gem5 Developers return -ENOMEM; 110910037SARM gem5 Developers } else { 111010037SARM gem5 Developers uint64_t new_start = provided_address; 111110037SARM gem5 Developers if (!use_provided_address) { 111210037SARM gem5 Developers new_start = process->mmapGrowsDown() ? 111310037SARM gem5 Developers mmap_end - new_length : mmap_end; 111410037SARM gem5 Developers mmap_end = process->mmapGrowsDown() ? 111510037SARM gem5 Developers new_start : mmap_end + new_length; 111610037SARM gem5 Developers mem_state->setMmapEnd(mmap_end); 111710037SARM gem5 Developers } 111810037SARM gem5 Developers 111910037SARM gem5 Developers process->pTable->remap(start, old_length, new_start); 112010037SARM gem5 Developers warn("mremapping to new vaddr %08p-%08p, adding %d\n", 112110037SARM gem5 Developers new_start, new_start + new_length, 112210037SARM gem5 Developers new_length - old_length); 112310037SARM gem5 Developers // add on the remaining unallocated pages 112410037SARM gem5 Developers process->allocateMem(new_start + old_length, 112510037SARM gem5 Developers new_length - old_length, 112610037SARM gem5 Developers use_provided_address /* clobber */); 112710037SARM gem5 Developers if (use_provided_address && 112810037SARM gem5 Developers ((new_start + new_length > mem_state->getMmapEnd() && 112910037SARM gem5 Developers !process->mmapGrowsDown()) || 113010037SARM gem5 Developers (new_start < mem_state->getMmapEnd() && 113110037SARM gem5 Developers process->mmapGrowsDown()))) { 113210037SARM gem5 Developers // something fishy going on here, at least notify the user 113310037SARM gem5 Developers // @todo: increase mmap_end? 113410037SARM gem5 Developers warn("mmap region limit exceeded with MREMAP_FIXED\n"); 113510037SARM gem5 Developers } 113610037SARM gem5 Developers warn("returning %08p as start\n", new_start); 113710037SARM gem5 Developers return new_start; 113810037SARM gem5 Developers } 113910037SARM gem5 Developers } 114010037SARM gem5 Developers } else { 114110037SARM gem5 Developers if (use_provided_address && provided_address != start) 114210037SARM gem5 Developers process->pTable->remap(start, new_length, provided_address); 114310037SARM gem5 Developers process->pTable->unmap(start + new_length, old_length - new_length); 114410037SARM gem5 Developers return use_provided_address ? provided_address : start; 114510037SARM gem5 Developers } 114610037SARM gem5 Developers} 114710037SARM gem5 Developers 114810037SARM gem5 Developers/// Target stat() handler. 114910037SARM gem5 Developerstemplate <class OS> 115010037SARM gem5 DevelopersSyscallReturn 115110037SARM gem5 DevelopersstatFunc(SyscallDesc *desc, int callnum, Process *process, 115210037SARM gem5 Developers ThreadContext *tc) 115310037SARM gem5 Developers{ 115410037SARM gem5 Developers std::string path; 115510037SARM gem5 Developers 115610037SARM gem5 Developers int index = 0; 115710037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 115810037SARM gem5 Developers process->getSyscallArg(tc, index))) { 115910037SARM gem5 Developers return -EFAULT; 116010037SARM gem5 Developers } 116110037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 116210037SARM gem5 Developers 116310037SARM gem5 Developers // Adjust path for current working directory 116410037SARM gem5 Developers path = process->fullPath(path); 116510037SARM gem5 Developers 116610037SARM gem5 Developers struct stat hostBuf; 116710037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 116810037SARM gem5 Developers 116910037SARM gem5 Developers if (result < 0) 117010037SARM gem5 Developers return -errno; 117110037SARM gem5 Developers 117210037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 117310037SARM gem5 Developers 117410037SARM gem5 Developers return 0; 117510037SARM gem5 Developers} 117610037SARM gem5 Developers 117710037SARM gem5 Developers 117810037SARM gem5 Developers/// Target stat64() handler. 117910037SARM gem5 Developerstemplate <class OS> 118010037SARM gem5 DevelopersSyscallReturn 118110037SARM gem5 Developersstat64Func(SyscallDesc *desc, int callnum, Process *process, 118210037SARM gem5 Developers ThreadContext *tc) 118310037SARM gem5 Developers{ 118410037SARM gem5 Developers std::string path; 118510037SARM gem5 Developers 118610037SARM gem5 Developers int index = 0; 118710037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 118810037SARM gem5 Developers process->getSyscallArg(tc, index))) 118910037SARM gem5 Developers return -EFAULT; 119010037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 119110037SARM gem5 Developers 119210037SARM gem5 Developers // Adjust path for current working directory 119310037SARM gem5 Developers path = process->fullPath(path); 119410037SARM gem5 Developers 119510037SARM gem5 Developers#if NO_STAT64 119610037SARM gem5 Developers struct stat hostBuf; 119710037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 119810037SARM gem5 Developers#else 119910037SARM gem5 Developers struct stat64 hostBuf; 120010037SARM gem5 Developers int result = stat64(path.c_str(), &hostBuf); 120111581SDylan.Johnson@ARM.com#endif 120210037SARM gem5 Developers 120310037SARM gem5 Developers if (result < 0) 120410037SARM gem5 Developers return -errno; 120510037SARM gem5 Developers 120610037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 120710037SARM gem5 Developers 120810037SARM gem5 Developers return 0; 120910037SARM gem5 Developers} 121010037SARM gem5 Developers 121110367SAndrew.Bardsley@arm.com 121210367SAndrew.Bardsley@arm.com/// Target fstatat64() handler. 121310037SARM gem5 Developerstemplate <class OS> 121410037SARM gem5 DevelopersSyscallReturn 121510037SARM gem5 Developersfstatat64Func(SyscallDesc *desc, int callnum, Process *process, 121610037SARM gem5 Developers ThreadContext *tc) 121710037SARM gem5 Developers{ 121810037SARM gem5 Developers int index = 0; 121910037SARM gem5 Developers int dirfd = process->getSyscallArg(tc, index); 122010037SARM gem5 Developers if (dirfd != OS::TGT_AT_FDCWD) 122110037SARM gem5 Developers warn("fstatat64: first argument not AT_FDCWD; unlikely to work"); 122210037SARM gem5 Developers 122310037SARM gem5 Developers std::string path; 122410037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 122510037SARM gem5 Developers process->getSyscallArg(tc, index))) 122610037SARM gem5 Developers return -EFAULT; 122710037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 122810037SARM gem5 Developers 122910037SARM gem5 Developers // Adjust path for current working directory 123010037SARM gem5 Developers path = process->fullPath(path); 123110037SARM gem5 Developers 123210037SARM gem5 Developers#if NO_STAT64 123310037SARM gem5 Developers struct stat hostBuf; 123410037SARM gem5 Developers int result = stat(path.c_str(), &hostBuf); 123510037SARM gem5 Developers#else 123610037SARM gem5 Developers struct stat64 hostBuf; 123710037SARM gem5 Developers int result = stat64(path.c_str(), &hostBuf); 123810037SARM gem5 Developers#endif 123910037SARM gem5 Developers 124010037SARM gem5 Developers if (result < 0) 124110037SARM gem5 Developers return -errno; 124210037SARM gem5 Developers 124310037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 124410037SARM gem5 Developers 124510037SARM gem5 Developers return 0; 124610037SARM gem5 Developers} 124710037SARM gem5 Developers 124810037SARM gem5 Developers 124910037SARM gem5 Developers/// Target fstat64() handler. 125010037SARM gem5 Developerstemplate <class OS> 125110037SARM gem5 DevelopersSyscallReturn 125210037SARM gem5 Developersfstat64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 125310037SARM gem5 Developers{ 125410037SARM gem5 Developers int index = 0; 125510037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 125610037SARM gem5 Developers Addr bufPtr = p->getSyscallArg(tc, index); 125710037SARM gem5 Developers 125810037SARM gem5 Developers auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 125910037SARM gem5 Developers if (!ffdp) 126010037SARM gem5 Developers return -EBADF; 126110037SARM gem5 Developers int sim_fd = ffdp->getSimFD(); 126210037SARM gem5 Developers 126310037SARM gem5 Developers#if NO_STAT64 126410037SARM gem5 Developers struct stat hostBuf; 126510037SARM gem5 Developers int result = fstat(sim_fd, &hostBuf); 126610037SARM gem5 Developers#else 126711581SDylan.Johnson@ARM.com struct stat64 hostBuf; 126810037SARM gem5 Developers int result = fstat64(sim_fd, &hostBuf); 126910037SARM gem5 Developers#endif 127010037SARM gem5 Developers 127110037SARM gem5 Developers if (result < 0) 127210037SARM gem5 Developers return -errno; 127310037SARM gem5 Developers 127410037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 127510037SARM gem5 Developers 127610037SARM gem5 Developers return 0; 127710037SARM gem5 Developers} 127810037SARM gem5 Developers 127910037SARM gem5 Developers 128010037SARM gem5 Developers/// Target lstat() handler. 128110037SARM gem5 Developerstemplate <class OS> 128210037SARM gem5 DevelopersSyscallReturn 128310037SARM gem5 DeveloperslstatFunc(SyscallDesc *desc, int callnum, Process *process, 128410037SARM gem5 Developers ThreadContext *tc) 128510037SARM gem5 Developers{ 128610037SARM gem5 Developers std::string path; 128710037SARM gem5 Developers 128810037SARM gem5 Developers int index = 0; 128910037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 129010037SARM gem5 Developers process->getSyscallArg(tc, index))) { 129110037SARM gem5 Developers return -EFAULT; 129210037SARM gem5 Developers } 129310037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 129410037SARM gem5 Developers 129510037SARM gem5 Developers // Adjust path for current working directory 129610037SARM gem5 Developers path = process->fullPath(path); 129710037SARM gem5 Developers 129810037SARM gem5 Developers struct stat hostBuf; 129910037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 130010037SARM gem5 Developers 130110037SARM gem5 Developers if (result < 0) 130210037SARM gem5 Developers return -errno; 130310037SARM gem5 Developers 130410037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 130510037SARM gem5 Developers 130610037SARM gem5 Developers return 0; 130710037SARM gem5 Developers} 130810037SARM gem5 Developers 130910037SARM gem5 Developers/// Target lstat64() handler. 131010037SARM gem5 Developerstemplate <class OS> 131110037SARM gem5 DevelopersSyscallReturn 131210037SARM gem5 Developerslstat64Func(SyscallDesc *desc, int callnum, Process *process, 131310037SARM gem5 Developers ThreadContext *tc) 131410037SARM gem5 Developers{ 131510037SARM gem5 Developers std::string path; 131610037SARM gem5 Developers 131710037SARM gem5 Developers int index = 0; 131810037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 131910037SARM gem5 Developers process->getSyscallArg(tc, index))) { 132010037SARM gem5 Developers return -EFAULT; 132110037SARM gem5 Developers } 132210037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 132310037SARM gem5 Developers 132410037SARM gem5 Developers // Adjust path for current working directory 132510037SARM gem5 Developers path = process->fullPath(path); 132610037SARM gem5 Developers 132710037SARM gem5 Developers#if NO_STAT64 132810417Sandreas.hansson@arm.com struct stat hostBuf; 132910037SARM gem5 Developers int result = lstat(path.c_str(), &hostBuf); 133010037SARM gem5 Developers#else 133110037SARM gem5 Developers struct stat64 hostBuf; 133210037SARM gem5 Developers int result = lstat64(path.c_str(), &hostBuf); 133310037SARM gem5 Developers#endif 133410037SARM gem5 Developers 133510037SARM gem5 Developers if (result < 0) 133610037SARM gem5 Developers return -errno; 133710037SARM gem5 Developers 133810037SARM gem5 Developers copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 133910037SARM gem5 Developers 134010037SARM gem5 Developers return 0; 134110037SARM gem5 Developers} 134210037SARM gem5 Developers 134310037SARM gem5 Developers/// Target fstat() handler. 134410037SARM gem5 Developerstemplate <class OS> 134510037SARM gem5 DevelopersSyscallReturn 134610037SARM gem5 DevelopersfstatFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 134710037SARM gem5 Developers{ 134810037SARM gem5 Developers int index = 0; 134910037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 135010037SARM gem5 Developers Addr bufPtr = p->getSyscallArg(tc, index); 135110037SARM gem5 Developers 135210037SARM gem5 Developers DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd); 135310037SARM gem5 Developers 135410037SARM gem5 Developers auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 135510037SARM gem5 Developers if (!ffdp) 135610037SARM gem5 Developers return -EBADF; 135711581SDylan.Johnson@ARM.com int sim_fd = ffdp->getSimFD(); 135810037SARM gem5 Developers 135910037SARM gem5 Developers struct stat hostBuf; 136010037SARM gem5 Developers int result = fstat(sim_fd, &hostBuf); 136110037SARM gem5 Developers 136210037SARM gem5 Developers if (result < 0) 136310037SARM gem5 Developers return -errno; 136410037SARM gem5 Developers 136510037SARM gem5 Developers copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 136610037SARM gem5 Developers 136710037SARM gem5 Developers return 0; 136810037SARM gem5 Developers} 136910037SARM gem5 Developers 137010037SARM gem5 Developers/// Target statfs() handler. 137110037SARM gem5 Developerstemplate <class OS> 137210037SARM gem5 DevelopersSyscallReturn 137310037SARM gem5 DevelopersstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 137410037SARM gem5 Developers ThreadContext *tc) 137510037SARM gem5 Developers{ 137610037SARM gem5 Developers#if NO_STATFS 137710037SARM gem5 Developers warn("Host OS cannot support calls to statfs. Ignoring syscall"); 137810037SARM gem5 Developers#else 137910037SARM gem5 Developers std::string path; 138010037SARM gem5 Developers 138110037SARM gem5 Developers int index = 0; 138210037SARM gem5 Developers if (!tc->getMemProxy().tryReadString(path, 138310037SARM gem5 Developers process->getSyscallArg(tc, index))) { 138410037SARM gem5 Developers return -EFAULT; 138510037SARM gem5 Developers } 138610037SARM gem5 Developers Addr bufPtr = process->getSyscallArg(tc, index); 138710037SARM gem5 Developers 138810037SARM gem5 Developers // Adjust path for current working directory 138910037SARM gem5 Developers path = process->fullPath(path); 139010037SARM gem5 Developers 139110037SARM gem5 Developers struct statfs hostBuf; 139210037SARM gem5 Developers int result = statfs(path.c_str(), &hostBuf); 139310037SARM gem5 Developers 139410037SARM gem5 Developers if (result < 0) 139510037SARM gem5 Developers return -errno; 139611581SDylan.Johnson@ARM.com 139710037SARM gem5 Developers copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 139810037SARM gem5 Developers#endif 139910037SARM gem5 Developers return 0; 140010037SARM gem5 Developers} 140110037SARM gem5 Developers 140210037SARM gem5 Developerstemplate <class OS> 140310037SARM gem5 DevelopersSyscallReturn 140410037SARM gem5 DeveloperscloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 140510037SARM gem5 Developers{ 140610037SARM gem5 Developers int index = 0; 140710037SARM gem5 Developers 140810037SARM gem5 Developers RegVal flags = p->getSyscallArg(tc, index); 140910037SARM gem5 Developers RegVal newStack = p->getSyscallArg(tc, index); 141010037SARM gem5 Developers Addr ptidPtr = p->getSyscallArg(tc, index); 141110037SARM gem5 Developers 141210037SARM gem5 Developers#if THE_ISA == RISCV_ISA or THE_ISA == ARM_ISA 141310037SARM gem5 Developers /** 141410037SARM gem5 Developers * Linux sets CLONE_BACKWARDS flag for RISC-V and Arm. 141510037SARM gem5 Developers * The flag defines the list of clone() arguments in the following 141610037SARM gem5 Developers * order: flags -> newStack -> ptidPtr -> tlsPtr -> ctidPtr 141710037SARM gem5 Developers */ 141810037SARM gem5 Developers Addr tlsPtr = p->getSyscallArg(tc, index); 141910037SARM gem5 Developers Addr ctidPtr = p->getSyscallArg(tc, index); 142010037SARM gem5 Developers#else 142110037SARM gem5 Developers Addr ctidPtr = p->getSyscallArg(tc, index); 142210037SARM gem5 Developers Addr tlsPtr = p->getSyscallArg(tc, index); 142310037SARM gem5 Developers#endif 142410037SARM gem5 Developers 142510037SARM gem5 Developers if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) || 142610037SARM gem5 Developers ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) || 142710417Sandreas.hansson@arm.com ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) || 142810037SARM gem5 Developers ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) || 142910037SARM gem5 Developers ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) || 143010037SARM gem5 Developers ((flags & OS::TGT_CLONE_VM) && !(newStack))) 143110037SARM gem5 Developers return -EINVAL; 143210037SARM gem5 Developers 143310037SARM gem5 Developers ThreadContext *ctc; 143410037SARM gem5 Developers if (!(ctc = p->findFreeContext())) 143512568Sgiacomo.travaglini@arm.com fatal("clone: no spare thread context in system"); 143612568Sgiacomo.travaglini@arm.com 143712568Sgiacomo.travaglini@arm.com /** 143812568Sgiacomo.travaglini@arm.com * Note that ProcessParams is generated by swig and there are no other 143912568Sgiacomo.travaglini@arm.com * examples of how to create anything but this default constructor. The 144012568Sgiacomo.travaglini@arm.com * fields are manually initialized instead of passing parameters to the 144112568Sgiacomo.travaglini@arm.com * constructor. 144212568Sgiacomo.travaglini@arm.com */ 144312568Sgiacomo.travaglini@arm.com ProcessParams *pp = new ProcessParams(); 144412568Sgiacomo.travaglini@arm.com pp->executable.assign(*(new std::string(p->progName()))); 144512568Sgiacomo.travaglini@arm.com pp->cmd.push_back(*(new std::string(p->progName()))); 144612568Sgiacomo.travaglini@arm.com pp->system = p->system; 144712568Sgiacomo.travaglini@arm.com pp->cwd.assign(p->getcwd()); 144812568Sgiacomo.travaglini@arm.com pp->input.assign("stdin"); 144910037SARM gem5 Developers pp->output.assign("stdout"); 145010037SARM gem5 Developers pp->errout.assign("stderr"); 145110037SARM gem5 Developers pp->uid = p->uid(); 145210037SARM gem5 Developers pp->euid = p->euid(); 145310037SARM gem5 Developers pp->gid = p->gid(); 145410037SARM gem5 Developers pp->egid = p->egid(); 145510037SARM gem5 Developers 145610417Sandreas.hansson@arm.com /* Find the first free PID that's less than the maximum */ 145710037SARM gem5 Developers std::set<int> const& pids = p->system->PIDs; 145811150Smitch.hayenga@arm.com int temp_pid = *pids.begin(); 145910037SARM gem5 Developers do { 146010037SARM gem5 Developers temp_pid++; 146110037SARM gem5 Developers } while (pids.find(temp_pid) != pids.end()); 146210037SARM gem5 Developers if (temp_pid >= System::maxPID) 146310037SARM gem5 Developers fatal("temp_pid is too large: %d", temp_pid); 146410037SARM gem5 Developers 146510037SARM gem5 Developers pp->pid = temp_pid; 146610037SARM gem5 Developers pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid(); 146710037SARM gem5 Developers Process *cp = pp->create(); 146810037SARM gem5 Developers delete pp; 146910037SARM gem5 Developers 147010037SARM gem5 Developers Process *owner = ctc->getProcessPtr(); 147110037SARM gem5 Developers ctc->setProcessPtr(cp); 147210037SARM gem5 Developers cp->assignThreadContext(ctc->contextId()); 147310037SARM gem5 Developers owner->revokeThreadContext(ctc->contextId()); 147410037SARM gem5 Developers 147510037SARM gem5 Developers if (flags & OS::TGT_CLONE_PARENT_SETTID) { 147610037SARM gem5 Developers BufferArg ptidBuf(ptidPtr, sizeof(long)); 147710037SARM gem5 Developers long *ptid = (long *)ptidBuf.bufferPtr(); 147810037SARM gem5 Developers *ptid = cp->pid(); 147910037SARM gem5 Developers ptidBuf.copyOut(tc->getMemProxy()); 148011581SDylan.Johnson@ARM.com } 148111581SDylan.Johnson@ARM.com 148210037SARM gem5 Developers cp->initState(); 14837362Sgblack@eecs.umich.edu p->clone(tc, ctc, cp, flags); 14847362Sgblack@eecs.umich.edu 148512299Sandreas.sandberg@arm.com if (flags & OS::TGT_CLONE_THREAD) { 148612299Sandreas.sandberg@arm.com delete cp->sigchld; 148712299Sandreas.sandberg@arm.com cp->sigchld = p->sigchld; 148812299Sandreas.sandberg@arm.com } else if (flags & OS::TGT_SIGCHLD) { 148912299Sandreas.sandberg@arm.com *cp->sigchld = true; 149012299Sandreas.sandberg@arm.com } 149112299Sandreas.sandberg@arm.com 149212299Sandreas.sandberg@arm.com if (flags & OS::TGT_CLONE_CHILD_SETTID) { 149312299Sandreas.sandberg@arm.com BufferArg ctidBuf(ctidPtr, sizeof(long)); 149412299Sandreas.sandberg@arm.com long *ctid = (long *)ctidBuf.bufferPtr(); 149512299Sandreas.sandberg@arm.com *ctid = cp->pid(); 149612299Sandreas.sandberg@arm.com ctidBuf.copyOut(ctc->getMemProxy()); 149712299Sandreas.sandberg@arm.com } 149812299Sandreas.sandberg@arm.com 149912299Sandreas.sandberg@arm.com if (flags & OS::TGT_CLONE_CHILD_CLEARTID) 150012299Sandreas.sandberg@arm.com cp->childClearTID = (uint64_t)ctidPtr; 150112299Sandreas.sandberg@arm.com 150212299Sandreas.sandberg@arm.com ctc->clearArchRegs(); 150312299Sandreas.sandberg@arm.com 15047652Sminkyu.jeong@arm.com OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr); 150510417Sandreas.hansson@arm.com 15068518Sgeoffrey.blake@arm.com cp->setSyscallReturn(ctc, 0); 15078806Sgblack@eecs.umich.edu 15088806Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA 15098806Sgblack@eecs.umich.edu ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 15108806Sgblack@eecs.umich.edu#elif THE_ISA == SPARC_ISA 15118806Sgblack@eecs.umich.edu tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 15128806Sgblack@eecs.umich.edu ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 15138806Sgblack@eecs.umich.edu#endif 151411150Smitch.hayenga@arm.com 15158518Sgeoffrey.blake@arm.com TheISA::PCState cpc = tc->pcState(); 15168518Sgeoffrey.blake@arm.com cpc.advance(); 151710037SARM gem5 Developers ctc->pcState(cpc); 151810037SARM gem5 Developers ctc->activate(); 151910037SARM gem5 Developers 152010037SARM gem5 Developers return cp->pid(); 152110037SARM gem5 Developers} 152210037SARM gem5 Developers 152310037SARM gem5 Developers/// Target fstatfs() handler. 152410037SARM gem5 Developerstemplate <class OS> 152510037SARM gem5 DevelopersSyscallReturn 152610037SARM gem5 DevelopersfstatfsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 152710037SARM gem5 Developers{ 152810037SARM gem5 Developers int index = 0; 152910037SARM gem5 Developers int tgt_fd = p->getSyscallArg(tc, index); 153010037SARM gem5 Developers Addr bufPtr = p->getSyscallArg(tc, index); 153110037SARM gem5 Developers 153210037SARM gem5 Developers auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 153310037SARM gem5 Developers if (!ffdp) 153410037SARM gem5 Developers return -EBADF; 153510037SARM gem5 Developers int sim_fd = ffdp->getSimFD(); 153612299Sandreas.sandberg@arm.com 153710037SARM gem5 Developers struct statfs hostBuf; 153810037SARM gem5 Developers int result = fstatfs(sim_fd, &hostBuf); 153910037SARM gem5 Developers 154010037SARM gem5 Developers if (result < 0) 154110037SARM gem5 Developers return -errno; 154210037SARM gem5 Developers 154310037SARM gem5 Developers copyOutStatfsBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 154410037SARM gem5 Developers 154510037SARM gem5 Developers return 0; 15466019Shines@cs.fsu.edu} 15476019Shines@cs.fsu.edu 1548/// Target readv() handler. 1549template <class OS> 1550SyscallReturn 1551readvFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 1552{ 1553 int index = 0; 1554 int tgt_fd = p->getSyscallArg(tc, index); 1555 1556 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 1557 if (!ffdp) 1558 return -EBADF; 1559 int sim_fd = ffdp->getSimFD(); 1560 1561 SETranslatingPortProxy &prox = tc->getMemProxy(); 1562 uint64_t tiov_base = p->getSyscallArg(tc, index); 1563 size_t count = p->getSyscallArg(tc, index); 1564 typename OS::tgt_iovec tiov[count]; 1565 struct iovec hiov[count]; 1566 for (size_t i = 0; i < count; ++i) { 1567 prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)), 1568 (uint8_t*)&tiov[i], sizeof(typename OS::tgt_iovec)); 1569 hiov[i].iov_len = TheISA::gtoh(tiov[i].iov_len); 1570 hiov[i].iov_base = new char [hiov[i].iov_len]; 1571 } 1572 1573 int result = readv(sim_fd, hiov, count); 1574 int local_errno = errno; 1575 1576 for (size_t i = 0; i < count; ++i) { 1577 if (result != -1) { 1578 prox.writeBlob(TheISA::htog(tiov[i].iov_base), 1579 (uint8_t*)hiov[i].iov_base, hiov[i].iov_len); 1580 } 1581 delete [] (char *)hiov[i].iov_base; 1582 } 1583 1584 return (result == -1) ? -local_errno : result; 1585} 1586 1587/// Target writev() handler. 1588template <class OS> 1589SyscallReturn 1590writevFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 1591{ 1592 int index = 0; 1593 int tgt_fd = p->getSyscallArg(tc, index); 1594 1595 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]); 1596 if (!hbfdp) 1597 return -EBADF; 1598 int sim_fd = hbfdp->getSimFD(); 1599 1600 SETranslatingPortProxy &prox = tc->getMemProxy(); 1601 uint64_t tiov_base = p->getSyscallArg(tc, index); 1602 size_t count = p->getSyscallArg(tc, index); 1603 struct iovec hiov[count]; 1604 for (size_t i = 0; i < count; ++i) { 1605 typename OS::tgt_iovec tiov; 1606 1607 prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 1608 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 1609 hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 1610 hiov[i].iov_base = new char [hiov[i].iov_len]; 1611 prox.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 1612 hiov[i].iov_len); 1613 } 1614 1615 int result = writev(sim_fd, hiov, count); 1616 1617 for (size_t i = 0; i < count; ++i) 1618 delete [] (char *)hiov[i].iov_base; 1619 1620 return (result == -1) ? -errno : result; 1621} 1622 1623/// Real mmap handler. 1624template <class OS> 1625SyscallReturn 1626mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, 1627 bool is_mmap2) 1628{ 1629 int index = 0; 1630 Addr start = p->getSyscallArg(tc, index); 1631 uint64_t length = p->getSyscallArg(tc, index); 1632 int prot = p->getSyscallArg(tc, index); 1633 int tgt_flags = p->getSyscallArg(tc, index); 1634 int tgt_fd = p->getSyscallArg(tc, index); 1635 int offset = p->getSyscallArg(tc, index); 1636 1637 if (is_mmap2) 1638 offset *= TheISA::PageBytes; 1639 1640 if (start & (TheISA::PageBytes - 1) || 1641 offset & (TheISA::PageBytes - 1) || 1642 (tgt_flags & OS::TGT_MAP_PRIVATE && 1643 tgt_flags & OS::TGT_MAP_SHARED) || 1644 (!(tgt_flags & OS::TGT_MAP_PRIVATE) && 1645 !(tgt_flags & OS::TGT_MAP_SHARED)) || 1646 !length) { 1647 return -EINVAL; 1648 } 1649 1650 if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) { 1651 // With shared mmaps, there are two cases to consider: 1652 // 1) anonymous: writes should modify the mapping and this should be 1653 // visible to observers who share the mapping. Currently, it's 1654 // difficult to update the shared mapping because there's no 1655 // structure which maintains information about the which virtual 1656 // memory areas are shared. If that structure existed, it would be 1657 // possible to make the translations point to the same frames. 1658 // 2) file-backed: writes should modify the mapping and the file 1659 // which is backed by the mapping. The shared mapping problem is the 1660 // same as what was mentioned about the anonymous mappings. For 1661 // file-backed mappings, the writes to the file are difficult 1662 // because it requires syncing what the mapping holds with the file 1663 // that resides on the host system. So, any write on a real system 1664 // would cause the change to be propagated to the file mapping at 1665 // some point in the future (the inode is tracked along with the 1666 // mapping). This isn't guaranteed to always happen, but it usually 1667 // works well enough. The guarantee is provided by the msync system 1668 // call. We could force the change through with shared mappings with 1669 // a call to msync, but that again would require more information 1670 // than we currently maintain. 1671 warn("mmap: writing to shared mmap region is currently " 1672 "unsupported. The write succeeds on the target, but it " 1673 "will not be propagated to the host or shared mappings"); 1674 } 1675 1676 length = roundUp(length, TheISA::PageBytes); 1677 1678 int sim_fd = -1; 1679 uint8_t *pmap = nullptr; 1680 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) { 1681 std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd]; 1682 1683 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep); 1684 if (dfdp) { 1685 EmulatedDriver *emul_driver = dfdp->getDriver(); 1686 return emul_driver->mmap(p, tc, start, length, prot, 1687 tgt_flags, tgt_fd, offset); 1688 } 1689 1690 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep); 1691 if (!ffdp) 1692 return -EBADF; 1693 sim_fd = ffdp->getSimFD(); 1694 1695 pmap = (decltype(pmap))mmap(nullptr, length, PROT_READ, MAP_PRIVATE, 1696 sim_fd, offset); 1697 1698 if (pmap == (decltype(pmap))-1) { 1699 warn("mmap: failed to map file into host address space"); 1700 return -errno; 1701 } 1702 } 1703 1704 // Extend global mmap region if necessary. Note that we ignore the 1705 // start address unless MAP_FIXED is specified. 1706 if (!(tgt_flags & OS::TGT_MAP_FIXED)) { 1707 std::shared_ptr<MemState> mem_state = p->memState; 1708 Addr mmap_end = mem_state->getMmapEnd(); 1709 1710 start = p->mmapGrowsDown() ? mmap_end - length : mmap_end; 1711 mmap_end = p->mmapGrowsDown() ? start : mmap_end + length; 1712 1713 mem_state->setMmapEnd(mmap_end); 1714 } 1715 1716 DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n", 1717 start, start + length - 1); 1718 1719 // We only allow mappings to overwrite existing mappings if 1720 // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem 1721 // because we ignore the start hint if TGT_MAP_FIXED is not set. 1722 int clobber = tgt_flags & OS::TGT_MAP_FIXED; 1723 if (clobber) { 1724 for (auto tc : p->system->threadContexts) { 1725 // If we might be overwriting old mappings, we need to 1726 // invalidate potentially stale mappings out of the TLBs. 1727 tc->getDTBPtr()->flushAll(); 1728 tc->getITBPtr()->flushAll(); 1729 } 1730 } 1731 1732 // Allocate physical memory and map it in. If the page table is already 1733 // mapped and clobber is not set, the simulator will issue throw a 1734 // fatal and bail out of the simulation. 1735 p->allocateMem(start, length, clobber); 1736 1737 // Transfer content into target address space. 1738 SETranslatingPortProxy &tp = tc->getMemProxy(); 1739 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) { 1740 // In general, we should zero the mapped area for anonymous mappings, 1741 // with something like: 1742 // tp.memsetBlob(start, 0, length); 1743 // However, given that we don't support sparse mappings, and 1744 // some applications can map a couple of gigabytes of space 1745 // (intending sparse usage), that can get painfully expensive. 1746 // Fortunately, since we don't properly implement munmap either, 1747 // there's no danger of remapping used memory, so for now all 1748 // newly mapped memory should already be zeroed so we can skip it. 1749 } else { 1750 // It is possible to mmap an area larger than a file, however 1751 // accessing unmapped portions the system triggers a "Bus error" 1752 // on the host. We must know when to stop copying the file from 1753 // the host into the target address space. 1754 struct stat file_stat; 1755 if (fstat(sim_fd, &file_stat) > 0) 1756 fatal("mmap: cannot stat file"); 1757 1758 // Copy the portion of the file that is resident. This requires 1759 // checking both the mmap size and the filesize that we are 1760 // trying to mmap into this space; the mmap size also depends 1761 // on the specified offset into the file. 1762 uint64_t size = std::min((uint64_t)file_stat.st_size - offset, 1763 length); 1764 tp.writeBlob(start, pmap, size); 1765 1766 // Cleanup the mmap region before exiting this function. 1767 munmap(pmap, length); 1768 1769 // Maintain the symbol table for dynamic executables. 1770 // The loader will call mmap to map the images into its address 1771 // space and we intercept that here. We can verify that we are 1772 // executing inside the loader by checking the program counter value. 1773 // XXX: with multiprogrammed workloads or multi-node configurations, 1774 // this will not work since there is a single global symbol table. 1775 ObjectFile *interpreter = p->getInterpreter(); 1776 if (interpreter) { 1777 Addr text_start = interpreter->textBase(); 1778 Addr text_end = text_start + interpreter->textSize(); 1779 1780 Addr pc = tc->pcState().pc(); 1781 1782 if (pc >= text_start && pc < text_end) { 1783 std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd]; 1784 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep); 1785 ObjectFile *lib = createObjectFile(ffdp->getFileName()); 1786 1787 if (lib) { 1788 lib->loadAllSymbols(debugSymbolTable, 1789 lib->textBase(), start); 1790 } 1791 } 1792 } 1793 1794 // Note that we do not zero out the remainder of the mapping. This 1795 // is done by a real system, but it probably will not affect 1796 // execution (hopefully). 1797 } 1798 1799 return start; 1800} 1801 1802template <class OS> 1803SyscallReturn 1804pwrite64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1805{ 1806 int index = 0; 1807 int tgt_fd = p->getSyscallArg(tc, index); 1808 Addr bufPtr = p->getSyscallArg(tc, index); 1809 int nbytes = p->getSyscallArg(tc, index); 1810 int offset = p->getSyscallArg(tc, index); 1811 1812 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]); 1813 if (!ffdp) 1814 return -EBADF; 1815 int sim_fd = ffdp->getSimFD(); 1816 1817 BufferArg bufArg(bufPtr, nbytes); 1818 bufArg.copyIn(tc->getMemProxy()); 1819 1820 int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset); 1821 1822 return (bytes_written == -1) ? -errno : bytes_written; 1823} 1824 1825/// Target mmap() handler. 1826template <class OS> 1827SyscallReturn 1828mmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1829{ 1830 return mmapImpl<OS>(desc, num, p, tc, false); 1831} 1832 1833/// Target mmap2() handler. 1834template <class OS> 1835SyscallReturn 1836mmap2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1837{ 1838 return mmapImpl<OS>(desc, num, p, tc, true); 1839} 1840 1841/// Target getrlimit() handler. 1842template <class OS> 1843SyscallReturn 1844getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 1845 ThreadContext *tc) 1846{ 1847 int index = 0; 1848 unsigned resource = process->getSyscallArg(tc, index); 1849 TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1850 1851 switch (resource) { 1852 case OS::TGT_RLIMIT_STACK: 1853 // max stack size in bytes: make up a number (8MB for now) 1854 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 1855 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1856 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1857 break; 1858 1859 case OS::TGT_RLIMIT_DATA: 1860 // max data segment size in bytes: make up a number 1861 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 1862 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1863 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1864 break; 1865 1866 default: 1867 warn("getrlimit: unimplemented resource %d", resource); 1868 return -EINVAL; 1869 break; 1870 } 1871 1872 rlp.copyOut(tc->getMemProxy()); 1873 return 0; 1874} 1875 1876template <class OS> 1877SyscallReturn 1878prlimitFunc(SyscallDesc *desc, int callnum, Process *process, 1879 ThreadContext *tc) 1880{ 1881 int index = 0; 1882 if (process->getSyscallArg(tc, index) != 0) 1883 { 1884 warn("prlimit: ignoring rlimits for nonzero pid"); 1885 return -EPERM; 1886 } 1887 int resource = process->getSyscallArg(tc, index); 1888 Addr n = process->getSyscallArg(tc, index); 1889 if (n != 0) 1890 warn("prlimit: ignoring new rlimit"); 1891 Addr o = process->getSyscallArg(tc, index); 1892 if (o != 0) 1893 { 1894 TypedBufferArg<typename OS::rlimit> rlp(o); 1895 switch (resource) { 1896 case OS::TGT_RLIMIT_STACK: 1897 // max stack size in bytes: make up a number (8MB for now) 1898 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 1899 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1900 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1901 break; 1902 case OS::TGT_RLIMIT_DATA: 1903 // max data segment size in bytes: make up a number 1904 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024; 1905 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1906 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1907 break; 1908 default: 1909 warn("prlimit: unimplemented resource %d", resource); 1910 return -EINVAL; 1911 break; 1912 } 1913 rlp.copyOut(tc->getMemProxy()); 1914 } 1915 return 0; 1916} 1917 1918/// Target clock_gettime() function. 1919template <class OS> 1920SyscallReturn 1921clock_gettimeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1922{ 1923 int index = 1; 1924 //int clk_id = p->getSyscallArg(tc, index); 1925 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1926 1927 getElapsedTimeNano(tp->tv_sec, tp->tv_nsec); 1928 tp->tv_sec += seconds_since_epoch; 1929 tp->tv_sec = TheISA::htog(tp->tv_sec); 1930 tp->tv_nsec = TheISA::htog(tp->tv_nsec); 1931 1932 tp.copyOut(tc->getMemProxy()); 1933 1934 return 0; 1935} 1936 1937/// Target clock_getres() function. 1938template <class OS> 1939SyscallReturn 1940clock_getresFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1941{ 1942 int index = 1; 1943 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1944 1945 // Set resolution at ns, which is what clock_gettime() returns 1946 tp->tv_sec = 0; 1947 tp->tv_nsec = 1; 1948 1949 tp.copyOut(tc->getMemProxy()); 1950 1951 return 0; 1952} 1953 1954/// Target gettimeofday() handler. 1955template <class OS> 1956SyscallReturn 1957gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 1958 ThreadContext *tc) 1959{ 1960 int index = 0; 1961 TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1962 1963 getElapsedTimeMicro(tp->tv_sec, tp->tv_usec); 1964 tp->tv_sec += seconds_since_epoch; 1965 tp->tv_sec = TheISA::htog(tp->tv_sec); 1966 tp->tv_usec = TheISA::htog(tp->tv_usec); 1967 1968 tp.copyOut(tc->getMemProxy()); 1969 1970 return 0; 1971} 1972 1973 1974/// Target utimes() handler. 1975template <class OS> 1976SyscallReturn 1977utimesFunc(SyscallDesc *desc, int callnum, Process *process, 1978 ThreadContext *tc) 1979{ 1980 std::string path; 1981 1982 int index = 0; 1983 if (!tc->getMemProxy().tryReadString(path, 1984 process->getSyscallArg(tc, index))) { 1985 return -EFAULT; 1986 } 1987 1988 TypedBufferArg<typename OS::timeval [2]> 1989 tp(process->getSyscallArg(tc, index)); 1990 tp.copyIn(tc->getMemProxy()); 1991 1992 struct timeval hostTimeval[2]; 1993 for (int i = 0; i < 2; ++i) { 1994 hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 1995 hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 1996 } 1997 1998 // Adjust path for current working directory 1999 path = process->fullPath(path); 2000 2001 int result = utimes(path.c_str(), hostTimeval); 2002 2003 if (result < 0) 2004 return -errno; 2005 2006 return 0; 2007} 2008 2009template <class OS> 2010SyscallReturn 2011execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 2012{ 2013 desc->setFlags(0); 2014 2015 int index = 0; 2016 std::string path; 2017 SETranslatingPortProxy & mem_proxy = tc->getMemProxy(); 2018 if (!mem_proxy.tryReadString(path, p->getSyscallArg(tc, index))) 2019 return -EFAULT; 2020 2021 if (access(path.c_str(), F_OK) == -1) 2022 return -EACCES; 2023 2024 auto read_in = [](std::vector<std::string> & vect, 2025 SETranslatingPortProxy & mem_proxy, 2026 Addr mem_loc) 2027 { 2028 for (int inc = 0; ; inc++) { 2029 BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr)); 2030 b.copyIn(mem_proxy); 2031 2032 if (!*(Addr*)b.bufferPtr()) 2033 break; 2034 2035 vect.push_back(std::string()); 2036 mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr()); 2037 } 2038 }; 2039 2040 /** 2041 * Note that ProcessParams is generated by swig and there are no other 2042 * examples of how to create anything but this default constructor. The 2043 * fields are manually initialized instead of passing parameters to the 2044 * constructor. 2045 */ 2046 ProcessParams *pp = new ProcessParams(); 2047 pp->executable = path; 2048 Addr argv_mem_loc = p->getSyscallArg(tc, index); 2049 read_in(pp->cmd, mem_proxy, argv_mem_loc); 2050 Addr envp_mem_loc = p->getSyscallArg(tc, index); 2051 read_in(pp->env, mem_proxy, envp_mem_loc); 2052 pp->uid = p->uid(); 2053 pp->egid = p->egid(); 2054 pp->euid = p->euid(); 2055 pp->gid = p->gid(); 2056 pp->ppid = p->ppid(); 2057 pp->pid = p->pid(); 2058 pp->input.assign("cin"); 2059 pp->output.assign("cout"); 2060 pp->errout.assign("cerr"); 2061 pp->cwd.assign(p->getcwd()); 2062 pp->system = p->system; 2063 /** 2064 * Prevent process object creation with identical PIDs (which will trip 2065 * a fatal check in Process constructor). The execve call is supposed to 2066 * take over the currently executing process' identity but replace 2067 * whatever it is doing with a new process image. Instead of hijacking 2068 * the process object in the simulator, we create a new process object 2069 * and bind to the previous process' thread below (hijacking the thread). 2070 */ 2071 p->system->PIDs.erase(p->pid()); 2072 Process *new_p = pp->create(); 2073 delete pp; 2074 2075 /** 2076 * Work through the file descriptor array and close any files marked 2077 * close-on-exec. 2078 */ 2079 new_p->fds = p->fds; 2080 for (int i = 0; i < new_p->fds->getSize(); i++) { 2081 std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i]; 2082 if (fdep && fdep->getCOE()) 2083 new_p->fds->closeFDEntry(i); 2084 } 2085 2086 *new_p->sigchld = true; 2087 2088 delete p; 2089 tc->clearArchRegs(); 2090 tc->setProcessPtr(new_p); 2091 new_p->assignThreadContext(tc->contextId()); 2092 new_p->initState(); 2093 tc->activate(); 2094 TheISA::PCState pcState = tc->pcState(); 2095 tc->setNPC(pcState.instAddr()); 2096 2097 desc->setFlags(SyscallDesc::SuppressReturnValue); 2098 return 0; 2099} 2100 2101/// Target getrusage() function. 2102template <class OS> 2103SyscallReturn 2104getrusageFunc(SyscallDesc *desc, int callnum, Process *process, 2105 ThreadContext *tc) 2106{ 2107 int index = 0; 2108 int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 2109 TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 2110 2111 rup->ru_utime.tv_sec = 0; 2112 rup->ru_utime.tv_usec = 0; 2113 rup->ru_stime.tv_sec = 0; 2114 rup->ru_stime.tv_usec = 0; 2115 rup->ru_maxrss = 0; 2116 rup->ru_ixrss = 0; 2117 rup->ru_idrss = 0; 2118 rup->ru_isrss = 0; 2119 rup->ru_minflt = 0; 2120 rup->ru_majflt = 0; 2121 rup->ru_nswap = 0; 2122 rup->ru_inblock = 0; 2123 rup->ru_oublock = 0; 2124 rup->ru_msgsnd = 0; 2125 rup->ru_msgrcv = 0; 2126 rup->ru_nsignals = 0; 2127 rup->ru_nvcsw = 0; 2128 rup->ru_nivcsw = 0; 2129 2130 switch (who) { 2131 case OS::TGT_RUSAGE_SELF: 2132 getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 2133 rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 2134 rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 2135 break; 2136 2137 case OS::TGT_RUSAGE_CHILDREN: 2138 // do nothing. We have no child processes, so they take no time. 2139 break; 2140 2141 default: 2142 // don't really handle THREAD or CHILDREN, but just warn and 2143 // plow ahead 2144 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 2145 who); 2146 } 2147 2148 rup.copyOut(tc->getMemProxy()); 2149 2150 return 0; 2151} 2152 2153/// Target times() function. 2154template <class OS> 2155SyscallReturn 2156timesFunc(SyscallDesc *desc, int callnum, Process *process, 2157 ThreadContext *tc) 2158{ 2159 int index = 0; 2160 TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 2161 2162 // Fill in the time structure (in clocks) 2163 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 2164 bufp->tms_utime = clocks; 2165 bufp->tms_stime = 0; 2166 bufp->tms_cutime = 0; 2167 bufp->tms_cstime = 0; 2168 2169 // Convert to host endianness 2170 bufp->tms_utime = TheISA::htog(bufp->tms_utime); 2171 2172 // Write back 2173 bufp.copyOut(tc->getMemProxy()); 2174 2175 // Return clock ticks since system boot 2176 return clocks; 2177} 2178 2179/// Target time() function. 2180template <class OS> 2181SyscallReturn 2182timeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) 2183{ 2184 typename OS::time_t sec, usec; 2185 getElapsedTimeMicro(sec, usec); 2186 sec += seconds_since_epoch; 2187 2188 int index = 0; 2189 Addr taddr = (Addr)process->getSyscallArg(tc, index); 2190 if (taddr != 0) { 2191 typename OS::time_t t = sec; 2192 t = TheISA::htog(t); 2193 SETranslatingPortProxy &p = tc->getMemProxy(); 2194 p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 2195 } 2196 return sec; 2197} 2198 2199template <class OS> 2200SyscallReturn 2201tgkillFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) 2202{ 2203 int index = 0; 2204 int tgid = process->getSyscallArg(tc, index); 2205 int tid = process->getSyscallArg(tc, index); 2206 int sig = process->getSyscallArg(tc, index); 2207 2208 /** 2209 * This system call is intended to allow killing a specific thread 2210 * within an arbitrary thread group if sanctioned with permission checks. 2211 * It's usually true that threads share the termination signal as pointed 2212 * out by the pthread_kill man page and this seems to be the intended 2213 * usage. Due to this being an emulated environment, assume the following: 2214 * Threads are allowed to call tgkill because the EUID for all threads 2215 * should be the same. There is no signal handling mechanism for kernel 2216 * registration of signal handlers since signals are poorly supported in 2217 * emulation mode. Since signal handlers cannot be registered, all 2218 * threads within in a thread group must share the termination signal. 2219 * We never exhaust PIDs so there's no chance of finding the wrong one 2220 * due to PID rollover. 2221 */ 2222 2223 System *sys = tc->getSystemPtr(); 2224 Process *tgt_proc = nullptr; 2225 for (int i = 0; i < sys->numContexts(); i++) { 2226 Process *temp = sys->threadContexts[i]->getProcessPtr(); 2227 if (temp->pid() == tid) { 2228 tgt_proc = temp; 2229 break; 2230 } 2231 } 2232 2233 if (sig != 0 || sig != OS::TGT_SIGABRT) 2234 return -EINVAL; 2235 2236 if (tgt_proc == nullptr) 2237 return -ESRCH; 2238 2239 if (tgid != -1 && tgt_proc->tgid() != tgid) 2240 return -ESRCH; 2241 2242 if (sig == OS::TGT_SIGABRT) 2243 exitGroupFunc(desc, 252, process, tc); 2244 2245 return 0; 2246} 2247 2248template <class OS> 2249SyscallReturn 2250socketFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2251{ 2252 int index = 0; 2253 int domain = p->getSyscallArg(tc, index); 2254 int type = p->getSyscallArg(tc, index); 2255 int prot = p->getSyscallArg(tc, index); 2256 2257 int sim_fd = socket(domain, type, prot); 2258 if (sim_fd == -1) 2259 return -errno; 2260 2261 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot); 2262 int tgt_fd = p->fds->allocFD(sfdp); 2263 2264 return tgt_fd; 2265} 2266 2267template <class OS> 2268SyscallReturn 2269socketpairFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2270{ 2271 int index = 0; 2272 int domain = p->getSyscallArg(tc, index); 2273 int type = p->getSyscallArg(tc, index); 2274 int prot = p->getSyscallArg(tc, index); 2275 Addr svPtr = p->getSyscallArg(tc, index); 2276 2277 BufferArg svBuf((Addr)svPtr, 2 * sizeof(int)); 2278 int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr()); 2279 if (status == -1) 2280 return -errno; 2281 2282 int *fds = (int *)svBuf.bufferPtr(); 2283 2284 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot); 2285 fds[0] = p->fds->allocFD(sfdp1); 2286 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot); 2287 fds[1] = p->fds->allocFD(sfdp2); 2288 svBuf.copyOut(tc->getMemProxy()); 2289 2290 return status; 2291} 2292 2293template <class OS> 2294SyscallReturn 2295selectFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 2296{ 2297 int retval; 2298 2299 int index = 0; 2300 int nfds_t = p->getSyscallArg(tc, index); 2301 Addr fds_read_ptr = p->getSyscallArg(tc, index); 2302 Addr fds_writ_ptr = p->getSyscallArg(tc, index); 2303 Addr fds_excp_ptr = p->getSyscallArg(tc, index); 2304 Addr time_val_ptr = p->getSyscallArg(tc, index); 2305 2306 TypedBufferArg<typename OS::fd_set> rd_t(fds_read_ptr); 2307 TypedBufferArg<typename OS::fd_set> wr_t(fds_writ_ptr); 2308 TypedBufferArg<typename OS::fd_set> ex_t(fds_excp_ptr); 2309 TypedBufferArg<typename OS::timeval> tp(time_val_ptr); 2310 2311 /** 2312 * Host fields. Notice that these use the definitions from the system 2313 * headers instead of the gem5 headers and libraries. If the host and 2314 * target have different header file definitions, this will not work. 2315 */ 2316 fd_set rd_h; 2317 FD_ZERO(&rd_h); 2318 fd_set wr_h; 2319 FD_ZERO(&wr_h); 2320 fd_set ex_h; 2321 FD_ZERO(&ex_h); 2322 2323 /** 2324 * Copy in the fd_set from the target. 2325 */ 2326 if (fds_read_ptr) 2327 rd_t.copyIn(tc->getMemProxy()); 2328 if (fds_writ_ptr) 2329 wr_t.copyIn(tc->getMemProxy()); 2330 if (fds_excp_ptr) 2331 ex_t.copyIn(tc->getMemProxy()); 2332 2333 /** 2334 * We need to translate the target file descriptor set into a host file 2335 * descriptor set. This involves both our internal process fd array 2336 * and the fd_set defined in Linux header files. The nfds field also 2337 * needs to be updated as it will be only target specific after 2338 * retrieving it from the target; the nfds value is expected to be the 2339 * highest file descriptor that needs to be checked, so we need to extend 2340 * it out for nfds_h when we do the update. 2341 */ 2342 int nfds_h = 0; 2343 std::map<int, int> trans_map; 2344 auto try_add_host_set = [&](fd_set *tgt_set_entry, 2345 fd_set *hst_set_entry, 2346 int iter) -> bool 2347 { 2348 /** 2349 * By this point, we know that we are looking at a valid file 2350 * descriptor set on the target. We need to check if the target file 2351 * descriptor value passed in as iter is part of the set. 2352 */ 2353 if (FD_ISSET(iter, tgt_set_entry)) { 2354 /** 2355 * We know that the target file descriptor belongs to the set, 2356 * but we do not yet know if the file descriptor is valid or 2357 * that we have a host mapping. Check that now. 2358 */ 2359 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]); 2360 if (!hbfdp) 2361 return true; 2362 auto sim_fd = hbfdp->getSimFD(); 2363 2364 /** 2365 * Add the sim_fd to tgt_fd translation into trans_map for use 2366 * later when we need to zero the target fd_set structures and 2367 * then update them with hits returned from the host select call. 2368 */ 2369 trans_map[sim_fd] = iter; 2370 2371 /** 2372 * We know that the host file descriptor exists so now we check 2373 * if we need to update the max count for nfds_h before passing 2374 * the duplicated structure into the host. 2375 */ 2376 nfds_h = std::max(nfds_h - 1, sim_fd + 1); 2377 2378 /** 2379 * Add the host file descriptor to the set that we are going to 2380 * pass into the host. 2381 */ 2382 FD_SET(sim_fd, hst_set_entry); 2383 } 2384 return false; 2385 }; 2386 2387 for (int i = 0; i < nfds_t; i++) { 2388 if (fds_read_ptr) { 2389 bool ebadf = try_add_host_set((fd_set*)&*rd_t, &rd_h, i); 2390 if (ebadf) return -EBADF; 2391 } 2392 if (fds_writ_ptr) { 2393 bool ebadf = try_add_host_set((fd_set*)&*wr_t, &wr_h, i); 2394 if (ebadf) return -EBADF; 2395 } 2396 if (fds_excp_ptr) { 2397 bool ebadf = try_add_host_set((fd_set*)&*ex_t, &ex_h, i); 2398 if (ebadf) return -EBADF; 2399 } 2400 } 2401 2402 if (time_val_ptr) { 2403 /** 2404 * It might be possible to decrement the timeval based on some 2405 * derivation of wall clock determined from elapsed simulator ticks 2406 * but that seems like overkill. Rather, we just set the timeval with 2407 * zero timeout. (There is no reason to block during the simulation 2408 * as it only decreases simulator performance.) 2409 */ 2410 tp->tv_sec = 0; 2411 tp->tv_usec = 0; 2412 2413 retval = select(nfds_h, 2414 fds_read_ptr ? &rd_h : nullptr, 2415 fds_writ_ptr ? &wr_h : nullptr, 2416 fds_excp_ptr ? &ex_h : nullptr, 2417 (timeval*)&*tp); 2418 } else { 2419 /** 2420 * If the timeval pointer is null, setup a new timeval structure to 2421 * pass into the host select call. Unfortunately, we will need to 2422 * manually check the return value and throw a retry fault if the 2423 * return value is zero. Allowing the system call to block will 2424 * likely deadlock the event queue. 2425 */ 2426 struct timeval tv = { 0, 0 }; 2427 2428 retval = select(nfds_h, 2429 fds_read_ptr ? &rd_h : nullptr, 2430 fds_writ_ptr ? &wr_h : nullptr, 2431 fds_excp_ptr ? &ex_h : nullptr, 2432 &tv); 2433 2434 if (retval == 0) { 2435 /** 2436 * If blocking indefinitely, check the signal list to see if a 2437 * signal would break the poll out of the retry cycle and try to 2438 * return the signal interrupt instead. 2439 */ 2440 for (auto sig : tc->getSystemPtr()->signalList) 2441 if (sig.receiver == p) 2442 return -EINTR; 2443 return SyscallReturn::retry(); 2444 } 2445 } 2446 2447 if (retval == -1) 2448 return -errno; 2449 2450 FD_ZERO((fd_set*)&*rd_t); 2451 FD_ZERO((fd_set*)&*wr_t); 2452 FD_ZERO((fd_set*)&*ex_t); 2453 2454 /** 2455 * We need to translate the host file descriptor set into a target file 2456 * descriptor set. This involves both our internal process fd array 2457 * and the fd_set defined in header files. 2458 */ 2459 for (int i = 0; i < nfds_h; i++) { 2460 if (fds_read_ptr) { 2461 if (FD_ISSET(i, &rd_h)) 2462 FD_SET(trans_map[i], (fd_set*)&*rd_t); 2463 } 2464 2465 if (fds_writ_ptr) { 2466 if (FD_ISSET(i, &wr_h)) 2467 FD_SET(trans_map[i], (fd_set*)&*wr_t); 2468 } 2469 2470 if (fds_excp_ptr) { 2471 if (FD_ISSET(i, &ex_h)) 2472 FD_SET(trans_map[i], (fd_set*)&*ex_t); 2473 } 2474 } 2475 2476 if (fds_read_ptr) 2477 rd_t.copyOut(tc->getMemProxy()); 2478 if (fds_writ_ptr) 2479 wr_t.copyOut(tc->getMemProxy()); 2480 if (fds_excp_ptr) 2481 ex_t.copyOut(tc->getMemProxy()); 2482 if (time_val_ptr) 2483 tp.copyOut(tc->getMemProxy()); 2484 2485 return retval; 2486} 2487 2488template <class OS> 2489SyscallReturn 2490readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2491{ 2492 int index = 0; 2493 int tgt_fd = p->getSyscallArg(tc, index); 2494 Addr buf_ptr = p->getSyscallArg(tc, index); 2495 int nbytes = p->getSyscallArg(tc, index); 2496 2497 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]); 2498 if (!hbfdp) 2499 return -EBADF; 2500 int sim_fd = hbfdp->getSimFD(); 2501 2502 struct pollfd pfd; 2503 pfd.fd = sim_fd; 2504 pfd.events = POLLIN | POLLPRI; 2505 if ((poll(&pfd, 1, 0) == 0) 2506 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK)) 2507 return SyscallReturn::retry(); 2508 2509 BufferArg buf_arg(buf_ptr, nbytes); 2510 int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes); 2511 2512 if (bytes_read > 0) 2513 buf_arg.copyOut(tc->getMemProxy()); 2514 2515 return (bytes_read == -1) ? -errno : bytes_read; 2516} 2517 2518template <class OS> 2519SyscallReturn 2520writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2521{ 2522 int index = 0; 2523 int tgt_fd = p->getSyscallArg(tc, index); 2524 Addr buf_ptr = p->getSyscallArg(tc, index); 2525 int nbytes = p->getSyscallArg(tc, index); 2526 2527 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]); 2528 if (!hbfdp) 2529 return -EBADF; 2530 int sim_fd = hbfdp->getSimFD(); 2531 2532 BufferArg buf_arg(buf_ptr, nbytes); 2533 buf_arg.copyIn(tc->getMemProxy()); 2534 2535 struct pollfd pfd; 2536 pfd.fd = sim_fd; 2537 pfd.events = POLLOUT; 2538 2539 /** 2540 * We don't want to poll on /dev/random. The kernel will not enable the 2541 * file descriptor for writing unless the entropy in the system falls 2542 * below write_wakeup_threshold. This is not guaranteed to happen 2543 * depending on host settings. 2544 */ 2545 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp); 2546 if (ffdp && (ffdp->getFileName() != "/dev/random")) { 2547 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK)) 2548 return SyscallReturn::retry(); 2549 } 2550 2551 int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes); 2552 2553 if (bytes_written != -1) 2554 fsync(sim_fd); 2555 2556 return (bytes_written == -1) ? -errno : bytes_written; 2557} 2558 2559template <class OS> 2560SyscallReturn 2561wait4Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2562{ 2563 int index = 0; 2564 pid_t pid = p->getSyscallArg(tc, index); 2565 Addr statPtr = p->getSyscallArg(tc, index); 2566 int options = p->getSyscallArg(tc, index); 2567 Addr rusagePtr = p->getSyscallArg(tc, index); 2568 2569 if (rusagePtr) 2570 DPRINTFR(SyscallVerbose, 2571 "%d: %s: syscall wait4: rusage pointer provided however " 2572 "functionality not supported. Ignoring rusage pointer.\n", 2573 curTick(), tc->getCpuPtr()->name()); 2574 2575 /** 2576 * Currently, wait4 is only implemented so that it will wait for children 2577 * exit conditions which are denoted by a SIGCHLD signals posted into the 2578 * system signal list. We return no additional information via any of the 2579 * parameters supplied to wait4. If nothing is found in the system signal 2580 * list, we will wait indefinitely for SIGCHLD to post by retrying the 2581 * call. 2582 */ 2583 System *sysh = tc->getSystemPtr(); 2584 std::list<BasicSignal>::iterator iter; 2585 for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) { 2586 if (iter->receiver == p) { 2587 if (pid < -1) { 2588 if ((iter->sender->pgid() == -pid) 2589 && (iter->signalValue == OS::TGT_SIGCHLD)) 2590 goto success; 2591 } else if (pid == -1) { 2592 if (iter->signalValue == OS::TGT_SIGCHLD) 2593 goto success; 2594 } else if (pid == 0) { 2595 if ((iter->sender->pgid() == p->pgid()) 2596 && (iter->signalValue == OS::TGT_SIGCHLD)) 2597 goto success; 2598 } else { 2599 if ((iter->sender->pid() == pid) 2600 && (iter->signalValue == OS::TGT_SIGCHLD)) 2601 goto success; 2602 } 2603 } 2604 } 2605 2606 return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry(); 2607 2608success: 2609 // Set status to EXITED for WIFEXITED evaluations. 2610 const int EXITED = 0; 2611 BufferArg statusBuf(statPtr, sizeof(int)); 2612 *(int *)statusBuf.bufferPtr() = EXITED; 2613 statusBuf.copyOut(tc->getMemProxy()); 2614 2615 // Return the child PID. 2616 pid_t retval = iter->sender->pid(); 2617 sysh->signalList.erase(iter); 2618 return retval; 2619} 2620 2621template <class OS> 2622SyscallReturn 2623acceptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2624{ 2625 struct sockaddr sa; 2626 socklen_t addrLen; 2627 int host_fd; 2628 int index = 0; 2629 int tgt_fd = p->getSyscallArg(tc, index); 2630 Addr addrPtr = p->getSyscallArg(tc, index); 2631 Addr lenPtr = p->getSyscallArg(tc, index); 2632 2633 BufferArg *lenBufPtr = nullptr; 2634 BufferArg *addrBufPtr = nullptr; 2635 2636 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]); 2637 if (!sfdp) 2638 return -EBADF; 2639 int sim_fd = sfdp->getSimFD(); 2640 2641 /** 2642 * We poll the socket file descriptor first to guarantee that we do not 2643 * block on our accept call. The socket can be opened without the 2644 * non-blocking flag (it blocks). This will cause deadlocks between 2645 * communicating processes. 2646 */ 2647 struct pollfd pfd; 2648 pfd.fd = sim_fd; 2649 pfd.events = POLLIN | POLLPRI; 2650 if ((poll(&pfd, 1, 0) == 0) 2651 && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK)) 2652 return SyscallReturn::retry(); 2653 2654 if (lenPtr) { 2655 lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t)); 2656 lenBufPtr->copyIn(tc->getMemProxy()); 2657 memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(), 2658 sizeof(socklen_t)); 2659 } 2660 2661 if (addrPtr) { 2662 addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr)); 2663 addrBufPtr->copyIn(tc->getMemProxy()); 2664 memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(), 2665 sizeof(struct sockaddr)); 2666 } 2667 2668 host_fd = accept(sim_fd, &sa, &addrLen); 2669 2670 if (host_fd == -1) 2671 return -errno; 2672 2673 if (addrPtr) { 2674 memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa)); 2675 addrBufPtr->copyOut(tc->getMemProxy()); 2676 delete(addrBufPtr); 2677 } 2678 2679 if (lenPtr) { 2680 *(socklen_t *)lenBufPtr->bufferPtr() = addrLen; 2681 lenBufPtr->copyOut(tc->getMemProxy()); 2682 delete(lenBufPtr); 2683 } 2684 2685 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain, 2686 sfdp->_type, sfdp->_protocol); 2687 return p->fds->allocFD(afdp); 2688} 2689 2690#endif // __SIM_SYSCALL_EMUL_HH__ 2691