1360SN/A/*
21458SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
3360SN/A * All rights reserved.
4360SN/A *
5360SN/A * Redistribution and use in source and binary forms, with or without
6360SN/A * modification, are permitted provided that the following conditions are
7360SN/A * met: redistributions of source code must retain the above copyright
8360SN/A * notice, this list of conditions and the following disclaimer;
9360SN/A * redistributions in binary form must reproduce the above copyright
10360SN/A * notice, this list of conditions and the following disclaimer in the
11360SN/A * documentation and/or other materials provided with the distribution;
12360SN/A * neither the name of the copyright holders nor the names of its
13360SN/A * contributors may be used to endorse or promote products derived from
14360SN/A * this software without specific prior written permission.
15360SN/A *
16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
292665Ssaidi@eecs.umich.edu *          Ali Saidi
30360SN/A */
31360SN/A
3211793Sbrandon.potter@amd.com#include "sim/syscall_emul.hh"
3311793Sbrandon.potter@amd.com
342093SN/A#include <fcntl.h>
3513479Santhony.gutierrez@amd.com#include <sys/syscall.h>
36360SN/A#include <unistd.h>
37360SN/A
3811911SBrandon.Potter@amd.com#include <csignal>
396712Snate@binkert.org#include <iostream>
4013031Sbrandon.potter@amd.com#include <mutex>
41360SN/A#include <string>
42360SN/A
437680Sgblack@eecs.umich.edu#include "arch/utility.hh"
442474SN/A#include "base/chunk_generator.hh"
45360SN/A#include "base/trace.hh"
466658Snate@binkert.org#include "config/the_isa.hh"
472680Sktlim@umich.edu#include "cpu/thread_context.hh"
4812716Smichael.lebeane@amd.com#include "dev/net/dist_iface.hh"
492474SN/A#include "mem/page_table.hh"
5013031Sbrandon.potter@amd.com#include "sim/byteswap.hh"
51360SN/A#include "sim/process.hh"
528229Snate@binkert.org#include "sim/sim_exit.hh"
5311794Sbrandon.potter@amd.com#include "sim/syscall_debug_macros.hh"
5411794Sbrandon.potter@amd.com#include "sim/syscall_desc.hh"
556029Ssteve.reinhardt@amd.com#include "sim/system.hh"
56360SN/A
57360SN/Ausing namespace std;
582107SN/Ausing namespace TheISA;
59360SN/A
6013933Sbrandon.potter@amd.comvoid
6113933Sbrandon.potter@amd.comwarnUnsupportedOS(std::string syscall_name)
6213933Sbrandon.potter@amd.com{
6313933Sbrandon.potter@amd.com    warn("Cannot invoke %s on host operating system.", syscall_name);
6413933Sbrandon.potter@amd.com}
6513933Sbrandon.potter@amd.com
661450SN/ASyscallReturn
6713995Sbrandon.potter@amd.comunimplementedFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
68360SN/A{
6911794Sbrandon.potter@amd.com    fatal("syscall %s (#%d) unimplemented.", desc->name(), callnum);
702484SN/A
712484SN/A    return 1;
72360SN/A}
73360SN/A
74360SN/A
751450SN/ASyscallReturn
7613995Sbrandon.potter@amd.comignoreFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
77360SN/A{
7811794Sbrandon.potter@amd.com    if (desc->needWarning()) {
7911794Sbrandon.potter@amd.com        warn("ignoring syscall %s(...)%s", desc->name(), desc->warnOnce() ?
8011794Sbrandon.potter@amd.com             "\n      (further warnings will be suppressed)" : "");
8110831Ssteve.reinhardt@amd.com    }
82360SN/A
838149SChris.Emmons@ARM.com    return 0;
848149SChris.Emmons@ARM.com}
858149SChris.Emmons@ARM.com
8611886Sbrandon.potter@amd.comstatic void
8711911SBrandon.Potter@amd.comexitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
8811886Sbrandon.potter@amd.com{
8911911SBrandon.Potter@amd.com    // Clear value at address pointed to by thread's childClearTID field.
9011911SBrandon.Potter@amd.com    BufferArg ctidBuf(addr, sizeof(long));
9111911SBrandon.Potter@amd.com    long *ctid = (long *)ctidBuf.bufferPtr();
9211911SBrandon.Potter@amd.com    *ctid = 0;
9314024Sgabeblack@google.com    ctidBuf.copyOut(tc->getVirtProxy());
9411886Sbrandon.potter@amd.com
9511911SBrandon.Potter@amd.com    FutexMap &futex_map = tc->getSystemPtr()->futexMap;
9611911SBrandon.Potter@amd.com    // Wake one of the waiting threads.
9711911SBrandon.Potter@amd.com    futex_map.wakeup(addr, tgid, 1);
9811911SBrandon.Potter@amd.com}
9911911SBrandon.Potter@amd.com
10011911SBrandon.Potter@amd.comstatic SyscallReturn
10113995Sbrandon.potter@amd.comexitImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool group)
10211911SBrandon.Potter@amd.com{
10311911SBrandon.Potter@amd.com    int index = 0;
10413995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
10511911SBrandon.Potter@amd.com    int status = p->getSyscallArg(tc, index);
10611911SBrandon.Potter@amd.com
10711911SBrandon.Potter@amd.com    System *sys = tc->getSystemPtr();
10811911SBrandon.Potter@amd.com
10911911SBrandon.Potter@amd.com    if (group)
11011911SBrandon.Potter@amd.com        *p->exitGroup = true;
11111911SBrandon.Potter@amd.com
11211911SBrandon.Potter@amd.com    if (p->childClearTID)
11311911SBrandon.Potter@amd.com        exitFutexWake(tc, p->childClearTID, p->tgid());
11411911SBrandon.Potter@amd.com
11511911SBrandon.Potter@amd.com    bool last_thread = true;
11611911SBrandon.Potter@amd.com    Process *parent = nullptr, *tg_lead = nullptr;
11711911SBrandon.Potter@amd.com    for (int i = 0; last_thread && i < sys->numContexts(); i++) {
11811911SBrandon.Potter@amd.com        Process *walk;
11911911SBrandon.Potter@amd.com        if (!(walk = sys->threadContexts[i]->getProcessPtr()))
12011911SBrandon.Potter@amd.com            continue;
12111911SBrandon.Potter@amd.com
12211911SBrandon.Potter@amd.com        /**
12311911SBrandon.Potter@amd.com         * Threads in a thread group require special handing. For instance,
12411911SBrandon.Potter@amd.com         * we send the SIGCHLD signal so that it appears that it came from
12511911SBrandon.Potter@amd.com         * the head of the group. We also only delete file descriptors if
12611911SBrandon.Potter@amd.com         * we are the last thread in the thread group.
12711911SBrandon.Potter@amd.com         */
12811911SBrandon.Potter@amd.com        if (walk->pid() == p->tgid())
12911911SBrandon.Potter@amd.com            tg_lead = walk;
13011911SBrandon.Potter@amd.com
13113644Sqtt2@cornell.edu        if ((sys->threadContexts[i]->status() != ThreadContext::Halted) &&
13213644Sqtt2@cornell.edu            (sys->threadContexts[i]->status() != ThreadContext::Halting) &&
13313644Sqtt2@cornell.edu            (walk != p)) {
13411911SBrandon.Potter@amd.com            /**
13511911SBrandon.Potter@amd.com             * Check if we share thread group with the pointer; this denotes
13611911SBrandon.Potter@amd.com             * that we are not the last thread active in the thread group.
13711911SBrandon.Potter@amd.com             * Note that setting this to false also prevents further
13811911SBrandon.Potter@amd.com             * iterations of the loop.
13911911SBrandon.Potter@amd.com             */
14013644Sqtt2@cornell.edu            if (walk->tgid() == p->tgid()) {
14113644Sqtt2@cornell.edu                /**
14213644Sqtt2@cornell.edu                 * If p is trying to exit_group and both walk and p are in
14313644Sqtt2@cornell.edu                 * the same thread group (i.e., sharing the same tgid),
14413644Sqtt2@cornell.edu                 * we need to halt walk's thread context. After all threads
14513644Sqtt2@cornell.edu                 * except p are halted, p becomes the last thread in the
14613644Sqtt2@cornell.edu                 * group.
14713644Sqtt2@cornell.edu                 *
14813644Sqtt2@cornell.edu                 * If p is not doing exit_group and there exists another
14913644Sqtt2@cornell.edu                 * active thread context in the group, last_thread is
15013644Sqtt2@cornell.edu                 * set to false to prevent the parent thread from killing
15113644Sqtt2@cornell.edu                 * all threads in the group.
15213644Sqtt2@cornell.edu                 */
15313644Sqtt2@cornell.edu                if (*(p->exitGroup)) {
15413644Sqtt2@cornell.edu                    sys->threadContexts[i]->halt();
15513644Sqtt2@cornell.edu                } else {
15613644Sqtt2@cornell.edu                    last_thread = false;
15713644Sqtt2@cornell.edu                }
15813644Sqtt2@cornell.edu            }
15911911SBrandon.Potter@amd.com
16011911SBrandon.Potter@amd.com            /**
16111911SBrandon.Potter@amd.com             * A corner case exists which involves execve(). After execve(),
16211911SBrandon.Potter@amd.com             * the execve will enable SIGCHLD in the process. The problem
16311911SBrandon.Potter@amd.com             * occurs when the exiting process is the root process in the
16411911SBrandon.Potter@amd.com             * system; there is no parent to receive the signal. We obviate
16511911SBrandon.Potter@amd.com             * this problem by setting the root process' ppid to zero in the
16611911SBrandon.Potter@amd.com             * Python configuration files. We really should handle the
16711911SBrandon.Potter@amd.com             * root/execve specific case more gracefully.
16811911SBrandon.Potter@amd.com             */
16911911SBrandon.Potter@amd.com            if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
17011911SBrandon.Potter@amd.com                parent = walk;
17111886Sbrandon.potter@amd.com        }
17211886Sbrandon.potter@amd.com    }
17311911SBrandon.Potter@amd.com
17411911SBrandon.Potter@amd.com    if (last_thread) {
17511911SBrandon.Potter@amd.com        if (parent) {
17611911SBrandon.Potter@amd.com            assert(tg_lead);
17711911SBrandon.Potter@amd.com            sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
17811911SBrandon.Potter@amd.com        }
17911911SBrandon.Potter@amd.com
18011911SBrandon.Potter@amd.com        /**
18111911SBrandon.Potter@amd.com         * Run though FD array of the exiting process and close all file
18211911SBrandon.Potter@amd.com         * descriptors except for the standard file descriptors.
18311911SBrandon.Potter@amd.com         * (The standard file descriptors are shared with gem5.)
18411911SBrandon.Potter@amd.com         */
18511911SBrandon.Potter@amd.com        for (int i = 0; i < p->fds->getSize(); i++) {
18611911SBrandon.Potter@amd.com            if ((*p->fds)[i])
18711911SBrandon.Potter@amd.com                p->fds->closeFDEntry(i);
18811911SBrandon.Potter@amd.com        }
18911911SBrandon.Potter@amd.com    }
19011911SBrandon.Potter@amd.com
19111911SBrandon.Potter@amd.com    tc->halt();
19213644Sqtt2@cornell.edu
19313644Sqtt2@cornell.edu    /**
19413644Sqtt2@cornell.edu     * check to see if there is no more active thread in the system. If so,
19513644Sqtt2@cornell.edu     * exit the simulation loop
19613644Sqtt2@cornell.edu     */
19713644Sqtt2@cornell.edu    int activeContexts = 0;
19813644Sqtt2@cornell.edu    for (auto &system: sys->systemList)
19913644Sqtt2@cornell.edu        activeContexts += system->numRunningContexts();
20013644Sqtt2@cornell.edu
20113644Sqtt2@cornell.edu    if (activeContexts == 0) {
20213644Sqtt2@cornell.edu        /**
20313644Sqtt2@cornell.edu         * Even though we are terminating the final thread context, dist-gem5
20413644Sqtt2@cornell.edu         * requires the simulation to remain active and provide
20513644Sqtt2@cornell.edu         * synchronization messages to the switch process. So we just halt
20613644Sqtt2@cornell.edu         * the last thread context and return. The simulation will be
20713644Sqtt2@cornell.edu         * terminated by dist-gem5 in a coordinated manner once all nodes
20813644Sqtt2@cornell.edu         * have signaled their readiness to exit. For non dist-gem5
20913644Sqtt2@cornell.edu         * simulations, readyToExit() always returns true.
21013644Sqtt2@cornell.edu         */
21113644Sqtt2@cornell.edu        if (!DistIface::readyToExit(0)) {
21213644Sqtt2@cornell.edu            return status;
21313644Sqtt2@cornell.edu        }
21413644Sqtt2@cornell.edu
21513644Sqtt2@cornell.edu        exitSimLoop("exiting with last active thread context", status & 0xff);
21613644Sqtt2@cornell.edu        return status;
21713644Sqtt2@cornell.edu    }
21813644Sqtt2@cornell.edu
21911911SBrandon.Potter@amd.com    return status;
22011886Sbrandon.potter@amd.com}
2218149SChris.Emmons@ARM.com
2228149SChris.Emmons@ARM.comSyscallReturn
22313995Sbrandon.potter@amd.comexitFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
224360SN/A{
22513995Sbrandon.potter@amd.com    return exitImpl(desc, callnum, tc, false);
226360SN/A}
227360SN/A
2281450SN/ASyscallReturn
22913995Sbrandon.potter@amd.comexitGroupFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
2306109Ssanchezd@stanford.edu{
23113995Sbrandon.potter@amd.com    return exitImpl(desc, callnum, tc, true);
2326109Ssanchezd@stanford.edu}
2336109Ssanchezd@stanford.edu
2346109Ssanchezd@stanford.eduSyscallReturn
23513995Sbrandon.potter@amd.comgetpagesizeFunc(SyscallDesc *desc, int num, ThreadContext *tc)
236360SN/A{
23710318Sandreas.hansson@arm.com    return (int)PageBytes;
238360SN/A}
239360SN/A
240360SN/A
2411450SN/ASyscallReturn
24213995Sbrandon.potter@amd.combrkFunc(SyscallDesc *desc, int num, ThreadContext *tc)
243360SN/A{
244360SN/A    // change brk addr to first arg
2456701Sgblack@eecs.umich.edu    int index = 0;
24613995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
2476701Sgblack@eecs.umich.edu    Addr new_brk = p->getSyscallArg(tc, index);
2485748SSteve.Reinhardt@amd.com
24911905SBrandon.Potter@amd.com    std::shared_ptr<MemState> mem_state = p->memState;
25011905SBrandon.Potter@amd.com    Addr brk_point = mem_state->getBrkPoint();
25111905SBrandon.Potter@amd.com
2525748SSteve.Reinhardt@amd.com    // in Linux at least, brk(0) returns the current break value
2535748SSteve.Reinhardt@amd.com    // (note that the syscall and the glibc function have different behavior)
2545748SSteve.Reinhardt@amd.com    if (new_brk == 0)
25511905SBrandon.Potter@amd.com        return brk_point;
2565748SSteve.Reinhardt@amd.com
25711905SBrandon.Potter@amd.com    if (new_brk > brk_point) {
2585748SSteve.Reinhardt@amd.com        // might need to allocate some new pages
25911905SBrandon.Potter@amd.com        for (ChunkGenerator gen(brk_point,
26011905SBrandon.Potter@amd.com                                new_brk - brk_point,
26110318Sandreas.hansson@arm.com                                PageBytes); !gen.done(); gen.next()) {
2625748SSteve.Reinhardt@amd.com            if (!p->pTable->translate(gen.addr()))
26310318Sandreas.hansson@arm.com                p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes);
2646687Stjones1@inf.ed.ac.uk
2656687Stjones1@inf.ed.ac.uk            // if the address is already there, zero it out
2666687Stjones1@inf.ed.ac.uk            else {
26711905SBrandon.Potter@amd.com                uint8_t zero = 0;
26814024Sgabeblack@google.com                PortProxy &tp = tc->getVirtProxy();
2696687Stjones1@inf.ed.ac.uk
2706687Stjones1@inf.ed.ac.uk                // split non-page aligned accesses
27110318Sandreas.hansson@arm.com                Addr next_page = roundUp(gen.addr(), PageBytes);
2726687Stjones1@inf.ed.ac.uk                uint32_t size_needed = next_page - gen.addr();
2738852Sandreas.hansson@arm.com                tp.memsetBlob(gen.addr(), zero, size_needed);
27410318Sandreas.hansson@arm.com                if (gen.addr() + PageBytes > next_page &&
2756687Stjones1@inf.ed.ac.uk                    next_page < new_brk &&
27611906SBrandon.Potter@amd.com                    p->pTable->translate(next_page)) {
27710318Sandreas.hansson@arm.com                    size_needed = PageBytes - size_needed;
2788852Sandreas.hansson@arm.com                    tp.memsetBlob(next_page, zero, size_needed);
2796687Stjones1@inf.ed.ac.uk                }
2806687Stjones1@inf.ed.ac.uk            }
2812474SN/A        }
2821450SN/A    }
2835748SSteve.Reinhardt@amd.com
28411905SBrandon.Potter@amd.com    mem_state->setBrkPoint(new_brk);
28511380Salexandru.dutu@amd.com    DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
28611905SBrandon.Potter@amd.com                    mem_state->getBrkPoint());
28711905SBrandon.Potter@amd.com    return mem_state->getBrkPoint();
288360SN/A}
289360SN/A
29011886Sbrandon.potter@amd.comSyscallReturn
29113995Sbrandon.potter@amd.comsetTidAddressFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
29211886Sbrandon.potter@amd.com{
29311886Sbrandon.potter@amd.com    int index = 0;
29413995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
29511886Sbrandon.potter@amd.com    uint64_t tidPtr = process->getSyscallArg(tc, index);
29611886Sbrandon.potter@amd.com
29711886Sbrandon.potter@amd.com    process->childClearTID = tidPtr;
29811886Sbrandon.potter@amd.com    return process->pid();
29911886Sbrandon.potter@amd.com}
300360SN/A
3011450SN/ASyscallReturn
30213995Sbrandon.potter@amd.comcloseFunc(SyscallDesc *desc, int num, ThreadContext *tc)
303360SN/A{
3046701Sgblack@eecs.umich.edu    int index = 0;
30513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
30610931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
30710931Sbrandon.potter@amd.com
30811856Sbrandon.potter@amd.com    return p->fds->closeFDEntry(tgt_fd);
309360SN/A}
310360SN/A
3111450SN/ASyscallReturn
31213995Sbrandon.potter@amd.comlseekFunc(SyscallDesc *desc, int num, ThreadContext *tc)
313360SN/A{
3146701Sgblack@eecs.umich.edu    int index = 0;
31513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
31610931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
3176701Sgblack@eecs.umich.edu    uint64_t offs = p->getSyscallArg(tc, index);
3186701Sgblack@eecs.umich.edu    int whence = p->getSyscallArg(tc, index);
319360SN/A
32011856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
32111856Sbrandon.potter@amd.com    if (!ffdp)
32210931Sbrandon.potter@amd.com        return -EBADF;
32311856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
32410931Sbrandon.potter@amd.com
32510931Sbrandon.potter@amd.com    off_t result = lseek(sim_fd, offs, whence);
326360SN/A
3271458SN/A    return (result == (off_t)-1) ? -errno : result;
328360SN/A}
329360SN/A
330360SN/A
3311450SN/ASyscallReturn
33213995Sbrandon.potter@amd.com_llseekFunc(SyscallDesc *desc, int num, ThreadContext *tc)
3334118Sgblack@eecs.umich.edu{
3346701Sgblack@eecs.umich.edu    int index = 0;
33513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
33610931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
3376701Sgblack@eecs.umich.edu    uint64_t offset_high = p->getSyscallArg(tc, index);
3386701Sgblack@eecs.umich.edu    uint32_t offset_low = p->getSyscallArg(tc, index);
3396701Sgblack@eecs.umich.edu    Addr result_ptr = p->getSyscallArg(tc, index);
3406701Sgblack@eecs.umich.edu    int whence = p->getSyscallArg(tc, index);
3414118Sgblack@eecs.umich.edu
34211856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
34311856Sbrandon.potter@amd.com    if (!ffdp)
34410931Sbrandon.potter@amd.com        return -EBADF;
34511856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
34610931Sbrandon.potter@amd.com
3474118Sgblack@eecs.umich.edu    uint64_t offset = (offset_high << 32) | offset_low;
3484118Sgblack@eecs.umich.edu
34910931Sbrandon.potter@amd.com    uint64_t result = lseek(sim_fd, offset, whence);
3504118Sgblack@eecs.umich.edu    result = TheISA::htog(result);
3514118Sgblack@eecs.umich.edu
35211379Sbrandon.potter@amd.com    if (result == (off_t)-1)
3534118Sgblack@eecs.umich.edu        return -errno;
35411379Sbrandon.potter@amd.com    // Assuming that the size of loff_t is 64 bits on the target platform
35511379Sbrandon.potter@amd.com    BufferArg result_buf(result_ptr, sizeof(result));
35611379Sbrandon.potter@amd.com    memcpy(result_buf.bufferPtr(), &result, sizeof(result));
35714024Sgabeblack@google.com    result_buf.copyOut(tc->getVirtProxy());
35811379Sbrandon.potter@amd.com    return 0;
3594118Sgblack@eecs.umich.edu}
3604118Sgblack@eecs.umich.edu
3614118Sgblack@eecs.umich.edu
3624118Sgblack@eecs.umich.eduSyscallReturn
36313995Sbrandon.potter@amd.communmapFunc(SyscallDesc *desc, int num, ThreadContext *tc)
364360SN/A{
36511383Sbrandon.potter@amd.com    // With mmap more fully implemented, it might be worthwhile to bite
36611383Sbrandon.potter@amd.com    // the bullet and implement munmap. Should allow us to reuse simulated
36711383Sbrandon.potter@amd.com    // memory.
3681458SN/A    return 0;
369360SN/A}
370360SN/A
371360SN/A
372360SN/Aconst char *hostname = "m5.eecs.umich.edu";
373360SN/A
3741450SN/ASyscallReturn
37513995Sbrandon.potter@amd.comgethostnameFunc(SyscallDesc *desc, int num, ThreadContext *tc)
376360SN/A{
3776701Sgblack@eecs.umich.edu    int index = 0;
37813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
37911906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
3806701Sgblack@eecs.umich.edu    int name_len = p->getSyscallArg(tc, index);
38111906SBrandon.Potter@amd.com    BufferArg name(buf_ptr, name_len);
382360SN/A
383360SN/A    strncpy((char *)name.bufferPtr(), hostname, name_len);
384360SN/A
38514024Sgabeblack@google.com    name.copyOut(tc->getVirtProxy());
386360SN/A
3871458SN/A    return 0;
388360SN/A}
389360SN/A
3901450SN/ASyscallReturn
39113995Sbrandon.potter@amd.comgetcwdFunc(SyscallDesc *desc, int num, ThreadContext *tc)
3925513SMichael.Adler@intel.com{
3935513SMichael.Adler@intel.com    int result = 0;
3946731Svince@csl.cornell.edu    int index = 0;
39513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
39611906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
3976701Sgblack@eecs.umich.edu    unsigned long size = p->getSyscallArg(tc, index);
39811906SBrandon.Potter@amd.com    BufferArg buf(buf_ptr, size);
3995513SMichael.Adler@intel.com
4005513SMichael.Adler@intel.com    // Is current working directory defined?
40113883Sdavid.hashe@amd.com    string cwd = p->tgtCwd;
4025513SMichael.Adler@intel.com    if (!cwd.empty()) {
4035513SMichael.Adler@intel.com        if (cwd.length() >= size) {
4045513SMichael.Adler@intel.com            // Buffer too small
4055513SMichael.Adler@intel.com            return -ERANGE;
4065513SMichael.Adler@intel.com        }
4075513SMichael.Adler@intel.com        strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
4085513SMichael.Adler@intel.com        result = cwd.length();
40910955Sdavid.hashe@amd.com    } else {
41011856Sbrandon.potter@amd.com        if (getcwd((char *)buf.bufferPtr(), size)) {
4115513SMichael.Adler@intel.com            result = strlen((char *)buf.bufferPtr());
41210955Sdavid.hashe@amd.com        } else {
4135513SMichael.Adler@intel.com            result = -1;
4145513SMichael.Adler@intel.com        }
4155513SMichael.Adler@intel.com    }
4165513SMichael.Adler@intel.com
41714024Sgabeblack@google.com    buf.copyOut(tc->getVirtProxy());
4185513SMichael.Adler@intel.com
4195513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
4205513SMichael.Adler@intel.com}
4215513SMichael.Adler@intel.com
42210203SAli.Saidi@ARM.comSyscallReturn
42313995Sbrandon.potter@amd.comreadlinkFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
42410203SAli.Saidi@ARM.com{
42513995Sbrandon.potter@amd.com    return readlinkFunc(desc, callnum, tc, 0);
42610203SAli.Saidi@ARM.com}
4275513SMichael.Adler@intel.com
4285513SMichael.Adler@intel.comSyscallReturn
42913995Sbrandon.potter@amd.comreadlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc, int index)
4305513SMichael.Adler@intel.com{
4315513SMichael.Adler@intel.com    string path;
43213995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
4335513SMichael.Adler@intel.com
43414024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
43510223Ssteve.reinhardt@amd.com        return -EFAULT;
4365513SMichael.Adler@intel.com
43713883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
43813883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
4395513SMichael.Adler@intel.com
44011906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
4416701Sgblack@eecs.umich.edu    size_t bufsiz = p->getSyscallArg(tc, index);
4426701Sgblack@eecs.umich.edu
44311906SBrandon.Potter@amd.com    BufferArg buf(buf_ptr, bufsiz);
4445513SMichael.Adler@intel.com
44510955Sdavid.hashe@amd.com    int result = -1;
44610955Sdavid.hashe@amd.com    if (path != "/proc/self/exe") {
44710955Sdavid.hashe@amd.com        result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
44810955Sdavid.hashe@amd.com    } else {
44911140Sjthestness@gmail.com        // Emulate readlink() called on '/proc/self/exe' should return the
45011140Sjthestness@gmail.com        // absolute path of the binary running in the simulated system (the
45111851Sbrandon.potter@amd.com        // Process' executable). It is possible that using this path in
45211140Sjthestness@gmail.com        // the simulated system will result in unexpected behavior if:
45311140Sjthestness@gmail.com        //  1) One binary runs another (e.g., -c time -o "my_binary"), and
45411140Sjthestness@gmail.com        //     called binary calls readlink().
45511140Sjthestness@gmail.com        //  2) The host's full path to the running benchmark changes from one
45611140Sjthestness@gmail.com        //     simulation to another. This can result in different simulated
45711140Sjthestness@gmail.com        //     performance since the simulated system will process the binary
45811140Sjthestness@gmail.com        //     path differently, even if the binary itself does not change.
45911140Sjthestness@gmail.com
46011140Sjthestness@gmail.com        // Get the absolute canonical path to the running application
46111140Sjthestness@gmail.com        char real_path[PATH_MAX];
46211140Sjthestness@gmail.com        char *check_real_path = realpath(p->progName(), real_path);
46311140Sjthestness@gmail.com        if (!check_real_path) {
46411140Sjthestness@gmail.com            fatal("readlink('/proc/self/exe') unable to resolve path to "
46511140Sjthestness@gmail.com                  "executable: %s", p->progName());
46611140Sjthestness@gmail.com        }
46711140Sjthestness@gmail.com        strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
46811140Sjthestness@gmail.com        size_t real_path_len = strlen(real_path);
46911140Sjthestness@gmail.com        if (real_path_len > bufsiz) {
47010955Sdavid.hashe@amd.com            // readlink will truncate the contents of the
47110955Sdavid.hashe@amd.com            // path to ensure it is no more than bufsiz
47210955Sdavid.hashe@amd.com            result = bufsiz;
47310955Sdavid.hashe@amd.com        } else {
47411140Sjthestness@gmail.com            result = real_path_len;
47510955Sdavid.hashe@amd.com        }
47611140Sjthestness@gmail.com
47711140Sjthestness@gmail.com        // Issue a warning about potential unexpected results
47811140Sjthestness@gmail.com        warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
47911140Sjthestness@gmail.com                  "results in various settings.\n      Returning '%s'\n",
48011140Sjthestness@gmail.com                  (char*)buf.bufferPtr());
48110955Sdavid.hashe@amd.com    }
4825513SMichael.Adler@intel.com
48314024Sgabeblack@google.com    buf.copyOut(tc->getVirtProxy());
4845513SMichael.Adler@intel.com
4855513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
4865513SMichael.Adler@intel.com}
4875513SMichael.Adler@intel.com
4885513SMichael.Adler@intel.comSyscallReturn
48913995Sbrandon.potter@amd.comunlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc)
490511SN/A{
49113995Sbrandon.potter@amd.com    return unlinkHelper(desc, num, tc, 0);
49210633Smichaelupton@gmail.com}
49310633Smichaelupton@gmail.com
49410633Smichaelupton@gmail.comSyscallReturn
49513995Sbrandon.potter@amd.comunlinkHelper(SyscallDesc *desc, int num, ThreadContext *tc, int index)
49610633Smichaelupton@gmail.com{
4971706SN/A    string path;
49813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
499360SN/A
50014024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
50110223Ssteve.reinhardt@amd.com        return -EFAULT;
502511SN/A
50313883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
5043669Sbinkertn@umich.edu
505511SN/A    int result = unlink(path.c_str());
5061458SN/A    return (result == -1) ? -errno : result;
507511SN/A}
508511SN/A
50912795Smattdsinclair@gmail.comSyscallReturn
51013995Sbrandon.potter@amd.comlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc)
51112795Smattdsinclair@gmail.com{
51212795Smattdsinclair@gmail.com    string path;
51312795Smattdsinclair@gmail.com    string new_path;
51413995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
51512795Smattdsinclair@gmail.com
51612795Smattdsinclair@gmail.com    int index = 0;
51714024Sgabeblack@google.com    auto &virt_mem = tc->getVirtProxy();
51812795Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
51912795Smattdsinclair@gmail.com        return -EFAULT;
52012795Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
52112795Smattdsinclair@gmail.com        return -EFAULT;
52212795Smattdsinclair@gmail.com
52313883Sdavid.hashe@amd.com    path = p->absolutePath(path, true);
52413883Sdavid.hashe@amd.com    new_path = p->absolutePath(new_path, true);
52512795Smattdsinclair@gmail.com
52612795Smattdsinclair@gmail.com    int result = link(path.c_str(), new_path.c_str());
52712795Smattdsinclair@gmail.com    return (result == -1) ? -errno : result;
52812795Smattdsinclair@gmail.com}
5295513SMichael.Adler@intel.com
5305513SMichael.Adler@intel.comSyscallReturn
53113995Sbrandon.potter@amd.comsymlinkFunc(SyscallDesc *desc, int num, ThreadContext *tc)
53212796Smattdsinclair@gmail.com{
53312796Smattdsinclair@gmail.com    string path;
53412796Smattdsinclair@gmail.com    string new_path;
53513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
53612796Smattdsinclair@gmail.com
53712796Smattdsinclair@gmail.com    int index = 0;
53814024Sgabeblack@google.com    auto &virt_mem = tc->getVirtProxy();
53912796Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
54012796Smattdsinclair@gmail.com        return -EFAULT;
54112796Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
54212796Smattdsinclair@gmail.com        return -EFAULT;
54312796Smattdsinclair@gmail.com
54413883Sdavid.hashe@amd.com    path = p->absolutePath(path, true);
54513883Sdavid.hashe@amd.com    new_path = p->absolutePath(new_path, true);
54612796Smattdsinclair@gmail.com
54712796Smattdsinclair@gmail.com    int result = symlink(path.c_str(), new_path.c_str());
54812796Smattdsinclair@gmail.com    return (result == -1) ? -errno : result;
54912796Smattdsinclair@gmail.com}
55012796Smattdsinclair@gmail.com
55112796Smattdsinclair@gmail.comSyscallReturn
55213995Sbrandon.potter@amd.commkdirFunc(SyscallDesc *desc, int num, ThreadContext *tc)
5535513SMichael.Adler@intel.com{
55413995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
5556701Sgblack@eecs.umich.edu    int index = 0;
55613883Sdavid.hashe@amd.com    std::string path;
55714024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
55810223Ssteve.reinhardt@amd.com        return -EFAULT;
5595513SMichael.Adler@intel.com
56013883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
5616701Sgblack@eecs.umich.edu    mode_t mode = p->getSyscallArg(tc, index);
5625513SMichael.Adler@intel.com
56313883Sdavid.hashe@amd.com    auto result = mkdir(path.c_str(), mode);
5645513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
5655513SMichael.Adler@intel.com}
5665513SMichael.Adler@intel.com
5671450SN/ASyscallReturn
56813995Sbrandon.potter@amd.comrenameFunc(SyscallDesc *desc, int num, ThreadContext *tc)
569511SN/A{
5701706SN/A    string old_name;
57113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
572511SN/A
5736701Sgblack@eecs.umich.edu    int index = 0;
57414024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(
57514024Sgabeblack@google.com                old_name, p->getSyscallArg(tc, index))) {
5761458SN/A        return -EFAULT;
57714024Sgabeblack@google.com    }
578511SN/A
5791706SN/A    string new_name;
580511SN/A
58114024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(
58214024Sgabeblack@google.com                new_name, p->getSyscallArg(tc, index))) {
5831458SN/A        return -EFAULT;
58414024Sgabeblack@google.com    }
585511SN/A
58613883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
58713883Sdavid.hashe@amd.com    old_name = p->checkPathRedirect(old_name);
58813883Sdavid.hashe@amd.com    new_name = p->checkPathRedirect(new_name);
5893669Sbinkertn@umich.edu
5901706SN/A    int64_t result = rename(old_name.c_str(), new_name.c_str());
5911458SN/A    return (result == -1) ? -errno : result;
592511SN/A}
593511SN/A
5941706SN/ASyscallReturn
59513995Sbrandon.potter@amd.comtruncateFunc(SyscallDesc *desc, int num, ThreadContext *tc)
5961706SN/A{
5971706SN/A    string path;
59813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
5991706SN/A
6006701Sgblack@eecs.umich.edu    int index = 0;
60114024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
6021706SN/A        return -EFAULT;
6031706SN/A
6046701Sgblack@eecs.umich.edu    off_t length = p->getSyscallArg(tc, index);
6051706SN/A
60613883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
60713883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
6083669Sbinkertn@umich.edu
6091706SN/A    int result = truncate(path.c_str(), length);
6101706SN/A    return (result == -1) ? -errno : result;
6111706SN/A}
6121706SN/A
6131706SN/ASyscallReturn
61413995Sbrandon.potter@amd.comftruncateFunc(SyscallDesc *desc, int num, ThreadContext *tc)
6151706SN/A{
6166701Sgblack@eecs.umich.edu    int index = 0;
61713995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
61811856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
61911856Sbrandon.potter@amd.com    off_t length = p->getSyscallArg(tc, index);
6201706SN/A
62111856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
62211856Sbrandon.potter@amd.com    if (!ffdp)
6231706SN/A        return -EBADF;
62411856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
6251706SN/A
62610931Sbrandon.potter@amd.com    int result = ftruncate(sim_fd, length);
6271706SN/A    return (result == -1) ? -errno : result;
6281706SN/A}
6291999SN/A
6301999SN/ASyscallReturn
63113995Sbrandon.potter@amd.comtruncate64Func(SyscallDesc *desc, int num, ThreadContext *tc)
6326703Svince@csl.cornell.edu{
6336703Svince@csl.cornell.edu    int index = 0;
63413995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
6356703Svince@csl.cornell.edu    string path;
6366703Svince@csl.cornell.edu
63714024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(
63814024Sgabeblack@google.com                path, process->getSyscallArg(tc, index))) {
63911906SBrandon.Potter@amd.com        return -EFAULT;
64014024Sgabeblack@google.com    }
6416703Svince@csl.cornell.edu
6426744SAli.Saidi@arm.com    int64_t length = process->getSyscallArg(tc, index, 64);
6436703Svince@csl.cornell.edu
64413883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
64513883Sdavid.hashe@amd.com    path = process->checkPathRedirect(path);
6466703Svince@csl.cornell.edu
6476744SAli.Saidi@arm.com#if NO_STAT64
6486744SAli.Saidi@arm.com    int result = truncate(path.c_str(), length);
6496744SAli.Saidi@arm.com#else
6506703Svince@csl.cornell.edu    int result = truncate64(path.c_str(), length);
6516744SAli.Saidi@arm.com#endif
6526703Svince@csl.cornell.edu    return (result == -1) ? -errno : result;
6536703Svince@csl.cornell.edu}
6546703Svince@csl.cornell.edu
6556703Svince@csl.cornell.eduSyscallReturn
65613995Sbrandon.potter@amd.comftruncate64Func(SyscallDesc *desc, int num, ThreadContext *tc)
6576685Stjones1@inf.ed.ac.uk{
6586701Sgblack@eecs.umich.edu    int index = 0;
65913995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
66011856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
66111856Sbrandon.potter@amd.com    int64_t length = p->getSyscallArg(tc, index, 64);
6626685Stjones1@inf.ed.ac.uk
66311856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
66411856Sbrandon.potter@amd.com    if (!ffdp)
6656685Stjones1@inf.ed.ac.uk        return -EBADF;
66611856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
6676685Stjones1@inf.ed.ac.uk
6686744SAli.Saidi@arm.com#if NO_STAT64
66910931Sbrandon.potter@amd.com    int result = ftruncate(sim_fd, length);
6706744SAli.Saidi@arm.com#else
67110931Sbrandon.potter@amd.com    int result = ftruncate64(sim_fd, length);
6726744SAli.Saidi@arm.com#endif
6736685Stjones1@inf.ed.ac.uk    return (result == -1) ? -errno : result;
6746685Stjones1@inf.ed.ac.uk}
6756685Stjones1@inf.ed.ac.uk
6766685Stjones1@inf.ed.ac.ukSyscallReturn
67713995Sbrandon.potter@amd.comumaskFunc(SyscallDesc *desc, int num, ThreadContext *tc)
6785513SMichael.Adler@intel.com{
6795513SMichael.Adler@intel.com    // Letting the simulated program change the simulator's umask seems like
6805513SMichael.Adler@intel.com    // a bad idea.  Compromise by just returning the current umask but not
6815513SMichael.Adler@intel.com    // changing anything.
6825513SMichael.Adler@intel.com    mode_t oldMask = umask(0);
6835513SMichael.Adler@intel.com    umask(oldMask);
6845521Snate@binkert.org    return (int)oldMask;
6855513SMichael.Adler@intel.com}
6865513SMichael.Adler@intel.com
6875513SMichael.Adler@intel.comSyscallReturn
68813995Sbrandon.potter@amd.comchownFunc(SyscallDesc *desc, int num, ThreadContext *tc)
6891999SN/A{
6901999SN/A    string path;
69113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
6921999SN/A
6936701Sgblack@eecs.umich.edu    int index = 0;
69414024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
6951999SN/A        return -EFAULT;
6961999SN/A
6971999SN/A    /* XXX endianess */
6986701Sgblack@eecs.umich.edu    uint32_t owner = p->getSyscallArg(tc, index);
6991999SN/A    uid_t hostOwner = owner;
7006701Sgblack@eecs.umich.edu    uint32_t group = p->getSyscallArg(tc, index);
7011999SN/A    gid_t hostGroup = group;
7021999SN/A
70313883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
70413883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
7053669Sbinkertn@umich.edu
7061999SN/A    int result = chown(path.c_str(), hostOwner, hostGroup);
7071999SN/A    return (result == -1) ? -errno : result;
7081999SN/A}
7091999SN/A
7101999SN/ASyscallReturn
71113995Sbrandon.potter@amd.comfchownFunc(SyscallDesc *desc, int num, ThreadContext *tc)
7121999SN/A{
7136701Sgblack@eecs.umich.edu    int index = 0;
71413995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
71511856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
7161999SN/A
71711856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
71811856Sbrandon.potter@amd.com    if (!ffdp)
7191999SN/A        return -EBADF;
72011856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
7211999SN/A
7221999SN/A    /* XXX endianess */
72311856Sbrandon.potter@amd.com    uint32_t owner = p->getSyscallArg(tc, index);
7241999SN/A    uid_t hostOwner = owner;
72511856Sbrandon.potter@amd.com    uint32_t group = p->getSyscallArg(tc, index);
7261999SN/A    gid_t hostGroup = group;
7271999SN/A
72810931Sbrandon.potter@amd.com    int result = fchown(sim_fd, hostOwner, hostGroup);
7291999SN/A    return (result == -1) ? -errno : result;
7301999SN/A}
7312093SN/A
73211856Sbrandon.potter@amd.com/**
73311908SBrandon.Potter@amd.com * FIXME: The file description is not shared among file descriptors created
73411908SBrandon.Potter@amd.com * with dup. Really, it's difficult to maintain fields like file offset or
73511908SBrandon.Potter@amd.com * flags since an update to such a field won't be reflected in the metadata
73611908SBrandon.Potter@amd.com * for the fd entries that we maintain for checkpoint restoration.
73711856Sbrandon.potter@amd.com */
7382093SN/ASyscallReturn
73913995Sbrandon.potter@amd.comdupFunc(SyscallDesc *desc, int num, ThreadContext *tc)
7403079Sstever@eecs.umich.edu{
7416701Sgblack@eecs.umich.edu    int index = 0;
74213995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
74311856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
74410931Sbrandon.potter@amd.com
74511856Sbrandon.potter@amd.com    auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
74611856Sbrandon.potter@amd.com    if (!old_hbfdp)
7473079Sstever@eecs.umich.edu        return -EBADF;
74811856Sbrandon.potter@amd.com    int sim_fd = old_hbfdp->getSimFD();
7495282Srstrong@cs.ucsd.edu
75010781Snilay@cs.wisc.edu    int result = dup(sim_fd);
75111908SBrandon.Potter@amd.com    if (result == -1)
75211908SBrandon.Potter@amd.com        return -errno;
75311856Sbrandon.potter@amd.com
75411908SBrandon.Potter@amd.com    auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
75511856Sbrandon.potter@amd.com    new_hbfdp->setSimFD(result);
75611908SBrandon.Potter@amd.com    new_hbfdp->setCOE(false);
75711908SBrandon.Potter@amd.com    return p->fds->allocFD(new_hbfdp);
75811908SBrandon.Potter@amd.com}
75911856Sbrandon.potter@amd.com
76011908SBrandon.Potter@amd.comSyscallReturn
76113995Sbrandon.potter@amd.comdup2Func(SyscallDesc *desc, int num, ThreadContext *tc)
76211908SBrandon.Potter@amd.com{
76311908SBrandon.Potter@amd.com    int index = 0;
76413995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
76511908SBrandon.Potter@amd.com    int old_tgt_fd = p->getSyscallArg(tc, index);
76611908SBrandon.Potter@amd.com    auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
76711908SBrandon.Potter@amd.com    if (!old_hbp)
76811908SBrandon.Potter@amd.com        return -EBADF;
76911908SBrandon.Potter@amd.com    int old_sim_fd = old_hbp->getSimFD();
77011908SBrandon.Potter@amd.com
77111908SBrandon.Potter@amd.com    /**
77211908SBrandon.Potter@amd.com     * We need a valid host file descriptor number to be able to pass into
77311908SBrandon.Potter@amd.com     * the second parameter for dup2 (newfd), but we don't know what the
77411908SBrandon.Potter@amd.com     * viable numbers are; we execute the open call to retrieve one.
77511908SBrandon.Potter@amd.com     */
77611908SBrandon.Potter@amd.com    int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
77711908SBrandon.Potter@amd.com    if (res_fd == -1)
77811908SBrandon.Potter@amd.com        return -errno;
77911908SBrandon.Potter@amd.com
78011908SBrandon.Potter@amd.com    int new_tgt_fd = p->getSyscallArg(tc, index);
78111908SBrandon.Potter@amd.com    auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
78211908SBrandon.Potter@amd.com    if (new_hbp)
78311908SBrandon.Potter@amd.com        p->fds->closeFDEntry(new_tgt_fd);
78411908SBrandon.Potter@amd.com    new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
78511908SBrandon.Potter@amd.com    new_hbp->setSimFD(res_fd);
78611908SBrandon.Potter@amd.com    new_hbp->setCOE(false);
78711908SBrandon.Potter@amd.com
78811908SBrandon.Potter@amd.com    return p->fds->allocFD(new_hbp);
7893079Sstever@eecs.umich.edu}
7903079Sstever@eecs.umich.edu
7913079Sstever@eecs.umich.eduSyscallReturn
79213995Sbrandon.potter@amd.comfcntlFunc(SyscallDesc *desc, int num, ThreadContext *tc)
7932093SN/A{
79411875Sbrandon.potter@amd.com    int arg;
7956701Sgblack@eecs.umich.edu    int index = 0;
79613995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
79711856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
79811875Sbrandon.potter@amd.com    int cmd = p->getSyscallArg(tc, index);
7992093SN/A
80011856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
80111856Sbrandon.potter@amd.com    if (!hbfdp)
8022093SN/A        return -EBADF;
80311856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
8042093SN/A
80511875Sbrandon.potter@amd.com    int coe = hbfdp->getCOE();
80611875Sbrandon.potter@amd.com
8072093SN/A    switch (cmd) {
80811875Sbrandon.potter@amd.com      case F_GETFD:
80911875Sbrandon.potter@amd.com        return coe & FD_CLOEXEC;
8102093SN/A
81111875Sbrandon.potter@amd.com      case F_SETFD: {
81211875Sbrandon.potter@amd.com        arg = p->getSyscallArg(tc, index);
81311875Sbrandon.potter@amd.com        arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
8142093SN/A        return 0;
81511875Sbrandon.potter@amd.com      }
8162093SN/A
81711875Sbrandon.potter@amd.com      // Rely on the host to maintain the file status flags for this file
81811875Sbrandon.potter@amd.com      // description rather than maintain it ourselves. Admittedly, this
81911875Sbrandon.potter@amd.com      // is suboptimal (and possibly error prone), but it is difficult to
82011875Sbrandon.potter@amd.com      // maintain the flags by tracking them across the different descriptors
82111875Sbrandon.potter@amd.com      // (that refer to this file description) caused by clone, dup, and
82211875Sbrandon.potter@amd.com      // subsequent fcntls.
82311875Sbrandon.potter@amd.com      case F_GETFL:
82411875Sbrandon.potter@amd.com      case F_SETFL: {
82511875Sbrandon.potter@amd.com        arg = p->getSyscallArg(tc, index);
82611875Sbrandon.potter@amd.com        int rv = fcntl(sim_fd, cmd, arg);
82711875Sbrandon.potter@amd.com        return (rv == -1) ? -errno : rv;
82811875Sbrandon.potter@amd.com      }
8292093SN/A
8302093SN/A      default:
83111875Sbrandon.potter@amd.com        warn("fcntl: unsupported command %d\n", cmd);
8322093SN/A        return 0;
8332093SN/A    }
8342093SN/A}
8352093SN/A
8362238SN/ASyscallReturn
83713995Sbrandon.potter@amd.comfcntl64Func(SyscallDesc *desc, int num, ThreadContext *tc)
8382687Sksewell@umich.edu{
8396701Sgblack@eecs.umich.edu    int index = 0;
84013995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
84111856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
8422687Sksewell@umich.edu
84311856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
84411856Sbrandon.potter@amd.com    if (!hbfdp)
8452687Sksewell@umich.edu        return -EBADF;
84611856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
8472687Sksewell@umich.edu
84811856Sbrandon.potter@amd.com    int cmd = p->getSyscallArg(tc, index);
8492687Sksewell@umich.edu    switch (cmd) {
8502687Sksewell@umich.edu      case 33: //F_GETLK64
85110931Sbrandon.potter@amd.com        warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
8522687Sksewell@umich.edu        return -EMFILE;
8532687Sksewell@umich.edu
8542687Sksewell@umich.edu      case 34: // F_SETLK64
8552687Sksewell@umich.edu      case 35: // F_SETLKW64
85610931Sbrandon.potter@amd.com        warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
85710931Sbrandon.potter@amd.com             tgt_fd);
8582687Sksewell@umich.edu        return -EMFILE;
8592687Sksewell@umich.edu
8602687Sksewell@umich.edu      default:
8612687Sksewell@umich.edu        // not sure if this is totally valid, but we'll pass it through
8622687Sksewell@umich.edu        // to the underlying OS
86310931Sbrandon.potter@amd.com        warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
86410931Sbrandon.potter@amd.com        return fcntl(sim_fd, cmd);
8652687Sksewell@umich.edu    }
8662687Sksewell@umich.edu}
8672687Sksewell@umich.edu
8682687Sksewell@umich.eduSyscallReturn
86914129Smatthew.sinclair@amd.compipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudo_pipe,
87014129Smatthew.sinclair@amd.com         bool is_pipe2)
8712238SN/A{
87214124Sbrandon.potter@amd.com    Addr tgt_addr = 0;
87314129Smatthew.sinclair@amd.com    int flags = 0;
87414124Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
87514129Smatthew.sinclair@amd.com    if (!pseudo_pipe) {
87614124Sbrandon.potter@amd.com        int index = 0;
87714124Sbrandon.potter@amd.com        tgt_addr = p->getSyscallArg(tc, index);
87814129Smatthew.sinclair@amd.com        if (is_pipe2) {
87914129Smatthew.sinclair@amd.com            flags = p->getSyscallArg(tc, index);
88014129Smatthew.sinclair@amd.com        }
88114124Sbrandon.potter@amd.com    }
88214124Sbrandon.potter@amd.com
88311856Sbrandon.potter@amd.com    int sim_fds[2], tgt_fds[2];
8842093SN/A
88511856Sbrandon.potter@amd.com    int pipe_retval = pipe(sim_fds);
88611908SBrandon.Potter@amd.com    if (pipe_retval == -1)
88711908SBrandon.Potter@amd.com        return -errno;
8882238SN/A
88911856Sbrandon.potter@amd.com    auto rend = PipeFDEntry::EndType::read;
89011856Sbrandon.potter@amd.com    auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
89111908SBrandon.Potter@amd.com    tgt_fds[0] = p->fds->allocFD(rpfd);
89214129Smatthew.sinclair@amd.com    int sim_fd_rpfd = rpfd->getSimFD();
8932238SN/A
89411856Sbrandon.potter@amd.com    auto wend = PipeFDEntry::EndType::write;
89511856Sbrandon.potter@amd.com    auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
89611908SBrandon.Potter@amd.com    tgt_fds[1] = p->fds->allocFD(wpfd);
89714129Smatthew.sinclair@amd.com    int sim_fd_wpfd = wpfd->getSimFD();
89811856Sbrandon.potter@amd.com
89911856Sbrandon.potter@amd.com    /**
90011856Sbrandon.potter@amd.com     * Now patch the read object to record the target file descriptor chosen
90111856Sbrandon.potter@amd.com     * as the write end of the pipe.
90211856Sbrandon.potter@amd.com     */
90311856Sbrandon.potter@amd.com    rpfd->setPipeReadSource(tgt_fds[1]);
90411856Sbrandon.potter@amd.com
90511856Sbrandon.potter@amd.com    /**
90611856Sbrandon.potter@amd.com     * Alpha Linux convention for pipe() is that fd[0] is returned as
90711856Sbrandon.potter@amd.com     * the return value of the function, and fd[1] is returned in r20.
90811856Sbrandon.potter@amd.com     */
90914129Smatthew.sinclair@amd.com    if (pseudo_pipe) {
91011908SBrandon.Potter@amd.com        tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
91111908SBrandon.Potter@amd.com        return tgt_fds[0];
91211908SBrandon.Potter@amd.com    }
91311908SBrandon.Potter@amd.com
91411908SBrandon.Potter@amd.com    /**
91511908SBrandon.Potter@amd.com     * Copy the target file descriptors into buffer space and then copy
91611908SBrandon.Potter@amd.com     * the buffer space back into the target address space.
91711908SBrandon.Potter@amd.com     */
91811908SBrandon.Potter@amd.com    BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
91911908SBrandon.Potter@amd.com    int *buf_ptr = (int*)tgt_handle.bufferPtr();
92011908SBrandon.Potter@amd.com    buf_ptr[0] = tgt_fds[0];
92111908SBrandon.Potter@amd.com    buf_ptr[1] = tgt_fds[1];
92214024Sgabeblack@google.com    tgt_handle.copyOut(tc->getVirtProxy());
92314129Smatthew.sinclair@amd.com
92414129Smatthew.sinclair@amd.com    // pipe2 has additional behavior if flags != 0
92514129Smatthew.sinclair@amd.com    if (is_pipe2 && flags) {
92614129Smatthew.sinclair@amd.com        // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
92714129Smatthew.sinclair@amd.com        // if flags set to anything else, return EINVAL
92814129Smatthew.sinclair@amd.com        if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
92914129Smatthew.sinclair@amd.com            (flags != (O_CLOEXEC | O_NONBLOCK))) {
93014129Smatthew.sinclair@amd.com            return -EINVAL;
93114129Smatthew.sinclair@amd.com        }
93214129Smatthew.sinclair@amd.com
93314129Smatthew.sinclair@amd.com        /*
93414129Smatthew.sinclair@amd.com          If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
93514129Smatthew.sinclair@amd.com          status flag for two new open file descriptors.
93614129Smatthew.sinclair@amd.com        */
93714129Smatthew.sinclair@amd.com        if (flags & O_NONBLOCK) {
93814129Smatthew.sinclair@amd.com            /*
93914129Smatthew.sinclair@amd.com              O_NONBLOCK is set when the programmer wants to avoid a separate
94014129Smatthew.sinclair@amd.com              call(s) to fcntl in their code, so mirror the fcntl
94114129Smatthew.sinclair@amd.com              implementation for handling file descriptors -- rely on host to
94214129Smatthew.sinclair@amd.com              maintain file status flags.
94314129Smatthew.sinclair@amd.com            */
94414129Smatthew.sinclair@amd.com            if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
94514129Smatthew.sinclair@amd.com                return -errno;
94614129Smatthew.sinclair@amd.com            }
94714129Smatthew.sinclair@amd.com            if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
94814129Smatthew.sinclair@amd.com                return -errno;
94914129Smatthew.sinclair@amd.com            }
95014129Smatthew.sinclair@amd.com        }
95114129Smatthew.sinclair@amd.com
95214129Smatthew.sinclair@amd.com        /*
95314129Smatthew.sinclair@amd.com          If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
95414129Smatthew.sinclair@amd.com          (FD_CLOEXEC) file status flag for two new open file descriptors.
95514129Smatthew.sinclair@amd.com        */
95614129Smatthew.sinclair@amd.com        if (flags & O_CLOEXEC) {
95714129Smatthew.sinclair@amd.com            rpfd->setCOE(true);
95814129Smatthew.sinclair@amd.com            wpfd->setCOE(true);
95914129Smatthew.sinclair@amd.com        }
96014129Smatthew.sinclair@amd.com    }
96114129Smatthew.sinclair@amd.com
96211908SBrandon.Potter@amd.com    return 0;
96311908SBrandon.Potter@amd.com}
96411908SBrandon.Potter@amd.com
96511908SBrandon.Potter@amd.comSyscallReturn
96613995Sbrandon.potter@amd.compipePseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
96711908SBrandon.Potter@amd.com{
96813995Sbrandon.potter@amd.com    return pipeImpl(desc, callnum, tc, true);
96911908SBrandon.Potter@amd.com}
97011908SBrandon.Potter@amd.com
97111908SBrandon.Potter@amd.comSyscallReturn
97213995Sbrandon.potter@amd.compipeFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
97311908SBrandon.Potter@amd.com{
97413995Sbrandon.potter@amd.com    return pipeImpl(desc, callnum, tc, false);
9752238SN/A}
9762238SN/A
97711885Sbrandon.potter@amd.comSyscallReturn
97814129Smatthew.sinclair@amd.compipe2Func(SyscallDesc *desc, int callnum, ThreadContext *tc)
97914129Smatthew.sinclair@amd.com{
98014129Smatthew.sinclair@amd.com    // call pipeImpl since the only difference between pipe and pipe2 is
98114129Smatthew.sinclair@amd.com    // the flags values and what they do (at the end of pipeImpl)
98214129Smatthew.sinclair@amd.com    return pipeImpl(desc, callnum, tc, false, true);
98314129Smatthew.sinclair@amd.com}
98414129Smatthew.sinclair@amd.com
98514129Smatthew.sinclair@amd.comSyscallReturn
98614130Sbrandon.potter@amd.comgetpgrpFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
98714130Sbrandon.potter@amd.com{
98814130Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
98914130Sbrandon.potter@amd.com    return process->pgid();
99014130Sbrandon.potter@amd.com}
99114130Sbrandon.potter@amd.com
99214130Sbrandon.potter@amd.comSyscallReturn
99313995Sbrandon.potter@amd.comsetpgidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
99411885Sbrandon.potter@amd.com{
99511885Sbrandon.potter@amd.com    int index = 0;
99613995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
99711885Sbrandon.potter@amd.com    int pid = process->getSyscallArg(tc, index);
99811885Sbrandon.potter@amd.com    int pgid = process->getSyscallArg(tc, index);
99911885Sbrandon.potter@amd.com
100011885Sbrandon.potter@amd.com    if (pgid < 0)
100111885Sbrandon.potter@amd.com        return -EINVAL;
100211885Sbrandon.potter@amd.com
100311885Sbrandon.potter@amd.com    if (pid == 0) {
100414149Sbrandon.potter@amd.com        process->pgid(process->pid());
100511885Sbrandon.potter@amd.com        return 0;
100611885Sbrandon.potter@amd.com    }
100711885Sbrandon.potter@amd.com
100811913SBrandon.Potter@amd.com    Process *matched_ph = nullptr;
100911885Sbrandon.potter@amd.com    System *sysh = tc->getSystemPtr();
101011885Sbrandon.potter@amd.com
101111885Sbrandon.potter@amd.com    // Retrieves process pointer from active/suspended thread contexts.
101211885Sbrandon.potter@amd.com    for (int i = 0; i < sysh->numContexts(); i++) {
101311885Sbrandon.potter@amd.com        if (sysh->threadContexts[i]->status() != ThreadContext::Halted) {
101411885Sbrandon.potter@amd.com            Process *temp_h = sysh->threadContexts[i]->getProcessPtr();
101511885Sbrandon.potter@amd.com            Process *walk_ph = (Process*)temp_h;
101611885Sbrandon.potter@amd.com
101711885Sbrandon.potter@amd.com            if (walk_ph && walk_ph->pid() == process->pid())
101811885Sbrandon.potter@amd.com                matched_ph = walk_ph;
101911885Sbrandon.potter@amd.com        }
102011885Sbrandon.potter@amd.com    }
102111885Sbrandon.potter@amd.com
102211913SBrandon.Potter@amd.com    assert(matched_ph);
102314149Sbrandon.potter@amd.com    matched_ph->pgid((pgid == 0) ? matched_ph->pid() : pgid);
102411885Sbrandon.potter@amd.com
102511885Sbrandon.potter@amd.com    return 0;
102611885Sbrandon.potter@amd.com}
10272238SN/A
10282238SN/ASyscallReturn
102913995Sbrandon.potter@amd.comgetpidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10302238SN/A{
10312238SN/A    // Make up a PID.  There's no interprocess communication in
10322238SN/A    // fake_syscall mode, so there's no way for a process to know it's
10332238SN/A    // not getting a unique value.
10342238SN/A
103513995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
10363114Sgblack@eecs.umich.edu    tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
10373114Sgblack@eecs.umich.edu    return process->pid();
10382238SN/A}
10392238SN/A
10402238SN/A
10412238SN/ASyscallReturn
104213995Sbrandon.potter@amd.comgetuidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10432238SN/A{
10442238SN/A    // Make up a UID and EUID... it shouldn't matter, and we want the
10452238SN/A    // simulation to be deterministic.
10462238SN/A
10472238SN/A    // EUID goes in r20.
104813995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
104911906SBrandon.Potter@amd.com    tc->setIntReg(SyscallPseudoReturnReg, process->euid()); // EUID
105011906SBrandon.Potter@amd.com    return process->uid(); // UID
10512238SN/A}
10522238SN/A
10532238SN/A
10542238SN/ASyscallReturn
105513995Sbrandon.potter@amd.comgetgidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10562238SN/A{
10572238SN/A    // Get current group ID.  EGID goes in r20.
105813995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
105911906SBrandon.Potter@amd.com    tc->setIntReg(SyscallPseudoReturnReg, process->egid()); // EGID
10603114Sgblack@eecs.umich.edu    return process->gid();
10612238SN/A}
10622238SN/A
10632238SN/A
10642238SN/ASyscallReturn
106513995Sbrandon.potter@amd.comsetuidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10662238SN/A{
10672238SN/A    // can't fathom why a benchmark would call this.
10686701Sgblack@eecs.umich.edu    int index = 0;
106913995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
10706701Sgblack@eecs.umich.edu    warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index));
10712238SN/A    return 0;
10722238SN/A}
10732238SN/A
10742238SN/ASyscallReturn
107513995Sbrandon.potter@amd.comgetpidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10762238SN/A{
107713995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
107811885Sbrandon.potter@amd.com    return process->tgid();
107911885Sbrandon.potter@amd.com}
10802238SN/A
108111885Sbrandon.potter@amd.comSyscallReturn
108213995Sbrandon.potter@amd.comgettidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
108311885Sbrandon.potter@amd.com{
108413995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
10853114Sgblack@eecs.umich.edu    return process->pid();
10862238SN/A}
10872238SN/A
10882238SN/ASyscallReturn
108913995Sbrandon.potter@amd.comgetppidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10902238SN/A{
109113995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
10923114Sgblack@eecs.umich.edu    return process->ppid();
10932238SN/A}
10942238SN/A
10952238SN/ASyscallReturn
109613995Sbrandon.potter@amd.comgetuidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
10972238SN/A{
109813995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
10995543Ssaidi@eecs.umich.edu    return process->uid();              // UID
11002238SN/A}
11012238SN/A
11022238SN/ASyscallReturn
110313995Sbrandon.potter@amd.comgeteuidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
11042238SN/A{
110513995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
11065543Ssaidi@eecs.umich.edu    return process->euid();             // UID
11072238SN/A}
11082238SN/A
11092238SN/ASyscallReturn
111013995Sbrandon.potter@amd.comgetgidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
11112238SN/A{
111213995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
11133114Sgblack@eecs.umich.edu    return process->gid();
11142238SN/A}
11152238SN/A
11162238SN/ASyscallReturn
111713995Sbrandon.potter@amd.comgetegidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
11182238SN/A{
111913995Sbrandon.potter@amd.com    auto process = tc->getProcessPtr();
11203114Sgblack@eecs.umich.edu    return process->egid();
11212238SN/A}
11222238SN/A
11239455Smitch.hayenga+gem5@gmail.comSyscallReturn
112413995Sbrandon.potter@amd.comfallocateFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
112511760Sbrandon.potter@amd.com{
112613936SAndrea.Mondelli@ucf.edu#if defined(__linux__)
112711760Sbrandon.potter@amd.com    int index = 0;
112813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
112911856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
113011856Sbrandon.potter@amd.com    int mode = p->getSyscallArg(tc, index);
113111856Sbrandon.potter@amd.com    off_t offset = p->getSyscallArg(tc, index);
113211856Sbrandon.potter@amd.com    off_t len = p->getSyscallArg(tc, index);
113311760Sbrandon.potter@amd.com
113411856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
113511856Sbrandon.potter@amd.com    if (!ffdp)
113611760Sbrandon.potter@amd.com        return -EBADF;
113711856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
113811760Sbrandon.potter@amd.com
113911760Sbrandon.potter@amd.com    int result = fallocate(sim_fd, mode, offset, len);
114011760Sbrandon.potter@amd.com    if (result < 0)
114111760Sbrandon.potter@amd.com        return -errno;
114213933Sbrandon.potter@amd.com    return 0;
114313933Sbrandon.potter@amd.com#else
114413933Sbrandon.potter@amd.com    warnUnsupportedOS("fallocate");
114513933Sbrandon.potter@amd.com    return -1;
114611799Sbrandon.potter@amd.com#endif
114711760Sbrandon.potter@amd.com}
114811760Sbrandon.potter@amd.com
114911760Sbrandon.potter@amd.comSyscallReturn
115013995Sbrandon.potter@amd.comaccessFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, int index)
11519455Smitch.hayenga+gem5@gmail.com{
11529455Smitch.hayenga+gem5@gmail.com    string path;
115313995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
115414024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
115510223Ssteve.reinhardt@amd.com        return -EFAULT;
11569455Smitch.hayenga+gem5@gmail.com
115713883Sdavid.hashe@amd.com    // Adjust path for cwd and redirection
115813883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
11599455Smitch.hayenga+gem5@gmail.com
11609455Smitch.hayenga+gem5@gmail.com    mode_t mode = p->getSyscallArg(tc, index);
11619455Smitch.hayenga+gem5@gmail.com
11629455Smitch.hayenga+gem5@gmail.com    int result = access(path.c_str(), mode);
11639455Smitch.hayenga+gem5@gmail.com    return (result == -1) ? -errno : result;
11649455Smitch.hayenga+gem5@gmail.com}
116510203SAli.Saidi@ARM.com
116610203SAli.Saidi@ARM.comSyscallReturn
116713995Sbrandon.potter@amd.comaccessFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
116810203SAli.Saidi@ARM.com{
116913995Sbrandon.potter@amd.com    return accessFunc(desc, callnum, tc, 0);
117010203SAli.Saidi@ARM.com}
117110203SAli.Saidi@ARM.com
117213031Sbrandon.potter@amd.comSyscallReturn
117313995Sbrandon.potter@amd.commknodFunc(SyscallDesc *desc, int num, ThreadContext *tc)
117413031Sbrandon.potter@amd.com{
117513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
117613031Sbrandon.potter@amd.com    int index = 0;
117713031Sbrandon.potter@amd.com    std::string path;
117814024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
117913031Sbrandon.potter@amd.com        return -EFAULT;
118013031Sbrandon.potter@amd.com
118113883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
118213031Sbrandon.potter@amd.com    mode_t mode = p->getSyscallArg(tc, index);
118313031Sbrandon.potter@amd.com    dev_t dev = p->getSyscallArg(tc, index);
118413031Sbrandon.potter@amd.com
118513031Sbrandon.potter@amd.com    auto result = mknod(path.c_str(), mode, dev);
118613031Sbrandon.potter@amd.com    return (result == -1) ? -errno : result;
118713031Sbrandon.potter@amd.com}
118813031Sbrandon.potter@amd.com
118913031Sbrandon.potter@amd.comSyscallReturn
119013995Sbrandon.potter@amd.comchdirFunc(SyscallDesc *desc, int num, ThreadContext *tc)
119113031Sbrandon.potter@amd.com{
119213995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
119313031Sbrandon.potter@amd.com    int index = 0;
119413031Sbrandon.potter@amd.com    std::string path;
119514024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
119613031Sbrandon.potter@amd.com        return -EFAULT;
119713031Sbrandon.potter@amd.com
119813883Sdavid.hashe@amd.com    std::string tgt_cwd;
119913883Sdavid.hashe@amd.com    if (startswith(path, "/")) {
120013883Sdavid.hashe@amd.com        tgt_cwd = path;
120113883Sdavid.hashe@amd.com    } else {
120213883Sdavid.hashe@amd.com        char buf[PATH_MAX];
120313883Sdavid.hashe@amd.com        tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf);
120413883Sdavid.hashe@amd.com    }
120513883Sdavid.hashe@amd.com    std::string host_cwd = p->checkPathRedirect(tgt_cwd);
120613031Sbrandon.potter@amd.com
120713883Sdavid.hashe@amd.com    int result = chdir(host_cwd.c_str());
120813883Sdavid.hashe@amd.com
120913883Sdavid.hashe@amd.com    if (result == -1)
121013883Sdavid.hashe@amd.com        return -errno;
121113883Sdavid.hashe@amd.com
121213883Sdavid.hashe@amd.com    p->hostCwd = host_cwd;
121313883Sdavid.hashe@amd.com    p->tgtCwd = tgt_cwd;
121413883Sdavid.hashe@amd.com    return result;
121513031Sbrandon.potter@amd.com}
121613031Sbrandon.potter@amd.com
121713031Sbrandon.potter@amd.comSyscallReturn
121813995Sbrandon.potter@amd.comrmdirFunc(SyscallDesc *desc, int num, ThreadContext *tc)
121913031Sbrandon.potter@amd.com{
122013995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
122113031Sbrandon.potter@amd.com    int index = 0;
122213031Sbrandon.potter@amd.com    std::string path;
122314024Sgabeblack@google.com    if (!tc->getVirtProxy().tryReadString(path, p->getSyscallArg(tc, index)))
122413031Sbrandon.potter@amd.com        return -EFAULT;
122513031Sbrandon.potter@amd.com
122613883Sdavid.hashe@amd.com    path = p->checkPathRedirect(path);
122713031Sbrandon.potter@amd.com
122813031Sbrandon.potter@amd.com    auto result = rmdir(path.c_str());
122913031Sbrandon.potter@amd.com    return (result == -1) ? -errno : result;
123013031Sbrandon.potter@amd.com}
123113031Sbrandon.potter@amd.com
123213539Sjavier.setoain@arm.com#if defined(SYS_getdents) || defined(SYS_getdents64)
123313539Sjavier.setoain@arm.comtemplate<typename DE, int SYS_NUM>
123413539Sjavier.setoain@arm.comstatic SyscallReturn
123513995Sbrandon.potter@amd.comgetdentsImpl(SyscallDesc *desc, int callnum, ThreadContext *tc)
123613031Sbrandon.potter@amd.com{
123713031Sbrandon.potter@amd.com    int index = 0;
123813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
123913031Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
124013031Sbrandon.potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
124113031Sbrandon.potter@amd.com    unsigned count = p->getSyscallArg(tc, index);
124213031Sbrandon.potter@amd.com
124313031Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
124413031Sbrandon.potter@amd.com    if (!hbfdp)
124513031Sbrandon.potter@amd.com        return -EBADF;
124613031Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
124713031Sbrandon.potter@amd.com
124813031Sbrandon.potter@amd.com    BufferArg buf_arg(buf_ptr, count);
124913539Sjavier.setoain@arm.com    auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
125013031Sbrandon.potter@amd.com
125113031Sbrandon.potter@amd.com    if (status == -1)
125213031Sbrandon.potter@amd.com        return -errno;
125313031Sbrandon.potter@amd.com
125413031Sbrandon.potter@amd.com    unsigned traversed = 0;
125513031Sbrandon.potter@amd.com    while (traversed < status) {
125613539Sjavier.setoain@arm.com        DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
125713031Sbrandon.potter@amd.com
125813031Sbrandon.potter@amd.com        auto host_reclen = buffer->d_reclen;
125913031Sbrandon.potter@amd.com
126013031Sbrandon.potter@amd.com        /**
126113031Sbrandon.potter@amd.com         * Convert the byte ordering from the host to the target before
126213031Sbrandon.potter@amd.com         * passing the data back into the target's address space to preserve
126313031Sbrandon.potter@amd.com         * endianness.
126413031Sbrandon.potter@amd.com         */
126513031Sbrandon.potter@amd.com        buffer->d_ino = htog(buffer->d_ino);
126613031Sbrandon.potter@amd.com        buffer->d_off = htog(buffer->d_off);
126713031Sbrandon.potter@amd.com        buffer->d_reclen = htog(buffer->d_reclen);
126813031Sbrandon.potter@amd.com
126913031Sbrandon.potter@amd.com        traversed += host_reclen;
127013031Sbrandon.potter@amd.com    }
127113031Sbrandon.potter@amd.com
127214024Sgabeblack@google.com    buf_arg.copyOut(tc->getVirtProxy());
127313031Sbrandon.potter@amd.com    return status;
127413031Sbrandon.potter@amd.com}
127513448Sciro.santilli@arm.com#endif
127613539Sjavier.setoain@arm.com
127713539Sjavier.setoain@arm.com#if defined(SYS_getdents)
127813539Sjavier.setoain@arm.comSyscallReturn
127913995Sbrandon.potter@amd.comgetdentsFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
128013539Sjavier.setoain@arm.com{
128113539Sjavier.setoain@arm.com    typedef struct linux_dirent {
128213539Sjavier.setoain@arm.com        unsigned long d_ino;
128313539Sjavier.setoain@arm.com        unsigned long d_off;
128413539Sjavier.setoain@arm.com        unsigned short d_reclen;
128513539Sjavier.setoain@arm.com        char dname[];
128613539Sjavier.setoain@arm.com    } LinDent;
128713539Sjavier.setoain@arm.com
128813995Sbrandon.potter@amd.com    return getdentsImpl<LinDent, SYS_getdents>(desc, callnum, tc);
128913539Sjavier.setoain@arm.com}
129013539Sjavier.setoain@arm.com#endif
129113539Sjavier.setoain@arm.com
129213539Sjavier.setoain@arm.com#if defined(SYS_getdents64)
129313539Sjavier.setoain@arm.comSyscallReturn
129413995Sbrandon.potter@amd.comgetdents64Func(SyscallDesc *desc, int callnum, ThreadContext *tc)
129513539Sjavier.setoain@arm.com{
129613539Sjavier.setoain@arm.com    typedef struct linux_dirent64 {
129713539Sjavier.setoain@arm.com        ino64_t d_ino;
129813539Sjavier.setoain@arm.com        off64_t d_off;
129913539Sjavier.setoain@arm.com        unsigned short d_reclen;
130013539Sjavier.setoain@arm.com        char dname[];
130113539Sjavier.setoain@arm.com    } LinDent64;
130213539Sjavier.setoain@arm.com
130313995Sbrandon.potter@amd.com    return getdentsImpl<LinDent64, SYS_getdents64>(desc, callnum, tc);
130413539Sjavier.setoain@arm.com}
130513539Sjavier.setoain@arm.com#endif
130613568Sbrandon.potter@amd.com
130713568Sbrandon.potter@amd.comSyscallReturn
130813995Sbrandon.potter@amd.comshutdownFunc(SyscallDesc *desc, int num, ThreadContext *tc)
130913568Sbrandon.potter@amd.com{
131013568Sbrandon.potter@amd.com    int index = 0;
131113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
131213568Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
131313568Sbrandon.potter@amd.com    int how = p->getSyscallArg(tc, index);
131413568Sbrandon.potter@amd.com
131513568Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
131613568Sbrandon.potter@amd.com    if (!sfdp)
131713568Sbrandon.potter@amd.com        return -EBADF;
131813568Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
131913568Sbrandon.potter@amd.com
132013568Sbrandon.potter@amd.com    int retval = shutdown(sim_fd, how);
132113568Sbrandon.potter@amd.com
132213568Sbrandon.potter@amd.com    return (retval == -1) ? -errno : retval;
132313568Sbrandon.potter@amd.com}
132413568Sbrandon.potter@amd.com
132513568Sbrandon.potter@amd.comSyscallReturn
132613995Sbrandon.potter@amd.combindFunc(SyscallDesc *desc, int num, ThreadContext *tc)
132713568Sbrandon.potter@amd.com{
132813568Sbrandon.potter@amd.com    int index = 0;
132913995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
133013568Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
133113568Sbrandon.potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
133213568Sbrandon.potter@amd.com    int addrlen = p->getSyscallArg(tc, index);
133313568Sbrandon.potter@amd.com
133413568Sbrandon.potter@amd.com    BufferArg bufSock(buf_ptr, addrlen);
133514024Sgabeblack@google.com    bufSock.copyIn(tc->getVirtProxy());
133613568Sbrandon.potter@amd.com
133713568Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
133813568Sbrandon.potter@amd.com    if (!sfdp)
133913568Sbrandon.potter@amd.com        return -EBADF;
134013568Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
134113568Sbrandon.potter@amd.com
134213568Sbrandon.potter@amd.com    int status = ::bind(sim_fd,
134313568Sbrandon.potter@amd.com                        (struct sockaddr *)bufSock.bufferPtr(),
134413568Sbrandon.potter@amd.com                        addrlen);
134513568Sbrandon.potter@amd.com
134613568Sbrandon.potter@amd.com    return (status == -1) ? -errno : status;
134713568Sbrandon.potter@amd.com}
134813568Sbrandon.potter@amd.com
134913568Sbrandon.potter@amd.comSyscallReturn
135013995Sbrandon.potter@amd.comlistenFunc(SyscallDesc *desc, int num, ThreadContext *tc)
135113568Sbrandon.potter@amd.com{
135213568Sbrandon.potter@amd.com    int index = 0;
135313995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
135413568Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
135513568Sbrandon.potter@amd.com    int backlog = p->getSyscallArg(tc, index);
135613568Sbrandon.potter@amd.com
135713568Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
135813568Sbrandon.potter@amd.com    if (!sfdp)
135913568Sbrandon.potter@amd.com        return -EBADF;
136013568Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
136113568Sbrandon.potter@amd.com
136213568Sbrandon.potter@amd.com    int status = listen(sim_fd, backlog);
136313568Sbrandon.potter@amd.com
136413568Sbrandon.potter@amd.com    return (status == -1) ? -errno : status;
136513568Sbrandon.potter@amd.com}
136613568Sbrandon.potter@amd.com
136713568Sbrandon.potter@amd.comSyscallReturn
136813995Sbrandon.potter@amd.comconnectFunc(SyscallDesc *desc, int num, ThreadContext *tc)
136913568Sbrandon.potter@amd.com{
137013568Sbrandon.potter@amd.com    int index = 0;
137113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
137213568Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
137313568Sbrandon.potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
137413568Sbrandon.potter@amd.com    int addrlen = p->getSyscallArg(tc, index);
137513568Sbrandon.potter@amd.com
137613568Sbrandon.potter@amd.com    BufferArg addr(buf_ptr, addrlen);
137714024Sgabeblack@google.com    addr.copyIn(tc->getVirtProxy());
137813568Sbrandon.potter@amd.com
137913568Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
138013568Sbrandon.potter@amd.com    if (!sfdp)
138113568Sbrandon.potter@amd.com        return -EBADF;
138213568Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
138313568Sbrandon.potter@amd.com
138413568Sbrandon.potter@amd.com    int status = connect(sim_fd,
138513568Sbrandon.potter@amd.com                         (struct sockaddr *)addr.bufferPtr(),
138613568Sbrandon.potter@amd.com                         (socklen_t)addrlen);
138713568Sbrandon.potter@amd.com
138813568Sbrandon.potter@amd.com    return (status == -1) ? -errno : status;
138913568Sbrandon.potter@amd.com}
139013569Sbrandon.potter@amd.com
139113569Sbrandon.potter@amd.comSyscallReturn
139213995Sbrandon.potter@amd.comrecvfromFunc(SyscallDesc *desc, int num, ThreadContext *tc)
139313569Sbrandon.potter@amd.com{
139413569Sbrandon.potter@amd.com    int index = 0;
139513995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
139613569Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
139713569Sbrandon.potter@amd.com    Addr bufrPtr = p->getSyscallArg(tc, index);
139813569Sbrandon.potter@amd.com    size_t bufrLen = p->getSyscallArg(tc, index);
139913569Sbrandon.potter@amd.com    int flags = p->getSyscallArg(tc, index);
140013569Sbrandon.potter@amd.com    Addr addrPtr = p->getSyscallArg(tc, index);
140113569Sbrandon.potter@amd.com    Addr addrlenPtr = p->getSyscallArg(tc, index);
140213569Sbrandon.potter@amd.com
140313569Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
140413569Sbrandon.potter@amd.com    if (!sfdp)
140513569Sbrandon.potter@amd.com        return -EBADF;
140613569Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
140713569Sbrandon.potter@amd.com
140813569Sbrandon.potter@amd.com    // Reserve buffer space.
140913569Sbrandon.potter@amd.com    BufferArg bufrBuf(bufrPtr, bufrLen);
141013569Sbrandon.potter@amd.com
141113569Sbrandon.potter@amd.com    // Get address length.
141213569Sbrandon.potter@amd.com    socklen_t addrLen = 0;
141313569Sbrandon.potter@amd.com    if (addrlenPtr != 0) {
141413569Sbrandon.potter@amd.com        // Read address length parameter.
141513569Sbrandon.potter@amd.com        BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
141614024Sgabeblack@google.com        addrlenBuf.copyIn(tc->getVirtProxy());
141713569Sbrandon.potter@amd.com        addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
141813569Sbrandon.potter@amd.com    }
141913569Sbrandon.potter@amd.com
142013569Sbrandon.potter@amd.com    struct sockaddr sa, *sap = NULL;
142113569Sbrandon.potter@amd.com    if (addrLen != 0) {
142213569Sbrandon.potter@amd.com        BufferArg addrBuf(addrPtr, addrLen);
142314024Sgabeblack@google.com        addrBuf.copyIn(tc->getVirtProxy());
142413569Sbrandon.potter@amd.com        memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
142513569Sbrandon.potter@amd.com               sizeof(struct sockaddr));
142613569Sbrandon.potter@amd.com        sap = &sa;
142713569Sbrandon.potter@amd.com    }
142813569Sbrandon.potter@amd.com
142913569Sbrandon.potter@amd.com    ssize_t recvd_size = recvfrom(sim_fd,
143013569Sbrandon.potter@amd.com                                  (void *)bufrBuf.bufferPtr(),
143113569Sbrandon.potter@amd.com                                  bufrLen, flags, sap, (socklen_t *)&addrLen);
143213569Sbrandon.potter@amd.com
143313569Sbrandon.potter@amd.com    if (recvd_size == -1)
143413569Sbrandon.potter@amd.com        return -errno;
143513569Sbrandon.potter@amd.com
143613569Sbrandon.potter@amd.com    // Pass the received data out.
143714024Sgabeblack@google.com    bufrBuf.copyOut(tc->getVirtProxy());
143813569Sbrandon.potter@amd.com
143913569Sbrandon.potter@amd.com    // Copy address to addrPtr and pass it on.
144013569Sbrandon.potter@amd.com    if (sap != NULL) {
144113569Sbrandon.potter@amd.com        BufferArg addrBuf(addrPtr, addrLen);
144213569Sbrandon.potter@amd.com        memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
144314024Sgabeblack@google.com        addrBuf.copyOut(tc->getVirtProxy());
144413569Sbrandon.potter@amd.com    }
144513569Sbrandon.potter@amd.com
144613569Sbrandon.potter@amd.com    // Copy len to addrlenPtr and pass it on.
144713569Sbrandon.potter@amd.com    if (addrLen != 0) {
144813569Sbrandon.potter@amd.com        BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
144913569Sbrandon.potter@amd.com        *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
145014024Sgabeblack@google.com        addrlenBuf.copyOut(tc->getVirtProxy());
145113569Sbrandon.potter@amd.com    }
145213569Sbrandon.potter@amd.com
145313569Sbrandon.potter@amd.com    return recvd_size;
145413569Sbrandon.potter@amd.com}
145513569Sbrandon.potter@amd.com
145613569Sbrandon.potter@amd.comSyscallReturn
145713995Sbrandon.potter@amd.comsendtoFunc(SyscallDesc *desc, int num, ThreadContext *tc)
145813569Sbrandon.potter@amd.com{
145913569Sbrandon.potter@amd.com    int index = 0;
146013995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
146113569Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
146213569Sbrandon.potter@amd.com    Addr bufrPtr = p->getSyscallArg(tc, index);
146313569Sbrandon.potter@amd.com    size_t bufrLen = p->getSyscallArg(tc, index);
146413569Sbrandon.potter@amd.com    int flags = p->getSyscallArg(tc, index);
146513569Sbrandon.potter@amd.com    Addr addrPtr = p->getSyscallArg(tc, index);
146613569Sbrandon.potter@amd.com    socklen_t addrLen = p->getSyscallArg(tc, index);
146713569Sbrandon.potter@amd.com
146813569Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
146913569Sbrandon.potter@amd.com    if (!sfdp)
147013569Sbrandon.potter@amd.com        return -EBADF;
147113569Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
147213569Sbrandon.potter@amd.com
147313569Sbrandon.potter@amd.com    // Reserve buffer space.
147413569Sbrandon.potter@amd.com    BufferArg bufrBuf(bufrPtr, bufrLen);
147514024Sgabeblack@google.com    bufrBuf.copyIn(tc->getVirtProxy());
147613569Sbrandon.potter@amd.com
147713569Sbrandon.potter@amd.com    struct sockaddr sa, *sap = nullptr;
147813569Sbrandon.potter@amd.com    memset(&sa, 0, sizeof(sockaddr));
147913569Sbrandon.potter@amd.com    if (addrLen != 0) {
148013569Sbrandon.potter@amd.com        BufferArg addrBuf(addrPtr, addrLen);
148114024Sgabeblack@google.com        addrBuf.copyIn(tc->getVirtProxy());
148213569Sbrandon.potter@amd.com        memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
148313569Sbrandon.potter@amd.com        sap = &sa;
148413569Sbrandon.potter@amd.com    }
148513569Sbrandon.potter@amd.com
148613569Sbrandon.potter@amd.com    ssize_t sent_size = sendto(sim_fd,
148713569Sbrandon.potter@amd.com                               (void *)bufrBuf.bufferPtr(),
148813569Sbrandon.potter@amd.com                               bufrLen, flags, sap, (socklen_t)addrLen);
148913569Sbrandon.potter@amd.com
149013569Sbrandon.potter@amd.com    return (sent_size == -1) ? -errno : sent_size;
149113569Sbrandon.potter@amd.com}
149213569Sbrandon.potter@amd.com
149313569Sbrandon.potter@amd.comSyscallReturn
149413995Sbrandon.potter@amd.comrecvmsgFunc(SyscallDesc *desc, int num, ThreadContext *tc)
149513569Sbrandon.potter@amd.com{
149613569Sbrandon.potter@amd.com    int index = 0;
149713995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
149813569Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
149913569Sbrandon.potter@amd.com    Addr msgPtr = p->getSyscallArg(tc, index);
150013569Sbrandon.potter@amd.com    int flags = p->getSyscallArg(tc, index);
150113569Sbrandon.potter@amd.com
150213569Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
150313569Sbrandon.potter@amd.com    if (!sfdp)
150413569Sbrandon.potter@amd.com        return -EBADF;
150513569Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
150613569Sbrandon.potter@amd.com
150713569Sbrandon.potter@amd.com     /**
150813569Sbrandon.potter@amd.com      *  struct msghdr {
150913569Sbrandon.potter@amd.com      *     void         *msg_name;       // optional address
151013569Sbrandon.potter@amd.com      *    socklen_t     msg_namelen;    // size of address
151113569Sbrandon.potter@amd.com      *    struct iovec *msg_iov;        // iovec array
151213569Sbrandon.potter@amd.com      *    size_t        msg_iovlen;     // number entries in msg_iov
151313569Sbrandon.potter@amd.com      *    i                             // entries correspond to buffer
151413569Sbrandon.potter@amd.com      *    void         *msg_control;    // ancillary data
151513569Sbrandon.potter@amd.com      *    size_t        msg_controllen; // ancillary data buffer len
151613569Sbrandon.potter@amd.com      *    int           msg_flags;      // flags on received message
151713569Sbrandon.potter@amd.com      *  };
151813569Sbrandon.potter@amd.com      *
151913569Sbrandon.potter@amd.com      *  struct iovec {
152013569Sbrandon.potter@amd.com      *    void  *iov_base;              // starting address
152113569Sbrandon.potter@amd.com      *    size_t iov_len;               // number of bytes to transfer
152213569Sbrandon.potter@amd.com      *  };
152313569Sbrandon.potter@amd.com      */
152413569Sbrandon.potter@amd.com
152513569Sbrandon.potter@amd.com    /**
152613569Sbrandon.potter@amd.com     * The plan with this system call is to replace all of the pointers in the
152713569Sbrandon.potter@amd.com     * structure and the substructure with BufferArg class pointers. We will
152813569Sbrandon.potter@amd.com     * copy every field from the structures into our BufferArg classes.
152913569Sbrandon.potter@amd.com     */
153013569Sbrandon.potter@amd.com    BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
153114024Sgabeblack@google.com    msgBuf.copyIn(tc->getVirtProxy());
153213569Sbrandon.potter@amd.com    struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
153313569Sbrandon.potter@amd.com
153413569Sbrandon.potter@amd.com    /**
153513569Sbrandon.potter@amd.com     * We will use these address place holders to retain the pointers which
153613569Sbrandon.potter@amd.com     * we are going to replace with our own buffers in our simulator address
153713569Sbrandon.potter@amd.com     * space.
153813569Sbrandon.potter@amd.com     */
153913569Sbrandon.potter@amd.com    Addr msg_name_phold = 0;
154013569Sbrandon.potter@amd.com    Addr msg_iov_phold = 0;
154113569Sbrandon.potter@amd.com    Addr iovec_base_phold[msgHdr->msg_iovlen];
154213569Sbrandon.potter@amd.com    Addr msg_control_phold = 0;
154313569Sbrandon.potter@amd.com
154413569Sbrandon.potter@amd.com    /**
154513569Sbrandon.potter@amd.com     * Record msg_name pointer then replace with buffer pointer.
154613569Sbrandon.potter@amd.com     */
154713569Sbrandon.potter@amd.com    BufferArg *nameBuf = NULL;
154813569Sbrandon.potter@amd.com    if (msgHdr->msg_name) {
154913569Sbrandon.potter@amd.com        /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
155013569Sbrandon.potter@amd.com        /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
155114024Sgabeblack@google.com        /*3*/nameBuf->copyIn(tc->getVirtProxy());
155213569Sbrandon.potter@amd.com        /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
155313569Sbrandon.potter@amd.com    }
155413569Sbrandon.potter@amd.com
155513569Sbrandon.potter@amd.com    /**
155613569Sbrandon.potter@amd.com     * Record msg_iov pointer then replace with buffer pointer. Also, setup
155713569Sbrandon.potter@amd.com     * an array of buffer pointers for the iovec structs record and replace
155813569Sbrandon.potter@amd.com     * their pointers with buffer pointers.
155913569Sbrandon.potter@amd.com     */
156013569Sbrandon.potter@amd.com    BufferArg *iovBuf = NULL;
156113569Sbrandon.potter@amd.com    BufferArg *iovecBuf[msgHdr->msg_iovlen];
156213569Sbrandon.potter@amd.com    for (int i = 0; i < msgHdr->msg_iovlen; i++) {
156313569Sbrandon.potter@amd.com        iovec_base_phold[i] = 0;
156413569Sbrandon.potter@amd.com        iovecBuf[i] = NULL;
156513569Sbrandon.potter@amd.com    }
156613569Sbrandon.potter@amd.com
156713569Sbrandon.potter@amd.com    if (msgHdr->msg_iov) {
156813569Sbrandon.potter@amd.com        /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
156913569Sbrandon.potter@amd.com        /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
157013569Sbrandon.potter@amd.com                                    sizeof(struct iovec));
157114024Sgabeblack@google.com        /*3*/iovBuf->copyIn(tc->getVirtProxy());
157213569Sbrandon.potter@amd.com        for (int i = 0; i < msgHdr->msg_iovlen; i++) {
157313569Sbrandon.potter@amd.com            if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
157413569Sbrandon.potter@amd.com                /*1*/iovec_base_phold[i] =
157513569Sbrandon.potter@amd.com                     (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
157613569Sbrandon.potter@amd.com                /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
157713569Sbrandon.potter@amd.com                     ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
157814024Sgabeblack@google.com                /*3*/iovecBuf[i]->copyIn(tc->getVirtProxy());
157913569Sbrandon.potter@amd.com                /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
158013569Sbrandon.potter@amd.com                     iovecBuf[i]->bufferPtr();
158113569Sbrandon.potter@amd.com            }
158213569Sbrandon.potter@amd.com        }
158313569Sbrandon.potter@amd.com        /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
158413569Sbrandon.potter@amd.com    }
158513569Sbrandon.potter@amd.com
158613569Sbrandon.potter@amd.com    /**
158713569Sbrandon.potter@amd.com     * Record msg_control pointer then replace with buffer pointer.
158813569Sbrandon.potter@amd.com     */
158913569Sbrandon.potter@amd.com    BufferArg *controlBuf = NULL;
159013569Sbrandon.potter@amd.com    if (msgHdr->msg_control) {
159113569Sbrandon.potter@amd.com        /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
159213569Sbrandon.potter@amd.com        /*2*/controlBuf = new BufferArg(msg_control_phold,
159313569Sbrandon.potter@amd.com                                        CMSG_ALIGN(msgHdr->msg_controllen));
159414024Sgabeblack@google.com        /*3*/controlBuf->copyIn(tc->getVirtProxy());
159513569Sbrandon.potter@amd.com        /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
159613569Sbrandon.potter@amd.com    }
159713569Sbrandon.potter@amd.com
159813569Sbrandon.potter@amd.com    ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
159913569Sbrandon.potter@amd.com
160013569Sbrandon.potter@amd.com    if (recvd_size < 0)
160113569Sbrandon.potter@amd.com        return -errno;
160213569Sbrandon.potter@amd.com
160313569Sbrandon.potter@amd.com    if (msgHdr->msg_name) {
160414024Sgabeblack@google.com        nameBuf->copyOut(tc->getVirtProxy());
160513569Sbrandon.potter@amd.com        delete(nameBuf);
160613569Sbrandon.potter@amd.com        msgHdr->msg_name = (void *)msg_name_phold;
160713569Sbrandon.potter@amd.com    }
160813569Sbrandon.potter@amd.com
160913569Sbrandon.potter@amd.com    if (msgHdr->msg_iov) {
161013569Sbrandon.potter@amd.com        for (int i = 0; i< msgHdr->msg_iovlen; i++) {
161113569Sbrandon.potter@amd.com            if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
161214024Sgabeblack@google.com                iovecBuf[i]->copyOut(tc->getVirtProxy());
161313569Sbrandon.potter@amd.com                delete iovecBuf[i];
161413569Sbrandon.potter@amd.com                ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
161513569Sbrandon.potter@amd.com                (void *)iovec_base_phold[i];
161613569Sbrandon.potter@amd.com            }
161713569Sbrandon.potter@amd.com        }
161814024Sgabeblack@google.com        iovBuf->copyOut(tc->getVirtProxy());
161913569Sbrandon.potter@amd.com        delete iovBuf;
162013569Sbrandon.potter@amd.com        msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
162113569Sbrandon.potter@amd.com    }
162213569Sbrandon.potter@amd.com
162313569Sbrandon.potter@amd.com    if (msgHdr->msg_control) {
162414024Sgabeblack@google.com        controlBuf->copyOut(tc->getVirtProxy());
162513569Sbrandon.potter@amd.com        delete(controlBuf);
162613569Sbrandon.potter@amd.com        msgHdr->msg_control = (void *)msg_control_phold;
162713569Sbrandon.potter@amd.com    }
162813569Sbrandon.potter@amd.com
162914024Sgabeblack@google.com    msgBuf.copyOut(tc->getVirtProxy());
163013569Sbrandon.potter@amd.com
163113569Sbrandon.potter@amd.com    return recvd_size;
163213569Sbrandon.potter@amd.com}
163313569Sbrandon.potter@amd.com
163413569Sbrandon.potter@amd.comSyscallReturn
163513995Sbrandon.potter@amd.comsendmsgFunc(SyscallDesc *desc, int num, ThreadContext *tc)
163613569Sbrandon.potter@amd.com{
163713569Sbrandon.potter@amd.com    int index = 0;
163813995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
163913569Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
164013569Sbrandon.potter@amd.com    Addr msgPtr = p->getSyscallArg(tc, index);
164113569Sbrandon.potter@amd.com    int flags = p->getSyscallArg(tc, index);
164213569Sbrandon.potter@amd.com
164313569Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
164413569Sbrandon.potter@amd.com    if (!sfdp)
164513569Sbrandon.potter@amd.com        return -EBADF;
164613569Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
164713569Sbrandon.potter@amd.com
164813569Sbrandon.potter@amd.com    /**
164913569Sbrandon.potter@amd.com     * Reserve buffer space.
165013569Sbrandon.potter@amd.com     */
165113569Sbrandon.potter@amd.com    BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
165214024Sgabeblack@google.com    msgBuf.copyIn(tc->getVirtProxy());
165313569Sbrandon.potter@amd.com    struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
165413569Sbrandon.potter@amd.com
165513569Sbrandon.potter@amd.com    /**
165613569Sbrandon.potter@amd.com     * Assuming msgHdr.msg_iovlen >= 1, then there is no point calling
165713569Sbrandon.potter@amd.com     * recvmsg without a buffer.
165813569Sbrandon.potter@amd.com     */
165913569Sbrandon.potter@amd.com    struct iovec *iovPtr = msgHdr.msg_iov;
166013569Sbrandon.potter@amd.com    BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
166114024Sgabeblack@google.com    iovBuf.copyIn(tc->getVirtProxy());
166213569Sbrandon.potter@amd.com    struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
166313569Sbrandon.potter@amd.com    msgHdr.msg_iov = iov;
166413569Sbrandon.potter@amd.com
166513569Sbrandon.potter@amd.com    /**
166613569Sbrandon.potter@amd.com     * Cannot instantiate buffers till inside the loop.
166713569Sbrandon.potter@amd.com     * Create array to hold buffer addresses, to be used during copyIn of
166813569Sbrandon.potter@amd.com     * send data.
166913569Sbrandon.potter@amd.com     */
167013569Sbrandon.potter@amd.com    BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
167113569Sbrandon.potter@amd.com                                                   * sizeof(BufferArg *));
167213569Sbrandon.potter@amd.com
167313569Sbrandon.potter@amd.com    /**
167413569Sbrandon.potter@amd.com     * Iterate through the iovec structures:
167513569Sbrandon.potter@amd.com     * Get the base buffer addreses, reserve iov_len amount of space for each.
167613569Sbrandon.potter@amd.com     * Put the buf address into the bufferArray for later retrieval.
167713569Sbrandon.potter@amd.com     */
167813569Sbrandon.potter@amd.com    for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
167913569Sbrandon.potter@amd.com        Addr basePtr = (Addr) iov[iovIndex].iov_base;
168013569Sbrandon.potter@amd.com        bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
168114024Sgabeblack@google.com        bufferArray[iovIndex]->copyIn(tc->getVirtProxy());
168213569Sbrandon.potter@amd.com        iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
168313569Sbrandon.potter@amd.com    }
168413569Sbrandon.potter@amd.com
168513569Sbrandon.potter@amd.com    ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
168613569Sbrandon.potter@amd.com    int local_errno = errno;
168713569Sbrandon.potter@amd.com
168813569Sbrandon.potter@amd.com    /**
168913569Sbrandon.potter@amd.com     * Free dynamically allocated memory.
169013569Sbrandon.potter@amd.com     */
169113569Sbrandon.potter@amd.com    for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
169213569Sbrandon.potter@amd.com        BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
169313569Sbrandon.potter@amd.com        delete(baseBuf);
169413569Sbrandon.potter@amd.com    }
169513569Sbrandon.potter@amd.com
169613569Sbrandon.potter@amd.com    /**
169713569Sbrandon.potter@amd.com     * Malloced above.
169813569Sbrandon.potter@amd.com     */
169913569Sbrandon.potter@amd.com    free(bufferArray);
170013569Sbrandon.potter@amd.com
170113569Sbrandon.potter@amd.com    return (sent_size < 0) ? -local_errno : sent_size;
170213569Sbrandon.potter@amd.com}
170313569Sbrandon.potter@amd.com
170413571Sbrandon.potter@amd.comSyscallReturn
170513995Sbrandon.potter@amd.comgetsockoptFunc(SyscallDesc *desc, int num, ThreadContext *tc)
170613571Sbrandon.potter@amd.com{
170713571Sbrandon.potter@amd.com    // union of all possible return value types from getsockopt
170813571Sbrandon.potter@amd.com    union val {
170913571Sbrandon.potter@amd.com        int i_val;
171013571Sbrandon.potter@amd.com        long l_val;
171113571Sbrandon.potter@amd.com        struct linger linger_val;
171213571Sbrandon.potter@amd.com        struct timeval timeval_val;
171313571Sbrandon.potter@amd.com    } val;
171413571Sbrandon.potter@amd.com
171513571Sbrandon.potter@amd.com    int index = 0;
171613995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
171713571Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
171813571Sbrandon.potter@amd.com    int level = p->getSyscallArg(tc, index);
171913571Sbrandon.potter@amd.com    int optname = p->getSyscallArg(tc, index);
172013571Sbrandon.potter@amd.com    Addr valPtr = p->getSyscallArg(tc, index);
172113571Sbrandon.potter@amd.com    Addr lenPtr = p->getSyscallArg(tc, index);
172213571Sbrandon.potter@amd.com
172313571Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
172413571Sbrandon.potter@amd.com    if (!sfdp)
172513571Sbrandon.potter@amd.com        return -EBADF;
172613571Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
172713571Sbrandon.potter@amd.com
172813571Sbrandon.potter@amd.com    socklen_t len = sizeof(val);
172913571Sbrandon.potter@amd.com    int status = getsockopt(sim_fd, level, optname, &val, &len);
173013571Sbrandon.potter@amd.com
173113571Sbrandon.potter@amd.com    if (status == -1)
173213571Sbrandon.potter@amd.com        return -errno;
173313571Sbrandon.potter@amd.com
173413571Sbrandon.potter@amd.com    // copy val to valPtr and pass it on
173513571Sbrandon.potter@amd.com    BufferArg valBuf(valPtr, sizeof(val));
173613571Sbrandon.potter@amd.com    memcpy(valBuf.bufferPtr(), &val, sizeof(val));
173714024Sgabeblack@google.com    valBuf.copyOut(tc->getVirtProxy());
173813571Sbrandon.potter@amd.com
173913571Sbrandon.potter@amd.com    // copy len to lenPtr and pass  it on
174013571Sbrandon.potter@amd.com    BufferArg lenBuf(lenPtr, sizeof(len));
174113571Sbrandon.potter@amd.com    memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
174214024Sgabeblack@google.com    lenBuf.copyOut(tc->getVirtProxy());
174313571Sbrandon.potter@amd.com
174413571Sbrandon.potter@amd.com    return status;
174513571Sbrandon.potter@amd.com}
174613571Sbrandon.potter@amd.com
174713571Sbrandon.potter@amd.comSyscallReturn
174813995Sbrandon.potter@amd.comgetsocknameFunc(SyscallDesc *desc, int num, ThreadContext *tc)
174913571Sbrandon.potter@amd.com{
175013571Sbrandon.potter@amd.com    int index = 0;
175113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
175213571Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
175313571Sbrandon.potter@amd.com    Addr addrPtr = p->getSyscallArg(tc, index);
175413571Sbrandon.potter@amd.com    Addr lenPtr = p->getSyscallArg(tc, index);
175513571Sbrandon.potter@amd.com
175613571Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
175713571Sbrandon.potter@amd.com    if (!sfdp)
175813571Sbrandon.potter@amd.com        return -EBADF;
175913571Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
176013571Sbrandon.potter@amd.com
176113571Sbrandon.potter@amd.com    // lenPtr is an in-out paramenter:
176213571Sbrandon.potter@amd.com    // sending the address length in, conveying the final length out
176313571Sbrandon.potter@amd.com
176413571Sbrandon.potter@amd.com    // Read in the value of len from the passed pointer.
176513571Sbrandon.potter@amd.com    BufferArg lenBuf(lenPtr, sizeof(socklen_t));
176614024Sgabeblack@google.com    lenBuf.copyIn(tc->getVirtProxy());
176713571Sbrandon.potter@amd.com    socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
176813571Sbrandon.potter@amd.com
176913571Sbrandon.potter@amd.com    struct sockaddr sa;
177013571Sbrandon.potter@amd.com    int status = getsockname(sim_fd, &sa, &len);
177113571Sbrandon.potter@amd.com
177213571Sbrandon.potter@amd.com    if (status == -1)
177313571Sbrandon.potter@amd.com        return -errno;
177413571Sbrandon.potter@amd.com
177513571Sbrandon.potter@amd.com    // Copy address to addrPtr and pass it on.
177613571Sbrandon.potter@amd.com    BufferArg addrBuf(addrPtr, sizeof(sa));
177713571Sbrandon.potter@amd.com    memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
177814024Sgabeblack@google.com    addrBuf.copyOut(tc->getVirtProxy());
177913571Sbrandon.potter@amd.com
178013571Sbrandon.potter@amd.com    // Copy len to lenPtr and pass  it on.
178113571Sbrandon.potter@amd.com    *(socklen_t *)lenBuf.bufferPtr() = len;
178214024Sgabeblack@google.com    lenBuf.copyOut(tc->getVirtProxy());
178313571Sbrandon.potter@amd.com
178413571Sbrandon.potter@amd.com    return status;
178513571Sbrandon.potter@amd.com}
178613571Sbrandon.potter@amd.com
178713571Sbrandon.potter@amd.comSyscallReturn
178813995Sbrandon.potter@amd.comgetpeernameFunc(SyscallDesc *desc, int num, ThreadContext *tc)
178913571Sbrandon.potter@amd.com{
179013571Sbrandon.potter@amd.com    int index = 0;
179113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
179213571Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
179313571Sbrandon.potter@amd.com    Addr sockAddrPtr = p->getSyscallArg(tc, index);
179413571Sbrandon.potter@amd.com    Addr addrlenPtr = p->getSyscallArg(tc, index);
179513571Sbrandon.potter@amd.com
179613571Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
179713571Sbrandon.potter@amd.com    if (!sfdp)
179813571Sbrandon.potter@amd.com        return -EBADF;
179913571Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
180013571Sbrandon.potter@amd.com
180113571Sbrandon.potter@amd.com    BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
180214024Sgabeblack@google.com    bufAddrlen.copyIn(tc->getVirtProxy());
180313571Sbrandon.potter@amd.com    BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
180413571Sbrandon.potter@amd.com
180513571Sbrandon.potter@amd.com    int retval = getpeername(sim_fd,
180613571Sbrandon.potter@amd.com                             (struct sockaddr *)bufSock.bufferPtr(),
180713571Sbrandon.potter@amd.com                             (unsigned *)bufAddrlen.bufferPtr());
180813571Sbrandon.potter@amd.com
180913571Sbrandon.potter@amd.com    if (retval != -1) {
181014024Sgabeblack@google.com        bufSock.copyOut(tc->getVirtProxy());
181114024Sgabeblack@google.com        bufAddrlen.copyOut(tc->getVirtProxy());
181213571Sbrandon.potter@amd.com    }
181313571Sbrandon.potter@amd.com
181413571Sbrandon.potter@amd.com    return (retval == -1) ? -errno : retval;
181513571Sbrandon.potter@amd.com}
181613571Sbrandon.potter@amd.com
181713571Sbrandon.potter@amd.comSyscallReturn
181813995Sbrandon.potter@amd.comsetsockoptFunc(SyscallDesc *desc, int num, ThreadContext *tc)
181913571Sbrandon.potter@amd.com{
182013571Sbrandon.potter@amd.com    int index = 0;
182113995Sbrandon.potter@amd.com    auto p = tc->getProcessPtr();
182213571Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
182313571Sbrandon.potter@amd.com    int level = p->getSyscallArg(tc, index);
182413571Sbrandon.potter@amd.com    int optname = p->getSyscallArg(tc, index);
182513571Sbrandon.potter@amd.com    Addr valPtr = p->getSyscallArg(tc, index);
182613571Sbrandon.potter@amd.com    socklen_t len = p->getSyscallArg(tc, index);
182713571Sbrandon.potter@amd.com
182813571Sbrandon.potter@amd.com    BufferArg valBuf(valPtr, len);
182914024Sgabeblack@google.com    valBuf.copyIn(tc->getVirtProxy());
183013571Sbrandon.potter@amd.com
183113571Sbrandon.potter@amd.com    auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
183213571Sbrandon.potter@amd.com    if (!sfdp)
183313571Sbrandon.potter@amd.com        return -EBADF;
183413571Sbrandon.potter@amd.com    int sim_fd = sfdp->getSimFD();
183513571Sbrandon.potter@amd.com
183613571Sbrandon.potter@amd.com    int status = setsockopt(sim_fd, level, optname,
183713571Sbrandon.potter@amd.com                            (struct sockaddr *)valBuf.bufferPtr(), len);
183813571Sbrandon.potter@amd.com
183913571Sbrandon.potter@amd.com    return (status == -1) ? -errno : status;
184013571Sbrandon.potter@amd.com}
184113571Sbrandon.potter@amd.com
1842