/* * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "arch/power/linux/process.hh" #include "arch/power/isa_traits.hh" #include "arch/power/linux/linux.hh" #include "base/loader/object_file.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "kern/linux/linux.hh" #include "sim/process.hh" #include "sim/syscall_desc.hh" #include "sim/syscall_emul.hh" #include "sim/system.hh" using namespace std; using namespace PowerISA; namespace { class PowerLinuxObjectFileLoader : public Process::Loader { public: Process * load(ProcessParams *params, ObjectFile *obj_file) override { if (obj_file->getArch() != ObjectFile::Power) return nullptr; auto opsys = obj_file->getOpSys(); if (opsys == ObjectFile::UnknownOpSys) { warn("Unknown operating system; assuming Linux."); opsys = ObjectFile::Linux; } if (opsys != ObjectFile::Linux) return nullptr; return new PowerLinuxProcess(params, obj_file); } }; PowerLinuxObjectFileLoader loader; } // anonymous namespace /// Target uname() handler. static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr utsname) { auto process = tc->getProcessPtr(); TypedBufferArg name(utsname); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "sim.gem5.org"); strcpy(name->release, process->release.c_str()); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "power"); name.copyOut(tc->getVirtProxy()); return 0; } SyscallDescABI PowerLinuxProcess::syscallDescs[] = { /* 0 */ { "syscall" }, /* 1 */ { "exit", exitFunc }, /* 2 */ { "fork" }, /* 3 */ { "read", readFunc }, /* 4 */ { "write", writeFunc }, /* 5 */ { "open", openFunc }, /* 6 */ { "close", closeFunc }, /* 7 */ { "waitpid" }, //??? /* 8 */ { "creat" }, /* 9 */ { "link" }, /* 10 */ { "unlink", unlinkFunc }, /* 11 */ { "execve" }, /* 12 */ { "chdir" }, /* 13 */ { "time", timeFunc }, /* 14 */ { "mknod" }, /* 15 */ { "chmod", chmodFunc }, /* 16 */ { "lchown", chownFunc }, /* 17 */ { "break", brkFunc }, //??? /* 18 */ { "unused#18" }, //??? /* 19 */ { "lseek", lseekFunc }, /* 20 */ { "getpid", getpidFunc }, /* 21 */ { "mount" }, /* 22 */ { "umount" }, /* 23 */ { "setuid", ignoreFunc }, /* 24 */ { "getuid", getuidFunc }, /* 25 */ { "stime" }, /* 26 */ { "ptrace" }, /* 27 */ { "alarm" }, /* 28 */ { "unused#28" }, /* 29 */ { "pause" }, /* 30 */ { "utime" }, /* 31 */ { "stty" }, /* 32 */ { "gtty" }, /* 33 */ { "access" }, /* 34 */ { "nice" }, /* 35 */ { "ftime" }, /* 36 */ { "sync" }, /* 37 */ { "kill", ignoreFunc }, /* 38 */ { "rename", renameFunc }, /* 39 */ { "mkdir" }, /* 40 */ { "rmdir" }, /* 41 */ { "dup", dupFunc }, /* 42 */ { "pipe" }, /* 43 */ { "times", timesFunc }, /* 44 */ { "prof" }, /* 45 */ { "brk", brkFunc }, /* 46 */ { "setgid" }, /* 47 */ { "getgid", getgidFunc }, /* 48 */ { "signal", ignoreFunc }, /* 49 */ { "geteuid", geteuidFunc }, /* 50 */ { "getegid", getegidFunc }, /* 51 */ { "acct" }, /* 52 */ { "umount2" }, /* 53 */ { "lock" }, /* 54 */ { "ioctl", ioctlFunc }, /* 55 */ { "fcntl", fcntlFunc }, /* 56 */ { "mpx" }, /* 57 */ { "setpgid" }, /* 58 */ { "ulimit" }, /* 59 */ { "unused#59" }, /* 60 */ { "umask", umaskFunc }, /* 61 */ { "chroot" }, /* 62 */ { "ustat" }, /* 63 */ { "dup2" }, /* 64 */ { "getppid", getpagesizeFunc }, /* 65 */ { "getpgrp" }, /* 66 */ { "setsid" }, /* 67 */ { "sigaction" }, /* 68 */ { "sgetmask" }, /* 69 */ { "ssetmask" }, /* 70 */ { "setreuid" }, /* 71 */ { "setregid" }, /* 72 */ { "sigsuspend" }, /* 73 */ { "sigpending" }, /* 74 */ { "sethostname", ignoreFunc }, /* 75 */ { "setrlimit", ignoreFunc }, /* 76 */ { "getrlimit" }, /* 77 */ { "getrusage", ignoreFunc }, /* 78 */ { "gettimeofday" }, /* 79 */ { "settimeofday" }, /* 80 */ { "getgroups" }, /* 81 */ { "setgroups" }, /* 82 */ { "reserved#82" }, /* 83 */ { "symlink" }, /* 84 */ { "unused#84" }, /* 85 */ { "readlink" }, /* 86 */ { "uselib" }, /* 87 */ { "swapon", gethostnameFunc }, /* 88 */ { "reboot" }, /* 89 */ { "readdir" }, /* 90 */ { "mmap", mmapFunc }, /* 91 */ { "munmap",munmapFunc }, /* 92 */ { "truncate", truncateFunc }, /* 93 */ { "ftruncate", ftruncateFunc }, /* 94 */ { "fchmod" }, /* 95 */ { "fchown" }, /* 96 */ { "getpriority" }, /* 97 */ { "setpriority" }, /* 98 */ { "profil" }, /* 99 */ { "statfs" }, /* 100 */ { "fstatfs" }, /* 101 */ { "ioperm" }, /* 102 */ { "socketcall" }, /* 103 */ { "syslog" }, /* 104 */ { "setitimer" }, /* 105 */ { "getitimer" }, /* 106 */ { "stat", statFunc }, /* 107 */ { "lstat" }, /* 108 */ { "fstat", fstatFunc }, /* 109 */ { "unused#109" }, /* 110 */ { "iopl" }, /* 111 */ { "vhangup" }, /* 112 */ { "idle", ignoreFunc }, /* 113 */ { "vm86" }, /* 114 */ { "wait4" }, /* 115 */ { "swapoff" }, /* 116 */ { "sysinfo" }, /* 117 */ { "ipc" }, /* 118 */ { "fsync" }, /* 119 */ { "sigreturn" }, /* 120 */ { "clone" }, /* 121 */ { "setdomainname" }, /* 122 */ { "uname", unameFunc }, /* 123 */ { "modify_ldt" }, /* 124 */ { "adjtimex" }, /* 125 */ { "mprotect", ignoreFunc }, /* 126 */ { "sigprocmask" }, /* 127 */ { "create_module" }, /* 128 */ { "init_module" }, /* 129 */ { "delete_module" }, /* 130 */ { "get_kernel_syms" }, /* 131 */ { "quotactl" }, /* 132 */ { "getpgid" }, /* 133 */ { "fchdir" }, /* 134 */ { "bdflush" }, /* 135 */ { "sysfs" }, /* 136 */ { "personality" }, /* 137 */ { "afs_syscall" }, /* 138 */ { "setfsuid" }, /* 139 */ { "setfsgid" }, /* 140 */ { "llseek", _llseekFunc }, /* 141 */ { "getdents" }, /* 142 */ { "newselect" }, /* 143 */ { "flock" }, /* 144 */ { "msync" }, /* 145 */ { "readv" }, /* 146 */ { "writev", writevFunc }, /* 147 */ { "getsid" }, /* 148 */ { "fdatasync" }, /* 149 */ { "sysctl" }, /* 150 */ { "mlock" }, /* 151 */ { "munlock" }, /* 152 */ { "mlockall" }, /* 153 */ { "munlockall" }, /* 154 */ { "sched_setparam" }, /* 155 */ { "sched_getparam" }, /* 156 */ { "sched_setscheduler" }, /* 157 */ { "sched_getscheduler" }, /* 158 */ { "sched_yield" }, /* 159 */ { "sched_get_priority_max" }, /* 160 */ { "sched_get_priority_min" }, /* 161 */ { "sched_rr_get_interval" }, /* 162 */ { "nanosleep" }, /* 163 */ { "mremap" }, /* 164 */ { "setresuid" }, /* 165 */ { "getresuid" }, /* 166 */ { "vm862" }, /* 167 */ { "query_module" }, /* 168 */ { "poll" }, /* 169 */ { "nfsservctl" }, /* 170 */ { "setresgid" }, /* 171 */ { "getresgid" }, /* 172 */ { "prctl" }, /* 173 */ { "rt_sigaction", ignoreFunc }, /* 174 */ { "rt_sigprocmask" }, /* 175 */ { "unknown#175" }, /* 176 */ { "rt_sigpending" }, /* 177 */ { "rt_sigtimedwait" }, /* 178 */ { "rt_sigqueueinfo", ignoreFunc }, /* 179 */ { "rt_sigsuspend" }, /* 180 */ { "pread64" }, /* 181 */ { "pwrite64" }, /* 182 */ { "chown" }, /* 183 */ { "getcwd" }, /* 184 */ { "capget" }, /* 185 */ { "capset" }, /* 186 */ { "sigaltstack" }, /* 187 */ { "sendfile" }, /* 188 */ { "getpmsg" }, /* 189 */ { "putpmsg" }, /* 190 */ { "ugetrlimit", ignoreFunc }, /* 191 */ { "getrlimit" }, /* 192 */ { "mmap2", mmapFunc }, /* 193 */ { "truncate64" }, /* 194 */ { "ftruncate64", ftruncate64Func }, /* 195 */ { "stat64", stat64Func }, /* 196 */ { "lstat64", lstat64Func }, /* 197 */ { "fstat64", fstat64Func }, /* 198 */ { "lchown" }, /* 199 */ { "getuid", getuidFunc }, /* 200 */ { "getgid", getgidFunc }, /* 201 */ { "geteuid", geteuidFunc }, /* 202 */ { "getegid", getegidFunc }, /* 203 */ { "setreuid" }, /* 204 */ { "fcntl64", fcntl64Func }, /* 205 */ { "getgroups" }, /* 206 */ { "setgroups" }, /* 207 */ { "fchown" }, /* 208 */ { "setresuid" }, /* 209 */ { "getresuid" }, /* 210 */ { "setresgid" }, /* 211 */ { "getresgid" }, /* 212 */ { "chown" }, /* 213 */ { "setuid" }, /* 214 */ { "setgid" }, /* 215 */ { "setfsuid" }, /* 216 */ { "setfsgid" }, /* 217 */ { "getdents64" }, /* 218 */ { "pivot_root" }, /* 219 */ { "mincore" }, /* 220 */ { "madvise" }, /* 221 */ { "unknown#221" }, /* 222 */ { "tux" }, /* 223 */ { "unknown#223" }, /* 224 */ { "gettid" }, /* 225 */ { "readahead" }, /* 226 */ { "setxattr" }, /* 227 */ { "lsetxattr" }, /* 228 */ { "fsetxattr" }, /* 229 */ { "getxattr" }, /* 230 */ { "lgetxattr" }, /* 231 */ { "fgetxattr" }, /* 232 */ { "listxattr" }, /* 233 */ { "llistxattr" }, /* 234 */ { "exit_group", exitGroupFunc }, /* 235 */ { "removexattr" }, /* 236 */ { "lremovexattr" }, /* 237 */ { "fremovexattr" }, /* 238 */ { "tkill" }, /* 239 */ { "sendfile64" }, /* 240 */ { "futex" }, /* 241 */ { "sched_setaffinity" }, /* 242 */ { "sched_getaffinity" }, /* 243 */ { "io_setup" }, /* 244 */ { "io_destory" }, /* 245 */ { "io_getevents" }, /* 246 */ { "io_submit" }, /* 247 */ { "io_cancel" }, /* 248 */ { "unknown#248" }, /* 249 */ { "lookup_dcookie" }, /* 250 */ { "epoll_create" }, /* 251 */ { "epoll_ctl" }, /* 252 */ { "epoll_wait" }, /* 253 */ { "remap_file_pages" }, /* 254 */ { "set_thread_area" }, /* 255 */ { "get_thread_area" }, /* 256 */ { "set_tid_address" }, /* 257 */ { "timer_create" }, /* 258 */ { "timer_settime" }, /* 259 */ { "timer_gettime" }, /* 260 */ { "timer_getoverrun" }, /* 261 */ { "timer_delete" }, /* 262 */ { "clock_settime" }, /* 263 */ { "clock_gettime" }, /* 264 */ { "clock_getres" }, /* 265 */ { "clock_nanosleep" }, /* 266 */ { "statfs64" }, /* 267 */ { "fstatfs64" }, /* 268 */ { "tgkill" }, /* 269 */ { "utimes" }, /* 270 */ { "arm_fadvise64_64" }, /* 271 */ { "pciconfig_iobase" }, /* 272 */ { "pciconfig_read" }, /* 273 */ { "pciconfig_write" }, /* 274 */ { "mq_open" }, /* 275 */ { "mq_unlink" }, /* 276 */ { "mq_timedsend" }, /* 277 */ { "mq_timedreceive" }, /* 278 */ { "mq_notify" }, /* 279 */ { "mq_getsetattr" }, /* 280 */ { "waitid" }, /* 281 */ { "socket" }, /* 282 */ { "bind" }, /* 283 */ { "connect" }, /* 284 */ { "listen" }, /* 285 */ { "accept" }, /* 286 */ { "getsockname" }, /* 287 */ { "getpeername" }, /* 288 */ { "socketpair" }, /* 289 */ { "send" }, /* 290 */ { "sendto" }, /* 291 */ { "recv" }, /* 292 */ { "recvfrom" }, /* 293 */ { "shutdown" }, /* 294 */ { "setsockopt" }, /* 295 */ { "getsockopt" }, /* 296 */ { "sendmsg" }, /* 297 */ { "rcvmsg" }, /* 298 */ { "semop" }, /* 299 */ { "semget" }, /* 300 */ { "semctl" }, /* 301 */ { "msgsend" }, /* 302 */ { "msgrcv" }, /* 303 */ { "msgget" }, /* 304 */ { "msgctl" }, /* 305 */ { "shmat" }, /* 306 */ { "shmdt" }, /* 307 */ { "shmget" }, /* 308 */ { "shmctl" }, /* 309 */ { "add_key" }, /* 310 */ { "request_key" }, /* 311 */ { "keyctl" }, /* 312 */ { "semtimedop" }, /* 313 */ { "vserver" }, /* 314 */ { "ioprio_set" }, /* 315 */ { "ioprio_get" }, /* 316 */ { "inotify_init" }, /* 317 */ { "inotify_add_watch" }, /* 318 */ { "inotify_rm_watch" }, /* 319 */ { "mbind" }, /* 320 */ { "get_mempolicy" }, /* 321 */ { "set_mempolicy" }, /* 322 */ { "openat" }, /* 323 */ { "mkdirat" }, /* 324 */ { "mknodat" }, /* 325 */ { "fchownat" }, /* 326 */ { "futimesat" }, /* 327 */ { "fstatat64" }, /* 328 */ { "unlinkat" }, /* 329 */ { "renameat" }, /* 330 */ { "linkat" }, /* 331 */ { "symlinkat" }, /* 332 */ { "readlinkat" }, /* 333 */ { "fchmodat" }, /* 334 */ { "faccessat" }, /* 335 */ { "pselect6" }, /* 336 */ { "ppoll" }, /* 337 */ { "unshare" }, /* 338 */ { "set_robust_list" }, /* 339 */ { "get_robust_list" }, /* 340 */ { "splice" }, /* 341 */ { "arm_sync_file_range" }, /* 342 */ { "tee" }, /* 343 */ { "vmsplice" }, /* 344 */ { "move_pages" }, /* 345 */ { "getcpu" }, /* 346 */ { "epoll_pwait" }, }; PowerLinuxProcess::PowerLinuxProcess(ProcessParams * params, ObjectFile *objFile) : PowerProcess(params, objFile), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) { } SyscallDesc* PowerLinuxProcess::getDesc(int callnum) { if (callnum < 0 || callnum > Num_Syscall_Descs) return NULL; return &syscallDescs[callnum]; } void PowerLinuxProcess::initState() { PowerProcess::initState(); } void PowerLinuxProcess::syscall(ThreadContext *tc, Fault *fault) { doSyscall(tc->readIntReg(0), tc, fault); } RegVal PowerLinuxProcess::getSyscallArg(ThreadContext *tc, int &i) { // Linux apparently allows more parameter than the ABI says it should. // This limit may need to be increased even further. assert(i < 6); return tc->readIntReg(ArgumentReg0 + i++); }