Merge zizzer:/bk/m5 into isabel.reinhardt.house:/z/stever/bk/m5
[gem5.git] / sim / syscall_emul.cc
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
42 using namespace std;
43
44 void
45 SyscallDesc::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 int
61 unimplementedFunc(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
73 int
74 ignoreFunc(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 0;
83 }
84
85
86 int
87 exitFunc(SyscallDesc *desc, int callnum, Process *process,
88 ExecContext *xc)
89 {
90 new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
91
92 return 1;
93 }
94
95
96 int
97 getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
98 {
99 return VMPageSize;
100 }
101
102
103 int
104 obreakFunc(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 p->brk_point = xc->getSyscallArg(0);
110 return p->brk_point;
111 }
112
113
114 int
115 closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
116 {
117 int fd = p->sim_fd(xc->getSyscallArg(0));
118 return close(fd);
119 }
120
121
122 int
123 readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
124 {
125 int fd = p->sim_fd(xc->getSyscallArg(0));
126 int nbytes = xc->getSyscallArg(2);
127 BufferArg bufArg(xc->getSyscallArg(1), nbytes);
128
129 int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
130
131 if (bytes_read != -1)
132 bufArg.copyOut(xc->mem);
133
134 return bytes_read;
135 }
136
137 int
138 writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
139 {
140 int fd = p->sim_fd(xc->getSyscallArg(0));
141 int nbytes = xc->getSyscallArg(2);
142 BufferArg bufArg(xc->getSyscallArg(1), nbytes);
143
144 bufArg.copyIn(xc->mem);
145
146 int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
147
148 fsync(fd);
149
150 return bytes_written;
151 }
152
153
154 int
155 lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
156 {
157 int fd = p->sim_fd(xc->getSyscallArg(0));
158 uint64_t offs = xc->getSyscallArg(1);
159 int whence = xc->getSyscallArg(2);
160
161 off_t result = lseek(fd, offs, whence);
162
163 return (result == (off_t)-1) ? -errno : result;
164 }
165
166
167 int
168 munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
169 {
170 // given that we don't really implement mmap, munmap is really easy
171 return 0;
172 }
173
174
175 const char *hostname = "m5.eecs.umich.edu";
176
177 int
178 gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
179 {
180 int name_len = xc->getSyscallArg(1);
181 BufferArg name(xc->getSyscallArg(0), name_len);
182
183 strncpy((char *)name.bufferPtr(), hostname, name_len);
184
185 name.copyOut(xc->mem);
186
187 return 0;
188 }
189
190 int
191 unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
192 {
193 std::string path;
194
195 if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
196 return -EFAULT;
197
198 int result = unlink(path.c_str());
199 return (result == -1) ? -errno : result;
200 }
201
202 int
203 renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
204 {
205 std::string old_name;
206
207 if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
208 return -EFAULT;
209
210 std::string new_name;
211
212 if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
213 return -EFAULT;
214
215 int result = rename(old_name.c_str(),new_name.c_str());
216 return (result == -1) ? -errno : result;
217 }
218