xref: /qemu/target/ppc/excp_helper.c (revision c50eaed135216597cd75f71cec79ae28a7996c06)
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 #include "trace.h"
27 
28 #ifdef CONFIG_TCG
29 #include "exec/helper-proto.h"
30 #include "exec/cpu_ldst.h"
31 #endif
32 
33 /*****************************************************************************/
34 /* Exception processing */
35 #if !defined(CONFIG_USER_ONLY)
36 
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 
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 
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 
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 
167 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
168                                 target_ulong *msr)
169 {
170     /* We no longer are in a PM state */
171     env->resume_as_sreset = false;
172 
173     /* Pretend to be returning from doze always as we don't lose state */
174     *msr |= SRR1_WS_NOLOSS;
175 
176     /* Machine checks are sent normally */
177     if (excp == POWERPC_EXCP_MCHECK) {
178         return excp;
179     }
180     switch (excp) {
181     case POWERPC_EXCP_RESET:
182         *msr |= SRR1_WAKERESET;
183         break;
184     case POWERPC_EXCP_EXTERNAL:
185         *msr |= SRR1_WAKEEE;
186         break;
187     case POWERPC_EXCP_DECR:
188         *msr |= SRR1_WAKEDEC;
189         break;
190     case POWERPC_EXCP_SDOOR:
191         *msr |= SRR1_WAKEDBELL;
192         break;
193     case POWERPC_EXCP_SDOOR_HV:
194         *msr |= SRR1_WAKEHDBELL;
195         break;
196     case POWERPC_EXCP_HV_MAINT:
197         *msr |= SRR1_WAKEHMI;
198         break;
199     case POWERPC_EXCP_HVIRT:
200         *msr |= SRR1_WAKEHVI;
201         break;
202     default:
203         cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
204                   excp);
205     }
206     return POWERPC_EXCP_RESET;
207 }
208 
209 /*
210  * AIL - Alternate Interrupt Location, a mode that allows interrupts to be
211  * taken with the MMU on, and which uses an alternate location (e.g., so the
212  * kernel/hv can map the vectors there with an effective address).
213  *
214  * An interrupt is considered to be taken "with AIL" or "AIL applies" if they
215  * are delivered in this way. AIL requires the LPCR to be set to enable this
216  * mode, and then a number of conditions have to be true for AIL to apply.
217  *
218  * First of all, SRESET, MCE, and HMI are always delivered without AIL, because
219  * they specifically want to be in real mode (e.g., the MCE might be signaling
220  * a SLB multi-hit which requires SLB flush before the MMU can be enabled).
221  *
222  * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV],
223  * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current
224  * radix mode (LPCR[HR]).
225  *
226  * POWER8, POWER9 with LPCR[HR]=0
227  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
228  * +-----------+-------------+---------+-------------+-----+
229  * | a         | 00/01/10    | x       | x           | 0   |
230  * | a         | 11          | 0       | 1           | 0   |
231  * | a         | 11          | 1       | 1           | a   |
232  * | a         | 11          | 0       | 0           | a   |
233  * +-------------------------------------------------------+
234  *
235  * POWER9 with LPCR[HR]=1
236  * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
237  * +-----------+-------------+---------+-------------+-----+
238  * | a         | 00/01/10    | x       | x           | 0   |
239  * | a         | 11          | x       | x           | a   |
240  * +-------------------------------------------------------+
241  *
242  * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to
243  * the hypervisor in AIL mode if the guest is radix. This is good for
244  * performance but allows the guest to influence the AIL of hypervisor
245  * interrupts using its MSR, and also the hypervisor must disallow guest
246  * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to
247  * use AIL for its MSR[HV] 0->1 interrupts.
248  *
249  * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to
250  * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and
251  * MSR[HV] 1->1).
252  *
253  * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1.
254  *
255  * POWER10 behaviour is
256  * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
257  * +-----------+------------+-------------+---------+-------------+-----+
258  * | a         | h          | 00/01/10    | 0       | 0           | 0   |
259  * | a         | h          | 11          | 0       | 0           | a   |
260  * | a         | h          | x           | 0       | 1           | h   |
261  * | a         | h          | 00/01/10    | 1       | 1           | 0   |
262  * | a         | h          | 11          | 1       | 1           | h   |
263  * +--------------------------------------------------------------------+
264  */
265 static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
266                                       target_ulong msr,
267                                       target_ulong *new_msr,
268                                       target_ulong *vector)
269 {
270 #if defined(TARGET_PPC64)
271     CPUPPCState *env = &cpu->env;
272     bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
273     bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
274     int ail = 0;
275 
276     if (excp == POWERPC_EXCP_MCHECK ||
277         excp == POWERPC_EXCP_RESET ||
278         excp == POWERPC_EXCP_HV_MAINT) {
279         /* SRESET, MCE, HMI never apply AIL */
280         return;
281     }
282 
283     if (excp_model == POWERPC_EXCP_POWER8 ||
284         excp_model == POWERPC_EXCP_POWER9) {
285         if (!mmu_all_on) {
286             /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
287             return;
288         }
289         if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
290             /*
291              * AIL does not work if there is a MSR[HV] 0->1 transition and the
292              * partition is in HPT mode. For radix guests, such interrupts are
293              * allowed to be delivered to the hypervisor in ail mode.
294              */
295             return;
296         }
297 
298         ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
299         if (ail == 0) {
300             return;
301         }
302         if (ail == 1) {
303             /* AIL=1 is reserved, treat it like AIL=0 */
304             return;
305         }
306 
307     } else if (excp_model == POWERPC_EXCP_POWER10) {
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) {
326             return;
327         }
328         if (ail == 1 || ail == 2) {
329             /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
330             return;
331         }
332     } else {
333         /* Other processors do not support AIL */
334         return;
335     }
336 
337     /*
338      * AIL applies, so the new MSR gets IR and DR set, and an offset applied
339      * to the new IP.
340      */
341     *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
342 
343     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
344         if (ail == 2) {
345             *vector |= 0x0000000000018000ull;
346         } else if (ail == 3) {
347             *vector |= 0xc000000000004000ull;
348         }
349     } else {
350         /*
351          * scv AIL is a little different. AIL=2 does not change the address,
352          * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
353          */
354         if (ail == 3) {
355             *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */
356             *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
357         }
358     }
359 #endif
360 }
361 
362 static void powerpc_set_excp_state(PowerPCCPU *cpu,
363                                           target_ulong vector, target_ulong msr)
364 {
365     CPUState *cs = CPU(cpu);
366     CPUPPCState *env = &cpu->env;
367 
368     /*
369      * We don't use hreg_store_msr here as already have treated any
370      * special case that could occur. Just store MSR and update hflags
371      *
372      * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
373      * will prevent setting of the HV bit which some exceptions might need
374      * to do.
375      */
376     env->msr = msr & env->msr_mask;
377     hreg_compute_hflags(env);
378     env->nip = vector;
379     /* Reset exception state */
380     cs->exception_index = POWERPC_EXCP_NONE;
381     env->error_code = 0;
382 
383     /* Reset the reservation */
384     env->reserve_addr = -1;
385 
386     /*
387      * Any interrupt is context synchronizing, check if TCG TLB needs
388      * a delayed flush on ppc64
389      */
390     check_tlb_flush(env, false);
391 }
392 
393 static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
394 {
395     CPUState *cs = CPU(cpu);
396     CPUPPCState *env = &cpu->env;
397     target_ulong msr, new_msr, vector;
398     int srr0, srr1;
399 
400     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
401         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
402     }
403 
404     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
405                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
406                   excp, env->error_code);
407 
408     /* new srr1 value excluding must-be-zero bits */
409     msr = env->msr & ~0x783f0000ULL;
410 
411     /*
412      * new interrupt handler msr preserves existing ME unless
413      * explicitly overriden.
414      */
415     new_msr = env->msr & (((target_ulong)1 << MSR_ME));
416 
417     /* target registers */
418     srr0 = SPR_SRR0;
419     srr1 = SPR_SRR1;
420 
421     /*
422      * Hypervisor emulation assistance interrupt only exists on server
423      * arch 2.05 server or later.
424      */
425     if (excp == POWERPC_EXCP_HV_EMU) {
426         excp = POWERPC_EXCP_PROGRAM;
427     }
428 
429     vector = env->excp_vectors[excp];
430     if (vector == (target_ulong)-1ULL) {
431         cpu_abort(cs, "Raised an exception without defined vector %d\n",
432                   excp);
433     }
434 
435     vector |= env->excp_prefix;
436 
437     switch (excp) {
438     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
439         srr0 = SPR_40x_SRR2;
440         srr1 = SPR_40x_SRR3;
441         break;
442     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
443         if (msr_me == 0) {
444             /*
445              * Machine check exception is not enabled.  Enter
446              * checkstop state.
447              */
448             fprintf(stderr, "Machine check while not allowed. "
449                     "Entering checkstop state\n");
450             if (qemu_log_separate()) {
451                 qemu_log("Machine check while not allowed. "
452                         "Entering checkstop state\n");
453             }
454             cs->halted = 1;
455             cpu_interrupt_exittb(cs);
456         }
457 
458         /* machine check exceptions don't have ME set */
459         new_msr &= ~((target_ulong)1 << MSR_ME);
460 
461         srr0 = SPR_40x_SRR2;
462         srr1 = SPR_40x_SRR3;
463         break;
464     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
465         trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
466         break;
467     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
468         trace_ppc_excp_isi(msr, env->nip);
469         break;
470     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
471         break;
472     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
473         break;
474     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
475         switch (env->error_code & ~0xF) {
476         case POWERPC_EXCP_FP:
477             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
478                 trace_ppc_excp_fp_ignore();
479                 cs->exception_index = POWERPC_EXCP_NONE;
480                 env->error_code = 0;
481                 return;
482             }
483             env->spr[SPR_40x_ESR] = ESR_FP;
484             break;
485         case POWERPC_EXCP_INVAL:
486             trace_ppc_excp_inval(env->nip);
487             env->spr[SPR_40x_ESR] = ESR_PIL;
488             break;
489         case POWERPC_EXCP_PRIV:
490             env->spr[SPR_40x_ESR] = ESR_PPR;
491             break;
492         case POWERPC_EXCP_TRAP:
493             env->spr[SPR_40x_ESR] = ESR_PTR;
494             break;
495         default:
496             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
497                       env->error_code);
498             break;
499         }
500         break;
501     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
502         dump_syscall(env);
503 
504         /*
505          * We need to correct the NIP which in this case is supposed
506          * to point to the next instruction
507          */
508         env->nip += 4;
509         break;
510     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
511         trace_ppc_excp_print("FIT");
512         break;
513     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
514         trace_ppc_excp_print("WDT");
515         break;
516     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
517     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
518         break;
519     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
520         trace_ppc_excp_print("PIT");
521         break;
522     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
523         cpu_abort(cs, "%s exception not implemented\n",
524                   powerpc_excp_name(excp));
525         break;
526     default:
527         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
528         break;
529     }
530 
531     /* Sanity check */
532     if (!(env->msr_mask & MSR_HVB)) {
533         if (new_msr & MSR_HVB) {
534             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
535                       "no HV support\n", excp);
536         }
537         if (srr0 == SPR_HSRR0) {
538             cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
539                       "no HV support\n", excp);
540         }
541     }
542 
543     /* Save PC */
544     env->spr[srr0] = env->nip;
545 
546     /* Save MSR */
547     env->spr[srr1] = msr;
548 
549     powerpc_set_excp_state(cpu, vector, new_msr);
550 }
551 
552 static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
553 {
554     CPUState *cs = CPU(cpu);
555     CPUPPCState *env = &cpu->env;
556     target_ulong msr, new_msr, vector;
557 
558     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
559         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
560     }
561 
562     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
563                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
564                   excp, env->error_code);
565 
566     /* new srr1 value excluding must-be-zero bits */
567     msr = env->msr & ~0x783f0000ULL;
568 
569     /*
570      * new interrupt handler msr preserves existing ME unless
571      * explicitly overriden
572      */
573     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
574 
575     /*
576      * Hypervisor emulation assistance interrupt only exists on server
577      * arch 2.05 server or later.
578      */
579     if (excp == POWERPC_EXCP_HV_EMU) {
580         excp = POWERPC_EXCP_PROGRAM;
581     }
582 
583     vector = env->excp_vectors[excp];
584     if (vector == (target_ulong)-1ULL) {
585         cpu_abort(cs, "Raised an exception without defined vector %d\n",
586                   excp);
587     }
588 
589     vector |= env->excp_prefix;
590 
591     switch (excp) {
592     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
593         break;
594     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
595         if (msr_me == 0) {
596             /*
597              * Machine check exception is not enabled.  Enter
598              * checkstop state.
599              */
600             fprintf(stderr, "Machine check while not allowed. "
601                     "Entering checkstop state\n");
602             if (qemu_log_separate()) {
603                 qemu_log("Machine check while not allowed. "
604                         "Entering checkstop state\n");
605             }
606             cs->halted = 1;
607             cpu_interrupt_exittb(cs);
608         }
609 
610         /* machine check exceptions don't have ME set */
611         new_msr &= ~((target_ulong)1 << MSR_ME);
612 
613         break;
614     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
615         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
616         break;
617     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
618         trace_ppc_excp_isi(msr, env->nip);
619         msr |= env->error_code;
620         break;
621     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
622         break;
623     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
624         /* Get rS/rD and rA from faulting opcode */
625         /*
626          * Note: the opcode fields will not be set properly for a
627          * direct store load/store, but nobody cares as nobody
628          * actually uses direct store segments.
629          */
630         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
631         break;
632     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
633         switch (env->error_code & ~0xF) {
634         case POWERPC_EXCP_FP:
635             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
636                 trace_ppc_excp_fp_ignore();
637                 cs->exception_index = POWERPC_EXCP_NONE;
638                 env->error_code = 0;
639                 return;
640             }
641 
642             /*
643              * FP exceptions always have NIP pointing to the faulting
644              * instruction, so always use store_next and claim we are
645              * precise in the MSR.
646              */
647             msr |= 0x00100000;
648             break;
649         case POWERPC_EXCP_INVAL:
650             trace_ppc_excp_inval(env->nip);
651             msr |= 0x00080000;
652             break;
653         case POWERPC_EXCP_PRIV:
654             msr |= 0x00040000;
655             break;
656         case POWERPC_EXCP_TRAP:
657             msr |= 0x00020000;
658             break;
659         default:
660             /* Should never occur */
661             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
662                       env->error_code);
663             break;
664         }
665         break;
666     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
667         dump_syscall(env);
668 
669         /*
670          * We need to correct the NIP which in this case is supposed
671          * to point to the next instruction
672          */
673         env->nip += 4;
674         break;
675     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
676     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
677         break;
678     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
679     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
680         break;
681     case POWERPC_EXCP_RESET:     /* System reset exception                   */
682         if (msr_pow) {
683             cpu_abort(cs, "Trying to deliver power-saving system reset "
684                       "exception %d with no HV support\n", excp);
685         }
686         break;
687     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
688         break;
689     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
690     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
691     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
692         /* Swap temporary saved registers with GPRs */
693         if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
694             new_msr |= (target_ulong)1 << MSR_TGPR;
695             hreg_swap_gpr_tgpr(env);
696         }
697 
698         ppc_excp_debug_sw_tlb(env, excp);
699 
700         msr |= env->crf[0] << 28;
701         msr |= env->error_code; /* key, D/I, S/L bits */
702         /* Set way using a LRU mechanism */
703         msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
704         break;
705     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
706     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
707     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
708     case POWERPC_EXCP_SMI:       /* System management interrupt              */
709     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
710     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
711         cpu_abort(cs, "%s exception not implemented\n",
712                   powerpc_excp_name(excp));
713         break;
714     default:
715         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
716         break;
717     }
718 
719     /* Sanity check */
720     if (!(env->msr_mask & MSR_HVB)) {
721         if (new_msr & MSR_HVB) {
722             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
723                       "no HV support\n", excp);
724         }
725     }
726 
727     /*
728      * Sort out endianness of interrupt, this differs depending on the
729      * CPU, the HV mode, etc...
730      */
731     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
732         new_msr |= (target_ulong)1 << MSR_LE;
733     }
734 
735     /* Save PC */
736     env->spr[SPR_SRR0] = env->nip;
737 
738     /* Save MSR */
739     env->spr[SPR_SRR1] = msr;
740 
741     powerpc_set_excp_state(cpu, vector, new_msr);
742 }
743 
744 static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
745 {
746     CPUState *cs = CPU(cpu);
747     CPUPPCState *env = &cpu->env;
748     target_ulong msr, new_msr, vector;
749 
750     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
751         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
752     }
753 
754     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
755                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
756                   excp, env->error_code);
757 
758     /* new srr1 value excluding must-be-zero bits */
759     msr = env->msr & ~0x783f0000ULL;
760 
761     /*
762      * new interrupt handler msr preserves existing ME unless
763      * explicitly overriden
764      */
765     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
766 
767     /*
768      * Hypervisor emulation assistance interrupt only exists on server
769      * arch 2.05 server or later.
770      */
771     if (excp == POWERPC_EXCP_HV_EMU) {
772         excp = POWERPC_EXCP_PROGRAM;
773     }
774 
775     vector = env->excp_vectors[excp];
776     if (vector == (target_ulong)-1ULL) {
777         cpu_abort(cs, "Raised an exception without defined vector %d\n",
778                   excp);
779     }
780 
781     vector |= env->excp_prefix;
782 
783     switch (excp) {
784     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
785         if (msr_me == 0) {
786             /*
787              * Machine check exception is not enabled.  Enter
788              * checkstop state.
789              */
790             fprintf(stderr, "Machine check while not allowed. "
791                     "Entering checkstop state\n");
792             if (qemu_log_separate()) {
793                 qemu_log("Machine check while not allowed. "
794                         "Entering checkstop state\n");
795             }
796             cs->halted = 1;
797             cpu_interrupt_exittb(cs);
798         }
799 
800         /* machine check exceptions don't have ME set */
801         new_msr &= ~((target_ulong)1 << MSR_ME);
802 
803         break;
804     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
805         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
806         break;
807     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
808         trace_ppc_excp_isi(msr, env->nip);
809         msr |= env->error_code;
810         break;
811     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
812         break;
813     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
814         /* Get rS/rD and rA from faulting opcode */
815         /*
816          * Note: the opcode fields will not be set properly for a
817          * direct store load/store, but nobody cares as nobody
818          * actually uses direct store segments.
819          */
820         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
821         break;
822     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
823         switch (env->error_code & ~0xF) {
824         case POWERPC_EXCP_FP:
825             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
826                 trace_ppc_excp_fp_ignore();
827                 cs->exception_index = POWERPC_EXCP_NONE;
828                 env->error_code = 0;
829                 return;
830             }
831 
832             /*
833              * FP exceptions always have NIP pointing to the faulting
834              * instruction, so always use store_next and claim we are
835              * precise in the MSR.
836              */
837             msr |= 0x00100000;
838             break;
839         case POWERPC_EXCP_INVAL:
840             trace_ppc_excp_inval(env->nip);
841             msr |= 0x00080000;
842             break;
843         case POWERPC_EXCP_PRIV:
844             msr |= 0x00040000;
845             break;
846         case POWERPC_EXCP_TRAP:
847             msr |= 0x00020000;
848             break;
849         default:
850             /* Should never occur */
851             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
852                       env->error_code);
853             break;
854         }
855         break;
856     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
857     {
858         int lev = env->error_code;
859 
860         if ((lev == 1) && cpu->vhyp) {
861             dump_hcall(env);
862         } else {
863             dump_syscall(env);
864         }
865 
866         /*
867          * We need to correct the NIP which in this case is supposed
868          * to point to the next instruction
869          */
870         env->nip += 4;
871 
872         /*
873          * The Virtual Open Firmware (VOF) relies on the 'sc 1'
874          * instruction to communicate with QEMU. The pegasos2 machine
875          * uses VOF and the 74xx CPUs, so although the 74xx don't have
876          * HV mode, we need to keep hypercall support.
877          */
878         if ((lev == 1) && cpu->vhyp) {
879             PPCVirtualHypervisorClass *vhc =
880                 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
881             vhc->hypercall(cpu->vhyp, cpu);
882             return;
883         }
884 
885         break;
886     }
887     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
888     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
889         break;
890     case POWERPC_EXCP_RESET:     /* System reset exception                   */
891         if (msr_pow) {
892             cpu_abort(cs, "Trying to deliver power-saving system reset "
893                       "exception %d with no HV support\n", excp);
894         }
895         break;
896     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
897         break;
898     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
899         break;
900     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
901     case POWERPC_EXCP_SMI:       /* System management interrupt              */
902     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
903     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
904     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
905         cpu_abort(cs, "%s exception not implemented\n",
906                   powerpc_excp_name(excp));
907         break;
908     default:
909         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
910         break;
911     }
912 
913     /* Sanity check */
914     if (!(env->msr_mask & MSR_HVB)) {
915         if (new_msr & MSR_HVB) {
916             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
917                       "no HV support\n", excp);
918         }
919     }
920 
921     /*
922      * Sort out endianness of interrupt, this differs depending on the
923      * CPU, the HV mode, etc...
924      */
925     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
926         new_msr |= (target_ulong)1 << MSR_LE;
927     }
928 
929     /* Save PC */
930     env->spr[SPR_SRR0] = env->nip;
931 
932     /* Save MSR */
933     env->spr[SPR_SRR1] = msr;
934 
935     powerpc_set_excp_state(cpu, vector, new_msr);
936 }
937 
938 static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
939 {
940     CPUState *cs = CPU(cpu);
941     CPUPPCState *env = &cpu->env;
942     target_ulong msr, new_msr, vector;
943     int srr0, srr1;
944 
945     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
946         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
947     }
948 
949     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
950                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
951                   excp, env->error_code);
952 
953     msr = env->msr;
954 
955     /*
956      * new interrupt handler msr preserves existing ME unless
957      * explicitly overriden
958      */
959     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
960 
961     /* target registers */
962     srr0 = SPR_SRR0;
963     srr1 = SPR_SRR1;
964 
965     /*
966      * Hypervisor emulation assistance interrupt only exists on server
967      * arch 2.05 server or later.
968      */
969     if (excp == POWERPC_EXCP_HV_EMU) {
970         excp = POWERPC_EXCP_PROGRAM;
971     }
972 
973 #ifdef TARGET_PPC64
974     /*
975      * SPEU and VPU share the same IVOR but they exist in different
976      * processors. SPEU is e500v1/2 only and VPU is e6500 only.
977      */
978     if (excp == POWERPC_EXCP_VPU) {
979         excp = POWERPC_EXCP_SPEU;
980     }
981 #endif
982 
983     vector = env->excp_vectors[excp];
984     if (vector == (target_ulong)-1ULL) {
985         cpu_abort(cs, "Raised an exception without defined vector %d\n",
986                   excp);
987     }
988 
989     vector |= env->excp_prefix;
990 
991     switch (excp) {
992     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
993         srr0 = SPR_BOOKE_CSRR0;
994         srr1 = SPR_BOOKE_CSRR1;
995         break;
996     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
997         if (msr_me == 0) {
998             /*
999              * Machine check exception is not enabled.  Enter
1000              * checkstop state.
1001              */
1002             fprintf(stderr, "Machine check while not allowed. "
1003                     "Entering checkstop state\n");
1004             if (qemu_log_separate()) {
1005                 qemu_log("Machine check while not allowed. "
1006                         "Entering checkstop state\n");
1007             }
1008             cs->halted = 1;
1009             cpu_interrupt_exittb(cs);
1010         }
1011 
1012         /* machine check exceptions don't have ME set */
1013         new_msr &= ~((target_ulong)1 << MSR_ME);
1014 
1015         /* FIXME: choose one or the other based on CPU type */
1016         srr0 = SPR_BOOKE_MCSRR0;
1017         srr1 = SPR_BOOKE_MCSRR1;
1018 
1019         env->spr[SPR_BOOKE_CSRR0] = env->nip;
1020         env->spr[SPR_BOOKE_CSRR1] = msr;
1021 
1022         break;
1023     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1024         trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
1025         break;
1026     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1027         trace_ppc_excp_isi(msr, env->nip);
1028         break;
1029     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
1030         if (env->mpic_proxy) {
1031             /* IACK the IRQ on delivery */
1032             env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1033         }
1034         break;
1035     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
1036         break;
1037     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1038         switch (env->error_code & ~0xF) {
1039         case POWERPC_EXCP_FP:
1040             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1041                 trace_ppc_excp_fp_ignore();
1042                 cs->exception_index = POWERPC_EXCP_NONE;
1043                 env->error_code = 0;
1044                 return;
1045             }
1046 
1047             /*
1048              * FP exceptions always have NIP pointing to the faulting
1049              * instruction, so always use store_next and claim we are
1050              * precise in the MSR.
1051              */
1052             msr |= 0x00100000;
1053             env->spr[SPR_BOOKE_ESR] = ESR_FP;
1054             break;
1055         case POWERPC_EXCP_INVAL:
1056             trace_ppc_excp_inval(env->nip);
1057             msr |= 0x00080000;
1058             env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1059             break;
1060         case POWERPC_EXCP_PRIV:
1061             msr |= 0x00040000;
1062             env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1063             break;
1064         case POWERPC_EXCP_TRAP:
1065             msr |= 0x00020000;
1066             env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1067             break;
1068         default:
1069             /* Should never occur */
1070             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1071                       env->error_code);
1072             break;
1073         }
1074         break;
1075     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1076         dump_syscall(env);
1077 
1078         /*
1079          * We need to correct the NIP which in this case is supposed
1080          * to point to the next instruction
1081          */
1082         env->nip += 4;
1083         break;
1084     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
1085     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
1086     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
1087         break;
1088     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
1089         /* FIT on 4xx */
1090         trace_ppc_excp_print("FIT");
1091         break;
1092     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
1093         trace_ppc_excp_print("WDT");
1094         srr0 = SPR_BOOKE_CSRR0;
1095         srr1 = SPR_BOOKE_CSRR1;
1096         break;
1097     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
1098     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
1099         break;
1100     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
1101         if (env->flags & POWERPC_FLAG_DE) {
1102             /* FIXME: choose one or the other based on CPU type */
1103             srr0 = SPR_BOOKE_DSRR0;
1104             srr1 = SPR_BOOKE_DSRR1;
1105 
1106             env->spr[SPR_BOOKE_CSRR0] = env->nip;
1107             env->spr[SPR_BOOKE_CSRR1] = msr;
1108 
1109             /* DBSR already modified by caller */
1110         } else {
1111             cpu_abort(cs, "Debug exception triggered on unsupported model\n");
1112         }
1113         break;
1114     case POWERPC_EXCP_SPEU:   /* SPE/embedded floating-point unavailable/VPU  */
1115         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1116         break;
1117     case POWERPC_EXCP_RESET:     /* System reset exception                   */
1118         if (msr_pow) {
1119             cpu_abort(cs, "Trying to deliver power-saving system reset "
1120                       "exception %d with no HV support\n", excp);
1121         }
1122         break;
1123     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
1124     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
1125         cpu_abort(cs, "%s exception not implemented\n",
1126                   powerpc_excp_name(excp));
1127         break;
1128     default:
1129         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1130         break;
1131     }
1132 
1133     /* Sanity check */
1134     if (!(env->msr_mask & MSR_HVB)) {
1135         if (new_msr & MSR_HVB) {
1136             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
1137                       "no HV support\n", excp);
1138         }
1139         if (srr0 == SPR_HSRR0) {
1140             cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1141                       "no HV support\n", excp);
1142         }
1143     }
1144 
1145 #if defined(TARGET_PPC64)
1146     if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1147         /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
1148         new_msr |= (target_ulong)1 << MSR_CM;
1149     } else {
1150         vector = (uint32_t)vector;
1151     }
1152 #endif
1153 
1154     /* Save PC */
1155     env->spr[srr0] = env->nip;
1156 
1157     /* Save MSR */
1158     env->spr[srr1] = msr;
1159 
1160     powerpc_set_excp_state(cpu, vector, new_msr);
1161 }
1162 
1163 #ifdef TARGET_PPC64
1164 static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1165 {
1166     CPUState *cs = CPU(cpu);
1167     CPUPPCState *env = &cpu->env;
1168     int excp_model = env->excp_model;
1169     target_ulong msr, new_msr, vector;
1170     int srr0, srr1, lev = -1;
1171 
1172     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1173         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1174     }
1175 
1176     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1177                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1178                   excp, env->error_code);
1179 
1180     /* new srr1 value excluding must-be-zero bits */
1181     msr = env->msr & ~0x783f0000ULL;
1182 
1183     /*
1184      * new interrupt handler msr preserves existing HV and ME unless
1185      * explicitly overriden
1186      */
1187     new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1188 
1189     /* target registers */
1190     srr0 = SPR_SRR0;
1191     srr1 = SPR_SRR1;
1192 
1193     /*
1194      * check for special resume at 0x100 from doze/nap/sleep/winkle on
1195      * P7/P8/P9
1196      */
1197     if (env->resume_as_sreset) {
1198         excp = powerpc_reset_wakeup(cs, env, excp, &msr);
1199     }
1200 
1201     /*
1202      * We don't want to generate a Hypervisor Emulation Assistance
1203      * Interrupt if we don't have HVB in msr_mask (PAPR mode).
1204      */
1205     if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) {
1206         excp = POWERPC_EXCP_PROGRAM;
1207     }
1208 
1209     vector = env->excp_vectors[excp];
1210     if (vector == (target_ulong)-1ULL) {
1211         cpu_abort(cs, "Raised an exception without defined vector %d\n",
1212                   excp);
1213     }
1214 
1215     vector |= env->excp_prefix;
1216 
1217     switch (excp) {
1218     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
1219         if (msr_me == 0) {
1220             /*
1221              * Machine check exception is not enabled.  Enter
1222              * checkstop state.
1223              */
1224             fprintf(stderr, "Machine check while not allowed. "
1225                     "Entering checkstop state\n");
1226             if (qemu_log_separate()) {
1227                 qemu_log("Machine check while not allowed. "
1228                         "Entering checkstop state\n");
1229             }
1230             cs->halted = 1;
1231             cpu_interrupt_exittb(cs);
1232         }
1233         if (env->msr_mask & MSR_HVB) {
1234             /*
1235              * ISA specifies HV, but can be delivered to guest with HV
1236              * clear (e.g., see FWNMI in PAPR).
1237              */
1238             new_msr |= (target_ulong)MSR_HVB;
1239         }
1240 
1241         /* machine check exceptions don't have ME set */
1242         new_msr &= ~((target_ulong)1 << MSR_ME);
1243 
1244         break;
1245     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1246         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1247         break;
1248     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1249         trace_ppc_excp_isi(msr, env->nip);
1250         msr |= env->error_code;
1251         break;
1252     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
1253     {
1254         bool lpes0;
1255 
1256         /*
1257          * LPES0 is only taken into consideration if we support HV
1258          * mode for this CPU.
1259          */
1260         if (!env->has_hv_mode) {
1261             break;
1262         }
1263 
1264         lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1265 
1266         if (!lpes0) {
1267             new_msr |= (target_ulong)MSR_HVB;
1268             new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1269             srr0 = SPR_HSRR0;
1270             srr1 = SPR_HSRR1;
1271         }
1272 
1273         break;
1274     }
1275     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
1276         /* Get rS/rD and rA from faulting opcode */
1277         /*
1278          * Note: the opcode fields will not be set properly for a
1279          * direct store load/store, but nobody cares as nobody
1280          * actually uses direct store segments.
1281          */
1282         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1283         break;
1284     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1285         switch (env->error_code & ~0xF) {
1286         case POWERPC_EXCP_FP:
1287             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1288                 trace_ppc_excp_fp_ignore();
1289                 cs->exception_index = POWERPC_EXCP_NONE;
1290                 env->error_code = 0;
1291                 return;
1292             }
1293 
1294             /*
1295              * FP exceptions always have NIP pointing to the faulting
1296              * instruction, so always use store_next and claim we are
1297              * precise in the MSR.
1298              */
1299             msr |= 0x00100000;
1300             break;
1301         case POWERPC_EXCP_INVAL:
1302             trace_ppc_excp_inval(env->nip);
1303             msr |= 0x00080000;
1304             break;
1305         case POWERPC_EXCP_PRIV:
1306             msr |= 0x00040000;
1307             break;
1308         case POWERPC_EXCP_TRAP:
1309             msr |= 0x00020000;
1310             break;
1311         default:
1312             /* Should never occur */
1313             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1314                       env->error_code);
1315             break;
1316         }
1317         break;
1318     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1319         lev = env->error_code;
1320 
1321         if ((lev == 1) && cpu->vhyp) {
1322             dump_hcall(env);
1323         } else {
1324             dump_syscall(env);
1325         }
1326 
1327         /*
1328          * We need to correct the NIP which in this case is supposed
1329          * to point to the next instruction
1330          */
1331         env->nip += 4;
1332 
1333         /* "PAPR mode" built-in hypercall emulation */
1334         if ((lev == 1) && cpu->vhyp) {
1335             PPCVirtualHypervisorClass *vhc =
1336                 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1337             vhc->hypercall(cpu->vhyp, cpu);
1338             return;
1339         }
1340         if (lev == 1) {
1341             new_msr |= (target_ulong)MSR_HVB;
1342         }
1343         break;
1344     case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception                     */
1345         lev = env->error_code;
1346         dump_syscall(env);
1347         env->nip += 4;
1348         new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1349         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1350 
1351         vector += lev * 0x20;
1352 
1353         env->lr = env->nip;
1354         env->ctr = msr;
1355         break;
1356     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
1357     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
1358         break;
1359     case POWERPC_EXCP_RESET:     /* System reset exception                   */
1360         /* A power-saving exception sets ME, otherwise it is unchanged */
1361         if (msr_pow) {
1362             /* indicate that we resumed from power save mode */
1363             msr |= 0x10000;
1364             new_msr |= ((target_ulong)1 << MSR_ME);
1365         }
1366         if (env->msr_mask & MSR_HVB) {
1367             /*
1368              * ISA specifies HV, but can be delivered to guest with HV
1369              * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
1370              */
1371             new_msr |= (target_ulong)MSR_HVB;
1372         } else {
1373             if (msr_pow) {
1374                 cpu_abort(cs, "Trying to deliver power-saving system reset "
1375                           "exception %d with no HV support\n", excp);
1376             }
1377         }
1378         break;
1379     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
1380     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
1381     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
1382         break;
1383     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
1384         msr |= env->error_code;
1385         /* fall through */
1386     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
1387     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
1388     case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
1389     case POWERPC_EXCP_HV_EMU:
1390     case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
1391         srr0 = SPR_HSRR0;
1392         srr1 = SPR_HSRR1;
1393         new_msr |= (target_ulong)MSR_HVB;
1394         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1395         break;
1396     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
1397     case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               */
1398     case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
1399         env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1400         break;
1401     case POWERPC_EXCP_HV_FU:     /* Hypervisor Facility Unavailable Exception */
1402         env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1403         srr0 = SPR_HSRR0;
1404         srr1 = SPR_HSRR1;
1405         new_msr |= (target_ulong)MSR_HVB;
1406         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1407         break;
1408     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
1409     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
1410     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
1411     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
1412     case POWERPC_EXCP_SDOOR:     /* Doorbell interrupt                       */
1413     case POWERPC_EXCP_HV_MAINT:  /* Hypervisor Maintenance exception         */
1414         cpu_abort(cs, "%s exception not implemented\n",
1415                   powerpc_excp_name(excp));
1416         break;
1417     default:
1418         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1419         break;
1420     }
1421 
1422     /* Sanity check */
1423     if (!(env->msr_mask & MSR_HVB)) {
1424         if (new_msr & MSR_HVB) {
1425             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
1426                       "no HV support\n", excp);
1427         }
1428         if (srr0 == SPR_HSRR0) {
1429             cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1430                       "no HV support\n", excp);
1431         }
1432     }
1433 
1434     /*
1435      * Sort out endianness of interrupt, this differs depending on the
1436      * CPU, the HV mode, etc...
1437      */
1438     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1439         new_msr |= (target_ulong)1 << MSR_LE;
1440     }
1441 
1442     new_msr |= (target_ulong)1 << MSR_SF;
1443 
1444     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1445         /* Save PC */
1446         env->spr[srr0] = env->nip;
1447 
1448         /* Save MSR */
1449         env->spr[srr1] = msr;
1450     }
1451 
1452     /* This can update new_msr and vector if AIL applies */
1453     ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
1454 
1455     powerpc_set_excp_state(cpu, vector, new_msr);
1456 }
1457 #else
1458 static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1459 {
1460     g_assert_not_reached();
1461 }
1462 #endif
1463 
1464 /*
1465  * Note that this function should be greatly optimized when called
1466  * with a constant excp, from ppc_hw_interrupt
1467  */
1468 static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
1469 {
1470     CPUState *cs = CPU(cpu);
1471     CPUPPCState *env = &cpu->env;
1472     int excp_model = env->excp_model;
1473     target_ulong msr, new_msr, vector;
1474     int srr0, srr1, lev = -1;
1475 
1476     if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1477         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1478     }
1479 
1480     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1481                   " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1482                   excp, env->error_code);
1483 
1484     /* new srr1 value excluding must-be-zero bits */
1485     if (excp_model == POWERPC_EXCP_BOOKE) {
1486         msr = env->msr;
1487     } else {
1488         msr = env->msr & ~0x783f0000ULL;
1489     }
1490 
1491     /*
1492      * new interrupt handler msr preserves existing HV and ME unless
1493      * explicitly overriden
1494      */
1495     new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1496 
1497     /* target registers */
1498     srr0 = SPR_SRR0;
1499     srr1 = SPR_SRR1;
1500 
1501     /*
1502      * check for special resume at 0x100 from doze/nap/sleep/winkle on
1503      * P7/P8/P9
1504      */
1505     if (env->resume_as_sreset) {
1506         excp = powerpc_reset_wakeup(cs, env, excp, &msr);
1507     }
1508 
1509     /*
1510      * Hypervisor emulation assistance interrupt only exists on server
1511      * arch 2.05 server or later. We also don't want to generate it if
1512      * we don't have HVB in msr_mask (PAPR mode).
1513      */
1514     if (excp == POWERPC_EXCP_HV_EMU
1515 #if defined(TARGET_PPC64)
1516         && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB))
1517 #endif /* defined(TARGET_PPC64) */
1518 
1519     ) {
1520         excp = POWERPC_EXCP_PROGRAM;
1521     }
1522 
1523 #ifdef TARGET_PPC64
1524     /*
1525      * SPEU and VPU share the same IVOR but they exist in different
1526      * processors. SPEU is e500v1/2 only and VPU is e6500 only.
1527      */
1528     if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) {
1529         excp = POWERPC_EXCP_SPEU;
1530     }
1531 #endif
1532 
1533     vector = env->excp_vectors[excp];
1534     if (vector == (target_ulong)-1ULL) {
1535         cpu_abort(cs, "Raised an exception without defined vector %d\n",
1536                   excp);
1537     }
1538 
1539     vector |= env->excp_prefix;
1540 
1541     switch (excp) {
1542     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
1543         switch (excp_model) {
1544         case POWERPC_EXCP_40x:
1545             srr0 = SPR_40x_SRR2;
1546             srr1 = SPR_40x_SRR3;
1547             break;
1548         case POWERPC_EXCP_BOOKE:
1549             srr0 = SPR_BOOKE_CSRR0;
1550             srr1 = SPR_BOOKE_CSRR1;
1551             break;
1552         case POWERPC_EXCP_6xx:
1553             break;
1554         default:
1555             goto excp_invalid;
1556         }
1557         break;
1558     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
1559         if (msr_me == 0) {
1560             /*
1561              * Machine check exception is not enabled.  Enter
1562              * checkstop state.
1563              */
1564             fprintf(stderr, "Machine check while not allowed. "
1565                     "Entering checkstop state\n");
1566             if (qemu_log_separate()) {
1567                 qemu_log("Machine check while not allowed. "
1568                         "Entering checkstop state\n");
1569             }
1570             cs->halted = 1;
1571             cpu_interrupt_exittb(cs);
1572         }
1573         if (env->msr_mask & MSR_HVB) {
1574             /*
1575              * ISA specifies HV, but can be delivered to guest with HV
1576              * clear (e.g., see FWNMI in PAPR).
1577              */
1578             new_msr |= (target_ulong)MSR_HVB;
1579         }
1580 
1581         /* machine check exceptions don't have ME set */
1582         new_msr &= ~((target_ulong)1 << MSR_ME);
1583 
1584         /* XXX: should also have something loaded in DAR / DSISR */
1585         switch (excp_model) {
1586         case POWERPC_EXCP_40x:
1587             srr0 = SPR_40x_SRR2;
1588             srr1 = SPR_40x_SRR3;
1589             break;
1590         case POWERPC_EXCP_BOOKE:
1591             /* FIXME: choose one or the other based on CPU type */
1592             srr0 = SPR_BOOKE_MCSRR0;
1593             srr1 = SPR_BOOKE_MCSRR1;
1594 
1595             env->spr[SPR_BOOKE_CSRR0] = env->nip;
1596             env->spr[SPR_BOOKE_CSRR1] = msr;
1597             break;
1598         default:
1599             break;
1600         }
1601         break;
1602     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1603         trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1604         break;
1605     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1606         trace_ppc_excp_isi(msr, env->nip);
1607         msr |= env->error_code;
1608         break;
1609     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
1610     {
1611         bool lpes0;
1612 
1613         cs = CPU(cpu);
1614 
1615         /*
1616          * Exception targeting modifiers
1617          *
1618          * LPES0 is supported on POWER7/8/9
1619          * LPES1 is not supported (old iSeries mode)
1620          *
1621          * On anything else, we behave as if LPES0 is 1
1622          * (externals don't alter MSR:HV)
1623          */
1624 #if defined(TARGET_PPC64)
1625         if (excp_model == POWERPC_EXCP_POWER7 ||
1626             excp_model == POWERPC_EXCP_POWER8 ||
1627             excp_model == POWERPC_EXCP_POWER9 ||
1628             excp_model == POWERPC_EXCP_POWER10) {
1629             lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1630         } else
1631 #endif /* defined(TARGET_PPC64) */
1632         {
1633             lpes0 = true;
1634         }
1635 
1636         if (!lpes0) {
1637             new_msr |= (target_ulong)MSR_HVB;
1638             new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1639             srr0 = SPR_HSRR0;
1640             srr1 = SPR_HSRR1;
1641         }
1642         if (env->mpic_proxy) {
1643             /* IACK the IRQ on delivery */
1644             env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1645         }
1646         break;
1647     }
1648     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
1649         /* Get rS/rD and rA from faulting opcode */
1650         /*
1651          * Note: the opcode fields will not be set properly for a
1652          * direct store load/store, but nobody cares as nobody
1653          * actually uses direct store segments.
1654          */
1655         env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1656         break;
1657     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1658         switch (env->error_code & ~0xF) {
1659         case POWERPC_EXCP_FP:
1660             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1661                 trace_ppc_excp_fp_ignore();
1662                 cs->exception_index = POWERPC_EXCP_NONE;
1663                 env->error_code = 0;
1664                 return;
1665             }
1666 
1667             /*
1668              * FP exceptions always have NIP pointing to the faulting
1669              * instruction, so always use store_next and claim we are
1670              * precise in the MSR.
1671              */
1672             msr |= 0x00100000;
1673             env->spr[SPR_BOOKE_ESR] = ESR_FP;
1674             break;
1675         case POWERPC_EXCP_INVAL:
1676             trace_ppc_excp_inval(env->nip);
1677             msr |= 0x00080000;
1678             env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1679             break;
1680         case POWERPC_EXCP_PRIV:
1681             msr |= 0x00040000;
1682             env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1683             break;
1684         case POWERPC_EXCP_TRAP:
1685             msr |= 0x00020000;
1686             env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1687             break;
1688         default:
1689             /* Should never occur */
1690             cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1691                       env->error_code);
1692             break;
1693         }
1694         break;
1695     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1696         lev = env->error_code;
1697 
1698         if ((lev == 1) && cpu->vhyp) {
1699             dump_hcall(env);
1700         } else {
1701             dump_syscall(env);
1702         }
1703 
1704         /*
1705          * We need to correct the NIP which in this case is supposed
1706          * to point to the next instruction
1707          */
1708         env->nip += 4;
1709 
1710         /* "PAPR mode" built-in hypercall emulation */
1711         if ((lev == 1) && cpu->vhyp) {
1712             PPCVirtualHypervisorClass *vhc =
1713                 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1714             vhc->hypercall(cpu->vhyp, cpu);
1715             return;
1716         }
1717         if (lev == 1) {
1718             new_msr |= (target_ulong)MSR_HVB;
1719         }
1720         break;
1721     case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception                     */
1722         lev = env->error_code;
1723         dump_syscall(env);
1724         env->nip += 4;
1725         new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1726         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1727 
1728         vector += lev * 0x20;
1729 
1730         env->lr = env->nip;
1731         env->ctr = msr;
1732         break;
1733     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
1734     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
1735     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
1736         break;
1737     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
1738         /* FIT on 4xx */
1739         trace_ppc_excp_print("FIT");
1740         break;
1741     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
1742         trace_ppc_excp_print("WDT");
1743         switch (excp_model) {
1744         case POWERPC_EXCP_BOOKE:
1745             srr0 = SPR_BOOKE_CSRR0;
1746             srr1 = SPR_BOOKE_CSRR1;
1747             break;
1748         default:
1749             break;
1750         }
1751         break;
1752     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
1753     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
1754         break;
1755     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
1756         if (env->flags & POWERPC_FLAG_DE) {
1757             /* FIXME: choose one or the other based on CPU type */
1758             srr0 = SPR_BOOKE_DSRR0;
1759             srr1 = SPR_BOOKE_DSRR1;
1760 
1761             env->spr[SPR_BOOKE_CSRR0] = env->nip;
1762             env->spr[SPR_BOOKE_CSRR1] = msr;
1763 
1764             /* DBSR already modified by caller */
1765         } else {
1766             cpu_abort(cs, "Debug exception triggered on unsupported model\n");
1767         }
1768         break;
1769     case POWERPC_EXCP_SPEU:   /* SPE/embedded floating-point unavailable/VPU  */
1770         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1771         break;
1772     case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
1773         break;
1774     case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
1775         srr0 = SPR_BOOKE_CSRR0;
1776         srr1 = SPR_BOOKE_CSRR1;
1777         break;
1778     case POWERPC_EXCP_RESET:     /* System reset exception                   */
1779         /* A power-saving exception sets ME, otherwise it is unchanged */
1780         if (msr_pow) {
1781             /* indicate that we resumed from power save mode */
1782             msr |= 0x10000;
1783             new_msr |= ((target_ulong)1 << MSR_ME);
1784         }
1785         if (env->msr_mask & MSR_HVB) {
1786             /*
1787              * ISA specifies HV, but can be delivered to guest with HV
1788              * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
1789              */
1790             new_msr |= (target_ulong)MSR_HVB;
1791         } else {
1792             if (msr_pow) {
1793                 cpu_abort(cs, "Trying to deliver power-saving system reset "
1794                           "exception %d with no HV support\n", excp);
1795             }
1796         }
1797         break;
1798     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
1799     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
1800     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
1801         break;
1802     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
1803         msr |= env->error_code;
1804         /* fall through */
1805     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
1806     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
1807     case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
1808     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
1809     case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
1810     case POWERPC_EXCP_HV_EMU:
1811     case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
1812         srr0 = SPR_HSRR0;
1813         srr1 = SPR_HSRR1;
1814         new_msr |= (target_ulong)MSR_HVB;
1815         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1816         break;
1817     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
1818     case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               */
1819     case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
1820 #ifdef TARGET_PPC64
1821         env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1822 #endif
1823         break;
1824     case POWERPC_EXCP_HV_FU:     /* Hypervisor Facility Unavailable Exception */
1825 #ifdef TARGET_PPC64
1826         env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1827         srr0 = SPR_HSRR0;
1828         srr1 = SPR_HSRR1;
1829         new_msr |= (target_ulong)MSR_HVB;
1830         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1831 #endif
1832         break;
1833     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
1834         trace_ppc_excp_print("PIT");
1835         break;
1836     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
1837     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
1838     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
1839         switch (excp_model) {
1840         case POWERPC_EXCP_6xx:
1841             /* Swap temporary saved registers with GPRs */
1842             if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
1843                 new_msr |= (target_ulong)1 << MSR_TGPR;
1844                 hreg_swap_gpr_tgpr(env);
1845             }
1846             /* fall through */
1847         case POWERPC_EXCP_7x5:
1848             ppc_excp_debug_sw_tlb(env, excp);
1849 
1850             msr |= env->crf[0] << 28;
1851             msr |= env->error_code; /* key, D/I, S/L bits */
1852             /* Set way using a LRU mechanism */
1853             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
1854             break;
1855         default:
1856             cpu_abort(cs, "Invalid TLB miss exception\n");
1857             break;
1858         }
1859         break;
1860     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
1861     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
1862     case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
1863     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
1864     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
1865     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
1866     case POWERPC_EXCP_SMI:       /* System management interrupt              */
1867     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
1868     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
1869     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
1870     case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
1871     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
1872     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
1873     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
1874         cpu_abort(cs, "%s exception not implemented\n",
1875                   powerpc_excp_name(excp));
1876         break;
1877     default:
1878     excp_invalid:
1879         cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1880         break;
1881     }
1882 
1883     /* Sanity check */
1884     if (!(env->msr_mask & MSR_HVB)) {
1885         if (new_msr & MSR_HVB) {
1886             cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
1887                       "no HV support\n", excp);
1888         }
1889         if (srr0 == SPR_HSRR0) {
1890             cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1891                       "no HV support\n", excp);
1892         }
1893     }
1894 
1895     /*
1896      * Sort out endianness of interrupt, this differs depending on the
1897      * CPU, the HV mode, etc...
1898      */
1899     if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1900         new_msr |= (target_ulong)1 << MSR_LE;
1901     }
1902 
1903 #if defined(TARGET_PPC64)
1904     if (excp_model == POWERPC_EXCP_BOOKE) {
1905         if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1906             /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
1907             new_msr |= (target_ulong)1 << MSR_CM;
1908         } else {
1909             vector = (uint32_t)vector;
1910         }
1911     } else {
1912         if (!msr_isf && !mmu_is_64bit(env->mmu_model)) {
1913             vector = (uint32_t)vector;
1914         } else {
1915             new_msr |= (target_ulong)1 << MSR_SF;
1916         }
1917     }
1918 #endif
1919 
1920     if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1921         /* Save PC */
1922         env->spr[srr0] = env->nip;
1923 
1924         /* Save MSR */
1925         env->spr[srr1] = msr;
1926     }
1927 
1928     /* This can update new_msr and vector if AIL applies */
1929     ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
1930 
1931     powerpc_set_excp_state(cpu, vector, new_msr);
1932 }
1933 
1934 static void powerpc_excp(PowerPCCPU *cpu, int excp)
1935 {
1936     CPUPPCState *env = &cpu->env;
1937 
1938     switch (env->excp_model) {
1939     case POWERPC_EXCP_40x:
1940         powerpc_excp_40x(cpu, excp);
1941         break;
1942     case POWERPC_EXCP_6xx:
1943         powerpc_excp_6xx(cpu, excp);
1944         break;
1945     case POWERPC_EXCP_74xx:
1946         powerpc_excp_74xx(cpu, excp);
1947         break;
1948     case POWERPC_EXCP_BOOKE:
1949         powerpc_excp_booke(cpu, excp);
1950         break;
1951     case POWERPC_EXCP_970:
1952     case POWERPC_EXCP_POWER7:
1953     case POWERPC_EXCP_POWER8:
1954     case POWERPC_EXCP_POWER9:
1955     case POWERPC_EXCP_POWER10:
1956         powerpc_excp_books(cpu, excp);
1957         break;
1958     default:
1959         powerpc_excp_legacy(cpu, excp);
1960     }
1961 }
1962 
1963 void ppc_cpu_do_interrupt(CPUState *cs)
1964 {
1965     PowerPCCPU *cpu = POWERPC_CPU(cs);
1966 
1967     powerpc_excp(cpu, cs->exception_index);
1968 }
1969 
1970 static void ppc_hw_interrupt(CPUPPCState *env)
1971 {
1972     PowerPCCPU *cpu = env_archcpu(env);
1973     bool async_deliver;
1974 
1975     /* External reset */
1976     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
1977         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
1978         powerpc_excp(cpu, POWERPC_EXCP_RESET);
1979         return;
1980     }
1981     /* Machine check exception */
1982     if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
1983         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
1984         powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
1985         return;
1986     }
1987 #if 0 /* TODO */
1988     /* External debug exception */
1989     if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
1990         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
1991         powerpc_excp(cpu, POWERPC_EXCP_DEBUG);
1992         return;
1993     }
1994 #endif
1995 
1996     /*
1997      * For interrupts that gate on MSR:EE, we need to do something a
1998      * bit more subtle, as we need to let them through even when EE is
1999      * clear when coming out of some power management states (in order
2000      * for them to become a 0x100).
2001      */
2002     async_deliver = (msr_ee != 0) || env->resume_as_sreset;
2003 
2004     /* Hypervisor decrementer exception */
2005     if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2006         /* LPCR will be clear when not supported so this will work */
2007         bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
2008         if ((async_deliver || msr_hv == 0) && hdice) {
2009             /* HDEC clears on delivery */
2010             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2011             powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2012             return;
2013         }
2014     }
2015 
2016     /* Hypervisor virtualization interrupt */
2017     if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
2018         /* LPCR will be clear when not supported so this will work */
2019         bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
2020         if ((async_deliver || msr_hv == 0) && hvice) {
2021             powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2022             return;
2023         }
2024     }
2025 
2026     /* External interrupt can ignore MSR:EE under some circumstances */
2027     if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2028         bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
2029         bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
2030         /* HEIC blocks delivery to the hypervisor */
2031         if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
2032             (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
2033             powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2034             return;
2035         }
2036     }
2037     if (msr_ce != 0) {
2038         /* External critical interrupt */
2039         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2040             powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
2041             return;
2042         }
2043     }
2044     if (async_deliver != 0) {
2045         /* Watchdog timer on embedded PowerPC */
2046         if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2047             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2048             powerpc_excp(cpu, POWERPC_EXCP_WDT);
2049             return;
2050         }
2051         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2052             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2053             powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
2054             return;
2055         }
2056         /* Fixed interval timer on embedded PowerPC */
2057         if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2058             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2059             powerpc_excp(cpu, POWERPC_EXCP_FIT);
2060             return;
2061         }
2062         /* Programmable interval timer on embedded PowerPC */
2063         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2064             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2065             powerpc_excp(cpu, POWERPC_EXCP_PIT);
2066             return;
2067         }
2068         /* Decrementer exception */
2069         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2070             if (ppc_decr_clear_on_delivery(env)) {
2071                 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2072             }
2073             powerpc_excp(cpu, POWERPC_EXCP_DECR);
2074             return;
2075         }
2076         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2077             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2078             if (is_book3s_arch2x(env)) {
2079                 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2080             } else {
2081                 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2082             }
2083             return;
2084         }
2085         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
2086             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
2087             powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2088             return;
2089         }
2090         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2091             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2092             powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2093             return;
2094         }
2095         /* Thermal interrupt */
2096         if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2097             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2098             powerpc_excp(cpu, POWERPC_EXCP_THERM);
2099             return;
2100         }
2101     }
2102 
2103     if (env->resume_as_sreset) {
2104         /*
2105          * This is a bug ! It means that has_work took us out of halt without
2106          * anything to deliver while in a PM state that requires getting
2107          * out via a 0x100
2108          *
2109          * This means we will incorrectly execute past the power management
2110          * instruction instead of triggering a reset.
2111          *
2112          * It generally means a discrepancy between the wakeup conditions in the
2113          * processor has_work implementation and the logic in this function.
2114          */
2115         cpu_abort(env_cpu(env),
2116                   "Wakeup from PM state but interrupt Undelivered");
2117     }
2118 }
2119 
2120 void ppc_cpu_do_system_reset(CPUState *cs)
2121 {
2122     PowerPCCPU *cpu = POWERPC_CPU(cs);
2123 
2124     powerpc_excp(cpu, POWERPC_EXCP_RESET);
2125 }
2126 
2127 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
2128 {
2129     PowerPCCPU *cpu = POWERPC_CPU(cs);
2130     CPUPPCState *env = &cpu->env;
2131     target_ulong msr = 0;
2132 
2133     /*
2134      * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
2135      * been set by KVM.
2136      */
2137     msr = (1ULL << MSR_ME);
2138     msr |= env->msr & (1ULL << MSR_SF);
2139     if (ppc_interrupts_little_endian(cpu, false)) {
2140         msr |= (1ULL << MSR_LE);
2141     }
2142 
2143     powerpc_set_excp_state(cpu, vector, msr);
2144 }
2145 
2146 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
2147 {
2148     PowerPCCPU *cpu = POWERPC_CPU(cs);
2149     CPUPPCState *env = &cpu->env;
2150 
2151     if (interrupt_request & CPU_INTERRUPT_HARD) {
2152         ppc_hw_interrupt(env);
2153         if (env->pending_interrupts == 0) {
2154             cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
2155         }
2156         return true;
2157     }
2158     return false;
2159 }
2160 
2161 #endif /* !CONFIG_USER_ONLY */
2162 
2163 /*****************************************************************************/
2164 /* Exceptions processing helpers */
2165 
2166 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
2167                             uint32_t error_code, uintptr_t raddr)
2168 {
2169     CPUState *cs = env_cpu(env);
2170 
2171     cs->exception_index = exception;
2172     env->error_code = error_code;
2173     cpu_loop_exit_restore(cs, raddr);
2174 }
2175 
2176 void raise_exception_err(CPUPPCState *env, uint32_t exception,
2177                          uint32_t error_code)
2178 {
2179     raise_exception_err_ra(env, exception, error_code, 0);
2180 }
2181 
2182 void raise_exception(CPUPPCState *env, uint32_t exception)
2183 {
2184     raise_exception_err_ra(env, exception, 0, 0);
2185 }
2186 
2187 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
2188                         uintptr_t raddr)
2189 {
2190     raise_exception_err_ra(env, exception, 0, raddr);
2191 }
2192 
2193 #ifdef CONFIG_TCG
2194 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
2195                                 uint32_t error_code)
2196 {
2197     raise_exception_err_ra(env, exception, error_code, 0);
2198 }
2199 
2200 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
2201 {
2202     raise_exception_err_ra(env, exception, 0, 0);
2203 }
2204 #endif
2205 
2206 #if !defined(CONFIG_USER_ONLY)
2207 #ifdef CONFIG_TCG
2208 void helper_store_msr(CPUPPCState *env, target_ulong val)
2209 {
2210     uint32_t excp = hreg_store_msr(env, val, 0);
2211 
2212     if (excp != 0) {
2213         CPUState *cs = env_cpu(env);
2214         cpu_interrupt_exittb(cs);
2215         raise_exception(env, excp);
2216     }
2217 }
2218 
2219 #if defined(TARGET_PPC64)
2220 void helper_scv(CPUPPCState *env, uint32_t lev)
2221 {
2222     if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
2223         raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
2224     } else {
2225         raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
2226     }
2227 }
2228 
2229 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
2230 {
2231     CPUState *cs;
2232 
2233     cs = env_cpu(env);
2234     cs->halted = 1;
2235 
2236     /* Condition for waking up at 0x100 */
2237     env->resume_as_sreset = (insn != PPC_PM_STOP) ||
2238         (env->spr[SPR_PSSCR] & PSSCR_EC);
2239 }
2240 #endif /* defined(TARGET_PPC64) */
2241 
2242 static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
2243 {
2244     CPUState *cs = env_cpu(env);
2245 
2246     /* MSR:POW cannot be set by any form of rfi */
2247     msr &= ~(1ULL << MSR_POW);
2248 
2249     /* MSR:TGPR cannot be set by any form of rfi */
2250     if (env->flags & POWERPC_FLAG_TGPR)
2251         msr &= ~(1ULL << MSR_TGPR);
2252 
2253 #if defined(TARGET_PPC64)
2254     /* Switching to 32-bit ? Crop the nip */
2255     if (!msr_is_64bit(env, msr)) {
2256         nip = (uint32_t)nip;
2257     }
2258 #else
2259     nip = (uint32_t)nip;
2260 #endif
2261     /* XXX: beware: this is false if VLE is supported */
2262     env->nip = nip & ~((target_ulong)0x00000003);
2263     hreg_store_msr(env, msr, 1);
2264     trace_ppc_excp_rfi(env->nip, env->msr);
2265     /*
2266      * No need to raise an exception here, as rfi is always the last
2267      * insn of a TB
2268      */
2269     cpu_interrupt_exittb(cs);
2270     /* Reset the reservation */
2271     env->reserve_addr = -1;
2272 
2273     /* Context synchronizing: check if TCG TLB needs flush */
2274     check_tlb_flush(env, false);
2275 }
2276 
2277 void helper_rfi(CPUPPCState *env)
2278 {
2279     do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
2280 }
2281 
2282 #define MSR_BOOK3S_MASK
2283 #if defined(TARGET_PPC64)
2284 void helper_rfid(CPUPPCState *env)
2285 {
2286     /*
2287      * The architecture defines a number of rules for which bits can
2288      * change but in practice, we handle this in hreg_store_msr()
2289      * which will be called by do_rfi(), so there is no need to filter
2290      * here
2291      */
2292     do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
2293 }
2294 
2295 void helper_rfscv(CPUPPCState *env)
2296 {
2297     do_rfi(env, env->lr, env->ctr);
2298 }
2299 
2300 void helper_hrfid(CPUPPCState *env)
2301 {
2302     do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
2303 }
2304 #endif
2305 
2306 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
2307 void helper_rfebb(CPUPPCState *env, target_ulong s)
2308 {
2309     target_ulong msr = env->msr;
2310 
2311     /*
2312      * Handling of BESCR bits 32:33 according to PowerISA v3.1:
2313      *
2314      * "If BESCR 32:33 != 0b00 the instruction is treated as if
2315      *  the instruction form were invalid."
2316      */
2317     if (env->spr[SPR_BESCR] & BESCR_INVALID) {
2318         raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2319                             POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
2320     }
2321 
2322     env->nip = env->spr[SPR_EBBRR];
2323 
2324     /* Switching to 32-bit ? Crop the nip */
2325     if (!msr_is_64bit(env, msr)) {
2326         env->nip = (uint32_t)env->spr[SPR_EBBRR];
2327     }
2328 
2329     if (s) {
2330         env->spr[SPR_BESCR] |= BESCR_GE;
2331     } else {
2332         env->spr[SPR_BESCR] &= ~BESCR_GE;
2333     }
2334 }
2335 #endif
2336 
2337 /*****************************************************************************/
2338 /* Embedded PowerPC specific helpers */
2339 void helper_40x_rfci(CPUPPCState *env)
2340 {
2341     do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
2342 }
2343 
2344 void helper_rfci(CPUPPCState *env)
2345 {
2346     do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
2347 }
2348 
2349 void helper_rfdi(CPUPPCState *env)
2350 {
2351     /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
2352     do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
2353 }
2354 
2355 void helper_rfmci(CPUPPCState *env)
2356 {
2357     /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
2358     do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
2359 }
2360 #endif /* CONFIG_TCG */
2361 #endif /* !defined(CONFIG_USER_ONLY) */
2362 
2363 #ifdef CONFIG_TCG
2364 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2365                uint32_t flags)
2366 {
2367     if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
2368                   ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
2369                   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
2370                   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
2371                   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
2372         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2373                                POWERPC_EXCP_TRAP, GETPC());
2374     }
2375 }
2376 
2377 #if defined(TARGET_PPC64)
2378 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2379                uint32_t flags)
2380 {
2381     if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
2382                   ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
2383                   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
2384                   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
2385                   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
2386         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2387                                POWERPC_EXCP_TRAP, GETPC());
2388     }
2389 }
2390 #endif
2391 #endif
2392 
2393 #if !defined(CONFIG_USER_ONLY)
2394 
2395 #ifdef CONFIG_TCG
2396 
2397 /* Embedded.Processor Control */
2398 static int dbell2irq(target_ulong rb)
2399 {
2400     int msg = rb & DBELL_TYPE_MASK;
2401     int irq = -1;
2402 
2403     switch (msg) {
2404     case DBELL_TYPE_DBELL:
2405         irq = PPC_INTERRUPT_DOORBELL;
2406         break;
2407     case DBELL_TYPE_DBELL_CRIT:
2408         irq = PPC_INTERRUPT_CDOORBELL;
2409         break;
2410     case DBELL_TYPE_G_DBELL:
2411     case DBELL_TYPE_G_DBELL_CRIT:
2412     case DBELL_TYPE_G_DBELL_MC:
2413         /* XXX implement */
2414     default:
2415         break;
2416     }
2417 
2418     return irq;
2419 }
2420 
2421 void helper_msgclr(CPUPPCState *env, target_ulong rb)
2422 {
2423     int irq = dbell2irq(rb);
2424 
2425     if (irq < 0) {
2426         return;
2427     }
2428 
2429     env->pending_interrupts &= ~(1 << irq);
2430 }
2431 
2432 void helper_msgsnd(target_ulong rb)
2433 {
2434     int irq = dbell2irq(rb);
2435     int pir = rb & DBELL_PIRTAG_MASK;
2436     CPUState *cs;
2437 
2438     if (irq < 0) {
2439         return;
2440     }
2441 
2442     qemu_mutex_lock_iothread();
2443     CPU_FOREACH(cs) {
2444         PowerPCCPU *cpu = POWERPC_CPU(cs);
2445         CPUPPCState *cenv = &cpu->env;
2446 
2447         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
2448             cenv->pending_interrupts |= 1 << irq;
2449             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2450         }
2451     }
2452     qemu_mutex_unlock_iothread();
2453 }
2454 
2455 /* Server Processor Control */
2456 
2457 static bool dbell_type_server(target_ulong rb)
2458 {
2459     /*
2460      * A Directed Hypervisor Doorbell message is sent only if the
2461      * message type is 5. All other types are reserved and the
2462      * instruction is a no-op
2463      */
2464     return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
2465 }
2466 
2467 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
2468 {
2469     if (!dbell_type_server(rb)) {
2470         return;
2471     }
2472 
2473     env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
2474 }
2475 
2476 static void book3s_msgsnd_common(int pir, int irq)
2477 {
2478     CPUState *cs;
2479 
2480     qemu_mutex_lock_iothread();
2481     CPU_FOREACH(cs) {
2482         PowerPCCPU *cpu = POWERPC_CPU(cs);
2483         CPUPPCState *cenv = &cpu->env;
2484 
2485         /* TODO: broadcast message to all threads of the same  processor */
2486         if (cenv->spr_cb[SPR_PIR].default_value == pir) {
2487             cenv->pending_interrupts |= 1 << irq;
2488             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2489         }
2490     }
2491     qemu_mutex_unlock_iothread();
2492 }
2493 
2494 void helper_book3s_msgsnd(target_ulong rb)
2495 {
2496     int pir = rb & DBELL_PROCIDTAG_MASK;
2497 
2498     if (!dbell_type_server(rb)) {
2499         return;
2500     }
2501 
2502     book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
2503 }
2504 
2505 #if defined(TARGET_PPC64)
2506 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
2507 {
2508     helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
2509 
2510     if (!dbell_type_server(rb)) {
2511         return;
2512     }
2513 
2514     env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2515 }
2516 
2517 /*
2518  * sends a message to other threads that are on the same
2519  * multi-threaded processor
2520  */
2521 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
2522 {
2523     int pir = env->spr_cb[SPR_PIR].default_value;
2524 
2525     helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
2526 
2527     if (!dbell_type_server(rb)) {
2528         return;
2529     }
2530 
2531     /* TODO: TCG supports only one thread */
2532 
2533     book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
2534 }
2535 #endif /* TARGET_PPC64 */
2536 
2537 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
2538                                  MMUAccessType access_type,
2539                                  int mmu_idx, uintptr_t retaddr)
2540 {
2541     CPUPPCState *env = cs->env_ptr;
2542     uint32_t insn;
2543 
2544     /* Restore state and reload the insn we executed, for filling in DSISR.  */
2545     cpu_restore_state(cs, retaddr, true);
2546     insn = cpu_ldl_code(env, env->nip);
2547 
2548     switch (env->mmu_model) {
2549     case POWERPC_MMU_SOFT_4xx:
2550         env->spr[SPR_40x_DEAR] = vaddr;
2551         break;
2552     case POWERPC_MMU_BOOKE:
2553     case POWERPC_MMU_BOOKE206:
2554         env->spr[SPR_BOOKE_DEAR] = vaddr;
2555         break;
2556     default:
2557         env->spr[SPR_DAR] = vaddr;
2558         break;
2559     }
2560 
2561     cs->exception_index = POWERPC_EXCP_ALIGN;
2562     env->error_code = insn & 0x03FF0000;
2563     cpu_loop_exit(cs);
2564 }
2565 #endif /* CONFIG_TCG */
2566 #endif /* !CONFIG_USER_ONLY */
2567