syscall_emul.cc revision 1450
1/*
2 * Copyright (c) 2003-2004 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    SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
51
52    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
53             xc->cpu->name(), name, retval.value());
54
55    if (!(flags & SyscallDesc::SuppressReturnValue))
56        xc->setSyscallReturn(retval);
57}
58
59
60SyscallReturn
61unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
62                  ExecContext *xc)
63{
64    cerr << "Error: syscall " << desc->name
65         << " (#" << callnum << ") unimplemented.";
66    cerr << "  Args: " << xc->getSyscallArg(0) << ", " << xc->getSyscallArg(1)
67         << ", ..." << endl;
68
69    abort();
70}
71
72
73SyscallReturn
74ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
75           ExecContext *xc)
76{
77    DCOUT(SyscallWarnings) << "Warning: ignoring syscall " << desc->name
78                           << "(" << xc->getSyscallArg(0)
79                           << ", " << xc->getSyscallArg(1)
80                           << ", ...)" << endl;
81
82    return SyscallReturn(0);
83}
84
85
86SyscallReturn
87exitFunc(SyscallDesc *desc, int callnum, Process *process,
88         ExecContext *xc)
89{
90    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
91
92    return SyscallReturn(1);
93}
94
95
96SyscallReturn
97getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
98{
99    return SyscallReturn(VMPageSize);
100}
101
102
103SyscallReturn
104obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
105{
106    // change brk addr to first arg
107    Addr new_brk = xc->getSyscallArg(0);
108    if (new_brk != 0)
109    {
110        p->brk_point = xc->getSyscallArg(0);
111    }
112    return SyscallReturn(p->brk_point);
113}
114
115
116SyscallReturn
117closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
118{
119    int fd = p->sim_fd(xc->getSyscallArg(0));
120    return SyscallReturn(close(fd));
121}
122
123
124SyscallReturn
125readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
126{
127    int fd = p->sim_fd(xc->getSyscallArg(0));
128    int nbytes = xc->getSyscallArg(2);
129    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
130
131    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
132
133    if (bytes_read != -1)
134        bufArg.copyOut(xc->mem);
135
136    return SyscallReturn(bytes_read);
137}
138
139SyscallReturn
140writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
141{
142    int fd = p->sim_fd(xc->getSyscallArg(0));
143    int nbytes = xc->getSyscallArg(2);
144    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
145
146    bufArg.copyIn(xc->mem);
147
148    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
149
150    fsync(fd);
151
152    return SyscallReturn(bytes_written);
153}
154
155
156SyscallReturn
157lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
158{
159    int fd = p->sim_fd(xc->getSyscallArg(0));
160    uint64_t offs = xc->getSyscallArg(1);
161    int whence = xc->getSyscallArg(2);
162
163    off_t result = lseek(fd, offs, whence);
164
165    return (result == (off_t)-1) ? SyscallReturn(-errno) :
166                                   SyscallReturn(result);
167}
168
169
170SyscallReturn
171munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
172{
173    // given that we don't really implement mmap, munmap is really easy
174    return SyscallReturn(0);
175}
176
177
178const char *hostname = "m5.eecs.umich.edu";
179
180SyscallReturn
181gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
182{
183    int name_len = xc->getSyscallArg(1);
184    BufferArg name(xc->getSyscallArg(0), name_len);
185
186    strncpy((char *)name.bufferPtr(), hostname, name_len);
187
188    name.copyOut(xc->mem);
189
190    return SyscallReturn(0);
191}
192
193SyscallReturn
194unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
195{
196    std::string path;
197
198    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
199        return (TheISA::IntReg)-EFAULT;
200
201    int result = unlink(path.c_str());
202    return (result == -1) ? SyscallReturn(-errno) : SyscallReturn(result);
203}
204
205SyscallReturn
206renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
207{
208    std::string old_name;
209
210    if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
211        return SyscallReturn(-EFAULT);
212
213    std::string new_name;
214
215    if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
216        return SyscallReturn(-EFAULT);
217
218    int64_t result = rename(old_name.c_str(),new_name.c_str());
219    return (result == -1) ? SyscallReturn(-errno) : SyscallReturn(result);
220}
221
222