1ad71ed68SBlue Swirl /* 2ad71ed68SBlue Swirl * PowerPC exception emulation helpers for QEMU. 3ad71ed68SBlue Swirl * 4ad71ed68SBlue Swirl * Copyright (c) 2003-2007 Jocelyn Mayer 5ad71ed68SBlue Swirl * 6ad71ed68SBlue Swirl * This library is free software; you can redistribute it and/or 7ad71ed68SBlue Swirl * modify it under the terms of the GNU Lesser General Public 8ad71ed68SBlue Swirl * License as published by the Free Software Foundation; either 96bd039cdSChetan Pant * version 2.1 of the License, or (at your option) any later version. 10ad71ed68SBlue Swirl * 11ad71ed68SBlue Swirl * This library is distributed in the hope that it will be useful, 12ad71ed68SBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ad71ed68SBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14ad71ed68SBlue Swirl * Lesser General Public License for more details. 15ad71ed68SBlue Swirl * 16ad71ed68SBlue Swirl * You should have received a copy of the GNU Lesser General Public 17ad71ed68SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18ad71ed68SBlue Swirl */ 190d75590dSPeter Maydell #include "qemu/osdep.h" 20f1c29ebcSThomas Huth #include "qemu/main-loop.h" 21cd617484SPhilippe Mathieu-Daudé #include "qemu/log.h" 22*342e313dSPierrick Bouvier #include "system/memory.h" 2330de74bdSPhilippe Mathieu-Daudé #include "system/tcg.h" 2432cad1ffSPhilippe Mathieu-Daudé #include "system/system.h" 2532cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h" 26ad71ed68SBlue Swirl #include "cpu.h" 2763c91552SPaolo Bonzini #include "exec/exec-all.h" 280f3110faSRichard Henderson #include "internal.h" 29ad71ed68SBlue Swirl #include "helper_regs.h" 307b694df6SMatheus Ferst #include "hw/ppc/ppc.h" 31ad71ed68SBlue Swirl 322eb1ef73SCédric Le Goater #include "trace.h" 332eb1ef73SCédric Le Goater 34c79c73f6SBlue Swirl /*****************************************************************************/ 35c79c73f6SBlue Swirl /* Exception processing */ 36f6c2d68bSBALATON Zoltan #ifndef CONFIG_USER_ONLY 3797a8ea5aSAndreas Färber 386789f23bSCédric Le Goater static const char *powerpc_excp_name(int excp) 396789f23bSCédric Le Goater { 406789f23bSCédric Le Goater switch (excp) { 416789f23bSCédric Le Goater case POWERPC_EXCP_CRITICAL: return "CRITICAL"; 426789f23bSCédric Le Goater case POWERPC_EXCP_MCHECK: return "MCHECK"; 436789f23bSCédric Le Goater case POWERPC_EXCP_DSI: return "DSI"; 446789f23bSCédric Le Goater case POWERPC_EXCP_ISI: return "ISI"; 456789f23bSCédric Le Goater case POWERPC_EXCP_EXTERNAL: return "EXTERNAL"; 466789f23bSCédric Le Goater case POWERPC_EXCP_ALIGN: return "ALIGN"; 476789f23bSCédric Le Goater case POWERPC_EXCP_PROGRAM: return "PROGRAM"; 486789f23bSCédric Le Goater case POWERPC_EXCP_FPU: return "FPU"; 496789f23bSCédric Le Goater case POWERPC_EXCP_SYSCALL: return "SYSCALL"; 506789f23bSCédric Le Goater case POWERPC_EXCP_APU: return "APU"; 516789f23bSCédric Le Goater case POWERPC_EXCP_DECR: return "DECR"; 526789f23bSCédric Le Goater case POWERPC_EXCP_FIT: return "FIT"; 536789f23bSCédric Le Goater case POWERPC_EXCP_WDT: return "WDT"; 546789f23bSCédric Le Goater case POWERPC_EXCP_DTLB: return "DTLB"; 556789f23bSCédric Le Goater case POWERPC_EXCP_ITLB: return "ITLB"; 566789f23bSCédric Le Goater case POWERPC_EXCP_DEBUG: return "DEBUG"; 576789f23bSCédric Le Goater case POWERPC_EXCP_SPEU: return "SPEU"; 586789f23bSCédric Le Goater case POWERPC_EXCP_EFPDI: return "EFPDI"; 596789f23bSCédric Le Goater case POWERPC_EXCP_EFPRI: return "EFPRI"; 606789f23bSCédric Le Goater case POWERPC_EXCP_EPERFM: return "EPERFM"; 616789f23bSCédric Le Goater case POWERPC_EXCP_DOORI: return "DOORI"; 626789f23bSCédric Le Goater case POWERPC_EXCP_DOORCI: return "DOORCI"; 636789f23bSCédric Le Goater case POWERPC_EXCP_GDOORI: return "GDOORI"; 646789f23bSCédric Le Goater case POWERPC_EXCP_GDOORCI: return "GDOORCI"; 656789f23bSCédric Le Goater case POWERPC_EXCP_HYPPRIV: return "HYPPRIV"; 666789f23bSCédric Le Goater case POWERPC_EXCP_RESET: return "RESET"; 676789f23bSCédric Le Goater case POWERPC_EXCP_DSEG: return "DSEG"; 686789f23bSCédric Le Goater case POWERPC_EXCP_ISEG: return "ISEG"; 696789f23bSCédric Le Goater case POWERPC_EXCP_HDECR: return "HDECR"; 706789f23bSCédric Le Goater case POWERPC_EXCP_TRACE: return "TRACE"; 716789f23bSCédric Le Goater case POWERPC_EXCP_HDSI: return "HDSI"; 726789f23bSCédric Le Goater case POWERPC_EXCP_HISI: return "HISI"; 736789f23bSCédric Le Goater case POWERPC_EXCP_HDSEG: return "HDSEG"; 746789f23bSCédric Le Goater case POWERPC_EXCP_HISEG: return "HISEG"; 756789f23bSCédric Le Goater case POWERPC_EXCP_VPU: return "VPU"; 766789f23bSCédric Le Goater case POWERPC_EXCP_PIT: return "PIT"; 776789f23bSCédric Le Goater case POWERPC_EXCP_EMUL: return "EMUL"; 786789f23bSCédric Le Goater case POWERPC_EXCP_IFTLB: return "IFTLB"; 796789f23bSCédric Le Goater case POWERPC_EXCP_DLTLB: return "DLTLB"; 806789f23bSCédric Le Goater case POWERPC_EXCP_DSTLB: return "DSTLB"; 816789f23bSCédric Le Goater case POWERPC_EXCP_FPA: return "FPA"; 826789f23bSCédric Le Goater case POWERPC_EXCP_DABR: return "DABR"; 836789f23bSCédric Le Goater case POWERPC_EXCP_IABR: return "IABR"; 846789f23bSCédric Le Goater case POWERPC_EXCP_SMI: return "SMI"; 856789f23bSCédric Le Goater case POWERPC_EXCP_PERFM: return "PERFM"; 866789f23bSCédric Le Goater case POWERPC_EXCP_THERM: return "THERM"; 876789f23bSCédric Le Goater case POWERPC_EXCP_VPUA: return "VPUA"; 886789f23bSCédric Le Goater case POWERPC_EXCP_SOFTP: return "SOFTP"; 896789f23bSCédric Le Goater case POWERPC_EXCP_MAINT: return "MAINT"; 906789f23bSCédric Le Goater case POWERPC_EXCP_MEXTBR: return "MEXTBR"; 916789f23bSCédric Le Goater case POWERPC_EXCP_NMEXTBR: return "NMEXTBR"; 926789f23bSCédric Le Goater case POWERPC_EXCP_ITLBE: return "ITLBE"; 936789f23bSCédric Le Goater case POWERPC_EXCP_DTLBE: return "DTLBE"; 946789f23bSCédric Le Goater case POWERPC_EXCP_VSXU: return "VSXU"; 956789f23bSCédric Le Goater case POWERPC_EXCP_FU: return "FU"; 966789f23bSCédric Le Goater case POWERPC_EXCP_HV_EMU: return "HV_EMU"; 976789f23bSCédric Le Goater case POWERPC_EXCP_HV_MAINT: return "HV_MAINT"; 986789f23bSCédric Le Goater case POWERPC_EXCP_HV_FU: return "HV_FU"; 996789f23bSCédric Le Goater case POWERPC_EXCP_SDOOR: return "SDOOR"; 1006789f23bSCédric Le Goater case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV"; 1016789f23bSCédric Le Goater case POWERPC_EXCP_HVIRT: return "HVIRT"; 1026789f23bSCédric Le Goater case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED"; 1036789f23bSCédric Le Goater default: 1046789f23bSCédric Le Goater g_assert_not_reached(); 1056789f23bSCédric Le Goater } 1066789f23bSCédric Le Goater } 1076789f23bSCédric Le Goater 10862e79ef9SCédric Le Goater static void dump_syscall(CPUPPCState *env) 109c79c73f6SBlue Swirl { 1106dc6b557SNicholas Piggin qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 1116dc6b557SNicholas Piggin " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 1126dc6b557SNicholas Piggin " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 113c79c73f6SBlue Swirl " nip=" TARGET_FMT_lx "\n", 114c79c73f6SBlue Swirl ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), 115c79c73f6SBlue Swirl ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), 1166dc6b557SNicholas Piggin ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), 1176dc6b557SNicholas Piggin ppc_dump_gpr(env, 8), env->nip); 1186dc6b557SNicholas Piggin } 1196dc6b557SNicholas Piggin 12062e79ef9SCédric Le Goater static void dump_hcall(CPUPPCState *env) 1216dc6b557SNicholas Piggin { 1226dc6b557SNicholas Piggin qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 1236dc6b557SNicholas Piggin " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 1246dc6b557SNicholas Piggin " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 1256dc6b557SNicholas Piggin " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 1266dc6b557SNicholas Piggin " nip=" TARGET_FMT_lx "\n", 1276dc6b557SNicholas Piggin ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), 1286dc6b557SNicholas Piggin ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), 1296dc6b557SNicholas Piggin ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), 1306dc6b557SNicholas Piggin ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), 1316dc6b557SNicholas Piggin ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), 1326dc6b557SNicholas Piggin env->nip); 133c79c73f6SBlue Swirl } 134c79c73f6SBlue Swirl 135e4e27df7SFabiano Rosas static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) 136e4e27df7SFabiano Rosas { 137e4e27df7SFabiano Rosas const char *es; 138e4e27df7SFabiano Rosas target_ulong *miss, *cmp; 139e4e27df7SFabiano Rosas int en; 140e4e27df7SFabiano Rosas 1412e089eceSFabiano Rosas if (!qemu_loglevel_mask(CPU_LOG_MMU)) { 142e4e27df7SFabiano Rosas return; 143e4e27df7SFabiano Rosas } 144e4e27df7SFabiano Rosas 145e4e27df7SFabiano Rosas if (excp == POWERPC_EXCP_IFTLB) { 146e4e27df7SFabiano Rosas es = "I"; 147e4e27df7SFabiano Rosas en = 'I'; 148e4e27df7SFabiano Rosas miss = &env->spr[SPR_IMISS]; 149e4e27df7SFabiano Rosas cmp = &env->spr[SPR_ICMP]; 150e4e27df7SFabiano Rosas } else { 151e4e27df7SFabiano Rosas if (excp == POWERPC_EXCP_DLTLB) { 152e4e27df7SFabiano Rosas es = "DL"; 153e4e27df7SFabiano Rosas } else { 154e4e27df7SFabiano Rosas es = "DS"; 155e4e27df7SFabiano Rosas } 156e4e27df7SFabiano Rosas en = 'D'; 157e4e27df7SFabiano Rosas miss = &env->spr[SPR_DMISS]; 158e4e27df7SFabiano Rosas cmp = &env->spr[SPR_DCMP]; 159e4e27df7SFabiano Rosas } 160e4e27df7SFabiano Rosas qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 161e4e27df7SFabiano Rosas TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " 162e4e27df7SFabiano Rosas TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 163e4e27df7SFabiano Rosas env->spr[SPR_HASH1], env->spr[SPR_HASH2], 164e4e27df7SFabiano Rosas env->error_code); 165e4e27df7SFabiano Rosas } 166e4e27df7SFabiano Rosas 167f6c2d68bSBALATON Zoltan #ifdef TARGET_PPC64 1683f88a89dSBALATON Zoltan static int powerpc_reset_wakeup(CPUPPCState *env, int excp, target_ulong *msr) 169dead760bSBenjamin Herrenschmidt { 170dead760bSBenjamin Herrenschmidt /* We no longer are in a PM state */ 1711e7fd61dSBenjamin Herrenschmidt env->resume_as_sreset = false; 172dead760bSBenjamin Herrenschmidt 173dead760bSBenjamin Herrenschmidt /* Pretend to be returning from doze always as we don't lose state */ 1740911a60cSLeonardo Bras *msr |= SRR1_WS_NOLOSS; 175dead760bSBenjamin Herrenschmidt 176dead760bSBenjamin Herrenschmidt /* Machine checks are sent normally */ 177dead760bSBenjamin Herrenschmidt if (excp == POWERPC_EXCP_MCHECK) { 178dead760bSBenjamin Herrenschmidt return excp; 179dead760bSBenjamin Herrenschmidt } 180dead760bSBenjamin Herrenschmidt switch (excp) { 181dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_RESET: 1820911a60cSLeonardo Bras *msr |= SRR1_WAKERESET; 183dead760bSBenjamin Herrenschmidt break; 184dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_EXTERNAL: 1850911a60cSLeonardo Bras *msr |= SRR1_WAKEEE; 186dead760bSBenjamin Herrenschmidt break; 187dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_DECR: 1880911a60cSLeonardo Bras *msr |= SRR1_WAKEDEC; 189dead760bSBenjamin Herrenschmidt break; 190dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR: 1910911a60cSLeonardo Bras *msr |= SRR1_WAKEDBELL; 192dead760bSBenjamin Herrenschmidt break; 193dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR_HV: 1940911a60cSLeonardo Bras *msr |= SRR1_WAKEHDBELL; 195dead760bSBenjamin Herrenschmidt break; 196dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_HV_MAINT: 1970911a60cSLeonardo Bras *msr |= SRR1_WAKEHMI; 198dead760bSBenjamin Herrenschmidt break; 199d8ce5fd6SBenjamin Herrenschmidt case POWERPC_EXCP_HVIRT: 2000911a60cSLeonardo Bras *msr |= SRR1_WAKEHVI; 201d8ce5fd6SBenjamin Herrenschmidt break; 202dead760bSBenjamin Herrenschmidt default: 2033f88a89dSBALATON Zoltan cpu_abort(env_cpu(env), 2043f88a89dSBALATON Zoltan "Unsupported exception %d in Power Save mode\n", excp); 205dead760bSBenjamin Herrenschmidt } 206dead760bSBenjamin Herrenschmidt return POWERPC_EXCP_RESET; 207dead760bSBenjamin Herrenschmidt } 208dead760bSBenjamin Herrenschmidt 2098b7e6b07SNicholas Piggin /* 2108b7e6b07SNicholas Piggin * AIL - Alternate Interrupt Location, a mode that allows interrupts to be 2118b7e6b07SNicholas Piggin * taken with the MMU on, and which uses an alternate location (e.g., so the 2128b7e6b07SNicholas Piggin * kernel/hv can map the vectors there with an effective address). 2138b7e6b07SNicholas Piggin * 2148b7e6b07SNicholas Piggin * An interrupt is considered to be taken "with AIL" or "AIL applies" if they 2158b7e6b07SNicholas Piggin * are delivered in this way. AIL requires the LPCR to be set to enable this 2168b7e6b07SNicholas Piggin * mode, and then a number of conditions have to be true for AIL to apply. 2178b7e6b07SNicholas Piggin * 2188b7e6b07SNicholas Piggin * First of all, SRESET, MCE, and HMI are always delivered without AIL, because 2198b7e6b07SNicholas Piggin * they specifically want to be in real mode (e.g., the MCE might be signaling 2208b7e6b07SNicholas Piggin * a SLB multi-hit which requires SLB flush before the MMU can be enabled). 2218b7e6b07SNicholas Piggin * 2228b7e6b07SNicholas Piggin * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV], 2238b7e6b07SNicholas Piggin * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current 2248b7e6b07SNicholas Piggin * radix mode (LPCR[HR]). 2258b7e6b07SNicholas Piggin * 2268b7e6b07SNicholas Piggin * POWER8, POWER9 with LPCR[HR]=0 2278b7e6b07SNicholas Piggin * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 2288b7e6b07SNicholas Piggin * +-----------+-------------+---------+-------------+-----+ 2298b7e6b07SNicholas Piggin * | a | 00/01/10 | x | x | 0 | 2308b7e6b07SNicholas Piggin * | a | 11 | 0 | 1 | 0 | 2318b7e6b07SNicholas Piggin * | a | 11 | 1 | 1 | a | 2328b7e6b07SNicholas Piggin * | a | 11 | 0 | 0 | a | 2338b7e6b07SNicholas Piggin * +-------------------------------------------------------+ 2348b7e6b07SNicholas Piggin * 2358b7e6b07SNicholas Piggin * POWER9 with LPCR[HR]=1 2368b7e6b07SNicholas Piggin * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 2378b7e6b07SNicholas Piggin * +-----------+-------------+---------+-------------+-----+ 2388b7e6b07SNicholas Piggin * | a | 00/01/10 | x | x | 0 | 2398b7e6b07SNicholas Piggin * | a | 11 | x | x | a | 2408b7e6b07SNicholas Piggin * +-------------------------------------------------------+ 2418b7e6b07SNicholas Piggin * 2428b7e6b07SNicholas Piggin * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to 243526cdce7SNicholas Piggin * the hypervisor in AIL mode if the guest is radix. This is good for 244526cdce7SNicholas Piggin * performance but allows the guest to influence the AIL of hypervisor 245526cdce7SNicholas Piggin * interrupts using its MSR, and also the hypervisor must disallow guest 246526cdce7SNicholas Piggin * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to 247526cdce7SNicholas Piggin * use AIL for its MSR[HV] 0->1 interrupts. 248526cdce7SNicholas Piggin * 249526cdce7SNicholas Piggin * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to 250526cdce7SNicholas Piggin * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and 251526cdce7SNicholas Piggin * MSR[HV] 1->1). 252526cdce7SNicholas Piggin * 253526cdce7SNicholas Piggin * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1. 254526cdce7SNicholas Piggin * 255526cdce7SNicholas Piggin * POWER10 behaviour is 256526cdce7SNicholas Piggin * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 257526cdce7SNicholas Piggin * +-----------+------------+-------------+---------+-------------+-----+ 258526cdce7SNicholas Piggin * | a | h | 00/01/10 | 0 | 0 | 0 | 259526cdce7SNicholas Piggin * | a | h | 11 | 0 | 0 | a | 260526cdce7SNicholas Piggin * | a | h | x | 0 | 1 | h | 261526cdce7SNicholas Piggin * | a | h | 00/01/10 | 1 | 1 | 0 | 262526cdce7SNicholas Piggin * | a | h | 11 | 1 | 1 | h | 263526cdce7SNicholas Piggin * +--------------------------------------------------------------------+ 2648b7e6b07SNicholas Piggin */ 26510895ab6SFabiano Rosas static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr, 26610895ab6SFabiano Rosas target_ulong *new_msr, target_ulong *vector) 2672586a4d7SFabiano Rosas { 26810895ab6SFabiano Rosas PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); 2698b7e6b07SNicholas Piggin CPUPPCState *env = &cpu->env; 2708b7e6b07SNicholas Piggin bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1); 2718b7e6b07SNicholas Piggin bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB); 2728b7e6b07SNicholas Piggin int ail = 0; 2732586a4d7SFabiano Rosas 2748b7e6b07SNicholas Piggin if (excp == POWERPC_EXCP_MCHECK || 2758b7e6b07SNicholas Piggin excp == POWERPC_EXCP_RESET || 2768b7e6b07SNicholas Piggin excp == POWERPC_EXCP_HV_MAINT) { 2778b7e6b07SNicholas Piggin /* SRESET, MCE, HMI never apply AIL */ 2788b7e6b07SNicholas Piggin return; 2792586a4d7SFabiano Rosas } 2802586a4d7SFabiano Rosas 28110895ab6SFabiano Rosas if (!(pcc->lpcr_mask & LPCR_AIL)) { 28210895ab6SFabiano Rosas /* This CPU does not have AIL */ 28310895ab6SFabiano Rosas return; 28410895ab6SFabiano Rosas } 28510895ab6SFabiano Rosas 28610895ab6SFabiano Rosas /* P8 & P9 */ 28710895ab6SFabiano Rosas if (!(pcc->lpcr_mask & LPCR_HAIL)) { 2888b7e6b07SNicholas Piggin if (!mmu_all_on) { 2898b7e6b07SNicholas Piggin /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */ 2908b7e6b07SNicholas Piggin return; 2918b7e6b07SNicholas Piggin } 2928b7e6b07SNicholas Piggin if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) { 2938b7e6b07SNicholas Piggin /* 2948b7e6b07SNicholas Piggin * AIL does not work if there is a MSR[HV] 0->1 transition and the 2958b7e6b07SNicholas Piggin * partition is in HPT mode. For radix guests, such interrupts are 2968b7e6b07SNicholas Piggin * allowed to be delivered to the hypervisor in ail mode. 2978b7e6b07SNicholas Piggin */ 2988b7e6b07SNicholas Piggin return; 2998b7e6b07SNicholas Piggin } 3008b7e6b07SNicholas Piggin 3018b7e6b07SNicholas Piggin ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 3028bbf0cffSHarsh Prateek Bora if (ail == 0 || ail == 1) { 3038b7e6b07SNicholas Piggin /* AIL=1 is reserved, treat it like AIL=0 */ 3048b7e6b07SNicholas Piggin return; 3058b7e6b07SNicholas Piggin } 306526cdce7SNicholas Piggin 30710895ab6SFabiano Rosas /* P10 and up */ 30810895ab6SFabiano Rosas } else { 309526cdce7SNicholas Piggin if (!mmu_all_on && !hv_escalation) { 310526cdce7SNicholas Piggin /* 311526cdce7SNicholas Piggin * AIL works for HV interrupts even with guest MSR[IR/DR] disabled. 312526cdce7SNicholas Piggin * Guest->guest and HV->HV interrupts do require MMU on. 313526cdce7SNicholas Piggin */ 314526cdce7SNicholas Piggin return; 315526cdce7SNicholas Piggin } 316526cdce7SNicholas Piggin 317526cdce7SNicholas Piggin if (*new_msr & MSR_HVB) { 318526cdce7SNicholas Piggin if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) { 319526cdce7SNicholas Piggin /* HV interrupts depend on LPCR[HAIL] */ 320526cdce7SNicholas Piggin return; 321526cdce7SNicholas Piggin } 322526cdce7SNicholas Piggin ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */ 323526cdce7SNicholas Piggin } else { 324526cdce7SNicholas Piggin ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 325526cdce7SNicholas Piggin } 3268bbf0cffSHarsh Prateek Bora if (ail == 0 || ail == 1 || ail == 2) { 327526cdce7SNicholas Piggin /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */ 328526cdce7SNicholas Piggin return; 329526cdce7SNicholas Piggin } 3308b7e6b07SNicholas Piggin } 3318b7e6b07SNicholas Piggin 3328b7e6b07SNicholas Piggin /* 3338b7e6b07SNicholas Piggin * AIL applies, so the new MSR gets IR and DR set, and an offset applied 3348b7e6b07SNicholas Piggin * to the new IP. 3358b7e6b07SNicholas Piggin */ 3368b7e6b07SNicholas Piggin *new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 3378b7e6b07SNicholas Piggin 3388b7e6b07SNicholas Piggin if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { 3398b7e6b07SNicholas Piggin if (ail == 2) { 3408b7e6b07SNicholas Piggin *vector |= 0x0000000000018000ull; 3418b7e6b07SNicholas Piggin } else if (ail == 3) { 3428b7e6b07SNicholas Piggin *vector |= 0xc000000000004000ull; 3438b7e6b07SNicholas Piggin } 3448b7e6b07SNicholas Piggin } else { 3458b7e6b07SNicholas Piggin /* 3468b7e6b07SNicholas Piggin * scv AIL is a little different. AIL=2 does not change the address, 3478b7e6b07SNicholas Piggin * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000. 3488b7e6b07SNicholas Piggin */ 3498b7e6b07SNicholas Piggin if (ail == 3) { 3508b7e6b07SNicholas Piggin *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */ 3518b7e6b07SNicholas Piggin *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */ 3528b7e6b07SNicholas Piggin } 3538b7e6b07SNicholas Piggin } 3542586a4d7SFabiano Rosas } 355f6c2d68bSBALATON Zoltan #endif /* TARGET_PPC64 */ 356dead760bSBenjamin Herrenschmidt 3573680e994SNicholas Piggin static void powerpc_reset_excp_state(PowerPCCPU *cpu) 358ad77c6caSNicholas Piggin { 359ad77c6caSNicholas Piggin CPUState *cs = CPU(cpu); 360ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 361ad77c6caSNicholas Piggin 3623680e994SNicholas Piggin /* Reset exception state */ 3633680e994SNicholas Piggin cs->exception_index = POWERPC_EXCP_NONE; 3643680e994SNicholas Piggin env->error_code = 0; 3653680e994SNicholas Piggin } 3663680e994SNicholas Piggin 3673680e994SNicholas Piggin static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, 3683680e994SNicholas Piggin target_ulong msr) 3693680e994SNicholas Piggin { 3703680e994SNicholas Piggin CPUPPCState *env = &cpu->env; 3713680e994SNicholas Piggin 372fce9fbafSFabiano Rosas assert((msr & env->msr_mask) == msr); 373fce9fbafSFabiano Rosas 374ad77c6caSNicholas Piggin /* 375ad77c6caSNicholas Piggin * We don't use hreg_store_msr here as already have treated any 376ad77c6caSNicholas Piggin * special case that could occur. Just store MSR and update hflags 377ad77c6caSNicholas Piggin * 378ab452503SBALATON Zoltan * Note: We *MUST* not use hreg_store_msr() as-is anyway because it will 379ab452503SBALATON Zoltan * prevent setting of the HV bit which some exceptions might need to do. 380ad77c6caSNicholas Piggin */ 3813680e994SNicholas Piggin env->nip = vector; 382fce9fbafSFabiano Rosas env->msr = msr; 383ad77c6caSNicholas Piggin hreg_compute_hflags(env); 3842fdedcbcSMatheus Ferst ppc_maybe_interrupt(env); 385ad77c6caSNicholas Piggin 3863680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 387ad77c6caSNicholas Piggin 388ad77c6caSNicholas Piggin /* 389ad77c6caSNicholas Piggin * Any interrupt is context synchronizing, check if TCG TLB needs 390ad77c6caSNicholas Piggin * a delayed flush on ppc64 391ad77c6caSNicholas Piggin */ 392ad77c6caSNicholas Piggin check_tlb_flush(env, false); 3933680e994SNicholas Piggin 3943680e994SNicholas Piggin /* Reset the reservation */ 3953680e994SNicholas Piggin env->reserve_addr = -1; 396ad77c6caSNicholas Piggin } 397ad77c6caSNicholas Piggin 39845693f94SNicholas Piggin static void powerpc_mcheck_checkstop(CPUPPCState *env) 39945693f94SNicholas Piggin { 40045693f94SNicholas Piggin /* KVM guests always have MSR[ME] enabled */ 40145693f94SNicholas Piggin if (FIELD_EX64(env->msr, MSR, ME)) { 40245693f94SNicholas Piggin return; 40345693f94SNicholas Piggin } 40430de74bdSPhilippe Mathieu-Daudé assert(tcg_enabled()); 40545693f94SNicholas Piggin powerpc_checkstop(env, "machine check with MSR[ME]=0"); 406819b31b0SBALATON Zoltan } 407819b31b0SBALATON Zoltan 408e808c2edSFabiano Rosas static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) 409e808c2edSFabiano Rosas { 410e808c2edSFabiano Rosas CPUPPCState *env = &cpu->env; 411e808c2edSFabiano Rosas target_ulong msr, new_msr, vector; 412ab452503SBALATON Zoltan int srr0 = SPR_SRR0, srr1 = SPR_SRR1; 413e808c2edSFabiano Rosas 414e808c2edSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 415e808c2edSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 416e808c2edSFabiano Rosas 417ab452503SBALATON Zoltan /* new interrupt handler msr preserves ME unless explicitly overridden */ 418495fc7ffSFabiano Rosas new_msr = env->msr & (((target_ulong)1 << MSR_ME)); 419e808c2edSFabiano Rosas 420ab452503SBALATON Zoltan /* HV emu assistance interrupt only exists on server arch 2.05 or later */ 421495fc7ffSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 422e808c2edSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 423e808c2edSFabiano Rosas } 424e808c2edSFabiano Rosas 425e808c2edSFabiano Rosas vector = env->excp_vectors[excp]; 426e808c2edSFabiano Rosas if (vector == (target_ulong)-1ULL) { 427bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 428bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 429e808c2edSFabiano Rosas } 430e808c2edSFabiano Rosas vector |= env->excp_prefix; 431e808c2edSFabiano Rosas 432e808c2edSFabiano Rosas switch (excp) { 433e808c2edSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 434e808c2edSFabiano Rosas srr0 = SPR_40x_SRR2; 435e808c2edSFabiano Rosas srr1 = SPR_40x_SRR3; 436e808c2edSFabiano Rosas break; 437e808c2edSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 438819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 439e808c2edSFabiano Rosas /* machine check exceptions don't have ME set */ 440e808c2edSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 441e808c2edSFabiano Rosas srr0 = SPR_40x_SRR2; 442e808c2edSFabiano Rosas srr1 = SPR_40x_SRR3; 443e808c2edSFabiano Rosas break; 444e808c2edSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 445f9911e1eSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]); 446e808c2edSFabiano Rosas break; 447e808c2edSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 448e808c2edSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 449e808c2edSFabiano Rosas break; 450e808c2edSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 451e808c2edSFabiano Rosas break; 452e808c2edSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 453e808c2edSFabiano Rosas break; 454e808c2edSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 455e808c2edSFabiano Rosas switch (env->error_code & ~0xF) { 456e808c2edSFabiano Rosas case POWERPC_EXCP_FP: 457da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 458e808c2edSFabiano Rosas trace_ppc_excp_fp_ignore(); 4593680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 460e808c2edSFabiano Rosas return; 461e808c2edSFabiano Rosas } 46264e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_FP; 463e808c2edSFabiano Rosas break; 464e808c2edSFabiano Rosas case POWERPC_EXCP_INVAL: 465e808c2edSFabiano Rosas trace_ppc_excp_inval(env->nip); 46664e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PIL; 467e808c2edSFabiano Rosas break; 468e808c2edSFabiano Rosas case POWERPC_EXCP_PRIV: 46964e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PPR; 470e808c2edSFabiano Rosas break; 471e808c2edSFabiano Rosas case POWERPC_EXCP_TRAP: 47264e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PTR; 473e808c2edSFabiano Rosas break; 474e808c2edSFabiano Rosas default: 475bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 476e808c2edSFabiano Rosas env->error_code); 477e808c2edSFabiano Rosas break; 478e808c2edSFabiano Rosas } 479e808c2edSFabiano Rosas break; 480e808c2edSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 481e808c2edSFabiano Rosas dump_syscall(env); 482e808c2edSFabiano Rosas 483e808c2edSFabiano Rosas /* 484e808c2edSFabiano Rosas * We need to correct the NIP which in this case is supposed 485e808c2edSFabiano Rosas * to point to the next instruction 486e808c2edSFabiano Rosas */ 487e808c2edSFabiano Rosas env->nip += 4; 488e808c2edSFabiano Rosas break; 489e808c2edSFabiano Rosas case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 490e808c2edSFabiano Rosas trace_ppc_excp_print("FIT"); 491e808c2edSFabiano Rosas break; 492e808c2edSFabiano Rosas case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 493e808c2edSFabiano Rosas trace_ppc_excp_print("WDT"); 494e808c2edSFabiano Rosas break; 495e808c2edSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 496e808c2edSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 497e808c2edSFabiano Rosas break; 498e808c2edSFabiano Rosas case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ 499e808c2edSFabiano Rosas trace_ppc_excp_print("PIT"); 500e808c2edSFabiano Rosas break; 5014d8ac1d1SFabiano Rosas case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 502bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 5034d8ac1d1SFabiano Rosas powerpc_excp_name(excp)); 5044d8ac1d1SFabiano Rosas break; 505e808c2edSFabiano Rosas default: 506bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 507bc30c1c6SBALATON Zoltan excp); 508e808c2edSFabiano Rosas break; 509e808c2edSFabiano Rosas } 510e808c2edSFabiano Rosas 511e808c2edSFabiano Rosas env->spr[srr0] = env->nip; 512e808c2edSFabiano Rosas env->spr[srr1] = msr; 513e808c2edSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 514e808c2edSFabiano Rosas } 515e808c2edSFabiano Rosas 51658d178fbSFabiano Rosas static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp) 51758d178fbSFabiano Rosas { 51858d178fbSFabiano Rosas CPUPPCState *env = &cpu->env; 51958d178fbSFabiano Rosas target_ulong msr, new_msr, vector; 52058d178fbSFabiano Rosas 52158d178fbSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 52258d178fbSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 52358d178fbSFabiano Rosas 524ab452503SBALATON Zoltan /* new interrupt handler msr preserves ME unless explicitly overridden */ 525082d783bSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 52658d178fbSFabiano Rosas 527ab452503SBALATON Zoltan /* HV emu assistance interrupt only exists on server arch 2.05 or later */ 528082d783bSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 52958d178fbSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 53058d178fbSFabiano Rosas } 53158d178fbSFabiano Rosas 53258d178fbSFabiano Rosas vector = env->excp_vectors[excp]; 53358d178fbSFabiano Rosas if (vector == (target_ulong)-1ULL) { 534bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 535bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 53658d178fbSFabiano Rosas } 53758d178fbSFabiano Rosas vector |= env->excp_prefix; 53858d178fbSFabiano Rosas 53958d178fbSFabiano Rosas switch (excp) { 54058d178fbSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 54158d178fbSFabiano Rosas break; 54258d178fbSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 543819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 54458d178fbSFabiano Rosas /* machine check exceptions don't have ME set */ 54558d178fbSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 54658d178fbSFabiano Rosas break; 54758d178fbSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 54858d178fbSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 54958d178fbSFabiano Rosas break; 55058d178fbSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 55158d178fbSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 55258d178fbSFabiano Rosas msr |= env->error_code; 55358d178fbSFabiano Rosas break; 55458d178fbSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 55558d178fbSFabiano Rosas break; 55658d178fbSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 55758d178fbSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 55858d178fbSFabiano Rosas /* 55958d178fbSFabiano Rosas * Note: the opcode fields will not be set properly for a 56058d178fbSFabiano Rosas * direct store load/store, but nobody cares as nobody 56158d178fbSFabiano Rosas * actually uses direct store segments. 56258d178fbSFabiano Rosas */ 56358d178fbSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 56458d178fbSFabiano Rosas break; 56558d178fbSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 56658d178fbSFabiano Rosas switch (env->error_code & ~0xF) { 56758d178fbSFabiano Rosas case POWERPC_EXCP_FP: 568da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 56958d178fbSFabiano Rosas trace_ppc_excp_fp_ignore(); 5703680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 57158d178fbSFabiano Rosas return; 57258d178fbSFabiano Rosas } 57358d178fbSFabiano Rosas /* 574ab452503SBALATON Zoltan * NIP always points to the faulting instruction for FP exceptions, 575ab452503SBALATON Zoltan * so always use store_next and claim we are precise in the MSR. 57658d178fbSFabiano Rosas */ 57758d178fbSFabiano Rosas msr |= 0x00100000; 57858d178fbSFabiano Rosas break; 57958d178fbSFabiano Rosas case POWERPC_EXCP_INVAL: 58058d178fbSFabiano Rosas trace_ppc_excp_inval(env->nip); 58158d178fbSFabiano Rosas msr |= 0x00080000; 58258d178fbSFabiano Rosas break; 58358d178fbSFabiano Rosas case POWERPC_EXCP_PRIV: 58458d178fbSFabiano Rosas msr |= 0x00040000; 58558d178fbSFabiano Rosas break; 58658d178fbSFabiano Rosas case POWERPC_EXCP_TRAP: 58758d178fbSFabiano Rosas msr |= 0x00020000; 58858d178fbSFabiano Rosas break; 58958d178fbSFabiano Rosas default: 59058d178fbSFabiano Rosas /* Should never occur */ 591bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 59258d178fbSFabiano Rosas env->error_code); 59358d178fbSFabiano Rosas break; 59458d178fbSFabiano Rosas } 59558d178fbSFabiano Rosas break; 59658d178fbSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 59758d178fbSFabiano Rosas dump_syscall(env); 59858d178fbSFabiano Rosas 59958d178fbSFabiano Rosas /* 60058d178fbSFabiano Rosas * We need to correct the NIP which in this case is supposed 60158d178fbSFabiano Rosas * to point to the next instruction 60258d178fbSFabiano Rosas */ 60358d178fbSFabiano Rosas env->nip += 4; 60458d178fbSFabiano Rosas break; 60558d178fbSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 60658d178fbSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 60758d178fbSFabiano Rosas break; 60858d178fbSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 60958d178fbSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 61058d178fbSFabiano Rosas break; 61158d178fbSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 6128e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 613bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 614bc30c1c6SBALATON Zoltan "Trying to deliver power-saving system reset exception " 615bc30c1c6SBALATON Zoltan "%d with no HV support\n", excp); 61658d178fbSFabiano Rosas } 61758d178fbSFabiano Rosas break; 61858d178fbSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 61958d178fbSFabiano Rosas break; 62058d178fbSFabiano Rosas case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 62158d178fbSFabiano Rosas case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 62258d178fbSFabiano Rosas case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 62358d178fbSFabiano Rosas /* Swap temporary saved registers with GPRs */ 62458d178fbSFabiano Rosas if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { 62558d178fbSFabiano Rosas new_msr |= (target_ulong)1 << MSR_TGPR; 62658d178fbSFabiano Rosas hreg_swap_gpr_tgpr(env); 62758d178fbSFabiano Rosas } 6288f8c7932SFabiano Rosas 62958d178fbSFabiano Rosas ppc_excp_debug_sw_tlb(env, excp); 63058d178fbSFabiano Rosas 63158d178fbSFabiano Rosas msr |= env->crf[0] << 28; 63258d178fbSFabiano Rosas msr |= env->error_code; /* key, D/I, S/L bits */ 63358d178fbSFabiano Rosas /* Set way using a LRU mechanism */ 63458d178fbSFabiano Rosas msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 63558d178fbSFabiano Rosas break; 63658d178fbSFabiano Rosas case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 63758d178fbSFabiano Rosas case POWERPC_EXCP_DABR: /* Data address breakpoint */ 63858d178fbSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 63958d178fbSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 64058d178fbSFabiano Rosas case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ 64158d178fbSFabiano Rosas case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ 642bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 64358d178fbSFabiano Rosas powerpc_excp_name(excp)); 64458d178fbSFabiano Rosas break; 64558d178fbSFabiano Rosas default: 646bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 647bc30c1c6SBALATON Zoltan excp); 64858d178fbSFabiano Rosas break; 64958d178fbSFabiano Rosas } 65058d178fbSFabiano Rosas 65158d178fbSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 65258d178fbSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 65358d178fbSFabiano Rosas } 654c50eaed1SFabiano Rosas env->spr[SPR_SRR0] = env->nip; 655c50eaed1SFabiano Rosas env->spr[SPR_SRR1] = msr; 65658d178fbSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 65758d178fbSFabiano Rosas } 65858d178fbSFabiano Rosas 659ccfca2fcSFabiano Rosas static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp) 660ccfca2fcSFabiano Rosas { 661ccfca2fcSFabiano Rosas CPUPPCState *env = &cpu->env; 662ccfca2fcSFabiano Rosas target_ulong msr, new_msr, vector; 663ccfca2fcSFabiano Rosas 664ccfca2fcSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 665ccfca2fcSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 666ccfca2fcSFabiano Rosas 667ab452503SBALATON Zoltan /* new interrupt handler msr preserves ME unless explicitly overridden */ 66893848d6aSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 669ccfca2fcSFabiano Rosas 670ab452503SBALATON Zoltan /* HV emu assistance interrupt only exists on server arch 2.05 or later */ 67193848d6aSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 672ccfca2fcSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 673ccfca2fcSFabiano Rosas } 674ccfca2fcSFabiano Rosas 675ccfca2fcSFabiano Rosas vector = env->excp_vectors[excp]; 676ccfca2fcSFabiano Rosas if (vector == (target_ulong)-1ULL) { 677bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 678bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 679ccfca2fcSFabiano Rosas } 680ccfca2fcSFabiano Rosas vector |= env->excp_prefix; 681ccfca2fcSFabiano Rosas 682ccfca2fcSFabiano Rosas switch (excp) { 683ccfca2fcSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 684819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 685ccfca2fcSFabiano Rosas /* machine check exceptions don't have ME set */ 686ccfca2fcSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 687ccfca2fcSFabiano Rosas break; 688ccfca2fcSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 689ccfca2fcSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 690ccfca2fcSFabiano Rosas break; 691ccfca2fcSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 692ccfca2fcSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 693ccfca2fcSFabiano Rosas msr |= env->error_code; 694ccfca2fcSFabiano Rosas break; 695ccfca2fcSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 696ccfca2fcSFabiano Rosas break; 697ccfca2fcSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 698ccfca2fcSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 699ccfca2fcSFabiano Rosas /* 700ccfca2fcSFabiano Rosas * Note: the opcode fields will not be set properly for a 701ccfca2fcSFabiano Rosas * direct store load/store, but nobody cares as nobody 702ccfca2fcSFabiano Rosas * actually uses direct store segments. 703ccfca2fcSFabiano Rosas */ 704ccfca2fcSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 705ccfca2fcSFabiano Rosas break; 706ccfca2fcSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 707ccfca2fcSFabiano Rosas switch (env->error_code & ~0xF) { 708ccfca2fcSFabiano Rosas case POWERPC_EXCP_FP: 709da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 710ccfca2fcSFabiano Rosas trace_ppc_excp_fp_ignore(); 7113680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 712ccfca2fcSFabiano Rosas return; 713ccfca2fcSFabiano Rosas } 714ccfca2fcSFabiano Rosas /* 715ab452503SBALATON Zoltan * NIP always points to the faulting instruction for FP exceptions, 716ab452503SBALATON Zoltan * so always use store_next and claim we are precise in the MSR. 717ccfca2fcSFabiano Rosas */ 718ccfca2fcSFabiano Rosas msr |= 0x00100000; 719ccfca2fcSFabiano Rosas break; 720ccfca2fcSFabiano Rosas case POWERPC_EXCP_INVAL: 721ccfca2fcSFabiano Rosas trace_ppc_excp_inval(env->nip); 722ccfca2fcSFabiano Rosas msr |= 0x00080000; 723ccfca2fcSFabiano Rosas break; 724ccfca2fcSFabiano Rosas case POWERPC_EXCP_PRIV: 725ccfca2fcSFabiano Rosas msr |= 0x00040000; 726ccfca2fcSFabiano Rosas break; 727ccfca2fcSFabiano Rosas case POWERPC_EXCP_TRAP: 728ccfca2fcSFabiano Rosas msr |= 0x00020000; 729ccfca2fcSFabiano Rosas break; 730ccfca2fcSFabiano Rosas default: 731ccfca2fcSFabiano Rosas /* Should never occur */ 732bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 733ccfca2fcSFabiano Rosas env->error_code); 734ccfca2fcSFabiano Rosas break; 735ccfca2fcSFabiano Rosas } 736ccfca2fcSFabiano Rosas break; 737ccfca2fcSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 7383b578635SFabiano Rosas { 7393b578635SFabiano Rosas int lev = env->error_code; 740ccfca2fcSFabiano Rosas 7413b578635SFabiano Rosas if (lev == 1 && cpu->vhyp) { 742ccfca2fcSFabiano Rosas dump_hcall(env); 743ccfca2fcSFabiano Rosas } else { 744ccfca2fcSFabiano Rosas dump_syscall(env); 745ccfca2fcSFabiano Rosas } 746ccfca2fcSFabiano Rosas 747ccfca2fcSFabiano Rosas /* 748ccfca2fcSFabiano Rosas * We need to correct the NIP which in this case is supposed 749ccfca2fcSFabiano Rosas * to point to the next instruction 750ccfca2fcSFabiano Rosas */ 751ccfca2fcSFabiano Rosas env->nip += 4; 752ccfca2fcSFabiano Rosas 7533b578635SFabiano Rosas /* 7543b578635SFabiano Rosas * The Virtual Open Firmware (VOF) relies on the 'sc 1' 7553b578635SFabiano Rosas * instruction to communicate with QEMU. The pegasos2 machine 7563b578635SFabiano Rosas * uses VOF and the 7xx CPUs, so although the 7xx don't have 7573b578635SFabiano Rosas * HV mode, we need to keep hypercall support. 7583b578635SFabiano Rosas */ 7593b578635SFabiano Rosas if (lev == 1 && cpu->vhyp) { 760c700b5e1SNicholas Piggin cpu->vhyp_class->hypercall(cpu->vhyp, cpu); 7612c71b4f6SNicholas Piggin powerpc_reset_excp_state(cpu); 762ccfca2fcSFabiano Rosas return; 763ccfca2fcSFabiano Rosas } 7643b578635SFabiano Rosas 765ccfca2fcSFabiano Rosas break; 7663b578635SFabiano Rosas } 767ccfca2fcSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 768ccfca2fcSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 769ccfca2fcSFabiano Rosas break; 770ccfca2fcSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 7718e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 772bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 773bc30c1c6SBALATON Zoltan "Trying to deliver power-saving system reset exception " 774bc30c1c6SBALATON Zoltan "%d with no HV support\n", excp); 775ccfca2fcSFabiano Rosas } 776ccfca2fcSFabiano Rosas break; 777ccfca2fcSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 778ccfca2fcSFabiano Rosas break; 779ccfca2fcSFabiano Rosas case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 780ccfca2fcSFabiano Rosas case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 781ccfca2fcSFabiano Rosas case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 782ccfca2fcSFabiano Rosas ppc_excp_debug_sw_tlb(env, excp); 783ccfca2fcSFabiano Rosas msr |= env->crf[0] << 28; 784ccfca2fcSFabiano Rosas msr |= env->error_code; /* key, D/I, S/L bits */ 785ccfca2fcSFabiano Rosas /* Set way using a LRU mechanism */ 786ccfca2fcSFabiano Rosas msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 787ccfca2fcSFabiano Rosas break; 788ccfca2fcSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 789ccfca2fcSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 790ccfca2fcSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 791ccfca2fcSFabiano Rosas case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 792bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 793ccfca2fcSFabiano Rosas powerpc_excp_name(excp)); 794ccfca2fcSFabiano Rosas break; 795ccfca2fcSFabiano Rosas default: 796bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 797bc30c1c6SBALATON Zoltan excp); 798ccfca2fcSFabiano Rosas break; 799ccfca2fcSFabiano Rosas } 800ccfca2fcSFabiano Rosas 801ccfca2fcSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 802ccfca2fcSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 803ccfca2fcSFabiano Rosas } 804fe4b5c4cSFabiano Rosas env->spr[SPR_SRR0] = env->nip; 805fe4b5c4cSFabiano Rosas env->spr[SPR_SRR1] = msr; 806ccfca2fcSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 807ccfca2fcSFabiano Rosas } 808ccfca2fcSFabiano Rosas 80952926b0dSFabiano Rosas static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) 81052926b0dSFabiano Rosas { 81152926b0dSFabiano Rosas CPUPPCState *env = &cpu->env; 81252926b0dSFabiano Rosas target_ulong msr, new_msr, vector; 81352926b0dSFabiano Rosas 81452926b0dSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 81552926b0dSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 81652926b0dSFabiano Rosas 817ab452503SBALATON Zoltan /* new interrupt handler msr preserves ME unless explicitly overridden */ 8181f6faf8bSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 81952926b0dSFabiano Rosas 820ab452503SBALATON Zoltan /* HV emu assistance interrupt only exists on server arch 2.05 or later */ 8211f6faf8bSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 82252926b0dSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 82352926b0dSFabiano Rosas } 82452926b0dSFabiano Rosas 82552926b0dSFabiano Rosas vector = env->excp_vectors[excp]; 82652926b0dSFabiano Rosas if (vector == (target_ulong)-1ULL) { 827bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 828bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 82952926b0dSFabiano Rosas } 83052926b0dSFabiano Rosas vector |= env->excp_prefix; 83152926b0dSFabiano Rosas 83252926b0dSFabiano Rosas switch (excp) { 83352926b0dSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 834819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 83552926b0dSFabiano Rosas /* machine check exceptions don't have ME set */ 83652926b0dSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 83752926b0dSFabiano Rosas break; 83852926b0dSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 83952926b0dSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 84052926b0dSFabiano Rosas break; 84152926b0dSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 84252926b0dSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 84352926b0dSFabiano Rosas msr |= env->error_code; 84452926b0dSFabiano Rosas break; 84552926b0dSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 84652926b0dSFabiano Rosas break; 84752926b0dSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 84852926b0dSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 84952926b0dSFabiano Rosas /* 85052926b0dSFabiano Rosas * Note: the opcode fields will not be set properly for a 85152926b0dSFabiano Rosas * direct store load/store, but nobody cares as nobody 85252926b0dSFabiano Rosas * actually uses direct store segments. 85352926b0dSFabiano Rosas */ 85452926b0dSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 85552926b0dSFabiano Rosas break; 85652926b0dSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 85752926b0dSFabiano Rosas switch (env->error_code & ~0xF) { 85852926b0dSFabiano Rosas case POWERPC_EXCP_FP: 859da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 86052926b0dSFabiano Rosas trace_ppc_excp_fp_ignore(); 8613680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 86252926b0dSFabiano Rosas return; 86352926b0dSFabiano Rosas } 86452926b0dSFabiano Rosas /* 865ab452503SBALATON Zoltan * NIP always points to the faulting instruction for FP exceptions, 866ab452503SBALATON Zoltan * so always use store_next and claim we are precise in the MSR. 86752926b0dSFabiano Rosas */ 86852926b0dSFabiano Rosas msr |= 0x00100000; 86952926b0dSFabiano Rosas break; 87052926b0dSFabiano Rosas case POWERPC_EXCP_INVAL: 87152926b0dSFabiano Rosas trace_ppc_excp_inval(env->nip); 87252926b0dSFabiano Rosas msr |= 0x00080000; 87352926b0dSFabiano Rosas break; 87452926b0dSFabiano Rosas case POWERPC_EXCP_PRIV: 87552926b0dSFabiano Rosas msr |= 0x00040000; 87652926b0dSFabiano Rosas break; 87752926b0dSFabiano Rosas case POWERPC_EXCP_TRAP: 87852926b0dSFabiano Rosas msr |= 0x00020000; 87952926b0dSFabiano Rosas break; 88052926b0dSFabiano Rosas default: 88152926b0dSFabiano Rosas /* Should never occur */ 882bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 88352926b0dSFabiano Rosas env->error_code); 88452926b0dSFabiano Rosas break; 88552926b0dSFabiano Rosas } 88652926b0dSFabiano Rosas break; 88752926b0dSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 888bca2c6d9SFabiano Rosas { 889bca2c6d9SFabiano Rosas int lev = env->error_code; 89052926b0dSFabiano Rosas 8912306c606SBALATON Zoltan if (lev == 1 && cpu->vhyp) { 89252926b0dSFabiano Rosas dump_hcall(env); 89352926b0dSFabiano Rosas } else { 89452926b0dSFabiano Rosas dump_syscall(env); 89552926b0dSFabiano Rosas } 89652926b0dSFabiano Rosas 89752926b0dSFabiano Rosas /* 89852926b0dSFabiano Rosas * We need to correct the NIP which in this case is supposed 89952926b0dSFabiano Rosas * to point to the next instruction 90052926b0dSFabiano Rosas */ 90152926b0dSFabiano Rosas env->nip += 4; 90252926b0dSFabiano Rosas 903bca2c6d9SFabiano Rosas /* 904bca2c6d9SFabiano Rosas * The Virtual Open Firmware (VOF) relies on the 'sc 1' 905bca2c6d9SFabiano Rosas * instruction to communicate with QEMU. The pegasos2 machine 906bca2c6d9SFabiano Rosas * uses VOF and the 74xx CPUs, so although the 74xx don't have 907bca2c6d9SFabiano Rosas * HV mode, we need to keep hypercall support. 908bca2c6d9SFabiano Rosas */ 9092306c606SBALATON Zoltan if (lev == 1 && cpu->vhyp) { 910c700b5e1SNicholas Piggin cpu->vhyp_class->hypercall(cpu->vhyp, cpu); 9112c71b4f6SNicholas Piggin powerpc_reset_excp_state(cpu); 91252926b0dSFabiano Rosas return; 91352926b0dSFabiano Rosas } 914bca2c6d9SFabiano Rosas 91552926b0dSFabiano Rosas break; 916bca2c6d9SFabiano Rosas } 91752926b0dSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 91852926b0dSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 91952926b0dSFabiano Rosas break; 92052926b0dSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 9218e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 922bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 923bc30c1c6SBALATON Zoltan "Trying to deliver power-saving system reset " 92452926b0dSFabiano Rosas "exception %d with no HV support\n", excp); 92552926b0dSFabiano Rosas } 92652926b0dSFabiano Rosas break; 92752926b0dSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 92852926b0dSFabiano Rosas break; 92952926b0dSFabiano Rosas case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 93052926b0dSFabiano Rosas break; 93152926b0dSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 93252926b0dSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 93352926b0dSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 93452926b0dSFabiano Rosas case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 93552926b0dSFabiano Rosas case POWERPC_EXCP_VPUA: /* Vector assist exception */ 936bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 93752926b0dSFabiano Rosas powerpc_excp_name(excp)); 93852926b0dSFabiano Rosas break; 93952926b0dSFabiano Rosas default: 940bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 941bc30c1c6SBALATON Zoltan excp); 94252926b0dSFabiano Rosas break; 94352926b0dSFabiano Rosas } 94452926b0dSFabiano Rosas 94552926b0dSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 94652926b0dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 94752926b0dSFabiano Rosas } 948f82db777SFabiano Rosas env->spr[SPR_SRR0] = env->nip; 949f82db777SFabiano Rosas env->spr[SPR_SRR1] = msr; 95052926b0dSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 95152926b0dSFabiano Rosas } 95252926b0dSFabiano Rosas 953180952ceSFabiano Rosas static void powerpc_excp_booke(PowerPCCPU *cpu, int excp) 954180952ceSFabiano Rosas { 955180952ceSFabiano Rosas CPUPPCState *env = &cpu->env; 956180952ceSFabiano Rosas target_ulong msr, new_msr, vector; 957ab452503SBALATON Zoltan int srr0 = SPR_SRR0, srr1 = SPR_SRR1; 958180952ceSFabiano Rosas 959ab452503SBALATON Zoltan /* 960ab452503SBALATON Zoltan * Book E does not play games with certain bits of xSRR1 being MSR save 961ab452503SBALATON Zoltan * bits and others being error status. xSRR1 is the old MSR, period. 962ab452503SBALATON Zoltan */ 963180952ceSFabiano Rosas msr = env->msr; 964180952ceSFabiano Rosas 965ab452503SBALATON Zoltan /* new interrupt handler msr preserves ME unless explicitly overridden */ 9669dc20cc3SFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 967180952ceSFabiano Rosas 968ab452503SBALATON Zoltan /* HV emu assistance interrupt only exists on server arch 2.05 or later */ 9699dc20cc3SFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 970180952ceSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 971180952ceSFabiano Rosas } 972180952ceSFabiano Rosas 973180952ceSFabiano Rosas #ifdef TARGET_PPC64 974180952ceSFabiano Rosas /* 975180952ceSFabiano Rosas * SPEU and VPU share the same IVOR but they exist in different 976180952ceSFabiano Rosas * processors. SPEU is e500v1/2 only and VPU is e6500 only. 977180952ceSFabiano Rosas */ 9789dc20cc3SFabiano Rosas if (excp == POWERPC_EXCP_VPU) { 979180952ceSFabiano Rosas excp = POWERPC_EXCP_SPEU; 980180952ceSFabiano Rosas } 981180952ceSFabiano Rosas #endif 982180952ceSFabiano Rosas 983180952ceSFabiano Rosas vector = env->excp_vectors[excp]; 984180952ceSFabiano Rosas if (vector == (target_ulong)-1ULL) { 985bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 986bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 987180952ceSFabiano Rosas } 988180952ceSFabiano Rosas vector |= env->excp_prefix; 989180952ceSFabiano Rosas 990180952ceSFabiano Rosas switch (excp) { 991180952ceSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 992180952ceSFabiano Rosas srr0 = SPR_BOOKE_CSRR0; 993180952ceSFabiano Rosas srr1 = SPR_BOOKE_CSRR1; 994180952ceSFabiano Rosas break; 995180952ceSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 996819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 997180952ceSFabiano Rosas /* machine check exceptions don't have ME set */ 998180952ceSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 999180952ceSFabiano Rosas 1000180952ceSFabiano Rosas /* FIXME: choose one or the other based on CPU type */ 1001180952ceSFabiano Rosas srr0 = SPR_BOOKE_MCSRR0; 1002180952ceSFabiano Rosas srr1 = SPR_BOOKE_MCSRR1; 1003180952ceSFabiano Rosas 1004180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR0] = env->nip; 1005180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR1] = msr; 1006db403211SFabiano Rosas 1007180952ceSFabiano Rosas break; 1008180952ceSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 1009afdbc869SFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]); 1010180952ceSFabiano Rosas break; 1011180952ceSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 1012180952ceSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 1013180952ceSFabiano Rosas break; 1014180952ceSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 1015180952ceSFabiano Rosas if (env->mpic_proxy) { 1016bc30c1c6SBALATON Zoltan CPUState *cs = env_cpu(env); 1017180952ceSFabiano Rosas /* IACK the IRQ on delivery */ 1018180952ceSFabiano Rosas env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); 1019180952ceSFabiano Rosas } 1020180952ceSFabiano Rosas break; 1021180952ceSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 1022180952ceSFabiano Rosas break; 1023180952ceSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 1024180952ceSFabiano Rosas switch (env->error_code & ~0xF) { 1025180952ceSFabiano Rosas case POWERPC_EXCP_FP: 1026da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 1027180952ceSFabiano Rosas trace_ppc_excp_fp_ignore(); 10283680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 1029180952ceSFabiano Rosas return; 1030180952ceSFabiano Rosas } 1031180952ceSFabiano Rosas /* 1032ab452503SBALATON Zoltan * NIP always points to the faulting instruction for FP exceptions, 1033ab452503SBALATON Zoltan * so always use store_next and claim we are precise in the MSR. 1034180952ceSFabiano Rosas */ 1035180952ceSFabiano Rosas msr |= 0x00100000; 1036180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_FP; 1037180952ceSFabiano Rosas break; 1038180952ceSFabiano Rosas case POWERPC_EXCP_INVAL: 1039180952ceSFabiano Rosas trace_ppc_excp_inval(env->nip); 1040180952ceSFabiano Rosas msr |= 0x00080000; 1041180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PIL; 1042180952ceSFabiano Rosas break; 1043180952ceSFabiano Rosas case POWERPC_EXCP_PRIV: 1044180952ceSFabiano Rosas msr |= 0x00040000; 1045180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PPR; 1046180952ceSFabiano Rosas break; 1047180952ceSFabiano Rosas case POWERPC_EXCP_TRAP: 1048180952ceSFabiano Rosas msr |= 0x00020000; 1049180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PTR; 1050180952ceSFabiano Rosas break; 1051180952ceSFabiano Rosas default: 1052180952ceSFabiano Rosas /* Should never occur */ 1053bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 1054180952ceSFabiano Rosas env->error_code); 1055180952ceSFabiano Rosas break; 1056180952ceSFabiano Rosas } 1057180952ceSFabiano Rosas break; 1058180952ceSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 1059180952ceSFabiano Rosas dump_syscall(env); 1060180952ceSFabiano Rosas 1061180952ceSFabiano Rosas /* 1062180952ceSFabiano Rosas * We need to correct the NIP which in this case is supposed 1063180952ceSFabiano Rosas * to point to the next instruction 1064180952ceSFabiano Rosas */ 1065180952ceSFabiano Rosas env->nip += 4; 1066180952ceSFabiano Rosas break; 1067180952ceSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 1068180952ceSFabiano Rosas case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 1069180952ceSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 1070180952ceSFabiano Rosas break; 1071180952ceSFabiano Rosas case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 1072180952ceSFabiano Rosas /* FIT on 4xx */ 1073180952ceSFabiano Rosas trace_ppc_excp_print("FIT"); 1074180952ceSFabiano Rosas break; 1075180952ceSFabiano Rosas case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 1076180952ceSFabiano Rosas trace_ppc_excp_print("WDT"); 1077180952ceSFabiano Rosas srr0 = SPR_BOOKE_CSRR0; 1078180952ceSFabiano Rosas srr1 = SPR_BOOKE_CSRR1; 1079180952ceSFabiano Rosas break; 1080180952ceSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 1081180952ceSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 1082180952ceSFabiano Rosas break; 1083180952ceSFabiano Rosas case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 1084180952ceSFabiano Rosas if (env->flags & POWERPC_FLAG_DE) { 1085180952ceSFabiano Rosas /* FIXME: choose one or the other based on CPU type */ 1086180952ceSFabiano Rosas srr0 = SPR_BOOKE_DSRR0; 1087180952ceSFabiano Rosas srr1 = SPR_BOOKE_DSRR1; 1088180952ceSFabiano Rosas 1089180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR0] = env->nip; 1090180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR1] = msr; 1091180952ceSFabiano Rosas 1092180952ceSFabiano Rosas /* DBSR already modified by caller */ 1093180952ceSFabiano Rosas } else { 1094bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 1095bc30c1c6SBALATON Zoltan "Debug exception triggered on unsupported model\n"); 1096180952ceSFabiano Rosas } 1097180952ceSFabiano Rosas break; 1098180952ceSFabiano Rosas case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ 1099180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_SPV; 1100180952ceSFabiano Rosas break; 11019364df26SNicholas Piggin case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 11029364df26SNicholas Piggin break; 11039364df26SNicholas Piggin case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 11049364df26SNicholas Piggin srr0 = SPR_BOOKE_CSRR0; 11059364df26SNicholas Piggin srr1 = SPR_BOOKE_CSRR1; 11069364df26SNicholas Piggin break; 1107180952ceSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 11088e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 1109bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 1110bc30c1c6SBALATON Zoltan "Trying to deliver power-saving system reset " 1111180952ceSFabiano Rosas "exception %d with no HV support\n", excp); 1112180952ceSFabiano Rosas } 1113180952ceSFabiano Rosas break; 1114180952ceSFabiano Rosas case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ 1115180952ceSFabiano Rosas case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ 1116bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 1117180952ceSFabiano Rosas powerpc_excp_name(excp)); 1118180952ceSFabiano Rosas break; 1119180952ceSFabiano Rosas default: 1120bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 1121bc30c1c6SBALATON Zoltan excp); 1122180952ceSFabiano Rosas break; 1123180952ceSFabiano Rosas } 1124180952ceSFabiano Rosas 1125f6c2d68bSBALATON Zoltan #ifdef TARGET_PPC64 1126180952ceSFabiano Rosas if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { 1127180952ceSFabiano Rosas /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ 1128180952ceSFabiano Rosas new_msr |= (target_ulong)1 << MSR_CM; 1129180952ceSFabiano Rosas } else { 1130180952ceSFabiano Rosas vector = (uint32_t)vector; 1131180952ceSFabiano Rosas } 1132180952ceSFabiano Rosas #endif 1133180952ceSFabiano Rosas 1134180952ceSFabiano Rosas env->spr[srr0] = env->nip; 1135180952ceSFabiano Rosas env->spr[srr1] = msr; 1136180952ceSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 1137180952ceSFabiano Rosas } 1138180952ceSFabiano Rosas 11397cebc5dbSNicholas Piggin /* 11407cebc5dbSNicholas Piggin * When running a nested HV guest under vhyp, external interrupts are 11417cebc5dbSNicholas Piggin * delivered as HVIRT. 11427cebc5dbSNicholas Piggin */ 11437cebc5dbSNicholas Piggin static bool books_vhyp_promotes_external_to_hvirt(PowerPCCPU *cpu) 11447cebc5dbSNicholas Piggin { 11457cebc5dbSNicholas Piggin if (cpu->vhyp) { 11467cebc5dbSNicholas Piggin return vhyp_cpu_in_nested(cpu); 11477cebc5dbSNicholas Piggin } 11487cebc5dbSNicholas Piggin return false; 11497cebc5dbSNicholas Piggin } 11507cebc5dbSNicholas Piggin 115130c4e426SFabiano Rosas #ifdef TARGET_PPC64 11524c6cf6b2SNicholas Piggin /* 11534c6cf6b2SNicholas Piggin * When running under vhyp, hcalls are always intercepted and sent to the 11544c6cf6b2SNicholas Piggin * vhc->hypercall handler. 11554c6cf6b2SNicholas Piggin */ 11564c6cf6b2SNicholas Piggin static bool books_vhyp_handles_hcall(PowerPCCPU *cpu) 11574c6cf6b2SNicholas Piggin { 11584c6cf6b2SNicholas Piggin if (cpu->vhyp) { 11597cebc5dbSNicholas Piggin return !vhyp_cpu_in_nested(cpu); 11607cebc5dbSNicholas Piggin } 11617cebc5dbSNicholas Piggin return false; 11627cebc5dbSNicholas Piggin } 11637cebc5dbSNicholas Piggin 11647cebc5dbSNicholas Piggin /* 11657cebc5dbSNicholas Piggin * When running a nested KVM HV guest under vhyp, HV exceptions are not 11667cebc5dbSNicholas Piggin * delivered to the guest (because there is no concept of HV support), but 11677cebc5dbSNicholas Piggin * rather they are sent to the vhyp to exit from the L2 back to the L1 and 11687cebc5dbSNicholas Piggin * return from the H_ENTER_NESTED hypercall. 11697cebc5dbSNicholas Piggin */ 11707cebc5dbSNicholas Piggin static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu) 11717cebc5dbSNicholas Piggin { 11727cebc5dbSNicholas Piggin if (cpu->vhyp) { 11737cebc5dbSNicholas Piggin return vhyp_cpu_in_nested(cpu); 11744c6cf6b2SNicholas Piggin } 11754c6cf6b2SNicholas Piggin return false; 11764c6cf6b2SNicholas Piggin } 11774c6cf6b2SNicholas Piggin 11785a5d3b23SNicholas Piggin #ifdef CONFIG_TCG 11795a5d3b23SNicholas Piggin static bool is_prefix_insn(CPUPPCState *env, uint32_t insn) 11805a5d3b23SNicholas Piggin { 11815a5d3b23SNicholas Piggin if (!(env->insns_flags2 & PPC2_ISA310)) { 11825a5d3b23SNicholas Piggin return false; 11835a5d3b23SNicholas Piggin } 11845a5d3b23SNicholas Piggin return ((insn & 0xfc000000) == 0x04000000); 11855a5d3b23SNicholas Piggin } 11865a5d3b23SNicholas Piggin 11875a5d3b23SNicholas Piggin static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp) 11885a5d3b23SNicholas Piggin { 11895a5d3b23SNicholas Piggin CPUPPCState *env = &cpu->env; 11905a5d3b23SNicholas Piggin 1191c8fd9667SNicholas Piggin if (!(env->insns_flags2 & PPC2_ISA310)) { 1192c8fd9667SNicholas Piggin return false; 1193c8fd9667SNicholas Piggin } 1194c8fd9667SNicholas Piggin 11955a5d3b23SNicholas Piggin if (!tcg_enabled()) { 11965a5d3b23SNicholas Piggin /* 11975a5d3b23SNicholas Piggin * This does not load instructions and set the prefix bit correctly 11985a5d3b23SNicholas Piggin * for injected interrupts with KVM. That may have to be discovered 11995a5d3b23SNicholas Piggin * and set by the KVM layer before injecting. 12005a5d3b23SNicholas Piggin */ 12015a5d3b23SNicholas Piggin return false; 12025a5d3b23SNicholas Piggin } 12035a5d3b23SNicholas Piggin 12045a5d3b23SNicholas Piggin switch (excp) { 1205c8fd9667SNicholas Piggin case POWERPC_EXCP_MCHECK: 1206c8fd9667SNicholas Piggin if (!(env->error_code & PPC_BIT(42))) { 1207c8fd9667SNicholas Piggin /* 1208c8fd9667SNicholas Piggin * Fetch attempt caused a machine check, so attempting to fetch 1209c8fd9667SNicholas Piggin * again would cause a recursive machine check. 1210c8fd9667SNicholas Piggin */ 1211c8fd9667SNicholas Piggin return false; 1212c8fd9667SNicholas Piggin } 1213c8fd9667SNicholas Piggin break; 12145a5d3b23SNicholas Piggin case POWERPC_EXCP_HDSI: 12155a5d3b23SNicholas Piggin /* HDSI PRTABLE_FAULT has the originating access type in error_code */ 12165a5d3b23SNicholas Piggin if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) && 12175a5d3b23SNicholas Piggin (env->error_code == MMU_INST_FETCH)) { 12185a5d3b23SNicholas Piggin /* 12195a5d3b23SNicholas Piggin * Fetch failed due to partition scope translation, so prefix 12205a5d3b23SNicholas Piggin * indication is not relevant (and attempting to load the 12215a5d3b23SNicholas Piggin * instruction at NIP would cause recursive faults with the same 12225a5d3b23SNicholas Piggin * translation). 12235a5d3b23SNicholas Piggin */ 1224c8fd9667SNicholas Piggin return false; 12255a5d3b23SNicholas Piggin } 1226c8fd9667SNicholas Piggin break; 1227c8fd9667SNicholas Piggin 12285a5d3b23SNicholas Piggin case POWERPC_EXCP_DSI: 12295a5d3b23SNicholas Piggin case POWERPC_EXCP_DSEG: 12305a5d3b23SNicholas Piggin case POWERPC_EXCP_ALIGN: 12315a5d3b23SNicholas Piggin case POWERPC_EXCP_PROGRAM: 12325a5d3b23SNicholas Piggin case POWERPC_EXCP_FPU: 12335a5d3b23SNicholas Piggin case POWERPC_EXCP_TRACE: 12345a5d3b23SNicholas Piggin case POWERPC_EXCP_HV_EMU: 12355a5d3b23SNicholas Piggin case POWERPC_EXCP_VPU: 12365a5d3b23SNicholas Piggin case POWERPC_EXCP_VSXU: 12375a5d3b23SNicholas Piggin case POWERPC_EXCP_FU: 1238c8fd9667SNicholas Piggin case POWERPC_EXCP_HV_FU: 12395a5d3b23SNicholas Piggin break; 12405a5d3b23SNicholas Piggin default: 12415a5d3b23SNicholas Piggin return false; 12425a5d3b23SNicholas Piggin } 1243c8fd9667SNicholas Piggin 1244c8fd9667SNicholas Piggin return is_prefix_insn(env, ppc_ldl_code(env, env->nip)); 1245c8fd9667SNicholas Piggin } 12465a5d3b23SNicholas Piggin #else 12475a5d3b23SNicholas Piggin static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp) 12485a5d3b23SNicholas Piggin { 12495a5d3b23SNicholas Piggin return false; 12505a5d3b23SNicholas Piggin } 12515a5d3b23SNicholas Piggin #endif 12525a5d3b23SNicholas Piggin 12539f338e4dSFabiano Rosas static void powerpc_excp_books(PowerPCCPU *cpu, int excp) 12549f338e4dSFabiano Rosas { 12559f338e4dSFabiano Rosas CPUPPCState *env = &cpu->env; 12569f338e4dSFabiano Rosas target_ulong msr, new_msr, vector; 1257ab452503SBALATON Zoltan int srr0 = SPR_SRR0, srr1 = SPR_SRR1, lev = -1; 12589f338e4dSFabiano Rosas 12599f338e4dSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 12609f338e4dSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 12619f338e4dSFabiano Rosas 12629f338e4dSFabiano Rosas /* 1263ab452503SBALATON Zoltan * new interrupt handler msr preserves HV and ME unless explicitly 1264ab452503SBALATON Zoltan * overridden 12659f338e4dSFabiano Rosas */ 12669f338e4dSFabiano Rosas new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); 12679f338e4dSFabiano Rosas 12689f338e4dSFabiano Rosas /* 12699f338e4dSFabiano Rosas * check for special resume at 0x100 from doze/nap/sleep/winkle on 12709f338e4dSFabiano Rosas * P7/P8/P9 12719f338e4dSFabiano Rosas */ 12729f338e4dSFabiano Rosas if (env->resume_as_sreset) { 12733f88a89dSBALATON Zoltan excp = powerpc_reset_wakeup(env, excp, &msr); 12749f338e4dSFabiano Rosas } 12759f338e4dSFabiano Rosas 12769f338e4dSFabiano Rosas /* 127730c4e426SFabiano Rosas * We don't want to generate a Hypervisor Emulation Assistance 12786c242e79SNicholas Piggin * Interrupt if we don't have HVB in msr_mask (PAPR mode), 12796c242e79SNicholas Piggin * unless running a nested-hv guest, in which case the L1 12806c242e79SNicholas Piggin * kernel wants the interrupt. 12819f338e4dSFabiano Rosas */ 12826c242e79SNicholas Piggin if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB) && 12836c242e79SNicholas Piggin !books_vhyp_handles_hv_excp(cpu)) { 12849f338e4dSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 12859f338e4dSFabiano Rosas } 12869f338e4dSFabiano Rosas 12879f338e4dSFabiano Rosas vector = env->excp_vectors[excp]; 12889f338e4dSFabiano Rosas if (vector == (target_ulong)-1ULL) { 1289bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 1290bc30c1c6SBALATON Zoltan "Raised an exception without defined vector %d\n", excp); 12919f338e4dSFabiano Rosas } 12929f338e4dSFabiano Rosas vector |= env->excp_prefix; 12939f338e4dSFabiano Rosas 12945a5d3b23SNicholas Piggin if (is_prefix_insn_excp(cpu, excp)) { 12955a5d3b23SNicholas Piggin msr |= PPC_BIT(34); 12965a5d3b23SNicholas Piggin } 12975a5d3b23SNicholas Piggin 12989f338e4dSFabiano Rosas switch (excp) { 12999f338e4dSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1300819b31b0SBALATON Zoltan powerpc_mcheck_checkstop(env); 13019f338e4dSFabiano Rosas if (env->msr_mask & MSR_HVB) { 13029f338e4dSFabiano Rosas /* 13039f338e4dSFabiano Rosas * ISA specifies HV, but can be delivered to guest with HV 13049f338e4dSFabiano Rosas * clear (e.g., see FWNMI in PAPR). 13059f338e4dSFabiano Rosas */ 13069f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 130743453161SNicholas Piggin 130843453161SNicholas Piggin /* HV machine check exceptions don't have ME set */ 13099f338e4dSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 131043453161SNicholas Piggin } 13119f338e4dSFabiano Rosas 131255a7fa34SNicholas Piggin msr |= env->error_code; 13139f338e4dSFabiano Rosas break; 131455a7fa34SNicholas Piggin 13159f338e4dSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 13169f338e4dSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 13179f338e4dSFabiano Rosas break; 13189f338e4dSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 13199f338e4dSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 13209f338e4dSFabiano Rosas msr |= env->error_code; 13219f338e4dSFabiano Rosas break; 13229f338e4dSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 13239f338e4dSFabiano Rosas { 13249f338e4dSFabiano Rosas bool lpes0; 13259f338e4dSFabiano Rosas 1326ab452503SBALATON Zoltan /* LPES0 is only taken into consideration if we support HV mode */ 132767baff77SFabiano Rosas if (!env->has_hv_mode) { 132867baff77SFabiano Rosas break; 13299f338e4dSFabiano Rosas } 133067baff77SFabiano Rosas lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 13319f338e4dSFabiano Rosas if (!lpes0) { 13329f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 13339f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 13349f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 13359f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 13369f338e4dSFabiano Rosas } 13379f338e4dSFabiano Rosas break; 13389f338e4dSFabiano Rosas } 13399f338e4dSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 13404ee5d281SNicholas Piggin /* Optional DSISR update was removed from ISA v3.0 */ 13414ee5d281SNicholas Piggin if (!(env->insns_flags2 & PPC2_ISA300)) { 13429f338e4dSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 13439f338e4dSFabiano Rosas /* 13449f338e4dSFabiano Rosas * Note: the opcode fields will not be set properly for a 13459f338e4dSFabiano Rosas * direct store load/store, but nobody cares as nobody 13469f338e4dSFabiano Rosas * actually uses direct store segments. 13479f338e4dSFabiano Rosas */ 13489f338e4dSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 13494ee5d281SNicholas Piggin } 13509f338e4dSFabiano Rosas break; 13519f338e4dSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 13529f338e4dSFabiano Rosas switch (env->error_code & ~0xF) { 13539f338e4dSFabiano Rosas case POWERPC_EXCP_FP: 1354da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 13559f338e4dSFabiano Rosas trace_ppc_excp_fp_ignore(); 13563680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 13579f338e4dSFabiano Rosas return; 13589f338e4dSFabiano Rosas } 13599f338e4dSFabiano Rosas /* 1360ab452503SBALATON Zoltan * NIP always points to the faulting instruction for FP exceptions, 1361ab452503SBALATON Zoltan * so always use store_next and claim we are precise in the MSR. 13629f338e4dSFabiano Rosas */ 13639f338e4dSFabiano Rosas msr |= 0x00100000; 13649f338e4dSFabiano Rosas break; 13659f338e4dSFabiano Rosas case POWERPC_EXCP_INVAL: 13669f338e4dSFabiano Rosas trace_ppc_excp_inval(env->nip); 13679f338e4dSFabiano Rosas msr |= 0x00080000; 13689f338e4dSFabiano Rosas break; 13699f338e4dSFabiano Rosas case POWERPC_EXCP_PRIV: 13709f338e4dSFabiano Rosas msr |= 0x00040000; 13719f338e4dSFabiano Rosas break; 13729f338e4dSFabiano Rosas case POWERPC_EXCP_TRAP: 13739f338e4dSFabiano Rosas msr |= 0x00020000; 13749f338e4dSFabiano Rosas break; 13759f338e4dSFabiano Rosas default: 13769f338e4dSFabiano Rosas /* Should never occur */ 1377bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n", 13789f338e4dSFabiano Rosas env->error_code); 13799f338e4dSFabiano Rosas break; 13809f338e4dSFabiano Rosas } 13819f338e4dSFabiano Rosas break; 13829f338e4dSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 13839f338e4dSFabiano Rosas lev = env->error_code; 13849f338e4dSFabiano Rosas 13852306c606SBALATON Zoltan if (lev == 1 && cpu->vhyp) { 13869f338e4dSFabiano Rosas dump_hcall(env); 13879f338e4dSFabiano Rosas } else { 13889f338e4dSFabiano Rosas dump_syscall(env); 13899f338e4dSFabiano Rosas } 13909f338e4dSFabiano Rosas 13919f338e4dSFabiano Rosas /* 13929f338e4dSFabiano Rosas * We need to correct the NIP which in this case is supposed 13939f338e4dSFabiano Rosas * to point to the next instruction 13949f338e4dSFabiano Rosas */ 13959f338e4dSFabiano Rosas env->nip += 4; 13969f338e4dSFabiano Rosas 13979f338e4dSFabiano Rosas /* "PAPR mode" built-in hypercall emulation */ 13982306c606SBALATON Zoltan if (lev == 1 && books_vhyp_handles_hcall(cpu)) { 1399c700b5e1SNicholas Piggin cpu->vhyp_class->hypercall(cpu->vhyp, cpu); 14002c71b4f6SNicholas Piggin powerpc_reset_excp_state(cpu); 14019f338e4dSFabiano Rosas return; 14029f338e4dSFabiano Rosas } 1403eb701f30SNicholas Piggin if (env->insns_flags2 & PPC2_ISA310) { 1404eb701f30SNicholas Piggin /* ISAv3.1 puts LEV into SRR1 */ 1405eb701f30SNicholas Piggin msr |= lev << 20; 1406eb701f30SNicholas Piggin } 14079f338e4dSFabiano Rosas if (lev == 1) { 14089f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14099f338e4dSFabiano Rosas } 14109f338e4dSFabiano Rosas break; 14119f338e4dSFabiano Rosas case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ 14129f338e4dSFabiano Rosas lev = env->error_code; 14139f338e4dSFabiano Rosas dump_syscall(env); 14149f338e4dSFabiano Rosas env->nip += 4; 14159f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_EE); 14169f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 14179f338e4dSFabiano Rosas 14189f338e4dSFabiano Rosas vector += lev * 0x20; 14199f338e4dSFabiano Rosas 14209f338e4dSFabiano Rosas env->lr = env->nip; 14219f338e4dSFabiano Rosas env->ctr = msr; 14229f338e4dSFabiano Rosas break; 14239f338e4dSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 14249f338e4dSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 14259f338e4dSFabiano Rosas break; 14269f338e4dSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 14279f338e4dSFabiano Rosas /* A power-saving exception sets ME, otherwise it is unchanged */ 14288e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 14299f338e4dSFabiano Rosas /* indicate that we resumed from power save mode */ 14309f338e4dSFabiano Rosas msr |= 0x10000; 14319f338e4dSFabiano Rosas new_msr |= ((target_ulong)1 << MSR_ME); 14329f338e4dSFabiano Rosas } 14339f338e4dSFabiano Rosas if (env->msr_mask & MSR_HVB) { 14349f338e4dSFabiano Rosas /* 14359f338e4dSFabiano Rosas * ISA specifies HV, but can be delivered to guest with HV 14369f338e4dSFabiano Rosas * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). 14379f338e4dSFabiano Rosas */ 14389f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14399f338e4dSFabiano Rosas } else { 14408e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 1441bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), 1442bc30c1c6SBALATON Zoltan "Trying to deliver power-saving system reset " 14439f338e4dSFabiano Rosas "exception %d with no HV support\n", excp); 14449f338e4dSFabiano Rosas } 14459f338e4dSFabiano Rosas } 14469f338e4dSFabiano Rosas break; 144714895384SNicholas Piggin case POWERPC_EXCP_TRACE: /* Trace exception */ 144814895384SNicholas Piggin msr |= env->error_code; 144914895384SNicholas Piggin /* fall through */ 14509f338e4dSFabiano Rosas case POWERPC_EXCP_DSEG: /* Data segment exception */ 14519f338e4dSFabiano Rosas case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 1452fd7abfabSNicholas Piggin case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */ 1453c29b0704SNicholas Piggin case POWERPC_EXCP_PERFM: /* Performance monitor interrupt */ 14549f338e4dSFabiano Rosas break; 14559f338e4dSFabiano Rosas case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ 14569f338e4dSFabiano Rosas msr |= env->error_code; 14579f338e4dSFabiano Rosas /* fall through */ 14589f338e4dSFabiano Rosas case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 14599f338e4dSFabiano Rosas case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 14609f338e4dSFabiano Rosas case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ 14619f338e4dSFabiano Rosas case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ 14629f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 14639f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 14649f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14659f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 14669f338e4dSFabiano Rosas break; 1467a3c020d8SNicholas Piggin #ifdef CONFIG_TCG 1468a3c020d8SNicholas Piggin case POWERPC_EXCP_HV_EMU: { 1469a3c020d8SNicholas Piggin uint32_t insn = ppc_ldl_code(env, env->nip); 1470a3c020d8SNicholas Piggin env->spr[SPR_HEIR] = insn; 1471a3c020d8SNicholas Piggin if (is_prefix_insn(env, insn)) { 1472a3c020d8SNicholas Piggin uint32_t insn2 = ppc_ldl_code(env, env->nip + 4); 1473a3c020d8SNicholas Piggin env->spr[SPR_HEIR] <<= 32; 1474a3c020d8SNicholas Piggin env->spr[SPR_HEIR] |= insn2; 1475a3c020d8SNicholas Piggin } 1476a3c020d8SNicholas Piggin srr0 = SPR_HSRR0; 1477a3c020d8SNicholas Piggin srr1 = SPR_HSRR1; 1478a3c020d8SNicholas Piggin new_msr |= (target_ulong)MSR_HVB; 1479a3c020d8SNicholas Piggin new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 1480a3c020d8SNicholas Piggin break; 1481a3c020d8SNicholas Piggin } 1482a3c020d8SNicholas Piggin #endif 14839f338e4dSFabiano Rosas case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 14849f338e4dSFabiano Rosas case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ 14859f338e4dSFabiano Rosas case POWERPC_EXCP_FU: /* Facility unavailable exception */ 14869f338e4dSFabiano Rosas env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); 14879f338e4dSFabiano Rosas break; 14889f338e4dSFabiano Rosas case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ 14899f338e4dSFabiano Rosas env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); 14909f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 14919f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 14929f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14939f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 14949f338e4dSFabiano Rosas break; 1495cb76bbc4SDaniel Henrique Barboza case POWERPC_EXCP_PERFM_EBB: /* Performance Monitor EBB Exception */ 1496cb76bbc4SDaniel Henrique Barboza case POWERPC_EXCP_EXTERNAL_EBB: /* External EBB Exception */ 1497cb76bbc4SDaniel Henrique Barboza env->spr[SPR_BESCR] &= ~BESCR_GE; 1498cb76bbc4SDaniel Henrique Barboza 1499cb76bbc4SDaniel Henrique Barboza /* 1500cb76bbc4SDaniel Henrique Barboza * Save NIP for rfebb insn in SPR_EBBRR. Next nip is 1501cb76bbc4SDaniel Henrique Barboza * stored in the EBB Handler SPR_EBBHR. 1502cb76bbc4SDaniel Henrique Barboza */ 1503cb76bbc4SDaniel Henrique Barboza env->spr[SPR_EBBRR] = env->nip; 1504cb76bbc4SDaniel Henrique Barboza powerpc_set_excp_state(cpu, env->spr[SPR_EBBHR], env->msr); 1505cb76bbc4SDaniel Henrique Barboza 1506cb76bbc4SDaniel Henrique Barboza /* 1507cb76bbc4SDaniel Henrique Barboza * This exception is handled in userspace. No need to proceed. 1508cb76bbc4SDaniel Henrique Barboza */ 1509cb76bbc4SDaniel Henrique Barboza return; 15109f338e4dSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 15119f338e4dSFabiano Rosas case POWERPC_EXCP_VPUA: /* Vector assist exception */ 15129f338e4dSFabiano Rosas case POWERPC_EXCP_MAINT: /* Maintenance exception */ 151330c4e426SFabiano Rosas case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */ 1514bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "%s exception not implemented\n", 15159f338e4dSFabiano Rosas powerpc_excp_name(excp)); 15169f338e4dSFabiano Rosas break; 15179f338e4dSFabiano Rosas default: 1518bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 1519bc30c1c6SBALATON Zoltan excp); 15209f338e4dSFabiano Rosas break; 15219f338e4dSFabiano Rosas } 15229f338e4dSFabiano Rosas 15239f338e4dSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 15249f338e4dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 15259f338e4dSFabiano Rosas } 15269f338e4dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_SF; 15279f338e4dSFabiano Rosas 15289f338e4dSFabiano Rosas if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { 15299f338e4dSFabiano Rosas env->spr[srr0] = env->nip; 15309f338e4dSFabiano Rosas env->spr[srr1] = msr; 15319f338e4dSFabiano Rosas } 15329f338e4dSFabiano Rosas 15337cebc5dbSNicholas Piggin if ((new_msr & MSR_HVB) && books_vhyp_handles_hv_excp(cpu)) { 15347cebc5dbSNicholas Piggin /* Deliver interrupt to L1 by returning from the H_ENTER_NESTED call */ 1535c700b5e1SNicholas Piggin cpu->vhyp_class->deliver_hv_excp(cpu, excp); 15367cebc5dbSNicholas Piggin powerpc_reset_excp_state(cpu); 15377cebc5dbSNicholas Piggin } else { 15387cebc5dbSNicholas Piggin /* Sanity check */ 15397cebc5dbSNicholas Piggin if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) { 1540bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Trying to deliver HV exception (HSRR) %d " 1541bc30c1c6SBALATON Zoltan "with no HV support\n", excp); 15427cebc5dbSNicholas Piggin } 15439f338e4dSFabiano Rosas /* This can update new_msr and vector if AIL applies */ 154410895ab6SFabiano Rosas ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector); 15459f338e4dSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 15469f338e4dSFabiano Rosas } 15477cebc5dbSNicholas Piggin } 154830c4e426SFabiano Rosas #else 154930c4e426SFabiano Rosas static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp) 155030c4e426SFabiano Rosas { 155130c4e426SFabiano Rosas g_assert_not_reached(); 155230c4e426SFabiano Rosas } 1553f6c2d68bSBALATON Zoltan #endif /* TARGET_PPC64 */ 15549f338e4dSFabiano Rosas 155592c787deSPhilippe Mathieu-Daudé void powerpc_excp(PowerPCCPU *cpu, int excp) 1556dc88dd0aSFabiano Rosas { 1557dc88dd0aSFabiano Rosas CPUPPCState *env = &cpu->env; 1558dc88dd0aSFabiano Rosas 1559c6eaac89SFabiano Rosas if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { 1560bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n", 1561bc30c1c6SBALATON Zoltan excp); 1562c6eaac89SFabiano Rosas } 1563c6eaac89SFabiano Rosas 1564c6eaac89SFabiano Rosas qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx 1565c6eaac89SFabiano Rosas " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), 1566c6eaac89SFabiano Rosas excp, env->error_code); 15678a15cceeSBALATON Zoltan env->excp_stats[excp]++; 1568c6eaac89SFabiano Rosas 1569dc88dd0aSFabiano Rosas switch (env->excp_model) { 1570e808c2edSFabiano Rosas case POWERPC_EXCP_40x: 1571e808c2edSFabiano Rosas powerpc_excp_40x(cpu, excp); 1572e808c2edSFabiano Rosas break; 157358d178fbSFabiano Rosas case POWERPC_EXCP_6xx: 157458d178fbSFabiano Rosas powerpc_excp_6xx(cpu, excp); 157558d178fbSFabiano Rosas break; 1576ccfca2fcSFabiano Rosas case POWERPC_EXCP_7xx: 1577ccfca2fcSFabiano Rosas powerpc_excp_7xx(cpu, excp); 1578ccfca2fcSFabiano Rosas break; 157952926b0dSFabiano Rosas case POWERPC_EXCP_74xx: 158052926b0dSFabiano Rosas powerpc_excp_74xx(cpu, excp); 158152926b0dSFabiano Rosas break; 1582180952ceSFabiano Rosas case POWERPC_EXCP_BOOKE: 1583180952ceSFabiano Rosas powerpc_excp_booke(cpu, excp); 1584180952ceSFabiano Rosas break; 15859f338e4dSFabiano Rosas case POWERPC_EXCP_970: 15869f338e4dSFabiano Rosas case POWERPC_EXCP_POWER7: 15879f338e4dSFabiano Rosas case POWERPC_EXCP_POWER8: 15889f338e4dSFabiano Rosas case POWERPC_EXCP_POWER9: 15899f338e4dSFabiano Rosas case POWERPC_EXCP_POWER10: 1590c0d96407SAditya Gupta case POWERPC_EXCP_POWER11: 15919f338e4dSFabiano Rosas powerpc_excp_books(cpu, excp); 15929f338e4dSFabiano Rosas break; 1593dc88dd0aSFabiano Rosas default: 159428091374SFabiano Rosas g_assert_not_reached(); 1595dc88dd0aSFabiano Rosas } 1596dc88dd0aSFabiano Rosas } 1597dc88dd0aSFabiano Rosas 159897a8ea5aSAndreas Färber void ppc_cpu_do_interrupt(CPUState *cs) 1599c79c73f6SBlue Swirl { 160097a8ea5aSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 16015c26a5b3SAndreas Färber 160293130c84SFabiano Rosas powerpc_excp(cpu, cs->exception_index); 1603c79c73f6SBlue Swirl } 1604c79c73f6SBlue Swirl 1605f6c2d68bSBALATON Zoltan #ifdef TARGET_PPC64 1606c8e1de2eSMatheus Ferst #define P7_UNUSED_INTERRUPTS \ 1607c8e1de2eSMatheus Ferst (PPC_INTERRUPT_RESET | PPC_INTERRUPT_HVIRT | PPC_INTERRUPT_CEXT | \ 1608c8e1de2eSMatheus Ferst PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \ 1609c8e1de2eSMatheus Ferst PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \ 1610c8e1de2eSMatheus Ferst PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB) 1611c8e1de2eSMatheus Ferst 1612085cc364SHarsh Prateek Bora static int p7_interrupt_powersave(uint32_t pending_interrupts, 1613085cc364SHarsh Prateek Bora target_ulong lpcr) 16149c713713SMatheus Ferst { 1615085cc364SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_EXT) && 1616085cc364SHarsh Prateek Bora (lpcr & LPCR_P7_PECE0)) { 16179c713713SMatheus Ferst return PPC_INTERRUPT_EXT; 16189c713713SMatheus Ferst } 1619085cc364SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_DECR) && 1620085cc364SHarsh Prateek Bora (lpcr & LPCR_P7_PECE1)) { 16219c713713SMatheus Ferst return PPC_INTERRUPT_DECR; 16229c713713SMatheus Ferst } 1623085cc364SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_MCK) && 1624085cc364SHarsh Prateek Bora (lpcr & LPCR_P7_PECE2)) { 16259c713713SMatheus Ferst return PPC_INTERRUPT_MCK; 16269c713713SMatheus Ferst } 1627085cc364SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_HMI) && 1628085cc364SHarsh Prateek Bora (lpcr & LPCR_P7_PECE2)) { 16299c713713SMatheus Ferst return PPC_INTERRUPT_HMI; 16309c713713SMatheus Ferst } 1631085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_RESET) { 16329c713713SMatheus Ferst return PPC_INTERRUPT_RESET; 16339c713713SMatheus Ferst } 16349c713713SMatheus Ferst return 0; 16359c713713SMatheus Ferst } 16369c713713SMatheus Ferst 1637085cc364SHarsh Prateek Bora static int p7_next_unmasked_interrupt(CPUPPCState *env, 1638085cc364SHarsh Prateek Bora uint32_t pending_interrupts, 1639085cc364SHarsh Prateek Bora target_ulong lpcr) 1640bf303fb3SMatheus Ferst { 16414e6b7db2SBALATON Zoltan CPUState *cs = env_cpu(env); 16424e6b7db2SBALATON Zoltan 1643022b7128SMatheus Ferst /* Ignore MSR[EE] when coming out of some power management states */ 1644022b7128SMatheus Ferst bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; 1645bf303fb3SMatheus Ferst 1646085cc364SHarsh Prateek Bora assert((pending_interrupts & P7_UNUSED_INTERRUPTS) == 0); 1647c8e1de2eSMatheus Ferst 1648022b7128SMatheus Ferst if (cs->halted) { 1649022b7128SMatheus Ferst /* LPCR[PECE] controls which interrupts can exit power-saving mode */ 1650085cc364SHarsh Prateek Bora return p7_interrupt_powersave(pending_interrupts, lpcr); 1651022b7128SMatheus Ferst } 1652022b7128SMatheus Ferst 1653bf303fb3SMatheus Ferst /* Machine check exception */ 1654085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_MCK) { 1655bf303fb3SMatheus Ferst return PPC_INTERRUPT_MCK; 1656bf303fb3SMatheus Ferst } 1657bf303fb3SMatheus Ferst 1658bf303fb3SMatheus Ferst /* Hypervisor decrementer exception */ 1659085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDECR) { 1660bf303fb3SMatheus Ferst /* LPCR will be clear when not supported so this will work */ 1661bf303fb3SMatheus Ferst bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); 1662022b7128SMatheus Ferst if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { 1663bf303fb3SMatheus Ferst /* HDEC clears on delivery */ 1664bf303fb3SMatheus Ferst return PPC_INTERRUPT_HDECR; 1665bf303fb3SMatheus Ferst } 1666bf303fb3SMatheus Ferst } 1667bf303fb3SMatheus Ferst 1668bf303fb3SMatheus Ferst /* External interrupt can ignore MSR:EE under some circumstances */ 1669085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EXT) { 1670085cc364SHarsh Prateek Bora bool lpes0 = !!(lpcr & LPCR_LPES0); 1671085cc364SHarsh Prateek Bora bool heic = !!(lpcr & LPCR_HEIC); 1672bf303fb3SMatheus Ferst /* HEIC blocks delivery to the hypervisor */ 1673022b7128SMatheus Ferst if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) && 1674bf303fb3SMatheus Ferst !FIELD_EX64(env->msr, MSR, PR))) || 1675bf303fb3SMatheus Ferst (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) { 1676bf303fb3SMatheus Ferst return PPC_INTERRUPT_EXT; 1677bf303fb3SMatheus Ferst } 1678bf303fb3SMatheus Ferst } 1679022b7128SMatheus Ferst if (msr_ee != 0) { 1680bf303fb3SMatheus Ferst /* Decrementer exception */ 1681085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DECR) { 1682bf303fb3SMatheus Ferst return PPC_INTERRUPT_DECR; 1683bf303fb3SMatheus Ferst } 1684085cc364SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_PERFM) { 1685bf303fb3SMatheus Ferst return PPC_INTERRUPT_PERFM; 1686bf303fb3SMatheus Ferst } 1687bf303fb3SMatheus Ferst } 1688bf303fb3SMatheus Ferst 1689bf303fb3SMatheus Ferst return 0; 1690bf303fb3SMatheus Ferst } 1691bf303fb3SMatheus Ferst 1692f6194fddSMatheus Ferst #define P8_UNUSED_INTERRUPTS \ 1693f6194fddSMatheus Ferst (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_HVIRT | \ 1694f6194fddSMatheus Ferst PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \ 1695f6194fddSMatheus Ferst PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) 1696f6194fddSMatheus Ferst 169737e62398SHarsh Prateek Bora static int p8_interrupt_powersave(uint32_t pending_interrupts, 169837e62398SHarsh Prateek Bora target_ulong lpcr) 16999c713713SMatheus Ferst { 170037e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_EXT) && 170137e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE2)) { 17029c713713SMatheus Ferst return PPC_INTERRUPT_EXT; 17039c713713SMatheus Ferst } 170437e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_DECR) && 170537e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE3)) { 17069c713713SMatheus Ferst return PPC_INTERRUPT_DECR; 17079c713713SMatheus Ferst } 170837e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_MCK) && 170937e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE4)) { 17109c713713SMatheus Ferst return PPC_INTERRUPT_MCK; 17119c713713SMatheus Ferst } 171237e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_HMI) && 171337e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE4)) { 17149c713713SMatheus Ferst return PPC_INTERRUPT_HMI; 17159c713713SMatheus Ferst } 171637e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && 171737e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE0)) { 17189c713713SMatheus Ferst return PPC_INTERRUPT_DOORBELL; 17199c713713SMatheus Ferst } 172037e62398SHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && 172137e62398SHarsh Prateek Bora (lpcr & LPCR_P8_PECE1)) { 17229c713713SMatheus Ferst return PPC_INTERRUPT_HDOORBELL; 17239c713713SMatheus Ferst } 172437e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_RESET) { 17259c713713SMatheus Ferst return PPC_INTERRUPT_RESET; 17269c713713SMatheus Ferst } 17279c713713SMatheus Ferst return 0; 17289c713713SMatheus Ferst } 17299c713713SMatheus Ferst 173037e62398SHarsh Prateek Bora static int p8_next_unmasked_interrupt(CPUPPCState *env, 173137e62398SHarsh Prateek Bora uint32_t pending_interrupts, 173237e62398SHarsh Prateek Bora target_ulong lpcr) 1733a9899d42SMatheus Ferst { 17344e6b7db2SBALATON Zoltan CPUState *cs = env_cpu(env); 17354e6b7db2SBALATON Zoltan 173664a9b5eeSMatheus Ferst /* Ignore MSR[EE] when coming out of some power management states */ 173764a9b5eeSMatheus Ferst bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; 1738a9899d42SMatheus Ferst 1739f6194fddSMatheus Ferst assert((env->pending_interrupts & P8_UNUSED_INTERRUPTS) == 0); 1740f6194fddSMatheus Ferst 174164a9b5eeSMatheus Ferst if (cs->halted) { 174264a9b5eeSMatheus Ferst /* LPCR[PECE] controls which interrupts can exit power-saving mode */ 174337e62398SHarsh Prateek Bora return p8_interrupt_powersave(pending_interrupts, lpcr); 174464a9b5eeSMatheus Ferst } 174564a9b5eeSMatheus Ferst 1746a9899d42SMatheus Ferst /* Machine check exception */ 174737e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_MCK) { 1748a9899d42SMatheus Ferst return PPC_INTERRUPT_MCK; 1749a9899d42SMatheus Ferst } 1750a9899d42SMatheus Ferst 1751a9899d42SMatheus Ferst /* Hypervisor decrementer exception */ 175237e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDECR) { 1753a9899d42SMatheus Ferst /* LPCR will be clear when not supported so this will work */ 175437e62398SHarsh Prateek Bora bool hdice = !!(lpcr & LPCR_HDICE); 175564a9b5eeSMatheus Ferst if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { 1756a9899d42SMatheus Ferst /* HDEC clears on delivery */ 1757a9899d42SMatheus Ferst return PPC_INTERRUPT_HDECR; 1758a9899d42SMatheus Ferst } 1759a9899d42SMatheus Ferst } 1760a9899d42SMatheus Ferst 1761a9899d42SMatheus Ferst /* External interrupt can ignore MSR:EE under some circumstances */ 176237e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EXT) { 176337e62398SHarsh Prateek Bora bool lpes0 = !!(lpcr & LPCR_LPES0); 176437e62398SHarsh Prateek Bora bool heic = !!(lpcr & LPCR_HEIC); 1765a9899d42SMatheus Ferst /* HEIC blocks delivery to the hypervisor */ 176664a9b5eeSMatheus Ferst if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) && 1767a9899d42SMatheus Ferst !FIELD_EX64(env->msr, MSR, PR))) || 1768a9899d42SMatheus Ferst (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) { 1769a9899d42SMatheus Ferst return PPC_INTERRUPT_EXT; 1770a9899d42SMatheus Ferst } 1771a9899d42SMatheus Ferst } 177264a9b5eeSMatheus Ferst if (msr_ee != 0) { 1773a9899d42SMatheus Ferst /* Decrementer exception */ 177437e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DECR) { 1775a9899d42SMatheus Ferst return PPC_INTERRUPT_DECR; 1776a9899d42SMatheus Ferst } 177737e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DOORBELL) { 1778a9899d42SMatheus Ferst return PPC_INTERRUPT_DOORBELL; 1779a9899d42SMatheus Ferst } 178037e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) { 1781a9899d42SMatheus Ferst return PPC_INTERRUPT_HDOORBELL; 1782a9899d42SMatheus Ferst } 178337e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_PERFM) { 1784a9899d42SMatheus Ferst return PPC_INTERRUPT_PERFM; 1785a9899d42SMatheus Ferst } 1786a9899d42SMatheus Ferst /* EBB exception */ 178737e62398SHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EBB) { 1788a9899d42SMatheus Ferst /* 1789a9899d42SMatheus Ferst * EBB exception must be taken in problem state and 1790a9899d42SMatheus Ferst * with BESCR_GE set. 1791a9899d42SMatheus Ferst */ 1792a9899d42SMatheus Ferst if (FIELD_EX64(env->msr, MSR, PR) && 1793a9899d42SMatheus Ferst (env->spr[SPR_BESCR] & BESCR_GE)) { 1794a9899d42SMatheus Ferst return PPC_INTERRUPT_EBB; 1795a9899d42SMatheus Ferst } 1796a9899d42SMatheus Ferst } 1797a9899d42SMatheus Ferst } 1798a9899d42SMatheus Ferst 1799a9899d42SMatheus Ferst return 0; 1800a9899d42SMatheus Ferst } 1801a9899d42SMatheus Ferst 1802b00e9a2fSMatheus Ferst #define P9_UNUSED_INTERRUPTS \ 1803b00e9a2fSMatheus Ferst (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_CEXT | \ 1804b00e9a2fSMatheus Ferst PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \ 1805b00e9a2fSMatheus Ferst PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) 1806b00e9a2fSMatheus Ferst 18072a05a63cSHarsh Prateek Bora static int p9_interrupt_powersave(CPUPPCState *env, 18082a05a63cSHarsh Prateek Bora uint32_t pending_interrupts, 18092a05a63cSHarsh Prateek Bora target_ulong lpcr) 18109c713713SMatheus Ferst { 18112a05a63cSHarsh Prateek Bora 18129c713713SMatheus Ferst /* External Exception */ 18132a05a63cSHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_EXT) && 18142a05a63cSHarsh Prateek Bora (lpcr & LPCR_EEE)) { 18152a05a63cSHarsh Prateek Bora bool heic = !!(lpcr & LPCR_HEIC); 18169c713713SMatheus Ferst if (!heic || !FIELD_EX64_HV(env->msr) || 18179c713713SMatheus Ferst FIELD_EX64(env->msr, MSR, PR)) { 18189c713713SMatheus Ferst return PPC_INTERRUPT_EXT; 18199c713713SMatheus Ferst } 18209c713713SMatheus Ferst } 18219c713713SMatheus Ferst /* Decrementer Exception */ 18222a05a63cSHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_DECR) && 18232a05a63cSHarsh Prateek Bora (lpcr & LPCR_DEE)) { 18249c713713SMatheus Ferst return PPC_INTERRUPT_DECR; 18259c713713SMatheus Ferst } 18269c713713SMatheus Ferst /* Machine Check or Hypervisor Maintenance Exception */ 18272a05a63cSHarsh Prateek Bora if (lpcr & LPCR_OEE) { 18282a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_MCK) { 18299c713713SMatheus Ferst return PPC_INTERRUPT_MCK; 18309c713713SMatheus Ferst } 18312a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HMI) { 18329c713713SMatheus Ferst return PPC_INTERRUPT_HMI; 18339c713713SMatheus Ferst } 18349c713713SMatheus Ferst } 18359c713713SMatheus Ferst /* Privileged Doorbell Exception */ 18362a05a63cSHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && 18372a05a63cSHarsh Prateek Bora (lpcr & LPCR_PDEE)) { 18389c713713SMatheus Ferst return PPC_INTERRUPT_DOORBELL; 18399c713713SMatheus Ferst } 18409c713713SMatheus Ferst /* Hypervisor Doorbell Exception */ 18412a05a63cSHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && 18422a05a63cSHarsh Prateek Bora (lpcr & LPCR_HDEE)) { 18439c713713SMatheus Ferst return PPC_INTERRUPT_HDOORBELL; 18449c713713SMatheus Ferst } 18459c713713SMatheus Ferst /* Hypervisor virtualization exception */ 18462a05a63cSHarsh Prateek Bora if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && 18472a05a63cSHarsh Prateek Bora (lpcr & LPCR_HVEE)) { 18489c713713SMatheus Ferst return PPC_INTERRUPT_HVIRT; 18499c713713SMatheus Ferst } 18502a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_RESET) { 18519c713713SMatheus Ferst return PPC_INTERRUPT_RESET; 18529c713713SMatheus Ferst } 18539c713713SMatheus Ferst return 0; 18549c713713SMatheus Ferst } 18559c713713SMatheus Ferst 18562a05a63cSHarsh Prateek Bora static int p9_next_unmasked_interrupt(CPUPPCState *env, 18572a05a63cSHarsh Prateek Bora uint32_t pending_interrupts, 18582a05a63cSHarsh Prateek Bora target_ulong lpcr) 18592dfecf01SMatheus Ferst { 18604e6b7db2SBALATON Zoltan CPUState *cs = env_cpu(env); 18614e6b7db2SBALATON Zoltan 186227796411SMatheus Ferst /* Ignore MSR[EE] when coming out of some power management states */ 186327796411SMatheus Ferst bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; 18642dfecf01SMatheus Ferst 18652a05a63cSHarsh Prateek Bora assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); 1866b00e9a2fSMatheus Ferst 186727796411SMatheus Ferst if (cs->halted) { 186827796411SMatheus Ferst if (env->spr[SPR_PSSCR] & PSSCR_EC) { 186927796411SMatheus Ferst /* 187027796411SMatheus Ferst * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can 187127796411SMatheus Ferst * wakeup the processor 187227796411SMatheus Ferst */ 18732a05a63cSHarsh Prateek Bora return p9_interrupt_powersave(env, pending_interrupts, lpcr); 187427796411SMatheus Ferst } else { 187527796411SMatheus Ferst /* 187627796411SMatheus Ferst * When it's clear, any system-caused exception exits power-saving 187727796411SMatheus Ferst * mode, even the ones that gate on MSR[EE]. 187827796411SMatheus Ferst */ 187927796411SMatheus Ferst msr_ee = true; 188027796411SMatheus Ferst } 188127796411SMatheus Ferst } 188227796411SMatheus Ferst 18832dfecf01SMatheus Ferst /* Machine check exception */ 18842a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_MCK) { 18852dfecf01SMatheus Ferst return PPC_INTERRUPT_MCK; 18862dfecf01SMatheus Ferst } 18872dfecf01SMatheus Ferst 18882dfecf01SMatheus Ferst /* Hypervisor decrementer exception */ 18892a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDECR) { 18902dfecf01SMatheus Ferst /* LPCR will be clear when not supported so this will work */ 18912a05a63cSHarsh Prateek Bora bool hdice = !!(lpcr & LPCR_HDICE); 189227796411SMatheus Ferst if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { 18932dfecf01SMatheus Ferst /* HDEC clears on delivery */ 18942dfecf01SMatheus Ferst return PPC_INTERRUPT_HDECR; 18952dfecf01SMatheus Ferst } 18962dfecf01SMatheus Ferst } 18972dfecf01SMatheus Ferst 18982dfecf01SMatheus Ferst /* Hypervisor virtualization interrupt */ 18992a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HVIRT) { 19002dfecf01SMatheus Ferst /* LPCR will be clear when not supported so this will work */ 19012a05a63cSHarsh Prateek Bora bool hvice = !!(lpcr & LPCR_HVICE); 190227796411SMatheus Ferst if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) { 19032dfecf01SMatheus Ferst return PPC_INTERRUPT_HVIRT; 19042dfecf01SMatheus Ferst } 19052dfecf01SMatheus Ferst } 19062dfecf01SMatheus Ferst 19072dfecf01SMatheus Ferst /* External interrupt can ignore MSR:EE under some circumstances */ 19082a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EXT) { 19092a05a63cSHarsh Prateek Bora bool lpes0 = !!(lpcr & LPCR_LPES0); 19102a05a63cSHarsh Prateek Bora bool heic = !!(lpcr & LPCR_HEIC); 19112dfecf01SMatheus Ferst /* HEIC blocks delivery to the hypervisor */ 191227796411SMatheus Ferst if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) && 19132dfecf01SMatheus Ferst !FIELD_EX64(env->msr, MSR, PR))) || 19142dfecf01SMatheus Ferst (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) { 19152dfecf01SMatheus Ferst return PPC_INTERRUPT_EXT; 19162dfecf01SMatheus Ferst } 19172dfecf01SMatheus Ferst } 191827796411SMatheus Ferst if (msr_ee != 0) { 19192dfecf01SMatheus Ferst /* Decrementer exception */ 19202a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DECR) { 19212dfecf01SMatheus Ferst return PPC_INTERRUPT_DECR; 19222dfecf01SMatheus Ferst } 19232a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DOORBELL) { 19242dfecf01SMatheus Ferst return PPC_INTERRUPT_DOORBELL; 19252dfecf01SMatheus Ferst } 19262a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) { 19272dfecf01SMatheus Ferst return PPC_INTERRUPT_HDOORBELL; 19282dfecf01SMatheus Ferst } 19292a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_PERFM) { 19302dfecf01SMatheus Ferst return PPC_INTERRUPT_PERFM; 19312dfecf01SMatheus Ferst } 19322dfecf01SMatheus Ferst /* EBB exception */ 19332a05a63cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EBB) { 19342dfecf01SMatheus Ferst /* 19352dfecf01SMatheus Ferst * EBB exception must be taken in problem state and 19362dfecf01SMatheus Ferst * with BESCR_GE set. 19372dfecf01SMatheus Ferst */ 19382dfecf01SMatheus Ferst if (FIELD_EX64(env->msr, MSR, PR) && 19392dfecf01SMatheus Ferst (env->spr[SPR_BESCR] & BESCR_GE)) { 19402dfecf01SMatheus Ferst return PPC_INTERRUPT_EBB; 19412dfecf01SMatheus Ferst } 19422dfecf01SMatheus Ferst } 19432dfecf01SMatheus Ferst } 19442dfecf01SMatheus Ferst 19452dfecf01SMatheus Ferst return 0; 19462dfecf01SMatheus Ferst } 1947f6c2d68bSBALATON Zoltan #endif /* TARGET_PPC64 */ 19482dfecf01SMatheus Ferst 1949868cb6baSBALATON Zoltan static int ppc_next_unmasked_interrupt(CPUPPCState *env) 1950c79c73f6SBlue Swirl { 1951bb547c4cSHarsh Prateek Bora uint32_t pending_interrupts = env->pending_interrupts; 1952bb547c4cSHarsh Prateek Bora target_ulong lpcr = env->spr[SPR_LPCR]; 1953bb547c4cSHarsh Prateek Bora bool async_deliver; 1954bb547c4cSHarsh Prateek Bora 1955fb802acdSNicholas Piggin if (unlikely(env->quiesced)) { 1956fb802acdSNicholas Piggin return 0; 1957fb802acdSNicholas Piggin } 1958fb802acdSNicholas Piggin 1959868cb6baSBALATON Zoltan #ifdef TARGET_PPC64 1960868cb6baSBALATON Zoltan switch (env->excp_model) { 1961868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER7: 1962bb547c4cSHarsh Prateek Bora return p7_next_unmasked_interrupt(env, pending_interrupts, lpcr); 1963868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER8: 1964bb547c4cSHarsh Prateek Bora return p8_next_unmasked_interrupt(env, pending_interrupts, lpcr); 1965868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER9: 1966868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER10: 1967c0d96407SAditya Gupta case POWERPC_EXCP_POWER11: 1968bb547c4cSHarsh Prateek Bora return p9_next_unmasked_interrupt(env, pending_interrupts, lpcr); 1969868cb6baSBALATON Zoltan default: 1970868cb6baSBALATON Zoltan break; 1971868cb6baSBALATON Zoltan } 1972868cb6baSBALATON Zoltan #endif 1973259186a7SAndreas Färber 1974c79c73f6SBlue Swirl /* External reset */ 1975bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_RESET) { 1976de76b85cSMatheus Ferst return PPC_INTERRUPT_RESET; 1977c79c73f6SBlue Swirl } 1978c79c73f6SBlue Swirl /* Machine check exception */ 1979bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_MCK) { 1980de76b85cSMatheus Ferst return PPC_INTERRUPT_MCK; 1981c79c73f6SBlue Swirl } 1982c79c73f6SBlue Swirl #if 0 /* TODO */ 1983c79c73f6SBlue Swirl /* External debug exception */ 1984f003109fSMatheus Ferst if (env->pending_interrupts & PPC_INTERRUPT_DEBUG) { 1985de76b85cSMatheus Ferst return PPC_INTERRUPT_DEBUG; 1986c79c73f6SBlue Swirl } 1987c79c73f6SBlue Swirl #endif 19883621e2c9SBenjamin Herrenschmidt 19893621e2c9SBenjamin Herrenschmidt /* 19903621e2c9SBenjamin Herrenschmidt * For interrupts that gate on MSR:EE, we need to do something a 19913621e2c9SBenjamin Herrenschmidt * bit more subtle, as we need to let them through even when EE is 19923621e2c9SBenjamin Herrenschmidt * clear when coming out of some power management states (in order 19933621e2c9SBenjamin Herrenschmidt * for them to become a 0x100). 19943621e2c9SBenjamin Herrenschmidt */ 19950939b8f8SVíctor Colombo async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; 19963621e2c9SBenjamin Herrenschmidt 1997c79c73f6SBlue Swirl /* Hypervisor decrementer exception */ 1998bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDECR) { 19994b236b62SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 2000bb547c4cSHarsh Prateek Bora bool hdice = !!(lpcr & LPCR_HDICE); 20019de754d3SVíctor Colombo if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) { 20024b236b62SBenjamin Herrenschmidt /* HDEC clears on delivery */ 2003de76b85cSMatheus Ferst return PPC_INTERRUPT_HDECR; 2004c79c73f6SBlue Swirl } 2005c79c73f6SBlue Swirl } 2006d8ce5fd6SBenjamin Herrenschmidt 2007d8ce5fd6SBenjamin Herrenschmidt /* Hypervisor virtualization interrupt */ 2008bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HVIRT) { 2009d8ce5fd6SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 2010bb547c4cSHarsh Prateek Bora bool hvice = !!(lpcr & LPCR_HVICE); 20119de754d3SVíctor Colombo if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) { 2012de76b85cSMatheus Ferst return PPC_INTERRUPT_HVIRT; 2013d8ce5fd6SBenjamin Herrenschmidt } 2014d8ce5fd6SBenjamin Herrenschmidt } 2015d8ce5fd6SBenjamin Herrenschmidt 2016d8ce5fd6SBenjamin Herrenschmidt /* External interrupt can ignore MSR:EE under some circumstances */ 2017bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EXT) { 2018bb547c4cSHarsh Prateek Bora bool lpes0 = !!(lpcr & LPCR_LPES0); 2019bb547c4cSHarsh Prateek Bora bool heic = !!(lpcr & LPCR_HEIC); 20206eebe6dcSBenjamin Herrenschmidt /* HEIC blocks delivery to the hypervisor */ 20219de754d3SVíctor Colombo if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) && 2022d41ccf6eSVíctor Colombo !FIELD_EX64(env->msr, MSR, PR))) || 20239de754d3SVíctor Colombo (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) { 2024de76b85cSMatheus Ferst return PPC_INTERRUPT_EXT; 2025d1dbe37cSBenjamin Herrenschmidt } 2026d1dbe37cSBenjamin Herrenschmidt } 2027acc861c2SVíctor Colombo if (FIELD_EX64(env->msr, MSR, CE)) { 2028c79c73f6SBlue Swirl /* External critical interrupt */ 2029bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_CEXT) { 2030de76b85cSMatheus Ferst return PPC_INTERRUPT_CEXT; 2031c79c73f6SBlue Swirl } 2032c79c73f6SBlue Swirl } 20333621e2c9SBenjamin Herrenschmidt if (async_deliver != 0) { 2034c79c73f6SBlue Swirl /* Watchdog timer on embedded PowerPC */ 2035bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_WDT) { 2036de76b85cSMatheus Ferst return PPC_INTERRUPT_WDT; 2037c79c73f6SBlue Swirl } 2038bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_CDOORBELL) { 2039de76b85cSMatheus Ferst return PPC_INTERRUPT_CDOORBELL; 2040c79c73f6SBlue Swirl } 2041c79c73f6SBlue Swirl /* Fixed interval timer on embedded PowerPC */ 2042bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_FIT) { 2043de76b85cSMatheus Ferst return PPC_INTERRUPT_FIT; 2044c79c73f6SBlue Swirl } 2045c79c73f6SBlue Swirl /* Programmable interval timer on embedded PowerPC */ 2046bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_PIT) { 2047de76b85cSMatheus Ferst return PPC_INTERRUPT_PIT; 2048c79c73f6SBlue Swirl } 2049c79c73f6SBlue Swirl /* Decrementer exception */ 2050bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DECR) { 2051de76b85cSMatheus Ferst return PPC_INTERRUPT_DECR; 2052c79c73f6SBlue Swirl } 2053bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_DOORBELL) { 2054de76b85cSMatheus Ferst return PPC_INTERRUPT_DOORBELL; 2055c79c73f6SBlue Swirl } 2056bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) { 2057de76b85cSMatheus Ferst return PPC_INTERRUPT_HDOORBELL; 20587af1e7b0SCédric Le Goater } 2059bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_PERFM) { 2060de76b85cSMatheus Ferst return PPC_INTERRUPT_PERFM; 2061c79c73f6SBlue Swirl } 2062c79c73f6SBlue Swirl /* Thermal interrupt */ 2063bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_THERM) { 2064de76b85cSMatheus Ferst return PPC_INTERRUPT_THERM; 2065c79c73f6SBlue Swirl } 2066cb76bbc4SDaniel Henrique Barboza /* EBB exception */ 2067bb547c4cSHarsh Prateek Bora if (pending_interrupts & PPC_INTERRUPT_EBB) { 2068cb76bbc4SDaniel Henrique Barboza /* 2069cb76bbc4SDaniel Henrique Barboza * EBB exception must be taken in problem state and 2070cb76bbc4SDaniel Henrique Barboza * with BESCR_GE set. 2071cb76bbc4SDaniel Henrique Barboza */ 2072d41ccf6eSVíctor Colombo if (FIELD_EX64(env->msr, MSR, PR) && 2073d41ccf6eSVíctor Colombo (env->spr[SPR_BESCR] & BESCR_GE)) { 2074de76b85cSMatheus Ferst return PPC_INTERRUPT_EBB; 2075de76b85cSMatheus Ferst } 2076de76b85cSMatheus Ferst } 2077de76b85cSMatheus Ferst } 2078cb76bbc4SDaniel Henrique Barboza 2079de76b85cSMatheus Ferst return 0; 2080de76b85cSMatheus Ferst } 2081de76b85cSMatheus Ferst 20822fdedcbcSMatheus Ferst /* 20832fdedcbcSMatheus Ferst * Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be 20842fdedcbcSMatheus Ferst * delivered and clears CPU_INTERRUPT_HARD otherwise. 20852fdedcbcSMatheus Ferst * 20862fdedcbcSMatheus Ferst * This method is called by ppc_set_interrupt when an interrupt is raised or 20872fdedcbcSMatheus Ferst * lowered, and should also be called whenever an interrupt masking condition 20882fdedcbcSMatheus Ferst * is changed, e.g.: 20892fdedcbcSMatheus Ferst * - When relevant bits of MSR are altered, like EE, HV, PR, etc.; 20902fdedcbcSMatheus Ferst * - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.; 20912fdedcbcSMatheus Ferst * - When PSSCR[EC] or env->resume_as_sreset are changed; 20922fdedcbcSMatheus Ferst * - When cs->halted is changed and the CPU has a different interrupt masking 20932fdedcbcSMatheus Ferst * logic in power-saving mode (e.g., POWER7/8/9/10); 20942fdedcbcSMatheus Ferst */ 20952fdedcbcSMatheus Ferst void ppc_maybe_interrupt(CPUPPCState *env) 20962fdedcbcSMatheus Ferst { 20972fdedcbcSMatheus Ferst CPUState *cs = env_cpu(env); 209832ead8e6SStefan Hajnoczi BQL_LOCK_GUARD(); 20992fdedcbcSMatheus Ferst 21002fdedcbcSMatheus Ferst if (ppc_next_unmasked_interrupt(env)) { 21012fdedcbcSMatheus Ferst cpu_interrupt(cs, CPU_INTERRUPT_HARD); 21022fdedcbcSMatheus Ferst } else { 21032fdedcbcSMatheus Ferst cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 21042fdedcbcSMatheus Ferst } 21052fdedcbcSMatheus Ferst } 21062fdedcbcSMatheus Ferst 2107f6c2d68bSBALATON Zoltan #ifdef TARGET_PPC64 2108d93a4856SMatheus Ferst static void p7_deliver_interrupt(CPUPPCState *env, int interrupt) 2109d93a4856SMatheus Ferst { 2110d93a4856SMatheus Ferst PowerPCCPU *cpu = env_archcpu(env); 2111d93a4856SMatheus Ferst 2112d93a4856SMatheus Ferst switch (interrupt) { 2113d93a4856SMatheus Ferst case PPC_INTERRUPT_MCK: /* Machine check exception */ 2114d93a4856SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_MCK; 2115d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_MCHECK); 2116d93a4856SMatheus Ferst break; 2117d93a4856SMatheus Ferst 2118d93a4856SMatheus Ferst case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */ 2119d93a4856SMatheus Ferst /* HDEC clears on delivery */ 2120d93a4856SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDECR; 2121d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HDECR); 2122d93a4856SMatheus Ferst break; 2123d93a4856SMatheus Ferst 2124d93a4856SMatheus Ferst case PPC_INTERRUPT_EXT: 2125d93a4856SMatheus Ferst if (books_vhyp_promotes_external_to_hvirt(cpu)) { 2126d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 2127d93a4856SMatheus Ferst } else { 2128d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); 2129d93a4856SMatheus Ferst } 2130d93a4856SMatheus Ferst break; 2131d93a4856SMatheus Ferst 2132d93a4856SMatheus Ferst case PPC_INTERRUPT_DECR: /* Decrementer exception */ 2133d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DECR); 2134d93a4856SMatheus Ferst break; 2135d93a4856SMatheus Ferst case PPC_INTERRUPT_PERFM: 2136d93a4856SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM); 2137d93a4856SMatheus Ferst break; 2138d93a4856SMatheus Ferst case 0: 2139d93a4856SMatheus Ferst /* 2140d93a4856SMatheus Ferst * This is a bug ! It means that has_work took us out of halt without 2141d93a4856SMatheus Ferst * anything to deliver while in a PM state that requires getting 2142d93a4856SMatheus Ferst * out via a 0x100 2143d93a4856SMatheus Ferst * 2144d93a4856SMatheus Ferst * This means we will incorrectly execute past the power management 2145d93a4856SMatheus Ferst * instruction instead of triggering a reset. 2146d93a4856SMatheus Ferst * 2147d93a4856SMatheus Ferst * It generally means a discrepancy between the wakeup conditions in the 2148d93a4856SMatheus Ferst * processor has_work implementation and the logic in this function. 2149d93a4856SMatheus Ferst */ 2150d93a4856SMatheus Ferst assert(!env->resume_as_sreset); 2151d93a4856SMatheus Ferst break; 2152d93a4856SMatheus Ferst default: 2153bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n", 2154bc30c1c6SBALATON Zoltan interrupt); 2155d93a4856SMatheus Ferst } 2156d93a4856SMatheus Ferst } 2157d93a4856SMatheus Ferst 21586527e757SMatheus Ferst static void p8_deliver_interrupt(CPUPPCState *env, int interrupt) 21596527e757SMatheus Ferst { 21606527e757SMatheus Ferst PowerPCCPU *cpu = env_archcpu(env); 21616527e757SMatheus Ferst 21626527e757SMatheus Ferst switch (interrupt) { 21636527e757SMatheus Ferst case PPC_INTERRUPT_MCK: /* Machine check exception */ 21646527e757SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_MCK; 21656527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_MCHECK); 21666527e757SMatheus Ferst break; 21676527e757SMatheus Ferst 21686527e757SMatheus Ferst case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */ 21696527e757SMatheus Ferst /* HDEC clears on delivery */ 21706527e757SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDECR; 21716527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HDECR); 21726527e757SMatheus Ferst break; 21736527e757SMatheus Ferst 21746527e757SMatheus Ferst case PPC_INTERRUPT_EXT: 21756527e757SMatheus Ferst if (books_vhyp_promotes_external_to_hvirt(cpu)) { 21766527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 21776527e757SMatheus Ferst } else { 21786527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); 21796527e757SMatheus Ferst } 21806527e757SMatheus Ferst break; 21816527e757SMatheus Ferst 21826527e757SMatheus Ferst case PPC_INTERRUPT_DECR: /* Decrementer exception */ 21836527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DECR); 21846527e757SMatheus Ferst break; 21856527e757SMatheus Ferst case PPC_INTERRUPT_DOORBELL: 218606229545SNicholas Piggin if (!env->resume_as_sreset) { 21876527e757SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL; 218806229545SNicholas Piggin } 21896527e757SMatheus Ferst if (is_book3s_arch2x(env)) { 21906527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR); 21916527e757SMatheus Ferst } else { 21926527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DOORI); 21936527e757SMatheus Ferst } 21946527e757SMatheus Ferst break; 21956527e757SMatheus Ferst case PPC_INTERRUPT_HDOORBELL: 219606229545SNicholas Piggin if (!env->resume_as_sreset) { 21976527e757SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL; 219806229545SNicholas Piggin } 21996527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); 22006527e757SMatheus Ferst break; 22016527e757SMatheus Ferst case PPC_INTERRUPT_PERFM: 22026527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM); 22036527e757SMatheus Ferst break; 22046527e757SMatheus Ferst case PPC_INTERRUPT_EBB: /* EBB exception */ 22056527e757SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_EBB; 22066527e757SMatheus Ferst if (env->spr[SPR_BESCR] & BESCR_PMEO) { 22076527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB); 22086527e757SMatheus Ferst } else if (env->spr[SPR_BESCR] & BESCR_EEO) { 22096527e757SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB); 22106527e757SMatheus Ferst } 22116527e757SMatheus Ferst break; 22126527e757SMatheus Ferst case 0: 22136527e757SMatheus Ferst /* 22146527e757SMatheus Ferst * This is a bug ! It means that has_work took us out of halt without 22156527e757SMatheus Ferst * anything to deliver while in a PM state that requires getting 22166527e757SMatheus Ferst * out via a 0x100 22176527e757SMatheus Ferst * 22186527e757SMatheus Ferst * This means we will incorrectly execute past the power management 22196527e757SMatheus Ferst * instruction instead of triggering a reset. 22206527e757SMatheus Ferst * 22216527e757SMatheus Ferst * It generally means a discrepancy between the wakeup conditions in the 22226527e757SMatheus Ferst * processor has_work implementation and the logic in this function. 22236527e757SMatheus Ferst */ 22246527e757SMatheus Ferst assert(!env->resume_as_sreset); 22256527e757SMatheus Ferst break; 22266527e757SMatheus Ferst default: 2227bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n", 2228bc30c1c6SBALATON Zoltan interrupt); 22296527e757SMatheus Ferst } 22306527e757SMatheus Ferst } 22316527e757SMatheus Ferst 22323654e238SMatheus Ferst static void p9_deliver_interrupt(CPUPPCState *env, int interrupt) 22333654e238SMatheus Ferst { 22343654e238SMatheus Ferst PowerPCCPU *cpu = env_archcpu(env); 22353654e238SMatheus Ferst CPUState *cs = env_cpu(env); 22363654e238SMatheus Ferst 223727796411SMatheus Ferst if (cs->halted && !(env->spr[SPR_PSSCR] & PSSCR_EC) && 223827796411SMatheus Ferst !FIELD_EX64(env->msr, MSR, EE)) { 223927796411SMatheus Ferst /* 224027796411SMatheus Ferst * A pending interrupt took us out of power-saving, but MSR[EE] says 224127796411SMatheus Ferst * that we should return to NIP+4 instead of delivering it. 224227796411SMatheus Ferst */ 224327796411SMatheus Ferst return; 224427796411SMatheus Ferst } 224527796411SMatheus Ferst 22463654e238SMatheus Ferst switch (interrupt) { 22473654e238SMatheus Ferst case PPC_INTERRUPT_MCK: /* Machine check exception */ 22483654e238SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_MCK; 22493654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_MCHECK); 22503654e238SMatheus Ferst break; 22513654e238SMatheus Ferst 22523654e238SMatheus Ferst case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */ 22533654e238SMatheus Ferst /* HDEC clears on delivery */ 225406229545SNicholas Piggin /* XXX: should not see an HDEC if resume_as_sreset. assert? */ 22553654e238SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDECR; 22563654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HDECR); 22573654e238SMatheus Ferst break; 22583654e238SMatheus Ferst case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */ 22593654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 22603654e238SMatheus Ferst break; 22613654e238SMatheus Ferst 22623654e238SMatheus Ferst case PPC_INTERRUPT_EXT: 22633654e238SMatheus Ferst if (books_vhyp_promotes_external_to_hvirt(cpu)) { 22643654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 22653654e238SMatheus Ferst } else { 22663654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); 22673654e238SMatheus Ferst } 22683654e238SMatheus Ferst break; 22693654e238SMatheus Ferst 22703654e238SMatheus Ferst case PPC_INTERRUPT_DECR: /* Decrementer exception */ 22713654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DECR); 22723654e238SMatheus Ferst break; 22733654e238SMatheus Ferst case PPC_INTERRUPT_DOORBELL: 227406229545SNicholas Piggin if (!env->resume_as_sreset) { 22753654e238SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL; 227606229545SNicholas Piggin } 22773654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR); 22783654e238SMatheus Ferst break; 22793654e238SMatheus Ferst case PPC_INTERRUPT_HDOORBELL: 228006229545SNicholas Piggin if (!env->resume_as_sreset) { 22813654e238SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL; 228206229545SNicholas Piggin } 22833654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); 22843654e238SMatheus Ferst break; 22853654e238SMatheus Ferst case PPC_INTERRUPT_PERFM: 22863654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM); 22873654e238SMatheus Ferst break; 22883654e238SMatheus Ferst case PPC_INTERRUPT_EBB: /* EBB exception */ 22893654e238SMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_EBB; 22903654e238SMatheus Ferst if (env->spr[SPR_BESCR] & BESCR_PMEO) { 22913654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB); 22923654e238SMatheus Ferst } else if (env->spr[SPR_BESCR] & BESCR_EEO) { 22933654e238SMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB); 22943654e238SMatheus Ferst } 22953654e238SMatheus Ferst break; 22963654e238SMatheus Ferst case 0: 22973654e238SMatheus Ferst /* 22983654e238SMatheus Ferst * This is a bug ! It means that has_work took us out of halt without 22993654e238SMatheus Ferst * anything to deliver while in a PM state that requires getting 23003654e238SMatheus Ferst * out via a 0x100 23013654e238SMatheus Ferst * 23023654e238SMatheus Ferst * This means we will incorrectly execute past the power management 23033654e238SMatheus Ferst * instruction instead of triggering a reset. 23043654e238SMatheus Ferst * 23053654e238SMatheus Ferst * It generally means a discrepancy between the wakeup conditions in the 23063654e238SMatheus Ferst * processor has_work implementation and the logic in this function. 23073654e238SMatheus Ferst */ 23083654e238SMatheus Ferst assert(!env->resume_as_sreset); 23093654e238SMatheus Ferst break; 23103654e238SMatheus Ferst default: 2311bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n", 2312bc30c1c6SBALATON Zoltan interrupt); 23133654e238SMatheus Ferst } 23143654e238SMatheus Ferst } 2315f6c2d68bSBALATON Zoltan #endif /* TARGET_PPC64 */ 23163654e238SMatheus Ferst 2317868cb6baSBALATON Zoltan static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt) 2318de76b85cSMatheus Ferst { 2319868cb6baSBALATON Zoltan #ifdef TARGET_PPC64 2320868cb6baSBALATON Zoltan switch (env->excp_model) { 2321868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER7: 2322868cb6baSBALATON Zoltan return p7_deliver_interrupt(env, interrupt); 2323868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER8: 2324868cb6baSBALATON Zoltan return p8_deliver_interrupt(env, interrupt); 2325868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER9: 2326868cb6baSBALATON Zoltan case POWERPC_EXCP_POWER10: 2327c0d96407SAditya Gupta case POWERPC_EXCP_POWER11: 2328868cb6baSBALATON Zoltan return p9_deliver_interrupt(env, interrupt); 2329868cb6baSBALATON Zoltan default: 2330868cb6baSBALATON Zoltan break; 2331868cb6baSBALATON Zoltan } 2332de76b85cSMatheus Ferst #endif 2333de76b85cSMatheus Ferst PowerPCCPU *cpu = env_archcpu(env); 2334de76b85cSMatheus Ferst 2335de76b85cSMatheus Ferst switch (interrupt) { 2336de76b85cSMatheus Ferst case PPC_INTERRUPT_RESET: /* External reset */ 2337de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_RESET; 2338de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_RESET); 2339de76b85cSMatheus Ferst break; 2340de76b85cSMatheus Ferst case PPC_INTERRUPT_MCK: /* Machine check exception */ 2341de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_MCK; 2342de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_MCHECK); 2343de76b85cSMatheus Ferst break; 2344de76b85cSMatheus Ferst 2345de76b85cSMatheus Ferst case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */ 2346de76b85cSMatheus Ferst /* HDEC clears on delivery */ 2347de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDECR; 2348de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HDECR); 2349de76b85cSMatheus Ferst break; 2350de76b85cSMatheus Ferst case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */ 2351de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 2352de76b85cSMatheus Ferst break; 2353de76b85cSMatheus Ferst 2354de76b85cSMatheus Ferst case PPC_INTERRUPT_EXT: 2355de76b85cSMatheus Ferst if (books_vhyp_promotes_external_to_hvirt(cpu)) { 2356de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 2357de76b85cSMatheus Ferst } else { 2358de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); 2359de76b85cSMatheus Ferst } 2360de76b85cSMatheus Ferst break; 2361de76b85cSMatheus Ferst case PPC_INTERRUPT_CEXT: /* External critical interrupt */ 2362de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_CRITICAL); 2363de76b85cSMatheus Ferst break; 2364de76b85cSMatheus Ferst 2365de76b85cSMatheus Ferst case PPC_INTERRUPT_WDT: /* Watchdog timer on embedded PowerPC */ 2366de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_WDT; 2367de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_WDT); 2368de76b85cSMatheus Ferst break; 2369de76b85cSMatheus Ferst case PPC_INTERRUPT_CDOORBELL: 2370de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_CDOORBELL; 2371de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DOORCI); 2372de76b85cSMatheus Ferst break; 2373de76b85cSMatheus Ferst case PPC_INTERRUPT_FIT: /* Fixed interval timer on embedded PowerPC */ 2374de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_FIT; 2375de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_FIT); 2376de76b85cSMatheus Ferst break; 2377de76b85cSMatheus Ferst case PPC_INTERRUPT_PIT: /* Programmable interval timer on embedded ppc */ 2378de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_PIT; 2379de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PIT); 2380de76b85cSMatheus Ferst break; 2381de76b85cSMatheus Ferst case PPC_INTERRUPT_DECR: /* Decrementer exception */ 2382de76b85cSMatheus Ferst if (ppc_decr_clear_on_delivery(env)) { 2383de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_DECR; 2384de76b85cSMatheus Ferst } 2385de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DECR); 2386de76b85cSMatheus Ferst break; 2387de76b85cSMatheus Ferst case PPC_INTERRUPT_DOORBELL: 2388de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL; 2389de76b85cSMatheus Ferst if (is_book3s_arch2x(env)) { 2390de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR); 2391de76b85cSMatheus Ferst } else { 2392de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_DOORI); 2393de76b85cSMatheus Ferst } 2394de76b85cSMatheus Ferst break; 2395de76b85cSMatheus Ferst case PPC_INTERRUPT_HDOORBELL: 2396de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL; 2397de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); 2398de76b85cSMatheus Ferst break; 2399de76b85cSMatheus Ferst case PPC_INTERRUPT_PERFM: 2400de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_PERFM); 2401de76b85cSMatheus Ferst break; 2402de76b85cSMatheus Ferst case PPC_INTERRUPT_THERM: /* Thermal interrupt */ 2403de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_THERM; 2404de76b85cSMatheus Ferst powerpc_excp(cpu, POWERPC_EXCP_THERM); 2405de76b85cSMatheus Ferst break; 2406de76b85cSMatheus Ferst case PPC_INTERRUPT_EBB: /* EBB exception */ 2407de76b85cSMatheus Ferst env->pending_interrupts &= ~PPC_INTERRUPT_EBB; 2408cb76bbc4SDaniel Henrique Barboza if (env->spr[SPR_BESCR] & BESCR_PMEO) { 2409cb76bbc4SDaniel Henrique Barboza powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB); 2410cb76bbc4SDaniel Henrique Barboza } else if (env->spr[SPR_BESCR] & BESCR_EEO) { 2411cb76bbc4SDaniel Henrique Barboza powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB); 2412cb76bbc4SDaniel Henrique Barboza } 2413de76b85cSMatheus Ferst break; 2414de76b85cSMatheus Ferst case 0: 2415f8154fd2SBenjamin Herrenschmidt /* 2416f8154fd2SBenjamin Herrenschmidt * This is a bug ! It means that has_work took us out of halt without 2417f8154fd2SBenjamin Herrenschmidt * anything to deliver while in a PM state that requires getting 2418f8154fd2SBenjamin Herrenschmidt * out via a 0x100 2419f8154fd2SBenjamin Herrenschmidt * 2420f8154fd2SBenjamin Herrenschmidt * This means we will incorrectly execute past the power management 2421f8154fd2SBenjamin Herrenschmidt * instruction instead of triggering a reset. 2422f8154fd2SBenjamin Herrenschmidt * 2423136fbf65Szhaolichang * It generally means a discrepancy between the wakeup conditions in the 2424f8154fd2SBenjamin Herrenschmidt * processor has_work implementation and the logic in this function. 2425f8154fd2SBenjamin Herrenschmidt */ 2426de76b85cSMatheus Ferst assert(!env->resume_as_sreset); 2427de76b85cSMatheus Ferst break; 2428de76b85cSMatheus Ferst default: 2429bc30c1c6SBALATON Zoltan cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n", 2430bc30c1c6SBALATON Zoltan interrupt); 2431ba2898f7SMatheus Ferst } 2432ba2898f7SMatheus Ferst } 2433ba2898f7SMatheus Ferst 2434fa416ae6SNicholas Piggin /* 2435fa416ae6SNicholas Piggin * system reset is not delivered via normal irq method, so have to set 2436fa416ae6SNicholas Piggin * halted = 0 to resume CPU running if it was halted. Possibly we should 2437fa416ae6SNicholas Piggin * move it over to using PPC_INTERRUPT_RESET rather than async_run_on_cpu. 2438fa416ae6SNicholas Piggin */ 2439b5b7f391SNicholas Piggin void ppc_cpu_do_system_reset(CPUState *cs) 244034316482SAlexey Kardashevskiy { 244134316482SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 244234316482SAlexey Kardashevskiy 2443fa416ae6SNicholas Piggin cs->halted = 0; 244493130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_RESET); 244534316482SAlexey Kardashevskiy } 2446ad77c6caSNicholas Piggin 2447ad77c6caSNicholas Piggin void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) 2448ad77c6caSNicholas Piggin { 2449ad77c6caSNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 2450ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 2451ad77c6caSNicholas Piggin target_ulong msr = 0; 2452ad77c6caSNicholas Piggin 2453ad77c6caSNicholas Piggin /* 2454ad77c6caSNicholas Piggin * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already 2455ad77c6caSNicholas Piggin * been set by KVM. 2456ad77c6caSNicholas Piggin */ 2457ad77c6caSNicholas Piggin msr = (1ULL << MSR_ME); 2458ad77c6caSNicholas Piggin msr |= env->msr & (1ULL << MSR_SF); 2459516fc103SFabiano Rosas if (ppc_interrupts_little_endian(cpu, false)) { 2460ad77c6caSNicholas Piggin msr |= (1ULL << MSR_LE); 2461ad77c6caSNicholas Piggin } 2462ad77c6caSNicholas Piggin 24637cebc5dbSNicholas Piggin /* Anything for nested required here? MSR[HV] bit? */ 24647cebc5dbSNicholas Piggin 2465fa416ae6SNicholas Piggin cs->halted = 0; 2466ad77c6caSNicholas Piggin powerpc_set_excp_state(cpu, vector, msr); 2467ad77c6caSNicholas Piggin } 2468c79c73f6SBlue Swirl 2469458dd766SRichard Henderson bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 2470458dd766SRichard Henderson { 2471794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs); 2472de76b85cSMatheus Ferst int interrupt; 2473458dd766SRichard Henderson 2474de76b85cSMatheus Ferst if ((interrupt_request & CPU_INTERRUPT_HARD) == 0) { 2475de76b85cSMatheus Ferst return false; 2476de76b85cSMatheus Ferst } 2477de76b85cSMatheus Ferst 2478de76b85cSMatheus Ferst interrupt = ppc_next_unmasked_interrupt(env); 2479de76b85cSMatheus Ferst if (interrupt == 0) { 2480de76b85cSMatheus Ferst return false; 2481de76b85cSMatheus Ferst } 2482de76b85cSMatheus Ferst 2483de76b85cSMatheus Ferst ppc_deliver_interrupt(env, interrupt); 2484458dd766SRichard Henderson if (env->pending_interrupts == 0) { 2485de76b85cSMatheus Ferst cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 2486458dd766SRichard Henderson } 2487458dd766SRichard Henderson return true; 2488458dd766SRichard Henderson } 2489458dd766SRichard Henderson 2490f725245cSPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */ 2491