target/ppc: Add SRR1 prefix indication to interrupt handlers
[qemu/kevin.git] / target / ppc / excp_helper.c
blob847f8a33beba9b5e7f04e78186d8c324502172d5
1 /*
2 * PowerPC exception emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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/>.
19 #include "qemu/osdep.h"
20 #include "qemu/main-loop.h"
21 #include "qemu/log.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "internal.h"
25 #include "helper_regs.h"
26 #include "hw/ppc/ppc.h"
28 #include "trace.h"
30 #ifdef CONFIG_TCG
31 #include "sysemu/tcg.h"
32 #include "exec/helper-proto.h"
33 #include "exec/cpu_ldst.h"
34 #endif
36 /*****************************************************************************/
37 /* Exception processing */
38 #if !defined(CONFIG_USER_ONLY)
40 static const char *powerpc_excp_name(int excp)
42 switch (excp) {
43 case POWERPC_EXCP_CRITICAL: return "CRITICAL";
44 case POWERPC_EXCP_MCHECK: return "MCHECK";
45 case POWERPC_EXCP_DSI: return "DSI";
46 case POWERPC_EXCP_ISI: return "ISI";
47 case POWERPC_EXCP_EXTERNAL: return "EXTERNAL";
48 case POWERPC_EXCP_ALIGN: return "ALIGN";
49 case POWERPC_EXCP_PROGRAM: return "PROGRAM";
50 case POWERPC_EXCP_FPU: return "FPU";
51 case POWERPC_EXCP_SYSCALL: return "SYSCALL";
52 case POWERPC_EXCP_APU: return "APU";
53 case POWERPC_EXCP_DECR: return "DECR";
54 case POWERPC_EXCP_FIT: return "FIT";
55 case POWERPC_EXCP_WDT: return "WDT";
56 case POWERPC_EXCP_DTLB: return "DTLB";
57 case POWERPC_EXCP_ITLB: return "ITLB";
58 case POWERPC_EXCP_DEBUG: return "DEBUG";
59 case POWERPC_EXCP_SPEU: return "SPEU";
60 case POWERPC_EXCP_EFPDI: return "EFPDI";
61 case POWERPC_EXCP_EFPRI: return "EFPRI";
62 case POWERPC_EXCP_EPERFM: return "EPERFM";
63 case POWERPC_EXCP_DOORI: return "DOORI";
64 case POWERPC_EXCP_DOORCI: return "DOORCI";
65 case POWERPC_EXCP_GDOORI: return "GDOORI";
66 case POWERPC_EXCP_GDOORCI: return "GDOORCI";
67 case POWERPC_EXCP_HYPPRIV: return "HYPPRIV";
68 case POWERPC_EXCP_RESET: return "RESET";
69 case POWERPC_EXCP_DSEG: return "DSEG";
70 case POWERPC_EXCP_ISEG: return "ISEG";
71 case POWERPC_EXCP_HDECR: return "HDECR";
72 case POWERPC_EXCP_TRACE: return "TRACE";
73 case POWERPC_EXCP_HDSI: return "HDSI";
74 case POWERPC_EXCP_HISI: return "HISI";
75 case POWERPC_EXCP_HDSEG: return "HDSEG";
76 case POWERPC_EXCP_HISEG: return "HISEG";
77 case POWERPC_EXCP_VPU: return "VPU";
78 case POWERPC_EXCP_PIT: return "PIT";
79 case POWERPC_EXCP_EMUL: return "EMUL";
80 case POWERPC_EXCP_IFTLB: return "IFTLB";
81 case POWERPC_EXCP_DLTLB: return "DLTLB";
82 case POWERPC_EXCP_DSTLB: return "DSTLB";
83 case POWERPC_EXCP_FPA: return "FPA";
84 case POWERPC_EXCP_DABR: return "DABR";
85 case POWERPC_EXCP_IABR: return "IABR";
86 case POWERPC_EXCP_SMI: return "SMI";
87 case POWERPC_EXCP_PERFM: return "PERFM";
88 case POWERPC_EXCP_THERM: return "THERM";
89 case POWERPC_EXCP_VPUA: return "VPUA";
90 case POWERPC_EXCP_SOFTP: return "SOFTP";
91 case POWERPC_EXCP_MAINT: return "MAINT";
92 case POWERPC_EXCP_MEXTBR: return "MEXTBR";
93 case POWERPC_EXCP_NMEXTBR: return "NMEXTBR";
94 case POWERPC_EXCP_ITLBE: return "ITLBE";
95 case POWERPC_EXCP_DTLBE: return "DTLBE";
96 case POWERPC_EXCP_VSXU: return "VSXU";
97 case POWERPC_EXCP_FU: return "FU";
98 case POWERPC_EXCP_HV_EMU: return "HV_EMU";
99 case POWERPC_EXCP_HV_MAINT: return "HV_MAINT";
100 case POWERPC_EXCP_HV_FU: return "HV_FU";
101 case POWERPC_EXCP_SDOOR: return "SDOOR";
102 case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
103 case POWERPC_EXCP_HVIRT: return "HVIRT";
104 case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
105 default:
106 g_assert_not_reached();
110 static void dump_syscall(CPUPPCState *env)
112 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
113 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
114 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
115 " nip=" TARGET_FMT_lx "\n",
116 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
117 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
118 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
119 ppc_dump_gpr(env, 8), env->nip);
122 static void dump_hcall(CPUPPCState *env)
124 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
125 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
126 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
127 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
128 " nip=" TARGET_FMT_lx "\n",
129 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
130 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
131 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
132 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
133 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
134 env->nip);
137 #ifdef CONFIG_TCG
138 /* Return true iff byteswap is needed to load instruction */
139 static inline bool insn_need_byteswap(CPUArchState *env)
141 /* SYSTEM builds TARGET_BIG_ENDIAN. Need to swap when MSR[LE] is set */
142 return !!(env->msr & ((target_ulong)1 << MSR_LE));
145 static uint32_t ppc_ldl_code(CPUArchState *env, abi_ptr addr)
147 uint32_t insn = cpu_ldl_code(env, addr);
149 if (insn_need_byteswap(env)) {
150 insn = bswap32(insn);
153 return insn;
155 #endif
157 static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
159 const char *es;
160 target_ulong *miss, *cmp;
161 int en;
163 if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
164 return;
167 if (excp == POWERPC_EXCP_IFTLB) {
168 es = "I";
169 en = 'I';
170 miss = &env->spr[SPR_IMISS];
171 cmp = &env->spr[SPR_ICMP];
172 } else {
173 if (excp == POWERPC_EXCP_DLTLB) {
174 es = "DL";
175 } else {
176 es = "DS";
178 en = 'D';
179 miss = &env->spr[SPR_DMISS];
180 cmp = &env->spr[SPR_DCMP];
182 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
183 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
184 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
185 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
186 env->error_code);
189 #if defined(TARGET_PPC64)
190 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
191 target_ulong *msr)
193 /* We no longer are in a PM state */
194 env->resume_as_sreset = false;
196 /* Pretend to be returning from doze always as we don't lose state */
197 *msr |= SRR1_WS_NOLOSS;
199 /* Machine checks are sent normally */
200 if (excp == POWERPC_EXCP_MCHECK) {
201 return excp;
203 switch (excp) {
204 case POWERPC_EXCP_RESET:
205 *msr |= SRR1_WAKERESET;
206 break;
207 case POWERPC_EXCP_EXTERNAL:
208 *msr |= SRR1_WAKEEE;
209 break;
210 case POWERPC_EXCP_DECR:
211 *msr |= SRR1_WAKEDEC;
212 break;
213 case POWERPC_EXCP_SDOOR:
214 *msr |= SRR1_WAKEDBELL;
215 break;
216 case POWERPC_EXCP_SDOOR_HV:
217 *msr |= SRR1_WAKEHDBELL;
218 break;
219 case POWERPC_EXCP_HV_MAINT:
220 *msr |= SRR1_WAKEHMI;
221 break;
222 case POWERPC_EXCP_HVIRT:
223 *msr |= SRR1_WAKEHVI;
224 break;
225 default:
226 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
227 excp);
229 return POWERPC_EXCP_RESET;
233 * AIL - Alternate Interrupt Location, a mode that allows interrupts to be
234 * taken with the MMU on, and which uses an alternate location (e.g., so the
235 * kernel/hv can map the vectors there with an effective address).
237 * An interrupt is considered to be taken "with AIL" or "AIL applies" if they
238 * are delivered in this way. AIL requires the LPCR to be set to enable this
239 * mode, and then a number of conditions have to be true for AIL to apply.
241 * First of all, SRESET, MCE, and HMI are always delivered without AIL, because
242 * they specifically want to be in real mode (e.g., the MCE might be signaling
243 * a SLB multi-hit which requires SLB flush before the MMU can be enabled).
245 * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV],
246 * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current
247 * radix mode (LPCR[HR]).
249 * POWER8, POWER9 with LPCR[HR]=0
250 * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
251 * +-----------+-------------+---------+-------------+-----+
252 * | a | 00/01/10 | x | x | 0 |
253 * | a | 11 | 0 | 1 | 0 |
254 * | a | 11 | 1 | 1 | a |
255 * | a | 11 | 0 | 0 | a |
256 * +-------------------------------------------------------+
258 * POWER9 with LPCR[HR]=1
259 * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
260 * +-----------+-------------+---------+-------------+-----+
261 * | a | 00/01/10 | x | x | 0 |
262 * | a | 11 | x | x | a |
263 * +-------------------------------------------------------+
265 * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to
266 * the hypervisor in AIL mode if the guest is radix. This is good for
267 * performance but allows the guest to influence the AIL of hypervisor
268 * interrupts using its MSR, and also the hypervisor must disallow guest
269 * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to
270 * use AIL for its MSR[HV] 0->1 interrupts.
272 * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to
273 * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and
274 * MSR[HV] 1->1).
276 * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1.
278 * POWER10 behaviour is
279 * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
280 * +-----------+------------+-------------+---------+-------------+-----+
281 * | a | h | 00/01/10 | 0 | 0 | 0 |
282 * | a | h | 11 | 0 | 0 | a |
283 * | a | h | x | 0 | 1 | h |
284 * | a | h | 00/01/10 | 1 | 1 | 0 |
285 * | a | h | 11 | 1 | 1 | h |
286 * +--------------------------------------------------------------------+
288 static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
289 target_ulong *new_msr, target_ulong *vector)
291 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
292 CPUPPCState *env = &cpu->env;
293 bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
294 bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
295 int ail = 0;
297 if (excp == POWERPC_EXCP_MCHECK ||
298 excp == POWERPC_EXCP_RESET ||
299 excp == POWERPC_EXCP_HV_MAINT) {
300 /* SRESET, MCE, HMI never apply AIL */
301 return;
304 if (!(pcc->lpcr_mask & LPCR_AIL)) {
305 /* This CPU does not have AIL */
306 return;
309 /* P8 & P9 */
310 if (!(pcc->lpcr_mask & LPCR_HAIL)) {
311 if (!mmu_all_on) {
312 /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
313 return;
315 if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
317 * AIL does not work if there is a MSR[HV] 0->1 transition and the
318 * partition is in HPT mode. For radix guests, such interrupts are
319 * allowed to be delivered to the hypervisor in ail mode.
321 return;
324 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
325 if (ail == 0) {
326 return;
328 if (ail == 1) {
329 /* AIL=1 is reserved, treat it like AIL=0 */
330 return;
333 /* P10 and up */
334 } else {
335 if (!mmu_all_on && !hv_escalation) {
337 * AIL works for HV interrupts even with guest MSR[IR/DR] disabled.
338 * Guest->guest and HV->HV interrupts do require MMU on.
340 return;
343 if (*new_msr & MSR_HVB) {
344 if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
345 /* HV interrupts depend on LPCR[HAIL] */
346 return;
348 ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */
349 } else {
350 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
352 if (ail == 0) {
353 return;
355 if (ail == 1 || ail == 2) {
356 /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
357 return;
362 * AIL applies, so the new MSR gets IR and DR set, and an offset applied
363 * to the new IP.
365 *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
367 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
368 if (ail == 2) {
369 *vector |= 0x0000000000018000ull;
370 } else if (ail == 3) {
371 *vector |= 0xc000000000004000ull;
373 } else {
375 * scv AIL is a little different. AIL=2 does not change the address,
376 * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
378 if (ail == 3) {
379 *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */
380 *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
384 #endif
386 static void powerpc_reset_excp_state(PowerPCCPU *cpu)
388 CPUState *cs = CPU(cpu);
389 CPUPPCState *env = &cpu->env;
391 /* Reset exception state */
392 cs->exception_index = POWERPC_EXCP_NONE;
393 env->error_code = 0;
396 static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
397 target_ulong msr)
399 CPUPPCState *env = &cpu->env;
401 assert((msr & env->msr_mask) == msr);
404 * We don't use hreg_store_msr here as already have treated any
405 * special case that could occur. Just store MSR and update hflags
407 * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
408 * will prevent setting of the HV bit which some exceptions might need
409 * to do.
411 env->nip = vector;
412 env->msr = msr;
413 hreg_compute_hflags(env);
414 ppc_maybe_interrupt(env);
416 powerpc_reset_excp_state(cpu);
419 * Any interrupt is context synchronizing, check if TCG TLB needs
420 * a delayed flush on ppc64
422 check_tlb_flush(env, false);
424 /* Reset the reservation */
425 env->reserve_addr = -1;
428 static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
430 CPUState *cs = CPU(cpu);
431 CPUPPCState *env = &cpu->env;
432 target_ulong msr, new_msr, vector;
433 int srr0, srr1;
435 /* new srr1 value excluding must-be-zero bits */
436 msr = env->msr & ~0x783f0000ULL;
439 * new interrupt handler msr preserves existing ME unless
440 * explicitly overriden.
442 new_msr = env->msr & (((target_ulong)1 << MSR_ME));
444 /* target registers */
445 srr0 = SPR_SRR0;
446 srr1 = SPR_SRR1;
449 * Hypervisor emulation assistance interrupt only exists on server
450 * arch 2.05 server or later.
452 if (excp == POWERPC_EXCP_HV_EMU) {
453 excp = POWERPC_EXCP_PROGRAM;
456 vector = env->excp_vectors[excp];
457 if (vector == (target_ulong)-1ULL) {
458 cpu_abort(cs, "Raised an exception without defined vector %d\n",
459 excp);
462 vector |= env->excp_prefix;
464 switch (excp) {
465 case POWERPC_EXCP_CRITICAL: /* Critical input */
466 srr0 = SPR_40x_SRR2;
467 srr1 = SPR_40x_SRR3;
468 break;
469 case POWERPC_EXCP_MCHECK: /* Machine check exception */
470 if (!FIELD_EX64(env->msr, MSR, ME)) {
472 * Machine check exception is not enabled. Enter
473 * checkstop state.
475 fprintf(stderr, "Machine check while not allowed. "
476 "Entering checkstop state\n");
477 if (qemu_log_separate()) {
478 qemu_log("Machine check while not allowed. "
479 "Entering checkstop state\n");
481 cs->halted = 1;
482 cpu_interrupt_exittb(cs);
485 /* machine check exceptions don't have ME set */
486 new_msr &= ~((target_ulong)1 << MSR_ME);
488 srr0 = SPR_40x_SRR2;
489 srr1 = SPR_40x_SRR3;
490 break;
491 case POWERPC_EXCP_DSI: /* Data storage exception */
492 trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
493 break;
494 case POWERPC_EXCP_ISI: /* Instruction storage exception */
495 trace_ppc_excp_isi(msr, env->nip);
496 break;
497 case POWERPC_EXCP_EXTERNAL: /* External input */
498 break;
499 case POWERPC_EXCP_ALIGN: /* Alignment exception */
500 break;
501 case POWERPC_EXCP_PROGRAM: /* Program exception */
502 switch (env->error_code & ~0xF) {
503 case POWERPC_EXCP_FP:
504 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
505 trace_ppc_excp_fp_ignore();
506 powerpc_reset_excp_state(cpu);
507 return;
509 env->spr[SPR_40x_ESR] = ESR_FP;
510 break;
511 case POWERPC_EXCP_INVAL:
512 trace_ppc_excp_inval(env->nip);
513 env->spr[SPR_40x_ESR] = ESR_PIL;
514 break;
515 case POWERPC_EXCP_PRIV:
516 env->spr[SPR_40x_ESR] = ESR_PPR;
517 break;
518 case POWERPC_EXCP_TRAP:
519 env->spr[SPR_40x_ESR] = ESR_PTR;
520 break;
521 default:
522 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
523 env->error_code);
524 break;
526 break;
527 case POWERPC_EXCP_SYSCALL: /* System call exception */
528 dump_syscall(env);
531 * We need to correct the NIP which in this case is supposed
532 * to point to the next instruction
534 env->nip += 4;
535 break;
536 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
537 trace_ppc_excp_print("FIT");
538 break;
539 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
540 trace_ppc_excp_print("WDT");
541 break;
542 case POWERPC_EXCP_DTLB: /* Data TLB error */
543 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
544 break;
545 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
546 trace_ppc_excp_print("PIT");
547 break;
548 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
549 cpu_abort(cs, "%s exception not implemented\n",
550 powerpc_excp_name(excp));
551 break;
552 default:
553 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
554 break;
557 /* Save PC */
558 env->spr[srr0] = env->nip;
560 /* Save MSR */
561 env->spr[srr1] = msr;
563 powerpc_set_excp_state(cpu, vector, new_msr);
566 static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
568 CPUState *cs = CPU(cpu);
569 CPUPPCState *env = &cpu->env;
570 target_ulong msr, new_msr, vector;
572 /* new srr1 value excluding must-be-zero bits */
573 msr = env->msr & ~0x783f0000ULL;
576 * new interrupt handler msr preserves existing ME unless
577 * explicitly overriden
579 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
582 * Hypervisor emulation assistance interrupt only exists on server
583 * arch 2.05 server or later.
585 if (excp == POWERPC_EXCP_HV_EMU) {
586 excp = POWERPC_EXCP_PROGRAM;
589 vector = env->excp_vectors[excp];
590 if (vector == (target_ulong)-1ULL) {
591 cpu_abort(cs, "Raised an exception without defined vector %d\n",
592 excp);
595 vector |= env->excp_prefix;
597 switch (excp) {
598 case POWERPC_EXCP_CRITICAL: /* Critical input */
599 break;
600 case POWERPC_EXCP_MCHECK: /* Machine check exception */
601 if (!FIELD_EX64(env->msr, MSR, ME)) {
603 * Machine check exception is not enabled. Enter
604 * checkstop state.
606 fprintf(stderr, "Machine check while not allowed. "
607 "Entering checkstop state\n");
608 if (qemu_log_separate()) {
609 qemu_log("Machine check while not allowed. "
610 "Entering checkstop state\n");
612 cs->halted = 1;
613 cpu_interrupt_exittb(cs);
616 /* machine check exceptions don't have ME set */
617 new_msr &= ~((target_ulong)1 << MSR_ME);
619 break;
620 case POWERPC_EXCP_DSI: /* Data storage exception */
621 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
622 break;
623 case POWERPC_EXCP_ISI: /* Instruction storage exception */
624 trace_ppc_excp_isi(msr, env->nip);
625 msr |= env->error_code;
626 break;
627 case POWERPC_EXCP_EXTERNAL: /* External input */
628 break;
629 case POWERPC_EXCP_ALIGN: /* Alignment exception */
630 /* Get rS/rD and rA from faulting opcode */
632 * Note: the opcode fields will not be set properly for a
633 * direct store load/store, but nobody cares as nobody
634 * actually uses direct store segments.
636 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
637 break;
638 case POWERPC_EXCP_PROGRAM: /* Program exception */
639 switch (env->error_code & ~0xF) {
640 case POWERPC_EXCP_FP:
641 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
642 trace_ppc_excp_fp_ignore();
643 powerpc_reset_excp_state(cpu);
644 return;
648 * FP exceptions always have NIP pointing to the faulting
649 * instruction, so always use store_next and claim we are
650 * precise in the MSR.
652 msr |= 0x00100000;
653 break;
654 case POWERPC_EXCP_INVAL:
655 trace_ppc_excp_inval(env->nip);
656 msr |= 0x00080000;
657 break;
658 case POWERPC_EXCP_PRIV:
659 msr |= 0x00040000;
660 break;
661 case POWERPC_EXCP_TRAP:
662 msr |= 0x00020000;
663 break;
664 default:
665 /* Should never occur */
666 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
667 env->error_code);
668 break;
670 break;
671 case POWERPC_EXCP_SYSCALL: /* System call exception */
672 dump_syscall(env);
675 * We need to correct the NIP which in this case is supposed
676 * to point to the next instruction
678 env->nip += 4;
679 break;
680 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
681 case POWERPC_EXCP_DECR: /* Decrementer exception */
682 break;
683 case POWERPC_EXCP_DTLB: /* Data TLB error */
684 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
685 break;
686 case POWERPC_EXCP_RESET: /* System reset exception */
687 if (FIELD_EX64(env->msr, MSR, POW)) {
688 cpu_abort(cs, "Trying to deliver power-saving system reset "
689 "exception %d with no HV support\n", excp);
691 break;
692 case POWERPC_EXCP_TRACE: /* Trace exception */
693 break;
694 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
695 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
696 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
697 /* Swap temporary saved registers with GPRs */
698 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
699 new_msr |= (target_ulong)1 << MSR_TGPR;
700 hreg_swap_gpr_tgpr(env);
703 ppc_excp_debug_sw_tlb(env, excp);
705 msr |= env->crf[0] << 28;
706 msr |= env->error_code; /* key, D/I, S/L bits */
707 /* Set way using a LRU mechanism */
708 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
709 break;
710 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
711 case POWERPC_EXCP_DABR: /* Data address breakpoint */
712 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
713 case POWERPC_EXCP_SMI: /* System management interrupt */
714 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
715 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
716 cpu_abort(cs, "%s exception not implemented\n",
717 powerpc_excp_name(excp));
718 break;
719 default:
720 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
721 break;
725 * Sort out endianness of interrupt, this differs depending on the
726 * CPU, the HV mode, etc...
728 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
729 new_msr |= (target_ulong)1 << MSR_LE;
732 /* Save PC */
733 env->spr[SPR_SRR0] = env->nip;
735 /* Save MSR */
736 env->spr[SPR_SRR1] = msr;
738 powerpc_set_excp_state(cpu, vector, new_msr);
741 static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
743 CPUState *cs = CPU(cpu);
744 CPUPPCState *env = &cpu->env;
745 target_ulong msr, new_msr, vector;
747 /* new srr1 value excluding must-be-zero bits */
748 msr = env->msr & ~0x783f0000ULL;
751 * new interrupt handler msr preserves existing ME unless
752 * explicitly overriden
754 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
757 * Hypervisor emulation assistance interrupt only exists on server
758 * arch 2.05 server or later.
760 if (excp == POWERPC_EXCP_HV_EMU) {
761 excp = POWERPC_EXCP_PROGRAM;
764 vector = env->excp_vectors[excp];
765 if (vector == (target_ulong)-1ULL) {
766 cpu_abort(cs, "Raised an exception without defined vector %d\n",
767 excp);
770 vector |= env->excp_prefix;
772 switch (excp) {
773 case POWERPC_EXCP_MCHECK: /* Machine check exception */
774 if (!FIELD_EX64(env->msr, MSR, ME)) {
776 * Machine check exception is not enabled. Enter
777 * checkstop state.
779 fprintf(stderr, "Machine check while not allowed. "
780 "Entering checkstop state\n");
781 if (qemu_log_separate()) {
782 qemu_log("Machine check while not allowed. "
783 "Entering checkstop state\n");
785 cs->halted = 1;
786 cpu_interrupt_exittb(cs);
789 /* machine check exceptions don't have ME set */
790 new_msr &= ~((target_ulong)1 << MSR_ME);
792 break;
793 case POWERPC_EXCP_DSI: /* Data storage exception */
794 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
795 break;
796 case POWERPC_EXCP_ISI: /* Instruction storage exception */
797 trace_ppc_excp_isi(msr, env->nip);
798 msr |= env->error_code;
799 break;
800 case POWERPC_EXCP_EXTERNAL: /* External input */
801 break;
802 case POWERPC_EXCP_ALIGN: /* Alignment exception */
803 /* Get rS/rD and rA from faulting opcode */
805 * Note: the opcode fields will not be set properly for a
806 * direct store load/store, but nobody cares as nobody
807 * actually uses direct store segments.
809 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
810 break;
811 case POWERPC_EXCP_PROGRAM: /* Program exception */
812 switch (env->error_code & ~0xF) {
813 case POWERPC_EXCP_FP:
814 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
815 trace_ppc_excp_fp_ignore();
816 powerpc_reset_excp_state(cpu);
817 return;
821 * FP exceptions always have NIP pointing to the faulting
822 * instruction, so always use store_next and claim we are
823 * precise in the MSR.
825 msr |= 0x00100000;
826 break;
827 case POWERPC_EXCP_INVAL:
828 trace_ppc_excp_inval(env->nip);
829 msr |= 0x00080000;
830 break;
831 case POWERPC_EXCP_PRIV:
832 msr |= 0x00040000;
833 break;
834 case POWERPC_EXCP_TRAP:
835 msr |= 0x00020000;
836 break;
837 default:
838 /* Should never occur */
839 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
840 env->error_code);
841 break;
843 break;
844 case POWERPC_EXCP_SYSCALL: /* System call exception */
846 int lev = env->error_code;
848 if (lev == 1 && cpu->vhyp) {
849 dump_hcall(env);
850 } else {
851 dump_syscall(env);
855 * We need to correct the NIP which in this case is supposed
856 * to point to the next instruction
858 env->nip += 4;
861 * The Virtual Open Firmware (VOF) relies on the 'sc 1'
862 * instruction to communicate with QEMU. The pegasos2 machine
863 * uses VOF and the 7xx CPUs, so although the 7xx don't have
864 * HV mode, we need to keep hypercall support.
866 if (lev == 1 && cpu->vhyp) {
867 PPCVirtualHypervisorClass *vhc =
868 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
869 vhc->hypercall(cpu->vhyp, cpu);
870 return;
873 break;
875 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
876 case POWERPC_EXCP_DECR: /* Decrementer exception */
877 break;
878 case POWERPC_EXCP_RESET: /* System reset exception */
879 if (FIELD_EX64(env->msr, MSR, POW)) {
880 cpu_abort(cs, "Trying to deliver power-saving system reset "
881 "exception %d with no HV support\n", excp);
883 break;
884 case POWERPC_EXCP_TRACE: /* Trace exception */
885 break;
886 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
887 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
888 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
889 ppc_excp_debug_sw_tlb(env, excp);
891 msr |= env->crf[0] << 28;
892 msr |= env->error_code; /* key, D/I, S/L bits */
893 /* Set way using a LRU mechanism */
894 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
896 break;
897 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
898 case POWERPC_EXCP_SMI: /* System management interrupt */
899 case POWERPC_EXCP_THERM: /* Thermal interrupt */
900 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
901 cpu_abort(cs, "%s exception not implemented\n",
902 powerpc_excp_name(excp));
903 break;
904 default:
905 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
906 break;
910 * Sort out endianness of interrupt, this differs depending on the
911 * CPU, the HV mode, etc...
913 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
914 new_msr |= (target_ulong)1 << MSR_LE;
917 /* Save PC */
918 env->spr[SPR_SRR0] = env->nip;
920 /* Save MSR */
921 env->spr[SPR_SRR1] = msr;
923 powerpc_set_excp_state(cpu, vector, new_msr);
926 static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
928 CPUState *cs = CPU(cpu);
929 CPUPPCState *env = &cpu->env;
930 target_ulong msr, new_msr, vector;
932 /* new srr1 value excluding must-be-zero bits */
933 msr = env->msr & ~0x783f0000ULL;
936 * new interrupt handler msr preserves existing ME unless
937 * explicitly overriden
939 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
942 * Hypervisor emulation assistance interrupt only exists on server
943 * arch 2.05 server or later.
945 if (excp == POWERPC_EXCP_HV_EMU) {
946 excp = POWERPC_EXCP_PROGRAM;
949 vector = env->excp_vectors[excp];
950 if (vector == (target_ulong)-1ULL) {
951 cpu_abort(cs, "Raised an exception without defined vector %d\n",
952 excp);
955 vector |= env->excp_prefix;
957 switch (excp) {
958 case POWERPC_EXCP_MCHECK: /* Machine check exception */
959 if (!FIELD_EX64(env->msr, MSR, ME)) {
961 * Machine check exception is not enabled. Enter
962 * checkstop state.
964 fprintf(stderr, "Machine check while not allowed. "
965 "Entering checkstop state\n");
966 if (qemu_log_separate()) {
967 qemu_log("Machine check while not allowed. "
968 "Entering checkstop state\n");
970 cs->halted = 1;
971 cpu_interrupt_exittb(cs);
974 /* machine check exceptions don't have ME set */
975 new_msr &= ~((target_ulong)1 << MSR_ME);
977 break;
978 case POWERPC_EXCP_DSI: /* Data storage exception */
979 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
980 break;
981 case POWERPC_EXCP_ISI: /* Instruction storage exception */
982 trace_ppc_excp_isi(msr, env->nip);
983 msr |= env->error_code;
984 break;
985 case POWERPC_EXCP_EXTERNAL: /* External input */
986 break;
987 case POWERPC_EXCP_ALIGN: /* Alignment exception */
988 /* Get rS/rD and rA from faulting opcode */
990 * Note: the opcode fields will not be set properly for a
991 * direct store load/store, but nobody cares as nobody
992 * actually uses direct store segments.
994 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
995 break;
996 case POWERPC_EXCP_PROGRAM: /* Program exception */
997 switch (env->error_code & ~0xF) {
998 case POWERPC_EXCP_FP:
999 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1000 trace_ppc_excp_fp_ignore();
1001 powerpc_reset_excp_state(cpu);
1002 return;
1006 * FP exceptions always have NIP pointing to the faulting
1007 * instruction, so always use store_next and claim we are
1008 * precise in the MSR.
1010 msr |= 0x00100000;
1011 break;
1012 case POWERPC_EXCP_INVAL:
1013 trace_ppc_excp_inval(env->nip);
1014 msr |= 0x00080000;
1015 break;
1016 case POWERPC_EXCP_PRIV:
1017 msr |= 0x00040000;
1018 break;
1019 case POWERPC_EXCP_TRAP:
1020 msr |= 0x00020000;
1021 break;
1022 default:
1023 /* Should never occur */
1024 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1025 env->error_code);
1026 break;
1028 break;
1029 case POWERPC_EXCP_SYSCALL: /* System call exception */
1031 int lev = env->error_code;
1033 if ((lev == 1) && cpu->vhyp) {
1034 dump_hcall(env);
1035 } else {
1036 dump_syscall(env);
1040 * We need to correct the NIP which in this case is supposed
1041 * to point to the next instruction
1043 env->nip += 4;
1046 * The Virtual Open Firmware (VOF) relies on the 'sc 1'
1047 * instruction to communicate with QEMU. The pegasos2 machine
1048 * uses VOF and the 74xx CPUs, so although the 74xx don't have
1049 * HV mode, we need to keep hypercall support.
1051 if ((lev == 1) && cpu->vhyp) {
1052 PPCVirtualHypervisorClass *vhc =
1053 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1054 vhc->hypercall(cpu->vhyp, cpu);
1055 return;
1058 break;
1060 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1061 case POWERPC_EXCP_DECR: /* Decrementer exception */
1062 break;
1063 case POWERPC_EXCP_RESET: /* System reset exception */
1064 if (FIELD_EX64(env->msr, MSR, POW)) {
1065 cpu_abort(cs, "Trying to deliver power-saving system reset "
1066 "exception %d with no HV support\n", excp);
1068 break;
1069 case POWERPC_EXCP_TRACE: /* Trace exception */
1070 break;
1071 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1072 break;
1073 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1074 case POWERPC_EXCP_SMI: /* System management interrupt */
1075 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1076 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
1077 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1078 cpu_abort(cs, "%s exception not implemented\n",
1079 powerpc_excp_name(excp));
1080 break;
1081 default:
1082 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1083 break;
1087 * Sort out endianness of interrupt, this differs depending on the
1088 * CPU, the HV mode, etc...
1090 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1091 new_msr |= (target_ulong)1 << MSR_LE;
1094 /* Save PC */
1095 env->spr[SPR_SRR0] = env->nip;
1097 /* Save MSR */
1098 env->spr[SPR_SRR1] = msr;
1100 powerpc_set_excp_state(cpu, vector, new_msr);
1103 static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
1105 CPUState *cs = CPU(cpu);
1106 CPUPPCState *env = &cpu->env;
1107 target_ulong msr, new_msr, vector;
1108 int srr0, srr1;
1110 msr = env->msr;
1113 * new interrupt handler msr preserves existing ME unless
1114 * explicitly overriden
1116 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
1118 /* target registers */
1119 srr0 = SPR_SRR0;
1120 srr1 = SPR_SRR1;
1123 * Hypervisor emulation assistance interrupt only exists on server
1124 * arch 2.05 server or later.
1126 if (excp == POWERPC_EXCP_HV_EMU) {
1127 excp = POWERPC_EXCP_PROGRAM;
1130 #ifdef TARGET_PPC64
1132 * SPEU and VPU share the same IVOR but they exist in different
1133 * processors. SPEU is e500v1/2 only and VPU is e6500 only.
1135 if (excp == POWERPC_EXCP_VPU) {
1136 excp = POWERPC_EXCP_SPEU;
1138 #endif
1140 vector = env->excp_vectors[excp];
1141 if (vector == (target_ulong)-1ULL) {
1142 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1143 excp);
1146 vector |= env->excp_prefix;
1148 switch (excp) {
1149 case POWERPC_EXCP_CRITICAL: /* Critical input */
1150 srr0 = SPR_BOOKE_CSRR0;
1151 srr1 = SPR_BOOKE_CSRR1;
1152 break;
1153 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1154 if (!FIELD_EX64(env->msr, MSR, ME)) {
1156 * Machine check exception is not enabled. Enter
1157 * checkstop state.
1159 fprintf(stderr, "Machine check while not allowed. "
1160 "Entering checkstop state\n");
1161 if (qemu_log_separate()) {
1162 qemu_log("Machine check while not allowed. "
1163 "Entering checkstop state\n");
1165 cs->halted = 1;
1166 cpu_interrupt_exittb(cs);
1169 /* machine check exceptions don't have ME set */
1170 new_msr &= ~((target_ulong)1 << MSR_ME);
1172 /* FIXME: choose one or the other based on CPU type */
1173 srr0 = SPR_BOOKE_MCSRR0;
1174 srr1 = SPR_BOOKE_MCSRR1;
1176 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1177 env->spr[SPR_BOOKE_CSRR1] = msr;
1179 break;
1180 case POWERPC_EXCP_DSI: /* Data storage exception */
1181 trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
1182 break;
1183 case POWERPC_EXCP_ISI: /* Instruction storage exception */
1184 trace_ppc_excp_isi(msr, env->nip);
1185 break;
1186 case POWERPC_EXCP_EXTERNAL: /* External input */
1187 if (env->mpic_proxy) {
1188 /* IACK the IRQ on delivery */
1189 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1191 break;
1192 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1193 break;
1194 case POWERPC_EXCP_PROGRAM: /* Program exception */
1195 switch (env->error_code & ~0xF) {
1196 case POWERPC_EXCP_FP:
1197 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1198 trace_ppc_excp_fp_ignore();
1199 powerpc_reset_excp_state(cpu);
1200 return;
1204 * FP exceptions always have NIP pointing to the faulting
1205 * instruction, so always use store_next and claim we are
1206 * precise in the MSR.
1208 msr |= 0x00100000;
1209 env->spr[SPR_BOOKE_ESR] = ESR_FP;
1210 break;
1211 case POWERPC_EXCP_INVAL:
1212 trace_ppc_excp_inval(env->nip);
1213 msr |= 0x00080000;
1214 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1215 break;
1216 case POWERPC_EXCP_PRIV:
1217 msr |= 0x00040000;
1218 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1219 break;
1220 case POWERPC_EXCP_TRAP:
1221 msr |= 0x00020000;
1222 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1223 break;
1224 default:
1225 /* Should never occur */
1226 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1227 env->error_code);
1228 break;
1230 break;
1231 case POWERPC_EXCP_SYSCALL: /* System call exception */
1232 dump_syscall(env);
1235 * We need to correct the NIP which in this case is supposed
1236 * to point to the next instruction
1238 env->nip += 4;
1239 break;
1240 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1241 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1242 case POWERPC_EXCP_DECR: /* Decrementer exception */
1243 break;
1244 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1245 /* FIT on 4xx */
1246 trace_ppc_excp_print("FIT");
1247 break;
1248 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1249 trace_ppc_excp_print("WDT");
1250 srr0 = SPR_BOOKE_CSRR0;
1251 srr1 = SPR_BOOKE_CSRR1;
1252 break;
1253 case POWERPC_EXCP_DTLB: /* Data TLB error */
1254 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1255 break;
1256 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
1257 if (env->flags & POWERPC_FLAG_DE) {
1258 /* FIXME: choose one or the other based on CPU type */
1259 srr0 = SPR_BOOKE_DSRR0;
1260 srr1 = SPR_BOOKE_DSRR1;
1262 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1263 env->spr[SPR_BOOKE_CSRR1] = msr;
1265 /* DBSR already modified by caller */
1266 } else {
1267 cpu_abort(cs, "Debug exception triggered on unsupported model\n");
1269 break;
1270 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
1271 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1272 break;
1273 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
1274 break;
1275 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
1276 srr0 = SPR_BOOKE_CSRR0;
1277 srr1 = SPR_BOOKE_CSRR1;
1278 break;
1279 case POWERPC_EXCP_RESET: /* System reset exception */
1280 if (FIELD_EX64(env->msr, MSR, POW)) {
1281 cpu_abort(cs, "Trying to deliver power-saving system reset "
1282 "exception %d with no HV support\n", excp);
1284 break;
1285 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
1286 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
1287 cpu_abort(cs, "%s exception not implemented\n",
1288 powerpc_excp_name(excp));
1289 break;
1290 default:
1291 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1292 break;
1295 #if defined(TARGET_PPC64)
1296 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1297 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
1298 new_msr |= (target_ulong)1 << MSR_CM;
1299 } else {
1300 vector = (uint32_t)vector;
1302 #endif
1304 /* Save PC */
1305 env->spr[srr0] = env->nip;
1307 /* Save MSR */
1308 env->spr[srr1] = msr;
1310 powerpc_set_excp_state(cpu, vector, new_msr);
1314 * When running a nested HV guest under vhyp, external interrupts are
1315 * delivered as HVIRT.
1317 static bool books_vhyp_promotes_external_to_hvirt(PowerPCCPU *cpu)
1319 if (cpu->vhyp) {
1320 return vhyp_cpu_in_nested(cpu);
1322 return false;
1325 #ifdef TARGET_PPC64
1327 * When running under vhyp, hcalls are always intercepted and sent to the
1328 * vhc->hypercall handler.
1330 static bool books_vhyp_handles_hcall(PowerPCCPU *cpu)
1332 if (cpu->vhyp) {
1333 return !vhyp_cpu_in_nested(cpu);
1335 return false;
1339 * When running a nested KVM HV guest under vhyp, HV exceptions are not
1340 * delivered to the guest (because there is no concept of HV support), but
1341 * rather they are sent tothe vhyp to exit from the L2 back to the L1 and
1342 * return from the H_ENTER_NESTED hypercall.
1344 static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu)
1346 if (cpu->vhyp) {
1347 return vhyp_cpu_in_nested(cpu);
1349 return false;
1352 #ifdef CONFIG_TCG
1353 static bool is_prefix_insn(CPUPPCState *env, uint32_t insn)
1355 if (!(env->insns_flags2 & PPC2_ISA310)) {
1356 return false;
1358 return ((insn & 0xfc000000) == 0x04000000);
1361 static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
1363 CPUPPCState *env = &cpu->env;
1365 if (!tcg_enabled()) {
1367 * This does not load instructions and set the prefix bit correctly
1368 * for injected interrupts with KVM. That may have to be discovered
1369 * and set by the KVM layer before injecting.
1371 return false;
1374 switch (excp) {
1375 case POWERPC_EXCP_HDSI:
1376 /* HDSI PRTABLE_FAULT has the originating access type in error_code */
1377 if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
1378 (env->error_code == MMU_INST_FETCH)) {
1380 * Fetch failed due to partition scope translation, so prefix
1381 * indication is not relevant (and attempting to load the
1382 * instruction at NIP would cause recursive faults with the same
1383 * translation).
1385 break;
1387 /* fall through */
1388 case POWERPC_EXCP_MCHECK:
1389 case POWERPC_EXCP_DSI:
1390 case POWERPC_EXCP_DSEG:
1391 case POWERPC_EXCP_ALIGN:
1392 case POWERPC_EXCP_PROGRAM:
1393 case POWERPC_EXCP_FPU:
1394 case POWERPC_EXCP_TRACE:
1395 case POWERPC_EXCP_HV_EMU:
1396 case POWERPC_EXCP_VPU:
1397 case POWERPC_EXCP_VSXU:
1398 case POWERPC_EXCP_FU:
1399 case POWERPC_EXCP_HV_FU: {
1400 uint32_t insn = ppc_ldl_code(env, env->nip);
1401 if (is_prefix_insn(env, insn)) {
1402 return true;
1404 break;
1406 default:
1407 break;
1409 return false;
1411 #else
1412 static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
1414 return false;
1416 #endif
1418 static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1420 CPUState *cs = CPU(cpu);
1421 CPUPPCState *env = &cpu->env;
1422 target_ulong msr, new_msr, vector;
1423 int srr0, srr1, lev = -1;
1425 /* new srr1 value excluding must-be-zero bits */
1426 msr = env->msr & ~0x783f0000ULL;
1429 * new interrupt handler msr preserves existing HV and ME unless
1430 * explicitly overriden
1432 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1434 /* target registers */
1435 srr0 = SPR_SRR0;
1436 srr1 = SPR_SRR1;
1439 * check for special resume at 0x100 from doze/nap/sleep/winkle on
1440 * P7/P8/P9
1442 if (env->resume_as_sreset) {
1443 excp = powerpc_reset_wakeup(cs, env, excp, &msr);
1447 * We don't want to generate a Hypervisor Emulation Assistance
1448 * Interrupt if we don't have HVB in msr_mask (PAPR mode),
1449 * unless running a nested-hv guest, in which case the L1
1450 * kernel wants the interrupt.
1452 if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB) &&
1453 !books_vhyp_handles_hv_excp(cpu)) {
1454 excp = POWERPC_EXCP_PROGRAM;
1457 vector = env->excp_vectors[excp];
1458 if (vector == (target_ulong)-1ULL) {
1459 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1460 excp);
1463 vector |= env->excp_prefix;
1465 if (is_prefix_insn_excp(cpu, excp)) {
1466 msr |= PPC_BIT(34);
1469 switch (excp) {
1470 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1471 if (!FIELD_EX64(env->msr, MSR, ME)) {
1473 * Machine check exception is not enabled. Enter
1474 * checkstop state.
1476 fprintf(stderr, "Machine check while not allowed. "
1477 "Entering checkstop state\n");
1478 if (qemu_log_separate()) {
1479 qemu_log("Machine check while not allowed. "
1480 "Entering checkstop state\n");
1482 cs->halted = 1;
1483 cpu_interrupt_exittb(cs);
1485 if (env->msr_mask & MSR_HVB) {
1487 * ISA specifies HV, but can be delivered to guest with HV
1488 * clear (e.g., see FWNMI in PAPR).
1490 new_msr |= (target_ulong)MSR_HVB;
1493 /* machine check exceptions don't have ME set */
1494 new_msr &= ~((target_ulong)1 << MSR_ME);
1496 break;
1497 case POWERPC_EXCP_DSI: /* Data storage exception */
1498 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1499 break;
1500 case POWERPC_EXCP_ISI: /* Instruction storage exception */
1501 trace_ppc_excp_isi(msr, env->nip);
1502 msr |= env->error_code;
1503 break;
1504 case POWERPC_EXCP_EXTERNAL: /* External input */
1506 bool lpes0;
1509 * LPES0 is only taken into consideration if we support HV
1510 * mode for this CPU.
1512 if (!env->has_hv_mode) {
1513 break;
1516 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1518 if (!lpes0) {
1519 new_msr |= (target_ulong)MSR_HVB;
1520 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1521 srr0 = SPR_HSRR0;
1522 srr1 = SPR_HSRR1;
1525 break;
1527 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1528 /* Optional DSISR update was removed from ISA v3.0 */
1529 if (!(env->insns_flags2 & PPC2_ISA300)) {
1530 /* Get rS/rD and rA from faulting opcode */
1532 * Note: the opcode fields will not be set properly for a
1533 * direct store load/store, but nobody cares as nobody
1534 * actually uses direct store segments.
1536 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1538 break;
1539 case POWERPC_EXCP_PROGRAM: /* Program exception */
1540 switch (env->error_code & ~0xF) {
1541 case POWERPC_EXCP_FP:
1542 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1543 trace_ppc_excp_fp_ignore();
1544 powerpc_reset_excp_state(cpu);
1545 return;
1549 * FP exceptions always have NIP pointing to the faulting
1550 * instruction, so always use store_next and claim we are
1551 * precise in the MSR.
1553 msr |= 0x00100000;
1554 break;
1555 case POWERPC_EXCP_INVAL:
1556 trace_ppc_excp_inval(env->nip);
1557 msr |= 0x00080000;
1558 break;
1559 case POWERPC_EXCP_PRIV:
1560 msr |= 0x00040000;
1561 break;
1562 case POWERPC_EXCP_TRAP:
1563 msr |= 0x00020000;
1564 break;
1565 default:
1566 /* Should never occur */
1567 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1568 env->error_code);
1569 break;
1571 break;
1572 case POWERPC_EXCP_SYSCALL: /* System call exception */
1573 lev = env->error_code;
1575 if ((lev == 1) && cpu->vhyp) {
1576 dump_hcall(env);
1577 } else {
1578 dump_syscall(env);
1582 * We need to correct the NIP which in this case is supposed
1583 * to point to the next instruction
1585 env->nip += 4;
1587 /* "PAPR mode" built-in hypercall emulation */
1588 if ((lev == 1) && books_vhyp_handles_hcall(cpu)) {
1589 PPCVirtualHypervisorClass *vhc =
1590 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1591 vhc->hypercall(cpu->vhyp, cpu);
1592 return;
1594 if (lev == 1) {
1595 new_msr |= (target_ulong)MSR_HVB;
1597 break;
1598 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
1599 lev = env->error_code;
1600 dump_syscall(env);
1601 env->nip += 4;
1602 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1603 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1605 vector += lev * 0x20;
1607 env->lr = env->nip;
1608 env->ctr = msr;
1609 break;
1610 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1611 case POWERPC_EXCP_DECR: /* Decrementer exception */
1612 break;
1613 case POWERPC_EXCP_RESET: /* System reset exception */
1614 /* A power-saving exception sets ME, otherwise it is unchanged */
1615 if (FIELD_EX64(env->msr, MSR, POW)) {
1616 /* indicate that we resumed from power save mode */
1617 msr |= 0x10000;
1618 new_msr |= ((target_ulong)1 << MSR_ME);
1620 if (env->msr_mask & MSR_HVB) {
1622 * ISA specifies HV, but can be delivered to guest with HV
1623 * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
1625 new_msr |= (target_ulong)MSR_HVB;
1626 } else {
1627 if (FIELD_EX64(env->msr, MSR, POW)) {
1628 cpu_abort(cs, "Trying to deliver power-saving system reset "
1629 "exception %d with no HV support\n", excp);
1632 break;
1633 case POWERPC_EXCP_DSEG: /* Data segment exception */
1634 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1635 case POWERPC_EXCP_TRACE: /* Trace exception */
1636 case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
1637 case POWERPC_EXCP_PERFM: /* Performance monitor interrupt */
1638 break;
1639 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
1640 msr |= env->error_code;
1641 /* fall through */
1642 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1643 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1644 case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
1645 case POWERPC_EXCP_HV_EMU:
1646 case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
1647 srr0 = SPR_HSRR0;
1648 srr1 = SPR_HSRR1;
1649 new_msr |= (target_ulong)MSR_HVB;
1650 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1651 break;
1652 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1653 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
1654 case POWERPC_EXCP_FU: /* Facility unavailable exception */
1655 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1656 break;
1657 case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
1658 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1659 srr0 = SPR_HSRR0;
1660 srr1 = SPR_HSRR1;
1661 new_msr |= (target_ulong)MSR_HVB;
1662 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1663 break;
1664 case POWERPC_EXCP_PERFM_EBB: /* Performance Monitor EBB Exception */
1665 case POWERPC_EXCP_EXTERNAL_EBB: /* External EBB Exception */
1666 env->spr[SPR_BESCR] &= ~BESCR_GE;
1669 * Save NIP for rfebb insn in SPR_EBBRR. Next nip is
1670 * stored in the EBB Handler SPR_EBBHR.
1672 env->spr[SPR_EBBRR] = env->nip;
1673 powerpc_set_excp_state(cpu, env->spr[SPR_EBBHR], env->msr);
1676 * This exception is handled in userspace. No need to proceed.
1678 return;
1679 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1680 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1681 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1682 case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */
1683 cpu_abort(cs, "%s exception not implemented\n",
1684 powerpc_excp_name(excp));
1685 break;
1686 default:
1687 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1688 break;
1692 * Sort out endianness of interrupt, this differs depending on the
1693 * CPU, the HV mode, etc...
1695 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1696 new_msr |= (target_ulong)1 << MSR_LE;
1699 new_msr |= (target_ulong)1 << MSR_SF;
1701 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1702 /* Save PC */
1703 env->spr[srr0] = env->nip;
1705 /* Save MSR */
1706 env->spr[srr1] = msr;
1709 if ((new_msr & MSR_HVB) && books_vhyp_handles_hv_excp(cpu)) {
1710 PPCVirtualHypervisorClass *vhc =
1711 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1712 /* Deliver interrupt to L1 by returning from the H_ENTER_NESTED call */
1713 vhc->deliver_hv_excp(cpu, excp);
1715 powerpc_reset_excp_state(cpu);
1717 } else {
1718 /* Sanity check */
1719 if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
1720 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1721 "no HV support\n", excp);
1724 /* This can update new_msr and vector if AIL applies */
1725 ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
1727 powerpc_set_excp_state(cpu, vector, new_msr);
1730 #else
1731 static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1733 g_assert_not_reached();
1735 #endif
1737 static void powerpc_excp(PowerPCCPU *cpu, int excp)
1739 CPUState *cs = CPU(cpu);
1740 CPUPPCState *env = &cpu->env;
1742 if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1743 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1746 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1747 " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1748 excp, env->error_code);
1749 env->excp_stats[excp]++;
1751 switch (env->excp_model) {
1752 case POWERPC_EXCP_40x:
1753 powerpc_excp_40x(cpu, excp);
1754 break;
1755 case POWERPC_EXCP_6xx:
1756 powerpc_excp_6xx(cpu, excp);
1757 break;
1758 case POWERPC_EXCP_7xx:
1759 powerpc_excp_7xx(cpu, excp);
1760 break;
1761 case POWERPC_EXCP_74xx:
1762 powerpc_excp_74xx(cpu, excp);
1763 break;
1764 case POWERPC_EXCP_BOOKE:
1765 powerpc_excp_booke(cpu, excp);
1766 break;
1767 case POWERPC_EXCP_970:
1768 case POWERPC_EXCP_POWER7:
1769 case POWERPC_EXCP_POWER8:
1770 case POWERPC_EXCP_POWER9:
1771 case POWERPC_EXCP_POWER10:
1772 powerpc_excp_books(cpu, excp);
1773 break;
1774 default:
1775 g_assert_not_reached();
1779 void ppc_cpu_do_interrupt(CPUState *cs)
1781 PowerPCCPU *cpu = POWERPC_CPU(cs);
1783 powerpc_excp(cpu, cs->exception_index);
1786 #if defined(TARGET_PPC64)
1787 #define P7_UNUSED_INTERRUPTS \
1788 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_HVIRT | PPC_INTERRUPT_CEXT | \
1789 PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
1790 PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
1791 PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
1793 static int p7_interrupt_powersave(CPUPPCState *env)
1795 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1796 (env->spr[SPR_LPCR] & LPCR_P7_PECE0)) {
1797 return PPC_INTERRUPT_EXT;
1799 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1800 (env->spr[SPR_LPCR] & LPCR_P7_PECE1)) {
1801 return PPC_INTERRUPT_DECR;
1803 if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
1804 (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
1805 return PPC_INTERRUPT_MCK;
1807 if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
1808 (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
1809 return PPC_INTERRUPT_HMI;
1811 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
1812 return PPC_INTERRUPT_RESET;
1814 return 0;
1817 static int p7_next_unmasked_interrupt(CPUPPCState *env)
1819 PowerPCCPU *cpu = env_archcpu(env);
1820 CPUState *cs = CPU(cpu);
1821 /* Ignore MSR[EE] when coming out of some power management states */
1822 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1824 assert((env->pending_interrupts & P7_UNUSED_INTERRUPTS) == 0);
1826 if (cs->halted) {
1827 /* LPCR[PECE] controls which interrupts can exit power-saving mode */
1828 return p7_interrupt_powersave(env);
1831 /* Machine check exception */
1832 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1833 return PPC_INTERRUPT_MCK;
1836 /* Hypervisor decrementer exception */
1837 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
1838 /* LPCR will be clear when not supported so this will work */
1839 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1840 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1841 /* HDEC clears on delivery */
1842 return PPC_INTERRUPT_HDECR;
1846 /* External interrupt can ignore MSR:EE under some circumstances */
1847 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
1848 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1849 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1850 /* HEIC blocks delivery to the hypervisor */
1851 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1852 !FIELD_EX64(env->msr, MSR, PR))) ||
1853 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1854 return PPC_INTERRUPT_EXT;
1857 if (msr_ee != 0) {
1858 /* Decrementer exception */
1859 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
1860 return PPC_INTERRUPT_DECR;
1862 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
1863 return PPC_INTERRUPT_PERFM;
1867 return 0;
1870 #define P8_UNUSED_INTERRUPTS \
1871 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_HVIRT | \
1872 PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \
1873 PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1875 static int p8_interrupt_powersave(CPUPPCState *env)
1877 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1878 (env->spr[SPR_LPCR] & LPCR_P8_PECE2)) {
1879 return PPC_INTERRUPT_EXT;
1881 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1882 (env->spr[SPR_LPCR] & LPCR_P8_PECE3)) {
1883 return PPC_INTERRUPT_DECR;
1885 if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
1886 (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
1887 return PPC_INTERRUPT_MCK;
1889 if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
1890 (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
1891 return PPC_INTERRUPT_HMI;
1893 if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
1894 (env->spr[SPR_LPCR] & LPCR_P8_PECE0)) {
1895 return PPC_INTERRUPT_DOORBELL;
1897 if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
1898 (env->spr[SPR_LPCR] & LPCR_P8_PECE1)) {
1899 return PPC_INTERRUPT_HDOORBELL;
1901 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
1902 return PPC_INTERRUPT_RESET;
1904 return 0;
1907 static int p8_next_unmasked_interrupt(CPUPPCState *env)
1909 PowerPCCPU *cpu = env_archcpu(env);
1910 CPUState *cs = CPU(cpu);
1911 /* Ignore MSR[EE] when coming out of some power management states */
1912 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1914 assert((env->pending_interrupts & P8_UNUSED_INTERRUPTS) == 0);
1916 if (cs->halted) {
1917 /* LPCR[PECE] controls which interrupts can exit power-saving mode */
1918 return p8_interrupt_powersave(env);
1921 /* Machine check exception */
1922 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1923 return PPC_INTERRUPT_MCK;
1926 /* Hypervisor decrementer exception */
1927 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
1928 /* LPCR will be clear when not supported so this will work */
1929 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1930 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1931 /* HDEC clears on delivery */
1932 return PPC_INTERRUPT_HDECR;
1936 /* External interrupt can ignore MSR:EE under some circumstances */
1937 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
1938 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1939 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1940 /* HEIC blocks delivery to the hypervisor */
1941 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1942 !FIELD_EX64(env->msr, MSR, PR))) ||
1943 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1944 return PPC_INTERRUPT_EXT;
1947 if (msr_ee != 0) {
1948 /* Decrementer exception */
1949 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
1950 return PPC_INTERRUPT_DECR;
1952 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
1953 return PPC_INTERRUPT_DOORBELL;
1955 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
1956 return PPC_INTERRUPT_HDOORBELL;
1958 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
1959 return PPC_INTERRUPT_PERFM;
1961 /* EBB exception */
1962 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
1964 * EBB exception must be taken in problem state and
1965 * with BESCR_GE set.
1967 if (FIELD_EX64(env->msr, MSR, PR) &&
1968 (env->spr[SPR_BESCR] & BESCR_GE)) {
1969 return PPC_INTERRUPT_EBB;
1974 return 0;
1977 #define P9_UNUSED_INTERRUPTS \
1978 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_CEXT | \
1979 PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
1980 PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1982 static int p9_interrupt_powersave(CPUPPCState *env)
1984 /* External Exception */
1985 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1986 (env->spr[SPR_LPCR] & LPCR_EEE)) {
1987 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1988 if (!heic || !FIELD_EX64_HV(env->msr) ||
1989 FIELD_EX64(env->msr, MSR, PR)) {
1990 return PPC_INTERRUPT_EXT;
1993 /* Decrementer Exception */
1994 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1995 (env->spr[SPR_LPCR] & LPCR_DEE)) {
1996 return PPC_INTERRUPT_DECR;
1998 /* Machine Check or Hypervisor Maintenance Exception */
1999 if (env->spr[SPR_LPCR] & LPCR_OEE) {
2000 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
2001 return PPC_INTERRUPT_MCK;
2003 if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
2004 return PPC_INTERRUPT_HMI;
2007 /* Privileged Doorbell Exception */
2008 if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
2009 (env->spr[SPR_LPCR] & LPCR_PDEE)) {
2010 return PPC_INTERRUPT_DOORBELL;
2012 /* Hypervisor Doorbell Exception */
2013 if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
2014 (env->spr[SPR_LPCR] & LPCR_HDEE)) {
2015 return PPC_INTERRUPT_HDOORBELL;
2017 /* Hypervisor virtualization exception */
2018 if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
2019 (env->spr[SPR_LPCR] & LPCR_HVEE)) {
2020 return PPC_INTERRUPT_HVIRT;
2022 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
2023 return PPC_INTERRUPT_RESET;
2025 return 0;
2028 static int p9_next_unmasked_interrupt(CPUPPCState *env)
2030 PowerPCCPU *cpu = env_archcpu(env);
2031 CPUState *cs = CPU(cpu);
2032 /* Ignore MSR[EE] when coming out of some power management states */
2033 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
2035 assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
2037 if (cs->halted) {
2038 if (env->spr[SPR_PSSCR] & PSSCR_EC) {
2040 * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can
2041 * wakeup the processor
2043 return p9_interrupt_powersave(env);
2044 } else {
2046 * When it's clear, any system-caused exception exits power-saving
2047 * mode, even the ones that gate on MSR[EE].
2049 msr_ee = true;
2053 /* Machine check exception */
2054 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
2055 return PPC_INTERRUPT_MCK;
2058 /* Hypervisor decrementer exception */
2059 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
2060 /* LPCR will be clear when not supported so this will work */
2061 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
2062 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
2063 /* HDEC clears on delivery */
2064 return PPC_INTERRUPT_HDECR;
2068 /* Hypervisor virtualization interrupt */
2069 if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
2070 /* LPCR will be clear when not supported so this will work */
2071 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
2072 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) {
2073 return PPC_INTERRUPT_HVIRT;
2077 /* External interrupt can ignore MSR:EE under some circumstances */
2078 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
2079 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
2080 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
2081 /* HEIC blocks delivery to the hypervisor */
2082 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
2083 !FIELD_EX64(env->msr, MSR, PR))) ||
2084 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
2085 return PPC_INTERRUPT_EXT;
2088 if (msr_ee != 0) {
2089 /* Decrementer exception */
2090 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
2091 return PPC_INTERRUPT_DECR;
2093 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
2094 return PPC_INTERRUPT_DOORBELL;
2096 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
2097 return PPC_INTERRUPT_HDOORBELL;
2099 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
2100 return PPC_INTERRUPT_PERFM;
2102 /* EBB exception */
2103 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
2105 * EBB exception must be taken in problem state and
2106 * with BESCR_GE set.
2108 if (FIELD_EX64(env->msr, MSR, PR) &&
2109 (env->spr[SPR_BESCR] & BESCR_GE)) {
2110 return PPC_INTERRUPT_EBB;
2115 return 0;
2117 #endif
2119 static int ppc_next_unmasked_interrupt_generic(CPUPPCState *env)
2121 bool async_deliver;
2123 /* External reset */
2124 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
2125 return PPC_INTERRUPT_RESET;
2127 /* Machine check exception */
2128 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
2129 return PPC_INTERRUPT_MCK;
2131 #if 0 /* TODO */
2132 /* External debug exception */
2133 if (env->pending_interrupts & PPC_INTERRUPT_DEBUG) {
2134 return PPC_INTERRUPT_DEBUG;
2136 #endif
2139 * For interrupts that gate on MSR:EE, we need to do something a
2140 * bit more subtle, as we need to let them through even when EE is
2141 * clear when coming out of some power management states (in order
2142 * for them to become a 0x100).
2144 async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
2146 /* Hypervisor decrementer exception */
2147 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
2148 /* LPCR will be clear when not supported so this will work */
2149 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
2150 if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) {
2151 /* HDEC clears on delivery */
2152 return PPC_INTERRUPT_HDECR;
2156 /* Hypervisor virtualization interrupt */
2157 if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
2158 /* LPCR will be clear when not supported so this will work */
2159 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
2160 if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) {
2161 return PPC_INTERRUPT_HVIRT;
2165 /* External interrupt can ignore MSR:EE under some circumstances */
2166 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
2167 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
2168 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
2169 /* HEIC blocks delivery to the hypervisor */
2170 if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) &&
2171 !FIELD_EX64(env->msr, MSR, PR))) ||
2172 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
2173 return PPC_INTERRUPT_EXT;
2176 if (FIELD_EX64(env->msr, MSR, CE)) {
2177 /* External critical interrupt */
2178 if (env->pending_interrupts & PPC_INTERRUPT_CEXT) {
2179 return PPC_INTERRUPT_CEXT;
2182 if (async_deliver != 0) {
2183 /* Watchdog timer on embedded PowerPC */
2184 if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
2185 return PPC_INTERRUPT_WDT;
2187 if (env->pending_interrupts & PPC_INTERRUPT_CDOORBELL) {
2188 return PPC_INTERRUPT_CDOORBELL;
2190 /* Fixed interval timer on embedded PowerPC */
2191 if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
2192 return PPC_INTERRUPT_FIT;
2194 /* Programmable interval timer on embedded PowerPC */
2195 if (env->pending_interrupts & PPC_INTERRUPT_PIT) {
2196 return PPC_INTERRUPT_PIT;
2198 /* Decrementer exception */
2199 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
2200 return PPC_INTERRUPT_DECR;
2202 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
2203 return PPC_INTERRUPT_DOORBELL;
2205 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
2206 return PPC_INTERRUPT_HDOORBELL;
2208 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
2209 return PPC_INTERRUPT_PERFM;
2211 /* Thermal interrupt */
2212 if (env->pending_interrupts & PPC_INTERRUPT_THERM) {
2213 return PPC_INTERRUPT_THERM;
2215 /* EBB exception */
2216 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
2218 * EBB exception must be taken in problem state and
2219 * with BESCR_GE set.
2221 if (FIELD_EX64(env->msr, MSR, PR) &&
2222 (env->spr[SPR_BESCR] & BESCR_GE)) {
2223 return PPC_INTERRUPT_EBB;
2228 return 0;
2231 static int ppc_next_unmasked_interrupt(CPUPPCState *env)
2233 switch (env->excp_model) {
2234 #if defined(TARGET_PPC64)
2235 case POWERPC_EXCP_POWER7:
2236 return p7_next_unmasked_interrupt(env);
2237 case POWERPC_EXCP_POWER8:
2238 return p8_next_unmasked_interrupt(env);
2239 case POWERPC_EXCP_POWER9:
2240 case POWERPC_EXCP_POWER10:
2241 return p9_next_unmasked_interrupt(env);
2242 #endif
2243 default:
2244 return ppc_next_unmasked_interrupt_generic(env);
2249 * Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
2250 * delivered and clears CPU_INTERRUPT_HARD otherwise.
2252 * This method is called by ppc_set_interrupt when an interrupt is raised or
2253 * lowered, and should also be called whenever an interrupt masking condition
2254 * is changed, e.g.:
2255 * - When relevant bits of MSR are altered, like EE, HV, PR, etc.;
2256 * - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.;
2257 * - When PSSCR[EC] or env->resume_as_sreset are changed;
2258 * - When cs->halted is changed and the CPU has a different interrupt masking
2259 * logic in power-saving mode (e.g., POWER7/8/9/10);
2261 void ppc_maybe_interrupt(CPUPPCState *env)
2263 CPUState *cs = env_cpu(env);
2264 QEMU_IOTHREAD_LOCK_GUARD();
2266 if (ppc_next_unmasked_interrupt(env)) {
2267 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2268 } else {
2269 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2273 #if defined(TARGET_PPC64)
2274 static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
2276 PowerPCCPU *cpu = env_archcpu(env);
2277 CPUState *cs = env_cpu(env);
2279 switch (interrupt) {
2280 case PPC_INTERRUPT_MCK: /* Machine check exception */
2281 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2282 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2283 break;
2285 case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2286 /* HDEC clears on delivery */
2287 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2288 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2289 break;
2291 case PPC_INTERRUPT_EXT:
2292 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2293 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2294 } else {
2295 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2297 break;
2299 case PPC_INTERRUPT_DECR: /* Decrementer exception */
2300 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2301 break;
2302 case PPC_INTERRUPT_PERFM:
2303 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2304 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2305 break;
2306 case 0:
2308 * This is a bug ! It means that has_work took us out of halt without
2309 * anything to deliver while in a PM state that requires getting
2310 * out via a 0x100
2312 * This means we will incorrectly execute past the power management
2313 * instruction instead of triggering a reset.
2315 * It generally means a discrepancy between the wakeup conditions in the
2316 * processor has_work implementation and the logic in this function.
2318 assert(!env->resume_as_sreset);
2319 break;
2320 default:
2321 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2325 static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
2327 PowerPCCPU *cpu = env_archcpu(env);
2328 CPUState *cs = env_cpu(env);
2330 switch (interrupt) {
2331 case PPC_INTERRUPT_MCK: /* Machine check exception */
2332 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2333 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2334 break;
2336 case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2337 /* HDEC clears on delivery */
2338 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2339 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2340 break;
2342 case PPC_INTERRUPT_EXT:
2343 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2344 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2345 } else {
2346 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2348 break;
2350 case PPC_INTERRUPT_DECR: /* Decrementer exception */
2351 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2352 break;
2353 case PPC_INTERRUPT_DOORBELL:
2354 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2355 if (is_book3s_arch2x(env)) {
2356 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2357 } else {
2358 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2360 break;
2361 case PPC_INTERRUPT_HDOORBELL:
2362 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2363 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2364 break;
2365 case PPC_INTERRUPT_PERFM:
2366 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2367 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2368 break;
2369 case PPC_INTERRUPT_EBB: /* EBB exception */
2370 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2371 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2372 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2373 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2374 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2376 break;
2377 case 0:
2379 * This is a bug ! It means that has_work took us out of halt without
2380 * anything to deliver while in a PM state that requires getting
2381 * out via a 0x100
2383 * This means we will incorrectly execute past the power management
2384 * instruction instead of triggering a reset.
2386 * It generally means a discrepancy between the wakeup conditions in the
2387 * processor has_work implementation and the logic in this function.
2389 assert(!env->resume_as_sreset);
2390 break;
2391 default:
2392 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2396 static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
2398 PowerPCCPU *cpu = env_archcpu(env);
2399 CPUState *cs = env_cpu(env);
2401 if (cs->halted && !(env->spr[SPR_PSSCR] & PSSCR_EC) &&
2402 !FIELD_EX64(env->msr, MSR, EE)) {
2404 * A pending interrupt took us out of power-saving, but MSR[EE] says
2405 * that we should return to NIP+4 instead of delivering it.
2407 return;
2410 switch (interrupt) {
2411 case PPC_INTERRUPT_MCK: /* Machine check exception */
2412 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2413 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2414 break;
2416 case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2417 /* HDEC clears on delivery */
2418 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2419 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2420 break;
2421 case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */
2422 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2423 break;
2425 case PPC_INTERRUPT_EXT:
2426 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2427 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2428 } else {
2429 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2431 break;
2433 case PPC_INTERRUPT_DECR: /* Decrementer exception */
2434 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2435 break;
2436 case PPC_INTERRUPT_DOORBELL:
2437 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2438 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2439 break;
2440 case PPC_INTERRUPT_HDOORBELL:
2441 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2442 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2443 break;
2444 case PPC_INTERRUPT_PERFM:
2445 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2446 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2447 break;
2448 case PPC_INTERRUPT_EBB: /* EBB exception */
2449 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2450 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2451 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2452 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2453 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2455 break;
2456 case 0:
2458 * This is a bug ! It means that has_work took us out of halt without
2459 * anything to deliver while in a PM state that requires getting
2460 * out via a 0x100
2462 * This means we will incorrectly execute past the power management
2463 * instruction instead of triggering a reset.
2465 * It generally means a discrepancy between the wakeup conditions in the
2466 * processor has_work implementation and the logic in this function.
2468 assert(!env->resume_as_sreset);
2469 break;
2470 default:
2471 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2474 #endif
2476 static void ppc_deliver_interrupt_generic(CPUPPCState *env, int interrupt)
2478 PowerPCCPU *cpu = env_archcpu(env);
2479 CPUState *cs = env_cpu(env);
2481 switch (interrupt) {
2482 case PPC_INTERRUPT_RESET: /* External reset */
2483 env->pending_interrupts &= ~PPC_INTERRUPT_RESET;
2484 powerpc_excp(cpu, POWERPC_EXCP_RESET);
2485 break;
2486 case PPC_INTERRUPT_MCK: /* Machine check exception */
2487 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2488 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2489 break;
2491 case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
2492 /* HDEC clears on delivery */
2493 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2494 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2495 break;
2496 case PPC_INTERRUPT_HVIRT: /* Hypervisor virtualization interrupt */
2497 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2498 break;
2500 case PPC_INTERRUPT_EXT:
2501 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2502 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2503 } else {
2504 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2506 break;
2507 case PPC_INTERRUPT_CEXT: /* External critical interrupt */
2508 powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
2509 break;
2511 case PPC_INTERRUPT_WDT: /* Watchdog timer on embedded PowerPC */
2512 env->pending_interrupts &= ~PPC_INTERRUPT_WDT;
2513 powerpc_excp(cpu, POWERPC_EXCP_WDT);
2514 break;
2515 case PPC_INTERRUPT_CDOORBELL:
2516 env->pending_interrupts &= ~PPC_INTERRUPT_CDOORBELL;
2517 powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
2518 break;
2519 case PPC_INTERRUPT_FIT: /* Fixed interval timer on embedded PowerPC */
2520 env->pending_interrupts &= ~PPC_INTERRUPT_FIT;
2521 powerpc_excp(cpu, POWERPC_EXCP_FIT);
2522 break;
2523 case PPC_INTERRUPT_PIT: /* Programmable interval timer on embedded ppc */
2524 env->pending_interrupts &= ~PPC_INTERRUPT_PIT;
2525 powerpc_excp(cpu, POWERPC_EXCP_PIT);
2526 break;
2527 case PPC_INTERRUPT_DECR: /* Decrementer exception */
2528 if (ppc_decr_clear_on_delivery(env)) {
2529 env->pending_interrupts &= ~PPC_INTERRUPT_DECR;
2531 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2532 break;
2533 case PPC_INTERRUPT_DOORBELL:
2534 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2535 if (is_book3s_arch2x(env)) {
2536 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2537 } else {
2538 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2540 break;
2541 case PPC_INTERRUPT_HDOORBELL:
2542 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2543 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2544 break;
2545 case PPC_INTERRUPT_PERFM:
2546 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2547 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2548 break;
2549 case PPC_INTERRUPT_THERM: /* Thermal interrupt */
2550 env->pending_interrupts &= ~PPC_INTERRUPT_THERM;
2551 powerpc_excp(cpu, POWERPC_EXCP_THERM);
2552 break;
2553 case PPC_INTERRUPT_EBB: /* EBB exception */
2554 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2555 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2556 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2557 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2558 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2560 break;
2561 case 0:
2563 * This is a bug ! It means that has_work took us out of halt without
2564 * anything to deliver while in a PM state that requires getting
2565 * out via a 0x100
2567 * This means we will incorrectly execute past the power management
2568 * instruction instead of triggering a reset.
2570 * It generally means a discrepancy between the wakeup conditions in the
2571 * processor has_work implementation and the logic in this function.
2573 assert(!env->resume_as_sreset);
2574 break;
2575 default:
2576 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2580 static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
2582 switch (env->excp_model) {
2583 #if defined(TARGET_PPC64)
2584 case POWERPC_EXCP_POWER7:
2585 p7_deliver_interrupt(env, interrupt);
2586 break;
2587 case POWERPC_EXCP_POWER8:
2588 p8_deliver_interrupt(env, interrupt);
2589 break;
2590 case POWERPC_EXCP_POWER9:
2591 case POWERPC_EXCP_POWER10:
2592 p9_deliver_interrupt(env, interrupt);
2593 break;
2594 #endif
2595 default:
2596 ppc_deliver_interrupt_generic(env, interrupt);
2600 void ppc_cpu_do_system_reset(CPUState *cs)
2602 PowerPCCPU *cpu = POWERPC_CPU(cs);
2604 powerpc_excp(cpu, POWERPC_EXCP_RESET);
2607 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
2609 PowerPCCPU *cpu = POWERPC_CPU(cs);
2610 CPUPPCState *env = &cpu->env;
2611 target_ulong msr = 0;
2614 * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
2615 * been set by KVM.
2617 msr = (1ULL << MSR_ME);
2618 msr |= env->msr & (1ULL << MSR_SF);
2619 if (ppc_interrupts_little_endian(cpu, false)) {
2620 msr |= (1ULL << MSR_LE);
2623 /* Anything for nested required here? MSR[HV] bit? */
2625 powerpc_set_excp_state(cpu, vector, msr);
2628 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
2630 PowerPCCPU *cpu = POWERPC_CPU(cs);
2631 CPUPPCState *env = &cpu->env;
2632 int interrupt;
2634 if ((interrupt_request & CPU_INTERRUPT_HARD) == 0) {
2635 return false;
2638 interrupt = ppc_next_unmasked_interrupt(env);
2639 if (interrupt == 0) {
2640 return false;
2643 ppc_deliver_interrupt(env, interrupt);
2644 if (env->pending_interrupts == 0) {
2645 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2647 return true;
2650 #endif /* !CONFIG_USER_ONLY */
2652 /*****************************************************************************/
2653 /* Exceptions processing helpers */
2655 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
2656 uint32_t error_code, uintptr_t raddr)
2658 CPUState *cs = env_cpu(env);
2660 cs->exception_index = exception;
2661 env->error_code = error_code;
2662 cpu_loop_exit_restore(cs, raddr);
2665 void raise_exception_err(CPUPPCState *env, uint32_t exception,
2666 uint32_t error_code)
2668 raise_exception_err_ra(env, exception, error_code, 0);
2671 void raise_exception(CPUPPCState *env, uint32_t exception)
2673 raise_exception_err_ra(env, exception, 0, 0);
2676 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
2677 uintptr_t raddr)
2679 raise_exception_err_ra(env, exception, 0, raddr);
2682 #ifdef CONFIG_TCG
2683 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
2684 uint32_t error_code)
2686 raise_exception_err_ra(env, exception, error_code, 0);
2689 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
2691 raise_exception_err_ra(env, exception, 0, 0);
2693 #endif
2695 #if !defined(CONFIG_USER_ONLY)
2696 #ifdef CONFIG_TCG
2697 void helper_store_msr(CPUPPCState *env, target_ulong val)
2699 uint32_t excp = hreg_store_msr(env, val, 0);
2701 if (excp != 0) {
2702 CPUState *cs = env_cpu(env);
2703 cpu_interrupt_exittb(cs);
2704 raise_exception(env, excp);
2708 void helper_ppc_maybe_interrupt(CPUPPCState *env)
2710 ppc_maybe_interrupt(env);
2713 #if defined(TARGET_PPC64)
2714 void helper_scv(CPUPPCState *env, uint32_t lev)
2716 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
2717 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
2718 } else {
2719 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
2723 void helper_pminsn(CPUPPCState *env, uint32_t insn)
2725 CPUState *cs;
2727 cs = env_cpu(env);
2728 cs->halted = 1;
2730 /* Condition for waking up at 0x100 */
2731 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
2732 (env->spr[SPR_PSSCR] & PSSCR_EC);
2734 ppc_maybe_interrupt(env);
2736 #endif /* defined(TARGET_PPC64) */
2738 static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
2740 CPUState *cs = env_cpu(env);
2742 /* MSR:POW cannot be set by any form of rfi */
2743 msr &= ~(1ULL << MSR_POW);
2745 /* MSR:TGPR cannot be set by any form of rfi */
2746 if (env->flags & POWERPC_FLAG_TGPR)
2747 msr &= ~(1ULL << MSR_TGPR);
2749 #if defined(TARGET_PPC64)
2750 /* Switching to 32-bit ? Crop the nip */
2751 if (!msr_is_64bit(env, msr)) {
2752 nip = (uint32_t)nip;
2754 #else
2755 nip = (uint32_t)nip;
2756 #endif
2757 /* XXX: beware: this is false if VLE is supported */
2758 env->nip = nip & ~((target_ulong)0x00000003);
2759 hreg_store_msr(env, msr, 1);
2760 trace_ppc_excp_rfi(env->nip, env->msr);
2762 * No need to raise an exception here, as rfi is always the last
2763 * insn of a TB
2765 cpu_interrupt_exittb(cs);
2766 /* Reset the reservation */
2767 env->reserve_addr = -1;
2769 /* Context synchronizing: check if TCG TLB needs flush */
2770 check_tlb_flush(env, false);
2773 void helper_rfi(CPUPPCState *env)
2775 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
2778 #if defined(TARGET_PPC64)
2779 void helper_rfid(CPUPPCState *env)
2782 * The architecture defines a number of rules for which bits can
2783 * change but in practice, we handle this in hreg_store_msr()
2784 * which will be called by do_rfi(), so there is no need to filter
2785 * here
2787 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
2790 void helper_rfscv(CPUPPCState *env)
2792 do_rfi(env, env->lr, env->ctr);
2795 void helper_hrfid(CPUPPCState *env)
2797 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
2799 #endif
2801 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
2802 void helper_rfebb(CPUPPCState *env, target_ulong s)
2804 target_ulong msr = env->msr;
2807 * Handling of BESCR bits 32:33 according to PowerISA v3.1:
2809 * "If BESCR 32:33 != 0b00 the instruction is treated as if
2810 * the instruction form were invalid."
2812 if (env->spr[SPR_BESCR] & BESCR_INVALID) {
2813 raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2814 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
2817 env->nip = env->spr[SPR_EBBRR];
2819 /* Switching to 32-bit ? Crop the nip */
2820 if (!msr_is_64bit(env, msr)) {
2821 env->nip = (uint32_t)env->spr[SPR_EBBRR];
2824 if (s) {
2825 env->spr[SPR_BESCR] |= BESCR_GE;
2826 } else {
2827 env->spr[SPR_BESCR] &= ~BESCR_GE;
2832 * Triggers or queues an 'ebb_excp' EBB exception. All checks
2833 * but FSCR, HFSCR and msr_pr must be done beforehand.
2835 * PowerISA v3.1 isn't clear about whether an EBB should be
2836 * postponed or cancelled if the EBB facility is unavailable.
2837 * Our assumption here is that the EBB is cancelled if both
2838 * FSCR and HFSCR EBB facilities aren't available.
2840 static void do_ebb(CPUPPCState *env, int ebb_excp)
2842 PowerPCCPU *cpu = env_archcpu(env);
2845 * FSCR_EBB and FSCR_IC_EBB are the same bits used with
2846 * HFSCR.
2848 helper_fscr_facility_check(env, FSCR_EBB, 0, FSCR_IC_EBB);
2849 helper_hfscr_facility_check(env, FSCR_EBB, "EBB", FSCR_IC_EBB);
2851 if (ebb_excp == POWERPC_EXCP_PERFM_EBB) {
2852 env->spr[SPR_BESCR] |= BESCR_PMEO;
2853 } else if (ebb_excp == POWERPC_EXCP_EXTERNAL_EBB) {
2854 env->spr[SPR_BESCR] |= BESCR_EEO;
2857 if (FIELD_EX64(env->msr, MSR, PR)) {
2858 powerpc_excp(cpu, ebb_excp);
2859 } else {
2860 ppc_set_irq(cpu, PPC_INTERRUPT_EBB, 1);
2864 void raise_ebb_perfm_exception(CPUPPCState *env)
2866 bool perfm_ebb_enabled = env->spr[SPR_POWER_MMCR0] & MMCR0_EBE &&
2867 env->spr[SPR_BESCR] & BESCR_PME &&
2868 env->spr[SPR_BESCR] & BESCR_GE;
2870 if (!perfm_ebb_enabled) {
2871 return;
2874 do_ebb(env, POWERPC_EXCP_PERFM_EBB);
2876 #endif
2878 /*****************************************************************************/
2879 /* Embedded PowerPC specific helpers */
2880 void helper_40x_rfci(CPUPPCState *env)
2882 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
2885 void helper_rfci(CPUPPCState *env)
2887 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
2890 void helper_rfdi(CPUPPCState *env)
2892 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
2893 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
2896 void helper_rfmci(CPUPPCState *env)
2898 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
2899 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
2901 #endif /* CONFIG_TCG */
2902 #endif /* !defined(CONFIG_USER_ONLY) */
2904 #ifdef CONFIG_TCG
2905 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2906 uint32_t flags)
2908 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
2909 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
2910 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
2911 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
2912 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
2913 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2914 POWERPC_EXCP_TRAP, GETPC());
2918 #if defined(TARGET_PPC64)
2919 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2920 uint32_t flags)
2922 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
2923 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
2924 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
2925 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
2926 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
2927 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2928 POWERPC_EXCP_TRAP, GETPC());
2931 #endif
2932 #endif
2934 #ifdef CONFIG_TCG
2935 static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
2937 const uint16_t c = 0xfffc;
2938 const uint64_t z0 = 0xfa2561cdf44ac398ULL;
2939 uint16_t z = 0, temp;
2940 uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
2942 for (int i = 3; i >= 0; i--) {
2943 k[i] = key & 0xffff;
2944 key >>= 16;
2946 xleft[0] = x & 0xffff;
2947 xright[0] = (x >> 16) & 0xffff;
2949 for (int i = 0; i < 28; i++) {
2950 z = (z0 >> (63 - i)) & 1;
2951 temp = ror16(k[i + 3], 3) ^ k[i + 1];
2952 k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
2955 for (int i = 0; i < 8; i++) {
2956 eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
2957 eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
2958 eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
2959 eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
2962 for (int i = 0; i < 32; i++) {
2963 fxleft[i] = (rol16(xleft[i], 1) &
2964 rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
2965 xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
2966 xright[i + 1] = xleft[i];
2969 return (((uint32_t)xright[32]) << 16) | xleft[32];
2972 static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
2974 uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
2975 uint64_t stage1_h, stage1_l;
2977 for (int i = 0; i < 4; i++) {
2978 stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
2979 stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
2980 stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
2981 stage0_l |= (ra & 0xff) << (8 * 2 * i);
2982 rb >>= 8;
2983 ra >>= 8;
2986 stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
2987 stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
2988 stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
2989 stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
2991 return stage1_h ^ stage1_l;
2994 static void do_hash(CPUPPCState *env, target_ulong ea, target_ulong ra,
2995 target_ulong rb, uint64_t key, bool store)
2997 uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;
2999 if (store) {
3000 cpu_stq_data_ra(env, ea, calculated_hash, GETPC());
3001 } else {
3002 loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());
3003 if (loaded_hash != calculated_hash) {
3004 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
3005 POWERPC_EXCP_TRAP, GETPC());
3010 #include "qemu/guest-random.h"
3012 #ifdef TARGET_PPC64
3013 #define HELPER_HASH(op, key, store, dexcr_aspect) \
3014 void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
3015 target_ulong rb) \
3017 if (env->msr & R_MSR_PR_MASK) { \
3018 if (!(env->spr[SPR_DEXCR] & R_DEXCR_PRO_##dexcr_aspect##_MASK || \
3019 env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
3020 return; \
3021 } else if (!(env->msr & R_MSR_HV_MASK)) { \
3022 if (!(env->spr[SPR_DEXCR] & R_DEXCR_PNH_##dexcr_aspect##_MASK || \
3023 env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
3024 return; \
3025 } else if (!(env->msr & R_MSR_S_MASK)) { \
3026 if (!(env->spr[SPR_HDEXCR] & R_HDEXCR_HNU_##dexcr_aspect##_MASK)) \
3027 return; \
3030 do_hash(env, ea, ra, rb, key, store); \
3032 #else
3033 #define HELPER_HASH(op, key, store, dexcr_aspect) \
3034 void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
3035 target_ulong rb) \
3037 do_hash(env, ea, ra, rb, key, store); \
3039 #endif /* TARGET_PPC64 */
3041 HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true, NPHIE)
3042 HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false, NPHIE)
3043 HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true, PHIE)
3044 HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false, PHIE)
3045 #endif /* CONFIG_TCG */
3047 #if !defined(CONFIG_USER_ONLY)
3049 #ifdef CONFIG_TCG
3051 /* Embedded.Processor Control */
3052 static int dbell2irq(target_ulong rb)
3054 int msg = rb & DBELL_TYPE_MASK;
3055 int irq = -1;
3057 switch (msg) {
3058 case DBELL_TYPE_DBELL:
3059 irq = PPC_INTERRUPT_DOORBELL;
3060 break;
3061 case DBELL_TYPE_DBELL_CRIT:
3062 irq = PPC_INTERRUPT_CDOORBELL;
3063 break;
3064 case DBELL_TYPE_G_DBELL:
3065 case DBELL_TYPE_G_DBELL_CRIT:
3066 case DBELL_TYPE_G_DBELL_MC:
3067 /* XXX implement */
3068 default:
3069 break;
3072 return irq;
3075 void helper_msgclr(CPUPPCState *env, target_ulong rb)
3077 int irq = dbell2irq(rb);
3079 if (irq < 0) {
3080 return;
3083 ppc_set_irq(env_archcpu(env), irq, 0);
3086 void helper_msgsnd(target_ulong rb)
3088 int irq = dbell2irq(rb);
3089 int pir = rb & DBELL_PIRTAG_MASK;
3090 CPUState *cs;
3092 if (irq < 0) {
3093 return;
3096 qemu_mutex_lock_iothread();
3097 CPU_FOREACH(cs) {
3098 PowerPCCPU *cpu = POWERPC_CPU(cs);
3099 CPUPPCState *cenv = &cpu->env;
3101 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
3102 ppc_set_irq(cpu, irq, 1);
3105 qemu_mutex_unlock_iothread();
3108 /* Server Processor Control */
3110 static bool dbell_type_server(target_ulong rb)
3113 * A Directed Hypervisor Doorbell message is sent only if the
3114 * message type is 5. All other types are reserved and the
3115 * instruction is a no-op
3117 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
3120 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
3122 if (!dbell_type_server(rb)) {
3123 return;
3126 ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
3129 static void book3s_msgsnd_common(int pir, int irq)
3131 CPUState *cs;
3133 qemu_mutex_lock_iothread();
3134 CPU_FOREACH(cs) {
3135 PowerPCCPU *cpu = POWERPC_CPU(cs);
3136 CPUPPCState *cenv = &cpu->env;
3138 /* TODO: broadcast message to all threads of the same processor */
3139 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
3140 ppc_set_irq(cpu, irq, 1);
3143 qemu_mutex_unlock_iothread();
3146 void helper_book3s_msgsnd(target_ulong rb)
3148 int pir = rb & DBELL_PROCIDTAG_MASK;
3150 if (!dbell_type_server(rb)) {
3151 return;
3154 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
3157 #if defined(TARGET_PPC64)
3158 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
3160 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
3162 if (!dbell_type_server(rb)) {
3163 return;
3166 ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_DOORBELL, 0);
3170 * sends a message to other threads that are on the same
3171 * multi-threaded processor
3173 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
3175 int pir = env->spr_cb[SPR_PIR].default_value;
3177 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
3179 if (!dbell_type_server(rb)) {
3180 return;
3183 /* TODO: TCG supports only one thread */
3185 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
3187 #endif /* TARGET_PPC64 */
3189 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
3190 MMUAccessType access_type,
3191 int mmu_idx, uintptr_t retaddr)
3193 CPUPPCState *env = cs->env_ptr;
3194 uint32_t insn;
3196 /* Restore state and reload the insn we executed, for filling in DSISR. */
3197 cpu_restore_state(cs, retaddr);
3198 insn = ppc_ldl_code(env, env->nip);
3200 switch (env->mmu_model) {
3201 case POWERPC_MMU_SOFT_4xx:
3202 env->spr[SPR_40x_DEAR] = vaddr;
3203 break;
3204 case POWERPC_MMU_BOOKE:
3205 case POWERPC_MMU_BOOKE206:
3206 env->spr[SPR_BOOKE_DEAR] = vaddr;
3207 break;
3208 default:
3209 env->spr[SPR_DAR] = vaddr;
3210 break;
3213 cs->exception_index = POWERPC_EXCP_ALIGN;
3214 env->error_code = insn & 0x03FF0000;
3215 cpu_loop_exit(cs);
3217 #endif /* CONFIG_TCG */
3218 #endif /* !CONFIG_USER_ONLY */