syscall_emul.cc revision 11851
12SN/A/* 28922Swilliam.wang@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 38707Sandreas.hansson@arm.com * All rights reserved. 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 157897Shestness@cs.utexas.edu * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Steve Reinhardt 292SN/A * Ali Saidi 302SN/A */ 312SN/A 322SN/A#include "sim/syscall_emul.hh" 332SN/A 342SN/A#include <fcntl.h> 352SN/A#include <unistd.h> 362SN/A 372SN/A#include <iostream> 382SN/A#include <string> 392SN/A 402665Ssaidi@eecs.umich.edu#include "arch/utility.hh" 412665Ssaidi@eecs.umich.edu#include "base/chunk_generator.hh" 422665Ssaidi@eecs.umich.edu#include "base/trace.hh" 437897Shestness@cs.utexas.edu#include "config/the_isa.hh" 442SN/A#include "cpu/thread_context.hh" 452SN/A#include "mem/page_table.hh" 461388SN/A#include "sim/process.hh" 478229Snate@binkert.org#include "sim/sim_exit.hh" 482SN/A#include "sim/syscall_debug_macros.hh" 492SN/A#include "sim/syscall_desc.hh" 507781SAli.Saidi@ARM.com#include "sim/system.hh" 518229Snate@binkert.org 521191SN/Ausing namespace std; 531191SN/Ausing namespace TheISA; 541388SN/A 555529Snate@binkert.orgSyscallReturn 561717SN/AunimplementedFunc(SyscallDesc *desc, int callnum, Process *process, 578887Sgeoffrey.blake@arm.com ThreadContext *tc) 582651Ssaidi@eecs.umich.edu{ 598229Snate@binkert.org fatal("syscall %s (#%d) unimplemented.", desc->name(), callnum); 602680Sktlim@umich.edu 618232Snate@binkert.org return 1; 625529Snate@binkert.org} 638779Sgblack@eecs.umich.edu 642190SN/A 6556SN/ASyscallReturn 668229Snate@binkert.orgignoreFunc(SyscallDesc *desc, int callnum, Process *process, 672190SN/A ThreadContext *tc) 682SN/A{ 692359SN/A if (desc->needWarning()) { 702359SN/A warn("ignoring syscall %s(...)%s", desc->name(), desc->warnOnce() ? 712359SN/A "\n (further warnings will be suppressed)" : ""); 722SN/A } 732SN/A 742SN/A return 0; 752SN/A} 762SN/A 772SN/A 782SN/ASyscallReturn 792SN/AexitFunc(SyscallDesc *desc, int callnum, Process *process, 802SN/A ThreadContext *tc) 815606Snate@binkert.org{ 826144Sksewell@umich.edu if (process->system->numRunningContexts() == 1) { 836144Sksewell@umich.edu // Last running context... exit simulator 843126Sktlim@umich.edu int index = 0; 856144Sksewell@umich.edu exitSimLoop("target called exit()", 867823Ssteve.reinhardt@amd.com process->getSyscallArg(tc, index) & 0xff); 873126Sktlim@umich.edu } else { 883126Sktlim@umich.edu // other running threads... just halt this one 892356SN/A tc->halt(); 902356SN/A } 912356SN/A 928834Satgutier@umich.edu return 1; 932356SN/A} 949179Sandreas.hansson@arm.com 952367SN/A 966144Sksewell@umich.eduSyscallReturn 976144Sksewell@umich.eduexitGroupFunc(SyscallDesc *desc, int callnum, Process *process, 986144Sksewell@umich.edu ThreadContext *tc) 992356SN/A{ 1002367SN/A // halt all threads belonging to this process 1016144Sksewell@umich.edu for (auto i: process->contextIds) { 1027823Ssteve.reinhardt@amd.com process->system->getThreadContext(i)->halt(); 1036144Sksewell@umich.edu } 1042367SN/A 1052356SN/A if (!process->system->numRunningContexts()) { 1066144Sksewell@umich.edu // all threads belonged to this process... exit simulator 1076144Sksewell@umich.edu int index = 0; 1087823Ssteve.reinhardt@amd.com exitSimLoop("target called exit()", 1092356SN/A process->getSyscallArg(tc, index) & 0xff); 1102356SN/A } 1112356SN/A 1125336Shines@cs.fsu.edu return 1; 1132356SN/A} 1144873Sstever@eecs.umich.edu 1152356SN/A 1162356SN/ASyscallReturn 1178876Sandreas.hansson@arm.comgetpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1189157Sandreas.hansson@arm.com{ 1198832SAli.Saidi@ARM.com return (int)PageBytes; 1208832SAli.Saidi@ARM.com} 1219332Sdam.sunwoo@arm.com 1229433SAndreas.Sandberg@ARM.com 1239220Shestness@cs.wisc.eduSyscallReturn 1249157Sandreas.hansson@arm.combrkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1252SN/A{ 1265712Shsul@eecs.umich.edu // change brk addr to first arg 1275712Shsul@eecs.umich.edu int index = 0; 1285712Shsul@eecs.umich.edu Addr new_brk = p->getSyscallArg(tc, index); 1295712Shsul@eecs.umich.edu 1305712Shsul@eecs.umich.edu // in Linux at least, brk(0) returns the current break value 1312SN/A // (note that the syscall and the glibc function have different behavior) 1322SN/A if (new_brk == 0) 1332SN/A return p->brk_point; 1345712Shsul@eecs.umich.edu 1355712Shsul@eecs.umich.edu if (new_brk > p->brk_point) { 1366221Snate@binkert.org // might need to allocate some new pages 1376221Snate@binkert.org for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, 1382SN/A PageBytes); !gen.done(); gen.next()) { 1392SN/A if (!p->pTable->translate(gen.addr())) 1406221Snate@binkert.org p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes); 1416221Snate@binkert.org 1426221Snate@binkert.org // if the address is already there, zero it out 1436221Snate@binkert.org else { 1442SN/A uint8_t zero = 0; 1452SN/A SETranslatingPortProxy &tp = tc->getMemProxy(); 1462SN/A 1472SN/A // split non-page aligned accesses 1485606Snate@binkert.org Addr next_page = roundUp(gen.addr(), PageBytes); 1495606Snate@binkert.org uint32_t size_needed = next_page - gen.addr(); 1506221Snate@binkert.org tp.memsetBlob(gen.addr(), zero, size_needed); 1515606Snate@binkert.org if (gen.addr() + PageBytes > next_page && 1526221Snate@binkert.org next_page < new_brk && 1535606Snate@binkert.org p->pTable->translate(next_page)) 1545606Snate@binkert.org { 1552SN/A size_needed = PageBytes - size_needed; 1561400SN/A tp.memsetBlob(next_page, zero, size_needed); 1575606Snate@binkert.org } 1585606Snate@binkert.org } 1592SN/A } 1602SN/A } 1612SN/A 1622SN/A p->brk_point = new_brk; 1636221Snate@binkert.org DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n", 1646221Snate@binkert.org p->brk_point); 1655606Snate@binkert.org return p->brk_point; 1666670Shsul@eecs.umich.edu} 1675606Snate@binkert.org 1682SN/A 1692SN/ASyscallReturn 170124SN/AcloseFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 1716221Snate@binkert.org{ 1726221Snate@binkert.org int index = 0; 1736221Snate@binkert.org int tgt_fd = p->getSyscallArg(tc, index); 174124SN/A 175124SN/A int sim_fd = p->getSimFD(tgt_fd); 176124SN/A if (sim_fd < 0) 177124SN/A return -EBADF; 1785606Snate@binkert.org 1795606Snate@binkert.org int status = 0; 1806221Snate@binkert.org if (sim_fd > 2) 1815606Snate@binkert.org status = close(sim_fd); 1826221Snate@binkert.org if (status >= 0) 1835606Snate@binkert.org p->resetFDEntry(tgt_fd); 1845606Snate@binkert.org return status; 185124SN/A} 1861400SN/A 1875606Snate@binkert.org 188124SN/ASyscallReturn 189124SN/AreadFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 190124SN/A{ 191124SN/A int index = 0; 1926221Snate@binkert.org int tgt_fd = p->getSyscallArg(tc, index); 1936221Snate@binkert.org Addr bufPtr = p->getSyscallArg(tc, index); 1945606Snate@binkert.org int nbytes = p->getSyscallArg(tc, index); 1956221Snate@binkert.org BufferArg bufArg(bufPtr, nbytes); 1965606Snate@binkert.org 197124SN/A int sim_fd = p->getSimFD(tgt_fd); 198124SN/A if (sim_fd < 0) 1991191SN/A return -EBADF; 2005529Snate@binkert.org 2018634Schris.emmons@arm.com int bytes_read = read(sim_fd, bufArg.bufferPtr(), nbytes); 2028634Schris.emmons@arm.com 2038634Schris.emmons@arm.com if (bytes_read > 0) 2048634Schris.emmons@arm.com bufArg.copyOut(tc->getMemProxy()); 2058634Schris.emmons@arm.com 2061191SN/A return bytes_read; 2075529Snate@binkert.org} 2081191SN/A 2095529Snate@binkert.orgSyscallReturn 2101191SN/AwriteFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2111191SN/A{ 2125606Snate@binkert.org int index = 0; 2135606Snate@binkert.org int tgt_fd = p->getSyscallArg(tc, index); 2145606Snate@binkert.org Addr bufPtr = p->getSyscallArg(tc, index); 2151191SN/A int nbytes = p->getSyscallArg(tc, index); 2161191SN/A BufferArg bufArg(bufPtr, nbytes); 2178876Sandreas.hansson@arm.com 2188876Sandreas.hansson@arm.com int sim_fd = p->getSimFD(tgt_fd); 2198876Sandreas.hansson@arm.com if (sim_fd < 0) 2209433SAndreas.Sandberg@ARM.com return -EBADF; 2218876Sandreas.hansson@arm.com 2228876Sandreas.hansson@arm.com bufArg.copyIn(tc->getMemProxy()); 2238876Sandreas.hansson@arm.com 2248876Sandreas.hansson@arm.com int bytes_written = write(sim_fd, bufArg.bufferPtr(), nbytes); 2258876Sandreas.hansson@arm.com 2268876Sandreas.hansson@arm.com fsync(sim_fd); 2278876Sandreas.hansson@arm.com 2285810Sgblack@eecs.umich.edu return bytes_written; 2298779Sgblack@eecs.umich.edu} 2308779Sgblack@eecs.umich.edu 2318779Sgblack@eecs.umich.edu 2328779Sgblack@eecs.umich.eduSyscallReturn 2335529Snate@binkert.orglseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2349384SAndreas.Sandberg@arm.com{ 2359384SAndreas.Sandberg@arm.com int index = 0; 2369384SAndreas.Sandberg@arm.com int tgt_fd = p->getSyscallArg(tc, index); 2379384SAndreas.Sandberg@arm.com uint64_t offs = p->getSyscallArg(tc, index); 2389384SAndreas.Sandberg@arm.com int whence = p->getSyscallArg(tc, index); 2391917SN/A 2401191SN/A int sim_fd = p->getSimFD(tgt_fd); 2411191SN/A if (sim_fd < 0) 2421191SN/A return -EBADF; 2431191SN/A 2441191SN/A off_t result = lseek(sim_fd, offs, whence); 2451191SN/A 2461191SN/A return (result == (off_t)-1) ? -errno : result; 2471191SN/A} 2481191SN/A 2499086Sandreas.hansson@arm.com 2509086Sandreas.hansson@arm.comSyscallReturn 2519086Sandreas.hansson@arm.com_llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2521191SN/A{ 2531191SN/A int index = 0; 2541129SN/A int tgt_fd = p->getSyscallArg(tc, index); 2551129SN/A uint64_t offset_high = p->getSyscallArg(tc, index); 2561129SN/A uint32_t offset_low = p->getSyscallArg(tc, index); 2579433SAndreas.Sandberg@ARM.com Addr result_ptr = p->getSyscallArg(tc, index); 2582680Sktlim@umich.edu int whence = p->getSyscallArg(tc, index); 2591129SN/A 260180SN/A int sim_fd = p->getSimFD(tgt_fd); 2612SN/A if (sim_fd < 0) 2621917SN/A return -EBADF; 2631917SN/A 2648779Sgblack@eecs.umich.edu uint64_t offset = (offset_high << 32) | offset_low; 2659433SAndreas.Sandberg@ARM.com 2668779Sgblack@eecs.umich.edu uint64_t result = lseek(sim_fd, offset, whence); 2678779Sgblack@eecs.umich.edu result = TheISA::htog(result); 2682356SN/A 2695529Snate@binkert.org if (result == (off_t)-1) 2709179Sandreas.hansson@arm.com return -errno; 2712356SN/A // Assuming that the size of loff_t is 64 bits on the target platform 2721917SN/A BufferArg result_buf(result_ptr, sizeof(result)); 2731917SN/A memcpy(result_buf.bufferPtr(), &result, sizeof(result)); 2741917SN/A result_buf.copyOut(tc->getMemProxy()); 2751917SN/A return 0; 2762SN/A} 2772SN/A 278729SN/A 279707SN/ASyscallReturn 280707SN/AmunmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 281707SN/A{ 282707SN/A // With mmap more fully implemented, it might be worthwhile to bite 283707SN/A // the bullet and implement munmap. Should allow us to reuse simulated 284707SN/A // memory. 2857914SBrad.Beckmann@amd.com return 0; 2867914SBrad.Beckmann@amd.com} 2877914SBrad.Beckmann@amd.com 2887914SBrad.Beckmann@amd.com 2897914SBrad.Beckmann@amd.comconst char *hostname = "m5.eecs.umich.edu"; 2907914SBrad.Beckmann@amd.com 2917914SBrad.Beckmann@amd.comSyscallReturn 2927914SBrad.Beckmann@amd.comgethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 2937914SBrad.Beckmann@amd.com{ 2947914SBrad.Beckmann@amd.com int index = 0; 2952680Sktlim@umich.edu Addr bufPtr = p->getSyscallArg(tc, index); 2962SN/A int name_len = p->getSyscallArg(tc, index); 2972SN/A BufferArg name(bufPtr, name_len); 2982SN/A 2992SN/A strncpy((char *)name.bufferPtr(), hostname, name_len); 3002680Sktlim@umich.edu 3012SN/A name.copyOut(tc->getMemProxy()); 3022SN/A 3032680Sktlim@umich.edu return 0; 3042SN/A} 3052SN/A 3069294Sandreas.hansson@arm.comSyscallReturn 3079294Sandreas.hansson@arm.comgetcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 3088850Sandreas.hansson@arm.com{ 3098850Sandreas.hansson@arm.com int result = 0; 3108850Sandreas.hansson@arm.com int index = 0; 3118850Sandreas.hansson@arm.com Addr bufPtr = p->getSyscallArg(tc, index); 3128850Sandreas.hansson@arm.com unsigned long size = p->getSyscallArg(tc, index); 3138850Sandreas.hansson@arm.com BufferArg buf(bufPtr, size); 3148922Swilliam.wang@arm.com 3158850Sandreas.hansson@arm.com // Is current working directory defined? 3168922Swilliam.wang@arm.com string cwd = p->getcwd(); 3178850Sandreas.hansson@arm.com if (!cwd.empty()) { 3188922Swilliam.wang@arm.com if (cwd.length() >= size) { 3198850Sandreas.hansson@arm.com // Buffer too small 3208850Sandreas.hansson@arm.com return -ERANGE; 321180SN/A } 3222680Sktlim@umich.edu strncpy((char *)buf.bufferPtr(), cwd.c_str(), size); 323180SN/A result = cwd.length(); 3246221Snate@binkert.org } else { 3256221Snate@binkert.org if (getcwd((char *)buf.bufferPtr(), size) != NULL) { 3266221Snate@binkert.org result = strlen((char *)buf.bufferPtr()); 3272378SN/A } else { 3285718Shsul@eecs.umich.edu result = -1; 3295718Shsul@eecs.umich.edu } 3305718Shsul@eecs.umich.edu } 3315718Shsul@eecs.umich.edu 3325718Shsul@eecs.umich.edu buf.copyOut(tc->getMemProxy()); 3335718Shsul@eecs.umich.edu 3345718Shsul@eecs.umich.edu return (result == -1) ? -errno : result; 3356221Snate@binkert.org} 3365718Shsul@eecs.umich.edu 3375718Shsul@eecs.umich.edu/// Target open() handler. 3385718Shsul@eecs.umich.eduSyscallReturn 3398779Sgblack@eecs.umich.edureadlinkFunc(SyscallDesc *desc, int callnum, Process *process, 3408779Sgblack@eecs.umich.edu ThreadContext *tc) 3418779Sgblack@eecs.umich.edu{ 342180SN/A return readlinkFunc(desc, callnum, process, tc, 0); 343180SN/A} 344180SN/A 345180SN/ASyscallReturn 3464000Ssaidi@eecs.umich.edureadlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, 3474000Ssaidi@eecs.umich.edu int index) 3484000Ssaidi@eecs.umich.edu{ 3496221Snate@binkert.org string path; 3506221Snate@binkert.org 3516221Snate@binkert.org if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 3526221Snate@binkert.org return -EFAULT; 3534000Ssaidi@eecs.umich.edu 3544000Ssaidi@eecs.umich.edu // Adjust path for current working directory 3554000Ssaidi@eecs.umich.edu path = p->fullPath(path); 3564000Ssaidi@eecs.umich.edu 357180SN/A Addr bufPtr = p->getSyscallArg(tc, index); 3582798Sktlim@umich.edu size_t bufsiz = p->getSyscallArg(tc, index); 359180SN/A 3609430SAndreas.Sandberg@ARM.com BufferArg buf(bufPtr, bufsiz); 3619430SAndreas.Sandberg@ARM.com 3622359SN/A int result = -1; 3635606Snate@binkert.org if (path != "/proc/self/exe") { 3649446SAndreas.Sandberg@ARM.com result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); 3659446SAndreas.Sandberg@ARM.com } else { 3669446SAndreas.Sandberg@ARM.com // Emulate readlink() called on '/proc/self/exe' should return the 3679446SAndreas.Sandberg@ARM.com // absolute path of the binary running in the simulated system (the 368180SN/A // Process' executable). It is possible that using this path in 369180SN/A // the simulated system will result in unexpected behavior if: 370180SN/A // 1) One binary runs another (e.g., -c time -o "my_binary"), and 3718737Skoansin.tan@gmail.com // called binary calls readlink(). 372180SN/A // 2) The host's full path to the running benchmark changes from one 3732680Sktlim@umich.edu // simulation to another. This can result in different simulated 3749152Satgutier@umich.edu // performance since the simulated system will process the binary 3759430SAndreas.Sandberg@ARM.com // path differently, even if the binary itself does not change. 3769430SAndreas.Sandberg@ARM.com 3779332Sdam.sunwoo@arm.com // Get the absolute canonical path to the running application 3789332Sdam.sunwoo@arm.com char real_path[PATH_MAX]; 3799430SAndreas.Sandberg@ARM.com char *check_real_path = realpath(p->progName(), real_path); 3805712Shsul@eecs.umich.edu if (!check_real_path) { 3816221Snate@binkert.org fatal("readlink('/proc/self/exe') unable to resolve path to " 3826221Snate@binkert.org "executable: %s", p->progName()); 3832680Sktlim@umich.edu } 3842680Sktlim@umich.edu strncpy((char*)buf.bufferPtr(), real_path, bufsiz); 385180SN/A size_t real_path_len = strlen(real_path); 3862680Sktlim@umich.edu if (real_path_len > bufsiz) { 3872651Ssaidi@eecs.umich.edu // readlink will truncate the contents of the 3882680Sktlim@umich.edu // path to ensure it is no more than bufsiz 3892651Ssaidi@eecs.umich.edu result = bufsiz; 3905714Shsul@eecs.umich.edu } else { 3915715Shsul@eecs.umich.edu result = real_path_len; 3925714Shsul@eecs.umich.edu } 3932359SN/A 3945875Ssteve.reinhardt@amd.com // Issue a warning about potential unexpected results 3955875Ssteve.reinhardt@amd.com warn_once("readlink() called on '/proc/self/exe' may yield unexpected " 3965875Ssteve.reinhardt@amd.com "results in various settings.\n Returning '%s'\n", 3975875Ssteve.reinhardt@amd.com (char*)buf.bufferPtr()); 3985217Ssaidi@eecs.umich.edu } 3995875Ssteve.reinhardt@amd.com 4007781SAli.Saidi@ARM.com buf.copyOut(tc->getMemProxy()); 4019294Sandreas.hansson@arm.com 4029294Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 4039294Sandreas.hansson@arm.com} 4049294Sandreas.hansson@arm.com 4057781SAli.Saidi@ARM.comSyscallReturn 4067781SAli.Saidi@ARM.comunlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 4079178Sandreas.hansson@arm.com{ 4089178Sandreas.hansson@arm.com return unlinkHelper(desc, num, p, tc, 0); 4097781SAli.Saidi@ARM.com} 4109178Sandreas.hansson@arm.com 4119294Sandreas.hansson@arm.comSyscallReturn 4129178Sandreas.hansson@arm.comunlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, 4138922Swilliam.wang@arm.com int index) 4147781SAli.Saidi@ARM.com{ 4159178Sandreas.hansson@arm.com string path; 4169178Sandreas.hansson@arm.com 4177781SAli.Saidi@ARM.com if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 4189178Sandreas.hansson@arm.com return -EFAULT; 4199294Sandreas.hansson@arm.com 4209178Sandreas.hansson@arm.com // Adjust path for current working directory 4218922Swilliam.wang@arm.com path = p->fullPath(path); 4227781SAli.Saidi@ARM.com 4238733Sgeoffrey.blake@arm.com int result = unlink(path.c_str()); 4248887Sgeoffrey.blake@arm.com return (result == -1) ? -errno : result; 4258887Sgeoffrey.blake@arm.com} 4268887Sgeoffrey.blake@arm.com 4278887Sgeoffrey.blake@arm.com 4288887Sgeoffrey.blake@arm.comSyscallReturn 4299294Sandreas.hansson@arm.commkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 4308922Swilliam.wang@arm.com{ 4319294Sandreas.hansson@arm.com string path; 4328922Swilliam.wang@arm.com 4339294Sandreas.hansson@arm.com int index = 0; 4348922Swilliam.wang@arm.com if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 4359294Sandreas.hansson@arm.com return -EFAULT; 4368922Swilliam.wang@arm.com 4378733Sgeoffrey.blake@arm.com // Adjust path for current working directory 4388887Sgeoffrey.blake@arm.com path = p->fullPath(path); 4399178Sandreas.hansson@arm.com 4409178Sandreas.hansson@arm.com mode_t mode = p->getSyscallArg(tc, index); 4418887Sgeoffrey.blake@arm.com 4429178Sandreas.hansson@arm.com int result = mkdir(path.c_str(), mode); 4439294Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 4449294Sandreas.hansson@arm.com} 4459178Sandreas.hansson@arm.com 4468922Swilliam.wang@arm.comSyscallReturn 4478887Sgeoffrey.blake@arm.comrenameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 4489178Sandreas.hansson@arm.com{ 4499178Sandreas.hansson@arm.com string old_name; 4508887Sgeoffrey.blake@arm.com 4519178Sandreas.hansson@arm.com int index = 0; 4529294Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index))) 4539294Sandreas.hansson@arm.com return -EFAULT; 4549178Sandreas.hansson@arm.com 4558922Swilliam.wang@arm.com string new_name; 4568887Sgeoffrey.blake@arm.com 4578733Sgeoffrey.blake@arm.com if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index))) 458180SN/A return -EFAULT; 459605SN/A 4603520Sgblack@eecs.umich.edu // Adjust path for current working directory 4615810Sgblack@eecs.umich.edu old_name = p->fullPath(old_name); 4629152Satgutier@umich.edu new_name = p->fullPath(new_name); 4632254SN/A 4648779Sgblack@eecs.umich.edu int64_t result = rename(old_name.c_str(), new_name.c_str()); 4658779Sgblack@eecs.umich.edu return (result == -1) ? -errno : result; 4668779Sgblack@eecs.umich.edu} 4672254SN/A 4688779Sgblack@eecs.umich.eduSyscallReturn 4698779Sgblack@eecs.umich.edutruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 4708779Sgblack@eecs.umich.edu{ 4714192Sktlim@umich.edu string path; 4729178Sandreas.hansson@arm.com 4739178Sandreas.hansson@arm.com int index = 0; 4749178Sandreas.hansson@arm.com if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 4759178Sandreas.hansson@arm.com return -EFAULT; 4769178Sandreas.hansson@arm.com 4779178Sandreas.hansson@arm.com off_t length = p->getSyscallArg(tc, index); 4789294Sandreas.hansson@arm.com 4799178Sandreas.hansson@arm.com // Adjust path for current working directory 4809178Sandreas.hansson@arm.com path = p->fullPath(path); 4814192Sktlim@umich.edu 4829178Sandreas.hansson@arm.com int result = truncate(path.c_str(), length); 4839178Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 4849294Sandreas.hansson@arm.com} 4859178Sandreas.hansson@arm.com 4869178Sandreas.hansson@arm.comSyscallReturn 487180SN/AftruncateFunc(SyscallDesc *desc, int num, 488180SN/A Process *process, ThreadContext *tc) 4899446SAndreas.Sandberg@ARM.com{ 4909446SAndreas.Sandberg@ARM.com int index = 0; 4919446SAndreas.Sandberg@ARM.com int tgt_fd = process->getSyscallArg(tc, index); 4929446SAndreas.Sandberg@ARM.com off_t length = process->getSyscallArg(tc, index); 4939446SAndreas.Sandberg@ARM.com 4949446SAndreas.Sandberg@ARM.com int sim_fd = process->getSimFD(tgt_fd); 4959446SAndreas.Sandberg@ARM.com if (sim_fd < 0) 4969446SAndreas.Sandberg@ARM.com return -EBADF; 4979446SAndreas.Sandberg@ARM.com 4989446SAndreas.Sandberg@ARM.com int result = ftruncate(sim_fd, length); 4999446SAndreas.Sandberg@ARM.com return (result == -1) ? -errno : result; 5009446SAndreas.Sandberg@ARM.com} 5019446SAndreas.Sandberg@ARM.com 5029446SAndreas.Sandberg@ARM.comSyscallReturn 5039446SAndreas.Sandberg@ARM.comtruncate64Func(SyscallDesc *desc, int num, 5049446SAndreas.Sandberg@ARM.com Process *process, ThreadContext *tc) 505180SN/A{ 5065536Srstrong@hp.com int index = 0; 5075606Snate@binkert.org string path; 5081917SN/A 5091917SN/A if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index))) 5101917SN/A return -EFAULT; 5111917SN/A 5121917SN/A int64_t length = process->getSyscallArg(tc, index, 64); 5136221Snate@binkert.org 5146221Snate@binkert.org // Adjust path for current working directory 5152680Sktlim@umich.edu path = process->fullPath(path); 5162680Sktlim@umich.edu 5171917SN/A#if NO_STAT64 5182254SN/A int result = truncate(path.c_str(), length); 5197823Ssteve.reinhardt@amd.com#else 5201917SN/A int result = truncate64(path.c_str(), length); 5211917SN/A#endif 5222SN/A return (result == -1) ? -errno : result; 523921SN/A} 524921SN/A 5254000Ssaidi@eecs.umich.eduSyscallReturn 5269332Sdam.sunwoo@arm.comftruncate64Func(SyscallDesc *desc, int num, 5279448SAndreas.Sandberg@ARM.com Process *process, ThreadContext *tc) 5289448SAndreas.Sandberg@ARM.com{ 5299448SAndreas.Sandberg@ARM.com int index = 0; 5309448SAndreas.Sandberg@ARM.com int tgt_fd = process->getSyscallArg(tc, index); 5319448SAndreas.Sandberg@ARM.com int64_t length = process->getSyscallArg(tc, index, 64); 5329448SAndreas.Sandberg@ARM.com 5339332Sdam.sunwoo@arm.com int sim_fd = process->getSimFD(tgt_fd); 5349448SAndreas.Sandberg@ARM.com if (sim_fd < 0) 5359448SAndreas.Sandberg@ARM.com return -EBADF; 5369448SAndreas.Sandberg@ARM.com 5379448SAndreas.Sandberg@ARM.com#if NO_STAT64 5389448SAndreas.Sandberg@ARM.com int result = ftruncate(sim_fd, length); 5399448SAndreas.Sandberg@ARM.com#else 5409448SAndreas.Sandberg@ARM.com int result = ftruncate64(sim_fd, length); 5419448SAndreas.Sandberg@ARM.com#endif 542921SN/A return (result == -1) ? -errno : result; 543921SN/A} 544921SN/A 545921SN/ASyscallReturn 546921SN/AumaskFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) 5474000Ssaidi@eecs.umich.edu{ 5489448SAndreas.Sandberg@ARM.com // Letting the simulated program change the simulator's umask seems like 5499448SAndreas.Sandberg@ARM.com // a bad idea. Compromise by just returning the current umask but not 5509448SAndreas.Sandberg@ARM.com // changing anything. 5519448SAndreas.Sandberg@ARM.com mode_t oldMask = umask(0); 5529448SAndreas.Sandberg@ARM.com umask(oldMask); 5539448SAndreas.Sandberg@ARM.com return (int)oldMask; 5549448SAndreas.Sandberg@ARM.com} 5559448SAndreas.Sandberg@ARM.com 5569448SAndreas.Sandberg@ARM.comSyscallReturn 557921SN/AchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) 558921SN/A{ 5591191SN/A string path; 5601191SN/A 5611191SN/A int index = 0; 5621191SN/A if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 5631191SN/A return -EFAULT; 5641191SN/A 5651191SN/A /* XXX endianess */ 5661191SN/A uint32_t owner = p->getSyscallArg(tc, index); 5671191SN/A uid_t hostOwner = owner; 5681191SN/A uint32_t group = p->getSyscallArg(tc, index); 5691191SN/A gid_t hostGroup = group; 5701191SN/A 5711191SN/A // Adjust path for current working directory 5721191SN/A path = p->fullPath(path); 5731191SN/A 5741191SN/A int result = chown(path.c_str(), hostOwner, hostGroup); 5751191SN/A return (result == -1) ? -errno : result; 5761191SN/A} 5771191SN/A 5781191SN/ASyscallReturn 5791191SN/AfchownFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) 5801191SN/A{ 5817823Ssteve.reinhardt@amd.com int index = 0; 5827823Ssteve.reinhardt@amd.com int tgt_fd = process->getSyscallArg(tc, index); 5831191SN/A 5841191SN/A int sim_fd = process->getSimFD(tgt_fd); 5858707Sandreas.hansson@arm.com if (sim_fd < 0) 5868707Sandreas.hansson@arm.com return -EBADF; 5878975Sandreas.hansson@arm.com 5888707Sandreas.hansson@arm.com /* XXX endianess */ 5898948Sandreas.hansson@arm.com uint32_t owner = process->getSyscallArg(tc, index); 5908707Sandreas.hansson@arm.com uid_t hostOwner = owner; 5918707Sandreas.hansson@arm.com uint32_t group = process->getSyscallArg(tc, index); 5928707Sandreas.hansson@arm.com gid_t hostGroup = group; 5938707Sandreas.hansson@arm.com 5948707Sandreas.hansson@arm.com int result = fchown(sim_fd, hostOwner, hostGroup); 5958707Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 5968948Sandreas.hansson@arm.com} 5978707Sandreas.hansson@arm.com 5988707Sandreas.hansson@arm.com 5998707Sandreas.hansson@arm.comSyscallReturn 6008948Sandreas.hansson@arm.comdupFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) 6018707Sandreas.hansson@arm.com{ 6028948Sandreas.hansson@arm.com int index = 0; 6038948Sandreas.hansson@arm.com int tgt_fd = process->getSyscallArg(tc, index); 6048948Sandreas.hansson@arm.com 6058707Sandreas.hansson@arm.com int sim_fd = process->getSimFD(tgt_fd); 606 if (sim_fd < 0) 607 return -EBADF; 608 609 FDEntry *fde = process->getFDEntry(tgt_fd); 610 611 int result = dup(sim_fd); 612 return (result == -1) ? -errno : 613 process->allocFD(result, fde->filename, fde->flags, fde->mode, false); 614} 615 616 617SyscallReturn 618fcntlFunc(SyscallDesc *desc, int num, Process *process, 619 ThreadContext *tc) 620{ 621 int index = 0; 622 int tgt_fd = process->getSyscallArg(tc, index); 623 624 int sim_fd = process->getSimFD(tgt_fd); 625 if (sim_fd < 0) 626 return -EBADF; 627 628 int cmd = process->getSyscallArg(tc, index); 629 switch (cmd) { 630 case 0: // F_DUPFD 631 // if we really wanted to support this, we'd need to do it 632 // in the target fd space. 633 warn("fcntl(%d, F_DUPFD) not supported, error returned\n", tgt_fd); 634 return -EMFILE; 635 636 case 1: // F_GETFD (get close-on-exec flag) 637 case 2: // F_SETFD (set close-on-exec flag) 638 return 0; 639 640 case 3: // F_GETFL (get file flags) 641 case 4: // F_SETFL (set file flags) 642 // not sure if this is totally valid, but we'll pass it through 643 // to the underlying OS 644 warn("fcntl(%d, %d) passed through to host\n", tgt_fd, cmd); 645 return fcntl(sim_fd, cmd); 646 // return 0; 647 648 case 7: // F_GETLK (get lock) 649 case 8: // F_SETLK (set lock) 650 case 9: // F_SETLKW (set lock and wait) 651 // don't mess with file locking... just act like it's OK 652 warn("File lock call (fcntl(%d, %d)) ignored.\n", tgt_fd, cmd); 653 return 0; 654 655 default: 656 warn("Unknown fcntl command %d\n", cmd); 657 return 0; 658 } 659} 660 661SyscallReturn 662fcntl64Func(SyscallDesc *desc, int num, Process *process, 663 ThreadContext *tc) 664{ 665 int index = 0; 666 int tgt_fd = process->getSyscallArg(tc, index); 667 668 int sim_fd = process->getSimFD(tgt_fd); 669 if (sim_fd < 0) 670 return -EBADF; 671 672 int cmd = process->getSyscallArg(tc, index); 673 switch (cmd) { 674 case 33: //F_GETLK64 675 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd); 676 return -EMFILE; 677 678 case 34: // F_SETLK64 679 case 35: // F_SETLKW64 680 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", 681 tgt_fd); 682 return -EMFILE; 683 684 default: 685 // not sure if this is totally valid, but we'll pass it through 686 // to the underlying OS 687 warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd); 688 return fcntl(sim_fd, cmd); 689 // return 0; 690 } 691} 692 693SyscallReturn 694pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, 695 ThreadContext *tc) 696{ 697 int fds[2], sim_fds[2]; 698 int pipe_retval = pipe(fds); 699 700 if (pipe_retval < 0) { 701 // error 702 return pipe_retval; 703 } 704 705 sim_fds[0] = process->allocFD(fds[0], "PIPE-READ", O_WRONLY, -1, true); 706 sim_fds[1] = process->allocFD(fds[1], "PIPE-WRITE", O_RDONLY, -1, true); 707 708 process->setReadPipeSource(sim_fds[0], sim_fds[1]); 709 // Alpha Linux convention for pipe() is that fd[0] is returned as 710 // the return value of the function, and fd[1] is returned in r20. 711 tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); 712 return sim_fds[0]; 713} 714 715 716SyscallReturn 717getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, 718 ThreadContext *tc) 719{ 720 // Make up a PID. There's no interprocess communication in 721 // fake_syscall mode, so there's no way for a process to know it's 722 // not getting a unique value. 723 724 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); 725 return process->pid(); 726} 727 728 729SyscallReturn 730getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, 731 ThreadContext *tc) 732{ 733 // Make up a UID and EUID... it shouldn't matter, and we want the 734 // simulation to be deterministic. 735 736 // EUID goes in r20. 737 tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID 738 return process->uid(); // UID 739} 740 741 742SyscallReturn 743getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, 744 ThreadContext *tc) 745{ 746 // Get current group ID. EGID goes in r20. 747 tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID 748 return process->gid(); 749} 750 751 752SyscallReturn 753setuidFunc(SyscallDesc *desc, int callnum, Process *process, 754 ThreadContext *tc) 755{ 756 // can't fathom why a benchmark would call this. 757 int index = 0; 758 warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); 759 return 0; 760} 761 762SyscallReturn 763getpidFunc(SyscallDesc *desc, int callnum, Process *process, 764 ThreadContext *tc) 765{ 766 // Make up a PID. There's no interprocess communication in 767 // fake_syscall mode, so there's no way for a process to know it's 768 // not getting a unique value. 769 770 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID 771 return process->pid(); 772} 773 774SyscallReturn 775getppidFunc(SyscallDesc *desc, int callnum, Process *process, 776 ThreadContext *tc) 777{ 778 return process->ppid(); 779} 780 781SyscallReturn 782getuidFunc(SyscallDesc *desc, int callnum, Process *process, 783 ThreadContext *tc) 784{ 785 return process->uid(); // UID 786} 787 788SyscallReturn 789geteuidFunc(SyscallDesc *desc, int callnum, Process *process, 790 ThreadContext *tc) 791{ 792 return process->euid(); // UID 793} 794 795SyscallReturn 796getgidFunc(SyscallDesc *desc, int callnum, Process *process, 797 ThreadContext *tc) 798{ 799 return process->gid(); 800} 801 802SyscallReturn 803getegidFunc(SyscallDesc *desc, int callnum, Process *process, 804 ThreadContext *tc) 805{ 806 return process->egid(); 807} 808 809 810SyscallReturn 811cloneFunc(SyscallDesc *desc, int callnum, Process *process, 812 ThreadContext *tc) 813{ 814 int index = 0; 815 IntReg flags = process->getSyscallArg(tc, index); 816 IntReg newStack = process->getSyscallArg(tc, index); 817 818 DPRINTF(SyscallVerbose, "In sys_clone:\n"); 819 DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); 820 DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); 821 822 823 if (flags != 0x10f00) { 824 warn("This sys_clone implementation assumes flags " 825 "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " 826 "(0x10f00), and may not work correctly with given flags " 827 "0x%llx\n", flags); 828 } 829 830 ThreadContext* ctc; // child thread context 831 if ( ( ctc = process->findFreeContext() ) != NULL ) { 832 DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); 833 834 ctc->clearArchRegs(); 835 836 // Arch-specific cloning code 837 #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA 838 // Cloning the misc. regs for these archs is enough 839 TheISA::copyMiscRegs(tc, ctc); 840 #elif THE_ISA == SPARC_ISA 841 TheISA::copyRegs(tc, ctc); 842 843 // TODO: Explain what this code actually does :-) 844 ctc->setIntReg(NumIntArchRegs + 6, 0); 845 ctc->setIntReg(NumIntArchRegs + 4, 0); 846 ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 847 ctc->setIntReg(NumIntArchRegs + 5, NWindows); 848 ctc->setMiscReg(MISCREG_CWP, 0); 849 ctc->setIntReg(NumIntArchRegs + 7, 0); 850 ctc->setMiscRegNoEffect(MISCREG_TL, 0); 851 ctc->setMiscReg(MISCREG_ASI, ASI_PRIMARY); 852 853 for (int y = 8; y < 32; y++) 854 ctc->setIntReg(y, tc->readIntReg(y)); 855 #elif THE_ISA == ARM_ISA 856 TheISA::copyRegs(tc, ctc); 857 #else 858 fatal("sys_clone is not implemented for this ISA\n"); 859 #endif 860 861 // Set up stack register 862 ctc->setIntReg(TheISA::StackPointerReg, newStack); 863 864 // Set up syscall return values in parent and child 865 ctc->setIntReg(ReturnValueReg, 0); // return value, child 866 867 // Alpha needs SyscallSuccessReg=0 in child 868 #if THE_ISA == ALPHA_ISA 869 ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 870 #endif 871 872 // In SPARC/Linux, clone returns 0 on pseudo-return register if 873 // parent, non-zero if child 874 #if THE_ISA == SPARC_ISA 875 tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 876 ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 877 #endif 878 879 ctc->pcState(tc->nextInstAddr()); 880 881 ctc->activate(); 882 883 // Should return nonzero child TID in parent's syscall return register, 884 // but for our pthread library any non-zero value will work 885 return 1; 886 } else { 887 fatal("Called sys_clone, but no unallocated thread contexts found!\n"); 888 return 0; 889 } 890} 891 892SyscallReturn 893fallocateFunc(SyscallDesc *desc, int callnum, Process *process, 894 ThreadContext *tc) 895{ 896#if NO_FALLOCATE 897 warn("Host OS cannot support calls to fallocate. Ignoring syscall"); 898#else 899 int index = 0; 900 int tgt_fd = process->getSyscallArg(tc, index); 901 int mode = process->getSyscallArg(tc, index); 902 off_t offset = process->getSyscallArg(tc, index); 903 off_t len = process->getSyscallArg(tc, index); 904 905 int sim_fd = process->getSimFD(tgt_fd); 906 if (sim_fd < 0) 907 return -EBADF; 908 909 int result = fallocate(sim_fd, mode, offset, len); 910 if (result < 0) 911 return -errno; 912#endif 913 return 0; 914} 915 916SyscallReturn 917accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, 918 int index) 919{ 920 string path; 921 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 922 return -EFAULT; 923 924 // Adjust path for current working directory 925 path = p->fullPath(path); 926 927 mode_t mode = p->getSyscallArg(tc, index); 928 929 int result = access(path.c_str(), mode); 930 return (result == -1) ? -errno : result; 931} 932 933SyscallReturn 934accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) 935{ 936 return accessFunc(desc, callnum, p, tc, 0); 937} 938 939