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