xref: /qemu/target/ppc/excp_helper.c (revision b355f08a)
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 "cpu.h"
22 #include "exec/exec-all.h"
23 #include "internal.h"
24 #include "helper_regs.h"
25 
26 #ifdef CONFIG_TCG
27 #include "exec/helper-proto.h"
28 #include "exec/cpu_ldst.h"
29 #endif
30 
31 /* #define DEBUG_OP */
32 /* #define DEBUG_SOFTWARE_TLB */
33 /* #define DEBUG_EXCEPTIONS */
34 
35 #ifdef DEBUG_EXCEPTIONS
36 #  define LOG_EXCP(...) qemu_log(__VA_ARGS__)
37 #else
38 #  define LOG_EXCP(...) do { } while (0)
39 #endif
40 
41 /*****************************************************************************/
42 /* Exception processing */
43 #if !defined(CONFIG_USER_ONLY)
44 
45 static inline void dump_syscall(CPUPPCState *env)
46 {
47     qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
48                   " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
49                   " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
50                   " nip=" TARGET_FMT_lx "\n",
51                   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
52                   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
53                   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
54                   ppc_dump_gpr(env, 8), env->nip);
55 }
56 
57 static inline void dump_hcall(CPUPPCState *env)
58 {
59     qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
60                   " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
61                   " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
62                   " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
63                   " nip=" TARGET_FMT_lx "\n",
64                   ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
65                   ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
66                   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
67                   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
68                   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
69                   env->nip);
70 }
71 
72 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
73                                 target_ulong *msr)
74 {
75     /* We no longer are in a PM state */
76     env->resume_as_sreset = false;
77 
78     /* Pretend to be returning from doze always as we don't lose state */
79     *msr |= SRR1_WS_NOLOSS;
80 
81     /* Machine checks are sent normally */
82     if (excp == POWERPC_EXCP_MCHECK) {
83         return excp;
84     }
85     switch (excp) {
86     case POWERPC_EXCP_RESET:
87         *msr |= SRR1_WAKERESET;
88         break;
89     case POWERPC_EXCP_EXTERNAL:
90         *msr |= SRR1_WAKEEE;
91         break;
92     case POWERPC_EXCP_DECR:
93         *msr |= SRR1_WAKEDEC;
94         break;
95     case POWERPC_EXCP_SDOOR:
96         *msr |= SRR1_WAKEDBELL;
97         break;
98     case POWERPC_EXCP_SDOOR_HV:
99         *msr |= SRR1_WAKEHDBELL;
100         break;
101     case POWERPC_EXCP_HV_MAINT:
102         *msr |= SRR1_WAKEHMI;
103         break;
104     case POWERPC_EXCP_HVIRT:
105         *msr |= SRR1_WAKEHVI;
106         break;
107     default:
108         cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
109                   excp);
110     }
111     return POWERPC_EXCP_RESET;
112 }
113 
114 /*
115  * AIL - Alternate Interrupt Location, a mode that allows interrupts to be
116  * taken with the MMU on, and which uses an alternate location (e.g., so the
117  * kernel/hv can map the vectors there with an effective address).
118  *
119  * An interrupt is considered to be taken "with AIL" or "AIL applies" if they
120  * are delivered in this way. AIL requires the LPCR to be set to enable this
121  * mode, and then a number of conditions have to be true for AIL to apply.
122  *
123  * First of all, SRESET, MCE, and HMI are always delivered without AIL, because
124  * they specifically want to be in real mode (e.g., the MCE might be signaling
125  * a SLB multi-hit which requires SLB flush before the MMU can be enabled).
126  *
127  * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV],
128  * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current
129  * radix mode (LPCR[HR]).
130  *
131  * POWER8, POWER9 with LPCR[HR]=0
132  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
133  * +-----------+-------------+---------+-------------+-----+
134  * | a         | 00/01/10    | x       | x           | 0   |
135  * | a         | 11          | 0       | 1           | 0   |
136  * | a         | 11          | 1       | 1           | a   |
137  * | a         | 11          | 0       | 0           | a   |
138  * +-------------------------------------------------------+
139  *
140  * POWER9 with LPCR[HR]=1
141  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
142  * +-----------+-------------+---------+-------------+-----+
143  * | a         | 00/01/10    | x       | x           | 0   |
144  * | a         | 11          | x       | x           | a   |
145  * +-------------------------------------------------------+
146  *
147  * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to
148  * the hypervisor in AIL mode if the guest is radix. This is good for
149  * performance but allows the guest to influence the AIL of hypervisor
150  * interrupts using its MSR, and also the hypervisor must disallow guest
151  * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to
152  * use AIL for its MSR[HV] 0->1 interrupts.
153  *
154  * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to
155  * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and
156  * MSR[HV] 1->1).
157  *
158  * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1.
159  *
160  * POWER10 behaviour is
161  * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
162  * +-----------+------------+-------------+---------+-------------+-----+
163  * | a         | h          | 00/01/10    | 0       | 0           | 0   |
164  * | a         | h          | 11          | 0       | 0           | a   |
165  * | a         | h          | x           | 0       | 1           | h   |
166  * | a         | h          | 00/01/10    | 1       | 1           | 0   |
167  * | a         | h          | 11          | 1       | 1           | h   |
168  * +--------------------------------------------------------------------+
169  */
170 static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
171                                       target_ulong msr,
172                                       target_ulong *new_msr,
173                                       target_ulong *vector)
174 {
175 #if defined(TARGET_PPC64)
176     CPUPPCState *env = &cpu->env;
177     bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
178     bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
179     int ail = 0;
180 
181     if (excp == POWERPC_EXCP_MCHECK ||
182         excp == POWERPC_EXCP_RESET ||
183         excp == POWERPC_EXCP_HV_MAINT) {
184         /* SRESET, MCE, HMI never apply AIL */
185         return;
186     }
187 
188     if (excp_model == POWERPC_EXCP_POWER8 ||
189         excp_model == POWERPC_EXCP_POWER9) {
190         if (!mmu_all_on) {
191             /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
192             return;
193         }
194         if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
195             /*
196              * AIL does not work if there is a MSR[HV] 0->1 transition and the
197              * partition is in HPT mode. For radix guests, such interrupts are
198              * allowed to be delivered to the hypervisor in ail mode.
199              */
200             return;
201         }
202 
203         ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
204         if (ail == 0) {
205             return;
206         }
207         if (ail == 1) {
208             /* AIL=1 is reserved, treat it like AIL=0 */
209             return;
210         }
211 
212     } else if (excp_model == POWERPC_EXCP_POWER10) {
213         if (!mmu_all_on && !hv_escalation) {
214             /*
215              * AIL works for HV interrupts even with guest MSR[IR/DR] disabled.
216              * Guest->guest and HV->HV interrupts do require MMU on.
217              */
218             return;
219         }
220 
221         if (*new_msr & MSR_HVB) {
222             if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
223                 /* HV interrupts depend on LPCR[HAIL] */
224                 return;
225             }
226             ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */
227         } else {
228             ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
229         }
230         if (ail == 0) {
231             return;
232         }
233         if (ail == 1 || ail == 2) {
234             /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
235             return;
236         }
237     } else {
238         /* Other processors do not support AIL */
239         return;
240     }
241 
242     /*
243      * AIL applies, so the new MSR gets IR and DR set, and an offset applied
244      * to the new IP.
245      */
246     *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
247 
248     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
249         if (ail == 2) {
250             *vector |= 0x0000000000018000ull;
251         } else if (ail == 3) {
252             *vector |= 0xc000000000004000ull;
253         }
254     } else {
255         /*
256          * scv AIL is a little different. AIL=2 does not change the address,
257          * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
258          */
259         if (ail == 3) {
260             *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */
261             *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
262         }
263     }
264 #endif
265 }
266 
267 static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
268                                           target_ulong vector, target_ulong msr)
269 {
270     CPUState *cs = CPU(cpu);
271     CPUPPCState *env = &cpu->env;
272 
273     /*
274      * We don't use hreg_store_msr here as already have treated any
275      * special case that could occur. Just store MSR and update hflags
276      *
277      * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
278      * will prevent setting of the HV bit which some exceptions might need
279      * to do.
280      */
281     env->msr = msr & env->msr_mask;
282     hreg_compute_hflags(env);
283     env->nip = vector;
284     /* Reset exception state */
285     cs->exception_index = POWERPC_EXCP_NONE;
286     env->error_code = 0;
287 
288     /* Reset the reservation */
289     env->reserve_addr = -1;
290 
291     /*
292      * Any interrupt is context synchronizing, check if TCG TLB needs
293      * a delayed flush on ppc64
294      */
295     check_tlb_flush(env, false);
296 }
297 
298 /*
299  * Note that this function should be greatly optimized when called
300  * with a constant excp, from ppc_hw_interrupt
301  */
302 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
303 {
304     CPUState *cs = CPU(cpu);
305     CPUPPCState *env = &cpu->env;
306     target_ulong msr, new_msr, vector;
307     int srr0, srr1, asrr0, asrr1, lev = -1;
308 
309     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
310                   " => %08x (%02x)\n", env->nip, excp, env->error_code);
311 
312     /* new srr1 value excluding must-be-zero bits */
313     if (excp_model == POWERPC_EXCP_BOOKE) {
314         msr = env->msr;
315     } else {
316         msr = env->msr & ~0x783f0000ULL;
317     }
318 
319     /*
320      * new interrupt handler msr preserves existing HV and ME unless
321      * explicitly overriden
322      */
323     new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
324 
325     /* target registers */
326     srr0 = SPR_SRR0;
327     srr1 = SPR_SRR1;
328     asrr0 = -1;
329     asrr1 = -1;
330 
331     /*
332      * check for special resume at 0x100 from doze/nap/sleep/winkle on
333      * P7/P8/P9
334      */
335     if (env->resume_as_sreset) {
336         excp = powerpc_reset_wakeup(cs, env, excp, &msr);
337     }
338 
339     /*
340      * Hypervisor emulation assistance interrupt only exists on server
341      * arch 2.05 server or later. We also don't want to generate it if
342      * we don't have HVB in msr_mask (PAPR mode).
343      */
344     if (excp == POWERPC_EXCP_HV_EMU
345 #if defined(TARGET_PPC64)
346         && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB))
347 #endif /* defined(TARGET_PPC64) */
348 
349     ) {
350         excp = POWERPC_EXCP_PROGRAM;
351     }
352 
353     switch (excp) {
354     case POWERPC_EXCP_NONE:
355         /* Should never happen */
356         return;
357     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
358         switch (excp_model) {
359         case POWERPC_EXCP_40x:
360             srr0 = SPR_40x_SRR2;
361             srr1 = SPR_40x_SRR3;
362             break;
363         case POWERPC_EXCP_BOOKE:
364             srr0 = SPR_BOOKE_CSRR0;
365             srr1 = SPR_BOOKE_CSRR1;
366             break;
367         case POWERPC_EXCP_G2:
368             break;
369         default:
370             goto excp_invalid;
371         }
372         break;
373     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
374         if (msr_me == 0) {
375             /*
376              * Machine check exception is not enabled.  Enter
377              * checkstop state.
378              */
379             fprintf(stderr, "Machine check while not allowed. "
380                     "Entering checkstop state\n");
381             if (qemu_log_separate()) {
382                 qemu_log("Machine check while not allowed. "
383                         "Entering checkstop state\n");
384             }
385             cs->halted = 1;
386             cpu_interrupt_exittb(cs);
387         }
388         if (env->msr_mask & MSR_HVB) {
389             /*
390              * ISA specifies HV, but can be delivered to guest with HV
391              * clear (e.g., see FWNMI in PAPR).
392              */
393             new_msr |= (target_ulong)MSR_HVB;
394         }
395 
396         /* machine check exceptions don't have ME set */
397         new_msr &= ~((target_ulong)1 << MSR_ME);
398 
399         /* XXX: should also have something loaded in DAR / DSISR */
400         switch (excp_model) {
401         case POWERPC_EXCP_40x:
402             srr0 = SPR_40x_SRR2;
403             srr1 = SPR_40x_SRR3;
404             break;
405         case POWERPC_EXCP_BOOKE:
406             /* FIXME: choose one or the other based on CPU type */
407             srr0 = SPR_BOOKE_MCSRR0;
408             srr1 = SPR_BOOKE_MCSRR1;
409             asrr0 = SPR_BOOKE_CSRR0;
410             asrr1 = SPR_BOOKE_CSRR1;
411             break;
412         default:
413             break;
414         }
415         break;
416     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
417         LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
418                  "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
419         break;
420     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
421         LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
422                  "\n", msr, env->nip);
423         msr |= env->error_code;
424         break;
425     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
426     {
427         bool lpes0;
428 
429         cs = CPU(cpu);
430 
431         /*
432          * Exception targeting modifiers
433          *
434          * LPES0 is supported on POWER7/8/9
435          * LPES1 is not supported (old iSeries mode)
436          *
437          * On anything else, we behave as if LPES0 is 1
438          * (externals don't alter MSR:HV)
439          */
440 #if defined(TARGET_PPC64)
441         if (excp_model == POWERPC_EXCP_POWER7 ||
442             excp_model == POWERPC_EXCP_POWER8 ||
443             excp_model == POWERPC_EXCP_POWER9 ||
444             excp_model == POWERPC_EXCP_POWER10) {
445             lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
446         } else
447 #endif /* defined(TARGET_PPC64) */
448         {
449             lpes0 = true;
450         }
451 
452         if (!lpes0) {
453             new_msr |= (target_ulong)MSR_HVB;
454             new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
455             srr0 = SPR_HSRR0;
456             srr1 = SPR_HSRR1;
457         }
458         if (env->mpic_proxy) {
459             /* IACK the IRQ on delivery */
460             env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
461         }
462         break;
463     }
464     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
465         /* Get rS/rD and rA from faulting opcode */
466         /*
467          * Note: the opcode fields will not be set properly for a
468          * direct store load/store, but nobody cares as nobody
469          * actually uses direct store segments.
470          */
471         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
472         break;
473     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
474         switch (env->error_code & ~0xF) {
475         case POWERPC_EXCP_FP:
476             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
477                 LOG_EXCP("Ignore floating point exception\n");
478                 cs->exception_index = POWERPC_EXCP_NONE;
479                 env->error_code = 0;
480                 return;
481             }
482 
483             /*
484              * FP exceptions always have NIP pointing to the faulting
485              * instruction, so always use store_next and claim we are
486              * precise in the MSR.
487              */
488             msr |= 0x00100000;
489             env->spr[SPR_BOOKE_ESR] = ESR_FP;
490             break;
491         case POWERPC_EXCP_INVAL:
492             LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
493             msr |= 0x00080000;
494             env->spr[SPR_BOOKE_ESR] = ESR_PIL;
495             break;
496         case POWERPC_EXCP_PRIV:
497             msr |= 0x00040000;
498             env->spr[SPR_BOOKE_ESR] = ESR_PPR;
499             break;
500         case POWERPC_EXCP_TRAP:
501             msr |= 0x00020000;
502             env->spr[SPR_BOOKE_ESR] = ESR_PTR;
503             break;
504         default:
505             /* Should never occur */
506             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
507                       env->error_code);
508             break;
509         }
510         break;
511     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
512         lev = env->error_code;
513 
514         if ((lev == 1) && cpu->vhyp) {
515             dump_hcall(env);
516         } else {
517             dump_syscall(env);
518         }
519 
520         /*
521          * We need to correct the NIP which in this case is supposed
522          * to point to the next instruction
523          */
524         env->nip += 4;
525 
526         /* "PAPR mode" built-in hypercall emulation */
527         if ((lev == 1) && cpu->vhyp) {
528             PPCVirtualHypervisorClass *vhc =
529                 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
530             vhc->hypercall(cpu->vhyp, cpu);
531             return;
532         }
533         if (lev == 1) {
534             new_msr |= (target_ulong)MSR_HVB;
535         }
536         break;
537     case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception                     */
538         lev = env->error_code;
539         dump_syscall(env);
540         env->nip += 4;
541         new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
542         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
543         break;
544     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
545     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
546     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
547         break;
548     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
549         /* FIT on 4xx */
550         LOG_EXCP("FIT exception\n");
551         break;
552     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
553         LOG_EXCP("WDT exception\n");
554         switch (excp_model) {
555         case POWERPC_EXCP_BOOKE:
556             srr0 = SPR_BOOKE_CSRR0;
557             srr1 = SPR_BOOKE_CSRR1;
558             break;
559         default:
560             break;
561         }
562         break;
563     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
564     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
565         break;
566     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
567         if (env->flags & POWERPC_FLAG_DE) {
568             /* FIXME: choose one or the other based on CPU type */
569             srr0 = SPR_BOOKE_DSRR0;
570             srr1 = SPR_BOOKE_DSRR1;
571             asrr0 = SPR_BOOKE_CSRR0;
572             asrr1 = SPR_BOOKE_CSRR1;
573             /* DBSR already modified by caller */
574         } else {
575             cpu_abort(cs, "Debug exception triggered on unsupported model\n");
576         }
577         break;
578     case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
579         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
580         break;
581     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
582         /* XXX: TODO */
583         cpu_abort(cs, "Embedded floating point data exception "
584                   "is not implemented yet !\n");
585         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
586         break;
587     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
588         /* XXX: TODO */
589         cpu_abort(cs, "Embedded floating point round exception "
590                   "is not implemented yet !\n");
591         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
592         break;
593     case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
594         /* XXX: TODO */
595         cpu_abort(cs,
596                   "Performance counter exception is not implemented yet !\n");
597         break;
598     case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
599         break;
600     case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
601         srr0 = SPR_BOOKE_CSRR0;
602         srr1 = SPR_BOOKE_CSRR1;
603         break;
604     case POWERPC_EXCP_RESET:     /* System reset exception                   */
605         /* A power-saving exception sets ME, otherwise it is unchanged */
606         if (msr_pow) {
607             /* indicate that we resumed from power save mode */
608             msr |= 0x10000;
609             new_msr |= ((target_ulong)1 << MSR_ME);
610         }
611         if (env->msr_mask & MSR_HVB) {
612             /*
613              * ISA specifies HV, but can be delivered to guest with HV
614              * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
615              */
616             new_msr |= (target_ulong)MSR_HVB;
617         } else {
618             if (msr_pow) {
619                 cpu_abort(cs, "Trying to deliver power-saving system reset "
620                           "exception %d with no HV support\n", excp);
621             }
622         }
623         break;
624     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
625     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
626     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
627         break;
628     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
629         msr |= env->error_code;
630         /* fall through */
631     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
632     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
633     case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
634     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
635     case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
636     case POWERPC_EXCP_HV_EMU:
637     case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
638         srr0 = SPR_HSRR0;
639         srr1 = SPR_HSRR1;
640         new_msr |= (target_ulong)MSR_HVB;
641         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
642         break;
643     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
644     case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               */
645     case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
646 #ifdef TARGET_PPC64
647         env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
648 #endif
649         break;
650     case POWERPC_EXCP_HV_FU:     /* Hypervisor Facility Unavailable Exception */
651 #ifdef TARGET_PPC64
652         env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
653         srr0 = SPR_HSRR0;
654         srr1 = SPR_HSRR1;
655         new_msr |= (target_ulong)MSR_HVB;
656         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
657 #endif
658         break;
659     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
660         LOG_EXCP("PIT exception\n");
661         break;
662     case POWERPC_EXCP_IO:        /* IO error exception                       */
663         /* XXX: TODO */
664         cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
665         break;
666     case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
667         /* XXX: TODO */
668         cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
669         break;
670     case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
671         /* XXX: TODO */
672         cpu_abort(cs, "602 emulation trap exception "
673                   "is not implemented yet !\n");
674         break;
675     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
676     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
677     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
678         switch (excp_model) {
679         case POWERPC_EXCP_602:
680         case POWERPC_EXCP_603:
681         case POWERPC_EXCP_603E:
682         case POWERPC_EXCP_G2:
683             /* Swap temporary saved registers with GPRs */
684             if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
685                 new_msr |= (target_ulong)1 << MSR_TGPR;
686                 hreg_swap_gpr_tgpr(env);
687             }
688             /* fall through */
689         case POWERPC_EXCP_7x5:
690 #if defined(DEBUG_SOFTWARE_TLB)
691             if (qemu_log_enabled()) {
692                 const char *es;
693                 target_ulong *miss, *cmp;
694                 int en;
695 
696                 if (excp == POWERPC_EXCP_IFTLB) {
697                     es = "I";
698                     en = 'I';
699                     miss = &env->spr[SPR_IMISS];
700                     cmp = &env->spr[SPR_ICMP];
701                 } else {
702                     if (excp == POWERPC_EXCP_DLTLB) {
703                         es = "DL";
704                     } else {
705                         es = "DS";
706                     }
707                     en = 'D';
708                     miss = &env->spr[SPR_DMISS];
709                     cmp = &env->spr[SPR_DCMP];
710                 }
711                 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
712                          TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
713                          TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
714                          env->spr[SPR_HASH1], env->spr[SPR_HASH2],
715                          env->error_code);
716             }
717 #endif
718             msr |= env->crf[0] << 28;
719             msr |= env->error_code; /* key, D/I, S/L bits */
720             /* Set way using a LRU mechanism */
721             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
722             break;
723         case POWERPC_EXCP_74xx:
724 #if defined(DEBUG_SOFTWARE_TLB)
725             if (qemu_log_enabled()) {
726                 const char *es;
727                 target_ulong *miss, *cmp;
728                 int en;
729 
730                 if (excp == POWERPC_EXCP_IFTLB) {
731                     es = "I";
732                     en = 'I';
733                     miss = &env->spr[SPR_TLBMISS];
734                     cmp = &env->spr[SPR_PTEHI];
735                 } else {
736                     if (excp == POWERPC_EXCP_DLTLB) {
737                         es = "DL";
738                     } else {
739                         es = "DS";
740                     }
741                     en = 'D';
742                     miss = &env->spr[SPR_TLBMISS];
743                     cmp = &env->spr[SPR_PTEHI];
744                 }
745                 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
746                          TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
747                          env->error_code);
748             }
749 #endif
750             msr |= env->error_code; /* key bit */
751             break;
752         default:
753             cpu_abort(cs, "Invalid TLB miss exception\n");
754             break;
755         }
756         break;
757     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
758         /* XXX: TODO */
759         cpu_abort(cs, "Floating point assist exception "
760                   "is not implemented yet !\n");
761         break;
762     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
763         /* XXX: TODO */
764         cpu_abort(cs, "DABR exception is not implemented yet !\n");
765         break;
766     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
767         /* XXX: TODO */
768         cpu_abort(cs, "IABR exception is not implemented yet !\n");
769         break;
770     case POWERPC_EXCP_SMI:       /* System management interrupt              */
771         /* XXX: TODO */
772         cpu_abort(cs, "SMI exception is not implemented yet !\n");
773         break;
774     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
775         /* XXX: TODO */
776         cpu_abort(cs, "Thermal management exception "
777                   "is not implemented yet !\n");
778         break;
779     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
780         /* XXX: TODO */
781         cpu_abort(cs,
782                   "Performance counter exception is not implemented yet !\n");
783         break;
784     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
785         /* XXX: TODO */
786         cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
787         break;
788     case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
789         /* XXX: TODO */
790         cpu_abort(cs,
791                   "970 soft-patch exception is not implemented yet !\n");
792         break;
793     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
794         /* XXX: TODO */
795         cpu_abort(cs,
796                   "970 maintenance exception is not implemented yet !\n");
797         break;
798     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
799         /* XXX: TODO */
800         cpu_abort(cs, "Maskable external exception "
801                   "is not implemented yet !\n");
802         break;
803     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
804         /* XXX: TODO */
805         cpu_abort(cs, "Non maskable external exception "
806                   "is not implemented yet !\n");
807         break;
808     default:
809     excp_invalid:
810         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
811         break;
812     }
813 
814     /* Sanity check */
815     if (!(env->msr_mask & MSR_HVB)) {
816         if (new_msr & MSR_HVB) {
817             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
818                       "no HV support\n", excp);
819         }
820         if (srr0 == SPR_HSRR0) {
821             cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
822                       "no HV support\n", excp);
823         }
824     }
825 
826     /*
827      * Sort out endianness of interrupt, this differs depending on the
828      * CPU, the HV mode, etc...
829      */
830 #ifdef TARGET_PPC64
831     if (excp_model == POWERPC_EXCP_POWER7) {
832         if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
833             new_msr |= (target_ulong)1 << MSR_LE;
834         }
835     } else if (excp_model == POWERPC_EXCP_POWER8) {
836         if (new_msr & MSR_HVB) {
837             if (env->spr[SPR_HID0] & HID0_HILE) {
838                 new_msr |= (target_ulong)1 << MSR_LE;
839             }
840         } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
841             new_msr |= (target_ulong)1 << MSR_LE;
842         }
843     } else if (excp_model == POWERPC_EXCP_POWER9 ||
844                excp_model == POWERPC_EXCP_POWER10) {
845         if (new_msr & MSR_HVB) {
846             if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
847                 new_msr |= (target_ulong)1 << MSR_LE;
848             }
849         } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
850             new_msr |= (target_ulong)1 << MSR_LE;
851         }
852     } else if (msr_ile) {
853         new_msr |= (target_ulong)1 << MSR_LE;
854     }
855 #else
856     if (msr_ile) {
857         new_msr |= (target_ulong)1 << MSR_LE;
858     }
859 #endif
860 
861     vector = env->excp_vectors[excp];
862     if (vector == (target_ulong)-1ULL) {
863         cpu_abort(cs, "Raised an exception without defined vector %d\n",
864                   excp);
865     }
866 
867     vector |= env->excp_prefix;
868 
869     /* If any alternate SRR register are defined, duplicate saved values */
870     if (asrr0 != -1) {
871         env->spr[asrr0] = env->nip;
872     }
873     if (asrr1 != -1) {
874         env->spr[asrr1] = msr;
875     }
876 
877 #if defined(TARGET_PPC64)
878     if (excp_model == POWERPC_EXCP_BOOKE) {
879         if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
880             /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
881             new_msr |= (target_ulong)1 << MSR_CM;
882         } else {
883             vector = (uint32_t)vector;
884         }
885     } else {
886         if (!msr_isf && !mmu_is_64bit(env->mmu_model)) {
887             vector = (uint32_t)vector;
888         } else {
889             new_msr |= (target_ulong)1 << MSR_SF;
890         }
891     }
892 #endif
893 
894     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
895         /* Save PC */
896         env->spr[srr0] = env->nip;
897 
898         /* Save MSR */
899         env->spr[srr1] = msr;
900 
901 #if defined(TARGET_PPC64)
902     } else {
903         vector += lev * 0x20;
904 
905         env->lr = env->nip;
906         env->ctr = msr;
907 #endif
908     }
909 
910     /* This can update new_msr and vector if AIL applies */
911     ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
912 
913     powerpc_set_excp_state(cpu, vector, new_msr);
914 }
915 
916 void ppc_cpu_do_interrupt(CPUState *cs)
917 {
918     PowerPCCPU *cpu = POWERPC_CPU(cs);
919     CPUPPCState *env = &cpu->env;
920 
921     powerpc_excp(cpu, env->excp_model, cs->exception_index);
922 }
923 
924 static void ppc_hw_interrupt(CPUPPCState *env)
925 {
926     PowerPCCPU *cpu = env_archcpu(env);
927     bool async_deliver;
928 
929     /* External reset */
930     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
931         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
932         powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
933         return;
934     }
935     /* Machine check exception */
936     if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
937         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
938         powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
939         return;
940     }
941 #if 0 /* TODO */
942     /* External debug exception */
943     if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
944         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
945         powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
946         return;
947     }
948 #endif
949 
950     /*
951      * For interrupts that gate on MSR:EE, we need to do something a
952      * bit more subtle, as we need to let them through even when EE is
953      * clear when coming out of some power management states (in order
954      * for them to become a 0x100).
955      */
956     async_deliver = (msr_ee != 0) || env->resume_as_sreset;
957 
958     /* Hypervisor decrementer exception */
959     if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
960         /* LPCR will be clear when not supported so this will work */
961         bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
962         if ((async_deliver || msr_hv == 0) && hdice) {
963             /* HDEC clears on delivery */
964             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
965             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
966             return;
967         }
968     }
969 
970     /* Hypervisor virtualization interrupt */
971     if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
972         /* LPCR will be clear when not supported so this will work */
973         bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
974         if ((async_deliver || msr_hv == 0) && hvice) {
975             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
976             return;
977         }
978     }
979 
980     /* External interrupt can ignore MSR:EE under some circumstances */
981     if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
982         bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
983         bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
984         /* HEIC blocks delivery to the hypervisor */
985         if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
986             (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
987             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
988             return;
989         }
990     }
991     if (msr_ce != 0) {
992         /* External critical interrupt */
993         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
994             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
995             return;
996         }
997     }
998     if (async_deliver != 0) {
999         /* Watchdog timer on embedded PowerPC */
1000         if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
1001             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
1002             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
1003             return;
1004         }
1005         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
1006             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
1007             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
1008             return;
1009         }
1010         /* Fixed interval timer on embedded PowerPC */
1011         if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
1012             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
1013             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
1014             return;
1015         }
1016         /* Programmable interval timer on embedded PowerPC */
1017         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
1018             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
1019             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
1020             return;
1021         }
1022         /* Decrementer exception */
1023         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
1024             if (ppc_decr_clear_on_delivery(env)) {
1025                 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
1026             }
1027             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
1028             return;
1029         }
1030         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
1031             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1032             if (is_book3s_arch2x(env)) {
1033                 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
1034             } else {
1035                 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
1036             }
1037             return;
1038         }
1039         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
1040             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1041             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
1042             return;
1043         }
1044         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
1045             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
1046             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
1047             return;
1048         }
1049         /* Thermal interrupt */
1050         if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
1051             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
1052             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
1053             return;
1054         }
1055     }
1056 
1057     if (env->resume_as_sreset) {
1058         /*
1059          * This is a bug ! It means that has_work took us out of halt without
1060          * anything to deliver while in a PM state that requires getting
1061          * out via a 0x100
1062          *
1063          * This means we will incorrectly execute past the power management
1064          * instruction instead of triggering a reset.
1065          *
1066          * It generally means a discrepancy between the wakeup conditions in the
1067          * processor has_work implementation and the logic in this function.
1068          */
1069         cpu_abort(env_cpu(env),
1070                   "Wakeup from PM state but interrupt Undelivered");
1071     }
1072 }
1073 
1074 void ppc_cpu_do_system_reset(CPUState *cs)
1075 {
1076     PowerPCCPU *cpu = POWERPC_CPU(cs);
1077     CPUPPCState *env = &cpu->env;
1078 
1079     powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
1080 }
1081 
1082 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
1083 {
1084     PowerPCCPU *cpu = POWERPC_CPU(cs);
1085     CPUPPCState *env = &cpu->env;
1086     target_ulong msr = 0;
1087 
1088     /*
1089      * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
1090      * been set by KVM.
1091      */
1092     msr = (1ULL << MSR_ME);
1093     msr |= env->msr & (1ULL << MSR_SF);
1094     if (ppc_interrupts_little_endian(cpu)) {
1095         msr |= (1ULL << MSR_LE);
1096     }
1097 
1098     powerpc_set_excp_state(cpu, vector, msr);
1099 }
1100 
1101 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1102 {
1103     PowerPCCPU *cpu = POWERPC_CPU(cs);
1104     CPUPPCState *env = &cpu->env;
1105 
1106     if (interrupt_request & CPU_INTERRUPT_HARD) {
1107         ppc_hw_interrupt(env);
1108         if (env->pending_interrupts == 0) {
1109             cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
1110         }
1111         return true;
1112     }
1113     return false;
1114 }
1115 
1116 #endif /* !CONFIG_USER_ONLY */
1117 
1118 #if defined(DEBUG_OP)
1119 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
1120 {
1121     qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
1122              TARGET_FMT_lx "\n", RA, msr);
1123 }
1124 #endif
1125 
1126 /*****************************************************************************/
1127 /* Exceptions processing helpers */
1128 
1129 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
1130                             uint32_t error_code, uintptr_t raddr)
1131 {
1132     CPUState *cs = env_cpu(env);
1133 
1134     cs->exception_index = exception;
1135     env->error_code = error_code;
1136     cpu_loop_exit_restore(cs, raddr);
1137 }
1138 
1139 void raise_exception_err(CPUPPCState *env, uint32_t exception,
1140                          uint32_t error_code)
1141 {
1142     raise_exception_err_ra(env, exception, error_code, 0);
1143 }
1144 
1145 void raise_exception(CPUPPCState *env, uint32_t exception)
1146 {
1147     raise_exception_err_ra(env, exception, 0, 0);
1148 }
1149 
1150 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
1151                         uintptr_t raddr)
1152 {
1153     raise_exception_err_ra(env, exception, 0, raddr);
1154 }
1155 
1156 #ifdef CONFIG_TCG
1157 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1158                                 uint32_t error_code)
1159 {
1160     raise_exception_err_ra(env, exception, error_code, 0);
1161 }
1162 
1163 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1164 {
1165     raise_exception_err_ra(env, exception, 0, 0);
1166 }
1167 #endif
1168 
1169 #if !defined(CONFIG_USER_ONLY)
1170 #ifdef CONFIG_TCG
1171 void helper_store_msr(CPUPPCState *env, target_ulong val)
1172 {
1173     uint32_t excp = hreg_store_msr(env, val, 0);
1174 
1175     if (excp != 0) {
1176         CPUState *cs = env_cpu(env);
1177         cpu_interrupt_exittb(cs);
1178         raise_exception(env, excp);
1179     }
1180 }
1181 
1182 #if defined(TARGET_PPC64)
1183 void helper_scv(CPUPPCState *env, uint32_t lev)
1184 {
1185     if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
1186         raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
1187     } else {
1188         raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
1189     }
1190 }
1191 
1192 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1193 {
1194     CPUState *cs;
1195 
1196     cs = env_cpu(env);
1197     cs->halted = 1;
1198 
1199     /* Condition for waking up at 0x100 */
1200     env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1201         (env->spr[SPR_PSSCR] & PSSCR_EC);
1202 }
1203 #endif /* defined(TARGET_PPC64) */
1204 #endif /* CONFIG_TCG */
1205 
1206 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1207 {
1208     CPUState *cs = env_cpu(env);
1209 
1210     /* MSR:POW cannot be set by any form of rfi */
1211     msr &= ~(1ULL << MSR_POW);
1212 
1213 #if defined(TARGET_PPC64)
1214     /* Switching to 32-bit ? Crop the nip */
1215     if (!msr_is_64bit(env, msr)) {
1216         nip = (uint32_t)nip;
1217     }
1218 #else
1219     nip = (uint32_t)nip;
1220 #endif
1221     /* XXX: beware: this is false if VLE is supported */
1222     env->nip = nip & ~((target_ulong)0x00000003);
1223     hreg_store_msr(env, msr, 1);
1224 #if defined(DEBUG_OP)
1225     cpu_dump_rfi(env->nip, env->msr);
1226 #endif
1227     /*
1228      * No need to raise an exception here, as rfi is always the last
1229      * insn of a TB
1230      */
1231     cpu_interrupt_exittb(cs);
1232     /* Reset the reservation */
1233     env->reserve_addr = -1;
1234 
1235     /* Context synchronizing: check if TCG TLB needs flush */
1236     check_tlb_flush(env, false);
1237 }
1238 
1239 #ifdef CONFIG_TCG
1240 void helper_rfi(CPUPPCState *env)
1241 {
1242     do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1243 }
1244 
1245 #define MSR_BOOK3S_MASK
1246 #if defined(TARGET_PPC64)
1247 void helper_rfid(CPUPPCState *env)
1248 {
1249     /*
1250      * The architecture defines a number of rules for which bits can
1251      * change but in practice, we handle this in hreg_store_msr()
1252      * which will be called by do_rfi(), so there is no need to filter
1253      * here
1254      */
1255     do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1256 }
1257 
1258 void helper_rfscv(CPUPPCState *env)
1259 {
1260     do_rfi(env, env->lr, env->ctr);
1261 }
1262 
1263 void helper_hrfid(CPUPPCState *env)
1264 {
1265     do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1266 }
1267 #endif
1268 
1269 /*****************************************************************************/
1270 /* Embedded PowerPC specific helpers */
1271 void helper_40x_rfci(CPUPPCState *env)
1272 {
1273     do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
1274 }
1275 
1276 void helper_rfci(CPUPPCState *env)
1277 {
1278     do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
1279 }
1280 
1281 void helper_rfdi(CPUPPCState *env)
1282 {
1283     /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1284     do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
1285 }
1286 
1287 void helper_rfmci(CPUPPCState *env)
1288 {
1289     /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1290     do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
1291 }
1292 #endif /* CONFIG_TCG */
1293 #endif /* !defined(CONFIG_USER_ONLY) */
1294 
1295 #ifdef CONFIG_TCG
1296 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1297                uint32_t flags)
1298 {
1299     if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1300                   ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1301                   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1302                   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1303                   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1304         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1305                                POWERPC_EXCP_TRAP, GETPC());
1306     }
1307 }
1308 
1309 #if defined(TARGET_PPC64)
1310 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1311                uint32_t flags)
1312 {
1313     if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1314                   ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1315                   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1316                   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1317                   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1318         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1319                                POWERPC_EXCP_TRAP, GETPC());
1320     }
1321 }
1322 #endif
1323 #endif
1324 
1325 #if !defined(CONFIG_USER_ONLY)
1326 /*****************************************************************************/
1327 /* PowerPC 601 specific instructions (POWER bridge) */
1328 
1329 #ifdef CONFIG_TCG
1330 void helper_rfsvc(CPUPPCState *env)
1331 {
1332     do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
1333 }
1334 
1335 /* Embedded.Processor Control */
1336 static int dbell2irq(target_ulong rb)
1337 {
1338     int msg = rb & DBELL_TYPE_MASK;
1339     int irq = -1;
1340 
1341     switch (msg) {
1342     case DBELL_TYPE_DBELL:
1343         irq = PPC_INTERRUPT_DOORBELL;
1344         break;
1345     case DBELL_TYPE_DBELL_CRIT:
1346         irq = PPC_INTERRUPT_CDOORBELL;
1347         break;
1348     case DBELL_TYPE_G_DBELL:
1349     case DBELL_TYPE_G_DBELL_CRIT:
1350     case DBELL_TYPE_G_DBELL_MC:
1351         /* XXX implement */
1352     default:
1353         break;
1354     }
1355 
1356     return irq;
1357 }
1358 
1359 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1360 {
1361     int irq = dbell2irq(rb);
1362 
1363     if (irq < 0) {
1364         return;
1365     }
1366 
1367     env->pending_interrupts &= ~(1 << irq);
1368 }
1369 
1370 void helper_msgsnd(target_ulong rb)
1371 {
1372     int irq = dbell2irq(rb);
1373     int pir = rb & DBELL_PIRTAG_MASK;
1374     CPUState *cs;
1375 
1376     if (irq < 0) {
1377         return;
1378     }
1379 
1380     qemu_mutex_lock_iothread();
1381     CPU_FOREACH(cs) {
1382         PowerPCCPU *cpu = POWERPC_CPU(cs);
1383         CPUPPCState *cenv = &cpu->env;
1384 
1385         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1386             cenv->pending_interrupts |= 1 << irq;
1387             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1388         }
1389     }
1390     qemu_mutex_unlock_iothread();
1391 }
1392 
1393 /* Server Processor Control */
1394 
1395 static bool dbell_type_server(target_ulong rb)
1396 {
1397     /*
1398      * A Directed Hypervisor Doorbell message is sent only if the
1399      * message type is 5. All other types are reserved and the
1400      * instruction is a no-op
1401      */
1402     return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
1403 }
1404 
1405 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
1406 {
1407     if (!dbell_type_server(rb)) {
1408         return;
1409     }
1410 
1411     env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1412 }
1413 
1414 static void book3s_msgsnd_common(int pir, int irq)
1415 {
1416     CPUState *cs;
1417 
1418     qemu_mutex_lock_iothread();
1419     CPU_FOREACH(cs) {
1420         PowerPCCPU *cpu = POWERPC_CPU(cs);
1421         CPUPPCState *cenv = &cpu->env;
1422 
1423         /* TODO: broadcast message to all threads of the same  processor */
1424         if (cenv->spr_cb[SPR_PIR].default_value == pir) {
1425             cenv->pending_interrupts |= 1 << irq;
1426             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1427         }
1428     }
1429     qemu_mutex_unlock_iothread();
1430 }
1431 
1432 void helper_book3s_msgsnd(target_ulong rb)
1433 {
1434     int pir = rb & DBELL_PROCIDTAG_MASK;
1435 
1436     if (!dbell_type_server(rb)) {
1437         return;
1438     }
1439 
1440     book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
1441 }
1442 
1443 #if defined(TARGET_PPC64)
1444 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
1445 {
1446     helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
1447 
1448     if (!dbell_type_server(rb)) {
1449         return;
1450     }
1451 
1452     env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1453 }
1454 
1455 /*
1456  * sends a message to other threads that are on the same
1457  * multi-threaded processor
1458  */
1459 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
1460 {
1461     int pir = env->spr_cb[SPR_PIR].default_value;
1462 
1463     helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
1464 
1465     if (!dbell_type_server(rb)) {
1466         return;
1467     }
1468 
1469     /* TODO: TCG supports only one thread */
1470 
1471     book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
1472 }
1473 #endif
1474 #endif /* CONFIG_TCG */
1475 #endif
1476 
1477 #ifdef CONFIG_TCG
1478 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
1479                                  MMUAccessType access_type,
1480                                  int mmu_idx, uintptr_t retaddr)
1481 {
1482     CPUPPCState *env = cs->env_ptr;
1483     uint32_t insn;
1484 
1485     /* Restore state and reload the insn we executed, for filling in DSISR.  */
1486     cpu_restore_state(cs, retaddr, true);
1487     insn = cpu_ldl_code(env, env->nip);
1488 
1489     cs->exception_index = POWERPC_EXCP_ALIGN;
1490     env->error_code = insn & 0x03FF0000;
1491     cpu_loop_exit(cs);
1492 }
1493 #endif
1494