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 cpu_abort(cs, "Syscall exception while in user mode. " 271 "Aborting\n"); 272 break; 273 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 274 info.si_signo = TARGET_SIGILL; 275 info.si_errno = 0; 276 info.si_code = TARGET_ILL_COPROC; 277 info._sifields._sigfault._addr = env->nip; 278 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 279 break; 280 case POWERPC_EXCP_DECR: /* Decrementer exception */ 281 cpu_abort(cs, "Decrementer interrupt while in user mode. " 282 "Aborting\n"); 283 break; 284 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 285 cpu_abort(cs, "Fix interval timer interrupt while in user mode. " 286 "Aborting\n"); 287 break; 288 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 289 cpu_abort(cs, "Watchdog timer interrupt while in user mode. " 290 "Aborting\n"); 291 break; 292 case POWERPC_EXCP_DTLB: /* Data TLB error */ 293 cpu_abort(cs, "Data TLB exception while in user mode. " 294 "Aborting\n"); 295 break; 296 case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 297 cpu_abort(cs, "Instruction TLB exception while in user mode. " 298 "Aborting\n"); 299 break; 300 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 301 info.si_signo = TARGET_SIGILL; 302 info.si_errno = 0; 303 info.si_code = TARGET_ILL_COPROC; 304 info._sifields._sigfault._addr = env->nip; 305 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 306 break; 307 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 308 cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); 309 break; 310 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 311 cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); 312 break; 313 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 314 cpu_abort(cs, "Performance monitor exception not handled\n"); 315 break; 316 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 317 cpu_abort(cs, "Doorbell interrupt while in user mode. " 318 "Aborting\n"); 319 break; 320 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 321 cpu_abort(cs, "Doorbell critical interrupt while in user mode. " 322 "Aborting\n"); 323 break; 324 case POWERPC_EXCP_RESET: /* System reset exception */ 325 cpu_abort(cs, "Reset interrupt while in user mode. " 326 "Aborting\n"); 327 break; 328 case POWERPC_EXCP_DSEG: /* Data segment exception */ 329 cpu_abort(cs, "Data segment exception while in user mode. " 330 "Aborting\n"); 331 break; 332 case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 333 cpu_abort(cs, "Instruction segment exception " 334 "while in user mode. Aborting\n"); 335 break; 336 /* PowerPC 64 with hypervisor mode support */ 337 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 338 cpu_abort(cs, "Hypervisor decrementer interrupt " 339 "while in user mode. Aborting\n"); 340 break; 341 case POWERPC_EXCP_TRACE: /* Trace exception */ 342 /* Nothing to do: 343 * we use this exception to emulate step-by-step execution mode. 344 */ 345 break; 346 /* PowerPC 64 with hypervisor mode support */ 347 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 348 cpu_abort(cs, "Hypervisor data storage exception " 349 "while in user mode. Aborting\n"); 350 break; 351 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 352 cpu_abort(cs, "Hypervisor instruction storage exception " 353 "while in user mode. Aborting\n"); 354 break; 355 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 356 cpu_abort(cs, "Hypervisor data segment exception " 357 "while in user mode. Aborting\n"); 358 break; 359 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 360 cpu_abort(cs, "Hypervisor instruction segment exception " 361 "while in user mode. Aborting\n"); 362 break; 363 case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 364 info.si_signo = TARGET_SIGILL; 365 info.si_errno = 0; 366 info.si_code = TARGET_ILL_COPROC; 367 info._sifields._sigfault._addr = env->nip; 368 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 369 break; 370 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 371 cpu_abort(cs, "Programmable interval timer interrupt " 372 "while in user mode. Aborting\n"); 373 break; 374 case POWERPC_EXCP_IO: /* IO error exception */ 375 cpu_abort(cs, "IO error exception while in user mode. " 376 "Aborting\n"); 377 break; 378 case POWERPC_EXCP_RUNM: /* Run mode exception */ 379 cpu_abort(cs, "Run mode exception while in user mode. " 380 "Aborting\n"); 381 break; 382 case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 383 cpu_abort(cs, "Emulation trap exception not handled\n"); 384 break; 385 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 386 cpu_abort(cs, "Instruction fetch TLB exception " 387 "while in user-mode. Aborting"); 388 break; 389 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 390 cpu_abort(cs, "Data load TLB exception while in user-mode. " 391 "Aborting"); 392 break; 393 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 394 cpu_abort(cs, "Data store TLB exception while in user-mode. " 395 "Aborting"); 396 break; 397 case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 398 cpu_abort(cs, "Floating-point assist exception not handled\n"); 399 break; 400 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 401 cpu_abort(cs, "Instruction address breakpoint exception " 402 "not handled\n"); 403 break; 404 case POWERPC_EXCP_SMI: /* System management interrupt */ 405 cpu_abort(cs, "System management interrupt while in user mode. " 406 "Aborting\n"); 407 break; 408 case POWERPC_EXCP_THERM: /* Thermal interrupt */ 409 cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " 410 "Aborting\n"); 411 break; 412 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 413 cpu_abort(cs, "Performance monitor exception not handled\n"); 414 break; 415 case POWERPC_EXCP_VPUA: /* Vector assist exception */ 416 cpu_abort(cs, "Vector assist exception not handled\n"); 417 break; 418 case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 419 cpu_abort(cs, "Soft patch exception not handled\n"); 420 break; 421 case POWERPC_EXCP_MAINT: /* Maintenance exception */ 422 cpu_abort(cs, "Maintenance exception while in user mode. " 423 "Aborting\n"); 424 break; 425 case POWERPC_EXCP_STOP: /* stop translation */ 426 /* We did invalidate the instruction cache. Go on */ 427 break; 428 case POWERPC_EXCP_BRANCH: /* branch instruction: */ 429 /* We just stopped because of a branch. Go on */ 430 break; 431 case POWERPC_EXCP_SYSCALL_USER: 432 /* system call in user-mode emulation */ 433 /* WARNING: 434 * PPC ABI uses overflow flag in cr0 to signal an error 435 * in syscalls. 436 */ 437 env->crf[0] &= ~0x1; 438 env->nip += 4; 439 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 440 env->gpr[5], env->gpr[6], env->gpr[7], 441 env->gpr[8], 0, 0); 442 if (ret == -TARGET_ERESTARTSYS) { 443 env->nip -= 4; 444 break; 445 } 446 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 447 /* Returning from a successful sigreturn syscall. 448 Avoid corrupting register state. */ 449 break; 450 } 451 if (ret > (target_ulong)(-515)) { 452 env->crf[0] |= 0x1; 453 ret = -ret; 454 } 455 env->gpr[3] = ret; 456 break; 457 case EXCP_DEBUG: 458 info.si_signo = TARGET_SIGTRAP; 459 info.si_errno = 0; 460 info.si_code = TARGET_TRAP_BRKPT; 461 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 462 break; 463 case EXCP_INTERRUPT: 464 /* just indicate that signals should be handled asap */ 465 break; 466 case EXCP_ATOMIC: 467 cpu_exec_step_atomic(cs); 468 arch_interrupt = false; 469 break; 470 default: 471 cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr); 472 break; 473 } 474 process_pending_signals(env); 475 476 /* Most of the traps imply a transition through kernel mode, 477 * which implies an REI instruction has been executed. Which 478 * means that RX and LOCK_ADDR should be cleared. But there 479 * are a few exceptions for traps internal to QEMU. 480 */ 481 if (arch_interrupt) { 482 env->reserve_addr = -1; 483 } 484 } 485 } 486 487 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 488 { 489 int i; 490 491 #if defined(TARGET_PPC64) 492 int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF; 493 #if defined(TARGET_ABI32) 494 env->msr &= ~((target_ulong)1 << flag); 495 #else 496 env->msr |= (target_ulong)1 << flag; 497 #endif 498 #endif 499 env->nip = regs->nip; 500 for(i = 0; i < 32; i++) { 501 env->gpr[i] = regs->gpr[i]; 502 } 503 } 504