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