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" 22ad71ed68SBlue Swirl #include "cpu.h" 2363c91552SPaolo Bonzini #include "exec/exec-all.h" 240f3110faSRichard Henderson #include "internal.h" 25ad71ed68SBlue Swirl #include "helper_regs.h" 26ad71ed68SBlue Swirl 272eb1ef73SCédric Le Goater #include "trace.h" 282eb1ef73SCédric Le Goater 292b44e219SBruno Larsen (billionai) #ifdef CONFIG_TCG 302b44e219SBruno Larsen (billionai) #include "exec/helper-proto.h" 312b44e219SBruno Larsen (billionai) #include "exec/cpu_ldst.h" 322b44e219SBruno Larsen (billionai) #endif 332b44e219SBruno Larsen (billionai) 34c79c73f6SBlue Swirl /*****************************************************************************/ 35c79c73f6SBlue Swirl /* Exception processing */ 36f725245cSPhilippe Mathieu-Daudé #if !defined(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 16728091374SFabiano Rosas #if defined(TARGET_PPC64) 168dead760bSBenjamin Herrenschmidt static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, 169dead760bSBenjamin Herrenschmidt target_ulong *msr) 170dead760bSBenjamin Herrenschmidt { 171dead760bSBenjamin Herrenschmidt /* We no longer are in a PM state */ 1721e7fd61dSBenjamin Herrenschmidt env->resume_as_sreset = false; 173dead760bSBenjamin Herrenschmidt 174dead760bSBenjamin Herrenschmidt /* Pretend to be returning from doze always as we don't lose state */ 1750911a60cSLeonardo Bras *msr |= SRR1_WS_NOLOSS; 176dead760bSBenjamin Herrenschmidt 177dead760bSBenjamin Herrenschmidt /* Machine checks are sent normally */ 178dead760bSBenjamin Herrenschmidt if (excp == POWERPC_EXCP_MCHECK) { 179dead760bSBenjamin Herrenschmidt return excp; 180dead760bSBenjamin Herrenschmidt } 181dead760bSBenjamin Herrenschmidt switch (excp) { 182dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_RESET: 1830911a60cSLeonardo Bras *msr |= SRR1_WAKERESET; 184dead760bSBenjamin Herrenschmidt break; 185dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_EXTERNAL: 1860911a60cSLeonardo Bras *msr |= SRR1_WAKEEE; 187dead760bSBenjamin Herrenschmidt break; 188dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_DECR: 1890911a60cSLeonardo Bras *msr |= SRR1_WAKEDEC; 190dead760bSBenjamin Herrenschmidt break; 191dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR: 1920911a60cSLeonardo Bras *msr |= SRR1_WAKEDBELL; 193dead760bSBenjamin Herrenschmidt break; 194dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR_HV: 1950911a60cSLeonardo Bras *msr |= SRR1_WAKEHDBELL; 196dead760bSBenjamin Herrenschmidt break; 197dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_HV_MAINT: 1980911a60cSLeonardo Bras *msr |= SRR1_WAKEHMI; 199dead760bSBenjamin Herrenschmidt break; 200d8ce5fd6SBenjamin Herrenschmidt case POWERPC_EXCP_HVIRT: 2010911a60cSLeonardo Bras *msr |= SRR1_WAKEHVI; 202d8ce5fd6SBenjamin Herrenschmidt break; 203dead760bSBenjamin Herrenschmidt default: 204dead760bSBenjamin Herrenschmidt cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", 205dead760bSBenjamin Herrenschmidt excp); 206dead760bSBenjamin Herrenschmidt } 207dead760bSBenjamin Herrenschmidt return POWERPC_EXCP_RESET; 208dead760bSBenjamin Herrenschmidt } 209dead760bSBenjamin Herrenschmidt 2108b7e6b07SNicholas Piggin /* 2118b7e6b07SNicholas Piggin * AIL - Alternate Interrupt Location, a mode that allows interrupts to be 2128b7e6b07SNicholas Piggin * taken with the MMU on, and which uses an alternate location (e.g., so the 2138b7e6b07SNicholas Piggin * kernel/hv can map the vectors there with an effective address). 2148b7e6b07SNicholas Piggin * 2158b7e6b07SNicholas Piggin * An interrupt is considered to be taken "with AIL" or "AIL applies" if they 2168b7e6b07SNicholas Piggin * are delivered in this way. AIL requires the LPCR to be set to enable this 2178b7e6b07SNicholas Piggin * mode, and then a number of conditions have to be true for AIL to apply. 2188b7e6b07SNicholas Piggin * 2198b7e6b07SNicholas Piggin * First of all, SRESET, MCE, and HMI are always delivered without AIL, because 2208b7e6b07SNicholas Piggin * they specifically want to be in real mode (e.g., the MCE might be signaling 2218b7e6b07SNicholas Piggin * a SLB multi-hit which requires SLB flush before the MMU can be enabled). 2228b7e6b07SNicholas Piggin * 2238b7e6b07SNicholas Piggin * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV], 2248b7e6b07SNicholas Piggin * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current 2258b7e6b07SNicholas Piggin * radix mode (LPCR[HR]). 2268b7e6b07SNicholas Piggin * 2278b7e6b07SNicholas Piggin * POWER8, POWER9 with LPCR[HR]=0 2288b7e6b07SNicholas Piggin * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 2298b7e6b07SNicholas Piggin * +-----------+-------------+---------+-------------+-----+ 2308b7e6b07SNicholas Piggin * | a | 00/01/10 | x | x | 0 | 2318b7e6b07SNicholas Piggin * | a | 11 | 0 | 1 | 0 | 2328b7e6b07SNicholas Piggin * | a | 11 | 1 | 1 | a | 2338b7e6b07SNicholas Piggin * | a | 11 | 0 | 0 | a | 2348b7e6b07SNicholas Piggin * +-------------------------------------------------------+ 2358b7e6b07SNicholas Piggin * 2368b7e6b07SNicholas Piggin * POWER9 with LPCR[HR]=1 2378b7e6b07SNicholas Piggin * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 2388b7e6b07SNicholas Piggin * +-----------+-------------+---------+-------------+-----+ 2398b7e6b07SNicholas Piggin * | a | 00/01/10 | x | x | 0 | 2408b7e6b07SNicholas Piggin * | a | 11 | x | x | a | 2418b7e6b07SNicholas Piggin * +-------------------------------------------------------+ 2428b7e6b07SNicholas Piggin * 2438b7e6b07SNicholas Piggin * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to 244526cdce7SNicholas Piggin * the hypervisor in AIL mode if the guest is radix. This is good for 245526cdce7SNicholas Piggin * performance but allows the guest to influence the AIL of hypervisor 246526cdce7SNicholas Piggin * interrupts using its MSR, and also the hypervisor must disallow guest 247526cdce7SNicholas Piggin * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to 248526cdce7SNicholas Piggin * use AIL for its MSR[HV] 0->1 interrupts. 249526cdce7SNicholas Piggin * 250526cdce7SNicholas Piggin * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to 251526cdce7SNicholas Piggin * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and 252526cdce7SNicholas Piggin * MSR[HV] 1->1). 253526cdce7SNicholas Piggin * 254526cdce7SNicholas Piggin * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1. 255526cdce7SNicholas Piggin * 256526cdce7SNicholas Piggin * POWER10 behaviour is 257526cdce7SNicholas Piggin * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL | 258526cdce7SNicholas Piggin * +-----------+------------+-------------+---------+-------------+-----+ 259526cdce7SNicholas Piggin * | a | h | 00/01/10 | 0 | 0 | 0 | 260526cdce7SNicholas Piggin * | a | h | 11 | 0 | 0 | a | 261526cdce7SNicholas Piggin * | a | h | x | 0 | 1 | h | 262526cdce7SNicholas Piggin * | a | h | 00/01/10 | 1 | 1 | 0 | 263526cdce7SNicholas Piggin * | a | h | 11 | 1 | 1 | h | 264526cdce7SNicholas Piggin * +--------------------------------------------------------------------+ 2658b7e6b07SNicholas Piggin */ 26610895ab6SFabiano Rosas static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr, 26710895ab6SFabiano Rosas target_ulong *new_msr, target_ulong *vector) 2682586a4d7SFabiano Rosas { 26910895ab6SFabiano Rosas PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); 2708b7e6b07SNicholas Piggin CPUPPCState *env = &cpu->env; 2718b7e6b07SNicholas Piggin bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1); 2728b7e6b07SNicholas Piggin bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB); 2738b7e6b07SNicholas Piggin int ail = 0; 2742586a4d7SFabiano Rosas 2758b7e6b07SNicholas Piggin if (excp == POWERPC_EXCP_MCHECK || 2768b7e6b07SNicholas Piggin excp == POWERPC_EXCP_RESET || 2778b7e6b07SNicholas Piggin excp == POWERPC_EXCP_HV_MAINT) { 2788b7e6b07SNicholas Piggin /* SRESET, MCE, HMI never apply AIL */ 2798b7e6b07SNicholas Piggin return; 2802586a4d7SFabiano Rosas } 2812586a4d7SFabiano Rosas 28210895ab6SFabiano Rosas if (!(pcc->lpcr_mask & LPCR_AIL)) { 28310895ab6SFabiano Rosas /* This CPU does not have AIL */ 28410895ab6SFabiano Rosas return; 28510895ab6SFabiano Rosas } 28610895ab6SFabiano Rosas 28710895ab6SFabiano Rosas /* P8 & P9 */ 28810895ab6SFabiano Rosas if (!(pcc->lpcr_mask & LPCR_HAIL)) { 2898b7e6b07SNicholas Piggin if (!mmu_all_on) { 2908b7e6b07SNicholas Piggin /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */ 2918b7e6b07SNicholas Piggin return; 2928b7e6b07SNicholas Piggin } 2938b7e6b07SNicholas Piggin if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) { 2948b7e6b07SNicholas Piggin /* 2958b7e6b07SNicholas Piggin * AIL does not work if there is a MSR[HV] 0->1 transition and the 2968b7e6b07SNicholas Piggin * partition is in HPT mode. For radix guests, such interrupts are 2978b7e6b07SNicholas Piggin * allowed to be delivered to the hypervisor in ail mode. 2988b7e6b07SNicholas Piggin */ 2998b7e6b07SNicholas Piggin return; 3008b7e6b07SNicholas Piggin } 3018b7e6b07SNicholas Piggin 3028b7e6b07SNicholas Piggin ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 3038b7e6b07SNicholas Piggin if (ail == 0) { 3048b7e6b07SNicholas Piggin return; 3058b7e6b07SNicholas Piggin } 3068b7e6b07SNicholas Piggin if (ail == 1) { 3078b7e6b07SNicholas Piggin /* AIL=1 is reserved, treat it like AIL=0 */ 3088b7e6b07SNicholas Piggin return; 3098b7e6b07SNicholas Piggin } 310526cdce7SNicholas Piggin 31110895ab6SFabiano Rosas /* P10 and up */ 31210895ab6SFabiano Rosas } else { 313526cdce7SNicholas Piggin if (!mmu_all_on && !hv_escalation) { 314526cdce7SNicholas Piggin /* 315526cdce7SNicholas Piggin * AIL works for HV interrupts even with guest MSR[IR/DR] disabled. 316526cdce7SNicholas Piggin * Guest->guest and HV->HV interrupts do require MMU on. 317526cdce7SNicholas Piggin */ 318526cdce7SNicholas Piggin return; 319526cdce7SNicholas Piggin } 320526cdce7SNicholas Piggin 321526cdce7SNicholas Piggin if (*new_msr & MSR_HVB) { 322526cdce7SNicholas Piggin if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) { 323526cdce7SNicholas Piggin /* HV interrupts depend on LPCR[HAIL] */ 324526cdce7SNicholas Piggin return; 325526cdce7SNicholas Piggin } 326526cdce7SNicholas Piggin ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */ 327526cdce7SNicholas Piggin } else { 328526cdce7SNicholas Piggin ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 329526cdce7SNicholas Piggin } 330526cdce7SNicholas Piggin if (ail == 0) { 331526cdce7SNicholas Piggin return; 332526cdce7SNicholas Piggin } 333526cdce7SNicholas Piggin if (ail == 1 || ail == 2) { 334526cdce7SNicholas Piggin /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */ 335526cdce7SNicholas Piggin return; 336526cdce7SNicholas Piggin } 3378b7e6b07SNicholas Piggin } 3388b7e6b07SNicholas Piggin 3398b7e6b07SNicholas Piggin /* 3408b7e6b07SNicholas Piggin * AIL applies, so the new MSR gets IR and DR set, and an offset applied 3418b7e6b07SNicholas Piggin * to the new IP. 3428b7e6b07SNicholas Piggin */ 3438b7e6b07SNicholas Piggin *new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 3448b7e6b07SNicholas Piggin 3458b7e6b07SNicholas Piggin if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { 3468b7e6b07SNicholas Piggin if (ail == 2) { 3478b7e6b07SNicholas Piggin *vector |= 0x0000000000018000ull; 3488b7e6b07SNicholas Piggin } else if (ail == 3) { 3498b7e6b07SNicholas Piggin *vector |= 0xc000000000004000ull; 3508b7e6b07SNicholas Piggin } 3518b7e6b07SNicholas Piggin } else { 3528b7e6b07SNicholas Piggin /* 3538b7e6b07SNicholas Piggin * scv AIL is a little different. AIL=2 does not change the address, 3548b7e6b07SNicholas Piggin * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000. 3558b7e6b07SNicholas Piggin */ 3568b7e6b07SNicholas Piggin if (ail == 3) { 3578b7e6b07SNicholas Piggin *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */ 3588b7e6b07SNicholas Piggin *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */ 3598b7e6b07SNicholas Piggin } 3608b7e6b07SNicholas Piggin } 3612586a4d7SFabiano Rosas } 36228091374SFabiano Rosas #endif 363dead760bSBenjamin Herrenschmidt 3643680e994SNicholas Piggin static void powerpc_reset_excp_state(PowerPCCPU *cpu) 365ad77c6caSNicholas Piggin { 366ad77c6caSNicholas Piggin CPUState *cs = CPU(cpu); 367ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 368ad77c6caSNicholas Piggin 3693680e994SNicholas Piggin /* Reset exception state */ 3703680e994SNicholas Piggin cs->exception_index = POWERPC_EXCP_NONE; 3713680e994SNicholas Piggin env->error_code = 0; 3723680e994SNicholas Piggin } 3733680e994SNicholas Piggin 3743680e994SNicholas Piggin static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, 3753680e994SNicholas Piggin target_ulong msr) 3763680e994SNicholas Piggin { 3773680e994SNicholas Piggin CPUPPCState *env = &cpu->env; 3783680e994SNicholas Piggin 379fce9fbafSFabiano Rosas assert((msr & env->msr_mask) == msr); 380fce9fbafSFabiano Rosas 381ad77c6caSNicholas Piggin /* 382ad77c6caSNicholas Piggin * We don't use hreg_store_msr here as already have treated any 383ad77c6caSNicholas Piggin * special case that could occur. Just store MSR and update hflags 384ad77c6caSNicholas Piggin * 385ad77c6caSNicholas Piggin * Note: We *MUST* not use hreg_store_msr() as-is anyway because it 386ad77c6caSNicholas Piggin * will prevent setting of the HV bit which some exceptions might need 387ad77c6caSNicholas Piggin * to do. 388ad77c6caSNicholas Piggin */ 3893680e994SNicholas Piggin env->nip = vector; 390fce9fbafSFabiano Rosas env->msr = msr; 391ad77c6caSNicholas Piggin hreg_compute_hflags(env); 392ad77c6caSNicholas Piggin 3933680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 394ad77c6caSNicholas Piggin 395ad77c6caSNicholas Piggin /* 396ad77c6caSNicholas Piggin * Any interrupt is context synchronizing, check if TCG TLB needs 397ad77c6caSNicholas Piggin * a delayed flush on ppc64 398ad77c6caSNicholas Piggin */ 399ad77c6caSNicholas Piggin check_tlb_flush(env, false); 4003680e994SNicholas Piggin 4013680e994SNicholas Piggin /* Reset the reservation */ 4023680e994SNicholas Piggin env->reserve_addr = -1; 403ad77c6caSNicholas Piggin } 404ad77c6caSNicholas Piggin 405e808c2edSFabiano Rosas static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) 406e808c2edSFabiano Rosas { 407e808c2edSFabiano Rosas CPUState *cs = CPU(cpu); 408e808c2edSFabiano Rosas CPUPPCState *env = &cpu->env; 409e808c2edSFabiano Rosas target_ulong msr, new_msr, vector; 4108428cdb2SFabiano Rosas int srr0, srr1; 411e808c2edSFabiano Rosas 412e808c2edSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 413e808c2edSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 414e808c2edSFabiano Rosas 415e808c2edSFabiano Rosas /* 416495fc7ffSFabiano Rosas * new interrupt handler msr preserves existing ME unless 417495fc7ffSFabiano Rosas * explicitly overriden. 418e808c2edSFabiano Rosas */ 419495fc7ffSFabiano Rosas new_msr = env->msr & (((target_ulong)1 << MSR_ME)); 420e808c2edSFabiano Rosas 421e808c2edSFabiano Rosas /* target registers */ 422e808c2edSFabiano Rosas srr0 = SPR_SRR0; 423e808c2edSFabiano Rosas srr1 = SPR_SRR1; 424e808c2edSFabiano Rosas 425e808c2edSFabiano Rosas /* 426e808c2edSFabiano Rosas * Hypervisor emulation assistance interrupt only exists on server 427495fc7ffSFabiano Rosas * arch 2.05 server or later. 428e808c2edSFabiano Rosas */ 429495fc7ffSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 430e808c2edSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 431e808c2edSFabiano Rosas } 432e808c2edSFabiano Rosas 433e808c2edSFabiano Rosas vector = env->excp_vectors[excp]; 434e808c2edSFabiano Rosas if (vector == (target_ulong)-1ULL) { 435e808c2edSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 436e808c2edSFabiano Rosas excp); 437e808c2edSFabiano Rosas } 438e808c2edSFabiano Rosas 439e808c2edSFabiano Rosas vector |= env->excp_prefix; 440e808c2edSFabiano Rosas 441e808c2edSFabiano Rosas switch (excp) { 442e808c2edSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 443e808c2edSFabiano Rosas srr0 = SPR_40x_SRR2; 444e808c2edSFabiano Rosas srr1 = SPR_40x_SRR3; 445e808c2edSFabiano Rosas break; 446e808c2edSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 447c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 448e808c2edSFabiano Rosas /* 449e808c2edSFabiano Rosas * Machine check exception is not enabled. Enter 450e808c2edSFabiano Rosas * checkstop state. 451e808c2edSFabiano Rosas */ 452e808c2edSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 453e808c2edSFabiano Rosas "Entering checkstop state\n"); 454e808c2edSFabiano Rosas if (qemu_log_separate()) { 455e808c2edSFabiano Rosas qemu_log("Machine check while not allowed. " 456e808c2edSFabiano Rosas "Entering checkstop state\n"); 457e808c2edSFabiano Rosas } 458e808c2edSFabiano Rosas cs->halted = 1; 459e808c2edSFabiano Rosas cpu_interrupt_exittb(cs); 460e808c2edSFabiano Rosas } 461e808c2edSFabiano Rosas 462e808c2edSFabiano Rosas /* machine check exceptions don't have ME set */ 463e808c2edSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 464e808c2edSFabiano Rosas 465e808c2edSFabiano Rosas srr0 = SPR_40x_SRR2; 466e808c2edSFabiano Rosas srr1 = SPR_40x_SRR3; 467e808c2edSFabiano Rosas break; 468e808c2edSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 469f9911e1eSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]); 470e808c2edSFabiano Rosas break; 471e808c2edSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 472e808c2edSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 473e808c2edSFabiano Rosas break; 474e808c2edSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 475e808c2edSFabiano Rosas break; 476e808c2edSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 477e808c2edSFabiano Rosas break; 478e808c2edSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 479e808c2edSFabiano Rosas switch (env->error_code & ~0xF) { 480e808c2edSFabiano Rosas case POWERPC_EXCP_FP: 481da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 482e808c2edSFabiano Rosas trace_ppc_excp_fp_ignore(); 4833680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 484e808c2edSFabiano Rosas return; 485e808c2edSFabiano Rosas } 48664e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_FP; 487e808c2edSFabiano Rosas break; 488e808c2edSFabiano Rosas case POWERPC_EXCP_INVAL: 489e808c2edSFabiano Rosas trace_ppc_excp_inval(env->nip); 49064e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PIL; 491e808c2edSFabiano Rosas break; 492e808c2edSFabiano Rosas case POWERPC_EXCP_PRIV: 49364e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PPR; 494e808c2edSFabiano Rosas break; 495e808c2edSFabiano Rosas case POWERPC_EXCP_TRAP: 49664e62cfbSFabiano Rosas env->spr[SPR_40x_ESR] = ESR_PTR; 497e808c2edSFabiano Rosas break; 498e808c2edSFabiano Rosas default: 499e808c2edSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 500e808c2edSFabiano Rosas env->error_code); 501e808c2edSFabiano Rosas break; 502e808c2edSFabiano Rosas } 503e808c2edSFabiano Rosas break; 504e808c2edSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 505e808c2edSFabiano Rosas dump_syscall(env); 506e808c2edSFabiano Rosas 507e808c2edSFabiano Rosas /* 508e808c2edSFabiano Rosas * We need to correct the NIP which in this case is supposed 509e808c2edSFabiano Rosas * to point to the next instruction 510e808c2edSFabiano Rosas */ 511e808c2edSFabiano Rosas env->nip += 4; 512e808c2edSFabiano Rosas break; 513e808c2edSFabiano Rosas case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 514e808c2edSFabiano Rosas trace_ppc_excp_print("FIT"); 515e808c2edSFabiano Rosas break; 516e808c2edSFabiano Rosas case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 517e808c2edSFabiano Rosas trace_ppc_excp_print("WDT"); 518e808c2edSFabiano Rosas break; 519e808c2edSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 520e808c2edSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 521e808c2edSFabiano Rosas break; 522e808c2edSFabiano Rosas case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ 523e808c2edSFabiano Rosas trace_ppc_excp_print("PIT"); 524e808c2edSFabiano Rosas break; 5254d8ac1d1SFabiano Rosas case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 5264d8ac1d1SFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 5274d8ac1d1SFabiano Rosas powerpc_excp_name(excp)); 5284d8ac1d1SFabiano Rosas break; 529e808c2edSFabiano Rosas default: 530e808c2edSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 531e808c2edSFabiano Rosas break; 532e808c2edSFabiano Rosas } 533e808c2edSFabiano Rosas 534e808c2edSFabiano Rosas /* Save PC */ 535e808c2edSFabiano Rosas env->spr[srr0] = env->nip; 536e808c2edSFabiano Rosas 537e808c2edSFabiano Rosas /* Save MSR */ 538e808c2edSFabiano Rosas env->spr[srr1] = msr; 539e808c2edSFabiano Rosas 540e808c2edSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 541e808c2edSFabiano Rosas } 542e808c2edSFabiano Rosas 54358d178fbSFabiano Rosas static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp) 54458d178fbSFabiano Rosas { 54558d178fbSFabiano Rosas CPUState *cs = CPU(cpu); 54658d178fbSFabiano Rosas CPUPPCState *env = &cpu->env; 54758d178fbSFabiano Rosas target_ulong msr, new_msr, vector; 54858d178fbSFabiano Rosas 54958d178fbSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 55058d178fbSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 55158d178fbSFabiano Rosas 55258d178fbSFabiano Rosas /* 553082d783bSFabiano Rosas * new interrupt handler msr preserves existing ME unless 55458d178fbSFabiano Rosas * explicitly overriden 55558d178fbSFabiano Rosas */ 556082d783bSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 55758d178fbSFabiano Rosas 55858d178fbSFabiano Rosas /* 55958d178fbSFabiano Rosas * Hypervisor emulation assistance interrupt only exists on server 560082d783bSFabiano Rosas * arch 2.05 server or later. 56158d178fbSFabiano Rosas */ 562082d783bSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 56358d178fbSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 56458d178fbSFabiano Rosas } 56558d178fbSFabiano Rosas 56658d178fbSFabiano Rosas vector = env->excp_vectors[excp]; 56758d178fbSFabiano Rosas if (vector == (target_ulong)-1ULL) { 56858d178fbSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 56958d178fbSFabiano Rosas excp); 57058d178fbSFabiano Rosas } 57158d178fbSFabiano Rosas 57258d178fbSFabiano Rosas vector |= env->excp_prefix; 57358d178fbSFabiano Rosas 57458d178fbSFabiano Rosas switch (excp) { 57558d178fbSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 57658d178fbSFabiano Rosas break; 57758d178fbSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 578c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 57958d178fbSFabiano Rosas /* 58058d178fbSFabiano Rosas * Machine check exception is not enabled. Enter 58158d178fbSFabiano Rosas * checkstop state. 58258d178fbSFabiano Rosas */ 58358d178fbSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 58458d178fbSFabiano Rosas "Entering checkstop state\n"); 58558d178fbSFabiano Rosas if (qemu_log_separate()) { 58658d178fbSFabiano Rosas qemu_log("Machine check while not allowed. " 58758d178fbSFabiano Rosas "Entering checkstop state\n"); 58858d178fbSFabiano Rosas } 58958d178fbSFabiano Rosas cs->halted = 1; 59058d178fbSFabiano Rosas cpu_interrupt_exittb(cs); 59158d178fbSFabiano Rosas } 59258d178fbSFabiano Rosas 59358d178fbSFabiano Rosas /* machine check exceptions don't have ME set */ 59458d178fbSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 59558d178fbSFabiano Rosas 59658d178fbSFabiano Rosas break; 59758d178fbSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 59858d178fbSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 59958d178fbSFabiano Rosas break; 60058d178fbSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 60158d178fbSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 60258d178fbSFabiano Rosas msr |= env->error_code; 60358d178fbSFabiano Rosas break; 60458d178fbSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 60558d178fbSFabiano Rosas break; 60658d178fbSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 60758d178fbSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 60858d178fbSFabiano Rosas /* 60958d178fbSFabiano Rosas * Note: the opcode fields will not be set properly for a 61058d178fbSFabiano Rosas * direct store load/store, but nobody cares as nobody 61158d178fbSFabiano Rosas * actually uses direct store segments. 61258d178fbSFabiano Rosas */ 61358d178fbSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 61458d178fbSFabiano Rosas break; 61558d178fbSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 61658d178fbSFabiano Rosas switch (env->error_code & ~0xF) { 61758d178fbSFabiano Rosas case POWERPC_EXCP_FP: 618da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 61958d178fbSFabiano Rosas trace_ppc_excp_fp_ignore(); 6203680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 62158d178fbSFabiano Rosas return; 62258d178fbSFabiano Rosas } 62358d178fbSFabiano Rosas 62458d178fbSFabiano Rosas /* 62558d178fbSFabiano Rosas * FP exceptions always have NIP pointing to the faulting 62658d178fbSFabiano Rosas * instruction, so always use store_next and claim we are 62758d178fbSFabiano Rosas * precise in the MSR. 62858d178fbSFabiano Rosas */ 62958d178fbSFabiano Rosas msr |= 0x00100000; 63058d178fbSFabiano Rosas break; 63158d178fbSFabiano Rosas case POWERPC_EXCP_INVAL: 63258d178fbSFabiano Rosas trace_ppc_excp_inval(env->nip); 63358d178fbSFabiano Rosas msr |= 0x00080000; 63458d178fbSFabiano Rosas break; 63558d178fbSFabiano Rosas case POWERPC_EXCP_PRIV: 63658d178fbSFabiano Rosas msr |= 0x00040000; 63758d178fbSFabiano Rosas break; 63858d178fbSFabiano Rosas case POWERPC_EXCP_TRAP: 63958d178fbSFabiano Rosas msr |= 0x00020000; 64058d178fbSFabiano Rosas break; 64158d178fbSFabiano Rosas default: 64258d178fbSFabiano Rosas /* Should never occur */ 64358d178fbSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 64458d178fbSFabiano Rosas env->error_code); 64558d178fbSFabiano Rosas break; 64658d178fbSFabiano Rosas } 64758d178fbSFabiano Rosas break; 64858d178fbSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 64958d178fbSFabiano Rosas dump_syscall(env); 65058d178fbSFabiano Rosas 65158d178fbSFabiano Rosas /* 65258d178fbSFabiano Rosas * We need to correct the NIP which in this case is supposed 65358d178fbSFabiano Rosas * to point to the next instruction 65458d178fbSFabiano Rosas */ 65558d178fbSFabiano Rosas env->nip += 4; 65658d178fbSFabiano Rosas break; 65758d178fbSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 65858d178fbSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 65958d178fbSFabiano Rosas break; 66058d178fbSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 66158d178fbSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 66258d178fbSFabiano Rosas break; 66358d178fbSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 6648e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 66558d178fbSFabiano Rosas cpu_abort(cs, "Trying to deliver power-saving system reset " 66658d178fbSFabiano Rosas "exception %d with no HV support\n", excp); 66758d178fbSFabiano Rosas } 66858d178fbSFabiano Rosas break; 66958d178fbSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 67058d178fbSFabiano Rosas break; 67158d178fbSFabiano Rosas case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 67258d178fbSFabiano Rosas case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 67358d178fbSFabiano Rosas case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 67458d178fbSFabiano Rosas /* Swap temporary saved registers with GPRs */ 67558d178fbSFabiano Rosas if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { 67658d178fbSFabiano Rosas new_msr |= (target_ulong)1 << MSR_TGPR; 67758d178fbSFabiano Rosas hreg_swap_gpr_tgpr(env); 67858d178fbSFabiano Rosas } 6798f8c7932SFabiano Rosas 68058d178fbSFabiano Rosas ppc_excp_debug_sw_tlb(env, excp); 68158d178fbSFabiano Rosas 68258d178fbSFabiano Rosas msr |= env->crf[0] << 28; 68358d178fbSFabiano Rosas msr |= env->error_code; /* key, D/I, S/L bits */ 68458d178fbSFabiano Rosas /* Set way using a LRU mechanism */ 68558d178fbSFabiano Rosas msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 68658d178fbSFabiano Rosas break; 68758d178fbSFabiano Rosas case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 68858d178fbSFabiano Rosas case POWERPC_EXCP_DABR: /* Data address breakpoint */ 68958d178fbSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 69058d178fbSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 69158d178fbSFabiano Rosas case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ 69258d178fbSFabiano Rosas case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ 69358d178fbSFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 69458d178fbSFabiano Rosas powerpc_excp_name(excp)); 69558d178fbSFabiano Rosas break; 69658d178fbSFabiano Rosas default: 69758d178fbSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 69858d178fbSFabiano Rosas break; 69958d178fbSFabiano Rosas } 70058d178fbSFabiano Rosas 70158d178fbSFabiano Rosas /* 70258d178fbSFabiano Rosas * Sort out endianness of interrupt, this differs depending on the 70358d178fbSFabiano Rosas * CPU, the HV mode, etc... 70458d178fbSFabiano Rosas */ 70558d178fbSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 70658d178fbSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 70758d178fbSFabiano Rosas } 70858d178fbSFabiano Rosas 70958d178fbSFabiano Rosas /* Save PC */ 710c50eaed1SFabiano Rosas env->spr[SPR_SRR0] = env->nip; 71158d178fbSFabiano Rosas 71258d178fbSFabiano Rosas /* Save MSR */ 713c50eaed1SFabiano Rosas env->spr[SPR_SRR1] = msr; 71458d178fbSFabiano Rosas 71558d178fbSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 71658d178fbSFabiano Rosas } 71758d178fbSFabiano Rosas 718ccfca2fcSFabiano Rosas static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp) 719ccfca2fcSFabiano Rosas { 720ccfca2fcSFabiano Rosas CPUState *cs = CPU(cpu); 721ccfca2fcSFabiano Rosas CPUPPCState *env = &cpu->env; 722ccfca2fcSFabiano Rosas target_ulong msr, new_msr, vector; 723ccfca2fcSFabiano Rosas 724ccfca2fcSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 725ccfca2fcSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 726ccfca2fcSFabiano Rosas 727ccfca2fcSFabiano Rosas /* 72893848d6aSFabiano Rosas * new interrupt handler msr preserves existing ME unless 729ccfca2fcSFabiano Rosas * explicitly overriden 730ccfca2fcSFabiano Rosas */ 73193848d6aSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 732ccfca2fcSFabiano Rosas 733ccfca2fcSFabiano Rosas /* 734ccfca2fcSFabiano Rosas * Hypervisor emulation assistance interrupt only exists on server 73593848d6aSFabiano Rosas * arch 2.05 server or later. 736ccfca2fcSFabiano Rosas */ 73793848d6aSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 738ccfca2fcSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 739ccfca2fcSFabiano Rosas } 740ccfca2fcSFabiano Rosas 741ccfca2fcSFabiano Rosas vector = env->excp_vectors[excp]; 742ccfca2fcSFabiano Rosas if (vector == (target_ulong)-1ULL) { 743ccfca2fcSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 744ccfca2fcSFabiano Rosas excp); 745ccfca2fcSFabiano Rosas } 746ccfca2fcSFabiano Rosas 747ccfca2fcSFabiano Rosas vector |= env->excp_prefix; 748ccfca2fcSFabiano Rosas 749ccfca2fcSFabiano Rosas switch (excp) { 750ccfca2fcSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 751c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 752ccfca2fcSFabiano Rosas /* 753ccfca2fcSFabiano Rosas * Machine check exception is not enabled. Enter 754ccfca2fcSFabiano Rosas * checkstop state. 755ccfca2fcSFabiano Rosas */ 756ccfca2fcSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 757ccfca2fcSFabiano Rosas "Entering checkstop state\n"); 758ccfca2fcSFabiano Rosas if (qemu_log_separate()) { 759ccfca2fcSFabiano Rosas qemu_log("Machine check while not allowed. " 760ccfca2fcSFabiano Rosas "Entering checkstop state\n"); 761ccfca2fcSFabiano Rosas } 762ccfca2fcSFabiano Rosas cs->halted = 1; 763ccfca2fcSFabiano Rosas cpu_interrupt_exittb(cs); 764ccfca2fcSFabiano Rosas } 765ccfca2fcSFabiano Rosas 766ccfca2fcSFabiano Rosas /* machine check exceptions don't have ME set */ 767ccfca2fcSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 768ccfca2fcSFabiano Rosas 769ccfca2fcSFabiano Rosas break; 770ccfca2fcSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 771ccfca2fcSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 772ccfca2fcSFabiano Rosas break; 773ccfca2fcSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 774ccfca2fcSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 775ccfca2fcSFabiano Rosas msr |= env->error_code; 776ccfca2fcSFabiano Rosas break; 777ccfca2fcSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 778ccfca2fcSFabiano Rosas break; 779ccfca2fcSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 780ccfca2fcSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 781ccfca2fcSFabiano Rosas /* 782ccfca2fcSFabiano Rosas * Note: the opcode fields will not be set properly for a 783ccfca2fcSFabiano Rosas * direct store load/store, but nobody cares as nobody 784ccfca2fcSFabiano Rosas * actually uses direct store segments. 785ccfca2fcSFabiano Rosas */ 786ccfca2fcSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 787ccfca2fcSFabiano Rosas break; 788ccfca2fcSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 789ccfca2fcSFabiano Rosas switch (env->error_code & ~0xF) { 790ccfca2fcSFabiano Rosas case POWERPC_EXCP_FP: 791da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 792ccfca2fcSFabiano Rosas trace_ppc_excp_fp_ignore(); 7933680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 794ccfca2fcSFabiano Rosas return; 795ccfca2fcSFabiano Rosas } 796ccfca2fcSFabiano Rosas 797ccfca2fcSFabiano Rosas /* 798ccfca2fcSFabiano Rosas * FP exceptions always have NIP pointing to the faulting 799ccfca2fcSFabiano Rosas * instruction, so always use store_next and claim we are 800ccfca2fcSFabiano Rosas * precise in the MSR. 801ccfca2fcSFabiano Rosas */ 802ccfca2fcSFabiano Rosas msr |= 0x00100000; 803ccfca2fcSFabiano Rosas break; 804ccfca2fcSFabiano Rosas case POWERPC_EXCP_INVAL: 805ccfca2fcSFabiano Rosas trace_ppc_excp_inval(env->nip); 806ccfca2fcSFabiano Rosas msr |= 0x00080000; 807ccfca2fcSFabiano Rosas break; 808ccfca2fcSFabiano Rosas case POWERPC_EXCP_PRIV: 809ccfca2fcSFabiano Rosas msr |= 0x00040000; 810ccfca2fcSFabiano Rosas break; 811ccfca2fcSFabiano Rosas case POWERPC_EXCP_TRAP: 812ccfca2fcSFabiano Rosas msr |= 0x00020000; 813ccfca2fcSFabiano Rosas break; 814ccfca2fcSFabiano Rosas default: 815ccfca2fcSFabiano Rosas /* Should never occur */ 816ccfca2fcSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 817ccfca2fcSFabiano Rosas env->error_code); 818ccfca2fcSFabiano Rosas break; 819ccfca2fcSFabiano Rosas } 820ccfca2fcSFabiano Rosas break; 821ccfca2fcSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 8223b578635SFabiano Rosas { 8233b578635SFabiano Rosas int lev = env->error_code; 824ccfca2fcSFabiano Rosas 8253b578635SFabiano Rosas if (lev == 1 && cpu->vhyp) { 826ccfca2fcSFabiano Rosas dump_hcall(env); 827ccfca2fcSFabiano Rosas } else { 828ccfca2fcSFabiano Rosas dump_syscall(env); 829ccfca2fcSFabiano Rosas } 830ccfca2fcSFabiano Rosas 831ccfca2fcSFabiano Rosas /* 832ccfca2fcSFabiano Rosas * We need to correct the NIP which in this case is supposed 833ccfca2fcSFabiano Rosas * to point to the next instruction 834ccfca2fcSFabiano Rosas */ 835ccfca2fcSFabiano Rosas env->nip += 4; 836ccfca2fcSFabiano Rosas 8373b578635SFabiano Rosas /* 8383b578635SFabiano Rosas * The Virtual Open Firmware (VOF) relies on the 'sc 1' 8393b578635SFabiano Rosas * instruction to communicate with QEMU. The pegasos2 machine 8403b578635SFabiano Rosas * uses VOF and the 7xx CPUs, so although the 7xx don't have 8413b578635SFabiano Rosas * HV mode, we need to keep hypercall support. 8423b578635SFabiano Rosas */ 8433b578635SFabiano Rosas if (lev == 1 && cpu->vhyp) { 844ccfca2fcSFabiano Rosas PPCVirtualHypervisorClass *vhc = 845ccfca2fcSFabiano Rosas PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 846ccfca2fcSFabiano Rosas vhc->hypercall(cpu->vhyp, cpu); 847ccfca2fcSFabiano Rosas return; 848ccfca2fcSFabiano Rosas } 8493b578635SFabiano Rosas 850ccfca2fcSFabiano Rosas break; 8513b578635SFabiano Rosas } 852ccfca2fcSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 853ccfca2fcSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 854ccfca2fcSFabiano Rosas break; 855ccfca2fcSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 8568e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 857ccfca2fcSFabiano Rosas cpu_abort(cs, "Trying to deliver power-saving system reset " 858ccfca2fcSFabiano Rosas "exception %d with no HV support\n", excp); 859ccfca2fcSFabiano Rosas } 860ccfca2fcSFabiano Rosas break; 861ccfca2fcSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 862ccfca2fcSFabiano Rosas break; 863ccfca2fcSFabiano Rosas case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 864ccfca2fcSFabiano Rosas case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 865ccfca2fcSFabiano Rosas case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 866ccfca2fcSFabiano Rosas ppc_excp_debug_sw_tlb(env, excp); 867ccfca2fcSFabiano Rosas 868ccfca2fcSFabiano Rosas msr |= env->crf[0] << 28; 869ccfca2fcSFabiano Rosas msr |= env->error_code; /* key, D/I, S/L bits */ 870ccfca2fcSFabiano Rosas /* Set way using a LRU mechanism */ 871ccfca2fcSFabiano Rosas msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 8727df40c54SFabiano Rosas 873ccfca2fcSFabiano Rosas break; 874ccfca2fcSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 875ccfca2fcSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 876ccfca2fcSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 877ccfca2fcSFabiano Rosas case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 878ccfca2fcSFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 879ccfca2fcSFabiano Rosas powerpc_excp_name(excp)); 880ccfca2fcSFabiano Rosas break; 881ccfca2fcSFabiano Rosas default: 882ccfca2fcSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 883ccfca2fcSFabiano Rosas break; 884ccfca2fcSFabiano Rosas } 885ccfca2fcSFabiano Rosas 886ccfca2fcSFabiano Rosas /* 887ccfca2fcSFabiano Rosas * Sort out endianness of interrupt, this differs depending on the 888ccfca2fcSFabiano Rosas * CPU, the HV mode, etc... 889ccfca2fcSFabiano Rosas */ 890ccfca2fcSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 891ccfca2fcSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 892ccfca2fcSFabiano Rosas } 893ccfca2fcSFabiano Rosas 894ccfca2fcSFabiano Rosas /* Save PC */ 895fe4b5c4cSFabiano Rosas env->spr[SPR_SRR0] = env->nip; 896ccfca2fcSFabiano Rosas 897ccfca2fcSFabiano Rosas /* Save MSR */ 898fe4b5c4cSFabiano Rosas env->spr[SPR_SRR1] = msr; 899ccfca2fcSFabiano Rosas 900ccfca2fcSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 901ccfca2fcSFabiano Rosas } 902ccfca2fcSFabiano Rosas 90352926b0dSFabiano Rosas static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) 90452926b0dSFabiano Rosas { 90552926b0dSFabiano Rosas CPUState *cs = CPU(cpu); 90652926b0dSFabiano Rosas CPUPPCState *env = &cpu->env; 90752926b0dSFabiano Rosas target_ulong msr, new_msr, vector; 90852926b0dSFabiano Rosas 90952926b0dSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 91052926b0dSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 91152926b0dSFabiano Rosas 91252926b0dSFabiano Rosas /* 9131f6faf8bSFabiano Rosas * new interrupt handler msr preserves existing ME unless 91452926b0dSFabiano Rosas * explicitly overriden 91552926b0dSFabiano Rosas */ 9161f6faf8bSFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 91752926b0dSFabiano Rosas 91852926b0dSFabiano Rosas /* 91952926b0dSFabiano Rosas * Hypervisor emulation assistance interrupt only exists on server 9201f6faf8bSFabiano Rosas * arch 2.05 server or later. 92152926b0dSFabiano Rosas */ 9221f6faf8bSFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 92352926b0dSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 92452926b0dSFabiano Rosas } 92552926b0dSFabiano Rosas 92652926b0dSFabiano Rosas vector = env->excp_vectors[excp]; 92752926b0dSFabiano Rosas if (vector == (target_ulong)-1ULL) { 92852926b0dSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 92952926b0dSFabiano Rosas excp); 93052926b0dSFabiano Rosas } 93152926b0dSFabiano Rosas 93252926b0dSFabiano Rosas vector |= env->excp_prefix; 93352926b0dSFabiano Rosas 93452926b0dSFabiano Rosas switch (excp) { 93552926b0dSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 936c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 93752926b0dSFabiano Rosas /* 93852926b0dSFabiano Rosas * Machine check exception is not enabled. Enter 93952926b0dSFabiano Rosas * checkstop state. 94052926b0dSFabiano Rosas */ 94152926b0dSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 94252926b0dSFabiano Rosas "Entering checkstop state\n"); 94352926b0dSFabiano Rosas if (qemu_log_separate()) { 94452926b0dSFabiano Rosas qemu_log("Machine check while not allowed. " 94552926b0dSFabiano Rosas "Entering checkstop state\n"); 94652926b0dSFabiano Rosas } 94752926b0dSFabiano Rosas cs->halted = 1; 94852926b0dSFabiano Rosas cpu_interrupt_exittb(cs); 94952926b0dSFabiano Rosas } 95052926b0dSFabiano Rosas 95152926b0dSFabiano Rosas /* machine check exceptions don't have ME set */ 95252926b0dSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 95352926b0dSFabiano Rosas 95452926b0dSFabiano Rosas break; 95552926b0dSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 95652926b0dSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 95752926b0dSFabiano Rosas break; 95852926b0dSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 95952926b0dSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 96052926b0dSFabiano Rosas msr |= env->error_code; 96152926b0dSFabiano Rosas break; 96252926b0dSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 96352926b0dSFabiano Rosas break; 96452926b0dSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 96552926b0dSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 96652926b0dSFabiano Rosas /* 96752926b0dSFabiano Rosas * Note: the opcode fields will not be set properly for a 96852926b0dSFabiano Rosas * direct store load/store, but nobody cares as nobody 96952926b0dSFabiano Rosas * actually uses direct store segments. 97052926b0dSFabiano Rosas */ 97152926b0dSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 97252926b0dSFabiano Rosas break; 97352926b0dSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 97452926b0dSFabiano Rosas switch (env->error_code & ~0xF) { 97552926b0dSFabiano Rosas case POWERPC_EXCP_FP: 976da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 97752926b0dSFabiano Rosas trace_ppc_excp_fp_ignore(); 9783680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 97952926b0dSFabiano Rosas return; 98052926b0dSFabiano Rosas } 98152926b0dSFabiano Rosas 98252926b0dSFabiano Rosas /* 98352926b0dSFabiano Rosas * FP exceptions always have NIP pointing to the faulting 98452926b0dSFabiano Rosas * instruction, so always use store_next and claim we are 98552926b0dSFabiano Rosas * precise in the MSR. 98652926b0dSFabiano Rosas */ 98752926b0dSFabiano Rosas msr |= 0x00100000; 98852926b0dSFabiano Rosas break; 98952926b0dSFabiano Rosas case POWERPC_EXCP_INVAL: 99052926b0dSFabiano Rosas trace_ppc_excp_inval(env->nip); 99152926b0dSFabiano Rosas msr |= 0x00080000; 99252926b0dSFabiano Rosas break; 99352926b0dSFabiano Rosas case POWERPC_EXCP_PRIV: 99452926b0dSFabiano Rosas msr |= 0x00040000; 99552926b0dSFabiano Rosas break; 99652926b0dSFabiano Rosas case POWERPC_EXCP_TRAP: 99752926b0dSFabiano Rosas msr |= 0x00020000; 99852926b0dSFabiano Rosas break; 99952926b0dSFabiano Rosas default: 100052926b0dSFabiano Rosas /* Should never occur */ 100152926b0dSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 100252926b0dSFabiano Rosas env->error_code); 100352926b0dSFabiano Rosas break; 100452926b0dSFabiano Rosas } 100552926b0dSFabiano Rosas break; 100652926b0dSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 1007bca2c6d9SFabiano Rosas { 1008bca2c6d9SFabiano Rosas int lev = env->error_code; 100952926b0dSFabiano Rosas 101052926b0dSFabiano Rosas if ((lev == 1) && cpu->vhyp) { 101152926b0dSFabiano Rosas dump_hcall(env); 101252926b0dSFabiano Rosas } else { 101352926b0dSFabiano Rosas dump_syscall(env); 101452926b0dSFabiano Rosas } 101552926b0dSFabiano Rosas 101652926b0dSFabiano Rosas /* 101752926b0dSFabiano Rosas * We need to correct the NIP which in this case is supposed 101852926b0dSFabiano Rosas * to point to the next instruction 101952926b0dSFabiano Rosas */ 102052926b0dSFabiano Rosas env->nip += 4; 102152926b0dSFabiano Rosas 1022bca2c6d9SFabiano Rosas /* 1023bca2c6d9SFabiano Rosas * The Virtual Open Firmware (VOF) relies on the 'sc 1' 1024bca2c6d9SFabiano Rosas * instruction to communicate with QEMU. The pegasos2 machine 1025bca2c6d9SFabiano Rosas * uses VOF and the 74xx CPUs, so although the 74xx don't have 1026bca2c6d9SFabiano Rosas * HV mode, we need to keep hypercall support. 1027bca2c6d9SFabiano Rosas */ 102852926b0dSFabiano Rosas if ((lev == 1) && cpu->vhyp) { 102952926b0dSFabiano Rosas PPCVirtualHypervisorClass *vhc = 103052926b0dSFabiano Rosas PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 103152926b0dSFabiano Rosas vhc->hypercall(cpu->vhyp, cpu); 103252926b0dSFabiano Rosas return; 103352926b0dSFabiano Rosas } 1034bca2c6d9SFabiano Rosas 103552926b0dSFabiano Rosas break; 1036bca2c6d9SFabiano Rosas } 103752926b0dSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 103852926b0dSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 103952926b0dSFabiano Rosas break; 104052926b0dSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 10418e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 104252926b0dSFabiano Rosas cpu_abort(cs, "Trying to deliver power-saving system reset " 104352926b0dSFabiano Rosas "exception %d with no HV support\n", excp); 104452926b0dSFabiano Rosas } 104552926b0dSFabiano Rosas break; 104652926b0dSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 104752926b0dSFabiano Rosas break; 104852926b0dSFabiano Rosas case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 104952926b0dSFabiano Rosas break; 105052926b0dSFabiano Rosas case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 105152926b0dSFabiano Rosas case POWERPC_EXCP_SMI: /* System management interrupt */ 105252926b0dSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 105352926b0dSFabiano Rosas case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 105452926b0dSFabiano Rosas case POWERPC_EXCP_VPUA: /* Vector assist exception */ 105552926b0dSFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 105652926b0dSFabiano Rosas powerpc_excp_name(excp)); 105752926b0dSFabiano Rosas break; 105852926b0dSFabiano Rosas default: 105952926b0dSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 106052926b0dSFabiano Rosas break; 106152926b0dSFabiano Rosas } 106252926b0dSFabiano Rosas 106352926b0dSFabiano Rosas /* 106452926b0dSFabiano Rosas * Sort out endianness of interrupt, this differs depending on the 106552926b0dSFabiano Rosas * CPU, the HV mode, etc... 106652926b0dSFabiano Rosas */ 106752926b0dSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 106852926b0dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 106952926b0dSFabiano Rosas } 107052926b0dSFabiano Rosas 107152926b0dSFabiano Rosas /* Save PC */ 1072f82db777SFabiano Rosas env->spr[SPR_SRR0] = env->nip; 107352926b0dSFabiano Rosas 107452926b0dSFabiano Rosas /* Save MSR */ 1075f82db777SFabiano Rosas env->spr[SPR_SRR1] = msr; 107652926b0dSFabiano Rosas 107752926b0dSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 107852926b0dSFabiano Rosas } 107952926b0dSFabiano Rosas 1080180952ceSFabiano Rosas static void powerpc_excp_booke(PowerPCCPU *cpu, int excp) 1081180952ceSFabiano Rosas { 1082180952ceSFabiano Rosas CPUState *cs = CPU(cpu); 1083180952ceSFabiano Rosas CPUPPCState *env = &cpu->env; 1084180952ceSFabiano Rosas target_ulong msr, new_msr, vector; 1085904e8428SFabiano Rosas int srr0, srr1; 1086180952ceSFabiano Rosas 1087180952ceSFabiano Rosas msr = env->msr; 1088180952ceSFabiano Rosas 1089180952ceSFabiano Rosas /* 10909dc20cc3SFabiano Rosas * new interrupt handler msr preserves existing ME unless 1091180952ceSFabiano Rosas * explicitly overriden 1092180952ceSFabiano Rosas */ 10939dc20cc3SFabiano Rosas new_msr = env->msr & ((target_ulong)1 << MSR_ME); 1094180952ceSFabiano Rosas 1095180952ceSFabiano Rosas /* target registers */ 1096180952ceSFabiano Rosas srr0 = SPR_SRR0; 1097180952ceSFabiano Rosas srr1 = SPR_SRR1; 1098180952ceSFabiano Rosas 1099180952ceSFabiano Rosas /* 1100180952ceSFabiano Rosas * Hypervisor emulation assistance interrupt only exists on server 11019dc20cc3SFabiano Rosas * arch 2.05 server or later. 1102180952ceSFabiano Rosas */ 11039dc20cc3SFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU) { 1104180952ceSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 1105180952ceSFabiano Rosas } 1106180952ceSFabiano Rosas 1107180952ceSFabiano Rosas #ifdef TARGET_PPC64 1108180952ceSFabiano Rosas /* 1109180952ceSFabiano Rosas * SPEU and VPU share the same IVOR but they exist in different 1110180952ceSFabiano Rosas * processors. SPEU is e500v1/2 only and VPU is e6500 only. 1111180952ceSFabiano Rosas */ 11129dc20cc3SFabiano Rosas if (excp == POWERPC_EXCP_VPU) { 1113180952ceSFabiano Rosas excp = POWERPC_EXCP_SPEU; 1114180952ceSFabiano Rosas } 1115180952ceSFabiano Rosas #endif 1116180952ceSFabiano Rosas 1117180952ceSFabiano Rosas vector = env->excp_vectors[excp]; 1118180952ceSFabiano Rosas if (vector == (target_ulong)-1ULL) { 1119180952ceSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 1120180952ceSFabiano Rosas excp); 1121180952ceSFabiano Rosas } 1122180952ceSFabiano Rosas 1123180952ceSFabiano Rosas vector |= env->excp_prefix; 1124180952ceSFabiano Rosas 1125180952ceSFabiano Rosas switch (excp) { 1126180952ceSFabiano Rosas case POWERPC_EXCP_CRITICAL: /* Critical input */ 1127180952ceSFabiano Rosas srr0 = SPR_BOOKE_CSRR0; 1128180952ceSFabiano Rosas srr1 = SPR_BOOKE_CSRR1; 1129180952ceSFabiano Rosas break; 1130180952ceSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1131c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 1132180952ceSFabiano Rosas /* 1133180952ceSFabiano Rosas * Machine check exception is not enabled. Enter 1134180952ceSFabiano Rosas * checkstop state. 1135180952ceSFabiano Rosas */ 1136180952ceSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 1137180952ceSFabiano Rosas "Entering checkstop state\n"); 1138180952ceSFabiano Rosas if (qemu_log_separate()) { 1139180952ceSFabiano Rosas qemu_log("Machine check while not allowed. " 1140180952ceSFabiano Rosas "Entering checkstop state\n"); 1141180952ceSFabiano Rosas } 1142180952ceSFabiano Rosas cs->halted = 1; 1143180952ceSFabiano Rosas cpu_interrupt_exittb(cs); 1144180952ceSFabiano Rosas } 1145180952ceSFabiano Rosas 1146180952ceSFabiano Rosas /* machine check exceptions don't have ME set */ 1147180952ceSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 1148180952ceSFabiano Rosas 1149180952ceSFabiano Rosas /* FIXME: choose one or the other based on CPU type */ 1150180952ceSFabiano Rosas srr0 = SPR_BOOKE_MCSRR0; 1151180952ceSFabiano Rosas srr1 = SPR_BOOKE_MCSRR1; 1152180952ceSFabiano Rosas 1153180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR0] = env->nip; 1154180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR1] = msr; 1155db403211SFabiano Rosas 1156180952ceSFabiano Rosas break; 1157180952ceSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 1158afdbc869SFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]); 1159180952ceSFabiano Rosas break; 1160180952ceSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 1161180952ceSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 1162180952ceSFabiano Rosas break; 1163180952ceSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 1164180952ceSFabiano Rosas if (env->mpic_proxy) { 1165180952ceSFabiano Rosas /* IACK the IRQ on delivery */ 1166180952ceSFabiano Rosas env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); 1167180952ceSFabiano Rosas } 1168180952ceSFabiano Rosas break; 1169180952ceSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 1170180952ceSFabiano Rosas break; 1171180952ceSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 1172180952ceSFabiano Rosas switch (env->error_code & ~0xF) { 1173180952ceSFabiano Rosas case POWERPC_EXCP_FP: 1174da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 1175180952ceSFabiano Rosas trace_ppc_excp_fp_ignore(); 11763680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 1177180952ceSFabiano Rosas return; 1178180952ceSFabiano Rosas } 1179180952ceSFabiano Rosas 1180180952ceSFabiano Rosas /* 1181180952ceSFabiano Rosas * FP exceptions always have NIP pointing to the faulting 1182180952ceSFabiano Rosas * instruction, so always use store_next and claim we are 1183180952ceSFabiano Rosas * precise in the MSR. 1184180952ceSFabiano Rosas */ 1185180952ceSFabiano Rosas msr |= 0x00100000; 1186180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_FP; 1187180952ceSFabiano Rosas break; 1188180952ceSFabiano Rosas case POWERPC_EXCP_INVAL: 1189180952ceSFabiano Rosas trace_ppc_excp_inval(env->nip); 1190180952ceSFabiano Rosas msr |= 0x00080000; 1191180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PIL; 1192180952ceSFabiano Rosas break; 1193180952ceSFabiano Rosas case POWERPC_EXCP_PRIV: 1194180952ceSFabiano Rosas msr |= 0x00040000; 1195180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PPR; 1196180952ceSFabiano Rosas break; 1197180952ceSFabiano Rosas case POWERPC_EXCP_TRAP: 1198180952ceSFabiano Rosas msr |= 0x00020000; 1199180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_PTR; 1200180952ceSFabiano Rosas break; 1201180952ceSFabiano Rosas default: 1202180952ceSFabiano Rosas /* Should never occur */ 1203180952ceSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 1204180952ceSFabiano Rosas env->error_code); 1205180952ceSFabiano Rosas break; 1206180952ceSFabiano Rosas } 1207180952ceSFabiano Rosas break; 1208180952ceSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 1209180952ceSFabiano Rosas dump_syscall(env); 1210180952ceSFabiano Rosas 1211180952ceSFabiano Rosas /* 1212180952ceSFabiano Rosas * We need to correct the NIP which in this case is supposed 1213180952ceSFabiano Rosas * to point to the next instruction 1214180952ceSFabiano Rosas */ 1215180952ceSFabiano Rosas env->nip += 4; 1216180952ceSFabiano Rosas break; 1217180952ceSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 1218180952ceSFabiano Rosas case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 1219180952ceSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 1220180952ceSFabiano Rosas break; 1221180952ceSFabiano Rosas case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 1222180952ceSFabiano Rosas /* FIT on 4xx */ 1223180952ceSFabiano Rosas trace_ppc_excp_print("FIT"); 1224180952ceSFabiano Rosas break; 1225180952ceSFabiano Rosas case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 1226180952ceSFabiano Rosas trace_ppc_excp_print("WDT"); 1227180952ceSFabiano Rosas srr0 = SPR_BOOKE_CSRR0; 1228180952ceSFabiano Rosas srr1 = SPR_BOOKE_CSRR1; 1229180952ceSFabiano Rosas break; 1230180952ceSFabiano Rosas case POWERPC_EXCP_DTLB: /* Data TLB error */ 1231180952ceSFabiano Rosas case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 1232180952ceSFabiano Rosas break; 1233180952ceSFabiano Rosas case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 1234180952ceSFabiano Rosas if (env->flags & POWERPC_FLAG_DE) { 1235180952ceSFabiano Rosas /* FIXME: choose one or the other based on CPU type */ 1236180952ceSFabiano Rosas srr0 = SPR_BOOKE_DSRR0; 1237180952ceSFabiano Rosas srr1 = SPR_BOOKE_DSRR1; 1238180952ceSFabiano Rosas 1239180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR0] = env->nip; 1240180952ceSFabiano Rosas env->spr[SPR_BOOKE_CSRR1] = msr; 1241180952ceSFabiano Rosas 1242180952ceSFabiano Rosas /* DBSR already modified by caller */ 1243180952ceSFabiano Rosas } else { 1244180952ceSFabiano Rosas cpu_abort(cs, "Debug exception triggered on unsupported model\n"); 1245180952ceSFabiano Rosas } 1246180952ceSFabiano Rosas break; 1247180952ceSFabiano Rosas case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ 1248180952ceSFabiano Rosas env->spr[SPR_BOOKE_ESR] = ESR_SPV; 1249180952ceSFabiano Rosas break; 1250180952ceSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 12518e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 1252180952ceSFabiano Rosas cpu_abort(cs, "Trying to deliver power-saving system reset " 1253180952ceSFabiano Rosas "exception %d with no HV support\n", excp); 1254180952ceSFabiano Rosas } 1255180952ceSFabiano Rosas break; 1256180952ceSFabiano Rosas case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ 1257180952ceSFabiano Rosas case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ 1258180952ceSFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 1259180952ceSFabiano Rosas powerpc_excp_name(excp)); 1260180952ceSFabiano Rosas break; 1261180952ceSFabiano Rosas default: 1262180952ceSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 1263180952ceSFabiano Rosas break; 1264180952ceSFabiano Rosas } 1265180952ceSFabiano Rosas 1266180952ceSFabiano Rosas #if defined(TARGET_PPC64) 1267180952ceSFabiano Rosas if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { 1268180952ceSFabiano Rosas /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ 1269180952ceSFabiano Rosas new_msr |= (target_ulong)1 << MSR_CM; 1270180952ceSFabiano Rosas } else { 1271180952ceSFabiano Rosas vector = (uint32_t)vector; 1272180952ceSFabiano Rosas } 1273180952ceSFabiano Rosas #endif 1274180952ceSFabiano Rosas 1275180952ceSFabiano Rosas /* Save PC */ 1276180952ceSFabiano Rosas env->spr[srr0] = env->nip; 1277180952ceSFabiano Rosas 1278180952ceSFabiano Rosas /* Save MSR */ 1279180952ceSFabiano Rosas env->spr[srr1] = msr; 1280180952ceSFabiano Rosas 1281180952ceSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 1282180952ceSFabiano Rosas } 1283180952ceSFabiano Rosas 12847cebc5dbSNicholas Piggin /* 12857cebc5dbSNicholas Piggin * When running a nested HV guest under vhyp, external interrupts are 12867cebc5dbSNicholas Piggin * delivered as HVIRT. 12877cebc5dbSNicholas Piggin */ 12887cebc5dbSNicholas Piggin static bool books_vhyp_promotes_external_to_hvirt(PowerPCCPU *cpu) 12897cebc5dbSNicholas Piggin { 12907cebc5dbSNicholas Piggin if (cpu->vhyp) { 12917cebc5dbSNicholas Piggin return vhyp_cpu_in_nested(cpu); 12927cebc5dbSNicholas Piggin } 12937cebc5dbSNicholas Piggin return false; 12947cebc5dbSNicholas Piggin } 12957cebc5dbSNicholas Piggin 129630c4e426SFabiano Rosas #ifdef TARGET_PPC64 12974c6cf6b2SNicholas Piggin /* 12984c6cf6b2SNicholas Piggin * When running under vhyp, hcalls are always intercepted and sent to the 12994c6cf6b2SNicholas Piggin * vhc->hypercall handler. 13004c6cf6b2SNicholas Piggin */ 13014c6cf6b2SNicholas Piggin static bool books_vhyp_handles_hcall(PowerPCCPU *cpu) 13024c6cf6b2SNicholas Piggin { 13034c6cf6b2SNicholas Piggin if (cpu->vhyp) { 13047cebc5dbSNicholas Piggin return !vhyp_cpu_in_nested(cpu); 13057cebc5dbSNicholas Piggin } 13067cebc5dbSNicholas Piggin return false; 13077cebc5dbSNicholas Piggin } 13087cebc5dbSNicholas Piggin 13097cebc5dbSNicholas Piggin /* 13107cebc5dbSNicholas Piggin * When running a nested KVM HV guest under vhyp, HV exceptions are not 13117cebc5dbSNicholas Piggin * delivered to the guest (because there is no concept of HV support), but 13127cebc5dbSNicholas Piggin * rather they are sent tothe vhyp to exit from the L2 back to the L1 and 13137cebc5dbSNicholas Piggin * return from the H_ENTER_NESTED hypercall. 13147cebc5dbSNicholas Piggin */ 13157cebc5dbSNicholas Piggin static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu) 13167cebc5dbSNicholas Piggin { 13177cebc5dbSNicholas Piggin if (cpu->vhyp) { 13187cebc5dbSNicholas Piggin return vhyp_cpu_in_nested(cpu); 13194c6cf6b2SNicholas Piggin } 13204c6cf6b2SNicholas Piggin return false; 13214c6cf6b2SNicholas Piggin } 13224c6cf6b2SNicholas Piggin 13239f338e4dSFabiano Rosas static void powerpc_excp_books(PowerPCCPU *cpu, int excp) 13249f338e4dSFabiano Rosas { 13259f338e4dSFabiano Rosas CPUState *cs = CPU(cpu); 13269f338e4dSFabiano Rosas CPUPPCState *env = &cpu->env; 13279f338e4dSFabiano Rosas target_ulong msr, new_msr, vector; 13289f338e4dSFabiano Rosas int srr0, srr1, lev = -1; 13299f338e4dSFabiano Rosas 13309f338e4dSFabiano Rosas /* new srr1 value excluding must-be-zero bits */ 13319f338e4dSFabiano Rosas msr = env->msr & ~0x783f0000ULL; 13329f338e4dSFabiano Rosas 13339f338e4dSFabiano Rosas /* 13349f338e4dSFabiano Rosas * new interrupt handler msr preserves existing HV and ME unless 13359f338e4dSFabiano Rosas * explicitly overriden 13369f338e4dSFabiano Rosas */ 13379f338e4dSFabiano Rosas new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); 13389f338e4dSFabiano Rosas 13399f338e4dSFabiano Rosas /* target registers */ 13409f338e4dSFabiano Rosas srr0 = SPR_SRR0; 13419f338e4dSFabiano Rosas srr1 = SPR_SRR1; 13429f338e4dSFabiano Rosas 13439f338e4dSFabiano Rosas /* 13449f338e4dSFabiano Rosas * check for special resume at 0x100 from doze/nap/sleep/winkle on 13459f338e4dSFabiano Rosas * P7/P8/P9 13469f338e4dSFabiano Rosas */ 13479f338e4dSFabiano Rosas if (env->resume_as_sreset) { 13489f338e4dSFabiano Rosas excp = powerpc_reset_wakeup(cs, env, excp, &msr); 13499f338e4dSFabiano Rosas } 13509f338e4dSFabiano Rosas 13519f338e4dSFabiano Rosas /* 135230c4e426SFabiano Rosas * We don't want to generate a Hypervisor Emulation Assistance 135330c4e426SFabiano Rosas * Interrupt if we don't have HVB in msr_mask (PAPR mode). 13549f338e4dSFabiano Rosas */ 135530c4e426SFabiano Rosas if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) { 13569f338e4dSFabiano Rosas excp = POWERPC_EXCP_PROGRAM; 13579f338e4dSFabiano Rosas } 13589f338e4dSFabiano Rosas 13599f338e4dSFabiano Rosas vector = env->excp_vectors[excp]; 13609f338e4dSFabiano Rosas if (vector == (target_ulong)-1ULL) { 13619f338e4dSFabiano Rosas cpu_abort(cs, "Raised an exception without defined vector %d\n", 13629f338e4dSFabiano Rosas excp); 13639f338e4dSFabiano Rosas } 13649f338e4dSFabiano Rosas 13659f338e4dSFabiano Rosas vector |= env->excp_prefix; 13669f338e4dSFabiano Rosas 13679f338e4dSFabiano Rosas switch (excp) { 13689f338e4dSFabiano Rosas case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1369c354d858SVíctor Colombo if (!FIELD_EX64(env->msr, MSR, ME)) { 13709f338e4dSFabiano Rosas /* 13719f338e4dSFabiano Rosas * Machine check exception is not enabled. Enter 13729f338e4dSFabiano Rosas * checkstop state. 13739f338e4dSFabiano Rosas */ 13749f338e4dSFabiano Rosas fprintf(stderr, "Machine check while not allowed. " 13759f338e4dSFabiano Rosas "Entering checkstop state\n"); 13769f338e4dSFabiano Rosas if (qemu_log_separate()) { 13779f338e4dSFabiano Rosas qemu_log("Machine check while not allowed. " 13789f338e4dSFabiano Rosas "Entering checkstop state\n"); 13799f338e4dSFabiano Rosas } 13809f338e4dSFabiano Rosas cs->halted = 1; 13819f338e4dSFabiano Rosas cpu_interrupt_exittb(cs); 13829f338e4dSFabiano Rosas } 13839f338e4dSFabiano Rosas if (env->msr_mask & MSR_HVB) { 13849f338e4dSFabiano Rosas /* 13859f338e4dSFabiano Rosas * ISA specifies HV, but can be delivered to guest with HV 13869f338e4dSFabiano Rosas * clear (e.g., see FWNMI in PAPR). 13879f338e4dSFabiano Rosas */ 13889f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 13899f338e4dSFabiano Rosas } 13909f338e4dSFabiano Rosas 13919f338e4dSFabiano Rosas /* machine check exceptions don't have ME set */ 13929f338e4dSFabiano Rosas new_msr &= ~((target_ulong)1 << MSR_ME); 13939f338e4dSFabiano Rosas 13949f338e4dSFabiano Rosas break; 13959f338e4dSFabiano Rosas case POWERPC_EXCP_DSI: /* Data storage exception */ 13969f338e4dSFabiano Rosas trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); 13979f338e4dSFabiano Rosas break; 13989f338e4dSFabiano Rosas case POWERPC_EXCP_ISI: /* Instruction storage exception */ 13999f338e4dSFabiano Rosas trace_ppc_excp_isi(msr, env->nip); 14009f338e4dSFabiano Rosas msr |= env->error_code; 14019f338e4dSFabiano Rosas break; 14029f338e4dSFabiano Rosas case POWERPC_EXCP_EXTERNAL: /* External input */ 14039f338e4dSFabiano Rosas { 14049f338e4dSFabiano Rosas bool lpes0; 14059f338e4dSFabiano Rosas 14069f338e4dSFabiano Rosas /* 140767baff77SFabiano Rosas * LPES0 is only taken into consideration if we support HV 140867baff77SFabiano Rosas * mode for this CPU. 14099f338e4dSFabiano Rosas */ 141067baff77SFabiano Rosas if (!env->has_hv_mode) { 141167baff77SFabiano Rosas break; 14129f338e4dSFabiano Rosas } 14139f338e4dSFabiano Rosas 141467baff77SFabiano Rosas lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 141567baff77SFabiano Rosas 14169f338e4dSFabiano Rosas if (!lpes0) { 14179f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14189f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 14199f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 14209f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 14219f338e4dSFabiano Rosas } 142267baff77SFabiano Rosas 14239f338e4dSFabiano Rosas break; 14249f338e4dSFabiano Rosas } 14259f338e4dSFabiano Rosas case POWERPC_EXCP_ALIGN: /* Alignment exception */ 14269f338e4dSFabiano Rosas /* Get rS/rD and rA from faulting opcode */ 14279f338e4dSFabiano Rosas /* 14289f338e4dSFabiano Rosas * Note: the opcode fields will not be set properly for a 14299f338e4dSFabiano Rosas * direct store load/store, but nobody cares as nobody 14309f338e4dSFabiano Rosas * actually uses direct store segments. 14319f338e4dSFabiano Rosas */ 14329f338e4dSFabiano Rosas env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 14339f338e4dSFabiano Rosas break; 14349f338e4dSFabiano Rosas case POWERPC_EXCP_PROGRAM: /* Program exception */ 14359f338e4dSFabiano Rosas switch (env->error_code & ~0xF) { 14369f338e4dSFabiano Rosas case POWERPC_EXCP_FP: 1437da806a6cSVíctor Colombo if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) { 14389f338e4dSFabiano Rosas trace_ppc_excp_fp_ignore(); 14393680e994SNicholas Piggin powerpc_reset_excp_state(cpu); 14409f338e4dSFabiano Rosas return; 14419f338e4dSFabiano Rosas } 14429f338e4dSFabiano Rosas 14439f338e4dSFabiano Rosas /* 14449f338e4dSFabiano Rosas * FP exceptions always have NIP pointing to the faulting 14459f338e4dSFabiano Rosas * instruction, so always use store_next and claim we are 14469f338e4dSFabiano Rosas * precise in the MSR. 14479f338e4dSFabiano Rosas */ 14489f338e4dSFabiano Rosas msr |= 0x00100000; 14499f338e4dSFabiano Rosas break; 14509f338e4dSFabiano Rosas case POWERPC_EXCP_INVAL: 14519f338e4dSFabiano Rosas trace_ppc_excp_inval(env->nip); 14529f338e4dSFabiano Rosas msr |= 0x00080000; 14539f338e4dSFabiano Rosas break; 14549f338e4dSFabiano Rosas case POWERPC_EXCP_PRIV: 14559f338e4dSFabiano Rosas msr |= 0x00040000; 14569f338e4dSFabiano Rosas break; 14579f338e4dSFabiano Rosas case POWERPC_EXCP_TRAP: 14589f338e4dSFabiano Rosas msr |= 0x00020000; 14599f338e4dSFabiano Rosas break; 14609f338e4dSFabiano Rosas default: 14619f338e4dSFabiano Rosas /* Should never occur */ 14629f338e4dSFabiano Rosas cpu_abort(cs, "Invalid program exception %d. Aborting\n", 14639f338e4dSFabiano Rosas env->error_code); 14649f338e4dSFabiano Rosas break; 14659f338e4dSFabiano Rosas } 14669f338e4dSFabiano Rosas break; 14679f338e4dSFabiano Rosas case POWERPC_EXCP_SYSCALL: /* System call exception */ 14689f338e4dSFabiano Rosas lev = env->error_code; 14699f338e4dSFabiano Rosas 14709f338e4dSFabiano Rosas if ((lev == 1) && cpu->vhyp) { 14719f338e4dSFabiano Rosas dump_hcall(env); 14729f338e4dSFabiano Rosas } else { 14739f338e4dSFabiano Rosas dump_syscall(env); 14749f338e4dSFabiano Rosas } 14759f338e4dSFabiano Rosas 14769f338e4dSFabiano Rosas /* 14779f338e4dSFabiano Rosas * We need to correct the NIP which in this case is supposed 14789f338e4dSFabiano Rosas * to point to the next instruction 14799f338e4dSFabiano Rosas */ 14809f338e4dSFabiano Rosas env->nip += 4; 14819f338e4dSFabiano Rosas 14829f338e4dSFabiano Rosas /* "PAPR mode" built-in hypercall emulation */ 14834c6cf6b2SNicholas Piggin if ((lev == 1) && books_vhyp_handles_hcall(cpu)) { 14849f338e4dSFabiano Rosas PPCVirtualHypervisorClass *vhc = 14859f338e4dSFabiano Rosas PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 14869f338e4dSFabiano Rosas vhc->hypercall(cpu->vhyp, cpu); 14879f338e4dSFabiano Rosas return; 14889f338e4dSFabiano Rosas } 14899f338e4dSFabiano Rosas if (lev == 1) { 14909f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 14919f338e4dSFabiano Rosas } 14929f338e4dSFabiano Rosas break; 14939f338e4dSFabiano Rosas case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ 14949f338e4dSFabiano Rosas lev = env->error_code; 14959f338e4dSFabiano Rosas dump_syscall(env); 14969f338e4dSFabiano Rosas env->nip += 4; 14979f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_EE); 14989f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 14999f338e4dSFabiano Rosas 15009f338e4dSFabiano Rosas vector += lev * 0x20; 15019f338e4dSFabiano Rosas 15029f338e4dSFabiano Rosas env->lr = env->nip; 15039f338e4dSFabiano Rosas env->ctr = msr; 15049f338e4dSFabiano Rosas break; 15059f338e4dSFabiano Rosas case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 15069f338e4dSFabiano Rosas case POWERPC_EXCP_DECR: /* Decrementer exception */ 15079f338e4dSFabiano Rosas break; 15089f338e4dSFabiano Rosas case POWERPC_EXCP_RESET: /* System reset exception */ 15099f338e4dSFabiano Rosas /* A power-saving exception sets ME, otherwise it is unchanged */ 15108e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 15119f338e4dSFabiano Rosas /* indicate that we resumed from power save mode */ 15129f338e4dSFabiano Rosas msr |= 0x10000; 15139f338e4dSFabiano Rosas new_msr |= ((target_ulong)1 << MSR_ME); 15149f338e4dSFabiano Rosas } 15159f338e4dSFabiano Rosas if (env->msr_mask & MSR_HVB) { 15169f338e4dSFabiano Rosas /* 15179f338e4dSFabiano Rosas * ISA specifies HV, but can be delivered to guest with HV 15189f338e4dSFabiano Rosas * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). 15199f338e4dSFabiano Rosas */ 15209f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 15219f338e4dSFabiano Rosas } else { 15228e54ad65SVíctor Colombo if (FIELD_EX64(env->msr, MSR, POW)) { 15239f338e4dSFabiano Rosas cpu_abort(cs, "Trying to deliver power-saving system reset " 15249f338e4dSFabiano Rosas "exception %d with no HV support\n", excp); 15259f338e4dSFabiano Rosas } 15269f338e4dSFabiano Rosas } 15279f338e4dSFabiano Rosas break; 15289f338e4dSFabiano Rosas case POWERPC_EXCP_DSEG: /* Data segment exception */ 15299f338e4dSFabiano Rosas case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 15309f338e4dSFabiano Rosas case POWERPC_EXCP_TRACE: /* Trace exception */ 15319f338e4dSFabiano Rosas break; 15329f338e4dSFabiano Rosas case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ 15339f338e4dSFabiano Rosas msr |= env->error_code; 15349f338e4dSFabiano Rosas /* fall through */ 15359f338e4dSFabiano Rosas case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 15369f338e4dSFabiano Rosas case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 15379f338e4dSFabiano Rosas case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ 15389f338e4dSFabiano Rosas case POWERPC_EXCP_HV_EMU: 15399f338e4dSFabiano Rosas case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ 15409f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 15419f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 15429f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 15439f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 15449f338e4dSFabiano Rosas break; 15459f338e4dSFabiano Rosas case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 15469f338e4dSFabiano Rosas case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ 15479f338e4dSFabiano Rosas case POWERPC_EXCP_FU: /* Facility unavailable exception */ 15489f338e4dSFabiano Rosas env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); 15499f338e4dSFabiano Rosas break; 15509f338e4dSFabiano Rosas case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ 15519f338e4dSFabiano Rosas env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); 15529f338e4dSFabiano Rosas srr0 = SPR_HSRR0; 15539f338e4dSFabiano Rosas srr1 = SPR_HSRR1; 15549f338e4dSFabiano Rosas new_msr |= (target_ulong)MSR_HVB; 15559f338e4dSFabiano Rosas new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 15569f338e4dSFabiano Rosas break; 1557cb76bbc4SDaniel Henrique Barboza case POWERPC_EXCP_PERFM_EBB: /* Performance Monitor EBB Exception */ 1558cb76bbc4SDaniel Henrique Barboza case POWERPC_EXCP_EXTERNAL_EBB: /* External EBB Exception */ 1559cb76bbc4SDaniel Henrique Barboza env->spr[SPR_BESCR] &= ~BESCR_GE; 1560cb76bbc4SDaniel Henrique Barboza 1561cb76bbc4SDaniel Henrique Barboza /* 1562cb76bbc4SDaniel Henrique Barboza * Save NIP for rfebb insn in SPR_EBBRR. Next nip is 1563cb76bbc4SDaniel Henrique Barboza * stored in the EBB Handler SPR_EBBHR. 1564cb76bbc4SDaniel Henrique Barboza */ 1565cb76bbc4SDaniel Henrique Barboza env->spr[SPR_EBBRR] = env->nip; 1566cb76bbc4SDaniel Henrique Barboza powerpc_set_excp_state(cpu, env->spr[SPR_EBBHR], env->msr); 1567cb76bbc4SDaniel Henrique Barboza 1568cb76bbc4SDaniel Henrique Barboza /* 1569cb76bbc4SDaniel Henrique Barboza * This exception is handled in userspace. No need to proceed. 1570cb76bbc4SDaniel Henrique Barboza */ 1571cb76bbc4SDaniel Henrique Barboza return; 15729f338e4dSFabiano Rosas case POWERPC_EXCP_THERM: /* Thermal interrupt */ 15739f338e4dSFabiano Rosas case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 15749f338e4dSFabiano Rosas case POWERPC_EXCP_VPUA: /* Vector assist exception */ 15759f338e4dSFabiano Rosas case POWERPC_EXCP_MAINT: /* Maintenance exception */ 157630c4e426SFabiano Rosas case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */ 157730c4e426SFabiano Rosas case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */ 15789f338e4dSFabiano Rosas cpu_abort(cs, "%s exception not implemented\n", 15799f338e4dSFabiano Rosas powerpc_excp_name(excp)); 15809f338e4dSFabiano Rosas break; 15819f338e4dSFabiano Rosas default: 15829f338e4dSFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 15839f338e4dSFabiano Rosas break; 15849f338e4dSFabiano Rosas } 15859f338e4dSFabiano Rosas 15869f338e4dSFabiano Rosas /* 15879f338e4dSFabiano Rosas * Sort out endianness of interrupt, this differs depending on the 15889f338e4dSFabiano Rosas * CPU, the HV mode, etc... 15899f338e4dSFabiano Rosas */ 15909f338e4dSFabiano Rosas if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { 15919f338e4dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_LE; 15929f338e4dSFabiano Rosas } 15939f338e4dSFabiano Rosas 15949f338e4dSFabiano Rosas new_msr |= (target_ulong)1 << MSR_SF; 15959f338e4dSFabiano Rosas 15969f338e4dSFabiano Rosas if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { 15979f338e4dSFabiano Rosas /* Save PC */ 15989f338e4dSFabiano Rosas env->spr[srr0] = env->nip; 15999f338e4dSFabiano Rosas 16009f338e4dSFabiano Rosas /* Save MSR */ 16019f338e4dSFabiano Rosas env->spr[srr1] = msr; 16029f338e4dSFabiano Rosas } 16039f338e4dSFabiano Rosas 16047cebc5dbSNicholas Piggin if ((new_msr & MSR_HVB) && books_vhyp_handles_hv_excp(cpu)) { 16057cebc5dbSNicholas Piggin PPCVirtualHypervisorClass *vhc = 16067cebc5dbSNicholas Piggin PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 16077cebc5dbSNicholas Piggin /* Deliver interrupt to L1 by returning from the H_ENTER_NESTED call */ 16087cebc5dbSNicholas Piggin vhc->deliver_hv_excp(cpu, excp); 16097cebc5dbSNicholas Piggin 16107cebc5dbSNicholas Piggin powerpc_reset_excp_state(cpu); 16117cebc5dbSNicholas Piggin 16127cebc5dbSNicholas Piggin } else { 16137cebc5dbSNicholas Piggin /* Sanity check */ 16147cebc5dbSNicholas Piggin if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) { 16157cebc5dbSNicholas Piggin cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " 16167cebc5dbSNicholas Piggin "no HV support\n", excp); 16177cebc5dbSNicholas Piggin } 16187cebc5dbSNicholas Piggin 16199f338e4dSFabiano Rosas /* This can update new_msr and vector if AIL applies */ 162010895ab6SFabiano Rosas ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector); 16219f338e4dSFabiano Rosas 16229f338e4dSFabiano Rosas powerpc_set_excp_state(cpu, vector, new_msr); 16239f338e4dSFabiano Rosas } 16247cebc5dbSNicholas Piggin } 162530c4e426SFabiano Rosas #else 162630c4e426SFabiano Rosas static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp) 162730c4e426SFabiano Rosas { 162830c4e426SFabiano Rosas g_assert_not_reached(); 162930c4e426SFabiano Rosas } 163030c4e426SFabiano Rosas #endif 16319f338e4dSFabiano Rosas 1632dc88dd0aSFabiano Rosas static void powerpc_excp(PowerPCCPU *cpu, int excp) 1633dc88dd0aSFabiano Rosas { 1634c6eaac89SFabiano Rosas CPUState *cs = CPU(cpu); 1635dc88dd0aSFabiano Rosas CPUPPCState *env = &cpu->env; 1636dc88dd0aSFabiano Rosas 1637c6eaac89SFabiano Rosas if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { 1638c6eaac89SFabiano Rosas cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 1639c6eaac89SFabiano Rosas } 1640c6eaac89SFabiano Rosas 1641c6eaac89SFabiano Rosas qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx 1642c6eaac89SFabiano Rosas " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), 1643c6eaac89SFabiano Rosas excp, env->error_code); 1644c6eaac89SFabiano Rosas 1645dc88dd0aSFabiano Rosas switch (env->excp_model) { 1646e808c2edSFabiano Rosas case POWERPC_EXCP_40x: 1647e808c2edSFabiano Rosas powerpc_excp_40x(cpu, excp); 1648e808c2edSFabiano Rosas break; 164958d178fbSFabiano Rosas case POWERPC_EXCP_6xx: 165058d178fbSFabiano Rosas powerpc_excp_6xx(cpu, excp); 165158d178fbSFabiano Rosas break; 1652ccfca2fcSFabiano Rosas case POWERPC_EXCP_7xx: 1653ccfca2fcSFabiano Rosas powerpc_excp_7xx(cpu, excp); 1654ccfca2fcSFabiano Rosas break; 165552926b0dSFabiano Rosas case POWERPC_EXCP_74xx: 165652926b0dSFabiano Rosas powerpc_excp_74xx(cpu, excp); 165752926b0dSFabiano Rosas break; 1658180952ceSFabiano Rosas case POWERPC_EXCP_BOOKE: 1659180952ceSFabiano Rosas powerpc_excp_booke(cpu, excp); 1660180952ceSFabiano Rosas break; 16619f338e4dSFabiano Rosas case POWERPC_EXCP_970: 16629f338e4dSFabiano Rosas case POWERPC_EXCP_POWER7: 16639f338e4dSFabiano Rosas case POWERPC_EXCP_POWER8: 16649f338e4dSFabiano Rosas case POWERPC_EXCP_POWER9: 16659f338e4dSFabiano Rosas case POWERPC_EXCP_POWER10: 16669f338e4dSFabiano Rosas powerpc_excp_books(cpu, excp); 16679f338e4dSFabiano Rosas break; 1668dc88dd0aSFabiano Rosas default: 166928091374SFabiano Rosas g_assert_not_reached(); 1670dc88dd0aSFabiano Rosas } 1671dc88dd0aSFabiano Rosas } 1672dc88dd0aSFabiano Rosas 167397a8ea5aSAndreas Färber void ppc_cpu_do_interrupt(CPUState *cs) 1674c79c73f6SBlue Swirl { 167597a8ea5aSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 16765c26a5b3SAndreas Färber 167793130c84SFabiano Rosas powerpc_excp(cpu, cs->exception_index); 1678c79c73f6SBlue Swirl } 1679c79c73f6SBlue Swirl 1680458dd766SRichard Henderson static void ppc_hw_interrupt(CPUPPCState *env) 1681c79c73f6SBlue Swirl { 1682db70b311SRichard Henderson PowerPCCPU *cpu = env_archcpu(env); 16833621e2c9SBenjamin Herrenschmidt bool async_deliver; 1684259186a7SAndreas Färber 1685c79c73f6SBlue Swirl /* External reset */ 1686c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { 1687c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); 168893130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_RESET); 1689c79c73f6SBlue Swirl return; 1690c79c73f6SBlue Swirl } 1691c79c73f6SBlue Swirl /* Machine check exception */ 1692c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { 1693c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); 169493130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_MCHECK); 1695c79c73f6SBlue Swirl return; 1696c79c73f6SBlue Swirl } 1697c79c73f6SBlue Swirl #if 0 /* TODO */ 1698c79c73f6SBlue Swirl /* External debug exception */ 1699c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { 1700c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); 170193130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_DEBUG); 1702c79c73f6SBlue Swirl return; 1703c79c73f6SBlue Swirl } 1704c79c73f6SBlue Swirl #endif 17053621e2c9SBenjamin Herrenschmidt 17063621e2c9SBenjamin Herrenschmidt /* 17073621e2c9SBenjamin Herrenschmidt * For interrupts that gate on MSR:EE, we need to do something a 17083621e2c9SBenjamin Herrenschmidt * bit more subtle, as we need to let them through even when EE is 17093621e2c9SBenjamin Herrenschmidt * clear when coming out of some power management states (in order 17103621e2c9SBenjamin Herrenschmidt * for them to become a 0x100). 17113621e2c9SBenjamin Herrenschmidt */ 17120939b8f8SVíctor Colombo async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; 17133621e2c9SBenjamin Herrenschmidt 1714c79c73f6SBlue Swirl /* Hypervisor decrementer exception */ 1715c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { 17164b236b62SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 17174b236b62SBenjamin Herrenschmidt bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); 1718*9de754d3SVíctor Colombo if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) { 17194b236b62SBenjamin Herrenschmidt /* HDEC clears on delivery */ 17204b236b62SBenjamin Herrenschmidt env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 172193130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_HDECR); 1722c79c73f6SBlue Swirl return; 1723c79c73f6SBlue Swirl } 1724c79c73f6SBlue Swirl } 1725d8ce5fd6SBenjamin Herrenschmidt 1726d8ce5fd6SBenjamin Herrenschmidt /* Hypervisor virtualization interrupt */ 1727d8ce5fd6SBenjamin Herrenschmidt if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { 1728d8ce5fd6SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 1729d8ce5fd6SBenjamin Herrenschmidt bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); 1730*9de754d3SVíctor Colombo if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) { 173193130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 1732d8ce5fd6SBenjamin Herrenschmidt return; 1733d8ce5fd6SBenjamin Herrenschmidt } 1734d8ce5fd6SBenjamin Herrenschmidt } 1735d8ce5fd6SBenjamin Herrenschmidt 1736d8ce5fd6SBenjamin Herrenschmidt /* External interrupt can ignore MSR:EE under some circumstances */ 1737d1dbe37cSBenjamin Herrenschmidt if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { 1738d1dbe37cSBenjamin Herrenschmidt bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 17396eebe6dcSBenjamin Herrenschmidt bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); 17406eebe6dcSBenjamin Herrenschmidt /* HEIC blocks delivery to the hypervisor */ 1741*9de754d3SVíctor Colombo if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) && 1742d41ccf6eSVíctor Colombo !FIELD_EX64(env->msr, MSR, PR))) || 1743*9de754d3SVíctor Colombo (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) { 17447cebc5dbSNicholas Piggin if (books_vhyp_promotes_external_to_hvirt(cpu)) { 17457cebc5dbSNicholas Piggin powerpc_excp(cpu, POWERPC_EXCP_HVIRT); 17467cebc5dbSNicholas Piggin } else { 174793130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); 17487cebc5dbSNicholas Piggin } 1749d1dbe37cSBenjamin Herrenschmidt return; 1750d1dbe37cSBenjamin Herrenschmidt } 1751d1dbe37cSBenjamin Herrenschmidt } 1752acc861c2SVíctor Colombo if (FIELD_EX64(env->msr, MSR, CE)) { 1753c79c73f6SBlue Swirl /* External critical interrupt */ 1754c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { 175593130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_CRITICAL); 1756c79c73f6SBlue Swirl return; 1757c79c73f6SBlue Swirl } 1758c79c73f6SBlue Swirl } 17593621e2c9SBenjamin Herrenschmidt if (async_deliver != 0) { 1760c79c73f6SBlue Swirl /* Watchdog timer on embedded PowerPC */ 1761c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { 1762c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); 176393130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_WDT); 1764c79c73f6SBlue Swirl return; 1765c79c73f6SBlue Swirl } 1766c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { 1767c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); 176893130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_DOORCI); 1769c79c73f6SBlue Swirl return; 1770c79c73f6SBlue Swirl } 1771c79c73f6SBlue Swirl /* Fixed interval timer on embedded PowerPC */ 1772c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { 1773c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); 177493130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_FIT); 1775c79c73f6SBlue Swirl return; 1776c79c73f6SBlue Swirl } 1777c79c73f6SBlue Swirl /* Programmable interval timer on embedded PowerPC */ 1778c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { 1779c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); 178093130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_PIT); 1781c79c73f6SBlue Swirl return; 1782c79c73f6SBlue Swirl } 1783c79c73f6SBlue Swirl /* Decrementer exception */ 1784c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { 1785e81a982aSAlexander Graf if (ppc_decr_clear_on_delivery(env)) { 1786c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); 1787e81a982aSAlexander Graf } 178893130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_DECR); 1789c79c73f6SBlue Swirl return; 1790c79c73f6SBlue Swirl } 1791c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { 1792c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 17935ba7ba1dSCédric Le Goater if (is_book3s_arch2x(env)) { 179493130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_SDOOR); 17955ba7ba1dSCédric Le Goater } else { 179693130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_DOORI); 17975ba7ba1dSCédric Le Goater } 1798c79c73f6SBlue Swirl return; 1799c79c73f6SBlue Swirl } 18007af1e7b0SCédric Le Goater if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) { 18017af1e7b0SCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 180293130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); 18037af1e7b0SCédric Le Goater return; 18047af1e7b0SCédric Le Goater } 1805c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { 1806c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); 180793130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_PERFM); 1808c79c73f6SBlue Swirl return; 1809c79c73f6SBlue Swirl } 1810c79c73f6SBlue Swirl /* Thermal interrupt */ 1811c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { 1812c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); 181393130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_THERM); 1814c79c73f6SBlue Swirl return; 1815c79c73f6SBlue Swirl } 1816cb76bbc4SDaniel Henrique Barboza /* EBB exception */ 1817cb76bbc4SDaniel Henrique Barboza if (env->pending_interrupts & (1 << PPC_INTERRUPT_EBB)) { 1818cb76bbc4SDaniel Henrique Barboza /* 1819cb76bbc4SDaniel Henrique Barboza * EBB exception must be taken in problem state and 1820cb76bbc4SDaniel Henrique Barboza * with BESCR_GE set. 1821cb76bbc4SDaniel Henrique Barboza */ 1822d41ccf6eSVíctor Colombo if (FIELD_EX64(env->msr, MSR, PR) && 1823d41ccf6eSVíctor Colombo (env->spr[SPR_BESCR] & BESCR_GE)) { 1824cb76bbc4SDaniel Henrique Barboza env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EBB); 1825cb76bbc4SDaniel Henrique Barboza 1826cb76bbc4SDaniel Henrique Barboza if (env->spr[SPR_BESCR] & BESCR_PMEO) { 1827cb76bbc4SDaniel Henrique Barboza powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB); 1828cb76bbc4SDaniel Henrique Barboza } else if (env->spr[SPR_BESCR] & BESCR_EEO) { 1829cb76bbc4SDaniel Henrique Barboza powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB); 1830cb76bbc4SDaniel Henrique Barboza } 1831cb76bbc4SDaniel Henrique Barboza 1832cb76bbc4SDaniel Henrique Barboza return; 1833cb76bbc4SDaniel Henrique Barboza } 1834cb76bbc4SDaniel Henrique Barboza } 1835c79c73f6SBlue Swirl } 1836f8154fd2SBenjamin Herrenschmidt 1837f8154fd2SBenjamin Herrenschmidt if (env->resume_as_sreset) { 1838f8154fd2SBenjamin Herrenschmidt /* 1839f8154fd2SBenjamin Herrenschmidt * This is a bug ! It means that has_work took us out of halt without 1840f8154fd2SBenjamin Herrenschmidt * anything to deliver while in a PM state that requires getting 1841f8154fd2SBenjamin Herrenschmidt * out via a 0x100 1842f8154fd2SBenjamin Herrenschmidt * 1843f8154fd2SBenjamin Herrenschmidt * This means we will incorrectly execute past the power management 1844f8154fd2SBenjamin Herrenschmidt * instruction instead of triggering a reset. 1845f8154fd2SBenjamin Herrenschmidt * 1846136fbf65Szhaolichang * It generally means a discrepancy between the wakeup conditions in the 1847f8154fd2SBenjamin Herrenschmidt * processor has_work implementation and the logic in this function. 1848f8154fd2SBenjamin Herrenschmidt */ 1849db70b311SRichard Henderson cpu_abort(env_cpu(env), 1850f8154fd2SBenjamin Herrenschmidt "Wakeup from PM state but interrupt Undelivered"); 1851f8154fd2SBenjamin Herrenschmidt } 1852c79c73f6SBlue Swirl } 185334316482SAlexey Kardashevskiy 1854b5b7f391SNicholas Piggin void ppc_cpu_do_system_reset(CPUState *cs) 185534316482SAlexey Kardashevskiy { 185634316482SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 185734316482SAlexey Kardashevskiy 185893130c84SFabiano Rosas powerpc_excp(cpu, POWERPC_EXCP_RESET); 185934316482SAlexey Kardashevskiy } 1860ad77c6caSNicholas Piggin 1861ad77c6caSNicholas Piggin void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) 1862ad77c6caSNicholas Piggin { 1863ad77c6caSNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 1864ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 1865ad77c6caSNicholas Piggin target_ulong msr = 0; 1866ad77c6caSNicholas Piggin 1867ad77c6caSNicholas Piggin /* 1868ad77c6caSNicholas Piggin * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already 1869ad77c6caSNicholas Piggin * been set by KVM. 1870ad77c6caSNicholas Piggin */ 1871ad77c6caSNicholas Piggin msr = (1ULL << MSR_ME); 1872ad77c6caSNicholas Piggin msr |= env->msr & (1ULL << MSR_SF); 1873516fc103SFabiano Rosas if (ppc_interrupts_little_endian(cpu, false)) { 1874ad77c6caSNicholas Piggin msr |= (1ULL << MSR_LE); 1875ad77c6caSNicholas Piggin } 1876ad77c6caSNicholas Piggin 18777cebc5dbSNicholas Piggin /* Anything for nested required here? MSR[HV] bit? */ 18787cebc5dbSNicholas Piggin 1879ad77c6caSNicholas Piggin powerpc_set_excp_state(cpu, vector, msr); 1880ad77c6caSNicholas Piggin } 1881c79c73f6SBlue Swirl 1882458dd766SRichard Henderson bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 1883458dd766SRichard Henderson { 1884458dd766SRichard Henderson PowerPCCPU *cpu = POWERPC_CPU(cs); 1885458dd766SRichard Henderson CPUPPCState *env = &cpu->env; 1886458dd766SRichard Henderson 1887458dd766SRichard Henderson if (interrupt_request & CPU_INTERRUPT_HARD) { 1888458dd766SRichard Henderson ppc_hw_interrupt(env); 1889458dd766SRichard Henderson if (env->pending_interrupts == 0) { 1890458dd766SRichard Henderson cs->interrupt_request &= ~CPU_INTERRUPT_HARD; 1891458dd766SRichard Henderson } 1892458dd766SRichard Henderson return true; 1893458dd766SRichard Henderson } 1894458dd766SRichard Henderson return false; 1895458dd766SRichard Henderson } 1896458dd766SRichard Henderson 1897f725245cSPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */ 1898f725245cSPhilippe Mathieu-Daudé 1899ad71ed68SBlue Swirl /*****************************************************************************/ 1900ad71ed68SBlue Swirl /* Exceptions processing helpers */ 1901ad71ed68SBlue Swirl 1902db789c6cSBenjamin Herrenschmidt void raise_exception_err_ra(CPUPPCState *env, uint32_t exception, 1903db789c6cSBenjamin Herrenschmidt uint32_t error_code, uintptr_t raddr) 1904ad71ed68SBlue Swirl { 1905db70b311SRichard Henderson CPUState *cs = env_cpu(env); 190627103424SAndreas Färber 190727103424SAndreas Färber cs->exception_index = exception; 1908ad71ed68SBlue Swirl env->error_code = error_code; 1909db789c6cSBenjamin Herrenschmidt cpu_loop_exit_restore(cs, raddr); 1910db789c6cSBenjamin Herrenschmidt } 1911db789c6cSBenjamin Herrenschmidt 1912db789c6cSBenjamin Herrenschmidt void raise_exception_err(CPUPPCState *env, uint32_t exception, 1913db789c6cSBenjamin Herrenschmidt uint32_t error_code) 1914db789c6cSBenjamin Herrenschmidt { 1915db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, error_code, 0); 1916db789c6cSBenjamin Herrenschmidt } 1917db789c6cSBenjamin Herrenschmidt 1918db789c6cSBenjamin Herrenschmidt void raise_exception(CPUPPCState *env, uint32_t exception) 1919db789c6cSBenjamin Herrenschmidt { 1920db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, 0); 1921db789c6cSBenjamin Herrenschmidt } 1922db789c6cSBenjamin Herrenschmidt 1923db789c6cSBenjamin Herrenschmidt void raise_exception_ra(CPUPPCState *env, uint32_t exception, 1924db789c6cSBenjamin Herrenschmidt uintptr_t raddr) 1925db789c6cSBenjamin Herrenschmidt { 1926db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, raddr); 1927db789c6cSBenjamin Herrenschmidt } 1928db789c6cSBenjamin Herrenschmidt 19292b44e219SBruno Larsen (billionai) #ifdef CONFIG_TCG 1930db789c6cSBenjamin Herrenschmidt void helper_raise_exception_err(CPUPPCState *env, uint32_t exception, 1931db789c6cSBenjamin Herrenschmidt uint32_t error_code) 1932db789c6cSBenjamin Herrenschmidt { 1933db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, error_code, 0); 1934ad71ed68SBlue Swirl } 1935ad71ed68SBlue Swirl 1936e5f17ac6SBlue Swirl void helper_raise_exception(CPUPPCState *env, uint32_t exception) 1937ad71ed68SBlue Swirl { 1938db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, 0); 1939ad71ed68SBlue Swirl } 19402b44e219SBruno Larsen (billionai) #endif 1941ad71ed68SBlue Swirl 1942ad71ed68SBlue Swirl #if !defined(CONFIG_USER_ONLY) 19432b44e219SBruno Larsen (billionai) #ifdef CONFIG_TCG 1944e5f17ac6SBlue Swirl void helper_store_msr(CPUPPCState *env, target_ulong val) 1945ad71ed68SBlue Swirl { 1946db789c6cSBenjamin Herrenschmidt uint32_t excp = hreg_store_msr(env, val, 0); 1947259186a7SAndreas Färber 1948db789c6cSBenjamin Herrenschmidt if (excp != 0) { 1949db70b311SRichard Henderson CPUState *cs = env_cpu(env); 1950044897efSRichard Purdie cpu_interrupt_exittb(cs); 1951db789c6cSBenjamin Herrenschmidt raise_exception(env, excp); 1952ad71ed68SBlue Swirl } 1953ad71ed68SBlue Swirl } 1954ad71ed68SBlue Swirl 19557778a575SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 1956f43520e5SRichard Henderson void helper_scv(CPUPPCState *env, uint32_t lev) 1957f43520e5SRichard Henderson { 1958f43520e5SRichard Henderson if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) { 1959f43520e5SRichard Henderson raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev); 1960f43520e5SRichard Henderson } else { 1961f43520e5SRichard Henderson raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV); 1962f43520e5SRichard Henderson } 1963f43520e5SRichard Henderson } 1964f43520e5SRichard Henderson 19657778a575SBenjamin Herrenschmidt void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) 19667778a575SBenjamin Herrenschmidt { 19677778a575SBenjamin Herrenschmidt CPUState *cs; 19687778a575SBenjamin Herrenschmidt 1969db70b311SRichard Henderson cs = env_cpu(env); 19707778a575SBenjamin Herrenschmidt cs->halted = 1; 19717778a575SBenjamin Herrenschmidt 19723621e2c9SBenjamin Herrenschmidt /* Condition for waking up at 0x100 */ 19731e7fd61dSBenjamin Herrenschmidt env->resume_as_sreset = (insn != PPC_PM_STOP) || 197421c0d66aSBenjamin Herrenschmidt (env->spr[SPR_PSSCR] & PSSCR_EC); 19757778a575SBenjamin Herrenschmidt } 19767778a575SBenjamin Herrenschmidt #endif /* defined(TARGET_PPC64) */ 19777778a575SBenjamin Herrenschmidt 197862e79ef9SCédric Le Goater static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) 1979ad71ed68SBlue Swirl { 1980db70b311SRichard Henderson CPUState *cs = env_cpu(env); 1981259186a7SAndreas Färber 1982a2e71b28SBenjamin Herrenschmidt /* MSR:POW cannot be set by any form of rfi */ 1983a2e71b28SBenjamin Herrenschmidt msr &= ~(1ULL << MSR_POW); 1984a2e71b28SBenjamin Herrenschmidt 19855aad0457SChristophe Leroy /* MSR:TGPR cannot be set by any form of rfi */ 19865aad0457SChristophe Leroy if (env->flags & POWERPC_FLAG_TGPR) 19875aad0457SChristophe Leroy msr &= ~(1ULL << MSR_TGPR); 19885aad0457SChristophe Leroy 1989ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 1990a2e71b28SBenjamin Herrenschmidt /* Switching to 32-bit ? Crop the nip */ 1991a2e71b28SBenjamin Herrenschmidt if (!msr_is_64bit(env, msr)) { 1992ad71ed68SBlue Swirl nip = (uint32_t)nip; 1993ad71ed68SBlue Swirl } 1994ad71ed68SBlue Swirl #else 1995ad71ed68SBlue Swirl nip = (uint32_t)nip; 1996ad71ed68SBlue Swirl #endif 1997ad71ed68SBlue Swirl /* XXX: beware: this is false if VLE is supported */ 1998ad71ed68SBlue Swirl env->nip = nip & ~((target_ulong)0x00000003); 1999ad71ed68SBlue Swirl hreg_store_msr(env, msr, 1); 20002eb1ef73SCédric Le Goater trace_ppc_excp_rfi(env->nip, env->msr); 200147733729SDavid Gibson /* 200247733729SDavid Gibson * No need to raise an exception here, as rfi is always the last 200347733729SDavid Gibson * insn of a TB 2004ad71ed68SBlue Swirl */ 2005044897efSRichard Purdie cpu_interrupt_exittb(cs); 2006a8b73734SNikunj A Dadhania /* Reset the reservation */ 2007a8b73734SNikunj A Dadhania env->reserve_addr = -1; 2008a8b73734SNikunj A Dadhania 2009cd0c6f47SBenjamin Herrenschmidt /* Context synchronizing: check if TCG TLB needs flush */ 2010e3cffe6fSNikunj A Dadhania check_tlb_flush(env, false); 2011ad71ed68SBlue Swirl } 2012ad71ed68SBlue Swirl 2013e5f17ac6SBlue Swirl void helper_rfi(CPUPPCState *env) 2014ad71ed68SBlue Swirl { 2015a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); 2016a1bb7384SScott Wood } 2017ad71ed68SBlue Swirl 2018a2e71b28SBenjamin Herrenschmidt #define MSR_BOOK3S_MASK 2019ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 2020e5f17ac6SBlue Swirl void helper_rfid(CPUPPCState *env) 2021ad71ed68SBlue Swirl { 202247733729SDavid Gibson /* 2023136fbf65Szhaolichang * The architecture defines a number of rules for which bits can 202447733729SDavid Gibson * change but in practice, we handle this in hreg_store_msr() 2025a2e71b28SBenjamin Herrenschmidt * which will be called by do_rfi(), so there is no need to filter 2026a2e71b28SBenjamin Herrenschmidt * here 2027a2e71b28SBenjamin Herrenschmidt */ 2028a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); 2029ad71ed68SBlue Swirl } 2030ad71ed68SBlue Swirl 20313c89b8d6SNicholas Piggin void helper_rfscv(CPUPPCState *env) 20323c89b8d6SNicholas Piggin { 20333c89b8d6SNicholas Piggin do_rfi(env, env->lr, env->ctr); 20343c89b8d6SNicholas Piggin } 20353c89b8d6SNicholas Piggin 2036e5f17ac6SBlue Swirl void helper_hrfid(CPUPPCState *env) 2037ad71ed68SBlue Swirl { 2038a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); 2039ad71ed68SBlue Swirl } 2040ad71ed68SBlue Swirl #endif 2041ad71ed68SBlue Swirl 20421f26c751SDaniel Henrique Barboza #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) 20431f26c751SDaniel Henrique Barboza void helper_rfebb(CPUPPCState *env, target_ulong s) 20441f26c751SDaniel Henrique Barboza { 20451f26c751SDaniel Henrique Barboza target_ulong msr = env->msr; 20461f26c751SDaniel Henrique Barboza 20471f26c751SDaniel Henrique Barboza /* 20481f26c751SDaniel Henrique Barboza * Handling of BESCR bits 32:33 according to PowerISA v3.1: 20491f26c751SDaniel Henrique Barboza * 20501f26c751SDaniel Henrique Barboza * "If BESCR 32:33 != 0b00 the instruction is treated as if 20511f26c751SDaniel Henrique Barboza * the instruction form were invalid." 20521f26c751SDaniel Henrique Barboza */ 20531f26c751SDaniel Henrique Barboza if (env->spr[SPR_BESCR] & BESCR_INVALID) { 20541f26c751SDaniel Henrique Barboza raise_exception_err(env, POWERPC_EXCP_PROGRAM, 20551f26c751SDaniel Henrique Barboza POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL); 20561f26c751SDaniel Henrique Barboza } 20571f26c751SDaniel Henrique Barboza 20581f26c751SDaniel Henrique Barboza env->nip = env->spr[SPR_EBBRR]; 20591f26c751SDaniel Henrique Barboza 20601f26c751SDaniel Henrique Barboza /* Switching to 32-bit ? Crop the nip */ 20611f26c751SDaniel Henrique Barboza if (!msr_is_64bit(env, msr)) { 20621f26c751SDaniel Henrique Barboza env->nip = (uint32_t)env->spr[SPR_EBBRR]; 20631f26c751SDaniel Henrique Barboza } 20641f26c751SDaniel Henrique Barboza 20651f26c751SDaniel Henrique Barboza if (s) { 20661f26c751SDaniel Henrique Barboza env->spr[SPR_BESCR] |= BESCR_GE; 20671f26c751SDaniel Henrique Barboza } else { 20681f26c751SDaniel Henrique Barboza env->spr[SPR_BESCR] &= ~BESCR_GE; 20691f26c751SDaniel Henrique Barboza } 20701f26c751SDaniel Henrique Barboza } 2071d3412df2SDaniel Henrique Barboza 2072d3412df2SDaniel Henrique Barboza /* 2073d3412df2SDaniel Henrique Barboza * Triggers or queues an 'ebb_excp' EBB exception. All checks 2074d3412df2SDaniel Henrique Barboza * but FSCR, HFSCR and msr_pr must be done beforehand. 2075d3412df2SDaniel Henrique Barboza * 2076d3412df2SDaniel Henrique Barboza * PowerISA v3.1 isn't clear about whether an EBB should be 2077d3412df2SDaniel Henrique Barboza * postponed or cancelled if the EBB facility is unavailable. 2078d3412df2SDaniel Henrique Barboza * Our assumption here is that the EBB is cancelled if both 2079d3412df2SDaniel Henrique Barboza * FSCR and HFSCR EBB facilities aren't available. 2080d3412df2SDaniel Henrique Barboza */ 2081d3412df2SDaniel Henrique Barboza static void do_ebb(CPUPPCState *env, int ebb_excp) 2082d3412df2SDaniel Henrique Barboza { 2083d3412df2SDaniel Henrique Barboza PowerPCCPU *cpu = env_archcpu(env); 2084d3412df2SDaniel Henrique Barboza CPUState *cs = CPU(cpu); 2085d3412df2SDaniel Henrique Barboza 2086d3412df2SDaniel Henrique Barboza /* 2087d3412df2SDaniel Henrique Barboza * FSCR_EBB and FSCR_IC_EBB are the same bits used with 2088d3412df2SDaniel Henrique Barboza * HFSCR. 2089d3412df2SDaniel Henrique Barboza */ 2090d3412df2SDaniel Henrique Barboza helper_fscr_facility_check(env, FSCR_EBB, 0, FSCR_IC_EBB); 2091d3412df2SDaniel Henrique Barboza helper_hfscr_facility_check(env, FSCR_EBB, "EBB", FSCR_IC_EBB); 2092d3412df2SDaniel Henrique Barboza 2093d3412df2SDaniel Henrique Barboza if (ebb_excp == POWERPC_EXCP_PERFM_EBB) { 2094d3412df2SDaniel Henrique Barboza env->spr[SPR_BESCR] |= BESCR_PMEO; 2095d3412df2SDaniel Henrique Barboza } else if (ebb_excp == POWERPC_EXCP_EXTERNAL_EBB) { 2096d3412df2SDaniel Henrique Barboza env->spr[SPR_BESCR] |= BESCR_EEO; 2097d3412df2SDaniel Henrique Barboza } 2098d3412df2SDaniel Henrique Barboza 2099d41ccf6eSVíctor Colombo if (FIELD_EX64(env->msr, MSR, PR)) { 2100d3412df2SDaniel Henrique Barboza powerpc_excp(cpu, ebb_excp); 2101d3412df2SDaniel Henrique Barboza } else { 2102d3412df2SDaniel Henrique Barboza env->pending_interrupts |= 1 << PPC_INTERRUPT_EBB; 2103d3412df2SDaniel Henrique Barboza cpu_interrupt(cs, CPU_INTERRUPT_HARD); 2104d3412df2SDaniel Henrique Barboza } 2105d3412df2SDaniel Henrique Barboza } 2106d3412df2SDaniel Henrique Barboza 2107d3412df2SDaniel Henrique Barboza void raise_ebb_perfm_exception(CPUPPCState *env) 2108d3412df2SDaniel Henrique Barboza { 2109d3412df2SDaniel Henrique Barboza bool perfm_ebb_enabled = env->spr[SPR_POWER_MMCR0] & MMCR0_EBE && 2110d3412df2SDaniel Henrique Barboza env->spr[SPR_BESCR] & BESCR_PME && 2111d3412df2SDaniel Henrique Barboza env->spr[SPR_BESCR] & BESCR_GE; 2112d3412df2SDaniel Henrique Barboza 2113d3412df2SDaniel Henrique Barboza if (!perfm_ebb_enabled) { 2114d3412df2SDaniel Henrique Barboza return; 2115d3412df2SDaniel Henrique Barboza } 2116d3412df2SDaniel Henrique Barboza 2117d3412df2SDaniel Henrique Barboza do_ebb(env, POWERPC_EXCP_PERFM_EBB); 2118d3412df2SDaniel Henrique Barboza } 21191f26c751SDaniel Henrique Barboza #endif 21201f26c751SDaniel Henrique Barboza 2121ad71ed68SBlue Swirl /*****************************************************************************/ 2122ad71ed68SBlue Swirl /* Embedded PowerPC specific helpers */ 2123e5f17ac6SBlue Swirl void helper_40x_rfci(CPUPPCState *env) 2124ad71ed68SBlue Swirl { 2125a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]); 2126ad71ed68SBlue Swirl } 2127ad71ed68SBlue Swirl 2128e5f17ac6SBlue Swirl void helper_rfci(CPUPPCState *env) 2129ad71ed68SBlue Swirl { 2130a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]); 2131ad71ed68SBlue Swirl } 2132ad71ed68SBlue Swirl 2133e5f17ac6SBlue Swirl void helper_rfdi(CPUPPCState *env) 2134ad71ed68SBlue Swirl { 2135a1bb7384SScott Wood /* FIXME: choose CSRR1 or DSRR1 based on cpu type */ 2136a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]); 2137ad71ed68SBlue Swirl } 2138ad71ed68SBlue Swirl 2139e5f17ac6SBlue Swirl void helper_rfmci(CPUPPCState *env) 2140ad71ed68SBlue Swirl { 2141a1bb7384SScott Wood /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */ 2142a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]); 2143ad71ed68SBlue Swirl } 21442b44e219SBruno Larsen (billionai) #endif /* CONFIG_TCG */ 21452b44e219SBruno Larsen (billionai) #endif /* !defined(CONFIG_USER_ONLY) */ 2146ad71ed68SBlue Swirl 21472b44e219SBruno Larsen (billionai) #ifdef CONFIG_TCG 2148e5f17ac6SBlue Swirl void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 2149e5f17ac6SBlue Swirl uint32_t flags) 2150ad71ed68SBlue Swirl { 2151ad71ed68SBlue Swirl if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) || 2152ad71ed68SBlue Swirl ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) || 2153ad71ed68SBlue Swirl ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) || 2154ad71ed68SBlue Swirl ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) || 2155ad71ed68SBlue Swirl ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) { 215672073dccSBenjamin Herrenschmidt raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 215772073dccSBenjamin Herrenschmidt POWERPC_EXCP_TRAP, GETPC()); 2158ad71ed68SBlue Swirl } 2159ad71ed68SBlue Swirl } 2160ad71ed68SBlue Swirl 2161ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 2162e5f17ac6SBlue Swirl void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 2163e5f17ac6SBlue Swirl uint32_t flags) 2164ad71ed68SBlue Swirl { 2165ad71ed68SBlue Swirl if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) || 2166ad71ed68SBlue Swirl ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) || 2167ad71ed68SBlue Swirl ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) || 2168ad71ed68SBlue Swirl ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) || 2169ad71ed68SBlue Swirl ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) { 217072073dccSBenjamin Herrenschmidt raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 217172073dccSBenjamin Herrenschmidt POWERPC_EXCP_TRAP, GETPC()); 2172ad71ed68SBlue Swirl } 2173ad71ed68SBlue Swirl } 2174ad71ed68SBlue Swirl #endif 21752b44e219SBruno Larsen (billionai) #endif 2176ad71ed68SBlue Swirl 2177ad71ed68SBlue Swirl #if !defined(CONFIG_USER_ONLY) 2178ad71ed68SBlue Swirl 21792b44e219SBruno Larsen (billionai) #ifdef CONFIG_TCG 2180ad71ed68SBlue Swirl 2181ad71ed68SBlue Swirl /* Embedded.Processor Control */ 2182ad71ed68SBlue Swirl static int dbell2irq(target_ulong rb) 2183ad71ed68SBlue Swirl { 2184ad71ed68SBlue Swirl int msg = rb & DBELL_TYPE_MASK; 2185ad71ed68SBlue Swirl int irq = -1; 2186ad71ed68SBlue Swirl 2187ad71ed68SBlue Swirl switch (msg) { 2188ad71ed68SBlue Swirl case DBELL_TYPE_DBELL: 2189ad71ed68SBlue Swirl irq = PPC_INTERRUPT_DOORBELL; 2190ad71ed68SBlue Swirl break; 2191ad71ed68SBlue Swirl case DBELL_TYPE_DBELL_CRIT: 2192ad71ed68SBlue Swirl irq = PPC_INTERRUPT_CDOORBELL; 2193ad71ed68SBlue Swirl break; 2194ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL: 2195ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL_CRIT: 2196ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL_MC: 2197ad71ed68SBlue Swirl /* XXX implement */ 2198ad71ed68SBlue Swirl default: 2199ad71ed68SBlue Swirl break; 2200ad71ed68SBlue Swirl } 2201ad71ed68SBlue Swirl 2202ad71ed68SBlue Swirl return irq; 2203ad71ed68SBlue Swirl } 2204ad71ed68SBlue Swirl 2205e5f17ac6SBlue Swirl void helper_msgclr(CPUPPCState *env, target_ulong rb) 2206ad71ed68SBlue Swirl { 2207ad71ed68SBlue Swirl int irq = dbell2irq(rb); 2208ad71ed68SBlue Swirl 2209ad71ed68SBlue Swirl if (irq < 0) { 2210ad71ed68SBlue Swirl return; 2211ad71ed68SBlue Swirl } 2212ad71ed68SBlue Swirl 2213ad71ed68SBlue Swirl env->pending_interrupts &= ~(1 << irq); 2214ad71ed68SBlue Swirl } 2215ad71ed68SBlue Swirl 2216ad71ed68SBlue Swirl void helper_msgsnd(target_ulong rb) 2217ad71ed68SBlue Swirl { 2218ad71ed68SBlue Swirl int irq = dbell2irq(rb); 2219ad71ed68SBlue Swirl int pir = rb & DBELL_PIRTAG_MASK; 2220182735efSAndreas Färber CPUState *cs; 2221ad71ed68SBlue Swirl 2222ad71ed68SBlue Swirl if (irq < 0) { 2223ad71ed68SBlue Swirl return; 2224ad71ed68SBlue Swirl } 2225ad71ed68SBlue Swirl 2226f1c29ebcSThomas Huth qemu_mutex_lock_iothread(); 2227bdc44640SAndreas Färber CPU_FOREACH(cs) { 2228182735efSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 2229182735efSAndreas Färber CPUPPCState *cenv = &cpu->env; 2230182735efSAndreas Färber 2231ad71ed68SBlue Swirl if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { 2232ad71ed68SBlue Swirl cenv->pending_interrupts |= 1 << irq; 2233182735efSAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_HARD); 2234ad71ed68SBlue Swirl } 2235ad71ed68SBlue Swirl } 2236f1c29ebcSThomas Huth qemu_mutex_unlock_iothread(); 2237ad71ed68SBlue Swirl } 22387af1e7b0SCédric Le Goater 22397af1e7b0SCédric Le Goater /* Server Processor Control */ 22407af1e7b0SCédric Le Goater 22415ba7ba1dSCédric Le Goater static bool dbell_type_server(target_ulong rb) 22425ba7ba1dSCédric Le Goater { 224347733729SDavid Gibson /* 224447733729SDavid Gibson * A Directed Hypervisor Doorbell message is sent only if the 22457af1e7b0SCédric Le Goater * message type is 5. All other types are reserved and the 224647733729SDavid Gibson * instruction is a no-op 224747733729SDavid Gibson */ 22485ba7ba1dSCédric Le Goater return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER; 22497af1e7b0SCédric Le Goater } 22507af1e7b0SCédric Le Goater 22517af1e7b0SCédric Le Goater void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb) 22527af1e7b0SCédric Le Goater { 22535ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 22547af1e7b0SCédric Le Goater return; 22557af1e7b0SCédric Le Goater } 22567af1e7b0SCédric Le Goater 22575ba7ba1dSCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 22587af1e7b0SCédric Le Goater } 22597af1e7b0SCédric Le Goater 22605ba7ba1dSCédric Le Goater static void book3s_msgsnd_common(int pir, int irq) 22617af1e7b0SCédric Le Goater { 22627af1e7b0SCédric Le Goater CPUState *cs; 22637af1e7b0SCédric Le Goater 22647af1e7b0SCédric Le Goater qemu_mutex_lock_iothread(); 22657af1e7b0SCédric Le Goater CPU_FOREACH(cs) { 22667af1e7b0SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 22677af1e7b0SCédric Le Goater CPUPPCState *cenv = &cpu->env; 22687af1e7b0SCédric Le Goater 22697af1e7b0SCédric Le Goater /* TODO: broadcast message to all threads of the same processor */ 22707af1e7b0SCédric Le Goater if (cenv->spr_cb[SPR_PIR].default_value == pir) { 22717af1e7b0SCédric Le Goater cenv->pending_interrupts |= 1 << irq; 22727af1e7b0SCédric Le Goater cpu_interrupt(cs, CPU_INTERRUPT_HARD); 22737af1e7b0SCédric Le Goater } 22747af1e7b0SCédric Le Goater } 22757af1e7b0SCédric Le Goater qemu_mutex_unlock_iothread(); 22767af1e7b0SCédric Le Goater } 22775ba7ba1dSCédric Le Goater 22785ba7ba1dSCédric Le Goater void helper_book3s_msgsnd(target_ulong rb) 22795ba7ba1dSCédric Le Goater { 22805ba7ba1dSCédric Le Goater int pir = rb & DBELL_PROCIDTAG_MASK; 22815ba7ba1dSCédric Le Goater 22825ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 22835ba7ba1dSCédric Le Goater return; 22845ba7ba1dSCédric Le Goater } 22855ba7ba1dSCédric Le Goater 22865ba7ba1dSCédric Le Goater book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL); 22875ba7ba1dSCédric Le Goater } 22885ba7ba1dSCédric Le Goater 22895ba7ba1dSCédric Le Goater #if defined(TARGET_PPC64) 22905ba7ba1dSCédric Le Goater void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb) 22915ba7ba1dSCédric Le Goater { 2292493028d8SCédric Le Goater helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP); 2293493028d8SCédric Le Goater 22945ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 22955ba7ba1dSCédric Le Goater return; 22965ba7ba1dSCédric Le Goater } 22975ba7ba1dSCédric Le Goater 22985ba7ba1dSCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 22995ba7ba1dSCédric Le Goater } 23005ba7ba1dSCédric Le Goater 23015ba7ba1dSCédric Le Goater /* 23025ba7ba1dSCédric Le Goater * sends a message to other threads that are on the same 23035ba7ba1dSCédric Le Goater * multi-threaded processor 23045ba7ba1dSCédric Le Goater */ 23055ba7ba1dSCédric Le Goater void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) 23065ba7ba1dSCédric Le Goater { 23075ba7ba1dSCédric Le Goater int pir = env->spr_cb[SPR_PIR].default_value; 23085ba7ba1dSCédric Le Goater 2309493028d8SCédric Le Goater helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); 2310493028d8SCédric Le Goater 23115ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 23125ba7ba1dSCédric Le Goater return; 23135ba7ba1dSCédric Le Goater } 23145ba7ba1dSCédric Le Goater 23155ba7ba1dSCédric Le Goater /* TODO: TCG supports only one thread */ 23165ba7ba1dSCédric Le Goater 23175ba7ba1dSCédric Le Goater book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL); 23185ba7ba1dSCédric Le Goater } 2319996473e4SRichard Henderson #endif /* TARGET_PPC64 */ 23200f3110faSRichard Henderson 23210f3110faSRichard Henderson void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, 23220f3110faSRichard Henderson MMUAccessType access_type, 23230f3110faSRichard Henderson int mmu_idx, uintptr_t retaddr) 23240f3110faSRichard Henderson { 23250f3110faSRichard Henderson CPUPPCState *env = cs->env_ptr; 232629c4a336SFabiano Rosas uint32_t insn; 232729c4a336SFabiano Rosas 232829c4a336SFabiano Rosas /* Restore state and reload the insn we executed, for filling in DSISR. */ 232929c4a336SFabiano Rosas cpu_restore_state(cs, retaddr, true); 233029c4a336SFabiano Rosas insn = cpu_ldl_code(env, env->nip); 23310f3110faSRichard Henderson 2332a7e3af13SRichard Henderson switch (env->mmu_model) { 2333a7e3af13SRichard Henderson case POWERPC_MMU_SOFT_4xx: 2334a7e3af13SRichard Henderson env->spr[SPR_40x_DEAR] = vaddr; 2335a7e3af13SRichard Henderson break; 2336a7e3af13SRichard Henderson case POWERPC_MMU_BOOKE: 2337a7e3af13SRichard Henderson case POWERPC_MMU_BOOKE206: 2338a7e3af13SRichard Henderson env->spr[SPR_BOOKE_DEAR] = vaddr; 2339a7e3af13SRichard Henderson break; 2340a7e3af13SRichard Henderson default: 2341a7e3af13SRichard Henderson env->spr[SPR_DAR] = vaddr; 2342a7e3af13SRichard Henderson break; 2343a7e3af13SRichard Henderson } 2344a7e3af13SRichard Henderson 23450f3110faSRichard Henderson cs->exception_index = POWERPC_EXCP_ALIGN; 234629c4a336SFabiano Rosas env->error_code = insn & 0x03FF0000; 234729c4a336SFabiano Rosas cpu_loop_exit(cs); 23480f3110faSRichard Henderson } 2349996473e4SRichard Henderson #endif /* CONFIG_TCG */ 2350996473e4SRichard Henderson #endif /* !CONFIG_USER_ONLY */ 2351