syscall_emul.hh revision 511
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
310796Sbrandon.potter@amd.com * All rights reserved.
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without
610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are
710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright
810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer;
910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright
1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the
1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution;
1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its
1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from
1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission.
151458SN/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.
27360SN/A */
28360SN/A
29360SN/A#ifndef __SYSCALL_EMUL_HH__
30360SN/A#define __SYSCALL_EMUL_HH__
31360SN/A
32360SN/A///
33360SN/A/// @file syscall_emul.hh
34360SN/A///
35360SN/A/// This file defines objects used to emulate syscalls from the target
36360SN/A/// application on the host machine.
37360SN/A
38360SN/A#include <string>
39360SN/A
402665Ssaidi@eecs.umich.edu#include "base/intmath.hh"	// for RoundUp
412665Ssaidi@eecs.umich.edu#include "targetarch/isa_traits.hh"	// for Addr
422665Ssaidi@eecs.umich.edu#include "mem/functional_mem/functional_memory.hh"
43360SN/A
44360SN/Aclass Process;
451354SN/Aclass ExecContext;
461354SN/A
47360SN/A///
4812018Sandreas.sandberg@arm.com/// System call descriptor.
4912018Sandreas.sandberg@arm.com///
5012018Sandreas.sandberg@arm.comclass SyscallDesc {
5112018Sandreas.sandberg@arm.com
5212018Sandreas.sandberg@arm.com  public:
5312018Sandreas.sandberg@arm.com
5412018Sandreas.sandberg@arm.com    /// Typedef for target syscall handler functions.
552064SN/A    typedef int (*FuncPtr)(SyscallDesc *, int num,
5612018Sandreas.sandberg@arm.com                           Process *, ExecContext *);
5712018Sandreas.sandberg@arm.com
5812018Sandreas.sandberg@arm.com    const char *name;	//!< Syscall name (e.g., "open").
5912018Sandreas.sandberg@arm.com    FuncPtr funcPtr;	//!< Pointer to emulation function.
6012018Sandreas.sandberg@arm.com    int flags;		//!< Flags (see Flags enum).
6112018Sandreas.sandberg@arm.com
6211799Sbrandon.potter@amd.com    /// Flag values for controlling syscall behavior.
6312018Sandreas.sandberg@arm.com    enum Flags {
6412018Sandreas.sandberg@arm.com        /// Don't set return regs according to funcPtr return value.
6512018Sandreas.sandberg@arm.com        /// Used for syscalls with non-standard return conventions
6612018Sandreas.sandberg@arm.com        /// that explicitly set the ExecContext regs (e.g.,
6712018Sandreas.sandberg@arm.com        /// sigreturn).
6812018Sandreas.sandberg@arm.com        SuppressReturnValue = 1
6911799Sbrandon.potter@amd.com    };
70360SN/A
71360SN/A    /// Constructor.
72360SN/A    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
73360SN/A        : name(_name), funcPtr(_funcPtr), flags(_flags)
74360SN/A    {
75360SN/A    }
761809SN/A
7711800Sbrandon.potter@amd.com    /// Emulate the syscall.  Public interface for calling through funcPtr.
7811392Sbrandon.potter@amd.com    void doSyscall(int callnum, Process *proc, ExecContext *xc);
791809SN/A};
8011392Sbrandon.potter@amd.com
8113570Sbrandon.potter@amd.com
8211383Sbrandon.potter@amd.comclass BaseBufferArg {
8313568Sbrandon.potter@amd.com
843113Sgblack@eecs.umich.edu  public:
8511799Sbrandon.potter@amd.com
8611759Sbrandon.potter@amd.com    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
8711812Sbaz21@cam.ac.uk    {
8811812Sbaz21@cam.ac.uk        bufPtr = new uint8_t[size];
8911799Sbrandon.potter@amd.com        // clear out buffer: in case we only partially populate this,
908229Snate@binkert.org        // and then do a copyOut(), we want to make sure we don't
9113570Sbrandon.potter@amd.com        // introduce any random junk into the simulated address space
928229Snate@binkert.org        memset(bufPtr, 0, size);
9311594Santhony.gutierrez@amd.com    }
947075Snate@binkert.org
958229Snate@binkert.org    virtual ~BaseBufferArg() { delete [] bufPtr; }
9611856Sbrandon.potter@amd.com
977075Snate@binkert.org    //
98360SN/A    // copy data into simulator space (read from target memory)
9912461Sgabeblack@google.com    //
10011886Sbrandon.potter@amd.com    virtual bool copyIn(FunctionalMemory *mem)
10111800Sbrandon.potter@amd.com    {
10211392Sbrandon.potter@amd.com        mem->access(Read, addr, bufPtr, size);
10312334Sgabeblack@google.com        return true;	// no EFAULT detection for now
1041354SN/A    }
1056216Snate@binkert.org
1066658Snate@binkert.org    //
1072474SN/A    // copy data out of simulator space (write to target memory)
1082680Sktlim@umich.edu    //
1098229Snate@binkert.org    virtual bool copyOut(FunctionalMemory *mem)
11011886Sbrandon.potter@amd.com    {
11110496Ssteve.reinhardt@amd.com        mem->access(Write, addr, bufPtr, size);
11211911SBrandon.Potter@amd.com        return true;	// no EFAULT detection for now
1138229Snate@binkert.org    }
11411794Sbrandon.potter@amd.com
11511886Sbrandon.potter@amd.com  protected:
11610497Ssteve.reinhardt@amd.com    Addr addr;
11711794Sbrandon.potter@amd.com    int size;
118360SN/A    uint8_t *bufPtr;
119360SN/A};
120360SN/A
121360SN/A
122360SN/Aclass BufferArg : public BaseBufferArg
123360SN/A{
124360SN/A  public:
125360SN/A    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
126360SN/A    void *bufferPtr()	{ return bufPtr; }
127360SN/A};
128378SN/A
1291706SN/Atemplate <class T>
13011851Sbrandon.potter@amd.comclass TypedBufferArg : public BaseBufferArg
131378SN/A{
132378SN/A  public:
133378SN/A    // user can optionally specify a specific number of bytes to
134378SN/A    // allocate to deal with those structs that have variable-size
135378SN/A    // arrays at the end
1361706SN/A    TypedBufferArg(Addr _addr, int _size = sizeof(T))
13711851Sbrandon.potter@amd.com        : BaseBufferArg(_addr, _size)
138360SN/A    { }
13911760Sbrandon.potter@amd.com
14011760Sbrandon.potter@amd.com    // type case
14111851Sbrandon.potter@amd.com    operator T*() { return (T *)bufPtr; }
14211760Sbrandon.potter@amd.com
1436109Ssanchezd@stanford.edu    // dereference operators
1441706SN/A    T &operator*()	 { return *((T *)bufPtr); }
14511851Sbrandon.potter@amd.com    T* operator->()	 { return (T *)bufPtr; }
146378SN/A    T &operator[](int i) { return ((T *)bufPtr)[i]; }
1476109Ssanchezd@stanford.edu};
1486109Ssanchezd@stanford.edu
14911851Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
1506109Ssanchezd@stanford.edu//
15111886Sbrandon.potter@amd.com// The following emulation functions are generic enough that they
15211886Sbrandon.potter@amd.com// don't need to be recompiled for different emulated OS's.  They are
15311886Sbrandon.potter@amd.com// defined in sim/syscall_emul.cc.
15411886Sbrandon.potter@amd.com//
155378SN/A//////////////////////////////////////////////////////////////////////
1561706SN/A
15711851Sbrandon.potter@amd.com
158378SN/A/// Handler for unimplemented syscalls that we haven't thought about.
1595748SSteve.Reinhardt@amd.comint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1605748SSteve.Reinhardt@amd.com
16111851Sbrandon.potter@amd.com/// Handler for unimplemented syscalls that we never intend to
162378SN/A/// implement (signal handling, etc.) and should not affect the correct
163378SN/A/// behavior of the program.  Print a warning only if the appropriate
1641706SN/A/// trace flag is enabled.  Return success to the target program.
16511851Sbrandon.potter@amd.comint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
166378SN/A
167378SN/A/// Target exit() handler: terminate simulation.
1681706SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
16911851Sbrandon.potter@amd.com
170378SN/A/// Target getpagesize() handler.
1714118Sgblack@eecs.umich.eduint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1724118Sgblack@eecs.umich.edu
17311851Sbrandon.potter@amd.com/// Target obreak() handler: set brk address.
1744118Sgblack@eecs.umich.eduint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
175378SN/A
1761706SN/A/// Target close() handler.
17711851Sbrandon.potter@amd.comint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
178378SN/A
17913568Sbrandon.potter@amd.com/// Target read() handler.
18013568Sbrandon.potter@amd.comint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
18113568Sbrandon.potter@amd.com
18213568Sbrandon.potter@amd.com/// Target write() handler.
183378SN/Aint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1841706SN/A
18511851Sbrandon.potter@amd.com/// Target lseek() handler.
186360SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1875513SMichael.Adler@intel.com
1885513SMichael.Adler@intel.com/// Target munmap() handler.
18911851Sbrandon.potter@amd.comint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1905513SMichael.Adler@intel.com
19110203SAli.Saidi@ARM.com/// Target gethostname() handler.
19210203SAli.Saidi@ARM.comint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
19311851Sbrandon.potter@amd.com
19410203SAli.Saidi@ARM.com/// Target unlink() handler.
1955513SMichael.Adler@intel.comint unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
19611851Sbrandon.potter@amd.com
1975513SMichael.Adler@intel.com/// Target rename() handler.
198511SN/Aint renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
19910633Smichaelupton@gmail.com
20011851Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
20110633Smichaelupton@gmail.com//
2021706SN/A// The following emulation functions are generic, but need to be
20311851Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc.
204511SN/A//
20512795Smattdsinclair@gmail.com//////////////////////////////////////////////////////////////////////
20612795Smattdsinclair@gmail.com
20712795Smattdsinclair@gmail.com/// Target ioctl() handler.  For the most part, programs call ioctl()
20812795Smattdsinclair@gmail.com/// only to find out if their stdout is a tty, to determine whether to
20912796Smattdsinclair@gmail.com/// do line or block buffering.
21012796Smattdsinclair@gmail.comtemplate <class OS>
21112796Smattdsinclair@gmail.comint
21212796Smattdsinclair@gmail.comioctlFunc(SyscallDesc *desc, int callnum, Process *process,
2135513SMichael.Adler@intel.com          ExecContext *xc)
2145513SMichael.Adler@intel.com{
21511851Sbrandon.potter@amd.com    int fd = xc->getSyscallArg(0);
2165513SMichael.Adler@intel.com    unsigned req = xc->getSyscallArg(1);
21713031Sbrandon.potter@amd.com
21813031Sbrandon.potter@amd.com    // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
21913031Sbrandon.potter@amd.com
22013031Sbrandon.potter@amd.com    if (fd < 0 || process->sim_fd(fd) < 0) {
22113031Sbrandon.potter@amd.com        // doesn't map to any simulator fd: not a valid target fd
22213031Sbrandon.potter@amd.com        return -EBADF;
22313031Sbrandon.potter@amd.com    }
22413031Sbrandon.potter@amd.com
22513031Sbrandon.potter@amd.com    switch (req) {
22613031Sbrandon.potter@amd.com      case OS::TIOCISATTY:
22713031Sbrandon.potter@amd.com      case OS::TIOCGETP:
22813031Sbrandon.potter@amd.com      case OS::TIOCSETP:
229511SN/A      case OS::TIOCSETN:
2301706SN/A      case OS::TIOCSETC:
23111851Sbrandon.potter@amd.com      case OS::TIOCGETC:
2321706SN/A      case OS::TIOCGETS:
2331706SN/A      case OS::TIOCGETA:
2341706SN/A        return -ENOTTY;
2351706SN/A
23611851Sbrandon.potter@amd.com      default:
2371706SN/A        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", fd, req, xc->readPC());
2381706SN/A    }
2391706SN/A}
2401706SN/A
24111851Sbrandon.potter@amd.com/// This struct is used to build an target-OS-dependent table that
2421706SN/A/// maps the target's open() flags to the host open() flags.
243511SN/Astruct OpenFlagTransTable {
2446703Svince@csl.cornell.edu    int tgtFlag;	//!< Target system flag value.
2456703Svince@csl.cornell.edu    int hostFlag;	//!< Corresponding host system flag value.
24611851Sbrandon.potter@amd.com};
2476703Svince@csl.cornell.edu
2486685Stjones1@inf.ed.ac.uk
2496685Stjones1@inf.ed.ac.uk/// Target open() handler.
25011851Sbrandon.potter@amd.comtemplate <class OS>
2516685Stjones1@inf.ed.ac.ukint
2526685Stjones1@inf.ed.ac.ukopenFunc(SyscallDesc *desc, int callnum, Process *process,
2535513SMichael.Adler@intel.com         ExecContext *xc)
2545513SMichael.Adler@intel.com{
25511851Sbrandon.potter@amd.com    std::string path;
2565513SMichael.Adler@intel.com
25711885Sbrandon.potter@amd.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
25811885Sbrandon.potter@amd.com        return -EFAULT;
25911885Sbrandon.potter@amd.com
2605513SMichael.Adler@intel.com    if (path == "/dev/sysdev0") {
2611999SN/A        // This is a memory-mapped high-resolution timer device on Alpha.
2621999SN/A        // We don't support it, so just punt.
26311851Sbrandon.potter@amd.com        DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
2641999SN/A        return -ENOENT;
26511885Sbrandon.potter@amd.com    }
26611885Sbrandon.potter@amd.com
26711885Sbrandon.potter@amd.com    int tgtFlags = xc->getSyscallArg(1);
2681999SN/A    int mode = xc->getSyscallArg(2);
2691999SN/A    int hostFlags = 0;
2701999SN/A
27111851Sbrandon.potter@amd.com    // translate open flags
2721999SN/A    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
2733079Sstever@eecs.umich.edu        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
2743079Sstever@eecs.umich.edu            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
27511851Sbrandon.potter@amd.com            hostFlags |= OS::openFlagTable[i].hostFlag;
2763079Sstever@eecs.umich.edu        }
27711908SBrandon.Potter@amd.com    }
27811908SBrandon.Potter@amd.com
27911908SBrandon.Potter@amd.com    // any target flags left?
28011908SBrandon.Potter@amd.com    if (tgtFlags != 0)
28111875Sbrandon.potter@amd.com        cerr << "Syscall: open: cannot decode flags: " <<  tgtFlags << endl;
2822093SN/A
28311851Sbrandon.potter@amd.com#ifdef __CYGWIN32__
2842093SN/A    hostFlags |= O_BINARY;
2852687Sksewell@umich.edu#endif
2862687Sksewell@umich.edu
28711851Sbrandon.potter@amd.com    // open the file
2882687Sksewell@umich.edu    int fd = open(path.c_str(), hostFlags, mode);
2892238SN/A
2902238SN/A    return (fd == -1) ? -errno : process->open_fd(fd);
29111851Sbrandon.potter@amd.com}
2922238SN/A
29311908SBrandon.Potter@amd.com
29411908SBrandon.Potter@amd.com/// Target stat() handler.
29511908SBrandon.Potter@amd.comtemplate <class OS>
29611908SBrandon.Potter@amd.comint
29711908SBrandon.Potter@amd.comstatFunc(SyscallDesc *desc, int callnum, Process *process,
29811908SBrandon.Potter@amd.com         ExecContext *xc)
29911908SBrandon.Potter@amd.com{
30011908SBrandon.Potter@amd.com    std::string path;
3012238SN/A
3022238SN/A    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
30311851Sbrandon.potter@amd.com        return -EFAULT;
3042238SN/A
30513571Sbrandon.potter@amd.com    struct stat hostBuf;
30613571Sbrandon.potter@amd.com    int result = stat(path.c_str(), &hostBuf);
30713571Sbrandon.potter@amd.com
30813571Sbrandon.potter@amd.com    if (result < 0)
30913568Sbrandon.potter@amd.com        return -errno;
31013568Sbrandon.potter@amd.com
31113568Sbrandon.potter@amd.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
31213568Sbrandon.potter@amd.com
31313568Sbrandon.potter@amd.com    return 0;
31413568Sbrandon.potter@amd.com}
31513568Sbrandon.potter@amd.com
31613568Sbrandon.potter@amd.com
31713568Sbrandon.potter@amd.com/// Target lstat() handler.
31813568Sbrandon.potter@amd.comtemplate <class OS>
31913568Sbrandon.potter@amd.comint
32013568Sbrandon.potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, Process *process,
32113448Sciro.santilli@arm.com          ExecContext *xc)
32213031Sbrandon.potter@amd.com{
32313031Sbrandon.potter@amd.com    std::string path;
32413031Sbrandon.potter@amd.com
32513448Sciro.santilli@arm.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
32613031Sbrandon.potter@amd.com        return -EFAULT;
32713539Sjavier.setoain@arm.com
32813539Sjavier.setoain@arm.com    struct stat hostBuf;
32913539Sjavier.setoain@arm.com    int result = lstat(path.c_str(), &hostBuf);
33013539Sjavier.setoain@arm.com
33113539Sjavier.setoain@arm.com    if (result < 0)
33213539Sjavier.setoain@arm.com        return -errno;
33313569Sbrandon.potter@amd.com
33413569Sbrandon.potter@amd.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
33513569Sbrandon.potter@amd.com
33613569Sbrandon.potter@amd.com    return 0;
33713569Sbrandon.potter@amd.com}
33813569Sbrandon.potter@amd.com
33913569Sbrandon.potter@amd.com/// Target fstat() handler.
34013569Sbrandon.potter@amd.comtemplate <class OS>
34113569Sbrandon.potter@amd.comint
34213569Sbrandon.potter@amd.comfstatFunc(SyscallDesc *desc, int callnum, Process *process,
34313569Sbrandon.potter@amd.com          ExecContext *xc)
34413569Sbrandon.potter@amd.com{
34513569Sbrandon.potter@amd.com    int fd = process->sim_fd(xc->getSyscallArg(0));
34613569Sbrandon.potter@amd.com
34713569Sbrandon.potter@amd.com    // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
34813569Sbrandon.potter@amd.com
34913031Sbrandon.potter@amd.com    if (fd < 0)
3502238SN/A        return -EBADF;
35111851Sbrandon.potter@amd.com
3522238SN/A    struct stat hostBuf;
3532238SN/A    int result = fstat(fd, &hostBuf);
3542238SN/A
35511851Sbrandon.potter@amd.com    if (result < 0)
3562238SN/A        return -errno;
3572238SN/A
3582238SN/A    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
35911851Sbrandon.potter@amd.com
3602238SN/A    return 0;
3612238SN/A}
3622238SN/A
36311851Sbrandon.potter@amd.com
3642238SN/A/// Target mmap() handler.
3652238SN/A///
3662238SN/A/// We don't really handle mmap().  If the target is mmaping an
36711851Sbrandon.potter@amd.com/// anonymous region or /dev/zero, we can get away with doing basically
3682238SN/A/// nothing (since memory is initialized to zero and the simulator
3699455Smitch.hayenga+gem5@gmail.com/// doesn't really check addresses anyway).  Always print a warning,
3709455Smitch.hayenga+gem5@gmail.com/// since this could be seriously broken if we're not mapping
37111851Sbrandon.potter@amd.com/// /dev/zero.
37210203SAli.Saidi@ARM.com//
37311851Sbrandon.potter@amd.com/// Someday we should explicitly check for /dev/zero in open, flag the
37411851Sbrandon.potter@amd.com/// file descriptor, and fail (or implement!) a non-anonymous mmap to
3759455Smitch.hayenga+gem5@gmail.com/// anything else.
37613571Sbrandon.potter@amd.comtemplate <class OS>
37713571Sbrandon.potter@amd.comint
37813571Sbrandon.potter@amd.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
37913571Sbrandon.potter@amd.com{
38013571Sbrandon.potter@amd.com    Addr start = xc->getSyscallArg(0);
38113571Sbrandon.potter@amd.com    uint64_t length = xc->getSyscallArg(1);
38213571Sbrandon.potter@amd.com    // int prot = xc->getSyscallArg(2);
38313571Sbrandon.potter@amd.com    int flags = xc->getSyscallArg(3);
38413571Sbrandon.potter@amd.com    // int fd = p->sim_fd(xc->getSyscallArg(4));
38513571Sbrandon.potter@amd.com    // int offset = xc->getSyscallArg(5);
38613571Sbrandon.potter@amd.com
38713571Sbrandon.potter@amd.com    if (start == 0) {
3889112Smarc.orr@gmail.com        // user didn't give an address... pick one from our "mmap region"
38911906SBrandon.Potter@amd.com        start = p->mmap_base;
39011906SBrandon.Potter@amd.com        p->mmap_base += RoundUp<Addr>(length, VMPageSize);
3919112Smarc.orr@gmail.com    }
3929112Smarc.orr@gmail.com
39311851Sbrandon.potter@amd.com    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
3949112Smarc.orr@gmail.com        DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d.  "
3959112Smarc.orr@gmail.com                "This will break if not /dev/zero.", xc->getSyscallArg(4));
39611911SBrandon.Potter@amd.com    }
3979112Smarc.orr@gmail.com
39811911SBrandon.Potter@amd.com    return start;
39911911SBrandon.Potter@amd.com}
40011911SBrandon.Potter@amd.com
40111911SBrandon.Potter@amd.com/// Target getrlimit() handler.
4029112Smarc.orr@gmail.comtemplate <class OS>
40311911SBrandon.Potter@amd.comint
40411911SBrandon.Potter@amd.comgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
40511911SBrandon.Potter@amd.com              ExecContext *xc)
40611911SBrandon.Potter@amd.com{
4079238Slluc.alvarez@bsc.es    unsigned resource = xc->getSyscallArg(0);
4089112Smarc.orr@gmail.com    TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
40911911SBrandon.Potter@amd.com
4109112Smarc.orr@gmail.com    switch (resource) {
41111911SBrandon.Potter@amd.com      case OS::RLIMIT_STACK:
41211911SBrandon.Potter@amd.com        // max stack size in bytes: make up a number (2MB for now)
41311911SBrandon.Potter@amd.com        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
41411911SBrandon.Potter@amd.com        break;
41511911SBrandon.Potter@amd.com
4169112Smarc.orr@gmail.com      default:
41711911SBrandon.Potter@amd.com        cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
41811911SBrandon.Potter@amd.com        abort();
41911911SBrandon.Potter@amd.com        break;
42011911SBrandon.Potter@amd.com    }
42111911SBrandon.Potter@amd.com
42211911SBrandon.Potter@amd.com    rlp.copyOut(xc->mem);
4239112Smarc.orr@gmail.com    return 0;
4249112Smarc.orr@gmail.com}
42511911SBrandon.Potter@amd.com
42611911SBrandon.Potter@amd.com/// A readable name for 1,000,000, for converting microseconds to seconds.
4279112Smarc.orr@gmail.comconst int one_million = 1000000;
42811911SBrandon.Potter@amd.com
42911911SBrandon.Potter@amd.com/// Approximate seconds since the epoch (1/1/1970).  About a billion,
4309112Smarc.orr@gmail.com/// by my reckoning.  We want to keep this a constant (not use the
4319112Smarc.orr@gmail.com/// real-world time) to keep simulations repeatable.
43211911SBrandon.Potter@amd.comconst unsigned seconds_since_epoch = 1000000000;
43311911SBrandon.Potter@amd.com
4349112Smarc.orr@gmail.com/// Helper function to convert current elapsed time to seconds and
4359112Smarc.orr@gmail.com/// microseconds.
4362238SN/Atemplate <class T1, class T2>
4372238SN/Avoid
4382238SN/AgetElapsedTime(T1 &sec, T2 &usec)
4392238SN/A{
44011851Sbrandon.potter@amd.com    int cycles_per_usec = ticksPerSecond / one_million;
4412238SN/A
4422238SN/A    int elapsed_usecs = curTick / cycles_per_usec;
4432238SN/A    sec = elapsed_usecs / one_million;
44411851Sbrandon.potter@amd.com    usec = elapsed_usecs % one_million;
4452238SN/A}
4462238SN/A
4472238SN/A
44811851Sbrandon.potter@amd.com/// Target gettimeofday() handler.
4492238SN/Atemplate <class OS>
4502238SN/Aint
4512238SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
45211851Sbrandon.potter@amd.com                 ExecContext *xc)
4532238SN/A{
4542238SN/A    TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
4551354SN/A
4561354SN/A    getElapsedTime(tp->tv_sec, tp->tv_usec);
45710796Sbrandon.potter@amd.com    tp->tv_sec += seconds_since_epoch;
45810796Sbrandon.potter@amd.com
4591354SN/A    tp.copyOut(xc->mem);
4601354SN/A
4611354SN/A    return 0;
4621354SN/A}
4631354SN/A
4641354SN/A
4651354SN/A/// Target getrusage() function.
4661354SN/Atemplate <class OS>
4671354SN/Aint
4681354SN/AgetrusageFunc(SyscallDesc *desc, int callnum, Process *process,
46910796Sbrandon.potter@amd.com              ExecContext *xc)
4701354SN/A{
47110796Sbrandon.potter@amd.com    int who = xc->getSyscallArg(0);	// THREAD, SELF, or CHILDREN
4721354SN/A    TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
4731354SN/A
4741354SN/A    if (who != OS::RUSAGE_SELF) {
4751354SN/A        // don't really handle THREAD or CHILDREN, but just warn and
47610796Sbrandon.potter@amd.com        // plow ahead
47710796Sbrandon.potter@amd.com        DCOUT(SyscallWarnings)
47810796Sbrandon.potter@amd.com            << "Warning: getrusage() only supports RUSAGE_SELF."
47910796Sbrandon.potter@amd.com            << "  Parameter " << who << " ignored." << endl;
48010796Sbrandon.potter@amd.com    }
48110796Sbrandon.potter@amd.com
48210796Sbrandon.potter@amd.com    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
48310796Sbrandon.potter@amd.com    rup->ru_stime.tv_sec = 0;
48410796Sbrandon.potter@amd.com    rup->ru_stime.tv_usec = 0;
48510796Sbrandon.potter@amd.com    rup->ru_maxrss = 0;
48610796Sbrandon.potter@amd.com    rup->ru_ixrss = 0;
487360SN/A    rup->ru_idrss = 0;
488360SN/A    rup->ru_isrss = 0;
489360SN/A    rup->ru_minflt = 0;
490360SN/A    rup->ru_majflt = 0;
491360SN/A    rup->ru_nswap = 0;
492360SN/A    rup->ru_inblock = 0;
493360SN/A    rup->ru_oublock = 0;
49411759Sbrandon.potter@amd.com    rup->ru_msgsnd = 0;
4953113Sgblack@eecs.umich.edu    rup->ru_msgrcv = 0;
4963113Sgblack@eecs.umich.edu    rup->ru_nsignals = 0;
4973113Sgblack@eecs.umich.edu    rup->ru_nvcsw = 0;
4983113Sgblack@eecs.umich.edu    rup->ru_nivcsw = 0;
4993113Sgblack@eecs.umich.edu
5003113Sgblack@eecs.umich.edu    rup.copyOut(xc->mem);
5013113Sgblack@eecs.umich.edu
5023113Sgblack@eecs.umich.edu    return 0;
5033113Sgblack@eecs.umich.edu}
5043113Sgblack@eecs.umich.edu
5053113Sgblack@eecs.umich.edu
5063113Sgblack@eecs.umich.edu
5073113Sgblack@eecs.umich.edu#endif // __SYSCALL_EMUL_HH__
50812032Sandreas.sandberg@arm.com