syscall_emul.hh revision 360
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 int (*FuncPtr)(SyscallDesc *, int num,
552064SN/A                           Process *, ExecContext *);
5612018Sandreas.sandberg@arm.com
5712018Sandreas.sandberg@arm.com    const char *name;	//!< Syscall name (e.g., "open").
5812018Sandreas.sandberg@arm.com    FuncPtr funcPtr;	//!< Pointer to emulation function.
5912018Sandreas.sandberg@arm.com    int flags;		//!< Flags (see Flags enum).
6012018Sandreas.sandberg@arm.com
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
8111383Sbrandon.potter@amd.com
823113Sgblack@eecs.umich.educlass BaseBufferArg {
8311799Sbrandon.potter@amd.com
8411759Sbrandon.potter@amd.com  public:
8511812Sbaz21@cam.ac.uk
8611812Sbaz21@cam.ac.uk    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
8711799Sbrandon.potter@amd.com    {
888229Snate@binkert.org        bufPtr = new uint8_t[size];
898229Snate@binkert.org        // clear out buffer: in case we only partially populate this,
9011594Santhony.gutierrez@amd.com        // and then do a copyOut(), we want to make sure we don't
917075Snate@binkert.org        // introduce any random junk into the simulated address space
928229Snate@binkert.org        memset(bufPtr, 0, size);
9311856Sbrandon.potter@amd.com    }
947075Snate@binkert.org
95360SN/A    virtual ~BaseBufferArg() { delete [] bufPtr; }
9612461Sgabeblack@google.com
9711886Sbrandon.potter@amd.com    //
9811800Sbrandon.potter@amd.com    // copy data into simulator space (read from target memory)
9911392Sbrandon.potter@amd.com    //
10012334Sgabeblack@google.com    virtual bool copyIn(FunctionalMemory *mem)
1011354SN/A    {
1026216Snate@binkert.org        mem->access(Read, addr, bufPtr, size);
1036658Snate@binkert.org        return true;	// no EFAULT detection for now
1042474SN/A    }
1052680Sktlim@umich.edu
1068229Snate@binkert.org    //
10711886Sbrandon.potter@amd.com    // copy data out of simulator space (write to target memory)
10810496Ssteve.reinhardt@amd.com    //
10911911SBrandon.Potter@amd.com    virtual bool copyOut(FunctionalMemory *mem)
1108229Snate@binkert.org    {
11111794Sbrandon.potter@amd.com        mem->access(Write, addr, bufPtr, size);
11211886Sbrandon.potter@amd.com        return true;	// no EFAULT detection for now
11310497Ssteve.reinhardt@amd.com    }
11411794Sbrandon.potter@amd.com
115360SN/A  protected:
116360SN/A    Addr addr;
117360SN/A    int size;
118360SN/A    uint8_t *bufPtr;
119360SN/A};
120360SN/A
121360SN/A
122360SN/Aclass BufferArg : public BaseBufferArg
123360SN/A{
124360SN/A  public:
125378SN/A    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
1261706SN/A    void *bufferPtr()	{ return bufPtr; }
12711851Sbrandon.potter@amd.com};
128378SN/A
129378SN/Atemplate <class T>
130378SN/Aclass TypedBufferArg : public BaseBufferArg
131378SN/A{
132378SN/A  public:
1331706SN/A    // user can optionally specify a specific number of bytes to
13411851Sbrandon.potter@amd.com    // allocate to deal with those structs that have variable-size
135360SN/A    // arrays at the end
13611760Sbrandon.potter@amd.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
13711760Sbrandon.potter@amd.com        : BaseBufferArg(_addr, _size)
13811851Sbrandon.potter@amd.com    { }
13911760Sbrandon.potter@amd.com
1406109Ssanchezd@stanford.edu    // type case
1411706SN/A    operator T*() { return (T *)bufPtr; }
14211851Sbrandon.potter@amd.com
143378SN/A    // dereference operators
1446109Ssanchezd@stanford.edu    T& operator*()	 { return *((T *)bufPtr); }
1456109Ssanchezd@stanford.edu    T* operator->()	 { return (T *)bufPtr; }
14611851Sbrandon.potter@amd.com    T& operator[](int i) { return ((T *)bufPtr)[i]; }
1476109Ssanchezd@stanford.edu};
14811886Sbrandon.potter@amd.com
14911886Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////
15011886Sbrandon.potter@amd.com//
15111886Sbrandon.potter@amd.com// The following emulation functions are generic enough that they
152378SN/A// don't need to be recompiled for different emulated OS's.  They are
1531706SN/A// defined in sim/syscall_emul.cc.
15411851Sbrandon.potter@amd.com//
155378SN/A//////////////////////////////////////////////////////////////////////
1565748SSteve.Reinhardt@amd.com
1575748SSteve.Reinhardt@amd.com
15811851Sbrandon.potter@amd.comint unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
159378SN/Aint ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
160378SN/A
1611706SN/Aint exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
16211851Sbrandon.potter@amd.comint getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
163378SN/Aint obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
16411886Sbrandon.potter@amd.comint closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1651706SN/Aint readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
16611851Sbrandon.potter@amd.comint writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
167378SN/Aint lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
168378SN/Aint munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
1691706SN/Aint gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
17011851Sbrandon.potter@amd.com
171378SN/A//////////////////////////////////////////////////////////////////////
172378SN/A//
1731706SN/A// The following emulation functions are generic, but need to be
17411851Sbrandon.potter@amd.com// templated to account for differences in types, constants, etc.
175378SN/A//
1764118Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////
1774118Sgblack@eecs.umich.edu
17811851Sbrandon.potter@amd.comtemplate <class OS>
1794118Sgblack@eecs.umich.eduint
180378SN/AioctlFunc(SyscallDesc *desc, int callnum, Process *process,
1811706SN/A          ExecContext *xc)
18211851Sbrandon.potter@amd.com{
183378SN/A    int fd = xc->getSyscallArg(0);
184378SN/A    unsigned req = xc->getSyscallArg(1);
1851706SN/A
18611851Sbrandon.potter@amd.com    // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
187360SN/A
1885513SMichael.Adler@intel.com    if (fd < 0 || process->sim_fd(fd) < 0) {
1895513SMichael.Adler@intel.com        // doesn't map to any simulator fd: not a valid target fd
19011851Sbrandon.potter@amd.com        return -EBADF;
1915513SMichael.Adler@intel.com    }
19210203SAli.Saidi@ARM.com
19310203SAli.Saidi@ARM.com    switch (req) {
19411851Sbrandon.potter@amd.com      case OS::TIOCISATTY:
19510203SAli.Saidi@ARM.com      case OS::TIOCGETP:
1965513SMichael.Adler@intel.com      case OS::TIOCSETP:
19711851Sbrandon.potter@amd.com      case OS::TIOCSETN:
1985513SMichael.Adler@intel.com      case OS::TIOCSETC:
199511SN/A      case OS::TIOCGETC:
20010633Smichaelupton@gmail.com        return -ENOTTY;
20111851Sbrandon.potter@amd.com
20210633Smichaelupton@gmail.com      default:
2031706SN/A        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req);
20411851Sbrandon.potter@amd.com    }
205511SN/A}
20612795Smattdsinclair@gmail.com
20712795Smattdsinclair@gmail.comstruct OpenFlagTransTable {
20812795Smattdsinclair@gmail.com    int tgtFlag;
20912795Smattdsinclair@gmail.com    int hostFlag;
21012796Smattdsinclair@gmail.com};
21112796Smattdsinclair@gmail.com
21212796Smattdsinclair@gmail.com
21312796Smattdsinclair@gmail.comtemplate <class OS>
2145513SMichael.Adler@intel.comint
2155513SMichael.Adler@intel.comopenFunc(SyscallDesc *desc, int callnum, Process *process,
21611851Sbrandon.potter@amd.com         ExecContext *xc)
2175513SMichael.Adler@intel.com{
21813031Sbrandon.potter@amd.com    std::string path;
21913031Sbrandon.potter@amd.com
22013031Sbrandon.potter@amd.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
22113031Sbrandon.potter@amd.com        return -EFAULT;
22213031Sbrandon.potter@amd.com
22313031Sbrandon.potter@amd.com    if (path == "/dev/sysdev0") {
22413031Sbrandon.potter@amd.com        // This is a memory-mapped high-resolution timer device on Alpha.
22513031Sbrandon.potter@amd.com        // We don't support it, so just punt.
22613031Sbrandon.potter@amd.com        DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
22713031Sbrandon.potter@amd.com        return -ENOENT;
22813031Sbrandon.potter@amd.com    }
22913031Sbrandon.potter@amd.com
230511SN/A    int tgtFlags = xc->getSyscallArg(1);
2311706SN/A    int mode = xc->getSyscallArg(2);
23211851Sbrandon.potter@amd.com    int hostFlags = 0;
2331706SN/A
2341706SN/A    // translate open flags
2351706SN/A    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
2361706SN/A        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
23711851Sbrandon.potter@amd.com            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
2381706SN/A            hostFlags |= OS::openFlagTable[i].hostFlag;
2391706SN/A        }
2401706SN/A    }
2411706SN/A
24211851Sbrandon.potter@amd.com    // any target flags left?
2431706SN/A    if (tgtFlags != 0)
244511SN/A        cerr << "Syscall: open: cannot decode flags: " <<  tgtFlags << endl;
2456703Svince@csl.cornell.edu
2466703Svince@csl.cornell.edu#ifdef __CYGWIN32__
24711851Sbrandon.potter@amd.com    hostFlags |= O_BINARY;
2486703Svince@csl.cornell.edu#endif
2496685Stjones1@inf.ed.ac.uk
2506685Stjones1@inf.ed.ac.uk    // open the file
25111851Sbrandon.potter@amd.com    int fd = open(path.c_str(), hostFlags, mode);
2526685Stjones1@inf.ed.ac.uk
2536685Stjones1@inf.ed.ac.uk    return (fd == -1) ? -errno : process->open_fd(fd);
2545513SMichael.Adler@intel.com}
2555513SMichael.Adler@intel.com
25611851Sbrandon.potter@amd.com
2575513SMichael.Adler@intel.comtemplate <class OS>
25811885Sbrandon.potter@amd.comint
25911885Sbrandon.potter@amd.comstatFunc(SyscallDesc *desc, int callnum, Process *process,
26011885Sbrandon.potter@amd.com         ExecContext *xc)
2615513SMichael.Adler@intel.com{
2621999SN/A    std::string path;
2631999SN/A
26411851Sbrandon.potter@amd.com    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
2651999SN/A        return -EFAULT;
26611885Sbrandon.potter@amd.com
26711885Sbrandon.potter@amd.com    struct stat hostBuf;
26811885Sbrandon.potter@amd.com    int result = stat(path.c_str(), &hostBuf);
2691999SN/A
2701999SN/A    if (result < 0)
2711999SN/A        return -errno;
27211851Sbrandon.potter@amd.com
2731999SN/A    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
2743079Sstever@eecs.umich.edu
2753079Sstever@eecs.umich.edu    return 0;
27611851Sbrandon.potter@amd.com}
2773079Sstever@eecs.umich.edu
27811908SBrandon.Potter@amd.com
27911908SBrandon.Potter@amd.comtemplate <class OS>
28011908SBrandon.Potter@amd.comint
28111908SBrandon.Potter@amd.comlstatFunc(SyscallDesc *desc, int callnum, Process *process,
28211875Sbrandon.potter@amd.com          ExecContext *xc)
2832093SN/A{
28411851Sbrandon.potter@amd.com    std::string path;
2852093SN/A
2862687Sksewell@umich.edu    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
2872687Sksewell@umich.edu        return -EFAULT;
28811851Sbrandon.potter@amd.com
2892687Sksewell@umich.edu    struct stat hostBuf;
2902238SN/A    int result = lstat(path.c_str(), &hostBuf);
2912238SN/A
29211851Sbrandon.potter@amd.com    if (result < 0)
2932238SN/A        return -errno;
29411908SBrandon.Potter@amd.com
29511908SBrandon.Potter@amd.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
29611908SBrandon.Potter@amd.com
29711908SBrandon.Potter@amd.com    return 0;
29811908SBrandon.Potter@amd.com}
29911908SBrandon.Potter@amd.com
30011908SBrandon.Potter@amd.comtemplate <class OS>
30111908SBrandon.Potter@amd.comint
3022238SN/AfstatFunc(SyscallDesc *desc, int callnum, Process *process,
3032238SN/A          ExecContext *xc)
30411851Sbrandon.potter@amd.com{
3052238SN/A    int fd = process->sim_fd(xc->getSyscallArg(0));
30613448Sciro.santilli@arm.com
30713031Sbrandon.potter@amd.com    // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
30813031Sbrandon.potter@amd.com
30913031Sbrandon.potter@amd.com    if (fd < 0)
31013448Sciro.santilli@arm.com        return -EBADF;
31113031Sbrandon.potter@amd.com
31213539Sjavier.setoain@arm.com    struct stat hostBuf;
31313539Sjavier.setoain@arm.com    int result = fstat(fd, &hostBuf);
31413539Sjavier.setoain@arm.com
31513539Sjavier.setoain@arm.com    if (result < 0)
31613539Sjavier.setoain@arm.com        return -errno;
31713539Sjavier.setoain@arm.com
31813031Sbrandon.potter@amd.com    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
3192238SN/A
32011851Sbrandon.potter@amd.com    return 0;
3212238SN/A}
3222238SN/A
3232238SN/A
32411851Sbrandon.potter@amd.com//
3252238SN/A// We don't really handle mmap().  If the target is mmaping an
3262238SN/A// anonymous region or /dev/zero, we can get away with doing basically
3272238SN/A// nothing (since memory is initialized to zero and the simulator
32811851Sbrandon.potter@amd.com// doesn't really check addresses anyway).  Always print a warning,
3292238SN/A// since this could be seriously broken if we're not mapping
3302238SN/A// /dev/zero.
3312238SN/A//
33211851Sbrandon.potter@amd.com// Someday we should explicitly check for /dev/zero in open, flag the
3332238SN/A// file descriptor, and fail (or implement!) a non-anonymous mmap to
3342238SN/A// anything else.
3352238SN/A//
33611851Sbrandon.potter@amd.comtemplate <class OS>
3372238SN/Aint
3389455Smitch.hayenga+gem5@gmail.commmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
3399455Smitch.hayenga+gem5@gmail.com{
34011851Sbrandon.potter@amd.com    Addr start = xc->getSyscallArg(0);
34110203SAli.Saidi@ARM.com    uint64_t length = xc->getSyscallArg(1);
34211851Sbrandon.potter@amd.com    // int prot = xc->getSyscallArg(2);
34311851Sbrandon.potter@amd.com    int flags = xc->getSyscallArg(3);
3449455Smitch.hayenga+gem5@gmail.com    int fd = p->sim_fd(xc->getSyscallArg(4));
3459112Smarc.orr@gmail.com    // int offset = xc->getSyscallArg(5);
34611906SBrandon.Potter@amd.com
34711906SBrandon.Potter@amd.com    if (start == 0) {
3489112Smarc.orr@gmail.com        // user didn't give an address... pick one from our "mmap region"
3499112Smarc.orr@gmail.com        start = p->mmap_base;
35011851Sbrandon.potter@amd.com        p->mmap_base += RoundUp<Addr>(length, VMPageSize);
3519112Smarc.orr@gmail.com    }
3529112Smarc.orr@gmail.com
35311911SBrandon.Potter@amd.com    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
3549112Smarc.orr@gmail.com        DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d.  "
35511911SBrandon.Potter@amd.com                "This will break if not /dev/zero.", fd);
35611911SBrandon.Potter@amd.com    }
35711911SBrandon.Potter@amd.com
35811911SBrandon.Potter@amd.com    return start;
3599112Smarc.orr@gmail.com}
36011911SBrandon.Potter@amd.com
36111911SBrandon.Potter@amd.com
36211911SBrandon.Potter@amd.comtemplate <class OS>
36311911SBrandon.Potter@amd.comint
3649238Slluc.alvarez@bsc.esgetrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
3659112Smarc.orr@gmail.com              ExecContext *xc)
36611911SBrandon.Potter@amd.com{
3679112Smarc.orr@gmail.com    unsigned resource = xc->getSyscallArg(0);
36811911SBrandon.Potter@amd.com    TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
36911911SBrandon.Potter@amd.com
37011911SBrandon.Potter@amd.com    switch (resource) {
37111911SBrandon.Potter@amd.com      case OS::RLIMIT_STACK:
37211911SBrandon.Potter@amd.com        // max stack size in bytes: make up a number (2MB for now)
3739112Smarc.orr@gmail.com        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
37411911SBrandon.Potter@amd.com        break;
37511911SBrandon.Potter@amd.com
37611911SBrandon.Potter@amd.com      default:
37711911SBrandon.Potter@amd.com        cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
37811911SBrandon.Potter@amd.com        abort();
37911911SBrandon.Potter@amd.com        break;
3809112Smarc.orr@gmail.com    }
3819112Smarc.orr@gmail.com
38211911SBrandon.Potter@amd.com    rlp.copyOut(xc->mem);
38311911SBrandon.Potter@amd.com    return 0;
3849112Smarc.orr@gmail.com}
38511911SBrandon.Potter@amd.com
38611911SBrandon.Potter@amd.com// 1M usecs in 1 sec, for readability
3879112Smarc.orr@gmail.comconst int one_million = 1000000;
3889112Smarc.orr@gmail.com
38911911SBrandon.Potter@amd.com// seconds since the epoch (1/1/1970)... about a billion, by my reckoning
39011911SBrandon.Potter@amd.comconst unsigned seconds_since_epoch = 1000000000;
3919112Smarc.orr@gmail.com
3929112Smarc.orr@gmail.com//
3932238SN/A// helper function: populate struct timeval with approximation of
3942238SN/A// current elapsed time
3952238SN/A//
3962238SN/Atemplate <class T1, class T2>
39711851Sbrandon.potter@amd.comvoid
3982238SN/AgetElapsedTime(T1 &sec, T2 &usec)
3992238SN/A{
4002238SN/A    int cycles_per_usec = ticksPerSecond / one_million;
40111851Sbrandon.potter@amd.com
4022238SN/A    int elapsed_usecs = curTick / cycles_per_usec;
4032238SN/A    sec = elapsed_usecs / one_million;
4042238SN/A    usec = elapsed_usecs % one_million;
40511851Sbrandon.potter@amd.com}
4062238SN/A
4072238SN/A
4082238SN/Atemplate <class OS>
40911851Sbrandon.potter@amd.comint
4102238SN/AgettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
4112238SN/A                 ExecContext *xc)
4121354SN/A{
4131354SN/A    TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
41410796Sbrandon.potter@amd.com
41510796Sbrandon.potter@amd.com    getElapsedTime(tp->tv_sec, tp->tv_usec);
4161354SN/A    tp->tv_sec += seconds_since_epoch;
4171354SN/A
4181354SN/A    tp.copyOut(xc->mem);
4191354SN/A
4201354SN/A    return 0;
4211354SN/A}
4221354SN/A
4231354SN/A
4241354SN/Atemplate <class OS>
4251354SN/Aint
42610796Sbrandon.potter@amd.comgetrusageFunc(SyscallDesc *desc, int callnum, Process *process,
4271354SN/A              ExecContext *xc)
42810796Sbrandon.potter@amd.com{
4291354SN/A    int who = xc->getSyscallArg(0);	// THREAD, SELF, or CHILDREN
4301354SN/A    TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
4311354SN/A
4321354SN/A    if (who != OS::RUSAGE_SELF) {
43310796Sbrandon.potter@amd.com        // don't really handle THREAD or CHILDREN, but just warn and
43410796Sbrandon.potter@amd.com        // plow ahead
43510796Sbrandon.potter@amd.com        DCOUT(SyscallWarnings)
43610796Sbrandon.potter@amd.com            << "Warning: getrusage() only supports RUSAGE_SELF."
43710796Sbrandon.potter@amd.com            << "  Parameter " << who << " ignored." << endl;
43810796Sbrandon.potter@amd.com    }
43910796Sbrandon.potter@amd.com
44010796Sbrandon.potter@amd.com    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
44110796Sbrandon.potter@amd.com    rup->ru_stime.tv_sec = 0;
44210796Sbrandon.potter@amd.com    rup->ru_stime.tv_usec = 0;
44310796Sbrandon.potter@amd.com    rup->ru_maxrss = 0;
444360SN/A    rup->ru_ixrss = 0;
445360SN/A    rup->ru_idrss = 0;
446360SN/A    rup->ru_isrss = 0;
447360SN/A    rup->ru_minflt = 0;
448360SN/A    rup->ru_majflt = 0;
449360SN/A    rup->ru_nswap = 0;
450360SN/A    rup->ru_inblock = 0;
45111759Sbrandon.potter@amd.com    rup->ru_oublock = 0;
4523113Sgblack@eecs.umich.edu    rup->ru_msgsnd = 0;
4533113Sgblack@eecs.umich.edu    rup->ru_msgrcv = 0;
4543113Sgblack@eecs.umich.edu    rup->ru_nsignals = 0;
4553113Sgblack@eecs.umich.edu    rup->ru_nvcsw = 0;
4563113Sgblack@eecs.umich.edu    rup->ru_nivcsw = 0;
4573113Sgblack@eecs.umich.edu
4583113Sgblack@eecs.umich.edu    rup.copyOut(xc->mem);
4593113Sgblack@eecs.umich.edu
4603113Sgblack@eecs.umich.edu    return 0;
4613113Sgblack@eecs.umich.edu}
4623113Sgblack@eecs.umich.edu
4633113Sgblack@eecs.umich.edu
4643113Sgblack@eecs.umich.edu
46512032Sandreas.sandberg@arm.com#endif // __SYSCALL_EMUL_HH__
4663113Sgblack@eecs.umich.edu