xref: /qemu/target/ppc/excp_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
1 /*
2  *  PowerPC exception emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "qemu/osdep.h"
20 #include "qemu/main-loop.h"
21 #include "qemu/log.h"
22 #include "system/memory.h"
23 #include "system/tcg.h"
24 #include "system/system.h"
25 #include "system/runstate.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "helper_regs.h"
29 #include "hw/ppc/ppc.h"
30 
31 #include "trace.h"
32 
33 /*****************************************************************************/
34 /* Exception processing */
35 #ifndef CONFIG_USER_ONLY
36 
powerpc_excp_name(int excp)37 static const char *powerpc_excp_name(int excp)
38 {
39     switch (excp) {
40     case POWERPC_EXCP_CRITICAL: return "CRITICAL";
41     case POWERPC_EXCP_MCHECK:   return "MCHECK";
42     case POWERPC_EXCP_DSI:      return "DSI";
43     case POWERPC_EXCP_ISI:      return "ISI";
44     case POWERPC_EXCP_EXTERNAL: return "EXTERNAL";
45     case POWERPC_EXCP_ALIGN:    return "ALIGN";
46     case POWERPC_EXCP_PROGRAM:  return "PROGRAM";
47     case POWERPC_EXCP_FPU:      return "FPU";
48     case POWERPC_EXCP_SYSCALL:  return "SYSCALL";
49     case POWERPC_EXCP_APU:      return "APU";
50     case POWERPC_EXCP_DECR:     return "DECR";
51     case POWERPC_EXCP_FIT:      return "FIT";
52     case POWERPC_EXCP_WDT:      return "WDT";
53     case POWERPC_EXCP_DTLB:     return "DTLB";
54     case POWERPC_EXCP_ITLB:     return "ITLB";
55     case POWERPC_EXCP_DEBUG:    return "DEBUG";
56     case POWERPC_EXCP_SPEU:     return "SPEU";
57     case POWERPC_EXCP_EFPDI:    return "EFPDI";
58     case POWERPC_EXCP_EFPRI:    return "EFPRI";
59     case POWERPC_EXCP_EPERFM:   return "EPERFM";
60     case POWERPC_EXCP_DOORI:    return "DOORI";
61     case POWERPC_EXCP_DOORCI:   return "DOORCI";
62     case POWERPC_EXCP_GDOORI:   return "GDOORI";
63     case POWERPC_EXCP_GDOORCI:  return "GDOORCI";
64     case POWERPC_EXCP_HYPPRIV:  return "HYPPRIV";
65     case POWERPC_EXCP_RESET:    return "RESET";
66     case POWERPC_EXCP_DSEG:     return "DSEG";
67     case POWERPC_EXCP_ISEG:     return "ISEG";
68     case POWERPC_EXCP_HDECR:    return "HDECR";
69     case POWERPC_EXCP_TRACE:    return "TRACE";
70     case POWERPC_EXCP_HDSI:     return "HDSI";
71     case POWERPC_EXCP_HISI:     return "HISI";
72     case POWERPC_EXCP_HDSEG:    return "HDSEG";
73     case POWERPC_EXCP_HISEG:    return "HISEG";
74     case POWERPC_EXCP_VPU:      return "VPU";
75     case POWERPC_EXCP_PIT:      return "PIT";
76     case POWERPC_EXCP_EMUL:     return "EMUL";
77     case POWERPC_EXCP_IFTLB:    return "IFTLB";
78     case POWERPC_EXCP_DLTLB:    return "DLTLB";
79     case POWERPC_EXCP_DSTLB:    return "DSTLB";
80     case POWERPC_EXCP_FPA:      return "FPA";
81     case POWERPC_EXCP_DABR:     return "DABR";
82     case POWERPC_EXCP_IABR:     return "IABR";
83     case POWERPC_EXCP_SMI:      return "SMI";
84     case POWERPC_EXCP_PERFM:    return "PERFM";
85     case POWERPC_EXCP_THERM:    return "THERM";
86     case POWERPC_EXCP_VPUA:     return "VPUA";
87     case POWERPC_EXCP_SOFTP:    return "SOFTP";
88     case POWERPC_EXCP_MAINT:    return "MAINT";
89     case POWERPC_EXCP_MEXTBR:   return "MEXTBR";
90     case POWERPC_EXCP_NMEXTBR:  return "NMEXTBR";
91     case POWERPC_EXCP_ITLBE:    return "ITLBE";
92     case POWERPC_EXCP_DTLBE:    return "DTLBE";
93     case POWERPC_EXCP_VSXU:     return "VSXU";
94     case POWERPC_EXCP_FU:       return "FU";
95     case POWERPC_EXCP_HV_EMU:   return "HV_EMU";
96     case POWERPC_EXCP_HV_MAINT: return "HV_MAINT";
97     case POWERPC_EXCP_HV_FU:    return "HV_FU";
98     case POWERPC_EXCP_SDOOR:    return "SDOOR";
99     case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
100     case POWERPC_EXCP_HVIRT:    return "HVIRT";
101     case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
102     default:
103         g_assert_not_reached();
104     }
105 }
106 
dump_syscall(CPUPPCState * env)107 static void dump_syscall(CPUPPCState *env)
108 {
109     qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
110                   " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
111                   " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
112                   " nip=" TARGET_FMT_lx "\n",
113                   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
114                   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
115                   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
116                   ppc_dump_gpr(env, 8), env->nip);
117 }
118 
dump_hcall(CPUPPCState * env)119 static void dump_hcall(CPUPPCState *env)
120 {
121     qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
122                   " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
123                   " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
124                   " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
125                   " nip=" TARGET_FMT_lx "\n",
126                   ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
127                   ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
128                   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
129                   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
130                   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
131                   env->nip);
132 }
133 
ppc_excp_debug_sw_tlb(CPUPPCState * env,int excp)134 static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
135 {
136     const char *es;
137     target_ulong *miss, *cmp;
138     int en;
139 
140     if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
141         return;
142     }
143 
144     if (excp == POWERPC_EXCP_IFTLB) {
145         es = "I";
146         en = 'I';
147         miss = &env->spr[SPR_IMISS];
148         cmp = &env->spr[SPR_ICMP];
149     } else {
150         if (excp == POWERPC_EXCP_DLTLB) {
151             es = "DL";
152         } else {
153             es = "DS";
154         }
155         en = 'D';
156         miss = &env->spr[SPR_DMISS];
157         cmp = &env->spr[SPR_DCMP];
158     }
159     qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
160              TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
161              TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
162              env->spr[SPR_HASH1], env->spr[SPR_HASH2],
163              env->error_code);
164 }
165 
166 #ifdef TARGET_PPC64
powerpc_reset_wakeup(CPUPPCState * env,int excp,target_ulong * msr)167 static int powerpc_reset_wakeup(CPUPPCState *env, int excp, target_ulong *msr)
168 {
169     /* We no longer are in a PM state */
170     env->resume_as_sreset = false;
171 
172     /* Pretend to be returning from doze always as we don't lose state */
173     *msr |= SRR1_WS_NOLOSS;
174 
175     /* Machine checks are sent normally */
176     if (excp == POWERPC_EXCP_MCHECK) {
177         return excp;
178     }
179     switch (excp) {
180     case POWERPC_EXCP_RESET:
181         *msr |= SRR1_WAKERESET;
182         break;
183     case POWERPC_EXCP_EXTERNAL:
184         *msr |= SRR1_WAKEEE;
185         break;
186     case POWERPC_EXCP_DECR:
187         *msr |= SRR1_WAKEDEC;
188         break;
189     case POWERPC_EXCP_SDOOR:
190         *msr |= SRR1_WAKEDBELL;
191         break;
192     case POWERPC_EXCP_SDOOR_HV:
193         *msr |= SRR1_WAKEHDBELL;
194         break;
195     case POWERPC_EXCP_HV_MAINT:
196         *msr |= SRR1_WAKEHMI;
197         break;
198     case POWERPC_EXCP_HVIRT:
199         *msr |= SRR1_WAKEHVI;
200         break;
201     default:
202         cpu_abort(env_cpu(env),
203                   "Unsupported exception %d in Power Save mode\n", excp);
204     }
205     return POWERPC_EXCP_RESET;
206 }
207 
208 /*
209  * AIL - Alternate Interrupt Location, a mode that allows interrupts to be
210  * taken with the MMU on, and which uses an alternate location (e.g., so the
211  * kernel/hv can map the vectors there with an effective address).
212  *
213  * An interrupt is considered to be taken "with AIL" or "AIL applies" if they
214  * are delivered in this way. AIL requires the LPCR to be set to enable this
215  * mode, and then a number of conditions have to be true for AIL to apply.
216  *
217  * First of all, SRESET, MCE, and HMI are always delivered without AIL, because
218  * they specifically want to be in real mode (e.g., the MCE might be signaling
219  * a SLB multi-hit which requires SLB flush before the MMU can be enabled).
220  *
221  * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV],
222  * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current
223  * radix mode (LPCR[HR]).
224  *
225  * POWER8, POWER9 with LPCR[HR]=0
226  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
227  * +-----------+-------------+---------+-------------+-----+
228  * | a         | 00/01/10    | x       | x           | 0   |
229  * | a         | 11          | 0       | 1           | 0   |
230  * | a         | 11          | 1       | 1           | a   |
231  * | a         | 11          | 0       | 0           | a   |
232  * +-------------------------------------------------------+
233  *
234  * POWER9 with LPCR[HR]=1
235  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
236  * +-----------+-------------+---------+-------------+-----+
237  * | a         | 00/01/10    | x       | x           | 0   |
238  * | a         | 11          | x       | x           | a   |
239  * +-------------------------------------------------------+
240  *
241  * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to
242  * the hypervisor in AIL mode if the guest is radix. This is good for
243  * performance but allows the guest to influence the AIL of hypervisor
244  * interrupts using its MSR, and also the hypervisor must disallow guest
245  * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to
246  * use AIL for its MSR[HV] 0->1 interrupts.
247  *
248  * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to
249  * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and
250  * MSR[HV] 1->1).
251  *
252  * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1.
253  *
254  * POWER10 behaviour is
255  * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
256  * +-----------+------------+-------------+---------+-------------+-----+
257  * | a         | h          | 00/01/10    | 0       | 0           | 0   |
258  * | a         | h          | 11          | 0       | 0           | a   |
259  * | a         | h          | x           | 0       | 1           | h   |
260  * | a         | h          | 00/01/10    | 1       | 1           | 0   |
261  * | a         | h          | 11          | 1       | 1           | h   |
262  * +--------------------------------------------------------------------+
263  */
ppc_excp_apply_ail(PowerPCCPU * cpu,int excp,target_ulong msr,target_ulong * new_msr,target_ulong * vector)264 static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
265                                target_ulong *new_msr, target_ulong *vector)
266 {
267     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
268     CPUPPCState *env = &cpu->env;
269     bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
270     bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
271     int ail = 0;
272 
273     if (excp == POWERPC_EXCP_MCHECK ||
274         excp == POWERPC_EXCP_RESET ||
275         excp == POWERPC_EXCP_HV_MAINT) {
276         /* SRESET, MCE, HMI never apply AIL */
277         return;
278     }
279 
280     if (!(pcc->lpcr_mask & LPCR_AIL)) {
281         /* This CPU does not have AIL */
282         return;
283     }
284 
285     /* P8 & P9 */
286     if (!(pcc->lpcr_mask & LPCR_HAIL)) {
287         if (!mmu_all_on) {
288             /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
289             return;
290         }
291         if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
292             /*
293              * AIL does not work if there is a MSR[HV] 0->1 transition and the
294              * partition is in HPT mode. For radix guests, such interrupts are
295              * allowed to be delivered to the hypervisor in ail mode.
296              */
297             return;
298         }
299 
300         ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
301         if (ail == 0 || ail == 1) {
302             /* AIL=1 is reserved, treat it like AIL=0 */
303             return;
304         }
305 
306     /* P10 and up */
307     } else {
308         if (!mmu_all_on && !hv_escalation) {
309             /*
310              * AIL works for HV interrupts even with guest MSR[IR/DR] disabled.
311              * Guest->guest and HV->HV interrupts do require MMU on.
312              */
313             return;
314         }
315 
316         if (*new_msr & MSR_HVB) {
317             if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
318                 /* HV interrupts depend on LPCR[HAIL] */
319                 return;
320             }
321             ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */
322         } else {
323             ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
324         }
325         if (ail == 0 || ail == 1 || ail == 2) {
326             /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
327             return;
328         }
329     }
330 
331     /*
332      * AIL applies, so the new MSR gets IR and DR set, and an offset applied
333      * to the new IP.
334      */
335     *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
336 
337     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
338         if (ail == 2) {
339             *vector |= 0x0000000000018000ull;
340         } else if (ail == 3) {
341             *vector |= 0xc000000000004000ull;
342         }
343     } else {
344         /*
345          * scv AIL is a little different. AIL=2 does not change the address,
346          * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
347          */
348         if (ail == 3) {
349             *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */
350             *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
351         }
352     }
353 }
354 #endif /* TARGET_PPC64 */
355 
powerpc_reset_excp_state(PowerPCCPU * cpu)356 static void powerpc_reset_excp_state(PowerPCCPU *cpu)
357 {
358     CPUState *cs = CPU(cpu);
359     CPUPPCState *env = &cpu->env;
360 
361     /* Reset exception state */
362     cs->exception_index = POWERPC_EXCP_NONE;
363     env->error_code = 0;
364 }
365 
powerpc_set_excp_state(PowerPCCPU * cpu,target_ulong vector,target_ulong msr)366 static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
367                                    target_ulong msr)
368 {
369     CPUPPCState *env = &cpu->env;
370 
371     assert((msr & env->msr_mask) == msr);
372 
373     /*
374      * We don't use hreg_store_msr here as already have treated any
375      * special case that could occur. Just store MSR and update hflags
376      *
377      * Note: We *MUST* not use hreg_store_msr() as-is anyway because it will
378      * prevent setting of the HV bit which some exceptions might need to do.
379      */
380     env->nip = vector;
381     env->msr = msr;
382     hreg_compute_hflags(env);
383     ppc_maybe_interrupt(env);
384 
385     powerpc_reset_excp_state(cpu);
386 
387     /*
388      * Any interrupt is context synchronizing, check if TCG TLB needs
389      * a delayed flush on ppc64
390      */
391     check_tlb_flush(env, false);
392 
393     /* Reset the reservation */
394     env->reserve_addr = -1;
395 }
396 
powerpc_mcheck_checkstop(CPUPPCState * env)397 static void powerpc_mcheck_checkstop(CPUPPCState *env)
398 {
399     /* KVM guests always have MSR[ME] enabled */
400     if (FIELD_EX64(env->msr, MSR, ME)) {
401         return;
402     }
403     assert(tcg_enabled());
404     powerpc_checkstop(env, "machine check with MSR[ME]=0");
405 }
406 
powerpc_excp_40x(PowerPCCPU * cpu,int excp)407 static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
408 {
409     CPUPPCState *env = &cpu->env;
410     target_ulong msr, new_msr, vector;
411     int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
412 
413     /* new srr1 value excluding must-be-zero bits */
414     msr = env->msr & ~0x783f0000ULL;
415 
416     /* new interrupt handler msr preserves ME unless explicitly overridden */
417     new_msr = env->msr & (((target_ulong)1 << MSR_ME));
418 
419     /* HV emu assistance interrupt only exists on server arch 2.05 or later */
420     if (excp == POWERPC_EXCP_HV_EMU) {
421         excp = POWERPC_EXCP_PROGRAM;
422     }
423 
424     vector = env->excp_vectors[excp];
425     if (vector == (target_ulong)-1ULL) {
426         cpu_abort(env_cpu(env),
427                   "Raised an exception without defined vector %d\n", excp);
428     }
429     vector |= env->excp_prefix;
430 
431     switch (excp) {
432     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
433         srr0 = SPR_40x_SRR2;
434         srr1 = SPR_40x_SRR3;
435         break;
436     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
437         powerpc_mcheck_checkstop(env);
438         /* machine check exceptions don't have ME set */
439         new_msr &= ~((target_ulong)1 << MSR_ME);
440         srr0 = SPR_40x_SRR2;
441         srr1 = SPR_40x_SRR3;
442         break;
443     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
444         trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
445         break;
446     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
447         trace_ppc_excp_isi(msr, env->nip);
448         break;
449     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
450         break;
451     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
452         break;
453     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
454         switch (env->error_code & ~0xF) {
455         case POWERPC_EXCP_FP:
456             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
457                 trace_ppc_excp_fp_ignore();
458                 powerpc_reset_excp_state(cpu);
459                 return;
460             }
461             env->spr[SPR_40x_ESR] = ESR_FP;
462             break;
463         case POWERPC_EXCP_INVAL:
464             trace_ppc_excp_inval(env->nip);
465             env->spr[SPR_40x_ESR] = ESR_PIL;
466             break;
467         case POWERPC_EXCP_PRIV:
468             env->spr[SPR_40x_ESR] = ESR_PPR;
469             break;
470         case POWERPC_EXCP_TRAP:
471             env->spr[SPR_40x_ESR] = ESR_PTR;
472             break;
473         default:
474             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
475                       env->error_code);
476             break;
477         }
478         break;
479     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
480         dump_syscall(env);
481 
482         /*
483          * We need to correct the NIP which in this case is supposed
484          * to point to the next instruction
485          */
486         env->nip += 4;
487         break;
488     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
489         trace_ppc_excp_print("FIT");
490         break;
491     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
492         trace_ppc_excp_print("WDT");
493         break;
494     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
495     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
496         break;
497     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
498         trace_ppc_excp_print("PIT");
499         break;
500     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
501         cpu_abort(env_cpu(env), "%s exception not implemented\n",
502                   powerpc_excp_name(excp));
503         break;
504     default:
505         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
506                   excp);
507         break;
508     }
509 
510     env->spr[srr0] = env->nip;
511     env->spr[srr1] = msr;
512     powerpc_set_excp_state(cpu, vector, new_msr);
513 }
514 
powerpc_excp_6xx(PowerPCCPU * cpu,int excp)515 static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
516 {
517     CPUPPCState *env = &cpu->env;
518     target_ulong msr, new_msr, vector;
519 
520     /* new srr1 value excluding must-be-zero bits */
521     msr = env->msr & ~0x783f0000ULL;
522 
523     /* new interrupt handler msr preserves ME unless explicitly overridden */
524     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
525 
526     /* HV emu assistance interrupt only exists on server arch 2.05 or later */
527     if (excp == POWERPC_EXCP_HV_EMU) {
528         excp = POWERPC_EXCP_PROGRAM;
529     }
530 
531     vector = env->excp_vectors[excp];
532     if (vector == (target_ulong)-1ULL) {
533         cpu_abort(env_cpu(env),
534                   "Raised an exception without defined vector %d\n", excp);
535     }
536     vector |= env->excp_prefix;
537 
538     switch (excp) {
539     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
540         break;
541     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
542         powerpc_mcheck_checkstop(env);
543         /* machine check exceptions don't have ME set */
544         new_msr &= ~((target_ulong)1 << MSR_ME);
545         break;
546     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
547         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
548         break;
549     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
550         trace_ppc_excp_isi(msr, env->nip);
551         msr |= env->error_code;
552         break;
553     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
554         break;
555     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
556         /* Get rS/rD and rA from faulting opcode */
557         /*
558          * Note: the opcode fields will not be set properly for a
559          * direct store load/store, but nobody cares as nobody
560          * actually uses direct store segments.
561          */
562         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
563         break;
564     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
565         switch (env->error_code & ~0xF) {
566         case POWERPC_EXCP_FP:
567             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
568                 trace_ppc_excp_fp_ignore();
569                 powerpc_reset_excp_state(cpu);
570                 return;
571             }
572             /*
573              * NIP always points to the faulting instruction for FP exceptions,
574              * so always use store_next and claim we are precise in the MSR.
575              */
576             msr |= 0x00100000;
577             break;
578         case POWERPC_EXCP_INVAL:
579             trace_ppc_excp_inval(env->nip);
580             msr |= 0x00080000;
581             break;
582         case POWERPC_EXCP_PRIV:
583             msr |= 0x00040000;
584             break;
585         case POWERPC_EXCP_TRAP:
586             msr |= 0x00020000;
587             break;
588         default:
589             /* Should never occur */
590             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
591                       env->error_code);
592             break;
593         }
594         break;
595     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
596         dump_syscall(env);
597 
598         /*
599          * We need to correct the NIP which in this case is supposed
600          * to point to the next instruction
601          */
602         env->nip += 4;
603         break;
604     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
605     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
606         break;
607     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
608     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
609         break;
610     case POWERPC_EXCP_RESET:     /* System reset exception                   */
611         if (FIELD_EX64(env->msr, MSR, POW)) {
612             cpu_abort(env_cpu(env),
613                       "Trying to deliver power-saving system reset exception "
614                       "%d with no HV support\n", excp);
615         }
616         break;
617     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
618         break;
619     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
620     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
621     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
622         /* Swap temporary saved registers with GPRs */
623         if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
624             new_msr |= (target_ulong)1 << MSR_TGPR;
625             hreg_swap_gpr_tgpr(env);
626         }
627 
628         ppc_excp_debug_sw_tlb(env, excp);
629 
630         msr |= env->crf[0] << 28;
631         msr |= env->error_code; /* key, D/I, S/L bits */
632         /* Set way using a LRU mechanism */
633         msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
634         break;
635     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
636     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
637     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
638     case POWERPC_EXCP_SMI:       /* System management interrupt              */
639     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
640     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
641         cpu_abort(env_cpu(env), "%s exception not implemented\n",
642                   powerpc_excp_name(excp));
643         break;
644     default:
645         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
646                   excp);
647         break;
648     }
649 
650     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
651         new_msr |= (target_ulong)1 << MSR_LE;
652     }
653     env->spr[SPR_SRR0] = env->nip;
654     env->spr[SPR_SRR1] = msr;
655     powerpc_set_excp_state(cpu, vector, new_msr);
656 }
657 
powerpc_excp_7xx(PowerPCCPU * cpu,int excp)658 static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
659 {
660     CPUPPCState *env = &cpu->env;
661     target_ulong msr, new_msr, vector;
662 
663     /* new srr1 value excluding must-be-zero bits */
664     msr = env->msr & ~0x783f0000ULL;
665 
666     /* new interrupt handler msr preserves ME unless explicitly overridden */
667     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
668 
669     /* HV emu assistance interrupt only exists on server arch 2.05 or later */
670     if (excp == POWERPC_EXCP_HV_EMU) {
671         excp = POWERPC_EXCP_PROGRAM;
672     }
673 
674     vector = env->excp_vectors[excp];
675     if (vector == (target_ulong)-1ULL) {
676         cpu_abort(env_cpu(env),
677                   "Raised an exception without defined vector %d\n", excp);
678     }
679     vector |= env->excp_prefix;
680 
681     switch (excp) {
682     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
683         powerpc_mcheck_checkstop(env);
684         /* machine check exceptions don't have ME set */
685         new_msr &= ~((target_ulong)1 << MSR_ME);
686         break;
687     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
688         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
689         break;
690     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
691         trace_ppc_excp_isi(msr, env->nip);
692         msr |= env->error_code;
693         break;
694     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
695         break;
696     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
697         /* Get rS/rD and rA from faulting opcode */
698         /*
699          * Note: the opcode fields will not be set properly for a
700          * direct store load/store, but nobody cares as nobody
701          * actually uses direct store segments.
702          */
703         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
704         break;
705     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
706         switch (env->error_code & ~0xF) {
707         case POWERPC_EXCP_FP:
708             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
709                 trace_ppc_excp_fp_ignore();
710                 powerpc_reset_excp_state(cpu);
711                 return;
712             }
713             /*
714              * NIP always points to the faulting instruction for FP exceptions,
715              * so always use store_next and claim we are precise in the MSR.
716              */
717             msr |= 0x00100000;
718             break;
719         case POWERPC_EXCP_INVAL:
720             trace_ppc_excp_inval(env->nip);
721             msr |= 0x00080000;
722             break;
723         case POWERPC_EXCP_PRIV:
724             msr |= 0x00040000;
725             break;
726         case POWERPC_EXCP_TRAP:
727             msr |= 0x00020000;
728             break;
729         default:
730             /* Should never occur */
731             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
732                       env->error_code);
733             break;
734         }
735         break;
736     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
737     {
738         int lev = env->error_code;
739 
740         if (lev == 1 && cpu->vhyp) {
741             dump_hcall(env);
742         } else {
743             dump_syscall(env);
744         }
745 
746         /*
747          * We need to correct the NIP which in this case is supposed
748          * to point to the next instruction
749          */
750         env->nip += 4;
751 
752         /*
753          * The Virtual Open Firmware (VOF) relies on the 'sc 1'
754          * instruction to communicate with QEMU. The pegasos2 machine
755          * uses VOF and the 7xx CPUs, so although the 7xx don't have
756          * HV mode, we need to keep hypercall support.
757          */
758         if (lev == 1 && cpu->vhyp) {
759             cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
760             powerpc_reset_excp_state(cpu);
761             return;
762         }
763 
764         break;
765     }
766     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
767     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
768         break;
769     case POWERPC_EXCP_RESET:     /* System reset exception                   */
770         if (FIELD_EX64(env->msr, MSR, POW)) {
771             cpu_abort(env_cpu(env),
772                       "Trying to deliver power-saving system reset exception "
773                       "%d with no HV support\n", excp);
774         }
775         break;
776     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
777         break;
778     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
779     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
780     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
781         ppc_excp_debug_sw_tlb(env, excp);
782         msr |= env->crf[0] << 28;
783         msr |= env->error_code; /* key, D/I, S/L bits */
784         /* Set way using a LRU mechanism */
785         msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
786         break;
787     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
788     case POWERPC_EXCP_SMI:       /* System management interrupt              */
789     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
790     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
791         cpu_abort(env_cpu(env), "%s exception not implemented\n",
792                   powerpc_excp_name(excp));
793         break;
794     default:
795         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
796                   excp);
797         break;
798     }
799 
800     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
801         new_msr |= (target_ulong)1 << MSR_LE;
802     }
803     env->spr[SPR_SRR0] = env->nip;
804     env->spr[SPR_SRR1] = msr;
805     powerpc_set_excp_state(cpu, vector, new_msr);
806 }
807 
powerpc_excp_74xx(PowerPCCPU * cpu,int excp)808 static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
809 {
810     CPUPPCState *env = &cpu->env;
811     target_ulong msr, new_msr, vector;
812 
813     /* new srr1 value excluding must-be-zero bits */
814     msr = env->msr & ~0x783f0000ULL;
815 
816     /* new interrupt handler msr preserves ME unless explicitly overridden */
817     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
818 
819     /* HV emu assistance interrupt only exists on server arch 2.05 or later */
820     if (excp == POWERPC_EXCP_HV_EMU) {
821         excp = POWERPC_EXCP_PROGRAM;
822     }
823 
824     vector = env->excp_vectors[excp];
825     if (vector == (target_ulong)-1ULL) {
826         cpu_abort(env_cpu(env),
827                   "Raised an exception without defined vector %d\n", excp);
828     }
829     vector |= env->excp_prefix;
830 
831     switch (excp) {
832     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
833         powerpc_mcheck_checkstop(env);
834         /* machine check exceptions don't have ME set */
835         new_msr &= ~((target_ulong)1 << MSR_ME);
836         break;
837     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
838         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
839         break;
840     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
841         trace_ppc_excp_isi(msr, env->nip);
842         msr |= env->error_code;
843         break;
844     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
845         break;
846     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
847         /* Get rS/rD and rA from faulting opcode */
848         /*
849          * Note: the opcode fields will not be set properly for a
850          * direct store load/store, but nobody cares as nobody
851          * actually uses direct store segments.
852          */
853         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
854         break;
855     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
856         switch (env->error_code & ~0xF) {
857         case POWERPC_EXCP_FP:
858             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
859                 trace_ppc_excp_fp_ignore();
860                 powerpc_reset_excp_state(cpu);
861                 return;
862             }
863             /*
864              * NIP always points to the faulting instruction for FP exceptions,
865              * so always use store_next and claim we are precise in the MSR.
866              */
867             msr |= 0x00100000;
868             break;
869         case POWERPC_EXCP_INVAL:
870             trace_ppc_excp_inval(env->nip);
871             msr |= 0x00080000;
872             break;
873         case POWERPC_EXCP_PRIV:
874             msr |= 0x00040000;
875             break;
876         case POWERPC_EXCP_TRAP:
877             msr |= 0x00020000;
878             break;
879         default:
880             /* Should never occur */
881             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
882                       env->error_code);
883             break;
884         }
885         break;
886     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
887     {
888         int lev = env->error_code;
889 
890         if (lev == 1 && cpu->vhyp) {
891             dump_hcall(env);
892         } else {
893             dump_syscall(env);
894         }
895 
896         /*
897          * We need to correct the NIP which in this case is supposed
898          * to point to the next instruction
899          */
900         env->nip += 4;
901 
902         /*
903          * The Virtual Open Firmware (VOF) relies on the 'sc 1'
904          * instruction to communicate with QEMU. The pegasos2 machine
905          * uses VOF and the 74xx CPUs, so although the 74xx don't have
906          * HV mode, we need to keep hypercall support.
907          */
908         if (lev == 1 && cpu->vhyp) {
909             cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
910             powerpc_reset_excp_state(cpu);
911             return;
912         }
913 
914         break;
915     }
916     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
917     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
918         break;
919     case POWERPC_EXCP_RESET:     /* System reset exception                   */
920         if (FIELD_EX64(env->msr, MSR, POW)) {
921             cpu_abort(env_cpu(env),
922                       "Trying to deliver power-saving system reset "
923                       "exception %d with no HV support\n", excp);
924         }
925         break;
926     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
927         break;
928     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
929         break;
930     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
931     case POWERPC_EXCP_SMI:       /* System management interrupt              */
932     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
933     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
934     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
935         cpu_abort(env_cpu(env), "%s exception not implemented\n",
936                   powerpc_excp_name(excp));
937         break;
938     default:
939         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
940                   excp);
941         break;
942     }
943 
944     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
945         new_msr |= (target_ulong)1 << MSR_LE;
946     }
947     env->spr[SPR_SRR0] = env->nip;
948     env->spr[SPR_SRR1] = msr;
949     powerpc_set_excp_state(cpu, vector, new_msr);
950 }
951 
powerpc_excp_booke(PowerPCCPU * cpu,int excp)952 static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
953 {
954     CPUPPCState *env = &cpu->env;
955     target_ulong msr, new_msr, vector;
956     int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
957 
958     /*
959      * Book E does not play games with certain bits of xSRR1 being MSR save
960      * bits and others being error status. xSRR1 is the old MSR, period.
961      */
962     msr = env->msr;
963 
964     /* new interrupt handler msr preserves ME unless explicitly overridden */
965     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
966 
967     /* HV emu assistance interrupt only exists on server arch 2.05 or later */
968     if (excp == POWERPC_EXCP_HV_EMU) {
969         excp = POWERPC_EXCP_PROGRAM;
970     }
971 
972 #ifdef TARGET_PPC64
973     /*
974      * SPEU and VPU share the same IVOR but they exist in different
975      * processors. SPEU is e500v1/2 only and VPU is e6500 only.
976      */
977     if (excp == POWERPC_EXCP_VPU) {
978         excp = POWERPC_EXCP_SPEU;
979     }
980 #endif
981 
982     vector = env->excp_vectors[excp];
983     if (vector == (target_ulong)-1ULL) {
984         cpu_abort(env_cpu(env),
985                   "Raised an exception without defined vector %d\n", excp);
986     }
987     vector |= env->excp_prefix;
988 
989     switch (excp) {
990     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
991         srr0 = SPR_BOOKE_CSRR0;
992         srr1 = SPR_BOOKE_CSRR1;
993         break;
994     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
995         powerpc_mcheck_checkstop(env);
996         /* machine check exceptions don't have ME set */
997         new_msr &= ~((target_ulong)1 << MSR_ME);
998 
999         /* FIXME: choose one or the other based on CPU type */
1000         srr0 = SPR_BOOKE_MCSRR0;
1001         srr1 = SPR_BOOKE_MCSRR1;
1002 
1003         env->spr[SPR_BOOKE_CSRR0] = env->nip;
1004         env->spr[SPR_BOOKE_CSRR1] = msr;
1005 
1006         break;
1007     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1008         trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
1009         break;
1010     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1011         trace_ppc_excp_isi(msr, env->nip);
1012         break;
1013     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
1014         if (env->mpic_proxy) {
1015             CPUState *cs = env_cpu(env);
1016             /* IACK the IRQ on delivery */
1017             env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1018         }
1019         break;
1020     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
1021         break;
1022     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1023         switch (env->error_code & ~0xF) {
1024         case POWERPC_EXCP_FP:
1025             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1026                 trace_ppc_excp_fp_ignore();
1027                 powerpc_reset_excp_state(cpu);
1028                 return;
1029             }
1030             /*
1031              * NIP always points to the faulting instruction for FP exceptions,
1032              * so always use store_next and claim we are precise in the MSR.
1033              */
1034             msr |= 0x00100000;
1035             env->spr[SPR_BOOKE_ESR] = ESR_FP;
1036             break;
1037         case POWERPC_EXCP_INVAL:
1038             trace_ppc_excp_inval(env->nip);
1039             msr |= 0x00080000;
1040             env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1041             break;
1042         case POWERPC_EXCP_PRIV:
1043             msr |= 0x00040000;
1044             env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1045             break;
1046         case POWERPC_EXCP_TRAP:
1047             msr |= 0x00020000;
1048             env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1049             break;
1050         default:
1051             /* Should never occur */
1052             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
1053                       env->error_code);
1054             break;
1055         }
1056         break;
1057     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1058         dump_syscall(env);
1059 
1060         /*
1061          * We need to correct the NIP which in this case is supposed
1062          * to point to the next instruction
1063          */
1064         env->nip += 4;
1065         break;
1066     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
1067     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
1068     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
1069         break;
1070     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
1071         /* FIT on 4xx */
1072         trace_ppc_excp_print("FIT");
1073         break;
1074     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
1075         trace_ppc_excp_print("WDT");
1076         srr0 = SPR_BOOKE_CSRR0;
1077         srr1 = SPR_BOOKE_CSRR1;
1078         break;
1079     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
1080     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
1081         break;
1082     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
1083         if (env->flags & POWERPC_FLAG_DE) {
1084             /* FIXME: choose one or the other based on CPU type */
1085             srr0 = SPR_BOOKE_DSRR0;
1086             srr1 = SPR_BOOKE_DSRR1;
1087 
1088             env->spr[SPR_BOOKE_CSRR0] = env->nip;
1089             env->spr[SPR_BOOKE_CSRR1] = msr;
1090 
1091             /* DBSR already modified by caller */
1092         } else {
1093             cpu_abort(env_cpu(env),
1094                       "Debug exception triggered on unsupported model\n");
1095         }
1096         break;
1097     case POWERPC_EXCP_SPEU:   /* SPE/embedded floating-point unavailable/VPU  */
1098         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1099         break;
1100     case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
1101         break;
1102     case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
1103         srr0 = SPR_BOOKE_CSRR0;
1104         srr1 = SPR_BOOKE_CSRR1;
1105         break;
1106     case POWERPC_EXCP_RESET:     /* System reset exception                   */
1107         if (FIELD_EX64(env->msr, MSR, POW)) {
1108             cpu_abort(env_cpu(env),
1109                       "Trying to deliver power-saving system reset "
1110                       "exception %d with no HV support\n", excp);
1111         }
1112         break;
1113     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
1114     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
1115         cpu_abort(env_cpu(env), "%s exception not implemented\n",
1116                   powerpc_excp_name(excp));
1117         break;
1118     default:
1119         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
1120                   excp);
1121         break;
1122     }
1123 
1124 #ifdef TARGET_PPC64
1125     if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1126         /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
1127         new_msr |= (target_ulong)1 << MSR_CM;
1128     } else {
1129         vector = (uint32_t)vector;
1130     }
1131 #endif
1132 
1133     env->spr[srr0] = env->nip;
1134     env->spr[srr1] = msr;
1135     powerpc_set_excp_state(cpu, vector, new_msr);
1136 }
1137 
1138 /*
1139  * When running a nested HV guest under vhyp, external interrupts are
1140  * delivered as HVIRT.
1141  */
books_vhyp_promotes_external_to_hvirt(PowerPCCPU * cpu)1142 static bool books_vhyp_promotes_external_to_hvirt(PowerPCCPU *cpu)
1143 {
1144     if (cpu->vhyp) {
1145         return vhyp_cpu_in_nested(cpu);
1146     }
1147     return false;
1148 }
1149 
1150 #ifdef TARGET_PPC64
1151 /*
1152  * When running under vhyp, hcalls are always intercepted and sent to the
1153  * vhc->hypercall handler.
1154  */
books_vhyp_handles_hcall(PowerPCCPU * cpu)1155 static bool books_vhyp_handles_hcall(PowerPCCPU *cpu)
1156 {
1157     if (cpu->vhyp) {
1158         return !vhyp_cpu_in_nested(cpu);
1159     }
1160     return false;
1161 }
1162 
1163 /*
1164  * When running a nested KVM HV guest under vhyp, HV exceptions are not
1165  * delivered to the guest (because there is no concept of HV support), but
1166  * rather they are sent to the vhyp to exit from the L2 back to the L1 and
1167  * return from the H_ENTER_NESTED hypercall.
1168  */
books_vhyp_handles_hv_excp(PowerPCCPU * cpu)1169 static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu)
1170 {
1171     if (cpu->vhyp) {
1172         return vhyp_cpu_in_nested(cpu);
1173     }
1174     return false;
1175 }
1176 
1177 #ifdef CONFIG_TCG
is_prefix_insn(CPUPPCState * env,uint32_t insn)1178 static bool is_prefix_insn(CPUPPCState *env, uint32_t insn)
1179 {
1180     if (!(env->insns_flags2 & PPC2_ISA310)) {
1181         return false;
1182     }
1183     return ((insn & 0xfc000000) == 0x04000000);
1184 }
1185 
is_prefix_insn_excp(PowerPCCPU * cpu,int excp)1186 static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
1187 {
1188     CPUPPCState *env = &cpu->env;
1189 
1190     if (!(env->insns_flags2 & PPC2_ISA310)) {
1191         return false;
1192     }
1193 
1194     if (!tcg_enabled()) {
1195         /*
1196          * This does not load instructions and set the prefix bit correctly
1197          * for injected interrupts with KVM. That may have to be discovered
1198          * and set by the KVM layer before injecting.
1199          */
1200         return false;
1201     }
1202 
1203     switch (excp) {
1204     case POWERPC_EXCP_MCHECK:
1205         if (!(env->error_code & PPC_BIT(42))) {
1206             /*
1207              * Fetch attempt caused a machine check, so attempting to fetch
1208              * again would cause a recursive machine check.
1209              */
1210             return false;
1211         }
1212         break;
1213     case POWERPC_EXCP_HDSI:
1214         /* HDSI PRTABLE_FAULT has the originating access type in error_code */
1215         if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
1216             (env->error_code == MMU_INST_FETCH)) {
1217             /*
1218              * Fetch failed due to partition scope translation, so prefix
1219              * indication is not relevant (and attempting to load the
1220              * instruction at NIP would cause recursive faults with the same
1221              * translation).
1222              */
1223             return false;
1224         }
1225         break;
1226 
1227     case POWERPC_EXCP_DSI:
1228     case POWERPC_EXCP_DSEG:
1229     case POWERPC_EXCP_ALIGN:
1230     case POWERPC_EXCP_PROGRAM:
1231     case POWERPC_EXCP_FPU:
1232     case POWERPC_EXCP_TRACE:
1233     case POWERPC_EXCP_HV_EMU:
1234     case POWERPC_EXCP_VPU:
1235     case POWERPC_EXCP_VSXU:
1236     case POWERPC_EXCP_FU:
1237     case POWERPC_EXCP_HV_FU:
1238         break;
1239     default:
1240         return false;
1241     }
1242 
1243     return is_prefix_insn(env, ppc_ldl_code(env, env->nip));
1244 }
1245 #else
is_prefix_insn_excp(PowerPCCPU * cpu,int excp)1246 static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
1247 {
1248     return false;
1249 }
1250 #endif
1251 
powerpc_excp_books(PowerPCCPU * cpu,int excp)1252 static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1253 {
1254     CPUPPCState *env = &cpu->env;
1255     target_ulong msr, new_msr, vector;
1256     int srr0 = SPR_SRR0, srr1 = SPR_SRR1, lev = -1;
1257 
1258     /* new srr1 value excluding must-be-zero bits */
1259     msr = env->msr & ~0x783f0000ULL;
1260 
1261     /*
1262      * new interrupt handler msr preserves HV and ME unless explicitly
1263      * overridden
1264      */
1265     new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1266 
1267     /*
1268      * check for special resume at 0x100 from doze/nap/sleep/winkle on
1269      * P7/P8/P9
1270      */
1271     if (env->resume_as_sreset) {
1272         excp = powerpc_reset_wakeup(env, excp, &msr);
1273     }
1274 
1275     /*
1276      * We don't want to generate a Hypervisor Emulation Assistance
1277      * Interrupt if we don't have HVB in msr_mask (PAPR mode),
1278      * unless running a nested-hv guest, in which case the L1
1279      * kernel wants the interrupt.
1280      */
1281     if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB) &&
1282             !books_vhyp_handles_hv_excp(cpu)) {
1283         excp = POWERPC_EXCP_PROGRAM;
1284     }
1285 
1286     vector = env->excp_vectors[excp];
1287     if (vector == (target_ulong)-1ULL) {
1288         cpu_abort(env_cpu(env),
1289                   "Raised an exception without defined vector %d\n", excp);
1290     }
1291     vector |= env->excp_prefix;
1292 
1293     if (is_prefix_insn_excp(cpu, excp)) {
1294         msr |= PPC_BIT(34);
1295     }
1296 
1297     switch (excp) {
1298     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
1299         powerpc_mcheck_checkstop(env);
1300         if (env->msr_mask & MSR_HVB) {
1301             /*
1302              * ISA specifies HV, but can be delivered to guest with HV
1303              * clear (e.g., see FWNMI in PAPR).
1304              */
1305             new_msr |= (target_ulong)MSR_HVB;
1306 
1307             /* HV machine check exceptions don't have ME set */
1308             new_msr &= ~((target_ulong)1 << MSR_ME);
1309         }
1310 
1311         msr |= env->error_code;
1312         break;
1313 
1314     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1315         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1316         break;
1317     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1318         trace_ppc_excp_isi(msr, env->nip);
1319         msr |= env->error_code;
1320         break;
1321     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
1322     {
1323         bool lpes0;
1324 
1325         /* LPES0 is only taken into consideration if we support HV mode */
1326         if (!env->has_hv_mode) {
1327             break;
1328         }
1329         lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1330         if (!lpes0) {
1331             new_msr |= (target_ulong)MSR_HVB;
1332             new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1333             srr0 = SPR_HSRR0;
1334             srr1 = SPR_HSRR1;
1335         }
1336         break;
1337     }
1338     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
1339         /* Optional DSISR update was removed from ISA v3.0 */
1340         if (!(env->insns_flags2 & PPC2_ISA300)) {
1341             /* Get rS/rD and rA from faulting opcode */
1342             /*
1343              * Note: the opcode fields will not be set properly for a
1344              * direct store load/store, but nobody cares as nobody
1345              * actually uses direct store segments.
1346              */
1347             env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1348         }
1349         break;
1350     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1351         switch (env->error_code & ~0xF) {
1352         case POWERPC_EXCP_FP:
1353             if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1354                 trace_ppc_excp_fp_ignore();
1355                 powerpc_reset_excp_state(cpu);
1356                 return;
1357             }
1358             /*
1359              * NIP always points to the faulting instruction for FP exceptions,
1360              * so always use store_next and claim we are precise in the MSR.
1361              */
1362             msr |= 0x00100000;
1363             break;
1364         case POWERPC_EXCP_INVAL:
1365             trace_ppc_excp_inval(env->nip);
1366             msr |= 0x00080000;
1367             break;
1368         case POWERPC_EXCP_PRIV:
1369             msr |= 0x00040000;
1370             break;
1371         case POWERPC_EXCP_TRAP:
1372             msr |= 0x00020000;
1373             break;
1374         default:
1375             /* Should never occur */
1376             cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
1377                       env->error_code);
1378             break;
1379         }
1380         break;
1381     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1382         lev = env->error_code;
1383 
1384         if (lev == 1 && cpu->vhyp) {
1385             dump_hcall(env);
1386         } else {
1387             dump_syscall(env);
1388         }
1389 
1390         /*
1391          * We need to correct the NIP which in this case is supposed
1392          * to point to the next instruction
1393          */
1394         env->nip += 4;
1395 
1396         /* "PAPR mode" built-in hypercall emulation */
1397         if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
1398             cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
1399             powerpc_reset_excp_state(cpu);
1400             return;
1401         }
1402         if (env->insns_flags2 & PPC2_ISA310) {
1403             /* ISAv3.1 puts LEV into SRR1 */
1404             msr |= lev << 20;
1405         }
1406         if (lev == 1) {
1407             new_msr |= (target_ulong)MSR_HVB;
1408         }
1409         break;
1410     case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception                     */
1411         lev = env->error_code;
1412         dump_syscall(env);
1413         env->nip += 4;
1414         new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1415         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1416 
1417         vector += lev * 0x20;
1418 
1419         env->lr = env->nip;
1420         env->ctr = msr;
1421         break;
1422     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
1423     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
1424         break;
1425     case POWERPC_EXCP_RESET:     /* System reset exception                   */
1426         /* A power-saving exception sets ME, otherwise it is unchanged */
1427         if (FIELD_EX64(env->msr, MSR, POW)) {
1428             /* indicate that we resumed from power save mode */
1429             msr |= 0x10000;
1430             new_msr |= ((target_ulong)1 << MSR_ME);
1431         }
1432         if (env->msr_mask & MSR_HVB) {
1433             /*
1434              * ISA specifies HV, but can be delivered to guest with HV
1435              * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
1436              */
1437             new_msr |= (target_ulong)MSR_HVB;
1438         } else {
1439             if (FIELD_EX64(env->msr, MSR, POW)) {
1440                 cpu_abort(env_cpu(env),
1441                           "Trying to deliver power-saving system reset "
1442                           "exception %d with no HV support\n", excp);
1443             }
1444         }
1445         break;
1446     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
1447         msr |= env->error_code;
1448         /* fall through */
1449     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
1450     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
1451     case POWERPC_EXCP_SDOOR:     /* Doorbell interrupt                       */
1452     case POWERPC_EXCP_PERFM:     /* Performance monitor interrupt            */
1453         break;
1454     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
1455         msr |= env->error_code;
1456         /* fall through */
1457     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
1458     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
1459     case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
1460     case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
1461         srr0 = SPR_HSRR0;
1462         srr1 = SPR_HSRR1;
1463         new_msr |= (target_ulong)MSR_HVB;
1464         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1465         break;
1466 #ifdef CONFIG_TCG
1467     case POWERPC_EXCP_HV_EMU: {
1468         uint32_t insn = ppc_ldl_code(env, env->nip);
1469         env->spr[SPR_HEIR] = insn;
1470         if (is_prefix_insn(env, insn)) {
1471             uint32_t insn2 = ppc_ldl_code(env, env->nip + 4);
1472             env->spr[SPR_HEIR] <<= 32;
1473             env->spr[SPR_HEIR] |= insn2;
1474         }
1475         srr0 = SPR_HSRR0;
1476         srr1 = SPR_HSRR1;
1477         new_msr |= (target_ulong)MSR_HVB;
1478         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1479         break;
1480     }
1481 #endif
1482     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
1483     case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               */
1484     case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
1485         env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1486         break;
1487     case POWERPC_EXCP_HV_FU:     /* Hypervisor Facility Unavailable Exception */
1488         env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1489         srr0 = SPR_HSRR0;
1490         srr1 = SPR_HSRR1;
1491         new_msr |= (target_ulong)MSR_HVB;
1492         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1493         break;
1494     case POWERPC_EXCP_PERFM_EBB:        /* Performance Monitor EBB Exception  */
1495     case POWERPC_EXCP_EXTERNAL_EBB:     /* External EBB Exception             */
1496         env->spr[SPR_BESCR] &= ~BESCR_GE;
1497 
1498         /*
1499          * Save NIP for rfebb insn in SPR_EBBRR. Next nip is
1500          * stored in the EBB Handler SPR_EBBHR.
1501          */
1502         env->spr[SPR_EBBRR] = env->nip;
1503         powerpc_set_excp_state(cpu, env->spr[SPR_EBBHR], env->msr);
1504 
1505         /*
1506          * This exception is handled in userspace. No need to proceed.
1507          */
1508         return;
1509     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
1510     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
1511     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
1512     case POWERPC_EXCP_HV_MAINT:  /* Hypervisor Maintenance exception         */
1513         cpu_abort(env_cpu(env), "%s exception not implemented\n",
1514                   powerpc_excp_name(excp));
1515         break;
1516     default:
1517         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
1518                   excp);
1519         break;
1520     }
1521 
1522     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1523         new_msr |= (target_ulong)1 << MSR_LE;
1524     }
1525     new_msr |= (target_ulong)1 << MSR_SF;
1526 
1527     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1528         env->spr[srr0] = env->nip;
1529         env->spr[srr1] = msr;
1530     }
1531 
1532     if ((new_msr & MSR_HVB) && books_vhyp_handles_hv_excp(cpu)) {
1533         /* Deliver interrupt to L1 by returning from the H_ENTER_NESTED call */
1534         cpu->vhyp_class->deliver_hv_excp(cpu, excp);
1535         powerpc_reset_excp_state(cpu);
1536     } else {
1537         /* Sanity check */
1538         if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
1539             cpu_abort(env_cpu(env), "Trying to deliver HV exception (HSRR) %d "
1540                       "with no HV support\n", excp);
1541         }
1542         /* This can update new_msr and vector if AIL applies */
1543         ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
1544         powerpc_set_excp_state(cpu, vector, new_msr);
1545     }
1546 }
1547 #else
powerpc_excp_books(PowerPCCPU * cpu,int excp)1548 static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1549 {
1550     g_assert_not_reached();
1551 }
1552 #endif /* TARGET_PPC64 */
1553 
powerpc_excp(PowerPCCPU * cpu,int excp)1554 void powerpc_excp(PowerPCCPU *cpu, int excp)
1555 {
1556     CPUPPCState *env = &cpu->env;
1557 
1558     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1559         cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
1560                   excp);
1561     }
1562 
1563     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1564                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1565                   excp, env->error_code);
1566     env->excp_stats[excp]++;
1567 
1568     switch (env->excp_model) {
1569     case POWERPC_EXCP_40x:
1570         powerpc_excp_40x(cpu, excp);
1571         break;
1572     case POWERPC_EXCP_6xx:
1573         powerpc_excp_6xx(cpu, excp);
1574         break;
1575     case POWERPC_EXCP_7xx:
1576         powerpc_excp_7xx(cpu, excp);
1577         break;
1578     case POWERPC_EXCP_74xx:
1579         powerpc_excp_74xx(cpu, excp);
1580         break;
1581     case POWERPC_EXCP_BOOKE:
1582         powerpc_excp_booke(cpu, excp);
1583         break;
1584     case POWERPC_EXCP_970:
1585     case POWERPC_EXCP_POWER7:
1586     case POWERPC_EXCP_POWER8:
1587     case POWERPC_EXCP_POWER9:
1588     case POWERPC_EXCP_POWER10:
1589     case POWERPC_EXCP_POWER11:
1590         powerpc_excp_books(cpu, excp);
1591         break;
1592     default:
1593         g_assert_not_reached();
1594     }
1595 }
1596 
ppc_cpu_do_interrupt(CPUState * cs)1597 void ppc_cpu_do_interrupt(CPUState *cs)
1598 {
1599     PowerPCCPU *cpu = POWERPC_CPU(cs);
1600 
1601     powerpc_excp(cpu, cs->exception_index);
1602 }
1603 
1604 #ifdef TARGET_PPC64
1605 #define P7_UNUSED_INTERRUPTS \
1606     (PPC_INTERRUPT_RESET | PPC_INTERRUPT_HVIRT | PPC_INTERRUPT_CEXT |       \
1607      PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT |      \
1608      PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
1609      PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
1610 
p7_interrupt_powersave(uint32_t pending_interrupts,target_ulong lpcr)1611 static int p7_interrupt_powersave(uint32_t pending_interrupts,
1612                                   target_ulong lpcr)
1613 {
1614     if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
1615         (lpcr & LPCR_P7_PECE0)) {
1616         return PPC_INTERRUPT_EXT;
1617     }
1618     if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
1619         (lpcr & LPCR_P7_PECE1)) {
1620         return PPC_INTERRUPT_DECR;
1621     }
1622     if ((pending_interrupts & PPC_INTERRUPT_MCK) &&
1623         (lpcr & LPCR_P7_PECE2)) {
1624         return PPC_INTERRUPT_MCK;
1625     }
1626     if ((pending_interrupts & PPC_INTERRUPT_HMI) &&
1627         (lpcr & LPCR_P7_PECE2)) {
1628         return PPC_INTERRUPT_HMI;
1629     }
1630     if (pending_interrupts & PPC_INTERRUPT_RESET) {
1631         return PPC_INTERRUPT_RESET;
1632     }
1633     return 0;
1634 }
1635 
p7_next_unmasked_interrupt(CPUPPCState * env,uint32_t pending_interrupts,target_ulong lpcr)1636 static int p7_next_unmasked_interrupt(CPUPPCState *env,
1637                                       uint32_t pending_interrupts,
1638                                       target_ulong lpcr)
1639 {
1640     CPUState *cs = env_cpu(env);
1641 
1642     /* Ignore MSR[EE] when coming out of some power management states */
1643     bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1644 
1645     assert((pending_interrupts & P7_UNUSED_INTERRUPTS) == 0);
1646 
1647     if (cs->halted) {
1648         /* LPCR[PECE] controls which interrupts can exit power-saving mode */
1649         return p7_interrupt_powersave(pending_interrupts, lpcr);
1650     }
1651 
1652     /* Machine check exception */
1653     if (pending_interrupts & PPC_INTERRUPT_MCK) {
1654         return PPC_INTERRUPT_MCK;
1655     }
1656 
1657     /* Hypervisor decrementer exception */
1658     if (pending_interrupts & PPC_INTERRUPT_HDECR) {
1659         /* LPCR will be clear when not supported so this will work */
1660         bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1661         if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1662             /* HDEC clears on delivery */
1663             return PPC_INTERRUPT_HDECR;
1664         }
1665     }
1666 
1667     /* External interrupt can ignore MSR:EE under some circumstances */
1668     if (pending_interrupts & PPC_INTERRUPT_EXT) {
1669         bool lpes0 = !!(lpcr & LPCR_LPES0);
1670         bool heic = !!(lpcr & LPCR_HEIC);
1671         /* HEIC blocks delivery to the hypervisor */
1672         if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1673             !FIELD_EX64(env->msr, MSR, PR))) ||
1674             (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1675             return PPC_INTERRUPT_EXT;
1676         }
1677     }
1678     if (msr_ee != 0) {
1679         /* Decrementer exception */
1680         if (pending_interrupts & PPC_INTERRUPT_DECR) {
1681             return PPC_INTERRUPT_DECR;
1682         }
1683         if (pending_interrupts & PPC_INTERRUPT_PERFM) {
1684             return PPC_INTERRUPT_PERFM;
1685         }
1686     }
1687 
1688     return 0;
1689 }
1690 
1691 #define P8_UNUSED_INTERRUPTS \
1692     (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_HVIRT |  \
1693     PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL |  \
1694     PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1695 
p8_interrupt_powersave(uint32_t pending_interrupts,target_ulong lpcr)1696 static int p8_interrupt_powersave(uint32_t pending_interrupts,
1697                                   target_ulong lpcr)
1698 {
1699     if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
1700         (lpcr & LPCR_P8_PECE2)) {
1701         return PPC_INTERRUPT_EXT;
1702     }
1703     if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
1704         (lpcr & LPCR_P8_PECE3)) {
1705         return PPC_INTERRUPT_DECR;
1706     }
1707     if ((pending_interrupts & PPC_INTERRUPT_MCK) &&
1708         (lpcr & LPCR_P8_PECE4)) {
1709         return PPC_INTERRUPT_MCK;
1710     }
1711     if ((pending_interrupts & PPC_INTERRUPT_HMI) &&
1712         (lpcr & LPCR_P8_PECE4)) {
1713         return PPC_INTERRUPT_HMI;
1714     }
1715     if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
1716         (lpcr & LPCR_P8_PECE0)) {
1717         return PPC_INTERRUPT_DOORBELL;
1718     }
1719     if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
1720         (lpcr & LPCR_P8_PECE1)) {
1721         return PPC_INTERRUPT_HDOORBELL;
1722     }
1723     if (pending_interrupts & PPC_INTERRUPT_RESET) {
1724         return PPC_INTERRUPT_RESET;
1725     }
1726     return 0;
1727 }
1728 
p8_next_unmasked_interrupt(CPUPPCState * env,uint32_t pending_interrupts,target_ulong lpcr)1729 static int p8_next_unmasked_interrupt(CPUPPCState *env,
1730                                       uint32_t pending_interrupts,
1731                                       target_ulong lpcr)
1732 {
1733     CPUState *cs = env_cpu(env);
1734 
1735     /* Ignore MSR[EE] when coming out of some power management states */
1736     bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1737 
1738     assert((env->pending_interrupts & P8_UNUSED_INTERRUPTS) == 0);
1739 
1740     if (cs->halted) {
1741         /* LPCR[PECE] controls which interrupts can exit power-saving mode */
1742         return p8_interrupt_powersave(pending_interrupts, lpcr);
1743     }
1744 
1745     /* Machine check exception */
1746     if (pending_interrupts & PPC_INTERRUPT_MCK) {
1747         return PPC_INTERRUPT_MCK;
1748     }
1749 
1750     /* Hypervisor decrementer exception */
1751     if (pending_interrupts & PPC_INTERRUPT_HDECR) {
1752         /* LPCR will be clear when not supported so this will work */
1753         bool hdice = !!(lpcr & LPCR_HDICE);
1754         if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1755             /* HDEC clears on delivery */
1756             return PPC_INTERRUPT_HDECR;
1757         }
1758     }
1759 
1760     /* External interrupt can ignore MSR:EE under some circumstances */
1761     if (pending_interrupts & PPC_INTERRUPT_EXT) {
1762         bool lpes0 = !!(lpcr & LPCR_LPES0);
1763         bool heic = !!(lpcr & LPCR_HEIC);
1764         /* HEIC blocks delivery to the hypervisor */
1765         if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1766             !FIELD_EX64(env->msr, MSR, PR))) ||
1767             (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1768             return PPC_INTERRUPT_EXT;
1769         }
1770     }
1771     if (msr_ee != 0) {
1772         /* Decrementer exception */
1773         if (pending_interrupts & PPC_INTERRUPT_DECR) {
1774             return PPC_INTERRUPT_DECR;
1775         }
1776         if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
1777             return PPC_INTERRUPT_DOORBELL;
1778         }
1779         if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
1780             return PPC_INTERRUPT_HDOORBELL;
1781         }
1782         if (pending_interrupts & PPC_INTERRUPT_PERFM) {
1783             return PPC_INTERRUPT_PERFM;
1784         }
1785         /* EBB exception */
1786         if (pending_interrupts & PPC_INTERRUPT_EBB) {
1787             /*
1788              * EBB exception must be taken in problem state and
1789              * with BESCR_GE set.
1790              */
1791             if (FIELD_EX64(env->msr, MSR, PR) &&
1792                 (env->spr[SPR_BESCR] & BESCR_GE)) {
1793                 return PPC_INTERRUPT_EBB;
1794             }
1795         }
1796     }
1797 
1798     return 0;
1799 }
1800 
1801 #define P9_UNUSED_INTERRUPTS \
1802     (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_CEXT |   \
1803      PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT |  \
1804      PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1805 
p9_interrupt_powersave(CPUPPCState * env,uint32_t pending_interrupts,target_ulong lpcr)1806 static int p9_interrupt_powersave(CPUPPCState *env,
1807                                   uint32_t pending_interrupts,
1808                                   target_ulong lpcr)
1809 {
1810 
1811     /* External Exception */
1812     if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
1813         (lpcr & LPCR_EEE)) {
1814         bool heic = !!(lpcr & LPCR_HEIC);
1815         if (!heic || !FIELD_EX64_HV(env->msr) ||
1816             FIELD_EX64(env->msr, MSR, PR)) {
1817             return PPC_INTERRUPT_EXT;
1818         }
1819     }
1820     /* Decrementer Exception */
1821     if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
1822         (lpcr & LPCR_DEE)) {
1823         return PPC_INTERRUPT_DECR;
1824     }
1825     /* Machine Check or Hypervisor Maintenance Exception */
1826     if (lpcr & LPCR_OEE) {
1827         if (pending_interrupts & PPC_INTERRUPT_MCK) {
1828             return PPC_INTERRUPT_MCK;
1829         }
1830         if (pending_interrupts & PPC_INTERRUPT_HMI) {
1831             return PPC_INTERRUPT_HMI;
1832         }
1833     }
1834     /* Privileged Doorbell Exception */
1835     if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
1836         (lpcr & LPCR_PDEE)) {
1837         return PPC_INTERRUPT_DOORBELL;
1838     }
1839     /* Hypervisor Doorbell Exception */
1840     if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
1841         (lpcr & LPCR_HDEE)) {
1842         return PPC_INTERRUPT_HDOORBELL;
1843     }
1844     /* Hypervisor virtualization exception */
1845     if ((pending_interrupts & PPC_INTERRUPT_HVIRT) &&
1846         (lpcr & LPCR_HVEE)) {
1847         return PPC_INTERRUPT_HVIRT;
1848     }
1849     if (pending_interrupts & PPC_INTERRUPT_RESET) {
1850         return PPC_INTERRUPT_RESET;
1851     }
1852     return 0;
1853 }
1854 
p9_next_unmasked_interrupt(CPUPPCState * env,uint32_t pending_interrupts,target_ulong lpcr)1855 static int p9_next_unmasked_interrupt(CPUPPCState *env,
1856                                       uint32_t pending_interrupts,
1857                                       target_ulong lpcr)
1858 {
1859     CPUState *cs = env_cpu(env);
1860 
1861     /* Ignore MSR[EE] when coming out of some power management states */
1862     bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1863 
1864     assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
1865 
1866     if (cs->halted) {
1867         if (env->spr[SPR_PSSCR] & PSSCR_EC) {
1868             /*
1869              * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can
1870              * wakeup the processor
1871              */
1872             return p9_interrupt_powersave(env, pending_interrupts, lpcr);
1873         } else {
1874             /*
1875              * When it's clear, any system-caused exception exits power-saving
1876              * mode, even the ones that gate on MSR[EE].
1877              */
1878             msr_ee = true;
1879         }
1880     }
1881 
1882     /* Machine check exception */
1883     if (pending_interrupts & PPC_INTERRUPT_MCK) {
1884         return PPC_INTERRUPT_MCK;
1885     }
1886 
1887     /* Hypervisor decrementer exception */
1888     if (pending_interrupts & PPC_INTERRUPT_HDECR) {
1889         /* LPCR will be clear when not supported so this will work */
1890         bool hdice = !!(lpcr & LPCR_HDICE);
1891         if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1892             /* HDEC clears on delivery */
1893             return PPC_INTERRUPT_HDECR;
1894         }
1895     }
1896 
1897     /* Hypervisor virtualization interrupt */
1898     if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
1899         /* LPCR will be clear when not supported so this will work */
1900         bool hvice = !!(lpcr & LPCR_HVICE);
1901         if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) {
1902             return PPC_INTERRUPT_HVIRT;
1903         }
1904     }
1905 
1906     /* External interrupt can ignore MSR:EE under some circumstances */
1907     if (pending_interrupts & PPC_INTERRUPT_EXT) {
1908         bool lpes0 = !!(lpcr & LPCR_LPES0);
1909         bool heic = !!(lpcr & LPCR_HEIC);
1910         /* HEIC blocks delivery to the hypervisor */
1911         if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1912             !FIELD_EX64(env->msr, MSR, PR))) ||
1913             (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1914             return PPC_INTERRUPT_EXT;
1915         }
1916     }
1917     if (msr_ee != 0) {
1918         /* Decrementer exception */
1919         if (pending_interrupts & PPC_INTERRUPT_DECR) {
1920             return PPC_INTERRUPT_DECR;
1921         }
1922         if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
1923             return PPC_INTERRUPT_DOORBELL;
1924         }
1925         if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
1926             return PPC_INTERRUPT_HDOORBELL;
1927         }
1928         if (pending_interrupts & PPC_INTERRUPT_PERFM) {
1929             return PPC_INTERRUPT_PERFM;
1930         }
1931         /* EBB exception */
1932         if (pending_interrupts & PPC_INTERRUPT_EBB) {
1933             /*
1934              * EBB exception must be taken in problem state and
1935              * with BESCR_GE set.
1936              */
1937             if (FIELD_EX64(env->msr, MSR, PR) &&
1938                 (env->spr[SPR_BESCR] & BESCR_GE)) {
1939                 return PPC_INTERRUPT_EBB;
1940             }
1941         }
1942     }
1943 
1944     return 0;
1945 }
1946 #endif /* TARGET_PPC64 */
1947 
ppc_next_unmasked_interrupt(CPUPPCState * env)1948 static int ppc_next_unmasked_interrupt(CPUPPCState *env)
1949 {
1950     uint32_t pending_interrupts = env->pending_interrupts;
1951     target_ulong lpcr = env->spr[SPR_LPCR];
1952     bool async_deliver;
1953 
1954     if (unlikely(env->quiesced)) {
1955         return 0;
1956     }
1957 
1958 #ifdef TARGET_PPC64
1959     switch (env->excp_model) {
1960     case POWERPC_EXCP_POWER7:
1961         return p7_next_unmasked_interrupt(env, pending_interrupts, lpcr);
1962     case POWERPC_EXCP_POWER8:
1963         return p8_next_unmasked_interrupt(env, pending_interrupts, lpcr);
1964     case POWERPC_EXCP_POWER9:
1965     case POWERPC_EXCP_POWER10:
1966     case POWERPC_EXCP_POWER11:
1967         return p9_next_unmasked_interrupt(env, pending_interrupts, lpcr);
1968     default:
1969         break;
1970     }
1971 #endif
1972 
1973     /* External reset */
1974     if (pending_interrupts & PPC_INTERRUPT_RESET) {
1975         return PPC_INTERRUPT_RESET;
1976     }
1977     /* Machine check exception */
1978     if (pending_interrupts & PPC_INTERRUPT_MCK) {
1979         return PPC_INTERRUPT_MCK;
1980     }
1981 #if 0 /* TODO */
1982     /* External debug exception */
1983     if (env->pending_interrupts & PPC_INTERRUPT_DEBUG) {
1984         return PPC_INTERRUPT_DEBUG;
1985     }
1986 #endif
1987 
1988     /*
1989      * For interrupts that gate on MSR:EE, we need to do something a
1990      * bit more subtle, as we need to let them through even when EE is
1991      * clear when coming out of some power management states (in order
1992      * for them to become a 0x100).
1993      */
1994     async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1995 
1996     /* Hypervisor decrementer exception */
1997     if (pending_interrupts & PPC_INTERRUPT_HDECR) {
1998         /* LPCR will be clear when not supported so this will work */
1999         bool hdice = !!(lpcr & LPCR_HDICE);
2000         if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) {
2001             /* HDEC clears on delivery */
2002             return PPC_INTERRUPT_HDECR;
2003         }
2004     }
2005 
2006     /* Hypervisor virtualization interrupt */
2007     if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
2008         /* LPCR will be clear when not supported so this will work */
2009         bool hvice = !!(lpcr & LPCR_HVICE);
2010         if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) {
2011             return PPC_INTERRUPT_HVIRT;
2012         }
2013     }
2014 
2015     /* External interrupt can ignore MSR:EE under some circumstances */
2016     if (pending_interrupts & PPC_INTERRUPT_EXT) {
2017         bool lpes0 = !!(lpcr & LPCR_LPES0);
2018         bool heic = !!(lpcr & LPCR_HEIC);
2019         /* HEIC blocks delivery to the hypervisor */
2020         if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) &&
2021             !FIELD_EX64(env->msr, MSR, PR))) ||
2022             (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
2023             return PPC_INTERRUPT_EXT;
2024         }
2025     }
2026     if (FIELD_EX64(env->msr, MSR, CE)) {
2027         /* External critical interrupt */
2028         if (pending_interrupts & PPC_INTERRUPT_CEXT) {
2029             return PPC_INTERRUPT_CEXT;
2030         }
2031     }
2032     if (async_deliver != 0) {
2033         /* Watchdog timer on embedded PowerPC */
2034         if (pending_interrupts & PPC_INTERRUPT_WDT) {
2035             return PPC_INTERRUPT_WDT;
2036         }
2037         if (pending_interrupts & PPC_INTERRUPT_CDOORBELL) {
2038             return PPC_INTERRUPT_CDOORBELL;
2039         }
2040         /* Fixed interval timer on embedded PowerPC */
2041         if (pending_interrupts & PPC_INTERRUPT_FIT) {
2042             return PPC_INTERRUPT_FIT;
2043         }
2044         /* Programmable interval timer on embedded PowerPC */
2045         if (pending_interrupts & PPC_INTERRUPT_PIT) {
2046             return PPC_INTERRUPT_PIT;
2047         }
2048         /* Decrementer exception */
2049         if (pending_interrupts & PPC_INTERRUPT_DECR) {
2050             return PPC_INTERRUPT_DECR;
2051         }
2052         if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
2053             return PPC_INTERRUPT_DOORBELL;
2054         }
2055         if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
2056             return PPC_INTERRUPT_HDOORBELL;
2057         }
2058         if (pending_interrupts & PPC_INTERRUPT_PERFM) {
2059             return PPC_INTERRUPT_PERFM;
2060         }
2061         /* Thermal interrupt */
2062         if (pending_interrupts & PPC_INTERRUPT_THERM) {
2063             return PPC_INTERRUPT_THERM;
2064         }
2065         /* EBB exception */
2066         if (pending_interrupts & PPC_INTERRUPT_EBB) {
2067             /*
2068              * EBB exception must be taken in problem state and
2069              * with BESCR_GE set.
2070              */
2071             if (FIELD_EX64(env->msr, MSR, PR) &&
2072                 (env->spr[SPR_BESCR] & BESCR_GE)) {
2073                 return PPC_INTERRUPT_EBB;
2074             }
2075         }
2076     }
2077 
2078     return 0;
2079 }
2080 
2081 /*
2082  * Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
2083  * delivered and clears CPU_INTERRUPT_HARD otherwise.
2084  *
2085  * This method is called by ppc_set_interrupt when an interrupt is raised or
2086  * lowered, and should also be called whenever an interrupt masking condition
2087  * is changed, e.g.:
2088  *  - When relevant bits of MSR are altered, like EE, HV, PR, etc.;
2089  *  - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.;
2090  *  - When PSSCR[EC] or env->resume_as_sreset are changed;
2091  *  - When cs->halted is changed and the CPU has a different interrupt masking
2092  *    logic in power-saving mode (e.g., POWER7/8/9/10);
2093  */
ppc_maybe_interrupt(CPUPPCState * env)2094 void ppc_maybe_interrupt(CPUPPCState *env)
2095 {
2096     CPUState *cs = env_cpu(env);
2097     BQL_LOCK_GUARD();
2098 
2099     if (ppc_next_unmasked_interrupt(env)) {
2100         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2101     } else {
2102         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2103     }
2104 }
2105 
2106 #ifdef TARGET_PPC64
p7_deliver_interrupt(CPUPPCState * env,int interrupt)2107 static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
2108 {
2109     PowerPCCPU *cpu = env_archcpu(env);
2110 
2111     switch (interrupt) {
2112     case PPC_INTERRUPT_MCK: /* Machine check exception */
2113         env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2114         powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2115         break;
2116 
2117     case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2118         /* HDEC clears on delivery */
2119         env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2120         powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2121         break;
2122 
2123     case PPC_INTERRUPT_EXT:
2124         if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2125             powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2126         } else {
2127             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2128         }
2129         break;
2130 
2131     case PPC_INTERRUPT_DECR: /* Decrementer exception */
2132         powerpc_excp(cpu, POWERPC_EXCP_DECR);
2133         break;
2134     case PPC_INTERRUPT_PERFM:
2135         powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2136         break;
2137     case 0:
2138         /*
2139          * This is a bug ! It means that has_work took us out of halt without
2140          * anything to deliver while in a PM state that requires getting
2141          * out via a 0x100
2142          *
2143          * This means we will incorrectly execute past the power management
2144          * instruction instead of triggering a reset.
2145          *
2146          * It generally means a discrepancy between the wakeup conditions in the
2147          * processor has_work implementation and the logic in this function.
2148          */
2149         assert(!env->resume_as_sreset);
2150         break;
2151     default:
2152         cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
2153                   interrupt);
2154     }
2155 }
2156 
p8_deliver_interrupt(CPUPPCState * env,int interrupt)2157 static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
2158 {
2159     PowerPCCPU *cpu = env_archcpu(env);
2160 
2161     switch (interrupt) {
2162     case PPC_INTERRUPT_MCK: /* Machine check exception */
2163         env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2164         powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2165         break;
2166 
2167     case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2168         /* HDEC clears on delivery */
2169         env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2170         powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2171         break;
2172 
2173     case PPC_INTERRUPT_EXT:
2174         if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2175             powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2176         } else {
2177             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2178         }
2179         break;
2180 
2181     case PPC_INTERRUPT_DECR: /* Decrementer exception */
2182         powerpc_excp(cpu, POWERPC_EXCP_DECR);
2183         break;
2184     case PPC_INTERRUPT_DOORBELL:
2185         if (!env->resume_as_sreset) {
2186             env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2187         }
2188         if (is_book3s_arch2x(env)) {
2189             powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2190         } else {
2191             powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2192         }
2193         break;
2194     case PPC_INTERRUPT_HDOORBELL:
2195         if (!env->resume_as_sreset) {
2196             env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2197         }
2198         powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2199         break;
2200     case PPC_INTERRUPT_PERFM:
2201         powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2202         break;
2203     case PPC_INTERRUPT_EBB: /* EBB exception */
2204         env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2205         if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2206             powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2207         } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2208             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2209         }
2210         break;
2211     case 0:
2212         /*
2213          * This is a bug ! It means that has_work took us out of halt without
2214          * anything to deliver while in a PM state that requires getting
2215          * out via a 0x100
2216          *
2217          * This means we will incorrectly execute past the power management
2218          * instruction instead of triggering a reset.
2219          *
2220          * It generally means a discrepancy between the wakeup conditions in the
2221          * processor has_work implementation and the logic in this function.
2222          */
2223         assert(!env->resume_as_sreset);
2224         break;
2225     default:
2226         cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
2227                   interrupt);
2228     }
2229 }
2230 
p9_deliver_interrupt(CPUPPCState * env,int interrupt)2231 static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
2232 {
2233     PowerPCCPU *cpu = env_archcpu(env);
2234     CPUState *cs = env_cpu(env);
2235 
2236     if (cs->halted && !(env->spr[SPR_PSSCR] & PSSCR_EC) &&
2237         !FIELD_EX64(env->msr, MSR, EE)) {
2238         /*
2239          * A pending interrupt took us out of power-saving, but MSR[EE] says
2240          * that we should return to NIP+4 instead of delivering it.
2241          */
2242         return;
2243     }
2244 
2245     switch (interrupt) {
2246     case PPC_INTERRUPT_MCK: /* Machine check exception */
2247         env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2248         powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2249         break;
2250 
2251     case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2252         /* HDEC clears on delivery */
2253         /* XXX: should not see an HDEC if resume_as_sreset. assert? */
2254         env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2255         powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2256         break;
2257     case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */
2258         powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2259         break;
2260 
2261     case PPC_INTERRUPT_EXT:
2262         if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2263             powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2264         } else {
2265             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2266         }
2267         break;
2268 
2269     case PPC_INTERRUPT_DECR: /* Decrementer exception */
2270         powerpc_excp(cpu, POWERPC_EXCP_DECR);
2271         break;
2272     case PPC_INTERRUPT_DOORBELL:
2273         if (!env->resume_as_sreset) {
2274             env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2275         }
2276         powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2277         break;
2278     case PPC_INTERRUPT_HDOORBELL:
2279         if (!env->resume_as_sreset) {
2280             env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2281         }
2282         powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2283         break;
2284     case PPC_INTERRUPT_PERFM:
2285         powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2286         break;
2287     case PPC_INTERRUPT_EBB: /* EBB exception */
2288         env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2289         if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2290             powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2291         } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2292             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2293         }
2294         break;
2295     case 0:
2296         /*
2297          * This is a bug ! It means that has_work took us out of halt without
2298          * anything to deliver while in a PM state that requires getting
2299          * out via a 0x100
2300          *
2301          * This means we will incorrectly execute past the power management
2302          * instruction instead of triggering a reset.
2303          *
2304          * It generally means a discrepancy between the wakeup conditions in the
2305          * processor has_work implementation and the logic in this function.
2306          */
2307         assert(!env->resume_as_sreset);
2308         break;
2309     default:
2310         cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
2311                   interrupt);
2312     }
2313 }
2314 #endif /* TARGET_PPC64 */
2315 
ppc_deliver_interrupt(CPUPPCState * env,int interrupt)2316 static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
2317 {
2318 #ifdef TARGET_PPC64
2319     switch (env->excp_model) {
2320     case POWERPC_EXCP_POWER7:
2321         return p7_deliver_interrupt(env, interrupt);
2322     case POWERPC_EXCP_POWER8:
2323         return p8_deliver_interrupt(env, interrupt);
2324     case POWERPC_EXCP_POWER9:
2325     case POWERPC_EXCP_POWER10:
2326     case POWERPC_EXCP_POWER11:
2327         return p9_deliver_interrupt(env, interrupt);
2328     default:
2329         break;
2330     }
2331 #endif
2332     PowerPCCPU *cpu = env_archcpu(env);
2333 
2334     switch (interrupt) {
2335     case PPC_INTERRUPT_RESET: /* External reset */
2336         env->pending_interrupts &= ~PPC_INTERRUPT_RESET;
2337         powerpc_excp(cpu, POWERPC_EXCP_RESET);
2338         break;
2339     case PPC_INTERRUPT_MCK: /* Machine check exception */
2340         env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2341         powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2342         break;
2343 
2344     case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2345         /* HDEC clears on delivery */
2346         env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2347         powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2348         break;
2349     case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */
2350         powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2351         break;
2352 
2353     case PPC_INTERRUPT_EXT:
2354         if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2355             powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2356         } else {
2357             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2358         }
2359         break;
2360     case PPC_INTERRUPT_CEXT: /* External critical interrupt */
2361         powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
2362         break;
2363 
2364     case PPC_INTERRUPT_WDT: /* Watchdog timer on embedded PowerPC */
2365         env->pending_interrupts &= ~PPC_INTERRUPT_WDT;
2366         powerpc_excp(cpu, POWERPC_EXCP_WDT);
2367         break;
2368     case PPC_INTERRUPT_CDOORBELL:
2369         env->pending_interrupts &= ~PPC_INTERRUPT_CDOORBELL;
2370         powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
2371         break;
2372     case PPC_INTERRUPT_FIT: /* Fixed interval timer on embedded PowerPC */
2373         env->pending_interrupts &= ~PPC_INTERRUPT_FIT;
2374         powerpc_excp(cpu, POWERPC_EXCP_FIT);
2375         break;
2376     case PPC_INTERRUPT_PIT: /* Programmable interval timer on embedded ppc */
2377         env->pending_interrupts &= ~PPC_INTERRUPT_PIT;
2378         powerpc_excp(cpu, POWERPC_EXCP_PIT);
2379         break;
2380     case PPC_INTERRUPT_DECR: /* Decrementer exception */
2381         if (ppc_decr_clear_on_delivery(env)) {
2382             env->pending_interrupts &= ~PPC_INTERRUPT_DECR;
2383         }
2384         powerpc_excp(cpu, POWERPC_EXCP_DECR);
2385         break;
2386     case PPC_INTERRUPT_DOORBELL:
2387         env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2388         if (is_book3s_arch2x(env)) {
2389             powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2390         } else {
2391             powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2392         }
2393         break;
2394     case PPC_INTERRUPT_HDOORBELL:
2395         env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2396         powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2397         break;
2398     case PPC_INTERRUPT_PERFM:
2399         powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2400         break;
2401     case PPC_INTERRUPT_THERM:  /* Thermal interrupt */
2402         env->pending_interrupts &= ~PPC_INTERRUPT_THERM;
2403         powerpc_excp(cpu, POWERPC_EXCP_THERM);
2404         break;
2405     case PPC_INTERRUPT_EBB: /* EBB exception */
2406         env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2407         if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2408             powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2409         } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2410             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2411         }
2412         break;
2413     case 0:
2414         /*
2415          * This is a bug ! It means that has_work took us out of halt without
2416          * anything to deliver while in a PM state that requires getting
2417          * out via a 0x100
2418          *
2419          * This means we will incorrectly execute past the power management
2420          * instruction instead of triggering a reset.
2421          *
2422          * It generally means a discrepancy between the wakeup conditions in the
2423          * processor has_work implementation and the logic in this function.
2424          */
2425         assert(!env->resume_as_sreset);
2426         break;
2427     default:
2428         cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
2429                   interrupt);
2430     }
2431 }
2432 
2433 /*
2434  * system reset is not delivered via normal irq method, so have to set
2435  * halted = 0 to resume CPU running if it was halted. Possibly we should
2436  * move it over to using PPC_INTERRUPT_RESET rather than async_run_on_cpu.
2437  */
ppc_cpu_do_system_reset(CPUState * cs)2438 void ppc_cpu_do_system_reset(CPUState *cs)
2439 {
2440     PowerPCCPU *cpu = POWERPC_CPU(cs);
2441 
2442     cs->halted = 0;
2443     powerpc_excp(cpu, POWERPC_EXCP_RESET);
2444 }
2445 
ppc_cpu_do_fwnmi_machine_check(CPUState * cs,target_ulong vector)2446 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
2447 {
2448     PowerPCCPU *cpu = POWERPC_CPU(cs);
2449     CPUPPCState *env = &cpu->env;
2450     target_ulong msr = 0;
2451 
2452     /*
2453      * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
2454      * been set by KVM.
2455      */
2456     msr = (1ULL << MSR_ME);
2457     msr |= env->msr & (1ULL << MSR_SF);
2458     if (ppc_interrupts_little_endian(cpu, false)) {
2459         msr |= (1ULL << MSR_LE);
2460     }
2461 
2462     /* Anything for nested required here? MSR[HV] bit? */
2463 
2464     cs->halted = 0;
2465     powerpc_set_excp_state(cpu, vector, msr);
2466 }
2467 
ppc_cpu_exec_interrupt(CPUState * cs,int interrupt_request)2468 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
2469 {
2470     CPUPPCState *env = cpu_env(cs);
2471     int interrupt;
2472 
2473     if ((interrupt_request & CPU_INTERRUPT_HARD) == 0) {
2474         return false;
2475     }
2476 
2477     interrupt = ppc_next_unmasked_interrupt(env);
2478     if (interrupt == 0) {
2479         return false;
2480     }
2481 
2482     ppc_deliver_interrupt(env, interrupt);
2483     if (env->pending_interrupts == 0) {
2484         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2485     }
2486     return true;
2487 }
2488 
2489 #endif /* !CONFIG_USER_ONLY */
2490