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