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