arch: Switch SyscallDescABI in for SyscallDesc.
[gem5.git] / src / arch / mips / linux / process.cc
1 /*
2 * Copyright (c) 2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Gabe Black
30 * Korey Sewell
31 */
32
33 #include "arch/mips/linux/process.hh"
34
35 #include "arch/mips/isa_traits.hh"
36 #include "arch/mips/linux/linux.hh"
37 #include "base/loader/object_file.hh"
38 #include "base/trace.hh"
39 #include "cpu/thread_context.hh"
40 #include "debug/SyscallVerbose.hh"
41 #include "kern/linux/linux.hh"
42 #include "sim/eventq.hh"
43 #include "sim/process.hh"
44 #include "sim/syscall_desc.hh"
45 #include "sim/syscall_emul.hh"
46 #include "sim/system.hh"
47
48 using namespace std;
49 using namespace MipsISA;
50
51 namespace
52 {
53
54 class MipsLinuxObjectFileLoader : public Process::Loader
55 {
56 public:
57 Process *
58 load(ProcessParams *params, ObjectFile *obj_file) override
59 {
60 if (obj_file->getArch() != ObjectFile::Mips)
61 return nullptr;
62
63 auto opsys = obj_file->getOpSys();
64
65 if (opsys == ObjectFile::UnknownOpSys) {
66 warn("Unknown operating system; assuming Linux.");
67 opsys = ObjectFile::Linux;
68 }
69
70 if (opsys != ObjectFile::Linux)
71 return nullptr;
72
73 return new MipsLinuxProcess(params, obj_file);
74 }
75 };
76
77 MipsLinuxObjectFileLoader loader;
78
79 } // anonymous namespace
80
81 /// Target uname() handler.
82 static SyscallReturn
83 unameFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
84 {
85 int index = 0;
86 auto process = tc->getProcessPtr();
87 TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
88
89 strcpy(name->sysname, "Linux");
90 strcpy(name->nodename,"sim.gem5.org");
91 strcpy(name->release, process->release.c_str());
92 strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
93 strcpy(name->machine, "mips");
94
95 name.copyOut(tc->getVirtProxy());
96 return 0;
97 }
98
99 /// Target sys_getsysyinfo() handler. Even though this call is
100 /// borrowed from Tru64, the subcases that get used appear to be
101 /// different in practice from those used by Tru64 processes.
102 static SyscallReturn
103 sys_getsysinfoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
104 {
105 int index = 0;
106 auto process = tc->getProcessPtr();
107 unsigned op = process->getSyscallArg(tc, index);
108 unsigned bufPtr = process->getSyscallArg(tc, index);
109 // unsigned nbytes = process->getSyscallArg(tc, index);
110
111 switch (op) {
112 case 45:
113 {
114 // GSI_IEEE_FP_CONTROL
115 TypedBufferArg<uint64_t> fpcr(bufPtr);
116 // I don't think this exactly matches the HW FPCR
117 *fpcr = 0;
118 fpcr.copyOut(tc->getVirtProxy());
119 return 0;
120 }
121 default:
122 cerr << "sys_getsysinfo: unknown op " << op << endl;
123 abort();
124 break;
125 }
126
127 return 1;
128 }
129
130 /// Target sys_setsysinfo() handler.
131 static SyscallReturn
132 sys_setsysinfoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
133 {
134 int index = 0;
135 auto process = tc->getProcessPtr();
136 unsigned op = process->getSyscallArg(tc, index);
137 Addr bufPtr = process->getSyscallArg(tc, index);
138 // unsigned nbytes = process->getSyscallArg(tc, index);
139
140 switch (op) {
141
142 case 14:
143 {
144 // SSI_IEEE_FP_CONTROL
145 TypedBufferArg<uint64_t> fpcr(bufPtr);
146 // I don't think this exactly matches the HW FPCR
147 fpcr.copyIn(tc->getVirtProxy());
148 DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
149 " setting FPCR to 0x%x\n", letoh(*(uint64_t*)fpcr));
150 return 0;
151 }
152 default:
153 cerr << "sys_setsysinfo: unknown op " << op << endl;
154 abort();
155 break;
156 }
157
158 return 1;
159 }
160
161 static SyscallReturn
162 setThreadAreaFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
163 {
164 int index = 0;
165 auto process = tc->getProcessPtr();
166 Addr addr = process->getSyscallArg(tc, index);
167 tc->setMiscRegNoEffect(MISCREG_TP_VALUE, addr);
168 return 0;
169 }
170
171 SyscallDescABI<DefaultSyscallABI> MipsLinuxProcess::syscallDescs[] = {
172 /* 0 */ { "syscall" },
173 /* 1 */ { "exit", exitFunc },
174 /* 2 */ { "fork" },
175 /* 3 */ { "read", readFunc<MipsLinux> },
176 /* 4 */ { "write", writeFunc<MipsLinux> },
177 /* 5 */ { "open", openFunc<MipsLinux> },
178 /* 6 */ { "close", closeFunc },
179 /* 7 */ { "waitpid" },
180 /* 8 */ { "creat" },
181 /* 9 */ { "link" },
182 /* 10 */ { "unlink", unlinkFunc },
183 /* 11 */ { "execve" },
184 /* 12 */ { "chdir" },
185 /* 13 */ { "time" },
186 /* 14 */ { "mknod" },
187 /* 15 */ { "chmod", chmodFunc<MipsLinux> },
188 /* 16 */ { "lchown", chownFunc },
189 /* 17 */ { "break", brkFunc },
190 /* 18 */ { "unused#18" },
191 /* 19 */ { "lseek", lseekFunc },
192 /* 20 */ { "getpid", getpidFunc },
193 /* 21 */ { "mount" },
194 /* 22 */ { "umount" },
195 /* 23 */ { "setuid", setuidFunc },
196 /* 24 */ { "getuid", getuidFunc },
197 /* 25 */ { "stime" },
198 /* 26 */ { "ptrace" },
199 /* 27 */ { "alarm" },
200 /* 28 */ { "unused#28" },
201 /* 29 */ { "pause" },
202 /* 30 */ { "utime" },
203 /* 31 */ { "stty" },
204 /* 32 */ { "gtty" },
205 /* 33 */ { "access" },
206 /* 34 */ { "nice" },
207 /* 35 */ { "ftime" },
208 /* 36 */ { "sync" },
209 /* 37 */ { "kill" },
210 /* 38 */ { "rename" },
211 /* 39 */ { "mkdir", mkdirFunc },
212 /* 40 */ { "rmdir" },
213 /* 41 */ { "dup" },
214 /* 42 */ { "pipe", pipePseudoFunc },
215 /* 43 */ { "times" },
216 /* 44 */ { "prof" },
217 /* 45 */ { "brk", brkFunc },
218 /* 46 */ { "setgid" },
219 /* 47 */ { "getgid", getgidFunc },
220 /* 48 */ { "signal", ignoreFunc },
221 /* 49 */ { "geteuid", geteuidFunc },
222 /* 50 */ { "getegid", getegidFunc },
223 /* 51 */ { "acct" },
224 /* 52 */ { "umount2" },
225 /* 53 */ { "lock" },
226 /* 54 */ { "ioctl", ioctlFunc<MipsLinux> },
227 /* 55 */ { "fcntl", fcntlFunc },
228 /* 56 */ { "mpx" },
229 /* 57 */ { "setpgid" },
230 /* 58 */ { "ulimit" },
231 /* 59 */ { "unused#59" },
232 /* 60 */ { "umask", umaskFunc },
233 /* 61 */ { "chroot" },
234 /* 62 */ { "ustat" },
235 /* 63 */ { "dup2" },
236 /* 64 */ { "getppid", getpagesizeFunc },
237 /* 65 */ { "getpgrp" },
238 /* 66 */ { "setsid" },
239 /* 67 */ { "sigaction" },
240 /* 68 */ { "sgetmask" },
241 /* 69 */ { "ssetmask" },
242 /* 70 */ { "setreuid" },
243 /* 71 */ { "setregid" },
244 /* 72 */ { "sigsuspend" },
245 /* 73 */ { "sigpending" },
246 /* 74 */ { "sethostname", ignoreFunc },
247 /* 75 */ { "setrlimit" },
248 /* 76 */ { "getrlimit" },
249 /* 77 */ { "getrusage", getrusageFunc<MipsLinux> },
250 /* 78 */ { "gettimeofday" },
251 /* 79 */ { "settimeofday" },
252 /* 80 */ { "getgroups" },
253 /* 81 */ { "setgroups" },
254 /* 82 */ { "reserved#82" },
255 /* 83 */ { "symlink" },
256 /* 84 */ { "unused#84" },
257 /* 85 */ { "readlink", readlinkFunc },
258 /* 86 */ { "uselib" },
259 /* 87 */ { "swapon", gethostnameFunc },
260 /* 88 */ { "reboot" },
261 /* 89 */ { "readdir" },
262 /* 90 */ { "mmap", mmapFunc<MipsLinux> },
263 /* 91 */ { "munmap",munmapFunc },
264 /* 92 */ { "truncate", truncateFunc },
265 /* 93 */ { "ftruncate", ftruncateFunc },
266 /* 94 */ { "fchmod", fchmodFunc<MipsLinux> },
267 /* 95 */ { "fchown", fchownFunc },
268 /* 96 */ { "getpriority" },
269 /* 97 */ { "setpriority" },
270 /* 98 */ { "profil" },
271 /* 99 */ { "statfs" },
272 /* 100 */ { "fstatfs" },
273 /* 101 */ { "ioperm" },
274 /* 102 */ { "socketcall" },
275 /* 103 */ { "syslog" },
276 /* 104 */ { "setitimer" },
277 /* 105 */ { "getitimer" },
278 /* 106 */ { "stat", statFunc<MipsLinux> },
279 /* 107 */ { "lstat" },
280 /* 108 */ { "fstat", fstatFunc<MipsLinux> },
281 /* 109 */ { "unused#109" },
282 /* 110 */ { "iopl" },
283 /* 111 */ { "vhangup" },
284 /* 112 */ { "idle", ignoreFunc },
285 /* 113 */ { "vm86" },
286 /* 114 */ { "wait4" },
287 /* 115 */ { "swapoff" },
288 /* 116 */ { "sysinfo", sysinfoFunc<MipsLinux> },
289 /* 117 */ { "ipc" },
290 /* 118 */ { "fsync" },
291 /* 119 */ { "sigreturn" },
292 /* 120 */ { "clone" },
293 /* 121 */ { "setdomainname" },
294 /* 122 */ { "uname", unameFunc },
295 /* 123 */ { "modify_ldt" },
296 /* 124 */ { "adjtimex" },
297 /* 125 */ { "mprotect", ignoreFunc },
298 /* 126 */ { "sigprocmask" },
299 /* 127 */ { "create_module" },
300 /* 128 */ { "init_module" },
301 /* 129 */ { "delete_module" },
302 /* 130 */ { "get_kernel_syms" },
303 /* 131 */ { "quotactl" },
304 /* 132 */ { "getpgid" },
305 /* 133 */ { "fchdir" },
306 /* 134 */ { "bdflush" },
307 /* 135 */ { "sysfs" },
308 /* 136 */ { "personality" },
309 /* 137 */ { "afs_syscall" },
310 /* 138 */ { "setfsuid" },
311 /* 139 */ { "setfsgid" },
312 /* 140 */ { "llseek" },
313 /* 141 */ { "getdents" },
314 /* 142 */ { "newselect" },
315 /* 143 */ { "flock" },
316 /* 144 */ { "msync" },
317 /* 145 */ { "readv" },
318 /* 146 */ { "writev", writevFunc<MipsLinux> },
319 /* 147 */ { "cacheflush" },
320 /* 148 */ { "cachectl" },
321 /* 149 */ { "sysmips" },
322 /* 150 */ { "unused#150" },
323 /* 151 */ { "getsid" },
324 /* 152 */ { "fdatasync" },
325 /* 153 */ { "sysctl", ignoreFunc },
326 /* 154 */ { "mlock" },
327 /* 155 */ { "munlock" },
328 /* 156 */ { "mlockall" },
329 /* 157 */ { "munlockall" },
330 /* 158 */ { "sched_setparam" },
331 /* 159 */ { "sched_getparam" },
332 /* 160 */ { "sched_setscheduler" },
333 /* 161 */ { "sched_getscheduler" },
334 /* 162 */ { "sched_yield" },
335 /* 163 */ { "sched_get_prioritymax" },
336 /* 164 */ { "sched_get_priority_min" },
337 /* 165 */ { "sched_rr_get_interval" },
338 /* 166 */ { "nanosleep" },
339 /* 167 */ { "mremap", mremapFunc<MipsLinux> },
340 /* 168 */ { "accept" },
341 /* 169 */ { "bind" },
342 /* 170 */ { "connect" },
343 /* 171 */ { "getpeername" },
344 /* 172 */ { "getsockname" },
345 /* 173 */ { "getsockopt" },
346 /* 174 */ { "listen" },
347 /* 175 */ { "recv" },
348 /* 176 */ { "recvmsg" },
349 /* 177 */ { "send" },
350 /* 178 */ { "sendmsg", ignoreFunc },
351 /* 179 */ { "sendto" },
352 /* 180 */ { "setsockopt" },
353 /* 181 */ { "shutdown" },
354 /* 182 */ { "unknown #182" },
355 /* 183 */ { "socket", ignoreFunc },
356 /* 184 */ { "socketpair" },
357 /* 185 */ { "setresuid" },
358 /* 186 */ { "getresuid" },
359 /* 187 */ { "query_module" },
360 /* 188 */ { "poll" },
361 /* 189 */ { "nfsservctl" },
362 /* 190 */ { "setresgid" },
363 /* 191 */ { "getresgid" },
364 /* 192 */ { "prctl" },
365 /* 193 */ { "rt_sigreturn" },
366 /* 194 */ { "rt_sigaction" },
367 /* 195 */ { "rt_sigprocmask" },
368 /* 196 */ { "rt_sigpending" },
369 /* 197 */ { "rt_sigtimedwait" },
370 /* 198 */ { "rt_sigqueueinfo", ignoreFunc },
371 /* 199 */ { "rt_sigsuspend" },
372 /* 200 */ { "pread64" },
373 /* 201 */ { "pwrite64" },
374 /* 202 */ { "chown" },
375 /* 203 */ { "getcwd", getcwdFunc },
376 /* 204 */ { "capget" },
377 /* 205 */ { "capset" },
378 /* 206 */ { "sigalstack" },
379 /* 207 */ { "sendfile" },
380 /* 208 */ { "getpmsg" },
381 /* 209 */ { "putpmsg" },
382 /* 210 */ { "mmap2" },
383 /* 211 */ { "truncate64" },
384 /* 212 */ { "ftruncate64" },
385 /* 213 */ { "stat64" },
386 /* 214 */ { "lstat64", lstat64Func<MipsLinux> },
387 /* 215 */ { "fstat64", fstat64Func<MipsLinux> },
388 /* 216 */ { "pivot_root" },
389 /* 217 */ { "mincore" },
390 /* 218 */ { "madvise" },
391 /* 219 */ { "getdents64" },
392 /* 220 */ { "fcntl64", fcntl64Func },
393 /* 221 */ { "reserved#221" },
394 /* 222 */ { "gettid" },
395 /* 223 */ { "readahead" },
396 /* 224 */ { "setxattr" },
397 /* 225 */ { "lsetxattr" },
398 /* 226 */ { "fsetxattr" },
399 /* 227 */ { "getxattr" },
400 /* 228 */ { "lgetxattr" },
401 /* 229 */ { "fgetxattr" },
402 /* 230 */ { "listxattr" },
403 /* 231 */ { "llistxattr" },
404 /* 232 */ { "flistxattr" },
405 /* 233 */ { "removexattr" },
406 /* 234 */ { "lremovexattr" },
407 /* 235 */ { "fremovexattr", ignoreFunc },
408 /* 236 */ { "tkill" },
409 /* 237 */ { "sendfile64" },
410 /* 238 */ { "futex" },
411 /* 239 */ { "sched_setaffinity" },
412 /* 240 */ { "sched_getaffinity" },
413 /* 241 */ { "io_setup" },
414 /* 242 */ { "io_destroy" },
415 /* 243 */ { "io_getevents" },
416 /* 244 */ { "io_submit" },
417 /* 245 */ { "io_cancel" },
418 /* 246 */ { "exit_group", exitFunc },
419 /* 247 */ { "lookup_dcookie" },
420 /* 248 */ { "epoll_create" },
421 /* 249 */ { "epoll_ctl" },
422 /* 250 */ { "epoll_wait" },
423 /* 251 */ { "remap_file_pages" },
424 /* 252 */ { "set_tid_address" },
425 /* 253 */ { "restart_syscall" },
426 /* 254 */ { "fadvise64" },
427 /* 255 */ { "statfs64" },
428 /* 256 */ { "fstafs64" },
429 /* 257 */ { "timer_create", sys_getsysinfoFunc },
430 /* 258 */ { "timer_settime", sys_setsysinfoFunc },
431 /* 259 */ { "timer_gettime" },
432 /* 260 */ { "timer_getoverrun" },
433 /* 261 */ { "timer_delete" },
434 /* 262 */ { "clock_settime" },
435 /* 263 */ { "clock_gettime" },
436 /* 264 */ { "clock_getres" },
437 /* 265 */ { "clock_nanosleep" },
438 /* 266 */ { "tgkill" },
439 /* 267 */ { "utimes" },
440 /* 268 */ { "mbind" },
441 /* 269 */ { "get_mempolicy" },
442 /* 270 */ { "set_mempolicy" },
443 /* 271 */ { "mq_open" },
444 /* 272 */ { "mq_unlink" },
445 /* 273 */ { "mq_timedsend" },
446 /* 274 */ { "mq_timedreceive" },
447 /* 275 */ { "mq_notify" },
448 /* 276 */ { "mq_getsetattr" },
449 /* 277 */ { "vserver" },
450 /* 278 */ { "waitid" },
451 /* 279 */ { "unknown #279" },
452 /* 280 */ { "add_key" },
453 /* 281 */ { "request_key" },
454 /* 282 */ { "keyctl" },
455 /* 283 */ { "set_thread_area", setThreadAreaFunc },
456 /* 284 */ { "inotify_init" },
457 /* 285 */ { "inotify_add_watch" },
458 /* 286 */ { "inotify_rm_watch" },
459 /* 287 */ { "migrate_pages" },
460 /* 288 */ { "openat" },
461 /* 289 */ { "mkdirat" },
462 /* 290 */ { "mknodat" },
463 /* 291 */ { "fchownat" },
464 /* 292 */ { "futimesat" },
465 /* 293 */ { "fstatat64" },
466 /* 294 */ { "unlinkat" },
467 /* 295 */ { "renameat" },
468 /* 296 */ { "linkat" },
469 /* 297 */ { "symlinkat" },
470 /* 298 */ { "readlinkat" },
471 /* 299 */ { "fchmodat" },
472 /* 300 */ { "faccessat" },
473 /* 301 */ { "pselect6" },
474 /* 302 */ { "ppoll" },
475 /* 303 */ { "unshare" },
476 /* 304 */ { "splice" },
477 /* 305 */ { "sync_file_range" },
478 /* 306 */ { "tee" },
479 /* 307 */ { "vmsplice" },
480 /* 308 */ { "move_pages" },
481 /* 309 */ { "set_robust_list" },
482 /* 310 */ { "get_robust_list" },
483 /* 311 */ { "kexec_load" },
484 /* 312 */ { "getcpu" },
485 /* 313 */ { "epoll_pwait" },
486 /* 314 */ { "ioprio_set" },
487 /* 315 */ { "ioprio_get" },
488 /* 316 */ { "utimensat" },
489 /* 317 */ { "signalfd" },
490 /* 318 */ { "timerfd" },
491 /* 319 */ { "eventfd" }
492 };
493
494 MipsLinuxProcess::MipsLinuxProcess(ProcessParams * params,
495 ObjectFile *objFile)
496 : MipsProcess(params, objFile),
497 Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
498 { }
499
500 SyscallDesc*
501 MipsLinuxProcess::getDesc(int callnum)
502 {
503 //MIPS32 syscalls are in the range of 4000 - 4999
504 int m5_sys_idx = callnum - 4000;
505
506 if (m5_sys_idx < 0 || m5_sys_idx >= Num_Syscall_Descs)
507 return NULL;
508
509 return &syscallDescs[m5_sys_idx];
510 }
511
512 void
513 MipsLinuxProcess::syscall(ThreadContext *tc, Fault *fault)
514 {
515 doSyscall(tc->readIntReg(2), tc, fault);
516 }