syscall_emul.cc revision 1999
17893SN/A/*
27893SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
37893SN/A * All rights reserved.
48825Snilay@cs.wisc.edu *
57893SN/A * Redistribution and use in source and binary forms, with or without
67893SN/A * modification, are permitted provided that the following conditions are
77893SN/A * met: redistributions of source code must retain the above copyright
87893SN/A * notice, this list of conditions and the following disclaimer;
97893SN/A * redistributions in binary form must reproduce the above copyright
107893SN/A * notice, this list of conditions and the following disclaimer in the
119885Sstever@gmail.com * documentation and/or other materials provided with the distribution;
128825Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its
139885Sstever@gmail.com * contributors may be used to endorse or promote products derived from
149885Sstever@gmail.com * this software without specific prior written permission.
158825Snilay@cs.wisc.edu *
168825Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178825Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189449SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199449SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
208464SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218721SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228825Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
238825Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247935SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257935SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267935SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277935SN/A */
287935SN/A
297935SN/A#include <unistd.h>
307935SN/A
318983Snate@binkert.org#include <string>
327893SN/A#include <iostream>
339885Sstever@gmail.com
349885Sstever@gmail.com#include "sim/syscall_emul.hh"
359885Sstever@gmail.com#include "base/trace.hh"
369885Sstever@gmail.com#include "cpu/exec_context.hh"
379885Sstever@gmail.com#include "cpu/base.hh"
387893SN/A#include "sim/process.hh"
397893SN/A
409885Sstever@gmail.com#include "sim/sim_events.hh"
417893SN/A
427893SN/Ausing namespace std;
438241SN/A
448241SN/Avoid
457893SN/ASyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
467893SN/A{
477893SN/A    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
487893SN/A             xc->cpu->name(), name);
499481Snilay@cs.wisc.edu
507893SN/A    SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
517893SN/A
529885Sstever@gmail.com    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
537893SN/A             xc->cpu->name(), name, retval.value());
547893SN/A
557893SN/A    if (!(flags & SyscallDesc::SuppressReturnValue))
567893SN/A        xc->setSyscallReturn(retval);
577893SN/A}
587893SN/A
597893SN/A
607893SN/ASyscallReturn
617893SN/AunimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
627893SN/A                  ExecContext *xc)
637893SN/A{
648825Snilay@cs.wisc.edu    fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
657893SN/A}
667893SN/A
677893SN/A
687893SN/ASyscallReturn
697893SN/AignoreFunc(SyscallDesc *desc, int callnum, Process *process,
707893SN/A           ExecContext *xc)
717893SN/A{
727893SN/A    warn("ignoring syscall %s(%d, %d, ...)", desc->name,
737893SN/A         xc->getSyscallArg(0), xc->getSyscallArg(1));
747893SN/A
757893SN/A    return 0;
767893SN/A}
777893SN/A
788825Snilay@cs.wisc.edu
799449SAli.Saidi@ARM.comSyscallReturn
807893SN/AexitFunc(SyscallDesc *desc, int callnum, Process *process,
817893SN/A         ExecContext *xc)
827893SN/A{
837893SN/A    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
847893SN/A
857893SN/A    return 1;
867893SN/A}
878728SN/A
887893SN/A
897893SN/ASyscallReturn
907893SN/AgetpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
917893SN/A{
927893SN/A    return VMPageSize;
937893SN/A}
948825Snilay@cs.wisc.edu
957893SN/A
967893SN/ASyscallReturn
977893SN/AobreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
987893SN/A{
997893SN/A    // change brk addr to first arg
1007893SN/A    Addr new_brk = xc->getSyscallArg(0);
1019885Sstever@gmail.com    if (new_brk != 0)
1027893SN/A    {
1037893SN/A        p->brk_point = xc->getSyscallArg(0);
1047893SN/A    }
1057893SN/A    DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
1067893SN/A    return p->brk_point;
1077893SN/A}
1087893SN/A
1097893SN/A
1107893SN/ASyscallReturn
1117893SN/AcloseFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1128521SN/A{
1139449SAli.Saidi@ARM.com    int target_fd = xc->getSyscallArg(0);
1147893SN/A    int status = close(p->sim_fd(target_fd));
1157893SN/A    if (status >= 0)
1167893SN/A        p->free_fd(target_fd);
1177893SN/A    return status;
1187893SN/A}
1197893SN/A
1207893SN/A
1217893SN/ASyscallReturn
1227893SN/AreadFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1239885Sstever@gmail.com{
1249885Sstever@gmail.com    int fd = p->sim_fd(xc->getSyscallArg(0));
1259885Sstever@gmail.com    int nbytes = xc->getSyscallArg(2);
1269885Sstever@gmail.com    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
1279885Sstever@gmail.com
1289481Snilay@cs.wisc.edu    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
1299481Snilay@cs.wisc.edu
1309481Snilay@cs.wisc.edu    if (bytes_read != -1)
1319481Snilay@cs.wisc.edu        bufArg.copyOut(xc->mem);
1329481Snilay@cs.wisc.edu
1339481Snilay@cs.wisc.edu    return bytes_read;
1349481Snilay@cs.wisc.edu}
1359481Snilay@cs.wisc.edu
1369481Snilay@cs.wisc.eduSyscallReturn
1379481Snilay@cs.wisc.eduwriteFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1389481Snilay@cs.wisc.edu{
1399481Snilay@cs.wisc.edu    int fd = p->sim_fd(xc->getSyscallArg(0));
1409481Snilay@cs.wisc.edu    int nbytes = xc->getSyscallArg(2);
1419481Snilay@cs.wisc.edu    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
1429481Snilay@cs.wisc.edu
1439481Snilay@cs.wisc.edu    bufArg.copyIn(xc->mem);
1447893SN/A
1457893SN/A    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
1469885Sstever@gmail.com
1478983Snate@binkert.org    fsync(fd);
1487893SN/A
1499885Sstever@gmail.com    return bytes_written;
1507893SN/A}
1519348SAli.Saidi@ARM.com
1528200SN/A
1537893SN/ASyscallReturn
1549348SAli.Saidi@ARM.comlseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1557893SN/A{
1568835SAli.Saidi@ARM.com    int fd = p->sim_fd(xc->getSyscallArg(0));
1579348SAli.Saidi@ARM.com    uint64_t offs = xc->getSyscallArg(1);
1587893SN/A    int whence = xc->getSyscallArg(2);
1598835SAli.Saidi@ARM.com
1609885Sstever@gmail.com    off_t result = lseek(fd, offs, whence);
1617893SN/A
1627893SN/A    return (result == (off_t)-1) ? -errno : result;
1637893SN/A}
1647893SN/A
1658983Snate@binkert.org
1667893SN/ASyscallReturn
1679885Sstever@gmail.communmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1689885Sstever@gmail.com{
1699885Sstever@gmail.com    // given that we don't really implement mmap, munmap is really easy
1709885Sstever@gmail.com    return 0;
1719885Sstever@gmail.com}
1729885Sstever@gmail.com
1739885Sstever@gmail.com
1749885Sstever@gmail.comconst char *hostname = "m5.eecs.umich.edu";
1757893SN/A
1767893SN/ASyscallReturn
1778825Snilay@cs.wisc.edugethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1787893SN/A{
1798825Snilay@cs.wisc.edu    int name_len = xc->getSyscallArg(1);
1808825Snilay@cs.wisc.edu    BufferArg name(xc->getSyscallArg(0), name_len);
1818825Snilay@cs.wisc.edu
1828825Snilay@cs.wisc.edu    strncpy((char *)name.bufferPtr(), hostname, name_len);
1839885Sstever@gmail.com
1849885Sstever@gmail.com    name.copyOut(xc->mem);
1858825Snilay@cs.wisc.edu
1868983Snate@binkert.org    return 0;
1877893SN/A}
1887893SN/A
1897893SN/ASyscallReturn
1907893SN/AunlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
1917893SN/A{
1927893SN/A    string path;
1937893SN/A
1947893SN/A    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
1957893SN/A        return (TheISA::IntReg)-EFAULT;
1967893SN/A
1977893SN/A    int result = unlink(path.c_str());
1987893SN/A    return (result == -1) ? -errno : result;
1997893SN/A}
2007893SN/A
2017893SN/ASyscallReturn
2027893SN/ArenameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
2037893SN/A{
2047893SN/A    string old_name;
2057893SN/A
2067893SN/A    if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
2077893SN/A        return -EFAULT;
2087893SN/A
2097893SN/A    string new_name;
2107893SN/A
2117893SN/A    if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
2127893SN/A        return -EFAULT;
2137893SN/A
2147893SN/A    int64_t result = rename(old_name.c_str(), new_name.c_str());
2157893SN/A    return (result == -1) ? -errno : result;
2167893SN/A}
2177893SN/A
2187893SN/ASyscallReturn
2197893SN/AtruncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
2207893SN/A{
2217893SN/A    string path;
2227893SN/A
2237893SN/A    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
2247893SN/A        return -EFAULT;
2257893SN/A
2267893SN/A    off_t length = xc->getSyscallArg(1);
2277893SN/A
2287893SN/A    int result = truncate(path.c_str(), length);
2297893SN/A    return (result == -1) ? -errno : result;
2307893SN/A}
2317893SN/A
2327893SN/ASyscallReturn
2337893SN/AftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
2347893SN/A{
2357893SN/A    int fd = process->sim_fd(xc->getSyscallArg(0));
2367893SN/A
2377893SN/A    if (fd < 0)
2387893SN/A        return -EBADF;
2397893SN/A
2407893SN/A    off_t length = xc->getSyscallArg(1);
2417893SN/A
2427893SN/A    int result = ftruncate(fd, length);
2437893SN/A    return (result == -1) ? -errno : result;
2447893SN/A}
2457893SN/A
2467893SN/ASyscallReturn
2477893SN/AchownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
2487893SN/A{
2497893SN/A    string path;
2507893SN/A
2517893SN/A    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
2527893SN/A        return -EFAULT;
2537893SN/A
2547893SN/A    /* XXX endianess */
2557893SN/A    uint32_t owner = xc->getSyscallArg(1);
2567893SN/A    uid_t hostOwner = owner;
2577893SN/A    uint32_t group = xc->getSyscallArg(2);
2587893SN/A    gid_t hostGroup = group;
2597893SN/A
2607893SN/A    int result = chown(path.c_str(), hostOwner, hostGroup);
2617893SN/A    return (result == -1) ? -errno : result;
2627893SN/A}
2637893SN/A
2647893SN/ASyscallReturn
2657893SN/AfchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
2667893SN/A{
2677893SN/A    int fd = process->sim_fd(xc->getSyscallArg(0));
2687893SN/A
2697893SN/A    if (fd < 0)
2707893SN/A        return -EBADF;
2717893SN/A
2727893SN/A    /* XXX endianess */
2737893SN/A    uint32_t owner = xc->getSyscallArg(1);
2747893SN/A    uid_t hostOwner = owner;
2757893SN/A    uint32_t group = xc->getSyscallArg(2);
2767893SN/A    gid_t hostGroup = group;
2777893SN/A
2787893SN/A    int result = fchown(fd, hostOwner, hostGroup);
2797893SN/A    return (result == -1) ? -errno : result;
2807893SN/A}
2817893SN/A