syscall_emul.cc revision 6744
1955SN/A/* 2955SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 294762Snate@binkert.org * Ali Saidi 30955SN/A */ 315522Snate@binkert.org 326143Snate@binkert.org#include <fcntl.h> 334762Snate@binkert.org#include <unistd.h> 345522Snate@binkert.org 35955SN/A#include <cstdio> 365522Snate@binkert.org#include <iostream> 3711974Sgabeblack@google.com#include <string> 38955SN/A 395522Snate@binkert.org#include "sim/syscall_emul.hh" 404202Sbinkertn@umich.edu#include "base/chunk_generator.hh" 415742Snate@binkert.org#include "base/trace.hh" 42955SN/A#include "config/the_isa.hh" 434381Sbinkertn@umich.edu#include "cpu/thread_context.hh" 444381Sbinkertn@umich.edu#include "cpu/base.hh" 4512246Sgabeblack@google.com#include "mem/page_table.hh" 4612246Sgabeblack@google.com#include "sim/process.hh" 478334Snate@binkert.org#include "sim/system.hh" 48955SN/A#include "sim/sim_exit.hh" 49955SN/A 504202Sbinkertn@umich.eduusing namespace std; 51955SN/Ausing namespace TheISA; 524382Sbinkertn@umich.edu 534382Sbinkertn@umich.eduvoid 544382Sbinkertn@umich.eduSyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) 556654Snate@binkert.org{ 565517Snate@binkert.org#if TRACING_ON 578614Sgblack@eecs.umich.edu int index = 0; 587674Snate@binkert.org#endif 596143Snate@binkert.org DPRINTFR(SyscallVerbose, 606143Snate@binkert.org "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", 616143Snate@binkert.org curTick, tc->getCpuPtr()->name(), name, 6212302Sgabeblack@google.com process->getSyscallArg(tc, index), 6312302Sgabeblack@google.com process->getSyscallArg(tc, index), 6412302Sgabeblack@google.com process->getSyscallArg(tc, index), 6512302Sgabeblack@google.com process->getSyscallArg(tc, index)); 6612302Sgabeblack@google.com 6712302Sgabeblack@google.com SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); 6812302Sgabeblack@google.com 6912302Sgabeblack@google.com DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", 7012302Sgabeblack@google.com curTick,tc->getCpuPtr()->name(), name, retval.value()); 7112302Sgabeblack@google.com 7212302Sgabeblack@google.com if (!(flags & SyscallDesc::SuppressReturnValue)) 7312302Sgabeblack@google.com process->setSyscallReturn(tc, retval); 7412302Sgabeblack@google.com} 7512302Sgabeblack@google.com 7612302Sgabeblack@google.com 7712302Sgabeblack@google.comSyscallReturn 7812302Sgabeblack@google.comunimplementedFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7912302Sgabeblack@google.com ThreadContext *tc) 8012302Sgabeblack@google.com{ 8112302Sgabeblack@google.com fatal("syscall %s (#%d) unimplemented.", desc->name, callnum); 8212302Sgabeblack@google.com 8312302Sgabeblack@google.com return 1; 8412302Sgabeblack@google.com} 8512302Sgabeblack@google.com 8612302Sgabeblack@google.com 8712302Sgabeblack@google.comSyscallReturn 8812302Sgabeblack@google.comignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8912302Sgabeblack@google.com ThreadContext *tc) 9012302Sgabeblack@google.com{ 9111983Sgabeblack@google.com int index = 0; 926143Snate@binkert.org warn("ignoring syscall %s(%d, %d, ...)", desc->name, 938233Snate@binkert.org process->getSyscallArg(tc, index), process->getSyscallArg(tc, index)); 9412302Sgabeblack@google.com 956143Snate@binkert.org return 0; 966143Snate@binkert.org} 9712302Sgabeblack@google.com 984762Snate@binkert.org 996143Snate@binkert.orgSyscallReturn 1008233Snate@binkert.orgexitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1018233Snate@binkert.org ThreadContext *tc) 10212302Sgabeblack@google.com{ 10312302Sgabeblack@google.com if (process->system->numRunningContexts() == 1) { 1046143Snate@binkert.org // Last running context... exit simulator 10512302Sgabeblack@google.com int index = 0; 10612302Sgabeblack@google.com exitSimLoop("target called exit()", 10712302Sgabeblack@google.com process->getSyscallArg(tc, index) & 0xff); 10812302Sgabeblack@google.com } else { 10912302Sgabeblack@google.com // other running threads... just halt this one 11012302Sgabeblack@google.com tc->halt(); 11112302Sgabeblack@google.com } 11212302Sgabeblack@google.com 11312302Sgabeblack@google.com return 1; 11412302Sgabeblack@google.com} 1158233Snate@binkert.org 1166143Snate@binkert.org 1176143Snate@binkert.orgSyscallReturn 1186143Snate@binkert.orgexitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1196143Snate@binkert.org ThreadContext *tc) 1206143Snate@binkert.org{ 1216143Snate@binkert.org // really should just halt all thread contexts belonging to this 1226143Snate@binkert.org // process in case there's another process running... 1236143Snate@binkert.org int index = 0; 1246143Snate@binkert.org exitSimLoop("target called exit()", 1257065Snate@binkert.org process->getSyscallArg(tc, index) & 0xff); 1266143Snate@binkert.org 1278233Snate@binkert.org return 1; 1288233Snate@binkert.org} 1298233Snate@binkert.org 1308233Snate@binkert.org 1318233Snate@binkert.orgSyscallReturn 1328233Snate@binkert.orggetpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1338233Snate@binkert.org{ 1348233Snate@binkert.org return (int)VMPageSize; 1358233Snate@binkert.org} 1368233Snate@binkert.org 1378233Snate@binkert.org 1388233Snate@binkert.orgSyscallReturn 1398233Snate@binkert.orgbrkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1408233Snate@binkert.org{ 1418233Snate@binkert.org // change brk addr to first arg 1428233Snate@binkert.org int index = 0; 1438233Snate@binkert.org Addr new_brk = p->getSyscallArg(tc, index); 1448233Snate@binkert.org 1458233Snate@binkert.org // in Linux at least, brk(0) returns the current break value 1468233Snate@binkert.org // (note that the syscall and the glibc function have different behavior) 1478233Snate@binkert.org if (new_brk == 0) 1486143Snate@binkert.org return p->brk_point; 1496143Snate@binkert.org 1506143Snate@binkert.org if (new_brk > p->brk_point) { 1516143Snate@binkert.org // might need to allocate some new pages 1526143Snate@binkert.org for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, 1536143Snate@binkert.org VMPageSize); !gen.done(); gen.next()) { 1549982Satgutier@umich.edu if (!p->pTable->translate(gen.addr())) 1556143Snate@binkert.org p->pTable->allocate(roundDown(gen.addr(), VMPageSize), 15612302Sgabeblack@google.com VMPageSize); 15712302Sgabeblack@google.com 15812302Sgabeblack@google.com // if the address is already there, zero it out 15912302Sgabeblack@google.com else { 16012302Sgabeblack@google.com uint8_t zero = 0; 16112302Sgabeblack@google.com TranslatingPort *tp = tc->getMemPort(); 16212302Sgabeblack@google.com 16312302Sgabeblack@google.com // split non-page aligned accesses 16411983Sgabeblack@google.com Addr next_page = roundUp(gen.addr(), VMPageSize); 16511983Sgabeblack@google.com uint32_t size_needed = next_page - gen.addr(); 16611983Sgabeblack@google.com tp->memsetBlob(gen.addr(), zero, size_needed); 16712302Sgabeblack@google.com if (gen.addr() + VMPageSize > next_page && 16812302Sgabeblack@google.com next_page < new_brk && 16912302Sgabeblack@google.com p->pTable->translate(next_page)) 17012302Sgabeblack@google.com { 17112302Sgabeblack@google.com size_needed = VMPageSize - size_needed; 17212302Sgabeblack@google.com tp->memsetBlob(next_page, zero, size_needed); 17311983Sgabeblack@google.com } 1746143Snate@binkert.org } 17512305Sgabeblack@google.com } 17612302Sgabeblack@google.com } 17712302Sgabeblack@google.com 17812302Sgabeblack@google.com p->brk_point = new_brk; 1796143Snate@binkert.org DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point); 1806143Snate@binkert.org return p->brk_point; 1816143Snate@binkert.org} 1825522Snate@binkert.org 1836143Snate@binkert.org 1846143Snate@binkert.orgSyscallReturn 1856143Snate@binkert.orgcloseFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1869982Satgutier@umich.edu{ 18712302Sgabeblack@google.com int index = 0; 18812302Sgabeblack@google.com int target_fd = p->getSyscallArg(tc, index); 18912302Sgabeblack@google.com int status = close(p->sim_fd(target_fd)); 1906143Snate@binkert.org if (status >= 0) 1916143Snate@binkert.org p->free_fd(target_fd); 1926143Snate@binkert.org return status; 1936143Snate@binkert.org} 1945522Snate@binkert.org 1955522Snate@binkert.org 1965522Snate@binkert.orgSyscallReturn 1975522Snate@binkert.orgreadFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1985604Snate@binkert.org{ 1995604Snate@binkert.org int index = 0; 2006143Snate@binkert.org int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2016143Snate@binkert.org Addr bufPtr = p->getSyscallArg(tc, index); 2024762Snate@binkert.org int nbytes = p->getSyscallArg(tc, index); 2034762Snate@binkert.org BufferArg bufArg(bufPtr, nbytes); 2046143Snate@binkert.org 2056727Ssteve.reinhardt@amd.com int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); 2066727Ssteve.reinhardt@amd.com 2076727Ssteve.reinhardt@amd.com if (bytes_read != -1) 2084762Snate@binkert.org bufArg.copyOut(tc->getMemPort()); 2096143Snate@binkert.org 2106143Snate@binkert.org return bytes_read; 2116143Snate@binkert.org} 2126143Snate@binkert.org 2136727Ssteve.reinhardt@amd.comSyscallReturn 2146143Snate@binkert.orgwriteFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2157674Snate@binkert.org{ 2167674Snate@binkert.org int index = 0; 2175604Snate@binkert.org int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2186143Snate@binkert.org Addr bufPtr = p->getSyscallArg(tc, index); 2196143Snate@binkert.org int nbytes = p->getSyscallArg(tc, index); 2206143Snate@binkert.org BufferArg bufArg(bufPtr, nbytes); 2214762Snate@binkert.org 2226143Snate@binkert.org bufArg.copyIn(tc->getMemPort()); 2234762Snate@binkert.org 2244762Snate@binkert.org int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); 2254762Snate@binkert.org 2266143Snate@binkert.org fsync(fd); 2276143Snate@binkert.org 2284762Snate@binkert.org return bytes_written; 22912302Sgabeblack@google.com} 23012302Sgabeblack@google.com 2318233Snate@binkert.org 23212302Sgabeblack@google.comSyscallReturn 2336143Snate@binkert.orglseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2346143Snate@binkert.org{ 2354762Snate@binkert.org int index = 0; 2366143Snate@binkert.org int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2374762Snate@binkert.org uint64_t offs = p->getSyscallArg(tc, index); 2389396Sandreas.hansson@arm.com int whence = p->getSyscallArg(tc, index); 2399396Sandreas.hansson@arm.com 2409396Sandreas.hansson@arm.com off_t result = lseek(fd, offs, whence); 24112302Sgabeblack@google.com 24212302Sgabeblack@google.com return (result == (off_t)-1) ? -errno : result; 24312302Sgabeblack@google.com} 2449396Sandreas.hansson@arm.com 2459396Sandreas.hansson@arm.com 2469396Sandreas.hansson@arm.comSyscallReturn 2479396Sandreas.hansson@arm.com_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2489396Sandreas.hansson@arm.com{ 2499396Sandreas.hansson@arm.com int index = 0; 2509396Sandreas.hansson@arm.com int fd = p->sim_fd(p->getSyscallArg(tc, index)); 2519930Sandreas.hansson@arm.com uint64_t offset_high = p->getSyscallArg(tc, index); 2529930Sandreas.hansson@arm.com uint32_t offset_low = p->getSyscallArg(tc, index); 2539396Sandreas.hansson@arm.com Addr result_ptr = p->getSyscallArg(tc, index); 2548235Snate@binkert.org int whence = p->getSyscallArg(tc, index); 2558235Snate@binkert.org 2566143Snate@binkert.org uint64_t offset = (offset_high << 32) | offset_low; 2578235Snate@binkert.org 2589003SAli.Saidi@ARM.com uint64_t result = lseek(fd, offset, whence); 2598235Snate@binkert.org result = TheISA::htog(result); 2608235Snate@binkert.org 26112302Sgabeblack@google.com if (result == (off_t)-1) { 2628235Snate@binkert.org //The seek failed. 26312302Sgabeblack@google.com return -errno; 2648235Snate@binkert.org } else { 2658235Snate@binkert.org // The seek succeeded. 26612302Sgabeblack@google.com // Copy "result" to "result_ptr" 2678235Snate@binkert.org // XXX We'll assume that the size of loff_t is 64 bits on the 2688235Snate@binkert.org // target platform 2698235Snate@binkert.org BufferArg result_buf(result_ptr, sizeof(result)); 2708235Snate@binkert.org memcpy(result_buf.bufferPtr(), &result, sizeof(result)); 2719003SAli.Saidi@ARM.com result_buf.copyOut(tc->getMemPort()); 2728235Snate@binkert.org return 0; 2735584Snate@binkert.org } 2744382Sbinkertn@umich.edu 2754202Sbinkertn@umich.edu 2764382Sbinkertn@umich.edu return (result == (off_t)-1) ? -errno : result; 2774382Sbinkertn@umich.edu} 2789396Sandreas.hansson@arm.com 2795584Snate@binkert.org 2804382Sbinkertn@umich.eduSyscallReturn 2814382Sbinkertn@umich.edumunmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2824382Sbinkertn@umich.edu{ 2838232Snate@binkert.org // given that we don't really implement mmap, munmap is really easy 2845192Ssaidi@eecs.umich.edu return 0; 2858232Snate@binkert.org} 2868232Snate@binkert.org 2878232Snate@binkert.org 2885192Ssaidi@eecs.umich.educonst char *hostname = "m5.eecs.umich.edu"; 2898232Snate@binkert.org 2905192Ssaidi@eecs.umich.eduSyscallReturn 2915799Snate@binkert.orggethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 2928232Snate@binkert.org{ 2935192Ssaidi@eecs.umich.edu int index = 0; 2945192Ssaidi@eecs.umich.edu Addr bufPtr = p->getSyscallArg(tc, index); 2955192Ssaidi@eecs.umich.edu int name_len = p->getSyscallArg(tc, index); 2968232Snate@binkert.org BufferArg name(bufPtr, name_len); 2975192Ssaidi@eecs.umich.edu 2988232Snate@binkert.org strncpy((char *)name.bufferPtr(), hostname, name_len); 2995192Ssaidi@eecs.umich.edu 3005192Ssaidi@eecs.umich.edu name.copyOut(tc->getMemPort()); 3015192Ssaidi@eecs.umich.edu 3025192Ssaidi@eecs.umich.edu return 0; 3034382Sbinkertn@umich.edu} 3044382Sbinkertn@umich.edu 3054382Sbinkertn@umich.eduSyscallReturn 3062667Sstever@eecs.umich.edugetcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3072667Sstever@eecs.umich.edu{ 3082667Sstever@eecs.umich.edu int result = 0; 3092667Sstever@eecs.umich.edu int index = 0; 3102667Sstever@eecs.umich.edu Addr bufPtr = p->getSyscallArg(tc, index); 3112667Sstever@eecs.umich.edu unsigned long size = p->getSyscallArg(tc, index); 3125742Snate@binkert.org BufferArg buf(bufPtr, size); 3135742Snate@binkert.org 3145742Snate@binkert.org // Is current working directory defined? 3155793Snate@binkert.org string cwd = p->getcwd(); 3168334Snate@binkert.org if (!cwd.empty()) { 3175793Snate@binkert.org if (cwd.length() >= size) { 3185793Snate@binkert.org // Buffer too small 3195793Snate@binkert.org return -ERANGE; 3204382Sbinkertn@umich.edu } 3214762Snate@binkert.org strncpy((char *)buf.bufferPtr(), cwd.c_str(), size); 3225344Sstever@gmail.com result = cwd.length(); 3234382Sbinkertn@umich.edu } 3245341Sstever@gmail.com else { 3255742Snate@binkert.org if (getcwd((char *)buf.bufferPtr(), size) != NULL) { 3265742Snate@binkert.org result = strlen((char *)buf.bufferPtr()); 3275742Snate@binkert.org } 3285742Snate@binkert.org else { 3295742Snate@binkert.org result = -1; 3304762Snate@binkert.org } 3315742Snate@binkert.org } 3325742Snate@binkert.org 33311984Sgabeblack@google.com buf.copyOut(tc->getMemPort()); 3347722Sgblack@eecs.umich.edu 3355742Snate@binkert.org return (result == -1) ? -errno : result; 3365742Snate@binkert.org} 3375742Snate@binkert.org 3389930Sandreas.hansson@arm.com 3399930Sandreas.hansson@arm.comSyscallReturn 3409930Sandreas.hansson@arm.comreadlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3419930Sandreas.hansson@arm.com{ 3429930Sandreas.hansson@arm.com string path; 3435742Snate@binkert.org 3448242Sbradley.danofsky@amd.com int index = 0; 3458242Sbradley.danofsky@amd.com if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 3468242Sbradley.danofsky@amd.com return (TheISA::IntReg)-EFAULT; 3478242Sbradley.danofsky@amd.com 3485341Sstever@gmail.com // Adjust path for current working directory 3495742Snate@binkert.org path = p->fullPath(path); 3507722Sgblack@eecs.umich.edu 3514773Snate@binkert.org Addr bufPtr = p->getSyscallArg(tc, index); 3526108Snate@binkert.org size_t bufsiz = p->getSyscallArg(tc, index); 3531858SN/A 3541085SN/A BufferArg buf(bufPtr, bufsiz); 3556658Snate@binkert.org 3566658Snate@binkert.org int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); 3577673Snate@binkert.org 3586658Snate@binkert.org buf.copyOut(tc->getMemPort()); 3596658Snate@binkert.org 36011308Santhony.gutierrez@amd.com return (result == -1) ? -errno : result; 3616658Snate@binkert.org} 36211308Santhony.gutierrez@amd.com 3636658Snate@binkert.orgSyscallReturn 3646658Snate@binkert.orgunlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 3657673Snate@binkert.org{ 3667673Snate@binkert.org string path; 3677673Snate@binkert.org 3687673Snate@binkert.org int index = 0; 3697673Snate@binkert.org if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 3707673Snate@binkert.org return (TheISA::IntReg)-EFAULT; 3717673Snate@binkert.org 37210467Sandreas.hansson@arm.com // Adjust path for current working directory 3736658Snate@binkert.org path = p->fullPath(path); 3747673Snate@binkert.org 37510467Sandreas.hansson@arm.com int result = unlink(path.c_str()); 37610467Sandreas.hansson@arm.com return (result == -1) ? -errno : result; 37710467Sandreas.hansson@arm.com} 37810467Sandreas.hansson@arm.com 37910467Sandreas.hansson@arm.com 38010467Sandreas.hansson@arm.comSyscallReturn 38110467Sandreas.hansson@arm.commkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 38210467Sandreas.hansson@arm.com{ 38310467Sandreas.hansson@arm.com string path; 38410467Sandreas.hansson@arm.com 38510467Sandreas.hansson@arm.com int index = 0; 3867673Snate@binkert.org if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 3877673Snate@binkert.org return (TheISA::IntReg)-EFAULT; 3887673Snate@binkert.org 3897673Snate@binkert.org // Adjust path for current working directory 3907673Snate@binkert.org path = p->fullPath(path); 3919048SAli.Saidi@ARM.com 3927673Snate@binkert.org mode_t mode = p->getSyscallArg(tc, index); 3937673Snate@binkert.org 3947673Snate@binkert.org int result = mkdir(path.c_str(), mode); 3957673Snate@binkert.org return (result == -1) ? -errno : result; 3966658Snate@binkert.org} 3977756SAli.Saidi@ARM.com 3987816Ssteve.reinhardt@amd.comSyscallReturn 3996658Snate@binkert.orgrenameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 40011308Santhony.gutierrez@amd.com{ 40111308Santhony.gutierrez@amd.com string old_name; 40211308Santhony.gutierrez@amd.com 40311308Santhony.gutierrez@amd.com int index = 0; 40411308Santhony.gutierrez@amd.com if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, index))) 40511308Santhony.gutierrez@amd.com return -EFAULT; 40611308Santhony.gutierrez@amd.com 40711308Santhony.gutierrez@amd.com string new_name; 40811308Santhony.gutierrez@amd.com 40911308Santhony.gutierrez@amd.com if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, index))) 41011308Santhony.gutierrez@amd.com return -EFAULT; 41111308Santhony.gutierrez@amd.com 41211308Santhony.gutierrez@amd.com // Adjust path for current working directory 41311308Santhony.gutierrez@amd.com old_name = p->fullPath(old_name); 41411308Santhony.gutierrez@amd.com new_name = p->fullPath(new_name); 41511308Santhony.gutierrez@amd.com 41611308Santhony.gutierrez@amd.com int64_t result = rename(old_name.c_str(), new_name.c_str()); 41711308Santhony.gutierrez@amd.com return (result == -1) ? -errno : result; 41811308Santhony.gutierrez@amd.com} 41911308Santhony.gutierrez@amd.com 42011308Santhony.gutierrez@amd.comSyscallReturn 42111308Santhony.gutierrez@amd.comtruncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 42211308Santhony.gutierrez@amd.com{ 42311308Santhony.gutierrez@amd.com string path; 42411308Santhony.gutierrez@amd.com 42511308Santhony.gutierrez@amd.com int index = 0; 42611308Santhony.gutierrez@amd.com if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 42711308Santhony.gutierrez@amd.com return -EFAULT; 42811308Santhony.gutierrez@amd.com 42911308Santhony.gutierrez@amd.com off_t length = p->getSyscallArg(tc, index); 43011308Santhony.gutierrez@amd.com 43111308Santhony.gutierrez@amd.com // Adjust path for current working directory 43211308Santhony.gutierrez@amd.com path = p->fullPath(path); 43311308Santhony.gutierrez@amd.com 43411308Santhony.gutierrez@amd.com int result = truncate(path.c_str(), length); 43511308Santhony.gutierrez@amd.com return (result == -1) ? -errno : result; 43611308Santhony.gutierrez@amd.com} 43711308Santhony.gutierrez@amd.com 43811308Santhony.gutierrez@amd.comSyscallReturn 43911308Santhony.gutierrez@amd.comftruncateFunc(SyscallDesc *desc, int num, 44011308Santhony.gutierrez@amd.com LiveProcess *process, ThreadContext *tc) 44111308Santhony.gutierrez@amd.com{ 44211308Santhony.gutierrez@amd.com int index = 0; 44311308Santhony.gutierrez@amd.com int fd = process->sim_fd(process->getSyscallArg(tc, index)); 44411308Santhony.gutierrez@amd.com 4454382Sbinkertn@umich.edu if (fd < 0) 4464382Sbinkertn@umich.edu return -EBADF; 4474762Snate@binkert.org 4484762Snate@binkert.org off_t length = process->getSyscallArg(tc, index); 4494762Snate@binkert.org 4506654Snate@binkert.org int result = ftruncate(fd, length); 4516654Snate@binkert.org return (result == -1) ? -errno : result; 4525517Snate@binkert.org} 4535517Snate@binkert.org 4545517Snate@binkert.orgSyscallReturn 4555517Snate@binkert.orgtruncate64Func(SyscallDesc *desc, int num, 4565517Snate@binkert.org LiveProcess *process, ThreadContext *tc) 4575517Snate@binkert.org{ 4585517Snate@binkert.org int index = 0; 4595517Snate@binkert.org string path; 4605517Snate@binkert.org 4615517Snate@binkert.org if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, index))) 4625517Snate@binkert.org return -EFAULT; 4635517Snate@binkert.org 4645517Snate@binkert.org int64_t length = process->getSyscallArg(tc, index, 64); 4655517Snate@binkert.org 4665517Snate@binkert.org // Adjust path for current working directory 4675517Snate@binkert.org path = process->fullPath(path); 4685517Snate@binkert.org 4696654Snate@binkert.org#if NO_STAT64 4705517Snate@binkert.org int result = truncate(path.c_str(), length); 4715517Snate@binkert.org#else 4725517Snate@binkert.org int result = truncate64(path.c_str(), length); 4735517Snate@binkert.org#endif 4745517Snate@binkert.org return (result == -1) ? -errno : result; 47511802Sandreas.sandberg@arm.com} 4765517Snate@binkert.org 4775517Snate@binkert.orgSyscallReturn 4786143Snate@binkert.orgftruncate64Func(SyscallDesc *desc, int num, 4796654Snate@binkert.org LiveProcess *process, ThreadContext *tc) 4805517Snate@binkert.org{ 4815517Snate@binkert.org int index = 0; 4825517Snate@binkert.org int fd = process->sim_fd(process->getSyscallArg(tc, index)); 4835517Snate@binkert.org 4845517Snate@binkert.org if (fd < 0) 4855517Snate@binkert.org return -EBADF; 4865517Snate@binkert.org 4875517Snate@binkert.org int64_t length = process->getSyscallArg(tc, index, 64); 4885517Snate@binkert.org 4895517Snate@binkert.org#if NO_STAT64 4905517Snate@binkert.org int result = ftruncate(fd, length); 4915517Snate@binkert.org#else 4925517Snate@binkert.org int result = ftruncate64(fd, length); 4935517Snate@binkert.org#endif 4946654Snate@binkert.org return (result == -1) ? -errno : result; 4956654Snate@binkert.org} 4965517Snate@binkert.org 4975517Snate@binkert.orgSyscallReturn 4986143Snate@binkert.orgumaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 4996143Snate@binkert.org{ 5006143Snate@binkert.org // Letting the simulated program change the simulator's umask seems like 5016727Ssteve.reinhardt@amd.com // a bad idea. Compromise by just returning the current umask but not 5025517Snate@binkert.org // changing anything. 5036727Ssteve.reinhardt@amd.com mode_t oldMask = umask(0); 5045517Snate@binkert.org umask(oldMask); 5055517Snate@binkert.org return (int)oldMask; 5065517Snate@binkert.org} 5076654Snate@binkert.org 5086654Snate@binkert.orgSyscallReturn 5097673Snate@binkert.orgchownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 5106654Snate@binkert.org{ 5116654Snate@binkert.org string path; 5126654Snate@binkert.org 5136654Snate@binkert.org int index = 0; 5145517Snate@binkert.org if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) 5155517Snate@binkert.org return -EFAULT; 5165517Snate@binkert.org 5176143Snate@binkert.org /* XXX endianess */ 5185517Snate@binkert.org uint32_t owner = p->getSyscallArg(tc, index); 5194762Snate@binkert.org uid_t hostOwner = owner; 5205517Snate@binkert.org uint32_t group = p->getSyscallArg(tc, index); 5215517Snate@binkert.org gid_t hostGroup = group; 5226143Snate@binkert.org 5236143Snate@binkert.org // Adjust path for current working directory 5245517Snate@binkert.org path = p->fullPath(path); 5255517Snate@binkert.org 5265517Snate@binkert.org int result = chown(path.c_str(), hostOwner, hostGroup); 5275517Snate@binkert.org return (result == -1) ? -errno : result; 5285517Snate@binkert.org} 5295517Snate@binkert.org 5305517Snate@binkert.orgSyscallReturn 5315517Snate@binkert.orgfchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 5325517Snate@binkert.org{ 5336143Snate@binkert.org int index = 0; 5345517Snate@binkert.org int fd = process->sim_fd(process->getSyscallArg(tc, index)); 5356654Snate@binkert.org 5366654Snate@binkert.org if (fd < 0) 5376654Snate@binkert.org return -EBADF; 5386654Snate@binkert.org 5396654Snate@binkert.org /* XXX endianess */ 5406654Snate@binkert.org uint32_t owner = process->getSyscallArg(tc, index); 5414762Snate@binkert.org uid_t hostOwner = owner; 5424762Snate@binkert.org uint32_t group = process->getSyscallArg(tc, index); 5434762Snate@binkert.org gid_t hostGroup = group; 5444762Snate@binkert.org 5454762Snate@binkert.org int result = fchown(fd, hostOwner, hostGroup); 5467675Snate@binkert.org return (result == -1) ? -errno : result; 54710584Sandreas.hansson@arm.com} 5484762Snate@binkert.org 5494762Snate@binkert.org 5504762Snate@binkert.orgSyscallReturn 5514762Snate@binkert.orgdupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 5524382Sbinkertn@umich.edu{ 5534382Sbinkertn@umich.edu int index = 0; 5545517Snate@binkert.org int fd = process->sim_fd(process->getSyscallArg(tc, index)); 5556654Snate@binkert.org if (fd < 0) 5565517Snate@binkert.org return -EBADF; 5578126Sgblack@eecs.umich.edu 5586654Snate@binkert.org Process::FdMap *fdo = process->sim_fd_obj(fd); 5597673Snate@binkert.org 5606654Snate@binkert.org int result = dup(fd); 56111802Sandreas.sandberg@arm.com return (result == -1) ? -errno : 5626654Snate@binkert.org process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false); 5636654Snate@binkert.org} 5646654Snate@binkert.org 5656654Snate@binkert.org 56611802Sandreas.sandberg@arm.comSyscallReturn 5676669Snate@binkert.orgfcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, 56811802Sandreas.sandberg@arm.com ThreadContext *tc) 5696669Snate@binkert.org{ 5706669Snate@binkert.org int index = 0; 5716669Snate@binkert.org int fd = process->getSyscallArg(tc, index); 5726669Snate@binkert.org 5736654Snate@binkert.org if (fd < 0 || process->sim_fd(fd) < 0) 5747673Snate@binkert.org return -EBADF; 5755517Snate@binkert.org 5768126Sgblack@eecs.umich.edu int cmd = process->getSyscallArg(tc, index); 5775798Snate@binkert.org switch (cmd) { 5787756SAli.Saidi@ARM.com case 0: // F_DUPFD 5797816Ssteve.reinhardt@amd.com // if we really wanted to support this, we'd need to do it 5805798Snate@binkert.org // in the target fd space. 5815798Snate@binkert.org warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); 5825517Snate@binkert.org return -EMFILE; 5835517Snate@binkert.org 5847673Snate@binkert.org case 1: // F_GETFD (get close-on-exec flag) 5855517Snate@binkert.org case 2: // F_SETFD (set close-on-exec flag) 5865517Snate@binkert.org return 0; 5877673Snate@binkert.org 5887673Snate@binkert.org case 3: // F_GETFL (get file flags) 5895517Snate@binkert.org case 4: // F_SETFL (set file flags) 5905798Snate@binkert.org // not sure if this is totally valid, but we'll pass it through 5915798Snate@binkert.org // to the underlying OS 5928333Snate@binkert.org warn("fcntl(%d, %d) passed through to host\n", fd, cmd); 5937816Ssteve.reinhardt@amd.com return fcntl(process->sim_fd(fd), cmd); 5945798Snate@binkert.org // return 0; 5955798Snate@binkert.org 5964762Snate@binkert.org case 7: // F_GETLK (get lock) 5974762Snate@binkert.org case 8: // F_SETLK (set lock) 5984762Snate@binkert.org case 9: // F_SETLKW (set lock and wait) 5994762Snate@binkert.org // don't mess with file locking... just act like it's OK 6004762Snate@binkert.org warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); 6018596Ssteve.reinhardt@amd.com return 0; 6025517Snate@binkert.org 6035517Snate@binkert.org default: 60411997Sgabeblack@google.com warn("Unknown fcntl command %d\n", cmd); 6055517Snate@binkert.org return 0; 6065517Snate@binkert.org } 6077673Snate@binkert.org} 6088596Ssteve.reinhardt@amd.com 6097673Snate@binkert.orgSyscallReturn 6105517Snate@binkert.orgfcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, 61110458Sandreas.hansson@arm.com ThreadContext *tc) 61210458Sandreas.hansson@arm.com{ 61310458Sandreas.hansson@arm.com int index = 0; 61410458Sandreas.hansson@arm.com int fd = process->getSyscallArg(tc, index); 61510458Sandreas.hansson@arm.com 61610458Sandreas.hansson@arm.com if (fd < 0 || process->sim_fd(fd) < 0) 61710458Sandreas.hansson@arm.com return -EBADF; 61810458Sandreas.hansson@arm.com 61910458Sandreas.hansson@arm.com int cmd = process->getSyscallArg(tc, index); 62010458Sandreas.hansson@arm.com switch (cmd) { 62110458Sandreas.hansson@arm.com case 33: //F_GETLK64 62210458Sandreas.hansson@arm.com warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); 6235517Snate@binkert.org return -EMFILE; 62411996Sgabeblack@google.com 6255517Snate@binkert.org case 34: // F_SETLK64 62611997Sgabeblack@google.com case 35: // F_SETLKW64 62711996Sgabeblack@google.com warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd); 6285517Snate@binkert.org return -EMFILE; 6295517Snate@binkert.org 6307673Snate@binkert.org default: 6317673Snate@binkert.org // not sure if this is totally valid, but we'll pass it through 63211996Sgabeblack@google.com // to the underlying OS 63311988Sandreas.sandberg@arm.com warn("fcntl64(%d, %d) passed through to host\n", fd, cmd); 6347673Snate@binkert.org return fcntl(process->sim_fd(fd), cmd); 6355517Snate@binkert.org // return 0; 6368596Ssteve.reinhardt@amd.com } 6375517Snate@binkert.org} 6385517Snate@binkert.org 63911997Sgabeblack@google.comSyscallReturn 6405517Snate@binkert.orgpipePseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6415517Snate@binkert.org ThreadContext *tc) 6427673Snate@binkert.org{ 6437673Snate@binkert.org int fds[2], sim_fds[2]; 6447673Snate@binkert.org int pipe_retval = pipe(fds); 6455517Snate@binkert.org 64611988Sandreas.sandberg@arm.com if (pipe_retval < 0) { 64711997Sgabeblack@google.com // error 6488596Ssteve.reinhardt@amd.com return pipe_retval; 6498596Ssteve.reinhardt@amd.com } 6508596Ssteve.reinhardt@amd.com 65111988Sandreas.sandberg@arm.com sim_fds[0] = process->alloc_fd(fds[0], "PIPE-READ", O_WRONLY, -1, true); 6528596Ssteve.reinhardt@amd.com sim_fds[1] = process->alloc_fd(fds[1], "PIPE-WRITE", O_RDONLY, -1, true); 6538596Ssteve.reinhardt@amd.com 6548596Ssteve.reinhardt@amd.com process->setReadPipeSource(sim_fds[0], sim_fds[1]); 6554762Snate@binkert.org // Alpha Linux convention for pipe() is that fd[0] is returned as 6566143Snate@binkert.org // the return value of the function, and fd[1] is returned in r20. 6576143Snate@binkert.org tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); 6586143Snate@binkert.org return sim_fds[0]; 6594762Snate@binkert.org} 6604762Snate@binkert.org 6614762Snate@binkert.org 6627756SAli.Saidi@ARM.comSyscallReturn 6638596Ssteve.reinhardt@amd.comgetpidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6644762Snate@binkert.org ThreadContext *tc) 6654762Snate@binkert.org{ 66610458Sandreas.hansson@arm.com // Make up a PID. There's no interprocess communication in 66710458Sandreas.hansson@arm.com // fake_syscall mode, so there's no way for a process to know it's 66810458Sandreas.hansson@arm.com // not getting a unique value. 66910458Sandreas.hansson@arm.com 67010458Sandreas.hansson@arm.com tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); 67110458Sandreas.hansson@arm.com return process->pid(); 67210458Sandreas.hansson@arm.com} 67310458Sandreas.hansson@arm.com 67410458Sandreas.hansson@arm.com 67510458Sandreas.hansson@arm.comSyscallReturn 67610458Sandreas.hansson@arm.comgetuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 67710458Sandreas.hansson@arm.com ThreadContext *tc) 67810458Sandreas.hansson@arm.com{ 67910458Sandreas.hansson@arm.com // Make up a UID and EUID... it shouldn't matter, and we want the 68010458Sandreas.hansson@arm.com // simulation to be deterministic. 68110458Sandreas.hansson@arm.com 68210458Sandreas.hansson@arm.com // EUID goes in r20. 68310458Sandreas.hansson@arm.com tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID 68410458Sandreas.hansson@arm.com return process->uid(); // UID 68510458Sandreas.hansson@arm.com} 68610458Sandreas.hansson@arm.com 68710458Sandreas.hansson@arm.com 68810458Sandreas.hansson@arm.comSyscallReturn 68910458Sandreas.hansson@arm.comgetgidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 69010458Sandreas.hansson@arm.com ThreadContext *tc) 69110458Sandreas.hansson@arm.com{ 69210458Sandreas.hansson@arm.com // Get current group ID. EGID goes in r20. 69310458Sandreas.hansson@arm.com tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID 69410458Sandreas.hansson@arm.com return process->gid(); 69510458Sandreas.hansson@arm.com} 69610458Sandreas.hansson@arm.com 69710458Sandreas.hansson@arm.com 69810458Sandreas.hansson@arm.comSyscallReturn 69910458Sandreas.hansson@arm.comsetuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 70010458Sandreas.hansson@arm.com ThreadContext *tc) 70110458Sandreas.hansson@arm.com{ 70210458Sandreas.hansson@arm.com // can't fathom why a benchmark would call this. 70310458Sandreas.hansson@arm.com int index = 0; 70410458Sandreas.hansson@arm.com warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); 70510458Sandreas.hansson@arm.com return 0; 70610458Sandreas.hansson@arm.com} 70710458Sandreas.hansson@arm.com 70810458Sandreas.hansson@arm.comSyscallReturn 70910458Sandreas.hansson@arm.comgetpidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 71010458Sandreas.hansson@arm.com ThreadContext *tc) 71110458Sandreas.hansson@arm.com{ 71210458Sandreas.hansson@arm.com // Make up a PID. There's no interprocess communication in 71310458Sandreas.hansson@arm.com // fake_syscall mode, so there's no way for a process to know it's 71410458Sandreas.hansson@arm.com // not getting a unique value. 71510584Sandreas.hansson@arm.com 71610458Sandreas.hansson@arm.com tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID 71710458Sandreas.hansson@arm.com return process->pid(); 71810458Sandreas.hansson@arm.com} 71910458Sandreas.hansson@arm.com 72010458Sandreas.hansson@arm.comSyscallReturn 7214762Snate@binkert.orggetppidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7226143Snate@binkert.org ThreadContext *tc) 7236143Snate@binkert.org{ 7246143Snate@binkert.org return process->ppid(); 7254762Snate@binkert.org} 7264762Snate@binkert.org 72711996Sgabeblack@google.comSyscallReturn 7287816Ssteve.reinhardt@amd.comgetuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7294762Snate@binkert.org ThreadContext *tc) 7304762Snate@binkert.org{ 7314762Snate@binkert.org return process->uid(); // UID 7324762Snate@binkert.org} 7337756SAli.Saidi@ARM.com 7348596Ssteve.reinhardt@amd.comSyscallReturn 7354762Snate@binkert.orggeteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7364762Snate@binkert.org ThreadContext *tc) 73711988Sandreas.sandberg@arm.com{ 73811988Sandreas.sandberg@arm.com return process->euid(); // UID 73911988Sandreas.sandberg@arm.com} 74011988Sandreas.sandberg@arm.com 74111988Sandreas.sandberg@arm.comSyscallReturn 74211988Sandreas.sandberg@arm.comgetgidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 74311988Sandreas.sandberg@arm.com ThreadContext *tc) 74411988Sandreas.sandberg@arm.com{ 74511988Sandreas.sandberg@arm.com return process->gid(); 74611988Sandreas.sandberg@arm.com} 74711988Sandreas.sandberg@arm.com 7484382Sbinkertn@umich.eduSyscallReturn 7499396Sandreas.hansson@arm.comgetegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7509396Sandreas.hansson@arm.com ThreadContext *tc) 7519396Sandreas.hansson@arm.com{ 7529396Sandreas.hansson@arm.com return process->egid(); 7539396Sandreas.hansson@arm.com} 7549396Sandreas.hansson@arm.com 7559396Sandreas.hansson@arm.com 7569396Sandreas.hansson@arm.comSyscallReturn 7579396Sandreas.hansson@arm.comcloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7589396Sandreas.hansson@arm.com ThreadContext *tc) 7599396Sandreas.hansson@arm.com{ 7609396Sandreas.hansson@arm.com int index = 0; 7619396Sandreas.hansson@arm.com IntReg flags = process->getSyscallArg(tc, index); 76212302Sgabeblack@google.com IntReg newStack = process->getSyscallArg(tc, index); 7639396Sandreas.hansson@arm.com 7649396Sandreas.hansson@arm.com DPRINTF(SyscallVerbose, "In sys_clone:\n"); 7659396Sandreas.hansson@arm.com DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); 7669396Sandreas.hansson@arm.com DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); 7678232Snate@binkert.org 7688232Snate@binkert.org 7698232Snate@binkert.org if (flags != 0x10f00) { 7708232Snate@binkert.org warn("This sys_clone implementation assumes flags " 7718232Snate@binkert.org "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " 7726229Snate@binkert.org "(0x10f00), and may not work correctly with given flags " 77310455SCurtis.Dunham@arm.com "0x%llx\n", flags); 7746229Snate@binkert.org } 77510455SCurtis.Dunham@arm.com 77610455SCurtis.Dunham@arm.com ThreadContext* ctc; // child thread context 77710455SCurtis.Dunham@arm.com if ( ( ctc = process->findFreeContext() ) != NULL ) { 7785517Snate@binkert.org DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); 7795517Snate@binkert.org 7807673Snate@binkert.org ctc->clearArchRegs(); 7815517Snate@binkert.org 78210455SCurtis.Dunham@arm.com // Arch-specific cloning code 7835517Snate@binkert.org #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA 7845517Snate@binkert.org // Cloning the misc. regs for these archs is enough 7858232Snate@binkert.org TheISA::copyMiscRegs(tc, ctc); 78610455SCurtis.Dunham@arm.com #elif THE_ISA == SPARC_ISA 78710455SCurtis.Dunham@arm.com TheISA::copyRegs(tc, ctc); 78810455SCurtis.Dunham@arm.com 7897673Snate@binkert.org // TODO: Explain what this code actually does :-) 7907673Snate@binkert.org ctc->setIntReg(NumIntArchRegs + 6, 0); 79110455SCurtis.Dunham@arm.com ctc->setIntReg(NumIntArchRegs + 4, 0); 79210455SCurtis.Dunham@arm.com ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 79310455SCurtis.Dunham@arm.com ctc->setIntReg(NumIntArchRegs + 5, NWindows); 7945517Snate@binkert.org ctc->setMiscReg(MISCREG_CWP, 0); 79510455SCurtis.Dunham@arm.com ctc->setIntReg(NumIntArchRegs + 7, 0); 79610455SCurtis.Dunham@arm.com ctc->setMiscRegNoEffect(MISCREG_TL, 0); 79710455SCurtis.Dunham@arm.com ctc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); 79810455SCurtis.Dunham@arm.com 79910455SCurtis.Dunham@arm.com for (int y = 8; y < 32; y++) 80010455SCurtis.Dunham@arm.com ctc->setIntReg(y, tc->readIntReg(y)); 80110455SCurtis.Dunham@arm.com #else 80210455SCurtis.Dunham@arm.com fatal("sys_clone is not implemented for this ISA\n"); 80310685Sandreas.hansson@arm.com #endif 80410455SCurtis.Dunham@arm.com 80510685Sandreas.hansson@arm.com // Set up stack register 80610455SCurtis.Dunham@arm.com ctc->setIntReg(TheISA::StackPointerReg, newStack); 8075517Snate@binkert.org 80810455SCurtis.Dunham@arm.com // Set up syscall return values in parent and child 8098232Snate@binkert.org ctc->setIntReg(ReturnValueReg, 0); // return value, child 8108232Snate@binkert.org 8115517Snate@binkert.org // Alpha needs SyscallSuccessReg=0 in child 8127673Snate@binkert.org #if THE_ISA == ALPHA_ISA 8135517Snate@binkert.org ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 8148232Snate@binkert.org #endif 8158232Snate@binkert.org 8165517Snate@binkert.org // In SPARC/Linux, clone returns 0 on pseudo-return register if 8178232Snate@binkert.org // parent, non-zero if child 8188232Snate@binkert.org #if THE_ISA == SPARC_ISA 8198232Snate@binkert.org tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 8207673Snate@binkert.org ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 8215517Snate@binkert.org #endif 8225517Snate@binkert.org 8237673Snate@binkert.org ctc->setPC(tc->readNextPC()); 8245517Snate@binkert.org ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); 82510455SCurtis.Dunham@arm.com ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst)); 8265517Snate@binkert.org 8275517Snate@binkert.org ctc->activate(); 8288232Snate@binkert.org 8298232Snate@binkert.org // Should return nonzero child TID in parent's syscall return register, 8305517Snate@binkert.org // but for our pthread library any non-zero value will work 8318232Snate@binkert.org return 1; 8328232Snate@binkert.org } else { 8335517Snate@binkert.org fatal("Called sys_clone, but no unallocated thread contexts found!\n"); 8348232Snate@binkert.org return 0; 8358232Snate@binkert.org } 8368232Snate@binkert.org} 8375517Snate@binkert.org 8388232Snate@binkert.org