2 * Copyright (c) 2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
33 #include "arch/mips/linux/process.hh"
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"
49 using namespace MipsISA
;
54 class MipsLinuxObjectFileLoader
: public Process::Loader
58 load(ProcessParams
*params
, ObjectFile
*obj_file
) override
60 if (obj_file
->getArch() != ObjectFile::Mips
)
63 auto opsys
= obj_file
->getOpSys();
65 if (opsys
== ObjectFile::UnknownOpSys
) {
66 warn("Unknown operating system; assuming Linux.");
67 opsys
= ObjectFile::Linux
;
70 if (opsys
!= ObjectFile::Linux
)
73 return new MipsLinuxProcess(params
, obj_file
);
77 MipsLinuxObjectFileLoader loader
;
79 } // anonymous namespace
81 /// Target uname() handler.
83 unameFunc(SyscallDesc
*desc
, int callnum
, ThreadContext
*tc
)
86 auto process
= tc
->getProcessPtr();
87 TypedBufferArg
<Linux::utsname
> name(process
->getSyscallArg(tc
, index
));
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");
95 name
.copyOut(tc
->getVirtProxy());
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.
103 sys_getsysinfoFunc(SyscallDesc
*desc
, int callnum
, ThreadContext
*tc
)
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);
114 // GSI_IEEE_FP_CONTROL
115 TypedBufferArg
<uint64_t> fpcr(bufPtr
);
116 // I don't think this exactly matches the HW FPCR
118 fpcr
.copyOut(tc
->getVirtProxy());
122 cerr
<< "sys_getsysinfo: unknown op " << op
<< endl
;
130 /// Target sys_setsysinfo() handler.
132 sys_setsysinfoFunc(SyscallDesc
*desc
, int callnum
, ThreadContext
*tc
)
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);
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
));
153 cerr
<< "sys_setsysinfo: unknown op " << op
<< endl
;
162 setThreadAreaFunc(SyscallDesc
*desc
, int callnum
, ThreadContext
*tc
)
165 auto process
= tc
->getProcessPtr();
166 Addr addr
= process
->getSyscallArg(tc
, index
);
167 tc
->setMiscRegNoEffect(MISCREG_TP_VALUE
, addr
);
171 SyscallDescABI
<DefaultSyscallABI
> MipsLinuxProcess::syscallDescs
[] = {
172 /* 0 */ { "syscall" },
173 /* 1 */ { "exit", exitFunc
},
175 /* 3 */ { "read", readFunc
<MipsLinux
> },
176 /* 4 */ { "write", writeFunc
<MipsLinux
> },
177 /* 5 */ { "open", openFunc
<MipsLinux
> },
178 /* 6 */ { "close", closeFunc
},
179 /* 7 */ { "waitpid" },
182 /* 10 */ { "unlink", unlinkFunc
},
183 /* 11 */ { "execve" },
184 /* 12 */ { "chdir" },
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" },
205 /* 33 */ { "access" },
207 /* 35 */ { "ftime" },
210 /* 38 */ { "rename" },
211 /* 39 */ { "mkdir", mkdirFunc
},
212 /* 40 */ { "rmdir" },
214 /* 42 */ { "pipe", pipePseudoFunc
},
215 /* 43 */ { "times" },
217 /* 45 */ { "brk", brkFunc
},
218 /* 46 */ { "setgid" },
219 /* 47 */ { "getgid", getgidFunc
},
220 /* 48 */ { "signal", ignoreFunc
},
221 /* 49 */ { "geteuid", geteuidFunc
},
222 /* 50 */ { "getegid", getegidFunc
},
224 /* 52 */ { "umount2" },
226 /* 54 */ { "ioctl", ioctlFunc
<MipsLinux
> },
227 /* 55 */ { "fcntl", fcntlFunc
},
229 /* 57 */ { "setpgid" },
230 /* 58 */ { "ulimit" },
231 /* 59 */ { "unused#59" },
232 /* 60 */ { "umask", umaskFunc
},
233 /* 61 */ { "chroot" },
234 /* 62 */ { "ustat" },
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
> },
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" },
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" }
494 MipsLinuxProcess::MipsLinuxProcess(ProcessParams
* params
,
496 : MipsProcess(params
, objFile
),
497 Num_Syscall_Descs(sizeof(syscallDescs
) / sizeof(SyscallDesc
))
501 MipsLinuxProcess::getDesc(int callnum
)
503 //MIPS32 syscalls are in the range of 4000 - 4999
504 int m5_sys_idx
= callnum
- 4000;
506 if (m5_sys_idx
< 0 || m5_sys_idx
>= Num_Syscall_Descs
)
509 return &syscallDescs
[m5_sys_idx
];
513 MipsLinuxProcess::syscall(ThreadContext
*tc
, Fault
*fault
)
515 doSyscall(tc
->readIntReg(2), tc
, fault
);