syscall_emul.cc revision 360
1/*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <unistd.h>
30
31#include <string>
32#include <iostream>
33
34#include "sim/syscall_emul.hh"
35#include "base/trace.hh"
36#include "cpu/exec_context.hh"
37#include "cpu/base_cpu.hh"
38#include "sim/process.hh"
39
40#include "sim/sim_events.hh"
41
42using namespace std;
43
44void
45SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
46{
47    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
48             xc->cpu->name(), name);
49
50    int retval = (*funcPtr)(this, callnum, process, xc);
51
52    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
53             xc->cpu->name(), name, retval);
54
55    if (!((flags & SyscallDesc::SuppressReturnValue) && retval == 0))
56        xc->setSyscallReturn(retval);
57}
58
59
60//
61// Handler for unimplemented syscalls that we haven't thought about.
62//
63int
64unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
65                  ExecContext *xc)
66{
67    cerr << "Error: syscall " << desc->name
68         << " (#" << callnum << ") unimplemented.";
69    cerr << "  Args: " << xc->getSyscallArg(0) << ", " << xc->getSyscallArg(1)
70         << ", ..." << endl;
71
72    abort();
73}
74
75
76//
77// Handler for unimplemented syscalls that we never intend to
78// implement (signal handling, etc.) and should not affect the correct
79// behavior of the program.  Print a warning only if the appropriate
80// trace flag is enabled.  Return success to the target program.
81//
82int
83ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
84           ExecContext *xc)
85{
86    DCOUT(SyscallWarnings) << "Warning: ignoring syscall " << desc->name
87                           << "(" << xc->getSyscallArg(0)
88                           << ", " << xc->getSyscallArg(1)
89                           << ", ...)" << endl;
90
91    return 0;
92}
93
94
95int
96exitFunc(SyscallDesc *desc, int callnum, Process *process,
97         ExecContext *xc)
98{
99    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
100
101    return 1;
102}
103
104
105int
106getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
107{
108    return VMPageSize;
109}
110
111
112int
113obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
114{
115    // change brk addr to first arg
116    p->brk_point = xc->getSyscallArg(0);
117    return p->brk_point;
118}
119
120
121int
122closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
123{
124    int fd = p->sim_fd(xc->getSyscallArg(0));
125    return close(fd);
126}
127
128
129int
130readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
131{
132    int fd = p->sim_fd(xc->getSyscallArg(0));
133    int nbytes = xc->getSyscallArg(2);
134    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
135
136    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
137
138    if (bytes_read != -1)
139        bufArg.copyOut(xc->mem);
140
141    return bytes_read;
142}
143
144int
145writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
146{
147    int fd = p->sim_fd(xc->getSyscallArg(0));
148    int nbytes = xc->getSyscallArg(2);
149    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
150
151    bufArg.copyIn(xc->mem);
152
153    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
154
155    fsync(fd);
156
157    return bytes_written;
158}
159
160
161int
162lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
163{
164    int fd = p->sim_fd(xc->getSyscallArg(0));
165    uint64_t offs = xc->getSyscallArg(1);
166    int whence = xc->getSyscallArg(2);
167
168    off_t result = lseek(fd, offs, whence);
169
170    return (result == (off_t)-1) ? -errno : result;
171}
172
173
174int
175munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
176{
177    // given that we don't really implement mmap, munmap is really easy
178    return 0;
179}
180
181
182const char *hostname = "m5.eecs.umich.edu";
183
184int
185gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
186{
187    int name_len = xc->getSyscallArg(1);
188    BufferArg name(xc->getSyscallArg(0), name_len);
189
190    strncpy((char *)name.bufferPtr(), hostname, name_len);
191
192    name.copyOut(xc->mem);
193
194    return 0;
195}
196
197
198