1 /* 2 * qemu user cpu loop 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "qemu-common.h" 22 #include "qemu.h" 23 #include "user-internals.h" 24 #include "cpu_loop-common.h" 25 #include "signal-common.h" 26 27 static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 28 { 29 return cpu_get_host_ticks(); 30 } 31 32 uint64_t cpu_ppc_load_tbl(CPUPPCState *env) 33 { 34 return cpu_ppc_get_tb(env); 35 } 36 37 uint32_t cpu_ppc_load_tbu(CPUPPCState *env) 38 { 39 return cpu_ppc_get_tb(env) >> 32; 40 } 41 42 uint64_t cpu_ppc_load_atbl(CPUPPCState *env) 43 { 44 return cpu_ppc_get_tb(env); 45 } 46 47 uint32_t cpu_ppc_load_atbu(CPUPPCState *env) 48 { 49 return cpu_ppc_get_tb(env) >> 32; 50 } 51 52 uint64_t cpu_ppc_load_vtb(CPUPPCState *env) 53 { 54 return cpu_ppc_get_tb(env); 55 } 56 57 uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) 58 __attribute__ (( alias ("cpu_ppc_load_tbu") )); 59 60 uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) 61 { 62 return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 63 } 64 65 /* XXX: to be fixed */ 66 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 67 { 68 return -1; 69 } 70 71 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 72 { 73 return -1; 74 } 75 76 void cpu_loop(CPUPPCState *env) 77 { 78 CPUState *cs = env_cpu(env); 79 target_siginfo_t info; 80 int trapnr; 81 target_ulong ret; 82 83 for(;;) { 84 bool arch_interrupt; 85 86 cpu_exec_start(cs); 87 trapnr = cpu_exec(cs); 88 cpu_exec_end(cs); 89 process_queued_cpu_work(cs); 90 91 arch_interrupt = true; 92 switch (trapnr) { 93 case POWERPC_EXCP_NONE: 94 /* Just go on */ 95 break; 96 case POWERPC_EXCP_CRITICAL: /* Critical input */ 97 cpu_abort(cs, "Critical interrupt while in user mode. " 98 "Aborting\n"); 99 break; 100 case POWERPC_EXCP_MCHECK: /* Machine check exception */ 101 cpu_abort(cs, "Machine check exception while in user mode. " 102 "Aborting\n"); 103 break; 104 case POWERPC_EXCP_DSI: /* Data storage exception */ 105 /* XXX: check this. Seems bugged */ 106 switch (env->error_code & 0xFF000000) { 107 case 0x40000000: 108 case 0x42000000: 109 info.si_signo = TARGET_SIGSEGV; 110 info.si_errno = 0; 111 info.si_code = TARGET_SEGV_MAPERR; 112 break; 113 case 0x04000000: 114 info.si_signo = TARGET_SIGILL; 115 info.si_errno = 0; 116 info.si_code = TARGET_ILL_ILLADR; 117 break; 118 case 0x08000000: 119 info.si_signo = TARGET_SIGSEGV; 120 info.si_errno = 0; 121 info.si_code = TARGET_SEGV_ACCERR; 122 break; 123 default: 124 /* Let's send a regular segfault... */ 125 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 126 env->error_code); 127 info.si_signo = TARGET_SIGSEGV; 128 info.si_errno = 0; 129 info.si_code = TARGET_SEGV_MAPERR; 130 break; 131 } 132 info._sifields._sigfault._addr = env->spr[SPR_DAR]; 133 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 134 break; 135 case POWERPC_EXCP_ISI: /* Instruction storage exception */ 136 /* XXX: check this */ 137 switch (env->error_code & 0xFF000000) { 138 case 0x40000000: 139 info.si_signo = TARGET_SIGSEGV; 140 info.si_errno = 0; 141 info.si_code = TARGET_SEGV_MAPERR; 142 break; 143 case 0x10000000: 144 case 0x08000000: 145 info.si_signo = TARGET_SIGSEGV; 146 info.si_errno = 0; 147 info.si_code = TARGET_SEGV_ACCERR; 148 break; 149 default: 150 /* Let's send a regular segfault... */ 151 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 152 env->error_code); 153 info.si_signo = TARGET_SIGSEGV; 154 info.si_errno = 0; 155 info.si_code = TARGET_SEGV_MAPERR; 156 break; 157 } 158 info._sifields._sigfault._addr = env->nip - 4; 159 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 160 break; 161 case POWERPC_EXCP_EXTERNAL: /* External input */ 162 cpu_abort(cs, "External interrupt while in user mode. " 163 "Aborting\n"); 164 break; 165 case POWERPC_EXCP_PROGRAM: /* Program exception */ 166 case POWERPC_EXCP_HV_EMU: /* HV emulation */ 167 /* XXX: check this */ 168 switch (env->error_code & ~0xF) { 169 case POWERPC_EXCP_FP: 170 info.si_signo = TARGET_SIGFPE; 171 info.si_errno = 0; 172 switch (env->error_code & 0xF) { 173 case POWERPC_EXCP_FP_OX: 174 info.si_code = TARGET_FPE_FLTOVF; 175 break; 176 case POWERPC_EXCP_FP_UX: 177 info.si_code = TARGET_FPE_FLTUND; 178 break; 179 case POWERPC_EXCP_FP_ZX: 180 case POWERPC_EXCP_FP_VXZDZ: 181 info.si_code = TARGET_FPE_FLTDIV; 182 break; 183 case POWERPC_EXCP_FP_XX: 184 info.si_code = TARGET_FPE_FLTRES; 185 break; 186 case POWERPC_EXCP_FP_VXSOFT: 187 info.si_code = TARGET_FPE_FLTINV; 188 break; 189 case POWERPC_EXCP_FP_VXSNAN: 190 case POWERPC_EXCP_FP_VXISI: 191 case POWERPC_EXCP_FP_VXIDI: 192 case POWERPC_EXCP_FP_VXIMZ: 193 case POWERPC_EXCP_FP_VXVC: 194 case POWERPC_EXCP_FP_VXSQRT: 195 case POWERPC_EXCP_FP_VXCVI: 196 info.si_code = TARGET_FPE_FLTSUB; 197 break; 198 default: 199 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 200 env->error_code); 201 break; 202 } 203 break; 204 case POWERPC_EXCP_INVAL: 205 info.si_signo = TARGET_SIGILL; 206 info.si_errno = 0; 207 switch (env->error_code & 0xF) { 208 case POWERPC_EXCP_INVAL_INVAL: 209 info.si_code = TARGET_ILL_ILLOPC; 210 break; 211 case POWERPC_EXCP_INVAL_LSWX: 212 info.si_code = TARGET_ILL_ILLOPN; 213 break; 214 case POWERPC_EXCP_INVAL_SPR: 215 info.si_code = TARGET_ILL_PRVREG; 216 break; 217 case POWERPC_EXCP_INVAL_FP: 218 info.si_code = TARGET_ILL_COPROC; 219 break; 220 default: 221 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 222 env->error_code & 0xF); 223 info.si_code = TARGET_ILL_ILLADR; 224 break; 225 } 226 break; 227 case POWERPC_EXCP_PRIV: 228 info.si_signo = TARGET_SIGILL; 229 info.si_errno = 0; 230 switch (env->error_code & 0xF) { 231 case POWERPC_EXCP_PRIV_OPC: 232 info.si_code = TARGET_ILL_PRVOPC; 233 break; 234 case POWERPC_EXCP_PRIV_REG: 235 info.si_code = TARGET_ILL_PRVREG; 236 break; 237 default: 238 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 239 env->error_code & 0xF); 240 info.si_code = TARGET_ILL_PRVOPC; 241 break; 242 } 243 break; 244 case POWERPC_EXCP_TRAP: 245 cpu_abort(cs, "Tried to call a TRAP\n"); 246 break; 247 default: 248 /* Should not happen ! */ 249 cpu_abort(cs, "Unknown program exception (%02x)\n", 250 env->error_code); 251 break; 252 } 253 info._sifields._sigfault._addr = env->nip; 254 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 255 break; 256 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 257 info.si_signo = TARGET_SIGILL; 258 info.si_errno = 0; 259 info.si_code = TARGET_ILL_COPROC; 260 info._sifields._sigfault._addr = env->nip; 261 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 262 break; 263 case POWERPC_EXCP_SYSCALL: /* System call exception */ 264 case POWERPC_EXCP_SYSCALL_VECTORED: 265 cpu_abort(cs, "Syscall exception while in user mode. " 266 "Aborting\n"); 267 break; 268 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 269 info.si_signo = TARGET_SIGILL; 270 info.si_errno = 0; 271 info.si_code = TARGET_ILL_COPROC; 272 info._sifields._sigfault._addr = env->nip; 273 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 274 break; 275 case POWERPC_EXCP_DECR: /* Decrementer exception */ 276 cpu_abort(cs, "Decrementer interrupt while in user mode. " 277 "Aborting\n"); 278 break; 279 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 280 cpu_abort(cs, "Fix interval timer interrupt while in user mode. " 281 "Aborting\n"); 282 break; 283 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 284 cpu_abort(cs, "Watchdog timer interrupt while in user mode. " 285 "Aborting\n"); 286 break; 287 case POWERPC_EXCP_DTLB: /* Data TLB error */ 288 cpu_abort(cs, "Data TLB exception while in user mode. " 289 "Aborting\n"); 290 break; 291 case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 292 cpu_abort(cs, "Instruction TLB exception while in user mode. " 293 "Aborting\n"); 294 break; 295 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 296 info.si_signo = TARGET_SIGILL; 297 info.si_errno = 0; 298 info.si_code = TARGET_ILL_COPROC; 299 info._sifields._sigfault._addr = env->nip; 300 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 301 break; 302 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 303 cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); 304 break; 305 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 306 cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); 307 break; 308 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 309 cpu_abort(cs, "Performance monitor exception not handled\n"); 310 break; 311 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 312 cpu_abort(cs, "Doorbell interrupt while in user mode. " 313 "Aborting\n"); 314 break; 315 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 316 cpu_abort(cs, "Doorbell critical interrupt while in user mode. " 317 "Aborting\n"); 318 break; 319 case POWERPC_EXCP_RESET: /* System reset exception */ 320 cpu_abort(cs, "Reset interrupt while in user mode. " 321 "Aborting\n"); 322 break; 323 case POWERPC_EXCP_DSEG: /* Data segment exception */ 324 cpu_abort(cs, "Data segment exception while in user mode. " 325 "Aborting\n"); 326 break; 327 case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 328 cpu_abort(cs, "Instruction segment exception " 329 "while in user mode. Aborting\n"); 330 break; 331 /* PowerPC 64 with hypervisor mode support */ 332 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 333 cpu_abort(cs, "Hypervisor decrementer interrupt " 334 "while in user mode. Aborting\n"); 335 break; 336 case POWERPC_EXCP_TRACE: /* Trace exception */ 337 /* Nothing to do: 338 * we use this exception to emulate step-by-step execution mode. 339 */ 340 break; 341 /* PowerPC 64 with hypervisor mode support */ 342 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 343 cpu_abort(cs, "Hypervisor data storage exception " 344 "while in user mode. Aborting\n"); 345 break; 346 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 347 cpu_abort(cs, "Hypervisor instruction storage exception " 348 "while in user mode. Aborting\n"); 349 break; 350 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 351 cpu_abort(cs, "Hypervisor data segment exception " 352 "while in user mode. Aborting\n"); 353 break; 354 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 355 cpu_abort(cs, "Hypervisor instruction segment exception " 356 "while in user mode. Aborting\n"); 357 break; 358 case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 359 info.si_signo = TARGET_SIGILL; 360 info.si_errno = 0; 361 info.si_code = TARGET_ILL_COPROC; 362 info._sifields._sigfault._addr = env->nip; 363 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 364 break; 365 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 366 cpu_abort(cs, "Programmable interval timer interrupt " 367 "while in user mode. Aborting\n"); 368 break; 369 case POWERPC_EXCP_IO: /* IO error exception */ 370 cpu_abort(cs, "IO error exception while in user mode. " 371 "Aborting\n"); 372 break; 373 case POWERPC_EXCP_RUNM: /* Run mode exception */ 374 cpu_abort(cs, "Run mode exception while in user mode. " 375 "Aborting\n"); 376 break; 377 case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 378 cpu_abort(cs, "Emulation trap exception not handled\n"); 379 break; 380 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 381 cpu_abort(cs, "Instruction fetch TLB exception " 382 "while in user-mode. Aborting"); 383 break; 384 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 385 cpu_abort(cs, "Data load TLB exception while in user-mode. " 386 "Aborting"); 387 break; 388 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 389 cpu_abort(cs, "Data store TLB exception while in user-mode. " 390 "Aborting"); 391 break; 392 case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 393 cpu_abort(cs, "Floating-point assist exception not handled\n"); 394 break; 395 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 396 cpu_abort(cs, "Instruction address breakpoint exception " 397 "not handled\n"); 398 break; 399 case POWERPC_EXCP_SMI: /* System management interrupt */ 400 cpu_abort(cs, "System management interrupt while in user mode. " 401 "Aborting\n"); 402 break; 403 case POWERPC_EXCP_THERM: /* Thermal interrupt */ 404 cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " 405 "Aborting\n"); 406 break; 407 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 408 cpu_abort(cs, "Performance monitor exception not handled\n"); 409 break; 410 case POWERPC_EXCP_VPUA: /* Vector assist exception */ 411 cpu_abort(cs, "Vector assist exception not handled\n"); 412 break; 413 case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 414 cpu_abort(cs, "Soft patch exception not handled\n"); 415 break; 416 case POWERPC_EXCP_MAINT: /* Maintenance exception */ 417 cpu_abort(cs, "Maintenance exception while in user mode. " 418 "Aborting\n"); 419 break; 420 case POWERPC_EXCP_SYSCALL_USER: 421 /* system call in user-mode emulation */ 422 /* WARNING: 423 * PPC ABI uses overflow flag in cr0 to signal an error 424 * in syscalls. 425 */ 426 env->crf[0] &= ~0x1; 427 env->nip += 4; 428 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 429 env->gpr[5], env->gpr[6], env->gpr[7], 430 env->gpr[8], 0, 0); 431 if (ret == -TARGET_ERESTARTSYS) { 432 env->nip -= 4; 433 break; 434 } 435 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 436 /* Returning from a successful sigreturn syscall. 437 Avoid corrupting register state. */ 438 break; 439 } 440 if (ret > (target_ulong)(-515)) { 441 env->crf[0] |= 0x1; 442 ret = -ret; 443 } 444 env->gpr[3] = ret; 445 break; 446 case EXCP_DEBUG: 447 info.si_signo = TARGET_SIGTRAP; 448 info.si_errno = 0; 449 info.si_code = TARGET_TRAP_BRKPT; 450 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 451 break; 452 case EXCP_INTERRUPT: 453 /* just indicate that signals should be handled asap */ 454 break; 455 case EXCP_ATOMIC: 456 cpu_exec_step_atomic(cs); 457 arch_interrupt = false; 458 break; 459 default: 460 cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr); 461 break; 462 } 463 process_pending_signals(env); 464 465 /* Most of the traps imply a transition through kernel mode, 466 * which implies an REI instruction has been executed. Which 467 * means that RX and LOCK_ADDR should be cleared. But there 468 * are a few exceptions for traps internal to QEMU. 469 */ 470 if (arch_interrupt) { 471 env->reserve_addr = -1; 472 } 473 } 474 } 475 476 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 477 { 478 int i; 479 480 #if defined(TARGET_PPC64) 481 int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF; 482 #if defined(TARGET_ABI32) 483 ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag)); 484 #else 485 ppc_store_msr(env, env->msr | (target_ulong)1 << flag); 486 #endif 487 #endif 488 489 env->nip = regs->nip; 490 for(i = 0; i < 32; i++) { 491 env->gpr[i] = regs->gpr[i]; 492 } 493 } 494