1 /* 2 * PowerPC exception emulation helpers for QEMU. 3 * 4 * Copyright (c) 2003-2007 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library 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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include "qemu/osdep.h" 20 #include "qemu/main-loop.h" 21 #include "cpu.h" 22 #include "exec/helper-proto.h" 23 #include "exec/exec-all.h" 24 #include "exec/cpu_ldst.h" 25 #include "internal.h" 26 #include "helper_regs.h" 27 28 /* #define DEBUG_OP */ 29 /* #define DEBUG_SOFTWARE_TLB */ 30 /* #define DEBUG_EXCEPTIONS */ 31 32 #ifdef DEBUG_EXCEPTIONS 33 # define LOG_EXCP(...) qemu_log(__VA_ARGS__) 34 #else 35 # define LOG_EXCP(...) do { } while (0) 36 #endif 37 38 /*****************************************************************************/ 39 /* Exception processing */ 40 #if defined(CONFIG_USER_ONLY) 41 void ppc_cpu_do_interrupt(CPUState *cs) 42 { 43 PowerPCCPU *cpu = POWERPC_CPU(cs); 44 CPUPPCState *env = &cpu->env; 45 46 cs->exception_index = POWERPC_EXCP_NONE; 47 env->error_code = 0; 48 } 49 50 static void ppc_hw_interrupt(CPUPPCState *env) 51 { 52 CPUState *cs = env_cpu(env); 53 54 cs->exception_index = POWERPC_EXCP_NONE; 55 env->error_code = 0; 56 } 57 #else /* defined(CONFIG_USER_ONLY) */ 58 static inline void dump_syscall(CPUPPCState *env) 59 { 60 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 61 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 62 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 63 " nip=" TARGET_FMT_lx "\n", 64 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), 65 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), 66 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), 67 ppc_dump_gpr(env, 8), env->nip); 68 } 69 70 static inline void dump_syscall_vectored(CPUPPCState *env) 71 { 72 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 73 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 74 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 75 " nip=" TARGET_FMT_lx "\n", 76 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), 77 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), 78 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), 79 ppc_dump_gpr(env, 8), env->nip); 80 } 81 82 static inline void dump_hcall(CPUPPCState *env) 83 { 84 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 85 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 86 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 87 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 88 " nip=" TARGET_FMT_lx "\n", 89 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), 90 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), 91 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), 92 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), 93 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), 94 env->nip); 95 } 96 97 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, 98 target_ulong *msr) 99 { 100 /* We no longer are in a PM state */ 101 env->resume_as_sreset = false; 102 103 /* Pretend to be returning from doze always as we don't lose state */ 104 *msr |= SRR1_WS_NOLOSS; 105 106 /* Machine checks are sent normally */ 107 if (excp == POWERPC_EXCP_MCHECK) { 108 return excp; 109 } 110 switch (excp) { 111 case POWERPC_EXCP_RESET: 112 *msr |= SRR1_WAKERESET; 113 break; 114 case POWERPC_EXCP_EXTERNAL: 115 *msr |= SRR1_WAKEEE; 116 break; 117 case POWERPC_EXCP_DECR: 118 *msr |= SRR1_WAKEDEC; 119 break; 120 case POWERPC_EXCP_SDOOR: 121 *msr |= SRR1_WAKEDBELL; 122 break; 123 case POWERPC_EXCP_SDOOR_HV: 124 *msr |= SRR1_WAKEHDBELL; 125 break; 126 case POWERPC_EXCP_HV_MAINT: 127 *msr |= SRR1_WAKEHMI; 128 break; 129 case POWERPC_EXCP_HVIRT: 130 *msr |= SRR1_WAKEHVI; 131 break; 132 default: 133 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", 134 excp); 135 } 136 return POWERPC_EXCP_RESET; 137 } 138 139 static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail) 140 { 141 uint64_t offset = 0; 142 143 switch (ail) { 144 case AIL_NONE: 145 break; 146 case AIL_0001_8000: 147 offset = 0x18000; 148 break; 149 case AIL_C000_0000_0000_4000: 150 offset = 0xc000000000004000ull; 151 break; 152 default: 153 cpu_abort(cs, "Invalid AIL combination %d\n", ail); 154 break; 155 } 156 157 return offset; 158 } 159 160 static inline void powerpc_set_excp_state(PowerPCCPU *cpu, 161 target_ulong vector, target_ulong msr) 162 { 163 CPUState *cs = CPU(cpu); 164 CPUPPCState *env = &cpu->env; 165 166 /* 167 * We don't use hreg_store_msr here as already have treated any 168 * special case that could occur. Just store MSR and update hflags 169 * 170 * Note: We *MUST* not use hreg_store_msr() as-is anyway because it 171 * will prevent setting of the HV bit which some exceptions might need 172 * to do. 173 */ 174 env->msr = msr & env->msr_mask; 175 hreg_compute_hflags(env); 176 env->nip = vector; 177 /* Reset exception state */ 178 cs->exception_index = POWERPC_EXCP_NONE; 179 env->error_code = 0; 180 181 /* Reset the reservation */ 182 env->reserve_addr = -1; 183 184 /* 185 * Any interrupt is context synchronizing, check if TCG TLB needs 186 * a delayed flush on ppc64 187 */ 188 check_tlb_flush(env, false); 189 } 190 191 /* 192 * Note that this function should be greatly optimized when called 193 * with a constant excp, from ppc_hw_interrupt 194 */ 195 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) 196 { 197 CPUState *cs = CPU(cpu); 198 CPUPPCState *env = &cpu->env; 199 target_ulong msr, new_msr, vector; 200 int srr0, srr1, asrr0, asrr1, lev = -1, ail; 201 bool lpes0; 202 203 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx 204 " => %08x (%02x)\n", env->nip, excp, env->error_code); 205 206 /* new srr1 value excluding must-be-zero bits */ 207 if (excp_model == POWERPC_EXCP_BOOKE) { 208 msr = env->msr; 209 } else { 210 msr = env->msr & ~0x783f0000ULL; 211 } 212 213 /* 214 * new interrupt handler msr preserves existing HV and ME unless 215 * explicitly overriden 216 */ 217 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); 218 219 /* target registers */ 220 srr0 = SPR_SRR0; 221 srr1 = SPR_SRR1; 222 asrr0 = -1; 223 asrr1 = -1; 224 225 /* 226 * check for special resume at 0x100 from doze/nap/sleep/winkle on 227 * P7/P8/P9 228 */ 229 if (env->resume_as_sreset) { 230 excp = powerpc_reset_wakeup(cs, env, excp, &msr); 231 } 232 233 /* 234 * Exception targeting modifiers 235 * 236 * LPES0 is supported on POWER7/8/9 237 * LPES1 is not supported (old iSeries mode) 238 * 239 * On anything else, we behave as if LPES0 is 1 240 * (externals don't alter MSR:HV) 241 * 242 * AIL is initialized here but can be cleared by 243 * selected exceptions 244 */ 245 #if defined(TARGET_PPC64) 246 if (excp_model == POWERPC_EXCP_POWER7 || 247 excp_model == POWERPC_EXCP_POWER8 || 248 excp_model == POWERPC_EXCP_POWER9) { 249 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 250 if (excp_model != POWERPC_EXCP_POWER7) { 251 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 252 } else { 253 ail = 0; 254 } 255 } else 256 #endif /* defined(TARGET_PPC64) */ 257 { 258 lpes0 = true; 259 ail = 0; 260 } 261 262 /* 263 * Hypervisor emulation assistance interrupt only exists on server 264 * arch 2.05 server or later. We also don't want to generate it if 265 * we don't have HVB in msr_mask (PAPR mode). 266 */ 267 if (excp == POWERPC_EXCP_HV_EMU 268 #if defined(TARGET_PPC64) 269 && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB)) 270 #endif /* defined(TARGET_PPC64) */ 271 272 ) { 273 excp = POWERPC_EXCP_PROGRAM; 274 } 275 276 switch (excp) { 277 case POWERPC_EXCP_NONE: 278 /* Should never happen */ 279 return; 280 case POWERPC_EXCP_CRITICAL: /* Critical input */ 281 switch (excp_model) { 282 case POWERPC_EXCP_40x: 283 srr0 = SPR_40x_SRR2; 284 srr1 = SPR_40x_SRR3; 285 break; 286 case POWERPC_EXCP_BOOKE: 287 srr0 = SPR_BOOKE_CSRR0; 288 srr1 = SPR_BOOKE_CSRR1; 289 break; 290 case POWERPC_EXCP_G2: 291 break; 292 default: 293 goto excp_invalid; 294 } 295 break; 296 case POWERPC_EXCP_MCHECK: /* Machine check exception */ 297 if (msr_me == 0) { 298 /* 299 * Machine check exception is not enabled. Enter 300 * checkstop state. 301 */ 302 fprintf(stderr, "Machine check while not allowed. " 303 "Entering checkstop state\n"); 304 if (qemu_log_separate()) { 305 qemu_log("Machine check while not allowed. " 306 "Entering checkstop state\n"); 307 } 308 cs->halted = 1; 309 cpu_interrupt_exittb(cs); 310 } 311 if (env->msr_mask & MSR_HVB) { 312 /* 313 * ISA specifies HV, but can be delivered to guest with HV 314 * clear (e.g., see FWNMI in PAPR). 315 */ 316 new_msr |= (target_ulong)MSR_HVB; 317 } 318 ail = 0; 319 320 /* machine check exceptions don't have ME set */ 321 new_msr &= ~((target_ulong)1 << MSR_ME); 322 323 /* XXX: should also have something loaded in DAR / DSISR */ 324 switch (excp_model) { 325 case POWERPC_EXCP_40x: 326 srr0 = SPR_40x_SRR2; 327 srr1 = SPR_40x_SRR3; 328 break; 329 case POWERPC_EXCP_BOOKE: 330 /* FIXME: choose one or the other based on CPU type */ 331 srr0 = SPR_BOOKE_MCSRR0; 332 srr1 = SPR_BOOKE_MCSRR1; 333 asrr0 = SPR_BOOKE_CSRR0; 334 asrr1 = SPR_BOOKE_CSRR1; 335 break; 336 default: 337 break; 338 } 339 break; 340 case POWERPC_EXCP_DSI: /* Data storage exception */ 341 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx 342 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); 343 break; 344 case POWERPC_EXCP_ISI: /* Instruction storage exception */ 345 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx 346 "\n", msr, env->nip); 347 msr |= env->error_code; 348 break; 349 case POWERPC_EXCP_EXTERNAL: /* External input */ 350 cs = CPU(cpu); 351 352 if (!lpes0) { 353 new_msr |= (target_ulong)MSR_HVB; 354 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 355 srr0 = SPR_HSRR0; 356 srr1 = SPR_HSRR1; 357 } 358 if (env->mpic_proxy) { 359 /* IACK the IRQ on delivery */ 360 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); 361 } 362 break; 363 case POWERPC_EXCP_ALIGN: /* Alignment exception */ 364 /* Get rS/rD and rA from faulting opcode */ 365 /* 366 * Note: the opcode fields will not be set properly for a 367 * direct store load/store, but nobody cares as nobody 368 * actually uses direct store segments. 369 */ 370 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 371 break; 372 case POWERPC_EXCP_PROGRAM: /* Program exception */ 373 switch (env->error_code & ~0xF) { 374 case POWERPC_EXCP_FP: 375 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { 376 LOG_EXCP("Ignore floating point exception\n"); 377 cs->exception_index = POWERPC_EXCP_NONE; 378 env->error_code = 0; 379 return; 380 } 381 382 /* 383 * FP exceptions always have NIP pointing to the faulting 384 * instruction, so always use store_next and claim we are 385 * precise in the MSR. 386 */ 387 msr |= 0x00100000; 388 env->spr[SPR_BOOKE_ESR] = ESR_FP; 389 break; 390 case POWERPC_EXCP_INVAL: 391 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); 392 msr |= 0x00080000; 393 env->spr[SPR_BOOKE_ESR] = ESR_PIL; 394 break; 395 case POWERPC_EXCP_PRIV: 396 msr |= 0x00040000; 397 env->spr[SPR_BOOKE_ESR] = ESR_PPR; 398 break; 399 case POWERPC_EXCP_TRAP: 400 msr |= 0x00020000; 401 env->spr[SPR_BOOKE_ESR] = ESR_PTR; 402 break; 403 default: 404 /* Should never occur */ 405 cpu_abort(cs, "Invalid program exception %d. Aborting\n", 406 env->error_code); 407 break; 408 } 409 break; 410 case POWERPC_EXCP_SYSCALL: /* System call exception */ 411 lev = env->error_code; 412 413 if ((lev == 1) && cpu->vhyp) { 414 dump_hcall(env); 415 } else { 416 dump_syscall(env); 417 } 418 419 /* 420 * We need to correct the NIP which in this case is supposed 421 * to point to the next instruction 422 */ 423 env->nip += 4; 424 425 /* "PAPR mode" built-in hypercall emulation */ 426 if ((lev == 1) && cpu->vhyp) { 427 PPCVirtualHypervisorClass *vhc = 428 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 429 vhc->hypercall(cpu->vhyp, cpu); 430 return; 431 } 432 if (lev == 1) { 433 new_msr |= (target_ulong)MSR_HVB; 434 } 435 break; 436 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ 437 lev = env->error_code; 438 dump_syscall_vectored(env); 439 env->nip += 4; 440 new_msr |= env->msr & ((target_ulong)1 << MSR_EE); 441 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 442 break; 443 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 444 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 445 case POWERPC_EXCP_DECR: /* Decrementer exception */ 446 break; 447 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 448 /* FIT on 4xx */ 449 LOG_EXCP("FIT exception\n"); 450 break; 451 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 452 LOG_EXCP("WDT exception\n"); 453 switch (excp_model) { 454 case POWERPC_EXCP_BOOKE: 455 srr0 = SPR_BOOKE_CSRR0; 456 srr1 = SPR_BOOKE_CSRR1; 457 break; 458 default: 459 break; 460 } 461 break; 462 case POWERPC_EXCP_DTLB: /* Data TLB error */ 463 case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 464 break; 465 case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 466 if (env->flags & POWERPC_FLAG_DE) { 467 /* FIXME: choose one or the other based on CPU type */ 468 srr0 = SPR_BOOKE_DSRR0; 469 srr1 = SPR_BOOKE_DSRR1; 470 asrr0 = SPR_BOOKE_CSRR0; 471 asrr1 = SPR_BOOKE_CSRR1; 472 /* DBSR already modified by caller */ 473 } else { 474 cpu_abort(cs, "Debug exception triggered on unsupported model\n"); 475 } 476 break; 477 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ 478 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 479 break; 480 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ 481 /* XXX: TODO */ 482 cpu_abort(cs, "Embedded floating point data exception " 483 "is not implemented yet !\n"); 484 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 485 break; 486 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ 487 /* XXX: TODO */ 488 cpu_abort(cs, "Embedded floating point round exception " 489 "is not implemented yet !\n"); 490 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 491 break; 492 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ 493 /* XXX: TODO */ 494 cpu_abort(cs, 495 "Performance counter exception is not implemented yet !\n"); 496 break; 497 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 498 break; 499 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 500 srr0 = SPR_BOOKE_CSRR0; 501 srr1 = SPR_BOOKE_CSRR1; 502 break; 503 case POWERPC_EXCP_RESET: /* System reset exception */ 504 /* A power-saving exception sets ME, otherwise it is unchanged */ 505 if (msr_pow) { 506 /* indicate that we resumed from power save mode */ 507 msr |= 0x10000; 508 new_msr |= ((target_ulong)1 << MSR_ME); 509 } 510 if (env->msr_mask & MSR_HVB) { 511 /* 512 * ISA specifies HV, but can be delivered to guest with HV 513 * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). 514 */ 515 new_msr |= (target_ulong)MSR_HVB; 516 } else { 517 if (msr_pow) { 518 cpu_abort(cs, "Trying to deliver power-saving system reset " 519 "exception %d with no HV support\n", excp); 520 } 521 } 522 ail = 0; 523 break; 524 case POWERPC_EXCP_DSEG: /* Data segment exception */ 525 case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 526 case POWERPC_EXCP_TRACE: /* Trace exception */ 527 break; 528 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ 529 msr |= env->error_code; 530 /* fall through */ 531 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 532 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 533 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 534 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ 535 case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ 536 case POWERPC_EXCP_HV_EMU: 537 case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ 538 srr0 = SPR_HSRR0; 539 srr1 = SPR_HSRR1; 540 new_msr |= (target_ulong)MSR_HVB; 541 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 542 break; 543 case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 544 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ 545 case POWERPC_EXCP_FU: /* Facility unavailable exception */ 546 #ifdef TARGET_PPC64 547 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); 548 #endif 549 break; 550 case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ 551 #ifdef TARGET_PPC64 552 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); 553 srr0 = SPR_HSRR0; 554 srr1 = SPR_HSRR1; 555 new_msr |= (target_ulong)MSR_HVB; 556 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 557 #endif 558 break; 559 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ 560 LOG_EXCP("PIT exception\n"); 561 break; 562 case POWERPC_EXCP_IO: /* IO error exception */ 563 /* XXX: TODO */ 564 cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); 565 break; 566 case POWERPC_EXCP_RUNM: /* Run mode exception */ 567 /* XXX: TODO */ 568 cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); 569 break; 570 case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 571 /* XXX: TODO */ 572 cpu_abort(cs, "602 emulation trap exception " 573 "is not implemented yet !\n"); 574 break; 575 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 576 switch (excp_model) { 577 case POWERPC_EXCP_602: 578 case POWERPC_EXCP_603: 579 case POWERPC_EXCP_603E: 580 case POWERPC_EXCP_G2: 581 goto tlb_miss_tgpr; 582 case POWERPC_EXCP_7x5: 583 goto tlb_miss; 584 case POWERPC_EXCP_74xx: 585 goto tlb_miss_74xx; 586 default: 587 cpu_abort(cs, "Invalid instruction TLB miss exception\n"); 588 break; 589 } 590 break; 591 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 592 switch (excp_model) { 593 case POWERPC_EXCP_602: 594 case POWERPC_EXCP_603: 595 case POWERPC_EXCP_603E: 596 case POWERPC_EXCP_G2: 597 goto tlb_miss_tgpr; 598 case POWERPC_EXCP_7x5: 599 goto tlb_miss; 600 case POWERPC_EXCP_74xx: 601 goto tlb_miss_74xx; 602 default: 603 cpu_abort(cs, "Invalid data load TLB miss exception\n"); 604 break; 605 } 606 break; 607 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 608 switch (excp_model) { 609 case POWERPC_EXCP_602: 610 case POWERPC_EXCP_603: 611 case POWERPC_EXCP_603E: 612 case POWERPC_EXCP_G2: 613 tlb_miss_tgpr: 614 /* Swap temporary saved registers with GPRs */ 615 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { 616 new_msr |= (target_ulong)1 << MSR_TGPR; 617 hreg_swap_gpr_tgpr(env); 618 } 619 goto tlb_miss; 620 case POWERPC_EXCP_7x5: 621 tlb_miss: 622 #if defined(DEBUG_SOFTWARE_TLB) 623 if (qemu_log_enabled()) { 624 const char *es; 625 target_ulong *miss, *cmp; 626 int en; 627 628 if (excp == POWERPC_EXCP_IFTLB) { 629 es = "I"; 630 en = 'I'; 631 miss = &env->spr[SPR_IMISS]; 632 cmp = &env->spr[SPR_ICMP]; 633 } else { 634 if (excp == POWERPC_EXCP_DLTLB) { 635 es = "DL"; 636 } else { 637 es = "DS"; 638 } 639 en = 'D'; 640 miss = &env->spr[SPR_DMISS]; 641 cmp = &env->spr[SPR_DCMP]; 642 } 643 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 644 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " 645 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 646 env->spr[SPR_HASH1], env->spr[SPR_HASH2], 647 env->error_code); 648 } 649 #endif 650 msr |= env->crf[0] << 28; 651 msr |= env->error_code; /* key, D/I, S/L bits */ 652 /* Set way using a LRU mechanism */ 653 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 654 break; 655 case POWERPC_EXCP_74xx: 656 tlb_miss_74xx: 657 #if defined(DEBUG_SOFTWARE_TLB) 658 if (qemu_log_enabled()) { 659 const char *es; 660 target_ulong *miss, *cmp; 661 int en; 662 663 if (excp == POWERPC_EXCP_IFTLB) { 664 es = "I"; 665 en = 'I'; 666 miss = &env->spr[SPR_TLBMISS]; 667 cmp = &env->spr[SPR_PTEHI]; 668 } else { 669 if (excp == POWERPC_EXCP_DLTLB) { 670 es = "DL"; 671 } else { 672 es = "DS"; 673 } 674 en = 'D'; 675 miss = &env->spr[SPR_TLBMISS]; 676 cmp = &env->spr[SPR_PTEHI]; 677 } 678 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 679 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 680 env->error_code); 681 } 682 #endif 683 msr |= env->error_code; /* key bit */ 684 break; 685 default: 686 cpu_abort(cs, "Invalid data store TLB miss exception\n"); 687 break; 688 } 689 break; 690 case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 691 /* XXX: TODO */ 692 cpu_abort(cs, "Floating point assist exception " 693 "is not implemented yet !\n"); 694 break; 695 case POWERPC_EXCP_DABR: /* Data address breakpoint */ 696 /* XXX: TODO */ 697 cpu_abort(cs, "DABR exception is not implemented yet !\n"); 698 break; 699 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 700 /* XXX: TODO */ 701 cpu_abort(cs, "IABR exception is not implemented yet !\n"); 702 break; 703 case POWERPC_EXCP_SMI: /* System management interrupt */ 704 /* XXX: TODO */ 705 cpu_abort(cs, "SMI exception is not implemented yet !\n"); 706 break; 707 case POWERPC_EXCP_THERM: /* Thermal interrupt */ 708 /* XXX: TODO */ 709 cpu_abort(cs, "Thermal management exception " 710 "is not implemented yet !\n"); 711 break; 712 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 713 /* XXX: TODO */ 714 cpu_abort(cs, 715 "Performance counter exception is not implemented yet !\n"); 716 break; 717 case POWERPC_EXCP_VPUA: /* Vector assist exception */ 718 /* XXX: TODO */ 719 cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); 720 break; 721 case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 722 /* XXX: TODO */ 723 cpu_abort(cs, 724 "970 soft-patch exception is not implemented yet !\n"); 725 break; 726 case POWERPC_EXCP_MAINT: /* Maintenance exception */ 727 /* XXX: TODO */ 728 cpu_abort(cs, 729 "970 maintenance exception is not implemented yet !\n"); 730 break; 731 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ 732 /* XXX: TODO */ 733 cpu_abort(cs, "Maskable external exception " 734 "is not implemented yet !\n"); 735 break; 736 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ 737 /* XXX: TODO */ 738 cpu_abort(cs, "Non maskable external exception " 739 "is not implemented yet !\n"); 740 break; 741 default: 742 excp_invalid: 743 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 744 break; 745 } 746 747 /* Sanity check */ 748 if (!(env->msr_mask & MSR_HVB)) { 749 if (new_msr & MSR_HVB) { 750 cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " 751 "no HV support\n", excp); 752 } 753 if (srr0 == SPR_HSRR0) { 754 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " 755 "no HV support\n", excp); 756 } 757 } 758 759 /* 760 * Sort out endianness of interrupt, this differs depending on the 761 * CPU, the HV mode, etc... 762 */ 763 #ifdef TARGET_PPC64 764 if (excp_model == POWERPC_EXCP_POWER7) { 765 if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { 766 new_msr |= (target_ulong)1 << MSR_LE; 767 } 768 } else if (excp_model == POWERPC_EXCP_POWER8) { 769 if (new_msr & MSR_HVB) { 770 if (env->spr[SPR_HID0] & HID0_HILE) { 771 new_msr |= (target_ulong)1 << MSR_LE; 772 } 773 } else if (env->spr[SPR_LPCR] & LPCR_ILE) { 774 new_msr |= (target_ulong)1 << MSR_LE; 775 } 776 } else if (excp_model == POWERPC_EXCP_POWER9) { 777 if (new_msr & MSR_HVB) { 778 if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { 779 new_msr |= (target_ulong)1 << MSR_LE; 780 } 781 } else if (env->spr[SPR_LPCR] & LPCR_ILE) { 782 new_msr |= (target_ulong)1 << MSR_LE; 783 } 784 } else if (msr_ile) { 785 new_msr |= (target_ulong)1 << MSR_LE; 786 } 787 #else 788 if (msr_ile) { 789 new_msr |= (target_ulong)1 << MSR_LE; 790 } 791 #endif 792 793 /* 794 * AIL only works if there is no HV transition and we are running 795 * with translations enabled 796 */ 797 if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) || 798 ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { 799 ail = 0; 800 } 801 802 vector = env->excp_vectors[excp]; 803 if (vector == (target_ulong)-1ULL) { 804 cpu_abort(cs, "Raised an exception without defined vector %d\n", 805 excp); 806 } 807 808 vector |= env->excp_prefix; 809 810 /* If any alternate SRR register are defined, duplicate saved values */ 811 if (asrr0 != -1) { 812 env->spr[asrr0] = env->nip; 813 } 814 if (asrr1 != -1) { 815 env->spr[asrr1] = msr; 816 } 817 818 #if defined(TARGET_PPC64) 819 if (excp_model == POWERPC_EXCP_BOOKE) { 820 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { 821 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ 822 new_msr |= (target_ulong)1 << MSR_CM; 823 } else { 824 vector = (uint32_t)vector; 825 } 826 } else { 827 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) { 828 vector = (uint32_t)vector; 829 } else { 830 new_msr |= (target_ulong)1 << MSR_SF; 831 } 832 } 833 #endif 834 835 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { 836 /* Save PC */ 837 env->spr[srr0] = env->nip; 838 839 /* Save MSR */ 840 env->spr[srr1] = msr; 841 842 /* Handle AIL */ 843 if (ail) { 844 new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 845 vector |= ppc_excp_vector_offset(cs, ail); 846 } 847 848 #if defined(TARGET_PPC64) 849 } else { 850 /* scv AIL is a little different */ 851 if (ail) { 852 new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 853 } 854 if (ail == AIL_C000_0000_0000_4000) { 855 vector |= 0xc000000000003000ull; 856 } else { 857 vector |= 0x0000000000017000ull; 858 } 859 vector += lev * 0x20; 860 861 env->lr = env->nip; 862 env->ctr = msr; 863 #endif 864 } 865 866 powerpc_set_excp_state(cpu, vector, new_msr); 867 } 868 869 void ppc_cpu_do_interrupt(CPUState *cs) 870 { 871 PowerPCCPU *cpu = POWERPC_CPU(cs); 872 CPUPPCState *env = &cpu->env; 873 874 powerpc_excp(cpu, env->excp_model, cs->exception_index); 875 } 876 877 static void ppc_hw_interrupt(CPUPPCState *env) 878 { 879 PowerPCCPU *cpu = env_archcpu(env); 880 bool async_deliver; 881 882 /* External reset */ 883 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { 884 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); 885 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 886 return; 887 } 888 /* Machine check exception */ 889 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { 890 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); 891 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); 892 return; 893 } 894 #if 0 /* TODO */ 895 /* External debug exception */ 896 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { 897 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); 898 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); 899 return; 900 } 901 #endif 902 903 /* 904 * For interrupts that gate on MSR:EE, we need to do something a 905 * bit more subtle, as we need to let them through even when EE is 906 * clear when coming out of some power management states (in order 907 * for them to become a 0x100). 908 */ 909 async_deliver = (msr_ee != 0) || env->resume_as_sreset; 910 911 /* Hypervisor decrementer exception */ 912 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { 913 /* LPCR will be clear when not supported so this will work */ 914 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); 915 if ((async_deliver || msr_hv == 0) && hdice) { 916 /* HDEC clears on delivery */ 917 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 918 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); 919 return; 920 } 921 } 922 923 /* Hypervisor virtualization interrupt */ 924 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { 925 /* LPCR will be clear when not supported so this will work */ 926 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); 927 if ((async_deliver || msr_hv == 0) && hvice) { 928 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); 929 return; 930 } 931 } 932 933 /* External interrupt can ignore MSR:EE under some circumstances */ 934 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { 935 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 936 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); 937 /* HEIC blocks delivery to the hypervisor */ 938 if ((async_deliver && !(heic && msr_hv && !msr_pr)) || 939 (env->has_hv_mode && msr_hv == 0 && !lpes0)) { 940 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); 941 return; 942 } 943 } 944 if (msr_ce != 0) { 945 /* External critical interrupt */ 946 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { 947 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); 948 return; 949 } 950 } 951 if (async_deliver != 0) { 952 /* Watchdog timer on embedded PowerPC */ 953 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { 954 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); 955 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); 956 return; 957 } 958 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { 959 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); 960 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); 961 return; 962 } 963 /* Fixed interval timer on embedded PowerPC */ 964 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { 965 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); 966 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); 967 return; 968 } 969 /* Programmable interval timer on embedded PowerPC */ 970 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { 971 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); 972 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); 973 return; 974 } 975 /* Decrementer exception */ 976 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { 977 if (ppc_decr_clear_on_delivery(env)) { 978 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); 979 } 980 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); 981 return; 982 } 983 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { 984 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 985 if (is_book3s_arch2x(env)) { 986 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR); 987 } else { 988 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); 989 } 990 return; 991 } 992 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) { 993 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 994 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV); 995 return; 996 } 997 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { 998 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); 999 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); 1000 return; 1001 } 1002 /* Thermal interrupt */ 1003 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { 1004 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); 1005 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); 1006 return; 1007 } 1008 } 1009 1010 if (env->resume_as_sreset) { 1011 /* 1012 * This is a bug ! It means that has_work took us out of halt without 1013 * anything to deliver while in a PM state that requires getting 1014 * out via a 0x100 1015 * 1016 * This means we will incorrectly execute past the power management 1017 * instruction instead of triggering a reset. 1018 * 1019 * It generally means a discrepancy between the wakeup conditions in the 1020 * processor has_work implementation and the logic in this function. 1021 */ 1022 cpu_abort(env_cpu(env), 1023 "Wakeup from PM state but interrupt Undelivered"); 1024 } 1025 } 1026 1027 void ppc_cpu_do_system_reset(CPUState *cs) 1028 { 1029 PowerPCCPU *cpu = POWERPC_CPU(cs); 1030 CPUPPCState *env = &cpu->env; 1031 1032 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 1033 } 1034 1035 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) 1036 { 1037 PowerPCCPU *cpu = POWERPC_CPU(cs); 1038 CPUPPCState *env = &cpu->env; 1039 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); 1040 target_ulong msr = 0; 1041 1042 /* 1043 * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already 1044 * been set by KVM. 1045 */ 1046 msr = (1ULL << MSR_ME); 1047 msr |= env->msr & (1ULL << MSR_SF); 1048 if (!(*pcc->interrupts_big_endian)(cpu)) { 1049 msr |= (1ULL << MSR_LE); 1050 } 1051 1052 powerpc_set_excp_state(cpu, vector, msr); 1053 } 1054 #endif /* !CONFIG_USER_ONLY */ 1055 1056 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 1057 { 1058 PowerPCCPU *cpu = POWERPC_CPU(cs); 1059 CPUPPCState *env = &cpu->env; 1060 1061 if (interrupt_request & CPU_INTERRUPT_HARD) { 1062 ppc_hw_interrupt(env); 1063 if (env->pending_interrupts == 0) { 1064 cs->interrupt_request &= ~CPU_INTERRUPT_HARD; 1065 } 1066 return true; 1067 } 1068 return false; 1069 } 1070 1071 #if defined(DEBUG_OP) 1072 static void cpu_dump_rfi(target_ulong RA, target_ulong msr) 1073 { 1074 qemu_log("Return from exception at " TARGET_FMT_lx " with flags " 1075 TARGET_FMT_lx "\n", RA, msr); 1076 } 1077 #endif 1078 1079 /*****************************************************************************/ 1080 /* Exceptions processing helpers */ 1081 1082 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception, 1083 uint32_t error_code, uintptr_t raddr) 1084 { 1085 CPUState *cs = env_cpu(env); 1086 1087 cs->exception_index = exception; 1088 env->error_code = error_code; 1089 cpu_loop_exit_restore(cs, raddr); 1090 } 1091 1092 void raise_exception_err(CPUPPCState *env, uint32_t exception, 1093 uint32_t error_code) 1094 { 1095 raise_exception_err_ra(env, exception, error_code, 0); 1096 } 1097 1098 void raise_exception(CPUPPCState *env, uint32_t exception) 1099 { 1100 raise_exception_err_ra(env, exception, 0, 0); 1101 } 1102 1103 void raise_exception_ra(CPUPPCState *env, uint32_t exception, 1104 uintptr_t raddr) 1105 { 1106 raise_exception_err_ra(env, exception, 0, raddr); 1107 } 1108 1109 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception, 1110 uint32_t error_code) 1111 { 1112 raise_exception_err_ra(env, exception, error_code, 0); 1113 } 1114 1115 void helper_raise_exception(CPUPPCState *env, uint32_t exception) 1116 { 1117 raise_exception_err_ra(env, exception, 0, 0); 1118 } 1119 1120 #if !defined(CONFIG_USER_ONLY) 1121 void helper_store_msr(CPUPPCState *env, target_ulong val) 1122 { 1123 uint32_t excp = hreg_store_msr(env, val, 0); 1124 1125 if (excp != 0) { 1126 CPUState *cs = env_cpu(env); 1127 cpu_interrupt_exittb(cs); 1128 raise_exception(env, excp); 1129 } 1130 } 1131 1132 #if defined(TARGET_PPC64) 1133 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) 1134 { 1135 CPUState *cs; 1136 1137 cs = env_cpu(env); 1138 cs->halted = 1; 1139 1140 /* 1141 * The architecture specifies that HDEC interrupts are discarded 1142 * in PM states 1143 */ 1144 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 1145 1146 /* Condition for waking up at 0x100 */ 1147 env->resume_as_sreset = (insn != PPC_PM_STOP) || 1148 (env->spr[SPR_PSSCR] & PSSCR_EC); 1149 } 1150 #endif /* defined(TARGET_PPC64) */ 1151 1152 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) 1153 { 1154 CPUState *cs = env_cpu(env); 1155 1156 /* MSR:POW cannot be set by any form of rfi */ 1157 msr &= ~(1ULL << MSR_POW); 1158 1159 #if defined(TARGET_PPC64) 1160 /* Switching to 32-bit ? Crop the nip */ 1161 if (!msr_is_64bit(env, msr)) { 1162 nip = (uint32_t)nip; 1163 } 1164 #else 1165 nip = (uint32_t)nip; 1166 #endif 1167 /* XXX: beware: this is false if VLE is supported */ 1168 env->nip = nip & ~((target_ulong)0x00000003); 1169 hreg_store_msr(env, msr, 1); 1170 #if defined(DEBUG_OP) 1171 cpu_dump_rfi(env->nip, env->msr); 1172 #endif 1173 /* 1174 * No need to raise an exception here, as rfi is always the last 1175 * insn of a TB 1176 */ 1177 cpu_interrupt_exittb(cs); 1178 /* Reset the reservation */ 1179 env->reserve_addr = -1; 1180 1181 /* Context synchronizing: check if TCG TLB needs flush */ 1182 check_tlb_flush(env, false); 1183 } 1184 1185 void helper_rfi(CPUPPCState *env) 1186 { 1187 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); 1188 } 1189 1190 #define MSR_BOOK3S_MASK 1191 #if defined(TARGET_PPC64) 1192 void helper_rfid(CPUPPCState *env) 1193 { 1194 /* 1195 * The architecture defines a number of rules for which bits can 1196 * change but in practice, we handle this in hreg_store_msr() 1197 * which will be called by do_rfi(), so there is no need to filter 1198 * here 1199 */ 1200 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); 1201 } 1202 1203 void helper_rfscv(CPUPPCState *env) 1204 { 1205 do_rfi(env, env->lr, env->ctr); 1206 } 1207 1208 void helper_hrfid(CPUPPCState *env) 1209 { 1210 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); 1211 } 1212 #endif 1213 1214 /*****************************************************************************/ 1215 /* Embedded PowerPC specific helpers */ 1216 void helper_40x_rfci(CPUPPCState *env) 1217 { 1218 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]); 1219 } 1220 1221 void helper_rfci(CPUPPCState *env) 1222 { 1223 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]); 1224 } 1225 1226 void helper_rfdi(CPUPPCState *env) 1227 { 1228 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */ 1229 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]); 1230 } 1231 1232 void helper_rfmci(CPUPPCState *env) 1233 { 1234 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */ 1235 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]); 1236 } 1237 #endif 1238 1239 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1240 uint32_t flags) 1241 { 1242 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) || 1243 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) || 1244 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) || 1245 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) || 1246 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) { 1247 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1248 POWERPC_EXCP_TRAP, GETPC()); 1249 } 1250 } 1251 1252 #if defined(TARGET_PPC64) 1253 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1254 uint32_t flags) 1255 { 1256 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) || 1257 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) || 1258 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) || 1259 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) || 1260 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) { 1261 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1262 POWERPC_EXCP_TRAP, GETPC()); 1263 } 1264 } 1265 #endif 1266 1267 #if !defined(CONFIG_USER_ONLY) 1268 /*****************************************************************************/ 1269 /* PowerPC 601 specific instructions (POWER bridge) */ 1270 1271 void helper_rfsvc(CPUPPCState *env) 1272 { 1273 do_rfi(env, env->lr, env->ctr & 0x0000FFFF); 1274 } 1275 1276 /* Embedded.Processor Control */ 1277 static int dbell2irq(target_ulong rb) 1278 { 1279 int msg = rb & DBELL_TYPE_MASK; 1280 int irq = -1; 1281 1282 switch (msg) { 1283 case DBELL_TYPE_DBELL: 1284 irq = PPC_INTERRUPT_DOORBELL; 1285 break; 1286 case DBELL_TYPE_DBELL_CRIT: 1287 irq = PPC_INTERRUPT_CDOORBELL; 1288 break; 1289 case DBELL_TYPE_G_DBELL: 1290 case DBELL_TYPE_G_DBELL_CRIT: 1291 case DBELL_TYPE_G_DBELL_MC: 1292 /* XXX implement */ 1293 default: 1294 break; 1295 } 1296 1297 return irq; 1298 } 1299 1300 void helper_msgclr(CPUPPCState *env, target_ulong rb) 1301 { 1302 int irq = dbell2irq(rb); 1303 1304 if (irq < 0) { 1305 return; 1306 } 1307 1308 env->pending_interrupts &= ~(1 << irq); 1309 } 1310 1311 void helper_msgsnd(target_ulong rb) 1312 { 1313 int irq = dbell2irq(rb); 1314 int pir = rb & DBELL_PIRTAG_MASK; 1315 CPUState *cs; 1316 1317 if (irq < 0) { 1318 return; 1319 } 1320 1321 qemu_mutex_lock_iothread(); 1322 CPU_FOREACH(cs) { 1323 PowerPCCPU *cpu = POWERPC_CPU(cs); 1324 CPUPPCState *cenv = &cpu->env; 1325 1326 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { 1327 cenv->pending_interrupts |= 1 << irq; 1328 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 1329 } 1330 } 1331 qemu_mutex_unlock_iothread(); 1332 } 1333 1334 /* Server Processor Control */ 1335 1336 static bool dbell_type_server(target_ulong rb) 1337 { 1338 /* 1339 * A Directed Hypervisor Doorbell message is sent only if the 1340 * message type is 5. All other types are reserved and the 1341 * instruction is a no-op 1342 */ 1343 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER; 1344 } 1345 1346 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb) 1347 { 1348 if (!dbell_type_server(rb)) { 1349 return; 1350 } 1351 1352 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 1353 } 1354 1355 static void book3s_msgsnd_common(int pir, int irq) 1356 { 1357 CPUState *cs; 1358 1359 qemu_mutex_lock_iothread(); 1360 CPU_FOREACH(cs) { 1361 PowerPCCPU *cpu = POWERPC_CPU(cs); 1362 CPUPPCState *cenv = &cpu->env; 1363 1364 /* TODO: broadcast message to all threads of the same processor */ 1365 if (cenv->spr_cb[SPR_PIR].default_value == pir) { 1366 cenv->pending_interrupts |= 1 << irq; 1367 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 1368 } 1369 } 1370 qemu_mutex_unlock_iothread(); 1371 } 1372 1373 void helper_book3s_msgsnd(target_ulong rb) 1374 { 1375 int pir = rb & DBELL_PROCIDTAG_MASK; 1376 1377 if (!dbell_type_server(rb)) { 1378 return; 1379 } 1380 1381 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL); 1382 } 1383 1384 #if defined(TARGET_PPC64) 1385 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb) 1386 { 1387 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP); 1388 1389 if (!dbell_type_server(rb)) { 1390 return; 1391 } 1392 1393 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 1394 } 1395 1396 /* 1397 * sends a message to other threads that are on the same 1398 * multi-threaded processor 1399 */ 1400 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) 1401 { 1402 int pir = env->spr_cb[SPR_PIR].default_value; 1403 1404 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); 1405 1406 if (!dbell_type_server(rb)) { 1407 return; 1408 } 1409 1410 /* TODO: TCG supports only one thread */ 1411 1412 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL); 1413 } 1414 #endif 1415 #endif 1416 1417 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, 1418 MMUAccessType access_type, 1419 int mmu_idx, uintptr_t retaddr) 1420 { 1421 CPUPPCState *env = cs->env_ptr; 1422 uint32_t insn; 1423 1424 /* Restore state and reload the insn we executed, for filling in DSISR. */ 1425 cpu_restore_state(cs, retaddr, true); 1426 insn = cpu_ldl_code(env, env->nip); 1427 1428 cs->exception_index = POWERPC_EXCP_ALIGN; 1429 env->error_code = insn & 0x03FF0000; 1430 cpu_loop_exit(cs); 1431 } 1432