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 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 "cpu.h" 21 #include "exec/helper-proto.h" 22 #include "exec/exec-all.h" 23 #include "exec/cpu_ldst.h" 24 25 #include "helper_regs.h" 26 27 //#define DEBUG_OP 28 //#define DEBUG_SOFTWARE_TLB 29 //#define DEBUG_EXCEPTIONS 30 31 #ifdef DEBUG_EXCEPTIONS 32 # define LOG_EXCP(...) qemu_log(__VA_ARGS__) 33 #else 34 # define LOG_EXCP(...) do { } while (0) 35 #endif 36 37 /*****************************************************************************/ 38 /* Exception processing */ 39 #if defined(CONFIG_USER_ONLY) 40 void ppc_cpu_do_interrupt(CPUState *cs) 41 { 42 PowerPCCPU *cpu = POWERPC_CPU(cs); 43 CPUPPCState *env = &cpu->env; 44 45 cs->exception_index = POWERPC_EXCP_NONE; 46 env->error_code = 0; 47 } 48 49 static void ppc_hw_interrupt(CPUPPCState *env) 50 { 51 CPUState *cs = CPU(ppc_env_get_cpu(env)); 52 53 cs->exception_index = POWERPC_EXCP_NONE; 54 env->error_code = 0; 55 } 56 #else /* defined(CONFIG_USER_ONLY) */ 57 static inline void dump_syscall(CPUPPCState *env) 58 { 59 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64 60 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 61 " nip=" TARGET_FMT_lx "\n", 62 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), 63 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), 64 ppc_dump_gpr(env, 6), env->nip); 65 } 66 67 /* Note that this function should be greatly optimized 68 * when called with a constant excp, from ppc_hw_interrupt 69 */ 70 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) 71 { 72 CPUState *cs = CPU(cpu); 73 CPUPPCState *env = &cpu->env; 74 target_ulong msr, new_msr, vector; 75 int srr0, srr1, asrr0, asrr1, lev, ail; 76 bool lpes0; 77 78 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx 79 " => %08x (%02x)\n", env->nip, excp, env->error_code); 80 81 /* new srr1 value excluding must-be-zero bits */ 82 if (excp_model == POWERPC_EXCP_BOOKE) { 83 msr = env->msr; 84 } else { 85 msr = env->msr & ~0x783f0000ULL; 86 } 87 88 /* new interrupt handler msr preserves existing HV and ME unless 89 * explicitly overriden 90 */ 91 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); 92 93 /* target registers */ 94 srr0 = SPR_SRR0; 95 srr1 = SPR_SRR1; 96 asrr0 = -1; 97 asrr1 = -1; 98 99 /* check for special resume at 0x100 from doze/nap/sleep/winkle on P7/P8 */ 100 if (env->in_pm_state) { 101 env->in_pm_state = false; 102 103 /* Pretend to be returning from doze always as we don't lose state */ 104 msr |= (0x1ull << (63 - 47)); 105 106 /* Non-machine check are routed to 0x100 with a wakeup cause 107 * encoded in SRR1 108 */ 109 if (excp != POWERPC_EXCP_MCHECK) { 110 switch (excp) { 111 case POWERPC_EXCP_RESET: 112 msr |= 0x4ull << (63 - 45); 113 break; 114 case POWERPC_EXCP_EXTERNAL: 115 msr |= 0x8ull << (63 - 45); 116 break; 117 case POWERPC_EXCP_DECR: 118 msr |= 0x6ull << (63 - 45); 119 break; 120 case POWERPC_EXCP_SDOOR: 121 msr |= 0x5ull << (63 - 45); 122 break; 123 case POWERPC_EXCP_SDOOR_HV: 124 msr |= 0x3ull << (63 - 45); 125 break; 126 case POWERPC_EXCP_HV_MAINT: 127 msr |= 0xaull << (63 - 45); 128 break; 129 default: 130 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", 131 excp); 132 } 133 excp = POWERPC_EXCP_RESET; 134 } 135 } 136 137 /* Exception targetting modifiers 138 * 139 * LPES0 is supported on POWER7/8 140 * LPES1 is not supported (old iSeries mode) 141 * 142 * On anything else, we behave as if LPES0 is 1 143 * (externals don't alter MSR:HV) 144 * 145 * AIL is initialized here but can be cleared by 146 * selected exceptions 147 */ 148 #if defined(TARGET_PPC64) 149 if (excp_model == POWERPC_EXCP_POWER7 || 150 excp_model == POWERPC_EXCP_POWER8) { 151 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 152 if (excp_model == POWERPC_EXCP_POWER8) { 153 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 154 } else { 155 ail = 0; 156 } 157 } else 158 #endif /* defined(TARGET_PPC64) */ 159 { 160 lpes0 = true; 161 ail = 0; 162 } 163 164 /* Hypervisor emulation assistance interrupt only exists on server 165 * arch 2.05 server or later. We also don't want to generate it if 166 * we don't have HVB in msr_mask (PAPR mode). 167 */ 168 if (excp == POWERPC_EXCP_HV_EMU 169 #if defined(TARGET_PPC64) 170 && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB)) 171 #endif /* defined(TARGET_PPC64) */ 172 173 ) { 174 excp = POWERPC_EXCP_PROGRAM; 175 } 176 177 switch (excp) { 178 case POWERPC_EXCP_NONE: 179 /* Should never happen */ 180 return; 181 case POWERPC_EXCP_CRITICAL: /* Critical input */ 182 switch (excp_model) { 183 case POWERPC_EXCP_40x: 184 srr0 = SPR_40x_SRR2; 185 srr1 = SPR_40x_SRR3; 186 break; 187 case POWERPC_EXCP_BOOKE: 188 srr0 = SPR_BOOKE_CSRR0; 189 srr1 = SPR_BOOKE_CSRR1; 190 break; 191 case POWERPC_EXCP_G2: 192 break; 193 default: 194 goto excp_invalid; 195 } 196 break; 197 case POWERPC_EXCP_MCHECK: /* Machine check exception */ 198 if (msr_me == 0) { 199 /* Machine check exception is not enabled. 200 * Enter checkstop state. 201 */ 202 fprintf(stderr, "Machine check while not allowed. " 203 "Entering checkstop state\n"); 204 if (qemu_log_separate()) { 205 qemu_log("Machine check while not allowed. " 206 "Entering checkstop state\n"); 207 } 208 cs->halted = 1; 209 cs->interrupt_request |= CPU_INTERRUPT_EXITTB; 210 } 211 if (env->msr_mask & MSR_HVB) { 212 /* ISA specifies HV, but can be delivered to guest with HV clear 213 * (e.g., see FWNMI in PAPR). 214 */ 215 new_msr |= (target_ulong)MSR_HVB; 216 } 217 ail = 0; 218 219 /* machine check exceptions don't have ME set */ 220 new_msr &= ~((target_ulong)1 << MSR_ME); 221 222 /* XXX: should also have something loaded in DAR / DSISR */ 223 switch (excp_model) { 224 case POWERPC_EXCP_40x: 225 srr0 = SPR_40x_SRR2; 226 srr1 = SPR_40x_SRR3; 227 break; 228 case POWERPC_EXCP_BOOKE: 229 /* FIXME: choose one or the other based on CPU type */ 230 srr0 = SPR_BOOKE_MCSRR0; 231 srr1 = SPR_BOOKE_MCSRR1; 232 asrr0 = SPR_BOOKE_CSRR0; 233 asrr1 = SPR_BOOKE_CSRR1; 234 break; 235 default: 236 break; 237 } 238 break; 239 case POWERPC_EXCP_DSI: /* Data storage exception */ 240 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx 241 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); 242 break; 243 case POWERPC_EXCP_ISI: /* Instruction storage exception */ 244 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx 245 "\n", msr, env->nip); 246 msr |= env->error_code; 247 break; 248 case POWERPC_EXCP_EXTERNAL: /* External input */ 249 cs = CPU(cpu); 250 251 if (!lpes0) { 252 new_msr |= (target_ulong)MSR_HVB; 253 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 254 srr0 = SPR_HSRR0; 255 srr1 = SPR_HSRR1; 256 } 257 if (env->mpic_proxy) { 258 /* IACK the IRQ on delivery */ 259 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); 260 } 261 break; 262 case POWERPC_EXCP_ALIGN: /* Alignment exception */ 263 /* Get rS/rD and rA from faulting opcode */ 264 /* Note: the opcode fields will not be set properly for a direct 265 * store load/store, but nobody cares as nobody actually uses 266 * direct store segments. 267 */ 268 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 269 break; 270 case POWERPC_EXCP_PROGRAM: /* Program exception */ 271 switch (env->error_code & ~0xF) { 272 case POWERPC_EXCP_FP: 273 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { 274 LOG_EXCP("Ignore floating point exception\n"); 275 cs->exception_index = POWERPC_EXCP_NONE; 276 env->error_code = 0; 277 return; 278 } 279 280 /* FP exceptions always have NIP pointing to the faulting 281 * instruction, so always use store_next and claim we are 282 * precise in the MSR. 283 */ 284 msr |= 0x00100000; 285 break; 286 case POWERPC_EXCP_INVAL: 287 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); 288 msr |= 0x00080000; 289 env->spr[SPR_BOOKE_ESR] = ESR_PIL; 290 break; 291 case POWERPC_EXCP_PRIV: 292 msr |= 0x00040000; 293 env->spr[SPR_BOOKE_ESR] = ESR_PPR; 294 break; 295 case POWERPC_EXCP_TRAP: 296 msr |= 0x00020000; 297 env->spr[SPR_BOOKE_ESR] = ESR_PTR; 298 break; 299 default: 300 /* Should never occur */ 301 cpu_abort(cs, "Invalid program exception %d. Aborting\n", 302 env->error_code); 303 break; 304 } 305 break; 306 case POWERPC_EXCP_SYSCALL: /* System call exception */ 307 dump_syscall(env); 308 lev = env->error_code; 309 310 /* We need to correct the NIP which in this case is supposed 311 * to point to the next instruction 312 */ 313 env->nip += 4; 314 315 /* "PAPR mode" built-in hypercall emulation */ 316 if ((lev == 1) && cpu->vhyp) { 317 PPCVirtualHypervisorClass *vhc = 318 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 319 vhc->hypercall(cpu->vhyp, cpu); 320 return; 321 } 322 if (lev == 1) { 323 new_msr |= (target_ulong)MSR_HVB; 324 } 325 break; 326 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 327 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 328 case POWERPC_EXCP_DECR: /* Decrementer exception */ 329 break; 330 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 331 /* FIT on 4xx */ 332 LOG_EXCP("FIT exception\n"); 333 break; 334 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 335 LOG_EXCP("WDT exception\n"); 336 switch (excp_model) { 337 case POWERPC_EXCP_BOOKE: 338 srr0 = SPR_BOOKE_CSRR0; 339 srr1 = SPR_BOOKE_CSRR1; 340 break; 341 default: 342 break; 343 } 344 break; 345 case POWERPC_EXCP_DTLB: /* Data TLB error */ 346 case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 347 break; 348 case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 349 switch (excp_model) { 350 case POWERPC_EXCP_BOOKE: 351 /* FIXME: choose one or the other based on CPU type */ 352 srr0 = SPR_BOOKE_DSRR0; 353 srr1 = SPR_BOOKE_DSRR1; 354 asrr0 = SPR_BOOKE_CSRR0; 355 asrr1 = SPR_BOOKE_CSRR1; 356 break; 357 default: 358 break; 359 } 360 /* XXX: TODO */ 361 cpu_abort(cs, "Debug exception is not implemented yet !\n"); 362 break; 363 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ 364 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 365 break; 366 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ 367 /* XXX: TODO */ 368 cpu_abort(cs, "Embedded floating point data exception " 369 "is not implemented yet !\n"); 370 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 371 break; 372 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ 373 /* XXX: TODO */ 374 cpu_abort(cs, "Embedded floating point round exception " 375 "is not implemented yet !\n"); 376 env->spr[SPR_BOOKE_ESR] = ESR_SPV; 377 break; 378 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ 379 /* XXX: TODO */ 380 cpu_abort(cs, 381 "Performance counter exception is not implemented yet !\n"); 382 break; 383 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 384 break; 385 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 386 srr0 = SPR_BOOKE_CSRR0; 387 srr1 = SPR_BOOKE_CSRR1; 388 break; 389 case POWERPC_EXCP_RESET: /* System reset exception */ 390 /* A power-saving exception sets ME, otherwise it is unchanged */ 391 if (msr_pow) { 392 /* indicate that we resumed from power save mode */ 393 msr |= 0x10000; 394 new_msr |= ((target_ulong)1 << MSR_ME); 395 } 396 if (env->msr_mask & MSR_HVB) { 397 /* ISA specifies HV, but can be delivered to guest with HV clear 398 * (e.g., see FWNMI in PAPR, NMI injection in QEMU). 399 */ 400 new_msr |= (target_ulong)MSR_HVB; 401 } else { 402 if (msr_pow) { 403 cpu_abort(cs, "Trying to deliver power-saving system reset " 404 "exception %d with no HV support\n", excp); 405 } 406 } 407 ail = 0; 408 break; 409 case POWERPC_EXCP_DSEG: /* Data segment exception */ 410 case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 411 case POWERPC_EXCP_TRACE: /* Trace exception */ 412 break; 413 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 414 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 415 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ 416 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 417 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ 418 case POWERPC_EXCP_HV_EMU: 419 srr0 = SPR_HSRR0; 420 srr1 = SPR_HSRR1; 421 new_msr |= (target_ulong)MSR_HVB; 422 new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 423 break; 424 case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 425 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ 426 case POWERPC_EXCP_FU: /* Facility unavailable exception */ 427 #ifdef TARGET_PPC64 428 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); 429 #endif 430 break; 431 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ 432 LOG_EXCP("PIT exception\n"); 433 break; 434 case POWERPC_EXCP_IO: /* IO error exception */ 435 /* XXX: TODO */ 436 cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); 437 break; 438 case POWERPC_EXCP_RUNM: /* Run mode exception */ 439 /* XXX: TODO */ 440 cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); 441 break; 442 case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 443 /* XXX: TODO */ 444 cpu_abort(cs, "602 emulation trap exception " 445 "is not implemented yet !\n"); 446 break; 447 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 448 switch (excp_model) { 449 case POWERPC_EXCP_602: 450 case POWERPC_EXCP_603: 451 case POWERPC_EXCP_603E: 452 case POWERPC_EXCP_G2: 453 goto tlb_miss_tgpr; 454 case POWERPC_EXCP_7x5: 455 goto tlb_miss; 456 case POWERPC_EXCP_74xx: 457 goto tlb_miss_74xx; 458 default: 459 cpu_abort(cs, "Invalid instruction TLB miss exception\n"); 460 break; 461 } 462 break; 463 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 464 switch (excp_model) { 465 case POWERPC_EXCP_602: 466 case POWERPC_EXCP_603: 467 case POWERPC_EXCP_603E: 468 case POWERPC_EXCP_G2: 469 goto tlb_miss_tgpr; 470 case POWERPC_EXCP_7x5: 471 goto tlb_miss; 472 case POWERPC_EXCP_74xx: 473 goto tlb_miss_74xx; 474 default: 475 cpu_abort(cs, "Invalid data load TLB miss exception\n"); 476 break; 477 } 478 break; 479 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 480 switch (excp_model) { 481 case POWERPC_EXCP_602: 482 case POWERPC_EXCP_603: 483 case POWERPC_EXCP_603E: 484 case POWERPC_EXCP_G2: 485 tlb_miss_tgpr: 486 /* Swap temporary saved registers with GPRs */ 487 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { 488 new_msr |= (target_ulong)1 << MSR_TGPR; 489 hreg_swap_gpr_tgpr(env); 490 } 491 goto tlb_miss; 492 case POWERPC_EXCP_7x5: 493 tlb_miss: 494 #if defined(DEBUG_SOFTWARE_TLB) 495 if (qemu_log_enabled()) { 496 const char *es; 497 target_ulong *miss, *cmp; 498 int en; 499 500 if (excp == POWERPC_EXCP_IFTLB) { 501 es = "I"; 502 en = 'I'; 503 miss = &env->spr[SPR_IMISS]; 504 cmp = &env->spr[SPR_ICMP]; 505 } else { 506 if (excp == POWERPC_EXCP_DLTLB) { 507 es = "DL"; 508 } else { 509 es = "DS"; 510 } 511 en = 'D'; 512 miss = &env->spr[SPR_DMISS]; 513 cmp = &env->spr[SPR_DCMP]; 514 } 515 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 516 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " 517 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 518 env->spr[SPR_HASH1], env->spr[SPR_HASH2], 519 env->error_code); 520 } 521 #endif 522 msr |= env->crf[0] << 28; 523 msr |= env->error_code; /* key, D/I, S/L bits */ 524 /* Set way using a LRU mechanism */ 525 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 526 break; 527 case POWERPC_EXCP_74xx: 528 tlb_miss_74xx: 529 #if defined(DEBUG_SOFTWARE_TLB) 530 if (qemu_log_enabled()) { 531 const char *es; 532 target_ulong *miss, *cmp; 533 int en; 534 535 if (excp == POWERPC_EXCP_IFTLB) { 536 es = "I"; 537 en = 'I'; 538 miss = &env->spr[SPR_TLBMISS]; 539 cmp = &env->spr[SPR_PTEHI]; 540 } else { 541 if (excp == POWERPC_EXCP_DLTLB) { 542 es = "DL"; 543 } else { 544 es = "DS"; 545 } 546 en = 'D'; 547 miss = &env->spr[SPR_TLBMISS]; 548 cmp = &env->spr[SPR_PTEHI]; 549 } 550 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 551 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 552 env->error_code); 553 } 554 #endif 555 msr |= env->error_code; /* key bit */ 556 break; 557 default: 558 cpu_abort(cs, "Invalid data store TLB miss exception\n"); 559 break; 560 } 561 break; 562 case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 563 /* XXX: TODO */ 564 cpu_abort(cs, "Floating point assist exception " 565 "is not implemented yet !\n"); 566 break; 567 case POWERPC_EXCP_DABR: /* Data address breakpoint */ 568 /* XXX: TODO */ 569 cpu_abort(cs, "DABR exception is not implemented yet !\n"); 570 break; 571 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 572 /* XXX: TODO */ 573 cpu_abort(cs, "IABR exception is not implemented yet !\n"); 574 break; 575 case POWERPC_EXCP_SMI: /* System management interrupt */ 576 /* XXX: TODO */ 577 cpu_abort(cs, "SMI exception is not implemented yet !\n"); 578 break; 579 case POWERPC_EXCP_THERM: /* Thermal interrupt */ 580 /* XXX: TODO */ 581 cpu_abort(cs, "Thermal management exception " 582 "is not implemented yet !\n"); 583 break; 584 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 585 /* XXX: TODO */ 586 cpu_abort(cs, 587 "Performance counter exception is not implemented yet !\n"); 588 break; 589 case POWERPC_EXCP_VPUA: /* Vector assist exception */ 590 /* XXX: TODO */ 591 cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); 592 break; 593 case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 594 /* XXX: TODO */ 595 cpu_abort(cs, 596 "970 soft-patch exception is not implemented yet !\n"); 597 break; 598 case POWERPC_EXCP_MAINT: /* Maintenance exception */ 599 /* XXX: TODO */ 600 cpu_abort(cs, 601 "970 maintenance exception is not implemented yet !\n"); 602 break; 603 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ 604 /* XXX: TODO */ 605 cpu_abort(cs, "Maskable external exception " 606 "is not implemented yet !\n"); 607 break; 608 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ 609 /* XXX: TODO */ 610 cpu_abort(cs, "Non maskable external exception " 611 "is not implemented yet !\n"); 612 break; 613 default: 614 excp_invalid: 615 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 616 break; 617 } 618 619 /* Save PC */ 620 env->spr[srr0] = env->nip; 621 622 /* Save MSR */ 623 env->spr[srr1] = msr; 624 625 /* Sanity check */ 626 if (!(env->msr_mask & MSR_HVB)) { 627 if (new_msr & MSR_HVB) { 628 cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " 629 "no HV support\n", excp); 630 } 631 if (srr0 == SPR_HSRR0) { 632 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " 633 "no HV support\n", excp); 634 } 635 } 636 637 /* If any alternate SRR register are defined, duplicate saved values */ 638 if (asrr0 != -1) { 639 env->spr[asrr0] = env->spr[srr0]; 640 } 641 if (asrr1 != -1) { 642 env->spr[asrr1] = env->spr[srr1]; 643 } 644 645 /* Sort out endianness of interrupt, this differs depending on the 646 * CPU, the HV mode, etc... 647 */ 648 #ifdef TARGET_PPC64 649 if (excp_model == POWERPC_EXCP_POWER7) { 650 if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { 651 new_msr |= (target_ulong)1 << MSR_LE; 652 } 653 } else if (excp_model == POWERPC_EXCP_POWER8) { 654 if (new_msr & MSR_HVB) { 655 if (env->spr[SPR_HID0] & HID0_HILE) { 656 new_msr |= (target_ulong)1 << MSR_LE; 657 } 658 } else if (env->spr[SPR_LPCR] & LPCR_ILE) { 659 new_msr |= (target_ulong)1 << MSR_LE; 660 } 661 } else if (msr_ile) { 662 new_msr |= (target_ulong)1 << MSR_LE; 663 } 664 #else 665 if (msr_ile) { 666 new_msr |= (target_ulong)1 << MSR_LE; 667 } 668 #endif 669 670 /* Jump to handler */ 671 vector = env->excp_vectors[excp]; 672 if (vector == (target_ulong)-1ULL) { 673 cpu_abort(cs, "Raised an exception without defined vector %d\n", 674 excp); 675 } 676 vector |= env->excp_prefix; 677 678 /* AIL only works if there is no HV transition and we are running with 679 * translations enabled 680 */ 681 if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) || 682 ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { 683 ail = 0; 684 } 685 /* Handle AIL */ 686 if (ail) { 687 new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 688 switch(ail) { 689 case AIL_0001_8000: 690 vector |= 0x18000; 691 break; 692 case AIL_C000_0000_0000_4000: 693 vector |= 0xc000000000004000ull; 694 break; 695 default: 696 cpu_abort(cs, "Invalid AIL combination %d\n", ail); 697 break; 698 } 699 } 700 701 #if defined(TARGET_PPC64) 702 if (excp_model == POWERPC_EXCP_BOOKE) { 703 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { 704 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ 705 new_msr |= (target_ulong)1 << MSR_CM; 706 } else { 707 vector = (uint32_t)vector; 708 } 709 } else { 710 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) { 711 vector = (uint32_t)vector; 712 } else { 713 new_msr |= (target_ulong)1 << MSR_SF; 714 } 715 } 716 #endif 717 /* We don't use hreg_store_msr here as already have treated 718 * any special case that could occur. Just store MSR and update hflags 719 * 720 * Note: We *MUST* not use hreg_store_msr() as-is anyway because it 721 * will prevent setting of the HV bit which some exceptions might need 722 * to do. 723 */ 724 env->msr = new_msr & env->msr_mask; 725 hreg_compute_hflags(env); 726 env->nip = vector; 727 /* Reset exception state */ 728 cs->exception_index = POWERPC_EXCP_NONE; 729 env->error_code = 0; 730 731 /* Any interrupt is context synchronizing, check if TCG TLB 732 * needs a delayed flush on ppc64 733 */ 734 check_tlb_flush(env, false); 735 } 736 737 void ppc_cpu_do_interrupt(CPUState *cs) 738 { 739 PowerPCCPU *cpu = POWERPC_CPU(cs); 740 CPUPPCState *env = &cpu->env; 741 742 powerpc_excp(cpu, env->excp_model, cs->exception_index); 743 } 744 745 static void ppc_hw_interrupt(CPUPPCState *env) 746 { 747 PowerPCCPU *cpu = ppc_env_get_cpu(env); 748 #if 0 749 CPUState *cs = CPU(cpu); 750 751 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n", 752 __func__, env, env->pending_interrupts, 753 cs->interrupt_request, (int)msr_me, (int)msr_ee); 754 #endif 755 /* External reset */ 756 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { 757 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); 758 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 759 return; 760 } 761 /* Machine check exception */ 762 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { 763 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); 764 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); 765 return; 766 } 767 #if 0 /* TODO */ 768 /* External debug exception */ 769 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { 770 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); 771 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); 772 return; 773 } 774 #endif 775 /* Hypervisor decrementer exception */ 776 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { 777 /* LPCR will be clear when not supported so this will work */ 778 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); 779 if ((msr_ee != 0 || msr_hv == 0) && hdice) { 780 /* HDEC clears on delivery */ 781 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 782 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); 783 return; 784 } 785 } 786 /* Extermal interrupt can ignore MSR:EE under some circumstances */ 787 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { 788 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 789 if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { 790 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); 791 return; 792 } 793 } 794 if (msr_ce != 0) { 795 /* External critical interrupt */ 796 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { 797 /* Taking a critical external interrupt does not clear the external 798 * critical interrupt status 799 */ 800 #if 0 801 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT); 802 #endif 803 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); 804 return; 805 } 806 } 807 if (msr_ee != 0) { 808 /* Watchdog timer on embedded PowerPC */ 809 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { 810 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); 811 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); 812 return; 813 } 814 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { 815 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); 816 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); 817 return; 818 } 819 /* Fixed interval timer on embedded PowerPC */ 820 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { 821 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); 822 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); 823 return; 824 } 825 /* Programmable interval timer on embedded PowerPC */ 826 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { 827 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); 828 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); 829 return; 830 } 831 /* Decrementer exception */ 832 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { 833 if (ppc_decr_clear_on_delivery(env)) { 834 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); 835 } 836 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); 837 return; 838 } 839 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { 840 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 841 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); 842 return; 843 } 844 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { 845 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); 846 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); 847 return; 848 } 849 /* Thermal interrupt */ 850 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { 851 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); 852 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); 853 return; 854 } 855 } 856 } 857 858 void ppc_cpu_do_system_reset(CPUState *cs) 859 { 860 PowerPCCPU *cpu = POWERPC_CPU(cs); 861 CPUPPCState *env = &cpu->env; 862 863 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 864 } 865 #endif /* !CONFIG_USER_ONLY */ 866 867 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 868 { 869 PowerPCCPU *cpu = POWERPC_CPU(cs); 870 CPUPPCState *env = &cpu->env; 871 872 if (interrupt_request & CPU_INTERRUPT_HARD) { 873 ppc_hw_interrupt(env); 874 if (env->pending_interrupts == 0) { 875 cs->interrupt_request &= ~CPU_INTERRUPT_HARD; 876 } 877 return true; 878 } 879 return false; 880 } 881 882 #if defined(DEBUG_OP) 883 static void cpu_dump_rfi(target_ulong RA, target_ulong msr) 884 { 885 qemu_log("Return from exception at " TARGET_FMT_lx " with flags " 886 TARGET_FMT_lx "\n", RA, msr); 887 } 888 #endif 889 890 /*****************************************************************************/ 891 /* Exceptions processing helpers */ 892 893 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception, 894 uint32_t error_code, uintptr_t raddr) 895 { 896 CPUState *cs = CPU(ppc_env_get_cpu(env)); 897 898 cs->exception_index = exception; 899 env->error_code = error_code; 900 cpu_loop_exit_restore(cs, raddr); 901 } 902 903 void raise_exception_err(CPUPPCState *env, uint32_t exception, 904 uint32_t error_code) 905 { 906 raise_exception_err_ra(env, exception, error_code, 0); 907 } 908 909 void raise_exception(CPUPPCState *env, uint32_t exception) 910 { 911 raise_exception_err_ra(env, exception, 0, 0); 912 } 913 914 void raise_exception_ra(CPUPPCState *env, uint32_t exception, 915 uintptr_t raddr) 916 { 917 raise_exception_err_ra(env, exception, 0, raddr); 918 } 919 920 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception, 921 uint32_t error_code) 922 { 923 raise_exception_err_ra(env, exception, error_code, 0); 924 } 925 926 void helper_raise_exception(CPUPPCState *env, uint32_t exception) 927 { 928 raise_exception_err_ra(env, exception, 0, 0); 929 } 930 931 #if !defined(CONFIG_USER_ONLY) 932 void helper_store_msr(CPUPPCState *env, target_ulong val) 933 { 934 uint32_t excp = hreg_store_msr(env, val, 0); 935 936 if (excp != 0) { 937 CPUState *cs = CPU(ppc_env_get_cpu(env)); 938 cs->interrupt_request |= CPU_INTERRUPT_EXITTB; 939 raise_exception(env, excp); 940 } 941 } 942 943 #if defined(TARGET_PPC64) 944 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) 945 { 946 CPUState *cs; 947 948 cs = CPU(ppc_env_get_cpu(env)); 949 cs->halted = 1; 950 env->in_pm_state = true; 951 952 /* The architecture specifies that HDEC interrupts are 953 * discarded in PM states 954 */ 955 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 956 957 /* Technically, nap doesn't set EE, but if we don't set it 958 * then ppc_hw_interrupt() won't deliver. We could add some 959 * other tests there based on LPCR but it's simpler to just 960 * whack EE in. It will be cleared by the 0x100 at wakeup 961 * anyway. It will still be observable by the guest in SRR1 962 * but this doesn't seem to be a problem. 963 */ 964 env->msr |= (1ull << MSR_EE); 965 raise_exception(env, EXCP_HLT); 966 } 967 #endif /* defined(TARGET_PPC64) */ 968 969 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) 970 { 971 CPUState *cs = CPU(ppc_env_get_cpu(env)); 972 973 /* MSR:POW cannot be set by any form of rfi */ 974 msr &= ~(1ULL << MSR_POW); 975 976 #if defined(TARGET_PPC64) 977 /* Switching to 32-bit ? Crop the nip */ 978 if (!msr_is_64bit(env, msr)) { 979 nip = (uint32_t)nip; 980 } 981 #else 982 nip = (uint32_t)nip; 983 #endif 984 /* XXX: beware: this is false if VLE is supported */ 985 env->nip = nip & ~((target_ulong)0x00000003); 986 hreg_store_msr(env, msr, 1); 987 #if defined(DEBUG_OP) 988 cpu_dump_rfi(env->nip, env->msr); 989 #endif 990 /* No need to raise an exception here, 991 * as rfi is always the last insn of a TB 992 */ 993 cs->interrupt_request |= CPU_INTERRUPT_EXITTB; 994 995 /* Context synchronizing: check if TCG TLB needs flush */ 996 check_tlb_flush(env, false); 997 } 998 999 void helper_rfi(CPUPPCState *env) 1000 { 1001 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); 1002 } 1003 1004 #define MSR_BOOK3S_MASK 1005 #if defined(TARGET_PPC64) 1006 void helper_rfid(CPUPPCState *env) 1007 { 1008 /* The architeture defines a number of rules for which bits 1009 * can change but in practice, we handle this in hreg_store_msr() 1010 * which will be called by do_rfi(), so there is no need to filter 1011 * here 1012 */ 1013 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); 1014 } 1015 1016 void helper_hrfid(CPUPPCState *env) 1017 { 1018 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); 1019 } 1020 #endif 1021 1022 /*****************************************************************************/ 1023 /* Embedded PowerPC specific helpers */ 1024 void helper_40x_rfci(CPUPPCState *env) 1025 { 1026 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]); 1027 } 1028 1029 void helper_rfci(CPUPPCState *env) 1030 { 1031 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]); 1032 } 1033 1034 void helper_rfdi(CPUPPCState *env) 1035 { 1036 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */ 1037 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]); 1038 } 1039 1040 void helper_rfmci(CPUPPCState *env) 1041 { 1042 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */ 1043 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]); 1044 } 1045 #endif 1046 1047 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1048 uint32_t flags) 1049 { 1050 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) || 1051 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) || 1052 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) || 1053 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) || 1054 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) { 1055 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1056 POWERPC_EXCP_TRAP, GETPC()); 1057 } 1058 } 1059 1060 #if defined(TARGET_PPC64) 1061 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1062 uint32_t flags) 1063 { 1064 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) || 1065 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) || 1066 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) || 1067 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) || 1068 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) { 1069 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1070 POWERPC_EXCP_TRAP, GETPC()); 1071 } 1072 } 1073 #endif 1074 1075 #if !defined(CONFIG_USER_ONLY) 1076 /*****************************************************************************/ 1077 /* PowerPC 601 specific instructions (POWER bridge) */ 1078 1079 void helper_rfsvc(CPUPPCState *env) 1080 { 1081 do_rfi(env, env->lr, env->ctr & 0x0000FFFF); 1082 } 1083 1084 /* Embedded.Processor Control */ 1085 static int dbell2irq(target_ulong rb) 1086 { 1087 int msg = rb & DBELL_TYPE_MASK; 1088 int irq = -1; 1089 1090 switch (msg) { 1091 case DBELL_TYPE_DBELL: 1092 irq = PPC_INTERRUPT_DOORBELL; 1093 break; 1094 case DBELL_TYPE_DBELL_CRIT: 1095 irq = PPC_INTERRUPT_CDOORBELL; 1096 break; 1097 case DBELL_TYPE_G_DBELL: 1098 case DBELL_TYPE_G_DBELL_CRIT: 1099 case DBELL_TYPE_G_DBELL_MC: 1100 /* XXX implement */ 1101 default: 1102 break; 1103 } 1104 1105 return irq; 1106 } 1107 1108 void helper_msgclr(CPUPPCState *env, target_ulong rb) 1109 { 1110 int irq = dbell2irq(rb); 1111 1112 if (irq < 0) { 1113 return; 1114 } 1115 1116 env->pending_interrupts &= ~(1 << irq); 1117 } 1118 1119 void helper_msgsnd(target_ulong rb) 1120 { 1121 int irq = dbell2irq(rb); 1122 int pir = rb & DBELL_PIRTAG_MASK; 1123 CPUState *cs; 1124 1125 if (irq < 0) { 1126 return; 1127 } 1128 1129 CPU_FOREACH(cs) { 1130 PowerPCCPU *cpu = POWERPC_CPU(cs); 1131 CPUPPCState *cenv = &cpu->env; 1132 1133 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { 1134 cenv->pending_interrupts |= 1 << irq; 1135 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 1136 } 1137 } 1138 } 1139 #endif 1140