syscall_emul.cc revision 12796
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>
35360SN/A#include <unistd.h>
36360SN/A
3711911SBrandon.Potter@amd.com#include <csignal>
386712Snate@binkert.org#include <iostream>
39360SN/A#include <string>
40360SN/A
417680Sgblack@eecs.umich.edu#include "arch/utility.hh"
422474SN/A#include "base/chunk_generator.hh"
43360SN/A#include "base/trace.hh"
446658Snate@binkert.org#include "config/the_isa.hh"
452680Sktlim@umich.edu#include "cpu/thread_context.hh"
4612716Smichael.lebeane@amd.com#include "dev/net/dist_iface.hh"
472474SN/A#include "mem/page_table.hh"
48360SN/A#include "sim/process.hh"
498229Snate@binkert.org#include "sim/sim_exit.hh"
5011794Sbrandon.potter@amd.com#include "sim/syscall_debug_macros.hh"
5111794Sbrandon.potter@amd.com#include "sim/syscall_desc.hh"
526029Ssteve.reinhardt@amd.com#include "sim/system.hh"
53360SN/A
54360SN/Ausing namespace std;
552107SN/Ausing namespace TheISA;
56360SN/A
571450SN/ASyscallReturn
5811851Sbrandon.potter@amd.comunimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
592680Sktlim@umich.edu                  ThreadContext *tc)
60360SN/A{
6111794Sbrandon.potter@amd.com    fatal("syscall %s (#%d) unimplemented.", desc->name(), callnum);
622484SN/A
632484SN/A    return 1;
64360SN/A}
65360SN/A
66360SN/A
671450SN/ASyscallReturn
6811851Sbrandon.potter@amd.comignoreFunc(SyscallDesc *desc, int callnum, Process *process,
692680Sktlim@umich.edu           ThreadContext *tc)
70360SN/A{
7111794Sbrandon.potter@amd.com    if (desc->needWarning()) {
7211794Sbrandon.potter@amd.com        warn("ignoring syscall %s(...)%s", desc->name(), desc->warnOnce() ?
7311794Sbrandon.potter@amd.com             "\n      (further warnings will be suppressed)" : "");
7410831Ssteve.reinhardt@amd.com    }
75360SN/A
768149SChris.Emmons@ARM.com    return 0;
778149SChris.Emmons@ARM.com}
788149SChris.Emmons@ARM.com
7911886Sbrandon.potter@amd.comstatic void
8011911SBrandon.Potter@amd.comexitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
8111886Sbrandon.potter@amd.com{
8211911SBrandon.Potter@amd.com    // Clear value at address pointed to by thread's childClearTID field.
8311911SBrandon.Potter@amd.com    BufferArg ctidBuf(addr, sizeof(long));
8411911SBrandon.Potter@amd.com    long *ctid = (long *)ctidBuf.bufferPtr();
8511911SBrandon.Potter@amd.com    *ctid = 0;
8611911SBrandon.Potter@amd.com    ctidBuf.copyOut(tc->getMemProxy());
8711886Sbrandon.potter@amd.com
8811911SBrandon.Potter@amd.com    FutexMap &futex_map = tc->getSystemPtr()->futexMap;
8911911SBrandon.Potter@amd.com    // Wake one of the waiting threads.
9011911SBrandon.Potter@amd.com    futex_map.wakeup(addr, tgid, 1);
9111911SBrandon.Potter@amd.com}
9211911SBrandon.Potter@amd.com
9311911SBrandon.Potter@amd.comstatic SyscallReturn
9411911SBrandon.Potter@amd.comexitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
9511911SBrandon.Potter@amd.com         bool group)
9611911SBrandon.Potter@amd.com{
9711911SBrandon.Potter@amd.com    int index = 0;
9811911SBrandon.Potter@amd.com    int status = p->getSyscallArg(tc, index);
9911911SBrandon.Potter@amd.com
10011911SBrandon.Potter@amd.com    System *sys = tc->getSystemPtr();
10111911SBrandon.Potter@amd.com
10211911SBrandon.Potter@amd.com    int activeContexts = 0;
10311911SBrandon.Potter@amd.com    for (auto &system: sys->systemList)
10411911SBrandon.Potter@amd.com        activeContexts += system->numRunningContexts();
10511911SBrandon.Potter@amd.com    if (activeContexts == 1) {
10612716Smichael.lebeane@amd.com        /**
10712716Smichael.lebeane@amd.com         * Even though we are terminating the final thread context, dist-gem5
10812716Smichael.lebeane@amd.com         * requires the simulation to remain active and provide
10912716Smichael.lebeane@amd.com         * synchronization messages to the switch process. So we just halt
11012716Smichael.lebeane@amd.com         * the last thread context and return. The simulation will be
11112716Smichael.lebeane@amd.com         * terminated by dist-gem5 in a coordinated manner once all nodes
11212716Smichael.lebeane@amd.com         * have signaled their readiness to exit. For non dist-gem5
11312716Smichael.lebeane@amd.com         * simulations, readyToExit() always returns true.
11412716Smichael.lebeane@amd.com         */
11512716Smichael.lebeane@amd.com        if (!DistIface::readyToExit(0)) {
11612716Smichael.lebeane@amd.com            tc->halt();
11712716Smichael.lebeane@amd.com            return status;
11812716Smichael.lebeane@amd.com        }
11912716Smichael.lebeane@amd.com
12011911SBrandon.Potter@amd.com        exitSimLoop("exiting with last active thread context", status & 0xff);
12111911SBrandon.Potter@amd.com        return status;
12211911SBrandon.Potter@amd.com    }
12311911SBrandon.Potter@amd.com
12411911SBrandon.Potter@amd.com    if (group)
12511911SBrandon.Potter@amd.com        *p->exitGroup = true;
12611911SBrandon.Potter@amd.com
12711911SBrandon.Potter@amd.com    if (p->childClearTID)
12811911SBrandon.Potter@amd.com        exitFutexWake(tc, p->childClearTID, p->tgid());
12911911SBrandon.Potter@amd.com
13011911SBrandon.Potter@amd.com    bool last_thread = true;
13111911SBrandon.Potter@amd.com    Process *parent = nullptr, *tg_lead = nullptr;
13211911SBrandon.Potter@amd.com    for (int i = 0; last_thread && i < sys->numContexts(); i++) {
13311911SBrandon.Potter@amd.com        Process *walk;
13411911SBrandon.Potter@amd.com        if (!(walk = sys->threadContexts[i]->getProcessPtr()))
13511911SBrandon.Potter@amd.com            continue;
13611911SBrandon.Potter@amd.com
13711911SBrandon.Potter@amd.com        /**
13811911SBrandon.Potter@amd.com         * Threads in a thread group require special handing. For instance,
13911911SBrandon.Potter@amd.com         * we send the SIGCHLD signal so that it appears that it came from
14011911SBrandon.Potter@amd.com         * the head of the group. We also only delete file descriptors if
14111911SBrandon.Potter@amd.com         * we are the last thread in the thread group.
14211911SBrandon.Potter@amd.com         */
14311911SBrandon.Potter@amd.com        if (walk->pid() == p->tgid())
14411911SBrandon.Potter@amd.com            tg_lead = walk;
14511911SBrandon.Potter@amd.com
14611911SBrandon.Potter@amd.com        if ((sys->threadContexts[i]->status() != ThreadContext::Halted)
14711911SBrandon.Potter@amd.com            && (walk != p)) {
14811911SBrandon.Potter@amd.com            /**
14911911SBrandon.Potter@amd.com             * Check if we share thread group with the pointer; this denotes
15011911SBrandon.Potter@amd.com             * that we are not the last thread active in the thread group.
15111911SBrandon.Potter@amd.com             * Note that setting this to false also prevents further
15211911SBrandon.Potter@amd.com             * iterations of the loop.
15311911SBrandon.Potter@amd.com             */
15411911SBrandon.Potter@amd.com            if (walk->tgid() == p->tgid())
15511911SBrandon.Potter@amd.com                last_thread = false;
15611911SBrandon.Potter@amd.com
15711911SBrandon.Potter@amd.com            /**
15811911SBrandon.Potter@amd.com             * A corner case exists which involves execve(). After execve(),
15911911SBrandon.Potter@amd.com             * the execve will enable SIGCHLD in the process. The problem
16011911SBrandon.Potter@amd.com             * occurs when the exiting process is the root process in the
16111911SBrandon.Potter@amd.com             * system; there is no parent to receive the signal. We obviate
16211911SBrandon.Potter@amd.com             * this problem by setting the root process' ppid to zero in the
16311911SBrandon.Potter@amd.com             * Python configuration files. We really should handle the
16411911SBrandon.Potter@amd.com             * root/execve specific case more gracefully.
16511911SBrandon.Potter@amd.com             */
16611911SBrandon.Potter@amd.com            if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
16711911SBrandon.Potter@amd.com                parent = walk;
16811886Sbrandon.potter@amd.com        }
16911886Sbrandon.potter@amd.com    }
17011911SBrandon.Potter@amd.com
17111911SBrandon.Potter@amd.com    if (last_thread) {
17211911SBrandon.Potter@amd.com        if (parent) {
17311911SBrandon.Potter@amd.com            assert(tg_lead);
17411911SBrandon.Potter@amd.com            sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
17511911SBrandon.Potter@amd.com        }
17611911SBrandon.Potter@amd.com
17711911SBrandon.Potter@amd.com        /**
17811911SBrandon.Potter@amd.com         * Run though FD array of the exiting process and close all file
17911911SBrandon.Potter@amd.com         * descriptors except for the standard file descriptors.
18011911SBrandon.Potter@amd.com         * (The standard file descriptors are shared with gem5.)
18111911SBrandon.Potter@amd.com         */
18211911SBrandon.Potter@amd.com        for (int i = 0; i < p->fds->getSize(); i++) {
18311911SBrandon.Potter@amd.com            if ((*p->fds)[i])
18411911SBrandon.Potter@amd.com                p->fds->closeFDEntry(i);
18511911SBrandon.Potter@amd.com        }
18611911SBrandon.Potter@amd.com    }
18711911SBrandon.Potter@amd.com
18811911SBrandon.Potter@amd.com    tc->halt();
18911911SBrandon.Potter@amd.com    return status;
19011886Sbrandon.potter@amd.com}
1918149SChris.Emmons@ARM.com
1928149SChris.Emmons@ARM.comSyscallReturn
19311886Sbrandon.potter@amd.comexitFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
194360SN/A{
19511911SBrandon.Potter@amd.com    return exitImpl(desc, callnum, p, tc, false);
196360SN/A}
197360SN/A
1981450SN/ASyscallReturn
19911911SBrandon.Potter@amd.comexitGroupFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
2006109Ssanchezd@stanford.edu{
20111911SBrandon.Potter@amd.com    return exitImpl(desc, callnum, p, tc, true);
2026109Ssanchezd@stanford.edu}
2036109Ssanchezd@stanford.edu
2046109Ssanchezd@stanford.eduSyscallReturn
20511851Sbrandon.potter@amd.comgetpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
206360SN/A{
20710318Sandreas.hansson@arm.com    return (int)PageBytes;
208360SN/A}
209360SN/A
210360SN/A
2111450SN/ASyscallReturn
21211851Sbrandon.potter@amd.combrkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
213360SN/A{
214360SN/A    // change brk addr to first arg
2156701Sgblack@eecs.umich.edu    int index = 0;
2166701Sgblack@eecs.umich.edu    Addr new_brk = p->getSyscallArg(tc, index);
2175748SSteve.Reinhardt@amd.com
21811905SBrandon.Potter@amd.com    std::shared_ptr<MemState> mem_state = p->memState;
21911905SBrandon.Potter@amd.com    Addr brk_point = mem_state->getBrkPoint();
22011905SBrandon.Potter@amd.com
2215748SSteve.Reinhardt@amd.com    // in Linux at least, brk(0) returns the current break value
2225748SSteve.Reinhardt@amd.com    // (note that the syscall and the glibc function have different behavior)
2235748SSteve.Reinhardt@amd.com    if (new_brk == 0)
22411905SBrandon.Potter@amd.com        return brk_point;
2255748SSteve.Reinhardt@amd.com
22611905SBrandon.Potter@amd.com    if (new_brk > brk_point) {
2275748SSteve.Reinhardt@amd.com        // might need to allocate some new pages
22811905SBrandon.Potter@amd.com        for (ChunkGenerator gen(brk_point,
22911905SBrandon.Potter@amd.com                                new_brk - brk_point,
23010318Sandreas.hansson@arm.com                                PageBytes); !gen.done(); gen.next()) {
2315748SSteve.Reinhardt@amd.com            if (!p->pTable->translate(gen.addr()))
23210318Sandreas.hansson@arm.com                p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes);
2336687Stjones1@inf.ed.ac.uk
2346687Stjones1@inf.ed.ac.uk            // if the address is already there, zero it out
2356687Stjones1@inf.ed.ac.uk            else {
23611905SBrandon.Potter@amd.com                uint8_t zero = 0;
2378852Sandreas.hansson@arm.com                SETranslatingPortProxy &tp = tc->getMemProxy();
2386687Stjones1@inf.ed.ac.uk
2396687Stjones1@inf.ed.ac.uk                // split non-page aligned accesses
24010318Sandreas.hansson@arm.com                Addr next_page = roundUp(gen.addr(), PageBytes);
2416687Stjones1@inf.ed.ac.uk                uint32_t size_needed = next_page - gen.addr();
2428852Sandreas.hansson@arm.com                tp.memsetBlob(gen.addr(), zero, size_needed);
24310318Sandreas.hansson@arm.com                if (gen.addr() + PageBytes > next_page &&
2446687Stjones1@inf.ed.ac.uk                    next_page < new_brk &&
24511906SBrandon.Potter@amd.com                    p->pTable->translate(next_page)) {
24610318Sandreas.hansson@arm.com                    size_needed = PageBytes - size_needed;
2478852Sandreas.hansson@arm.com                    tp.memsetBlob(next_page, zero, size_needed);
2486687Stjones1@inf.ed.ac.uk                }
2496687Stjones1@inf.ed.ac.uk            }
2502474SN/A        }
2511450SN/A    }
2525748SSteve.Reinhardt@amd.com
25311905SBrandon.Potter@amd.com    mem_state->setBrkPoint(new_brk);
25411380Salexandru.dutu@amd.com    DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
25511905SBrandon.Potter@amd.com                    mem_state->getBrkPoint());
25611905SBrandon.Potter@amd.com    return mem_state->getBrkPoint();
257360SN/A}
258360SN/A
25911886Sbrandon.potter@amd.comSyscallReturn
26011886Sbrandon.potter@amd.comsetTidAddressFunc(SyscallDesc *desc, int callnum, Process *process,
26111886Sbrandon.potter@amd.com                  ThreadContext *tc)
26211886Sbrandon.potter@amd.com{
26311886Sbrandon.potter@amd.com    int index = 0;
26411886Sbrandon.potter@amd.com    uint64_t tidPtr = process->getSyscallArg(tc, index);
26511886Sbrandon.potter@amd.com
26611886Sbrandon.potter@amd.com    process->childClearTID = tidPtr;
26711886Sbrandon.potter@amd.com    return process->pid();
26811886Sbrandon.potter@amd.com}
269360SN/A
2701450SN/ASyscallReturn
27111851Sbrandon.potter@amd.comcloseFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
272360SN/A{
2736701Sgblack@eecs.umich.edu    int index = 0;
27410931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
27510931Sbrandon.potter@amd.com
27611856Sbrandon.potter@amd.com    return p->fds->closeFDEntry(tgt_fd);
277360SN/A}
278360SN/A
279360SN/A
2801450SN/ASyscallReturn
28111851Sbrandon.potter@amd.comreadFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
282360SN/A{
2836701Sgblack@eecs.umich.edu    int index = 0;
28410931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
28511906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
2866701Sgblack@eecs.umich.edu    int nbytes = p->getSyscallArg(tc, index);
28711856Sbrandon.potter@amd.com
28811856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
28911856Sbrandon.potter@amd.com    if (!hbfdp)
29011856Sbrandon.potter@amd.com        return -EBADF;
29111856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
29211856Sbrandon.potter@amd.com
29311906SBrandon.Potter@amd.com    BufferArg bufArg(buf_ptr, nbytes);
29410931Sbrandon.potter@amd.com    int bytes_read = read(sim_fd, bufArg.bufferPtr(), nbytes);
295360SN/A
29611684Snderumigny@gmail.com    if (bytes_read > 0)
2978706Sandreas.hansson@arm.com        bufArg.copyOut(tc->getMemProxy());
298360SN/A
2991458SN/A    return bytes_read;
300360SN/A}
301360SN/A
3021450SN/ASyscallReturn
30311851Sbrandon.potter@amd.comwriteFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
304360SN/A{
3056701Sgblack@eecs.umich.edu    int index = 0;
30610931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
30711906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
3086701Sgblack@eecs.umich.edu    int nbytes = p->getSyscallArg(tc, index);
30911856Sbrandon.potter@amd.com
31011856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
31111856Sbrandon.potter@amd.com    if (!hbfdp)
31211856Sbrandon.potter@amd.com        return -EBADF;
31311856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
31411856Sbrandon.potter@amd.com
31511906SBrandon.Potter@amd.com    BufferArg bufArg(buf_ptr, nbytes);
3168706Sandreas.hansson@arm.com    bufArg.copyIn(tc->getMemProxy());
317360SN/A
31810931Sbrandon.potter@amd.com    int bytes_written = write(sim_fd, bufArg.bufferPtr(), nbytes);
319360SN/A
32010931Sbrandon.potter@amd.com    fsync(sim_fd);
321360SN/A
3221458SN/A    return bytes_written;
323360SN/A}
324360SN/A
325360SN/A
3261450SN/ASyscallReturn
32711851Sbrandon.potter@amd.comlseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
328360SN/A{
3296701Sgblack@eecs.umich.edu    int index = 0;
33010931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
3316701Sgblack@eecs.umich.edu    uint64_t offs = p->getSyscallArg(tc, index);
3326701Sgblack@eecs.umich.edu    int whence = p->getSyscallArg(tc, index);
333360SN/A
33411856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
33511856Sbrandon.potter@amd.com    if (!ffdp)
33610931Sbrandon.potter@amd.com        return -EBADF;
33711856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
33810931Sbrandon.potter@amd.com
33910931Sbrandon.potter@amd.com    off_t result = lseek(sim_fd, offs, whence);
340360SN/A
3411458SN/A    return (result == (off_t)-1) ? -errno : result;
342360SN/A}
343360SN/A
344360SN/A
3451450SN/ASyscallReturn
34611851Sbrandon.potter@amd.com_llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
3474118Sgblack@eecs.umich.edu{
3486701Sgblack@eecs.umich.edu    int index = 0;
34910931Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
3506701Sgblack@eecs.umich.edu    uint64_t offset_high = p->getSyscallArg(tc, index);
3516701Sgblack@eecs.umich.edu    uint32_t offset_low = p->getSyscallArg(tc, index);
3526701Sgblack@eecs.umich.edu    Addr result_ptr = p->getSyscallArg(tc, index);
3536701Sgblack@eecs.umich.edu    int whence = p->getSyscallArg(tc, index);
3544118Sgblack@eecs.umich.edu
35511856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
35611856Sbrandon.potter@amd.com    if (!ffdp)
35710931Sbrandon.potter@amd.com        return -EBADF;
35811856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
35910931Sbrandon.potter@amd.com
3604118Sgblack@eecs.umich.edu    uint64_t offset = (offset_high << 32) | offset_low;
3614118Sgblack@eecs.umich.edu
36210931Sbrandon.potter@amd.com    uint64_t result = lseek(sim_fd, offset, whence);
3634118Sgblack@eecs.umich.edu    result = TheISA::htog(result);
3644118Sgblack@eecs.umich.edu
36511379Sbrandon.potter@amd.com    if (result == (off_t)-1)
3664118Sgblack@eecs.umich.edu        return -errno;
36711379Sbrandon.potter@amd.com    // Assuming that the size of loff_t is 64 bits on the target platform
36811379Sbrandon.potter@amd.com    BufferArg result_buf(result_ptr, sizeof(result));
36911379Sbrandon.potter@amd.com    memcpy(result_buf.bufferPtr(), &result, sizeof(result));
37011379Sbrandon.potter@amd.com    result_buf.copyOut(tc->getMemProxy());
37111379Sbrandon.potter@amd.com    return 0;
3724118Sgblack@eecs.umich.edu}
3734118Sgblack@eecs.umich.edu
3744118Sgblack@eecs.umich.edu
3754118Sgblack@eecs.umich.eduSyscallReturn
37611851Sbrandon.potter@amd.communmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
377360SN/A{
37811383Sbrandon.potter@amd.com    // With mmap more fully implemented, it might be worthwhile to bite
37911383Sbrandon.potter@amd.com    // the bullet and implement munmap. Should allow us to reuse simulated
38011383Sbrandon.potter@amd.com    // memory.
3811458SN/A    return 0;
382360SN/A}
383360SN/A
384360SN/A
385360SN/Aconst char *hostname = "m5.eecs.umich.edu";
386360SN/A
3871450SN/ASyscallReturn
38811851Sbrandon.potter@amd.comgethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
389360SN/A{
3906701Sgblack@eecs.umich.edu    int index = 0;
39111906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
3926701Sgblack@eecs.umich.edu    int name_len = p->getSyscallArg(tc, index);
39311906SBrandon.Potter@amd.com    BufferArg name(buf_ptr, name_len);
394360SN/A
395360SN/A    strncpy((char *)name.bufferPtr(), hostname, name_len);
396360SN/A
3978706Sandreas.hansson@arm.com    name.copyOut(tc->getMemProxy());
398360SN/A
3991458SN/A    return 0;
400360SN/A}
401360SN/A
4021450SN/ASyscallReturn
40311851Sbrandon.potter@amd.comgetcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
4045513SMichael.Adler@intel.com{
4055513SMichael.Adler@intel.com    int result = 0;
4066731Svince@csl.cornell.edu    int index = 0;
40711906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
4086701Sgblack@eecs.umich.edu    unsigned long size = p->getSyscallArg(tc, index);
40911906SBrandon.Potter@amd.com    BufferArg buf(buf_ptr, size);
4105513SMichael.Adler@intel.com
4115513SMichael.Adler@intel.com    // Is current working directory defined?
4125513SMichael.Adler@intel.com    string cwd = p->getcwd();
4135513SMichael.Adler@intel.com    if (!cwd.empty()) {
4145513SMichael.Adler@intel.com        if (cwd.length() >= size) {
4155513SMichael.Adler@intel.com            // Buffer too small
4165513SMichael.Adler@intel.com            return -ERANGE;
4175513SMichael.Adler@intel.com        }
4185513SMichael.Adler@intel.com        strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
4195513SMichael.Adler@intel.com        result = cwd.length();
42010955Sdavid.hashe@amd.com    } else {
42111856Sbrandon.potter@amd.com        if (getcwd((char *)buf.bufferPtr(), size)) {
4225513SMichael.Adler@intel.com            result = strlen((char *)buf.bufferPtr());
42310955Sdavid.hashe@amd.com        } else {
4245513SMichael.Adler@intel.com            result = -1;
4255513SMichael.Adler@intel.com        }
4265513SMichael.Adler@intel.com    }
4275513SMichael.Adler@intel.com
4288706Sandreas.hansson@arm.com    buf.copyOut(tc->getMemProxy());
4295513SMichael.Adler@intel.com
4305513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
4315513SMichael.Adler@intel.com}
4325513SMichael.Adler@intel.com
43310203SAli.Saidi@ARM.comSyscallReturn
43411851Sbrandon.potter@amd.comreadlinkFunc(SyscallDesc *desc, int callnum, Process *process,
43511851Sbrandon.potter@amd.com             ThreadContext *tc)
43610203SAli.Saidi@ARM.com{
43710203SAli.Saidi@ARM.com    return readlinkFunc(desc, callnum, process, tc, 0);
43810203SAli.Saidi@ARM.com}
4395513SMichael.Adler@intel.com
4405513SMichael.Adler@intel.comSyscallReturn
44111851Sbrandon.potter@amd.comreadlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
44211851Sbrandon.potter@amd.com             int index)
4435513SMichael.Adler@intel.com{
4445513SMichael.Adler@intel.com    string path;
4455513SMichael.Adler@intel.com
4468852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
44710223Ssteve.reinhardt@amd.com        return -EFAULT;
4485513SMichael.Adler@intel.com
4495513SMichael.Adler@intel.com    // Adjust path for current working directory
4505513SMichael.Adler@intel.com    path = p->fullPath(path);
4515513SMichael.Adler@intel.com
45211906SBrandon.Potter@amd.com    Addr buf_ptr = p->getSyscallArg(tc, index);
4536701Sgblack@eecs.umich.edu    size_t bufsiz = p->getSyscallArg(tc, index);
4546701Sgblack@eecs.umich.edu
45511906SBrandon.Potter@amd.com    BufferArg buf(buf_ptr, bufsiz);
4565513SMichael.Adler@intel.com
45710955Sdavid.hashe@amd.com    int result = -1;
45810955Sdavid.hashe@amd.com    if (path != "/proc/self/exe") {
45910955Sdavid.hashe@amd.com        result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
46010955Sdavid.hashe@amd.com    } else {
46111140Sjthestness@gmail.com        // Emulate readlink() called on '/proc/self/exe' should return the
46211140Sjthestness@gmail.com        // absolute path of the binary running in the simulated system (the
46311851Sbrandon.potter@amd.com        // Process' executable). It is possible that using this path in
46411140Sjthestness@gmail.com        // the simulated system will result in unexpected behavior if:
46511140Sjthestness@gmail.com        //  1) One binary runs another (e.g., -c time -o "my_binary"), and
46611140Sjthestness@gmail.com        //     called binary calls readlink().
46711140Sjthestness@gmail.com        //  2) The host's full path to the running benchmark changes from one
46811140Sjthestness@gmail.com        //     simulation to another. This can result in different simulated
46911140Sjthestness@gmail.com        //     performance since the simulated system will process the binary
47011140Sjthestness@gmail.com        //     path differently, even if the binary itself does not change.
47111140Sjthestness@gmail.com
47211140Sjthestness@gmail.com        // Get the absolute canonical path to the running application
47311140Sjthestness@gmail.com        char real_path[PATH_MAX];
47411140Sjthestness@gmail.com        char *check_real_path = realpath(p->progName(), real_path);
47511140Sjthestness@gmail.com        if (!check_real_path) {
47611140Sjthestness@gmail.com            fatal("readlink('/proc/self/exe') unable to resolve path to "
47711140Sjthestness@gmail.com                  "executable: %s", p->progName());
47811140Sjthestness@gmail.com        }
47911140Sjthestness@gmail.com        strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
48011140Sjthestness@gmail.com        size_t real_path_len = strlen(real_path);
48111140Sjthestness@gmail.com        if (real_path_len > bufsiz) {
48210955Sdavid.hashe@amd.com            // readlink will truncate the contents of the
48310955Sdavid.hashe@amd.com            // path to ensure it is no more than bufsiz
48410955Sdavid.hashe@amd.com            result = bufsiz;
48510955Sdavid.hashe@amd.com        } else {
48611140Sjthestness@gmail.com            result = real_path_len;
48710955Sdavid.hashe@amd.com        }
48811140Sjthestness@gmail.com
48911140Sjthestness@gmail.com        // Issue a warning about potential unexpected results
49011140Sjthestness@gmail.com        warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
49111140Sjthestness@gmail.com                  "results in various settings.\n      Returning '%s'\n",
49211140Sjthestness@gmail.com                  (char*)buf.bufferPtr());
49310955Sdavid.hashe@amd.com    }
4945513SMichael.Adler@intel.com
4958706Sandreas.hansson@arm.com    buf.copyOut(tc->getMemProxy());
4965513SMichael.Adler@intel.com
4975513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
4985513SMichael.Adler@intel.com}
4995513SMichael.Adler@intel.com
5005513SMichael.Adler@intel.comSyscallReturn
50111851Sbrandon.potter@amd.comunlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
502511SN/A{
50310633Smichaelupton@gmail.com    return unlinkHelper(desc, num, p, tc, 0);
50410633Smichaelupton@gmail.com}
50510633Smichaelupton@gmail.com
50610633Smichaelupton@gmail.comSyscallReturn
50711851Sbrandon.potter@amd.comunlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
50811851Sbrandon.potter@amd.com             int index)
50910633Smichaelupton@gmail.com{
5101706SN/A    string path;
511360SN/A
5128852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
51310223Ssteve.reinhardt@amd.com        return -EFAULT;
514511SN/A
5153669Sbinkertn@umich.edu    // Adjust path for current working directory
5163669Sbinkertn@umich.edu    path = p->fullPath(path);
5173669Sbinkertn@umich.edu
518511SN/A    int result = unlink(path.c_str());
5191458SN/A    return (result == -1) ? -errno : result;
520511SN/A}
521511SN/A
52212795Smattdsinclair@gmail.comSyscallReturn
52312795Smattdsinclair@gmail.comlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
52412795Smattdsinclair@gmail.com{
52512795Smattdsinclair@gmail.com    string path;
52612795Smattdsinclair@gmail.com    string new_path;
52712795Smattdsinclair@gmail.com
52812795Smattdsinclair@gmail.com    int index = 0;
52912795Smattdsinclair@gmail.com    auto &virt_mem = tc->getMemProxy();
53012795Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
53112795Smattdsinclair@gmail.com        return -EFAULT;
53212795Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
53312795Smattdsinclair@gmail.com        return -EFAULT;
53412795Smattdsinclair@gmail.com
53512795Smattdsinclair@gmail.com    path = p->fullPath(path);
53612795Smattdsinclair@gmail.com    new_path = p->fullPath(new_path);
53712795Smattdsinclair@gmail.com
53812795Smattdsinclair@gmail.com    int result = link(path.c_str(), new_path.c_str());
53912795Smattdsinclair@gmail.com    return (result == -1) ? -errno : result;
54012795Smattdsinclair@gmail.com}
5415513SMichael.Adler@intel.com
5425513SMichael.Adler@intel.comSyscallReturn
54312796Smattdsinclair@gmail.comsymlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
54412796Smattdsinclair@gmail.com{
54512796Smattdsinclair@gmail.com    string path;
54612796Smattdsinclair@gmail.com    string new_path;
54712796Smattdsinclair@gmail.com
54812796Smattdsinclair@gmail.com    int index = 0;
54912796Smattdsinclair@gmail.com    auto &virt_mem = tc->getMemProxy();
55012796Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
55112796Smattdsinclair@gmail.com        return -EFAULT;
55212796Smattdsinclair@gmail.com    if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
55312796Smattdsinclair@gmail.com        return -EFAULT;
55412796Smattdsinclair@gmail.com
55512796Smattdsinclair@gmail.com    path = p->fullPath(path);
55612796Smattdsinclair@gmail.com    new_path = p->fullPath(new_path);
55712796Smattdsinclair@gmail.com
55812796Smattdsinclair@gmail.com    int result = symlink(path.c_str(), new_path.c_str());
55912796Smattdsinclair@gmail.com    return (result == -1) ? -errno : result;
56012796Smattdsinclair@gmail.com}
56112796Smattdsinclair@gmail.com
56212796Smattdsinclair@gmail.comSyscallReturn
56311851Sbrandon.potter@amd.commkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
5645513SMichael.Adler@intel.com{
5655513SMichael.Adler@intel.com    string path;
5665513SMichael.Adler@intel.com
5676701Sgblack@eecs.umich.edu    int index = 0;
5688852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
56910223Ssteve.reinhardt@amd.com        return -EFAULT;
5705513SMichael.Adler@intel.com
5715513SMichael.Adler@intel.com    // Adjust path for current working directory
5725513SMichael.Adler@intel.com    path = p->fullPath(path);
5735513SMichael.Adler@intel.com
5746701Sgblack@eecs.umich.edu    mode_t mode = p->getSyscallArg(tc, index);
5755513SMichael.Adler@intel.com
5765513SMichael.Adler@intel.com    int result = mkdir(path.c_str(), mode);
5775513SMichael.Adler@intel.com    return (result == -1) ? -errno : result;
5785513SMichael.Adler@intel.com}
5795513SMichael.Adler@intel.com
5801450SN/ASyscallReturn
58111851Sbrandon.potter@amd.comrenameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
582511SN/A{
5831706SN/A    string old_name;
584511SN/A
5856701Sgblack@eecs.umich.edu    int index = 0;
5868852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index)))
5871458SN/A        return -EFAULT;
588511SN/A
5891706SN/A    string new_name;
590511SN/A
5918852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index)))
5921458SN/A        return -EFAULT;
593511SN/A
5943669Sbinkertn@umich.edu    // Adjust path for current working directory
5953669Sbinkertn@umich.edu    old_name = p->fullPath(old_name);
5963669Sbinkertn@umich.edu    new_name = p->fullPath(new_name);
5973669Sbinkertn@umich.edu
5981706SN/A    int64_t result = rename(old_name.c_str(), new_name.c_str());
5991458SN/A    return (result == -1) ? -errno : result;
600511SN/A}
601511SN/A
6021706SN/ASyscallReturn
60311851Sbrandon.potter@amd.comtruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
6041706SN/A{
6051706SN/A    string path;
6061706SN/A
6076701Sgblack@eecs.umich.edu    int index = 0;
6088852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
6091706SN/A        return -EFAULT;
6101706SN/A
6116701Sgblack@eecs.umich.edu    off_t length = p->getSyscallArg(tc, index);
6121706SN/A
6133669Sbinkertn@umich.edu    // Adjust path for current working directory
6143669Sbinkertn@umich.edu    path = p->fullPath(path);
6153669Sbinkertn@umich.edu
6161706SN/A    int result = truncate(path.c_str(), length);
6171706SN/A    return (result == -1) ? -errno : result;
6181706SN/A}
6191706SN/A
6201706SN/ASyscallReturn
62111856Sbrandon.potter@amd.comftruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
6221706SN/A{
6236701Sgblack@eecs.umich.edu    int index = 0;
62411856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
62511856Sbrandon.potter@amd.com    off_t length = p->getSyscallArg(tc, index);
6261706SN/A
62711856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
62811856Sbrandon.potter@amd.com    if (!ffdp)
6291706SN/A        return -EBADF;
63011856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
6311706SN/A
63210931Sbrandon.potter@amd.com    int result = ftruncate(sim_fd, length);
6331706SN/A    return (result == -1) ? -errno : result;
6341706SN/A}
6351999SN/A
6361999SN/ASyscallReturn
6376703Svince@csl.cornell.edutruncate64Func(SyscallDesc *desc, int num,
63811851Sbrandon.potter@amd.com               Process *process, ThreadContext *tc)
6396703Svince@csl.cornell.edu{
6406703Svince@csl.cornell.edu    int index = 0;
6416703Svince@csl.cornell.edu    string path;
6426703Svince@csl.cornell.edu
6438852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index)))
64411906SBrandon.Potter@amd.com        return -EFAULT;
6456703Svince@csl.cornell.edu
6466744SAli.Saidi@arm.com    int64_t length = process->getSyscallArg(tc, index, 64);
6476703Svince@csl.cornell.edu
6486703Svince@csl.cornell.edu    // Adjust path for current working directory
6496703Svince@csl.cornell.edu    path = process->fullPath(path);
6506703Svince@csl.cornell.edu
6516744SAli.Saidi@arm.com#if NO_STAT64
6526744SAli.Saidi@arm.com    int result = truncate(path.c_str(), length);
6536744SAli.Saidi@arm.com#else
6546703Svince@csl.cornell.edu    int result = truncate64(path.c_str(), length);
6556744SAli.Saidi@arm.com#endif
6566703Svince@csl.cornell.edu    return (result == -1) ? -errno : result;
6576703Svince@csl.cornell.edu}
6586703Svince@csl.cornell.edu
6596703Svince@csl.cornell.eduSyscallReturn
66011856Sbrandon.potter@amd.comftruncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
6616685Stjones1@inf.ed.ac.uk{
6626701Sgblack@eecs.umich.edu    int index = 0;
66311856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
66411856Sbrandon.potter@amd.com    int64_t length = p->getSyscallArg(tc, index, 64);
6656685Stjones1@inf.ed.ac.uk
66611856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
66711856Sbrandon.potter@amd.com    if (!ffdp)
6686685Stjones1@inf.ed.ac.uk        return -EBADF;
66911856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
6706685Stjones1@inf.ed.ac.uk
6716744SAli.Saidi@arm.com#if NO_STAT64
67210931Sbrandon.potter@amd.com    int result = ftruncate(sim_fd, length);
6736744SAli.Saidi@arm.com#else
67410931Sbrandon.potter@amd.com    int result = ftruncate64(sim_fd, length);
6756744SAli.Saidi@arm.com#endif
6766685Stjones1@inf.ed.ac.uk    return (result == -1) ? -errno : result;
6776685Stjones1@inf.ed.ac.uk}
6786685Stjones1@inf.ed.ac.uk
6796685Stjones1@inf.ed.ac.ukSyscallReturn
68011851Sbrandon.potter@amd.comumaskFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
6815513SMichael.Adler@intel.com{
6825513SMichael.Adler@intel.com    // Letting the simulated program change the simulator's umask seems like
6835513SMichael.Adler@intel.com    // a bad idea.  Compromise by just returning the current umask but not
6845513SMichael.Adler@intel.com    // changing anything.
6855513SMichael.Adler@intel.com    mode_t oldMask = umask(0);
6865513SMichael.Adler@intel.com    umask(oldMask);
6875521Snate@binkert.org    return (int)oldMask;
6885513SMichael.Adler@intel.com}
6895513SMichael.Adler@intel.com
6905513SMichael.Adler@intel.comSyscallReturn
69111851Sbrandon.potter@amd.comchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
6921999SN/A{
6931999SN/A    string path;
6941999SN/A
6956701Sgblack@eecs.umich.edu    int index = 0;
6968852Sandreas.hansson@arm.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
6971999SN/A        return -EFAULT;
6981999SN/A
6991999SN/A    /* XXX endianess */
7006701Sgblack@eecs.umich.edu    uint32_t owner = p->getSyscallArg(tc, index);
7011999SN/A    uid_t hostOwner = owner;
7026701Sgblack@eecs.umich.edu    uint32_t group = p->getSyscallArg(tc, index);
7031999SN/A    gid_t hostGroup = group;
7041999SN/A
7053669Sbinkertn@umich.edu    // Adjust path for current working directory
7063669Sbinkertn@umich.edu    path = p->fullPath(path);
7073669Sbinkertn@umich.edu
7081999SN/A    int result = chown(path.c_str(), hostOwner, hostGroup);
7091999SN/A    return (result == -1) ? -errno : result;
7101999SN/A}
7111999SN/A
7121999SN/ASyscallReturn
71311856Sbrandon.potter@amd.comfchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
7141999SN/A{
7156701Sgblack@eecs.umich.edu    int index = 0;
71611856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
7171999SN/A
71811856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
71911856Sbrandon.potter@amd.com    if (!ffdp)
7201999SN/A        return -EBADF;
72111856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
7221999SN/A
7231999SN/A    /* XXX endianess */
72411856Sbrandon.potter@amd.com    uint32_t owner = p->getSyscallArg(tc, index);
7251999SN/A    uid_t hostOwner = owner;
72611856Sbrandon.potter@amd.com    uint32_t group = p->getSyscallArg(tc, index);
7271999SN/A    gid_t hostGroup = group;
7281999SN/A
72910931Sbrandon.potter@amd.com    int result = fchown(sim_fd, hostOwner, hostGroup);
7301999SN/A    return (result == -1) ? -errno : result;
7311999SN/A}
7322093SN/A
73311856Sbrandon.potter@amd.com/**
73411908SBrandon.Potter@amd.com * FIXME: The file description is not shared among file descriptors created
73511908SBrandon.Potter@amd.com * with dup. Really, it's difficult to maintain fields like file offset or
73611908SBrandon.Potter@amd.com * flags since an update to such a field won't be reflected in the metadata
73711908SBrandon.Potter@amd.com * for the fd entries that we maintain for checkpoint restoration.
73811856Sbrandon.potter@amd.com */
7392093SN/ASyscallReturn
74011856Sbrandon.potter@amd.comdupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
7413079Sstever@eecs.umich.edu{
7426701Sgblack@eecs.umich.edu    int index = 0;
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
76111908SBrandon.Potter@amd.comdup2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
76211908SBrandon.Potter@amd.com{
76311908SBrandon.Potter@amd.com    int index = 0;
76411908SBrandon.Potter@amd.com
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
79211856Sbrandon.potter@amd.comfcntlFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
7932093SN/A{
79411875Sbrandon.potter@amd.com    int arg;
7956701Sgblack@eecs.umich.edu    int index = 0;
79611856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
79711875Sbrandon.potter@amd.com    int cmd = p->getSyscallArg(tc, index);
7982093SN/A
79911856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
80011856Sbrandon.potter@amd.com    if (!hbfdp)
8012093SN/A        return -EBADF;
80211856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
8032093SN/A
80411875Sbrandon.potter@amd.com    int coe = hbfdp->getCOE();
80511875Sbrandon.potter@amd.com
8062093SN/A    switch (cmd) {
80711875Sbrandon.potter@amd.com      case F_GETFD:
80811875Sbrandon.potter@amd.com        return coe & FD_CLOEXEC;
8092093SN/A
81011875Sbrandon.potter@amd.com      case F_SETFD: {
81111875Sbrandon.potter@amd.com        arg = p->getSyscallArg(tc, index);
81211875Sbrandon.potter@amd.com        arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
8132093SN/A        return 0;
81411875Sbrandon.potter@amd.com      }
8152093SN/A
81611875Sbrandon.potter@amd.com      // Rely on the host to maintain the file status flags for this file
81711875Sbrandon.potter@amd.com      // description rather than maintain it ourselves. Admittedly, this
81811875Sbrandon.potter@amd.com      // is suboptimal (and possibly error prone), but it is difficult to
81911875Sbrandon.potter@amd.com      // maintain the flags by tracking them across the different descriptors
82011875Sbrandon.potter@amd.com      // (that refer to this file description) caused by clone, dup, and
82111875Sbrandon.potter@amd.com      // subsequent fcntls.
82211875Sbrandon.potter@amd.com      case F_GETFL:
82311875Sbrandon.potter@amd.com      case F_SETFL: {
82411875Sbrandon.potter@amd.com        arg = p->getSyscallArg(tc, index);
82511875Sbrandon.potter@amd.com        int rv = fcntl(sim_fd, cmd, arg);
82611875Sbrandon.potter@amd.com        return (rv == -1) ? -errno : rv;
82711875Sbrandon.potter@amd.com      }
8282093SN/A
8292093SN/A      default:
83011875Sbrandon.potter@amd.com        warn("fcntl: unsupported command %d\n", cmd);
8312093SN/A        return 0;
8322093SN/A    }
8332093SN/A}
8342093SN/A
8352238SN/ASyscallReturn
83611856Sbrandon.potter@amd.comfcntl64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
8372687Sksewell@umich.edu{
8386701Sgblack@eecs.umich.edu    int index = 0;
83911856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
8402687Sksewell@umich.edu
84111856Sbrandon.potter@amd.com    auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
84211856Sbrandon.potter@amd.com    if (!hbfdp)
8432687Sksewell@umich.edu        return -EBADF;
84411856Sbrandon.potter@amd.com    int sim_fd = hbfdp->getSimFD();
8452687Sksewell@umich.edu
84611856Sbrandon.potter@amd.com    int cmd = p->getSyscallArg(tc, index);
8472687Sksewell@umich.edu    switch (cmd) {
8482687Sksewell@umich.edu      case 33: //F_GETLK64
84910931Sbrandon.potter@amd.com        warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
8502687Sksewell@umich.edu        return -EMFILE;
8512687Sksewell@umich.edu
8522687Sksewell@umich.edu      case 34: // F_SETLK64
8532687Sksewell@umich.edu      case 35: // F_SETLKW64
85410931Sbrandon.potter@amd.com        warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
85510931Sbrandon.potter@amd.com             tgt_fd);
8562687Sksewell@umich.edu        return -EMFILE;
8572687Sksewell@umich.edu
8582687Sksewell@umich.edu      default:
8592687Sksewell@umich.edu        // not sure if this is totally valid, but we'll pass it through
8602687Sksewell@umich.edu        // to the underlying OS
86110931Sbrandon.potter@amd.com        warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
86210931Sbrandon.potter@amd.com        return fcntl(sim_fd, cmd);
8632687Sksewell@umich.edu    }
8642687Sksewell@umich.edu}
8652687Sksewell@umich.edu
8662687Sksewell@umich.eduSyscallReturn
86711908SBrandon.Potter@amd.compipeImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
86811908SBrandon.Potter@amd.com         bool pseudoPipe)
8692238SN/A{
87011908SBrandon.Potter@amd.com    Addr tgt_addr = 0;
87111908SBrandon.Potter@amd.com    if (!pseudoPipe) {
87211908SBrandon.Potter@amd.com        int index = 0;
87311908SBrandon.Potter@amd.com        tgt_addr = p->getSyscallArg(tc, index);
87411908SBrandon.Potter@amd.com    }
87511908SBrandon.Potter@amd.com
87611856Sbrandon.potter@amd.com    int sim_fds[2], tgt_fds[2];
8772093SN/A
87811856Sbrandon.potter@amd.com    int pipe_retval = pipe(sim_fds);
87911908SBrandon.Potter@amd.com    if (pipe_retval == -1)
88011908SBrandon.Potter@amd.com        return -errno;
8812238SN/A
88211856Sbrandon.potter@amd.com    auto rend = PipeFDEntry::EndType::read;
88311856Sbrandon.potter@amd.com    auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
88411908SBrandon.Potter@amd.com    tgt_fds[0] = p->fds->allocFD(rpfd);
8852238SN/A
88611856Sbrandon.potter@amd.com    auto wend = PipeFDEntry::EndType::write;
88711856Sbrandon.potter@amd.com    auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
88811908SBrandon.Potter@amd.com    tgt_fds[1] = p->fds->allocFD(wpfd);
88911856Sbrandon.potter@amd.com
89011856Sbrandon.potter@amd.com    /**
89111856Sbrandon.potter@amd.com     * Now patch the read object to record the target file descriptor chosen
89211856Sbrandon.potter@amd.com     * as the write end of the pipe.
89311856Sbrandon.potter@amd.com     */
89411856Sbrandon.potter@amd.com    rpfd->setPipeReadSource(tgt_fds[1]);
89511856Sbrandon.potter@amd.com
89611856Sbrandon.potter@amd.com    /**
89711856Sbrandon.potter@amd.com     * Alpha Linux convention for pipe() is that fd[0] is returned as
89811856Sbrandon.potter@amd.com     * the return value of the function, and fd[1] is returned in r20.
89911856Sbrandon.potter@amd.com     */
90011908SBrandon.Potter@amd.com    if (pseudoPipe) {
90111908SBrandon.Potter@amd.com        tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
90211908SBrandon.Potter@amd.com        return tgt_fds[0];
90311908SBrandon.Potter@amd.com    }
90411908SBrandon.Potter@amd.com
90511908SBrandon.Potter@amd.com    /**
90611908SBrandon.Potter@amd.com     * Copy the target file descriptors into buffer space and then copy
90711908SBrandon.Potter@amd.com     * the buffer space back into the target address space.
90811908SBrandon.Potter@amd.com     */
90911908SBrandon.Potter@amd.com    BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
91011908SBrandon.Potter@amd.com    int *buf_ptr = (int*)tgt_handle.bufferPtr();
91111908SBrandon.Potter@amd.com    buf_ptr[0] = tgt_fds[0];
91211908SBrandon.Potter@amd.com    buf_ptr[1] = tgt_fds[1];
91311908SBrandon.Potter@amd.com    tgt_handle.copyOut(tc->getMemProxy());
91411908SBrandon.Potter@amd.com    return 0;
91511908SBrandon.Potter@amd.com}
91611908SBrandon.Potter@amd.com
91711908SBrandon.Potter@amd.comSyscallReturn
91811908SBrandon.Potter@amd.compipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
91911908SBrandon.Potter@amd.com               ThreadContext *tc)
92011908SBrandon.Potter@amd.com{
92111908SBrandon.Potter@amd.com    return pipeImpl(desc, callnum, process, tc, true);
92211908SBrandon.Potter@amd.com}
92311908SBrandon.Potter@amd.com
92411908SBrandon.Potter@amd.comSyscallReturn
92511908SBrandon.Potter@amd.compipeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
92611908SBrandon.Potter@amd.com{
92711908SBrandon.Potter@amd.com    return pipeImpl(desc, callnum, process, tc, false);
9282238SN/A}
9292238SN/A
93011885Sbrandon.potter@amd.comSyscallReturn
93111885Sbrandon.potter@amd.comsetpgidFunc(SyscallDesc *desc, int callnum, Process *process,
93211885Sbrandon.potter@amd.com            ThreadContext *tc)
93311885Sbrandon.potter@amd.com{
93411885Sbrandon.potter@amd.com    int index = 0;
93511885Sbrandon.potter@amd.com    int pid = process->getSyscallArg(tc, index);
93611885Sbrandon.potter@amd.com    int pgid = process->getSyscallArg(tc, index);
93711885Sbrandon.potter@amd.com
93811885Sbrandon.potter@amd.com    if (pgid < 0)
93911885Sbrandon.potter@amd.com        return -EINVAL;
94011885Sbrandon.potter@amd.com
94111885Sbrandon.potter@amd.com    if (pid == 0) {
94211885Sbrandon.potter@amd.com        process->setpgid(process->pid());
94311885Sbrandon.potter@amd.com        return 0;
94411885Sbrandon.potter@amd.com    }
94511885Sbrandon.potter@amd.com
94611913SBrandon.Potter@amd.com    Process *matched_ph = nullptr;
94711885Sbrandon.potter@amd.com    System *sysh = tc->getSystemPtr();
94811885Sbrandon.potter@amd.com
94911885Sbrandon.potter@amd.com    // Retrieves process pointer from active/suspended thread contexts.
95011885Sbrandon.potter@amd.com    for (int i = 0; i < sysh->numContexts(); i++) {
95111885Sbrandon.potter@amd.com        if (sysh->threadContexts[i]->status() != ThreadContext::Halted) {
95211885Sbrandon.potter@amd.com            Process *temp_h = sysh->threadContexts[i]->getProcessPtr();
95311885Sbrandon.potter@amd.com            Process *walk_ph = (Process*)temp_h;
95411885Sbrandon.potter@amd.com
95511885Sbrandon.potter@amd.com            if (walk_ph && walk_ph->pid() == process->pid())
95611885Sbrandon.potter@amd.com                matched_ph = walk_ph;
95711885Sbrandon.potter@amd.com        }
95811885Sbrandon.potter@amd.com    }
95911885Sbrandon.potter@amd.com
96011913SBrandon.Potter@amd.com    assert(matched_ph);
96111885Sbrandon.potter@amd.com    matched_ph->setpgid((pgid == 0) ? matched_ph->pid() : pgid);
96211885Sbrandon.potter@amd.com
96311885Sbrandon.potter@amd.com    return 0;
96411885Sbrandon.potter@amd.com}
9652238SN/A
9662238SN/ASyscallReturn
96711851Sbrandon.potter@amd.comgetpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
96811851Sbrandon.potter@amd.com                 ThreadContext *tc)
9692238SN/A{
9702238SN/A    // Make up a PID.  There's no interprocess communication in
9712238SN/A    // fake_syscall mode, so there's no way for a process to know it's
9722238SN/A    // not getting a unique value.
9732238SN/A
9743114Sgblack@eecs.umich.edu    tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
9753114Sgblack@eecs.umich.edu    return process->pid();
9762238SN/A}
9772238SN/A
9782238SN/A
9792238SN/ASyscallReturn
98011851Sbrandon.potter@amd.comgetuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
98111851Sbrandon.potter@amd.com                 ThreadContext *tc)
9822238SN/A{
9832238SN/A    // Make up a UID and EUID... it shouldn't matter, and we want the
9842238SN/A    // simulation to be deterministic.
9852238SN/A
9862238SN/A    // EUID goes in r20.
98711906SBrandon.Potter@amd.com    tc->setIntReg(SyscallPseudoReturnReg, process->euid()); // EUID
98811906SBrandon.Potter@amd.com    return process->uid(); // UID
9892238SN/A}
9902238SN/A
9912238SN/A
9922238SN/ASyscallReturn
99311851Sbrandon.potter@amd.comgetgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
99411851Sbrandon.potter@amd.com                 ThreadContext *tc)
9952238SN/A{
9962238SN/A    // Get current group ID.  EGID goes in r20.
99711906SBrandon.Potter@amd.com    tc->setIntReg(SyscallPseudoReturnReg, process->egid()); // EGID
9983114Sgblack@eecs.umich.edu    return process->gid();
9992238SN/A}
10002238SN/A
10012238SN/A
10022238SN/ASyscallReturn
100311851Sbrandon.potter@amd.comsetuidFunc(SyscallDesc *desc, int callnum, Process *process,
10042680Sktlim@umich.edu           ThreadContext *tc)
10052238SN/A{
10062238SN/A    // can't fathom why a benchmark would call this.
10076701Sgblack@eecs.umich.edu    int index = 0;
10086701Sgblack@eecs.umich.edu    warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index));
10092238SN/A    return 0;
10102238SN/A}
10112238SN/A
10122238SN/ASyscallReturn
101311851Sbrandon.potter@amd.comgetpidFunc(SyscallDesc *desc, int callnum, Process *process,
10142680Sktlim@umich.edu           ThreadContext *tc)
10152238SN/A{
101611885Sbrandon.potter@amd.com    return process->tgid();
101711885Sbrandon.potter@amd.com}
10182238SN/A
101911885Sbrandon.potter@amd.comSyscallReturn
102011885Sbrandon.potter@amd.comgettidFunc(SyscallDesc *desc, int callnum, Process *process,
102111885Sbrandon.potter@amd.com           ThreadContext *tc)
102211885Sbrandon.potter@amd.com{
10233114Sgblack@eecs.umich.edu    return process->pid();
10242238SN/A}
10252238SN/A
10262238SN/ASyscallReturn
102711851Sbrandon.potter@amd.comgetppidFunc(SyscallDesc *desc, int callnum, Process *process,
102811851Sbrandon.potter@amd.com            ThreadContext *tc)
10292238SN/A{
10303114Sgblack@eecs.umich.edu    return process->ppid();
10312238SN/A}
10322238SN/A
10332238SN/ASyscallReturn
103411851Sbrandon.potter@amd.comgetuidFunc(SyscallDesc *desc, int callnum, Process *process,
10352680Sktlim@umich.edu           ThreadContext *tc)
10362238SN/A{
10375543Ssaidi@eecs.umich.edu    return process->uid();              // UID
10382238SN/A}
10392238SN/A
10402238SN/ASyscallReturn
104111851Sbrandon.potter@amd.comgeteuidFunc(SyscallDesc *desc, int callnum, Process *process,
104211851Sbrandon.potter@amd.com            ThreadContext *tc)
10432238SN/A{
10445543Ssaidi@eecs.umich.edu    return process->euid();             // UID
10452238SN/A}
10462238SN/A
10472238SN/ASyscallReturn
104811851Sbrandon.potter@amd.comgetgidFunc(SyscallDesc *desc, int callnum, Process *process,
10492680Sktlim@umich.edu           ThreadContext *tc)
10502238SN/A{
10513114Sgblack@eecs.umich.edu    return process->gid();
10522238SN/A}
10532238SN/A
10542238SN/ASyscallReturn
105511851Sbrandon.potter@amd.comgetegidFunc(SyscallDesc *desc, int callnum, Process *process,
105611851Sbrandon.potter@amd.com            ThreadContext *tc)
10572238SN/A{
10583114Sgblack@eecs.umich.edu    return process->egid();
10592238SN/A}
10602238SN/A
10619455Smitch.hayenga+gem5@gmail.comSyscallReturn
106211856Sbrandon.potter@amd.comfallocateFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
106311760Sbrandon.potter@amd.com{
106411799Sbrandon.potter@amd.com#if NO_FALLOCATE
106511799Sbrandon.potter@amd.com    warn("Host OS cannot support calls to fallocate. Ignoring syscall");
106611799Sbrandon.potter@amd.com#else
106711760Sbrandon.potter@amd.com    int index = 0;
106811856Sbrandon.potter@amd.com    int tgt_fd = p->getSyscallArg(tc, index);
106911856Sbrandon.potter@amd.com    int mode = p->getSyscallArg(tc, index);
107011856Sbrandon.potter@amd.com    off_t offset = p->getSyscallArg(tc, index);
107111856Sbrandon.potter@amd.com    off_t len = p->getSyscallArg(tc, index);
107211760Sbrandon.potter@amd.com
107311856Sbrandon.potter@amd.com    auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
107411856Sbrandon.potter@amd.com    if (!ffdp)
107511760Sbrandon.potter@amd.com        return -EBADF;
107611856Sbrandon.potter@amd.com    int sim_fd = ffdp->getSimFD();
107711760Sbrandon.potter@amd.com
107811760Sbrandon.potter@amd.com    int result = fallocate(sim_fd, mode, offset, len);
107911760Sbrandon.potter@amd.com    if (result < 0)
108011760Sbrandon.potter@amd.com        return -errno;
108111799Sbrandon.potter@amd.com#endif
108211760Sbrandon.potter@amd.com    return 0;
108311760Sbrandon.potter@amd.com}
108411760Sbrandon.potter@amd.com
108511760Sbrandon.potter@amd.comSyscallReturn
108611851Sbrandon.potter@amd.comaccessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
108711851Sbrandon.potter@amd.com           int index)
10889455Smitch.hayenga+gem5@gmail.com{
10899455Smitch.hayenga+gem5@gmail.com    string path;
10909455Smitch.hayenga+gem5@gmail.com    if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
109110223Ssteve.reinhardt@amd.com        return -EFAULT;
10929455Smitch.hayenga+gem5@gmail.com
10939455Smitch.hayenga+gem5@gmail.com    // Adjust path for current working directory
10949455Smitch.hayenga+gem5@gmail.com    path = p->fullPath(path);
10959455Smitch.hayenga+gem5@gmail.com
10969455Smitch.hayenga+gem5@gmail.com    mode_t mode = p->getSyscallArg(tc, index);
10979455Smitch.hayenga+gem5@gmail.com
10989455Smitch.hayenga+gem5@gmail.com    int result = access(path.c_str(), mode);
10999455Smitch.hayenga+gem5@gmail.com    return (result == -1) ? -errno : result;
11009455Smitch.hayenga+gem5@gmail.com}
110110203SAli.Saidi@ARM.com
110210203SAli.Saidi@ARM.comSyscallReturn
110311851Sbrandon.potter@amd.comaccessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
110410203SAli.Saidi@ARM.com{
110510203SAli.Saidi@ARM.com    return accessFunc(desc, callnum, p, tc, 0);
110610203SAli.Saidi@ARM.com}
110710203SAli.Saidi@ARM.com
1108