syscall_emul.cc revision 8601
12SN/A/* 29428SAndreas.Sandberg@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 39920Syasuko.eckert@amd.com * All rights reserved. 48733Sgeoffrey.blake@arm.com * 58733Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without 68733Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are 78733Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright 88733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer; 98733Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright 108733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the 118733Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution; 128733Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its 138733Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from 148733Sgeoffrey.blake@arm.com * this software without specific prior written permission. 152190SN/A * 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 <fcntl.h> 332SN/A#include <unistd.h> 342SN/A 352SN/A#include <cstdio> 362SN/A#include <iostream> 372SN/A#include <string> 382SN/A 392SN/A#include "arch/utility.hh" 402665SN/A#include "base/chunk_generator.hh" 412665SN/A#include "base/trace.hh" 422SN/A#include "config/the_isa.hh" 432SN/A#include "cpu/base.hh" 442680Sktlim@umich.edu#include "cpu/thread_context.hh" 452680Sktlim@umich.edu#include "debug/SyscallVerbose.hh" 462SN/A#include "mem/page_table.hh" 478229Snate@binkert.org#include "sim/process.hh" 487680Sgblack@eecs.umich.edu#include "sim/sim_exit.hh" 497680Sgblack@eecs.umich.edu#include "sim/syscall_emul.hh" 506329Sgblack@eecs.umich.edu#include "sim/system.hh" 513453Sgblack@eecs.umich.edu 526216Snate@binkert.orgusing namespace std; 536658Snate@binkert.orgusing namespace TheISA; 542SN/A 552190SN/Avoid 562190SN/ASyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) 573453Sgblack@eecs.umich.edu{ 583453Sgblack@eecs.umich.edu#if TRACING_ON 599020Sgblack@eecs.umich.edu int index = 0; 606022Sgblack@eecs.umich.edu#endif 613453Sgblack@eecs.umich.edu DPRINTFR(SyscallVerbose, 622190SN/A "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", 638887Sgeoffrey.blake@arm.com curTick(), tc->getCpuPtr()->name(), name, 647680Sgblack@eecs.umich.edu process->getSyscallArg(tc, index), 652313SN/A process->getSyscallArg(tc, index), 668706Sandreas.hansson@arm.com process->getSyscallArg(tc, index), 678706Sandreas.hansson@arm.com process->getSyscallArg(tc, index)); 688706Sandreas.hansson@arm.com 692190SN/A SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); 702190SN/A 713548Sgblack@eecs.umich.edu DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", 723548Sgblack@eecs.umich.edu curTick(),tc->getCpuPtr()->name(), name, retval.value()); 733548Sgblack@eecs.umich.edu 748902Sandreas.hansson@arm.com if (!(flags & SyscallDesc::SuppressReturnValue)) 758902Sandreas.hansson@arm.com process->setSyscallReturn(tc, retval); 762SN/A} 772680Sktlim@umich.edu 782680Sktlim@umich.edu 792680Sktlim@umich.eduSyscallReturn 802680Sktlim@umich.eduunimplementedFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 812680Sktlim@umich.edu ThreadContext *tc) 822680Sktlim@umich.edu{ 832680Sktlim@umich.edu fatal("syscall %s (#%d) unimplemented.", desc->name, callnum); 842680Sktlim@umich.edu 852680Sktlim@umich.edu return 1; 862680Sktlim@umich.edu} 872680Sktlim@umich.edu 882682Sktlim@umich.edu 892680Sktlim@umich.eduSyscallReturn 902680Sktlim@umich.eduignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 912680Sktlim@umich.edu ThreadContext *tc) 922680Sktlim@umich.edu{ 932680Sktlim@umich.edu int index = 0; 942SN/A warn("ignoring syscall %s(%d, %d, ...)", desc->name, 952107SN/A process->getSyscallArg(tc, index), process->getSyscallArg(tc, index)); 962107SN/A 972190SN/A return 0; 982455SN/A} 992455SN/A 1009920Syasuko.eckert@amd.com 1012159SN/ASyscallReturn 1022SN/AignoreWarnOnceFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1036029Ssteve.reinhardt@amd.com ThreadContext *tc) 104246SN/A{ 105246SN/A int index = 0; 106246SN/A warn_once("ignoring syscall %s(%d, %d, ...)", desc->name, 107246SN/A process->getSyscallArg(tc, index), process->getSyscallArg(tc, index)); 108246SN/A 109246SN/A return 0; 110246SN/A} 1112190SN/A 112246SN/A 113246SN/ASyscallReturn 114246SN/AexitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 115246SN/A ThreadContext *tc) 116246SN/A{ 117246SN/A if (process->system->numRunningContexts() == 1) { 118246SN/A // Last running context... exit simulator 1192SN/A int index = 0; 1202680Sktlim@umich.edu exitSimLoop("target called exit()", 1212423SN/A process->getSyscallArg(tc, index) & 0xff); 1222190SN/A } else { 123180SN/A // other running threads... just halt this one 12410110Sandreas.hansson@arm.com tc->halt(); 1252190SN/A } 12610110Sandreas.hansson@arm.com 1275715Shsul@eecs.umich.edu return 1; 1285715Shsul@eecs.umich.edu} 1295714Shsul@eecs.umich.edu 13010110Sandreas.hansson@arm.com 1315714Shsul@eecs.umich.eduSyscallReturn 1325714Shsul@eecs.umich.eduexitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1335714Shsul@eecs.umich.edu ThreadContext *tc) 1346022Sgblack@eecs.umich.edu{ 1352190SN/A // really should just halt all thread contexts belonging to this 1366022Sgblack@eecs.umich.edu // process in case there's another process running... 1372521SN/A int index = 0; 1388887Sgeoffrey.blake@arm.com exitSimLoop("target called exit()", 1398733Sgeoffrey.blake@arm.com process->getSyscallArg(tc, index) & 0xff); 1409020Sgblack@eecs.umich.edu 1418541Sgblack@eecs.umich.edu return 1; 1424997Sgblack@eecs.umich.edu} 1434997Sgblack@eecs.umich.edu 1443548Sgblack@eecs.umich.edu 1452654SN/ASyscallReturn 1468852Sandreas.hansson@arm.comgetpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1472521SN/A{ 1488852Sandreas.hansson@arm.com return (int)VMPageSize; 1493673Srdreslin@umich.edu} 1508706Sandreas.hansson@arm.com 1518706Sandreas.hansson@arm.com 1528706Sandreas.hansson@arm.comSyscallReturn 1538706Sandreas.hansson@arm.combrkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1548706Sandreas.hansson@arm.com{ 1558706Sandreas.hansson@arm.com // change brk addr to first arg 1568706Sandreas.hansson@arm.com int index = 0; 1578799Sgblack@eecs.umich.edu Addr new_brk = p->getSyscallArg(tc, index); 1588852Sandreas.hansson@arm.com 1592518SN/A // in Linux at least, brk(0) returns the current break value 1602190SN/A // (note that the syscall and the glibc function have different behavior) 1612190SN/A if (new_brk == 0) 1622190SN/A return p->brk_point; 1632159SN/A 1642235SN/A if (new_brk > p->brk_point) { 1652103SN/A // might need to allocate some new pages 166393SN/A for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, 167393SN/A VMPageSize); !gen.done(); gen.next()) { 1689180Sandreas.hansson@arm.com if (!p->pTable->translate(gen.addr())) 169393SN/A p->allocateMem(roundDown(gen.addr(), VMPageSize), VMPageSize); 170393SN/A 1719180Sandreas.hansson@arm.com // if the address is already there, zero it out 172393SN/A else { 173393SN/A uint8_t zero = 0; 1749180Sandreas.hansson@arm.com TranslatingPort *tp = tc->getMemPort(); 1752159SN/A 1762190SN/A // split non-page aligned accesses 1772159SN/A Addr next_page = roundUp(gen.addr(), VMPageSize); 1782680Sktlim@umich.edu uint32_t size_needed = next_page - gen.addr(); 1792159SN/A tp->memsetBlob(gen.addr(), zero, size_needed); 1802190SN/A if (gen.addr() + VMPageSize > next_page && 1812159SN/A next_page < new_brk && 1822313SN/A p->pTable->translate(next_page)) 1832235SN/A { 1842235SN/A size_needed = VMPageSize - size_needed; 1852235SN/A tp->memsetBlob(next_page, zero, size_needed); 1862235SN/A } 1872235SN/A } 1882254SN/A } 1892254SN/A } 1902254SN/A 1912235SN/A p->brk_point = new_brk; 1922680Sktlim@umich.edu DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point); 1932159SN/A return p->brk_point; 1942190SN/A} 1952159SN/A 1962159SN/A 1972159SN/ASyscallReturn 1982159SN/AcloseFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1992190SN/A{ 2002159SN/A int index = 0; 2012455SN/A int target_fd = p->getSyscallArg(tc, index); 2022159SN/A int sim_fd = p->sim_fd(target_fd); 2032455SN/A int status = 0; 2042159SN/A if (sim_fd > 2) 2059920Syasuko.eckert@amd.com status = close(sim_fd); 2069920Syasuko.eckert@amd.com if (status >= 0) 2072190SN/A p->free_fd(target_fd); 2082159SN/A return status; 2092455SN/A} 2102159SN/A 2112455SN/A 2122455SN/ASyscallReturn 2139920Syasuko.eckert@amd.comreadFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2149920Syasuko.eckert@amd.com{ 2157720Sgblack@eecs.umich.edu int index = 0; 2162159SN/A int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2177720Sgblack@eecs.umich.edu Addr bufPtr = p->getSyscallArg(tc, index); 2182159SN/A int nbytes = p->getSyscallArg(tc, index); 2198733Sgeoffrey.blake@arm.com BufferArg bufArg(bufPtr, nbytes); 2208733Sgeoffrey.blake@arm.com 2217720Sgblack@eecs.umich.edu int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); 2222159SN/A 2237720Sgblack@eecs.umich.edu if (bytes_read != -1) 2242159SN/A bufArg.copyOut(tc->getMemPort()); 2257720Sgblack@eecs.umich.edu 2265260Sksewell@umich.edu return bytes_read; 2274172Ssaidi@eecs.umich.edu} 2284172Ssaidi@eecs.umich.edu 2292190SN/ASyscallReturn 2302159SN/AwriteFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2314172Ssaidi@eecs.umich.edu{ 2322190SN/A int index = 0; 2333468Sgblack@eecs.umich.edu int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2342190SN/A Addr bufPtr = p->getSyscallArg(tc, index); 2356313Sgblack@eecs.umich.edu int nbytes = p->getSyscallArg(tc, index); 2366313Sgblack@eecs.umich.edu BufferArg bufArg(bufPtr, nbytes); 2379920Syasuko.eckert@amd.com 23810033SAli.Saidi@ARM.com bufArg.copyIn(tc->getMemPort()); 2396313Sgblack@eecs.umich.edu 2406221Snate@binkert.org int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); 2416221Snate@binkert.org 2426221Snate@binkert.org fsync(fd); 2436221Snate@binkert.org 2446221Snate@binkert.org return bytes_written; 2454661Sksewell@umich.edu} 2466221Snate@binkert.org 2476221Snate@binkert.org 2486221Snate@binkert.orgSyscallReturn 2496221Snate@binkert.orglseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2504661Sksewell@umich.edu{ 2512235SN/A int index = 0; 2522235SN/A int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2532190SN/A uint64_t offs = p->getSyscallArg(tc, index); 2542190SN/A int whence = p->getSyscallArg(tc, index); 2552190SN/A 2562159SN/A off_t result = lseek(fd, offs, whence); 2572235SN/A 2582190SN/A return (result == (off_t)-1) ? -errno : result; 2592190SN/A} 2602235SN/A 2612190SN/A 2622834Sksewell@umich.eduSyscallReturn 2634111Sgblack@eecs.umich.edu_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2644111Sgblack@eecs.umich.edu{ 2652834Sksewell@umich.edu int index = 0; 2662834Sksewell@umich.edu int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2672834Sksewell@umich.edu uint64_t offset_high = p->getSyscallArg(tc, index); 2682834Sksewell@umich.edu uint32_t offset_low = p->getSyscallArg(tc, index); 2692525SN/A Addr result_ptr = p->getSyscallArg(tc, index); 2705217Ssaidi@eecs.umich.edu int whence = p->getSyscallArg(tc, index); 2715217Ssaidi@eecs.umich.edu 2729426SAndreas.Sandberg@ARM.com uint64_t offset = (offset_high << 32) | offset_low; 2739426SAndreas.Sandberg@ARM.com 2749426SAndreas.Sandberg@ARM.com uint64_t result = lseek(fd, offset, whence); 2759426SAndreas.Sandberg@ARM.com result = TheISA::htog(result); 2769426SAndreas.Sandberg@ARM.com 2779426SAndreas.Sandberg@ARM.com if (result == (off_t)-1) { 2789426SAndreas.Sandberg@ARM.com //The seek failed. 2799426SAndreas.Sandberg@ARM.com return -errno; 2809426SAndreas.Sandberg@ARM.com } else { 2819426SAndreas.Sandberg@ARM.com // The seek succeeded. 2829426SAndreas.Sandberg@ARM.com // Copy "result" to "result_ptr" 2839426SAndreas.Sandberg@ARM.com // XXX We'll assume that the size of loff_t is 64 bits on the 2849426SAndreas.Sandberg@ARM.com // target platform 2859426SAndreas.Sandberg@ARM.com BufferArg result_buf(result_ptr, sizeof(result)); 2869426SAndreas.Sandberg@ARM.com memcpy(result_buf.bufferPtr(), &result, sizeof(result)); 2879426SAndreas.Sandberg@ARM.com result_buf.copyOut(tc->getMemPort()); 2889426SAndreas.Sandberg@ARM.com return 0; 2899426SAndreas.Sandberg@ARM.com } 2909426SAndreas.Sandberg@ARM.com 2919426SAndreas.Sandberg@ARM.com 2929426SAndreas.Sandberg@ARM.com return (result == (off_t)-1) ? -errno : result; 2939426SAndreas.Sandberg@ARM.com} 2949920Syasuko.eckert@amd.com 2959920Syasuko.eckert@amd.com 2969426SAndreas.Sandberg@ARM.comSyscallReturn 2979426SAndreas.Sandberg@ARM.communmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2982159SN/A{ 2992159SN/A // given that we don't really implement mmap, munmap is really easy 3002682Sktlim@umich.edu return 0; 3012682Sktlim@umich.edu} 3022682Sktlim@umich.edu 3032682Sktlim@umich.edu 3042682Sktlim@umich.educonst char *hostname = "m5.eecs.umich.edu"; 3052682Sktlim@umich.edu 3062682Sktlim@umich.eduSyscallReturn 3072682Sktlim@umich.edugethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3082682Sktlim@umich.edu{ 3092682Sktlim@umich.edu int index = 0; 3102680Sktlim@umich.edu Addr bufPtr = p->getSyscallArg(tc, index); 3112680Sktlim@umich.edu int name_len = p->getSyscallArg(tc, index); 3122190SN/A BufferArg name(bufPtr, name_len); 3132190SN/A 3142680Sktlim@umich.edu strncpy((char *)name.bufferPtr(), hostname, name_len); 3152680Sktlim@umich.edu 3162159SN/A name.copyOut(tc->getMemPort()); 3172190SN/A 3182680Sktlim@umich.edu return 0; 3192SN/A} 3202SN/A 3212SN/ASyscallReturn 3222680Sktlim@umich.edugetcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3232SN/A{ 32410110Sandreas.hansson@arm.com int result = 0; 3252SN/A int index = 0; 32610110Sandreas.hansson@arm.com Addr bufPtr = p->getSyscallArg(tc, index); 3275715Shsul@eecs.umich.edu unsigned long size = p->getSyscallArg(tc, index); 32810110Sandreas.hansson@arm.com BufferArg buf(bufPtr, size); 3295714Shsul@eecs.umich.edu 33010110Sandreas.hansson@arm.com // Is current working directory defined? 3315714Shsul@eecs.umich.edu string cwd = p->getcwd(); 3325714Shsul@eecs.umich.edu if (!cwd.empty()) { 3335714Shsul@eecs.umich.edu if (cwd.length() >= size) { 3346022Sgblack@eecs.umich.edu // Buffer too small 3351917SN/A return -ERANGE; 3366022Sgblack@eecs.umich.edu } 3372521SN/A strncpy((char *)buf.bufferPtr(), cwd.c_str(), size); 3388887Sgeoffrey.blake@arm.com result = cwd.length(); 3398733Sgeoffrey.blake@arm.com } 3409020Sgblack@eecs.umich.edu else { 3418541Sgblack@eecs.umich.edu if (getcwd((char *)buf.bufferPtr(), size) != NULL) { 3424997Sgblack@eecs.umich.edu result = strlen((char *)buf.bufferPtr()); 3434997Sgblack@eecs.umich.edu } 3443548Sgblack@eecs.umich.edu else { 3453548Sgblack@eecs.umich.edu result = -1; 3462654SN/A } 3478852Sandreas.hansson@arm.com } 3482521SN/A 3498852Sandreas.hansson@arm.com buf.copyOut(tc->getMemPort()); 3503673Srdreslin@umich.edu 3518706Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 3528799Sgblack@eecs.umich.edu} 3538852Sandreas.hansson@arm.com 3542518SN/A 3552680Sktlim@umich.eduSyscallReturn 3562SN/AreadlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3572680Sktlim@umich.edu{ 358595SN/A string path; 3592680Sktlim@umich.edu 3602SN/A int index = 0; 3612190SN/A if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 3622190SN/A return (TheISA::IntReg)-EFAULT; 3639180Sandreas.hansson@arm.com 3649180Sandreas.hansson@arm.com // Adjust path for current working directory 3652SN/A path = p->fullPath(path); 3662190SN/A 3679180Sandreas.hansson@arm.com Addr bufPtr = p->getSyscallArg(tc, index); 3682SN/A size_t bufsiz = p->getSyscallArg(tc, index); 3692190SN/A 3709180Sandreas.hansson@arm.com BufferArg buf(bufPtr, bufsiz); 371217SN/A 3722680Sktlim@umich.edu int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); 3732190SN/A 3742680Sktlim@umich.edu buf.copyOut(tc->getMemPort()); 3752680Sktlim@umich.edu 3762190SN/A return (result == -1) ? -errno : result; 3772680Sktlim@umich.edu} 3782190SN/A 3792680Sktlim@umich.eduSyscallReturn 3802235SN/AunlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3812680Sktlim@umich.edu{ 3822680Sktlim@umich.edu string path; 3832254SN/A 3842680Sktlim@umich.edu int index = 0; 3852680Sktlim@umich.edu if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 3862SN/A return (TheISA::IntReg)-EFAULT; 3872190SN/A 3882680Sktlim@umich.edu // Adjust path for current working directory 3892SN/A path = p->fullPath(path); 3902680Sktlim@umich.edu 391716SN/A int result = unlink(path.c_str()); 3922SN/A return (result == -1) ? -errno : result; 3932SN/A} 3942SN/A 3952SN/A 3962680Sktlim@umich.eduSyscallReturn 3972SN/AmkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3982455SN/A{ 3992680Sktlim@umich.edu string path; 4002SN/A 4012455SN/A int index = 0; 4022680Sktlim@umich.edu if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 4032SN/A return (TheISA::IntReg)-EFAULT; 4049920Syasuko.eckert@amd.com 4059920Syasuko.eckert@amd.com // Adjust path for current working directory 4069920Syasuko.eckert@amd.com path = p->fullPath(path); 4072SN/A 4082680Sktlim@umich.edu mode_t mode = p->getSyscallArg(tc, index); 4092SN/A 4102455SN/A int result = mkdir(path.c_str(), mode); 4112680Sktlim@umich.edu return (result == -1) ? -errno : result; 4122SN/A} 4132455SN/A 4142680Sktlim@umich.eduSyscallReturn 4152SN/ArenameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 4169920Syasuko.eckert@amd.com{ 4179920Syasuko.eckert@amd.com string old_name; 4189920Syasuko.eckert@amd.com 4197720Sgblack@eecs.umich.edu int index = 0; 4202SN/A if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, index))) 4217720Sgblack@eecs.umich.edu return -EFAULT; 4222206SN/A 4238733Sgeoffrey.blake@arm.com string new_name; 4248733Sgeoffrey.blake@arm.com 4257720Sgblack@eecs.umich.edu if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, index))) 4267720Sgblack@eecs.umich.edu return -EFAULT; 4277720Sgblack@eecs.umich.edu 4285260Sksewell@umich.edu // Adjust path for current working directory 4297597Sminkyu.jeong@arm.com old_name = p->fullPath(old_name); 4307597Sminkyu.jeong@arm.com new_name = p->fullPath(new_name); 4317597Sminkyu.jeong@arm.com 4327597Sminkyu.jeong@arm.com int64_t result = rename(old_name.c_str(), new_name.c_str()); 4337597Sminkyu.jeong@arm.com return (result == -1) ? -errno : result; 4344172Ssaidi@eecs.umich.edu} 4354172Ssaidi@eecs.umich.edu 4364172Ssaidi@eecs.umich.eduSyscallReturn 4372159SN/AtruncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 4382680Sktlim@umich.edu{ 4392SN/A string path; 4404172Ssaidi@eecs.umich.edu 4414172Ssaidi@eecs.umich.edu int index = 0; 4422SN/A if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 4433468Sgblack@eecs.umich.edu return -EFAULT; 4442680Sktlim@umich.edu 4452SN/A off_t length = p->getSyscallArg(tc, index); 4466313Sgblack@eecs.umich.edu 4476313Sgblack@eecs.umich.edu // Adjust path for current working directory 4486313Sgblack@eecs.umich.edu path = p->fullPath(path); 4496313Sgblack@eecs.umich.edu 4506313Sgblack@eecs.umich.edu int result = truncate(path.c_str(), length); 4516313Sgblack@eecs.umich.edu return (result == -1) ? -errno : result; 4529920Syasuko.eckert@amd.com} 4539920Syasuko.eckert@amd.com 4549920Syasuko.eckert@amd.comSyscallReturn 45510033SAli.Saidi@ARM.comftruncateFunc(SyscallDesc *desc, int num, 45610033SAli.Saidi@ARM.com LiveProcess *process, ThreadContext *tc) 45710033SAli.Saidi@ARM.com{ 4582190SN/A int index = 0; 4592680Sktlim@umich.edu int fd = process->sim_fd(process->getSyscallArg(tc, index)); 4602190SN/A 4612190SN/A if (fd < 0) 4622680Sktlim@umich.edu return -EBADF; 4632SN/A 4642190SN/A off_t length = process->getSyscallArg(tc, index); 4652680Sktlim@umich.edu 4662190SN/A int result = ftruncate(fd, length); 4674111Sgblack@eecs.umich.edu return (result == -1) ? -errno : result; 4684111Sgblack@eecs.umich.edu} 4694111Sgblack@eecs.umich.edu 4702680Sktlim@umich.eduSyscallReturn 4719426SAndreas.Sandberg@ARM.comtruncate64Func(SyscallDesc *desc, int num, 4729426SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc) 4739426SAndreas.Sandberg@ARM.com{ 4749426SAndreas.Sandberg@ARM.com int index = 0; 4759426SAndreas.Sandberg@ARM.com string path; 4769426SAndreas.Sandberg@ARM.com 4779426SAndreas.Sandberg@ARM.com if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, index))) 4789426SAndreas.Sandberg@ARM.com return -EFAULT; 4799426SAndreas.Sandberg@ARM.com 4809426SAndreas.Sandberg@ARM.com int64_t length = process->getSyscallArg(tc, index, 64); 4819426SAndreas.Sandberg@ARM.com 4829426SAndreas.Sandberg@ARM.com // Adjust path for current working directory 4839426SAndreas.Sandberg@ARM.com path = process->fullPath(path); 4849426SAndreas.Sandberg@ARM.com 4859426SAndreas.Sandberg@ARM.com#if NO_STAT64 4869426SAndreas.Sandberg@ARM.com int result = truncate(path.c_str(), length); 4879426SAndreas.Sandberg@ARM.com#else 4889426SAndreas.Sandberg@ARM.com int result = truncate64(path.c_str(), length); 4899920Syasuko.eckert@amd.com#endif 4909920Syasuko.eckert@amd.com return (result == -1) ? -errno : result; 4919920Syasuko.eckert@amd.com} 4929920Syasuko.eckert@amd.com 4939920Syasuko.eckert@amd.comSyscallReturn 4949920Syasuko.eckert@amd.comftruncate64Func(SyscallDesc *desc, int num, 4952SN/A LiveProcess *process, ThreadContext *tc) 4962SN/A{ 4979428SAndreas.Sandberg@ARM.com int index = 0; 4989428SAndreas.Sandberg@ARM.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 4999428SAndreas.Sandberg@ARM.com 5009428SAndreas.Sandberg@ARM.com if (fd < 0) 5019428SAndreas.Sandberg@ARM.com return -EBADF; 5029428SAndreas.Sandberg@ARM.com 5039428SAndreas.Sandberg@ARM.com int64_t length = process->getSyscallArg(tc, index, 64); 5049428SAndreas.Sandberg@ARM.com 5059428SAndreas.Sandberg@ARM.com#if NO_STAT64 5069428SAndreas.Sandberg@ARM.com int result = ftruncate(fd, length); 5079428SAndreas.Sandberg@ARM.com#else 5089428SAndreas.Sandberg@ARM.com int result = ftruncate64(fd, length); 5099428SAndreas.Sandberg@ARM.com#endif 5109428SAndreas.Sandberg@ARM.com return (result == -1) ? -errno : result; 5119428SAndreas.Sandberg@ARM.com} 5129441SAndreas.Sandberg@ARM.com 5139441SAndreas.Sandberg@ARM.comSyscallReturn 5149441SAndreas.Sandberg@ARM.comumaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 5159441SAndreas.Sandberg@ARM.com{ 5169441SAndreas.Sandberg@ARM.com // Letting the simulated program change the simulator's umask seems like 5179441SAndreas.Sandberg@ARM.com // a bad idea. Compromise by just returning the current umask but not 5189441SAndreas.Sandberg@ARM.com // changing anything. 5199441SAndreas.Sandberg@ARM.com mode_t oldMask = umask(0); 5209441SAndreas.Sandberg@ARM.com umask(oldMask); 5219441SAndreas.Sandberg@ARM.com return (int)oldMask; 5229441SAndreas.Sandberg@ARM.com} 5239441SAndreas.Sandberg@ARM.com 5249441SAndreas.Sandberg@ARM.comSyscallReturn 5252190SN/AchownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 526{ 527 string path; 528 529 int index = 0; 530 if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 531 return -EFAULT; 532 533 /* XXX endianess */ 534 uint32_t owner = p->getSyscallArg(tc, index); 535 uid_t hostOwner = owner; 536 uint32_t group = p->getSyscallArg(tc, index); 537 gid_t hostGroup = group; 538 539 // Adjust path for current working directory 540 path = p->fullPath(path); 541 542 int result = chown(path.c_str(), hostOwner, hostGroup); 543 return (result == -1) ? -errno : result; 544} 545 546SyscallReturn 547fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 548{ 549 int index = 0; 550 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 551 552 if (fd < 0) 553 return -EBADF; 554 555 /* XXX endianess */ 556 uint32_t owner = process->getSyscallArg(tc, index); 557 uid_t hostOwner = owner; 558 uint32_t group = process->getSyscallArg(tc, index); 559 gid_t hostGroup = group; 560 561 int result = fchown(fd, hostOwner, hostGroup); 562 return (result == -1) ? -errno : result; 563} 564 565 566SyscallReturn 567dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 568{ 569 int index = 0; 570 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 571 if (fd < 0) 572 return -EBADF; 573 574 Process::FdMap *fdo = process->sim_fd_obj(fd); 575 576 int result = dup(fd); 577 return (result == -1) ? -errno : 578 process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false); 579} 580 581 582SyscallReturn 583fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, 584 ThreadContext *tc) 585{ 586 int index = 0; 587 int fd = process->getSyscallArg(tc, index); 588 589 if (fd < 0 || process->sim_fd(fd) < 0) 590 return -EBADF; 591 592 int cmd = process->getSyscallArg(tc, index); 593 switch (cmd) { 594 case 0: // F_DUPFD 595 // if we really wanted to support this, we'd need to do it 596 // in the target fd space. 597 warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); 598 return -EMFILE; 599 600 case 1: // F_GETFD (get close-on-exec flag) 601 case 2: // F_SETFD (set close-on-exec flag) 602 return 0; 603 604 case 3: // F_GETFL (get file flags) 605 case 4: // F_SETFL (set file flags) 606 // not sure if this is totally valid, but we'll pass it through 607 // to the underlying OS 608 warn("fcntl(%d, %d) passed through to host\n", fd, cmd); 609 return fcntl(process->sim_fd(fd), cmd); 610 // return 0; 611 612 case 7: // F_GETLK (get lock) 613 case 8: // F_SETLK (set lock) 614 case 9: // F_SETLKW (set lock and wait) 615 // don't mess with file locking... just act like it's OK 616 warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); 617 return 0; 618 619 default: 620 warn("Unknown fcntl command %d\n", cmd); 621 return 0; 622 } 623} 624 625SyscallReturn 626fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, 627 ThreadContext *tc) 628{ 629 int index = 0; 630 int fd = process->getSyscallArg(tc, index); 631 632 if (fd < 0 || process->sim_fd(fd) < 0) 633 return -EBADF; 634 635 int cmd = process->getSyscallArg(tc, index); 636 switch (cmd) { 637 case 33: //F_GETLK64 638 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); 639 return -EMFILE; 640 641 case 34: // F_SETLK64 642 case 35: // F_SETLKW64 643 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd); 644 return -EMFILE; 645 646 default: 647 // not sure if this is totally valid, but we'll pass it through 648 // to the underlying OS 649 warn("fcntl64(%d, %d) passed through to host\n", fd, cmd); 650 return fcntl(process->sim_fd(fd), cmd); 651 // return 0; 652 } 653} 654 655SyscallReturn 656pipePseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 657 ThreadContext *tc) 658{ 659 int fds[2], sim_fds[2]; 660 int pipe_retval = pipe(fds); 661 662 if (pipe_retval < 0) { 663 // error 664 return pipe_retval; 665 } 666 667 sim_fds[0] = process->alloc_fd(fds[0], "PIPE-READ", O_WRONLY, -1, true); 668 sim_fds[1] = process->alloc_fd(fds[1], "PIPE-WRITE", O_RDONLY, -1, true); 669 670 process->setReadPipeSource(sim_fds[0], sim_fds[1]); 671 // Alpha Linux convention for pipe() is that fd[0] is returned as 672 // the return value of the function, and fd[1] is returned in r20. 673 tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); 674 return sim_fds[0]; 675} 676 677 678SyscallReturn 679getpidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 680 ThreadContext *tc) 681{ 682 // Make up a PID. There's no interprocess communication in 683 // fake_syscall mode, so there's no way for a process to know it's 684 // not getting a unique value. 685 686 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); 687 return process->pid(); 688} 689 690 691SyscallReturn 692getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 693 ThreadContext *tc) 694{ 695 // Make up a UID and EUID... it shouldn't matter, and we want the 696 // simulation to be deterministic. 697 698 // EUID goes in r20. 699 tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID 700 return process->uid(); // UID 701} 702 703 704SyscallReturn 705getgidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 706 ThreadContext *tc) 707{ 708 // Get current group ID. EGID goes in r20. 709 tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID 710 return process->gid(); 711} 712 713 714SyscallReturn 715setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 716 ThreadContext *tc) 717{ 718 // can't fathom why a benchmark would call this. 719 int index = 0; 720 warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); 721 return 0; 722} 723 724SyscallReturn 725getpidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 726 ThreadContext *tc) 727{ 728 // Make up a PID. There's no interprocess communication in 729 // fake_syscall mode, so there's no way for a process to know it's 730 // not getting a unique value. 731 732 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID 733 return process->pid(); 734} 735 736SyscallReturn 737getppidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 738 ThreadContext *tc) 739{ 740 return process->ppid(); 741} 742 743SyscallReturn 744getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 745 ThreadContext *tc) 746{ 747 return process->uid(); // UID 748} 749 750SyscallReturn 751geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 752 ThreadContext *tc) 753{ 754 return process->euid(); // UID 755} 756 757SyscallReturn 758getgidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 759 ThreadContext *tc) 760{ 761 return process->gid(); 762} 763 764SyscallReturn 765getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 766 ThreadContext *tc) 767{ 768 return process->egid(); 769} 770 771 772SyscallReturn 773cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 774 ThreadContext *tc) 775{ 776 int index = 0; 777 IntReg flags = process->getSyscallArg(tc, index); 778 IntReg newStack = process->getSyscallArg(tc, index); 779 780 DPRINTF(SyscallVerbose, "In sys_clone:\n"); 781 DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); 782 DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); 783 784 785 if (flags != 0x10f00) { 786 warn("This sys_clone implementation assumes flags " 787 "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " 788 "(0x10f00), and may not work correctly with given flags " 789 "0x%llx\n", flags); 790 } 791 792 ThreadContext* ctc; // child thread context 793 if ( ( ctc = process->findFreeContext() ) != NULL ) { 794 DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); 795 796 ctc->clearArchRegs(); 797 798 // Arch-specific cloning code 799 #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA 800 // Cloning the misc. regs for these archs is enough 801 TheISA::copyMiscRegs(tc, ctc); 802 #elif THE_ISA == SPARC_ISA 803 TheISA::copyRegs(tc, ctc); 804 805 // TODO: Explain what this code actually does :-) 806 ctc->setIntReg(NumIntArchRegs + 6, 0); 807 ctc->setIntReg(NumIntArchRegs + 4, 0); 808 ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 809 ctc->setIntReg(NumIntArchRegs + 5, NWindows); 810 ctc->setMiscReg(MISCREG_CWP, 0); 811 ctc->setIntReg(NumIntArchRegs + 7, 0); 812 ctc->setMiscRegNoEffect(MISCREG_TL, 0); 813 ctc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); 814 815 for (int y = 8; y < 32; y++) 816 ctc->setIntReg(y, tc->readIntReg(y)); 817 #elif THE_ISA == ARM_ISA 818 TheISA::copyRegs(tc, ctc); 819 #else 820 fatal("sys_clone is not implemented for this ISA\n"); 821 #endif 822 823 // Set up stack register 824 ctc->setIntReg(TheISA::StackPointerReg, newStack); 825 826 // Set up syscall return values in parent and child 827 ctc->setIntReg(ReturnValueReg, 0); // return value, child 828 829 // Alpha needs SyscallSuccessReg=0 in child 830 #if THE_ISA == ALPHA_ISA 831 ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 832 #endif 833 834 // In SPARC/Linux, clone returns 0 on pseudo-return register if 835 // parent, non-zero if child 836 #if THE_ISA == SPARC_ISA 837 tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 838 ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 839 #endif 840 841 ctc->pcState(tc->nextInstAddr()); 842 843 ctc->activate(); 844 845 // Should return nonzero child TID in parent's syscall return register, 846 // but for our pthread library any non-zero value will work 847 return 1; 848 } else { 849 fatal("Called sys_clone, but no unallocated thread contexts found!\n"); 850 return 0; 851 } 852} 853 854