syscall_emul.hh revision 360
11689SN/A/*
214025Sgiacomo.gabrielli@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
312109SRekai.GonzalezAlberquilla@arm.com * All rights reserved.
412109SRekai.GonzalezAlberquilla@arm.com *
512109SRekai.GonzalezAlberquilla@arm.com * Redistribution and use in source and binary forms, with or without
612109SRekai.GonzalezAlberquilla@arm.com * modification, are permitted provided that the following conditions are
712109SRekai.GonzalezAlberquilla@arm.com * met: redistributions of source code must retain the above copyright
812109SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer;
912109SRekai.GonzalezAlberquilla@arm.com * redistributions in binary form must reproduce the above copyright
1012109SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer in the
1112109SRekai.GonzalezAlberquilla@arm.com * documentation and/or other materials provided with the distribution;
1212109SRekai.GonzalezAlberquilla@arm.com * neither the name of the copyright holders nor the names of its
1312109SRekai.GonzalezAlberquilla@arm.com * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
159919Ssteve.reinhardt@amd.com *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271689SN/A */
281689SN/A
291689SN/A#ifndef __SYSCALL_EMUL_HH__
301689SN/A#define __SYSCALL_EMUL_HH__
311689SN/A
321689SN/A///
331689SN/A/// @file syscall_emul.hh
341689SN/A///
351689SN/A/// This file defines objects used to emulate syscalls from the target
361689SN/A/// application on the host machine.
371689SN/A
381689SN/A#include <string>
391689SN/A
402665Ssaidi@eecs.umich.edu#include "base/intmath.hh"	// for RoundUp
412665Ssaidi@eecs.umich.edu#include "targetarch/isa_traits.hh"	// for Addr
421689SN/A#include "mem/functional_mem/functional_memory.hh"
431689SN/A
442292SN/Aclass Process;
452292SN/Aclass ExecContext;
461060SN/A
471060SN/A///
481060SN/A/// System call descriptor.
4912105Snathanael.premillieu@arm.com///
501060SN/Aclass SyscallDesc {
5112334Sgabeblack@google.com
521684SN/A  public:
531717SN/A
549919Ssteve.reinhardt@amd.com    typedef int (*FuncPtr)(SyscallDesc *, int num,
558232Snate@binkert.org                           Process *, ExecContext *);
561060SN/A
571060SN/A    const char *name;	//!< Syscall name (e.g., "open").
589919Ssteve.reinhardt@amd.com    FuncPtr funcPtr;	//!< Pointer to emulation function.
599919Ssteve.reinhardt@amd.com    int flags;		//!< Flags (see Flags enum).
609919Ssteve.reinhardt@amd.com
619919Ssteve.reinhardt@amd.com
629919Ssteve.reinhardt@amd.com    /// Flag values for controlling syscall behavior.
639919Ssteve.reinhardt@amd.com    enum Flags {
649919Ssteve.reinhardt@amd.com        /// Don't set return regs according to funcPtr return value.
659919Ssteve.reinhardt@amd.com        /// Used for syscalls with non-standard return conventions
669919Ssteve.reinhardt@amd.com        /// that explicitly set the ExecContext regs (e.g.,
679919Ssteve.reinhardt@amd.com        /// sigreturn).
689919Ssteve.reinhardt@amd.com        SuppressReturnValue = 1
6912105Snathanael.premillieu@arm.com    };
709919Ssteve.reinhardt@amd.com
719919Ssteve.reinhardt@amd.com    /// Constructor.
729919Ssteve.reinhardt@amd.com    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
739919Ssteve.reinhardt@amd.com        : name(_name), funcPtr(_funcPtr), flags(_flags)
749919Ssteve.reinhardt@amd.com    {
759919Ssteve.reinhardt@amd.com    }
7612105Snathanael.premillieu@arm.com
779919Ssteve.reinhardt@amd.com    /// Emulate the syscall.  Public interface for calling through funcPtr.
7812109SRekai.GonzalezAlberquilla@arm.com    void doSyscall(int callnum, Process *proc, ExecContext *xc);
7912109SRekai.GonzalezAlberquilla@arm.com};
8012109SRekai.GonzalezAlberquilla@arm.com
8112109SRekai.GonzalezAlberquilla@arm.com
8214025Sgiacomo.gabrielli@arm.comclass BaseBufferArg {
8314025Sgiacomo.gabrielli@arm.com
8414025Sgiacomo.gabrielli@arm.com  public:
8512109SRekai.GonzalezAlberquilla@arm.com
8612109SRekai.GonzalezAlberquilla@arm.com    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
879919Ssteve.reinhardt@amd.com    {
8812105Snathanael.premillieu@arm.com        bufPtr = new uint8_t[size];
899919Ssteve.reinhardt@amd.com        // clear out buffer: in case we only partially populate this,
909919Ssteve.reinhardt@amd.com        // and then do a copyOut(), we want to make sure we don't
9112105Snathanael.premillieu@arm.com        // introduce any random junk into the simulated address space
929919Ssteve.reinhardt@amd.com        memset(bufPtr, 0, size);
939919Ssteve.reinhardt@amd.com    }
949919Ssteve.reinhardt@amd.com
959919Ssteve.reinhardt@amd.com    virtual ~BaseBufferArg() { delete [] bufPtr; }
969919Ssteve.reinhardt@amd.com
979919Ssteve.reinhardt@amd.com    //
989919Ssteve.reinhardt@amd.com    // copy data into simulator space (read from target memory)
999919Ssteve.reinhardt@amd.com    //
1009919Ssteve.reinhardt@amd.com    virtual bool copyIn(FunctionalMemory *mem)
1019919Ssteve.reinhardt@amd.com    {
1029919Ssteve.reinhardt@amd.com        mem->access(Read, addr, bufPtr, size);
1039919Ssteve.reinhardt@amd.com        return true;	// no EFAULT detection for now
1049919Ssteve.reinhardt@amd.com    }
1051060SN/A
1061060SN/A    //
1071060SN/A    // copy data out of simulator space (write to target memory)
1081060SN/A    //
1091060SN/A    virtual bool copyOut(FunctionalMemory *mem)
1101060SN/A    {
1111060SN/A        mem->access(Write, addr, bufPtr, size);
1122292SN/A        return true;	// no EFAULT detection for now
1132292SN/A    }
1142292SN/A
1151060SN/A  protected:
1161060SN/A    Addr addr;
1179919Ssteve.reinhardt@amd.com    int size;
1181060SN/A    uint8_t *bufPtr;
1191060SN/A};
1209919Ssteve.reinhardt@amd.com
1219919Ssteve.reinhardt@amd.com
1229919Ssteve.reinhardt@amd.comclass BufferArg : public BaseBufferArg
1239919Ssteve.reinhardt@amd.com{
1249919Ssteve.reinhardt@amd.com  public:
1251060SN/A    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1269919Ssteve.reinhardt@amd.com    void *bufferPtr()	{ return bufPtr; }
1271060SN/A};
1281060SN/A
1299919Ssteve.reinhardt@amd.comtemplate <class T>
1301060SN/Aclass TypedBufferArg : public BaseBufferArg
13112109SRekai.GonzalezAlberquilla@arm.com{
13212109SRekai.GonzalezAlberquilla@arm.com  public:
13312109SRekai.GonzalezAlberquilla@arm.com    // user can optionally specify a specific number of bytes to
13412109SRekai.GonzalezAlberquilla@arm.com    // allocate to deal with those structs that have variable-size
13512109SRekai.GonzalezAlberquilla@arm.com    // arrays at the end
13612109SRekai.GonzalezAlberquilla@arm.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
13712109SRekai.GonzalezAlberquilla@arm.com        : BaseBufferArg(_addr, _size)
13812109SRekai.GonzalezAlberquilla@arm.com    { }
13912109SRekai.GonzalezAlberquilla@arm.com
14013610Sgiacomo.gabrielli@arm.com    // type case
14113610Sgiacomo.gabrielli@arm.com    operator T*() { return (T *)bufPtr; }
14213610Sgiacomo.gabrielli@arm.com
1439920Syasuko.eckert@amd.com    // dereference operators
1449920Syasuko.eckert@amd.com    T& operator*()	 { return *((T *)bufPtr); }
1459920Syasuko.eckert@amd.com    T* operator->()	 { return (T *)bufPtr; }
1469919Ssteve.reinhardt@amd.com    T& operator[](int i) { return ((T *)bufPtr)[i]; }
1479919Ssteve.reinhardt@amd.com};
1489919Ssteve.reinhardt@amd.com
1499919Ssteve.reinhardt@amd.com//////////////////////////////////////////////////////////////////////
1509919Ssteve.reinhardt@amd.com//
1511060SN/A// The following emulation functions are generic enough that they
1529919Ssteve.reinhardt@amd.com// don't need to be recompiled for different emulated OS's.  They are
1539919Ssteve.reinhardt@amd.com// defined in sim/syscall_emul.cc.
1549919Ssteve.reinhardt@amd.com//
1559919Ssteve.reinhardt@amd.com//////////////////////////////////////////////////////////////////////
1569919Ssteve.reinhardt@amd.com
1579919Ssteve.reinhardt@amd.com
1581060SN/Aint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1591060SN/Aint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1602292SN/A
1612292SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1629919Ssteve.reinhardt@amd.comint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1639919Ssteve.reinhardt@amd.comint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1642292SN/Aint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1659919Ssteve.reinhardt@amd.comint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1669919Ssteve.reinhardt@amd.comint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1672292SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1689919Ssteve.reinhardt@amd.comint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1691060SN/Aint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1702292SN/A
1719919Ssteve.reinhardt@amd.com//////////////////////////////////////////////////////////////////////
1722292SN/A//
1739920Syasuko.eckert@amd.com// The following emulation functions are generic, but need to be
1749920Syasuko.eckert@amd.com// templated to account for differences in types, constants, etc.
1759920Syasuko.eckert@amd.com//
1762292SN/A//////////////////////////////////////////////////////////////////////
17712105Snathanael.premillieu@arm.com
1781060SN/Atemplate <class OS>
1792292SN/Aint
18012105Snathanael.premillieu@arm.comioctlFunc(SyscallDesc *desc, int callnum, Process *process,
1811060SN/A          ExecContext *xc)
18212109SRekai.GonzalezAlberquilla@arm.com{
18312109SRekai.GonzalezAlberquilla@arm.com    int fd = xc->getSyscallArg(0);
18412109SRekai.GonzalezAlberquilla@arm.com    unsigned req = xc->getSyscallArg(1);
18512109SRekai.GonzalezAlberquilla@arm.com
18612109SRekai.GonzalezAlberquilla@arm.com    // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
18712109SRekai.GonzalezAlberquilla@arm.com
18813610Sgiacomo.gabrielli@arm.com    if (fd < 0 || process->sim_fd(fd) < 0) {
18913610Sgiacomo.gabrielli@arm.com        // doesn't map to any simulator fd: not a valid target fd
19013610Sgiacomo.gabrielli@arm.com        return -EBADF;
1919920Syasuko.eckert@amd.com    }
19212105Snathanael.premillieu@arm.com
1939920Syasuko.eckert@amd.com    switch (req) {
1942292SN/A      case OS::TIOCISATTY:
19512105Snathanael.premillieu@arm.com      case OS::TIOCGETP:
1961060SN/A      case OS::TIOCSETP:
19712109SRekai.GonzalezAlberquilla@arm.com      case OS::TIOCSETN:
19812109SRekai.GonzalezAlberquilla@arm.com      case OS::TIOCSETC:
19912109SRekai.GonzalezAlberquilla@arm.com      case OS::TIOCGETC:
20012109SRekai.GonzalezAlberquilla@arm.com        return -ENOTTY;
2012292SN/A
20212105Snathanael.premillieu@arm.com      default:
2031060SN/A        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req);
2042292SN/A    }
20512105Snathanael.premillieu@arm.com}
2061060SN/A
20712109SRekai.GonzalezAlberquilla@arm.comstruct OpenFlagTransTable {
20812109SRekai.GonzalezAlberquilla@arm.com    int tgtFlag;
20912109SRekai.GonzalezAlberquilla@arm.com    int hostFlag;
21012109SRekai.GonzalezAlberquilla@arm.com};
21112109SRekai.GonzalezAlberquilla@arm.com
21212109SRekai.GonzalezAlberquilla@arm.com
21312109SRekai.GonzalezAlberquilla@arm.comtemplate <class OS>
21412109SRekai.GonzalezAlberquilla@arm.comint
21513610Sgiacomo.gabrielli@arm.comopenFunc(SyscallDesc *desc, int callnum, Process *process,
21613610Sgiacomo.gabrielli@arm.com         ExecContext *xc)
21713610Sgiacomo.gabrielli@arm.com{
2189920Syasuko.eckert@amd.com    std::string path;
21912105Snathanael.premillieu@arm.com
2209920Syasuko.eckert@amd.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
2212292SN/A        return -EFAULT;
2229919Ssteve.reinhardt@amd.com
2231060SN/A    if (path == "/dev/sysdev0") {
2242292SN/A        // This is a memory-mapped high-resolution timer device on Alpha.
2259919Ssteve.reinhardt@amd.com        // We don't support it, so just punt.
2261060SN/A        DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
22712109SRekai.GonzalezAlberquilla@arm.com        return -ENOENT;
22812109SRekai.GonzalezAlberquilla@arm.com    }
22912109SRekai.GonzalezAlberquilla@arm.com
23012109SRekai.GonzalezAlberquilla@arm.com    int tgtFlags = xc->getSyscallArg(1);
23112109SRekai.GonzalezAlberquilla@arm.com    int mode = xc->getSyscallArg(2);
23212109SRekai.GonzalezAlberquilla@arm.com    int hostFlags = 0;
23313610Sgiacomo.gabrielli@arm.com
23413610Sgiacomo.gabrielli@arm.com    // translate open flags
23513610Sgiacomo.gabrielli@arm.com    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
2369920Syasuko.eckert@amd.com        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
2379920Syasuko.eckert@amd.com            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
2389920Syasuko.eckert@amd.com            hostFlags |= OS::openFlagTable[i].hostFlag;
2392292SN/A        }
2409919Ssteve.reinhardt@amd.com    }
2411060SN/A
2422292SN/A    // any target flags left?
2439919Ssteve.reinhardt@amd.com    if (tgtFlags != 0)
2449920Syasuko.eckert@amd.com        cerr << "Syscall: open: cannot decode flags: " <<  tgtFlags << endl;
24512109SRekai.GonzalezAlberquilla@arm.com
24612109SRekai.GonzalezAlberquilla@arm.com#ifdef __CYGWIN32__
24712109SRekai.GonzalezAlberquilla@arm.com    hostFlags |= O_BINARY;
24813598Sgiacomo.travaglini@arm.com#endif
24913598Sgiacomo.travaglini@arm.com
25013598Sgiacomo.travaglini@arm.com    // open the file
25113610Sgiacomo.gabrielli@arm.com    int fd = open(path.c_str(), hostFlags, mode);
25213610Sgiacomo.gabrielli@arm.com
25313610Sgiacomo.gabrielli@arm.com    return (fd == -1) ? -errno : process->open_fd(fd);
2549920Syasuko.eckert@amd.com}
2559920Syasuko.eckert@amd.com
2561060SN/A
2571060SN/Atemplate <class OS>
25812109SRekai.GonzalezAlberquilla@arm.comint
25912109SRekai.GonzalezAlberquilla@arm.comstatFunc(SyscallDesc *desc, int callnum, Process *process,
26012109SRekai.GonzalezAlberquilla@arm.com         ExecContext *xc)
26112109SRekai.GonzalezAlberquilla@arm.com{
26212109SRekai.GonzalezAlberquilla@arm.com    std::string path;
26312109SRekai.GonzalezAlberquilla@arm.com
26412109SRekai.GonzalezAlberquilla@arm.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
26512109SRekai.GonzalezAlberquilla@arm.com        return -EFAULT;
26612109SRekai.GonzalezAlberquilla@arm.com
26712109SRekai.GonzalezAlberquilla@arm.com    struct stat hostBuf;
26812109SRekai.GonzalezAlberquilla@arm.com    int result = stat(path.c_str(), &hostBuf);
26912109SRekai.GonzalezAlberquilla@arm.com
27012109SRekai.GonzalezAlberquilla@arm.com    if (result < 0)
27112109SRekai.GonzalezAlberquilla@arm.com        return -errno;
27212109SRekai.GonzalezAlberquilla@arm.com
27312109SRekai.GonzalezAlberquilla@arm.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
27412109SRekai.GonzalezAlberquilla@arm.com
27512109SRekai.GonzalezAlberquilla@arm.com    return 0;
27612109SRekai.GonzalezAlberquilla@arm.com}
27712109SRekai.GonzalezAlberquilla@arm.com
27812109SRekai.GonzalezAlberquilla@arm.com
27912109SRekai.GonzalezAlberquilla@arm.comtemplate <class OS>
28012109SRekai.GonzalezAlberquilla@arm.comint
28112109SRekai.GonzalezAlberquilla@arm.comlstatFunc(SyscallDesc *desc, int callnum, Process *process,
28212109SRekai.GonzalezAlberquilla@arm.com          ExecContext *xc)
28312109SRekai.GonzalezAlberquilla@arm.com{
28413610Sgiacomo.gabrielli@arm.com    std::string path;
28513610Sgiacomo.gabrielli@arm.com
28613610Sgiacomo.gabrielli@arm.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
28712109SRekai.GonzalezAlberquilla@arm.com        return -EFAULT;
28812109SRekai.GonzalezAlberquilla@arm.com
28912109SRekai.GonzalezAlberquilla@arm.com    struct stat hostBuf;
29012109SRekai.GonzalezAlberquilla@arm.com    int result = lstat(path.c_str(), &hostBuf);
29112109SRekai.GonzalezAlberquilla@arm.com
29212109SRekai.GonzalezAlberquilla@arm.com    if (result < 0)
29312109SRekai.GonzalezAlberquilla@arm.com        return -errno;
29412109SRekai.GonzalezAlberquilla@arm.com
29512109SRekai.GonzalezAlberquilla@arm.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
29612109SRekai.GonzalezAlberquilla@arm.com
2971060SN/A    return 0;
29812105Snathanael.premillieu@arm.com}
2991060SN/A
30012106SRekai.GonzalezAlberquilla@arm.comtemplate <class OS>
30112106SRekai.GonzalezAlberquilla@arm.comint
3021060SN/AfstatFunc(SyscallDesc *desc, int callnum, Process *process,
3031060SN/A          ExecContext *xc)
30412106SRekai.GonzalezAlberquilla@arm.com{
30512105Snathanael.premillieu@arm.com    int fd = process->sim_fd(xc->getSyscallArg(0));
30612105Snathanael.premillieu@arm.com
30712105Snathanael.premillieu@arm.com    // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
30812105Snathanael.premillieu@arm.com
30912105Snathanael.premillieu@arm.com    if (fd < 0)
31012105Snathanael.premillieu@arm.com        return -EBADF;
31112109SRekai.GonzalezAlberquilla@arm.com
31212109SRekai.GonzalezAlberquilla@arm.com    struct stat hostBuf;
31312109SRekai.GonzalezAlberquilla@arm.com    int result = fstat(fd, &hostBuf);
31412109SRekai.GonzalezAlberquilla@arm.com
31512109SRekai.GonzalezAlberquilla@arm.com    if (result < 0)
31612109SRekai.GonzalezAlberquilla@arm.com        return -errno;
31713610Sgiacomo.gabrielli@arm.com
31813610Sgiacomo.gabrielli@arm.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
31913610Sgiacomo.gabrielli@arm.com
32012105Snathanael.premillieu@arm.com    return 0;
32112105Snathanael.premillieu@arm.com}
32212105Snathanael.premillieu@arm.com
32312105Snathanael.premillieu@arm.com
32412105Snathanael.premillieu@arm.com//
32512106SRekai.GonzalezAlberquilla@arm.com// We don't really handle mmap().  If the target is mmaping an
3261060SN/A// anonymous region or /dev/zero, we can get away with doing basically
3275362Sksewell@umich.edu// nothing (since memory is initialized to zero and the simulator
3285364Sksewell@umich.edu// doesn't really check addresses anyway).  Always print a warning,
3295364Sksewell@umich.edu// since this could be seriously broken if we're not mapping
3305364Sksewell@umich.edu// /dev/zero.
3315364Sksewell@umich.edu//
3325364Sksewell@umich.edu// Someday we should explicitly check for /dev/zero in open, flag the
3335364Sksewell@umich.edu// file descriptor, and fail (or implement!) a non-anonymous mmap to
3345364Sksewell@umich.edu// anything else.
3355364Sksewell@umich.edu//
3365364Sksewell@umich.edutemplate <class OS>
3375364Sksewell@umich.eduint
3385364Sksewell@umich.edummapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
3391060SN/A{
3401060SN/A    Addr start = xc->getSyscallArg(0);
3411060SN/A    uint64_t length = xc->getSyscallArg(1);
3422292SN/A    // int prot = xc->getSyscallArg(2);
343    int flags = xc->getSyscallArg(3);
344    int fd = p->sim_fd(xc->getSyscallArg(4));
345    // int offset = xc->getSyscallArg(5);
346
347    if (start == 0) {
348        // user didn't give an address... pick one from our "mmap region"
349        start = p->mmap_base;
350        p->mmap_base += RoundUp<Addr>(length, VMPageSize);
351    }
352
353    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
354        DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d.  "
355                "This will break if not /dev/zero.", fd);
356    }
357
358    return start;
359}
360
361
362template <class OS>
363int
364getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
365              ExecContext *xc)
366{
367    unsigned resource = xc->getSyscallArg(0);
368    TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
369
370    switch (resource) {
371      case OS::RLIMIT_STACK:
372        // max stack size in bytes: make up a number (2MB for now)
373        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
374        break;
375
376      default:
377        cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
378        abort();
379        break;
380    }
381
382    rlp.copyOut(xc->mem);
383    return 0;
384}
385
386// 1M usecs in 1 sec, for readability
387const int one_million = 1000000;
388
389// seconds since the epoch (1/1/1970)... about a billion, by my reckoning
390const unsigned seconds_since_epoch = 1000000000;
391
392//
393// helper function: populate struct timeval with approximation of
394// current elapsed time
395//
396template <class T1, class T2>
397void
398getElapsedTime(T1 &sec, T2 &usec)
399{
400    int cycles_per_usec = ticksPerSecond / one_million;
401
402    int elapsed_usecs = curTick / cycles_per_usec;
403    sec = elapsed_usecs / one_million;
404    usec = elapsed_usecs % one_million;
405}
406
407
408template <class OS>
409int
410gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
411                 ExecContext *xc)
412{
413    TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
414
415    getElapsedTime(tp->tv_sec, tp->tv_usec);
416    tp->tv_sec += seconds_since_epoch;
417
418    tp.copyOut(xc->mem);
419
420    return 0;
421}
422
423
424template <class OS>
425int
426getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
427              ExecContext *xc)
428{
429    int who = xc->getSyscallArg(0);	// THREAD, SELF, or CHILDREN
430    TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
431
432    if (who != OS::RUSAGE_SELF) {
433        // don't really handle THREAD or CHILDREN, but just warn and
434        // plow ahead
435        DCOUT(SyscallWarnings)
436            << "Warning: getrusage() only supports RUSAGE_SELF."
437            << "  Parameter " << who << " ignored." << endl;
438    }
439
440    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
441    rup->ru_stime.tv_sec = 0;
442    rup->ru_stime.tv_usec = 0;
443    rup->ru_maxrss = 0;
444    rup->ru_ixrss = 0;
445    rup->ru_idrss = 0;
446    rup->ru_isrss = 0;
447    rup->ru_minflt = 0;
448    rup->ru_majflt = 0;
449    rup->ru_nswap = 0;
450    rup->ru_inblock = 0;
451    rup->ru_oublock = 0;
452    rup->ru_msgsnd = 0;
453    rup->ru_msgrcv = 0;
454    rup->ru_nsignals = 0;
455    rup->ru_nvcsw = 0;
456    rup->ru_nivcsw = 0;
457
458    rup.copyOut(xc->mem);
459
460    return 0;
461}
462
463
464
465#endif // __SYSCALL_EMUL_HH__
466