target/ppc: add helper for books vhyp hypercall handler
[qemu/rayw.git] / target / ppc / excp_helper.c
blob6b6ec71bc22ad430a1642cfeab0291611f108b92
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 "cpu.h"
22 #include "exec/exec-all.h"
23 #include "internal.h"
24 #include "helper_regs.h"
26 #include "trace.h"
28 #ifdef CONFIG_TCG
29 #include "exec/helper-proto.h"
30 #include "exec/cpu_ldst.h"
31 #endif
33 /*****************************************************************************/
34 /* Exception processing */
35 #if !defined(CONFIG_USER_ONLY)
37 static const char *powerpc_excp_name(int excp)
39 switch (excp) {
40 case POWERPC_EXCP_CRITICAL: return "CRITICAL";
41 case POWERPC_EXCP_MCHECK: return "MCHECK";
42 case POWERPC_EXCP_DSI: return "DSI";
43 case POWERPC_EXCP_ISI: return "ISI";
44 case POWERPC_EXCP_EXTERNAL: return "EXTERNAL";
45 case POWERPC_EXCP_ALIGN: return "ALIGN";
46 case POWERPC_EXCP_PROGRAM: return "PROGRAM";
47 case POWERPC_EXCP_FPU: return "FPU";
48 case POWERPC_EXCP_SYSCALL: return "SYSCALL";
49 case POWERPC_EXCP_APU: return "APU";
50 case POWERPC_EXCP_DECR: return "DECR";
51 case POWERPC_EXCP_FIT: return "FIT";
52 case POWERPC_EXCP_WDT: return "WDT";
53 case POWERPC_EXCP_DTLB: return "DTLB";
54 case POWERPC_EXCP_ITLB: return "ITLB";
55 case POWERPC_EXCP_DEBUG: return "DEBUG";
56 case POWERPC_EXCP_SPEU: return "SPEU";
57 case POWERPC_EXCP_EFPDI: return "EFPDI";
58 case POWERPC_EXCP_EFPRI: return "EFPRI";
59 case POWERPC_EXCP_EPERFM: return "EPERFM";
60 case POWERPC_EXCP_DOORI: return "DOORI";
61 case POWERPC_EXCP_DOORCI: return "DOORCI";
62 case POWERPC_EXCP_GDOORI: return "GDOORI";
63 case POWERPC_EXCP_GDOORCI: return "GDOORCI";
64 case POWERPC_EXCP_HYPPRIV: return "HYPPRIV";
65 case POWERPC_EXCP_RESET: return "RESET";
66 case POWERPC_EXCP_DSEG: return "DSEG";
67 case POWERPC_EXCP_ISEG: return "ISEG";
68 case POWERPC_EXCP_HDECR: return "HDECR";
69 case POWERPC_EXCP_TRACE: return "TRACE";
70 case POWERPC_EXCP_HDSI: return "HDSI";
71 case POWERPC_EXCP_HISI: return "HISI";
72 case POWERPC_EXCP_HDSEG: return "HDSEG";
73 case POWERPC_EXCP_HISEG: return "HISEG";
74 case POWERPC_EXCP_VPU: return "VPU";
75 case POWERPC_EXCP_PIT: return "PIT";
76 case POWERPC_EXCP_EMUL: return "EMUL";
77 case POWERPC_EXCP_IFTLB: return "IFTLB";
78 case POWERPC_EXCP_DLTLB: return "DLTLB";
79 case POWERPC_EXCP_DSTLB: return "DSTLB";
80 case POWERPC_EXCP_FPA: return "FPA";
81 case POWERPC_EXCP_DABR: return "DABR";
82 case POWERPC_EXCP_IABR: return "IABR";
83 case POWERPC_EXCP_SMI: return "SMI";
84 case POWERPC_EXCP_PERFM: return "PERFM";
85 case POWERPC_EXCP_THERM: return "THERM";
86 case POWERPC_EXCP_VPUA: return "VPUA";
87 case POWERPC_EXCP_SOFTP: return "SOFTP";
88 case POWERPC_EXCP_MAINT: return "MAINT";
89 case POWERPC_EXCP_MEXTBR: return "MEXTBR";
90 case POWERPC_EXCP_NMEXTBR: return "NMEXTBR";
91 case POWERPC_EXCP_ITLBE: return "ITLBE";
92 case POWERPC_EXCP_DTLBE: return "DTLBE";
93 case POWERPC_EXCP_VSXU: return "VSXU";
94 case POWERPC_EXCP_FU: return "FU";
95 case POWERPC_EXCP_HV_EMU: return "HV_EMU";
96 case POWERPC_EXCP_HV_MAINT: return "HV_MAINT";
97 case POWERPC_EXCP_HV_FU: return "HV_FU";
98 case POWERPC_EXCP_SDOOR: return "SDOOR";
99 case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
100 case POWERPC_EXCP_HVIRT: return "HVIRT";
101 case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
102 default:
103 g_assert_not_reached();
107 static void dump_syscall(CPUPPCState *env)
109 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
110 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
111 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
112 " nip=" TARGET_FMT_lx "\n",
113 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
114 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
115 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
116 ppc_dump_gpr(env, 8), env->nip);
119 static void dump_hcall(CPUPPCState *env)
121 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
122 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
123 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
124 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
125 " nip=" TARGET_FMT_lx "\n",
126 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
127 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
128 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
129 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
130 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
131 env->nip);
134 static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
136 const char *es;
137 target_ulong *miss, *cmp;
138 int en;
140 if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
141 return;
144 if (excp == POWERPC_EXCP_IFTLB) {
145 es = "I";
146 en = 'I';
147 miss = &env->spr[SPR_IMISS];
148 cmp = &env->spr[SPR_ICMP];
149 } else {
150 if (excp == POWERPC_EXCP_DLTLB) {
151 es = "DL";
152 } else {
153 es = "DS";
155 en = 'D';
156 miss = &env->spr[SPR_DMISS];
157 cmp = &env->spr[SPR_DCMP];
159 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
160 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
161 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
162 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
163 env->error_code);
166 #if defined(TARGET_PPC64)
167 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
168 target_ulong *msr)
170 /* We no longer are in a PM state */
171 env->resume_as_sreset = false;
173 /* Pretend to be returning from doze always as we don't lose state */
174 *msr |= SRR1_WS_NOLOSS;
176 /* Machine checks are sent normally */
177 if (excp == POWERPC_EXCP_MCHECK) {
178 return excp;
180 switch (excp) {
181 case POWERPC_EXCP_RESET:
182 *msr |= SRR1_WAKERESET;
183 break;
184 case POWERPC_EXCP_EXTERNAL:
185 *msr |= SRR1_WAKEEE;
186 break;
187 case POWERPC_EXCP_DECR:
188 *msr |= SRR1_WAKEDEC;
189 break;
190 case POWERPC_EXCP_SDOOR:
191 *msr |= SRR1_WAKEDBELL;
192 break;
193 case POWERPC_EXCP_SDOOR_HV:
194 *msr |= SRR1_WAKEHDBELL;
195 break;
196 case POWERPC_EXCP_HV_MAINT:
197 *msr |= SRR1_WAKEHMI;
198 break;
199 case POWERPC_EXCP_HVIRT:
200 *msr |= SRR1_WAKEHVI;
201 break;
202 default:
203 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
204 excp);
206 return POWERPC_EXCP_RESET;
210 * AIL - Alternate Interrupt Location, a mode that allows interrupts to be
211 * taken with the MMU on, and which uses an alternate location (e.g., so the
212 * kernel/hv can map the vectors there with an effective address).
214 * An interrupt is considered to be taken "with AIL" or "AIL applies" if they
215 * are delivered in this way. AIL requires the LPCR to be set to enable this
216 * mode, and then a number of conditions have to be true for AIL to apply.
218 * First of all, SRESET, MCE, and HMI are always delivered without AIL, because
219 * they specifically want to be in real mode (e.g., the MCE might be signaling
220 * a SLB multi-hit which requires SLB flush before the MMU can be enabled).
222 * After that, behaviour depends on the current MSR[IR], MSR[DR], MSR[HV],
223 * whether or not the interrupt changes MSR[HV] from 0 to 1, and the current
224 * radix mode (LPCR[HR]).
226 * POWER8, POWER9 with LPCR[HR]=0
227 * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
228 * +-----------+-------------+---------+-------------+-----+
229 * | a | 00/01/10 | x | x | 0 |
230 * | a | 11 | 0 | 1 | 0 |
231 * | a | 11 | 1 | 1 | a |
232 * | a | 11 | 0 | 0 | a |
233 * +-------------------------------------------------------+
235 * POWER9 with LPCR[HR]=1
236 * | LPCR[AIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
237 * +-----------+-------------+---------+-------------+-----+
238 * | a | 00/01/10 | x | x | 0 |
239 * | a | 11 | x | x | a |
240 * +-------------------------------------------------------+
242 * The difference with POWER9 being that MSR[HV] 0->1 interrupts can be sent to
243 * the hypervisor in AIL mode if the guest is radix. This is good for
244 * performance but allows the guest to influence the AIL of hypervisor
245 * interrupts using its MSR, and also the hypervisor must disallow guest
246 * interrupts (MSR[HV] 0->0) from using AIL if the hypervisor does not want to
247 * use AIL for its MSR[HV] 0->1 interrupts.
249 * POWER10 addresses those issues with a new LPCR[HAIL] bit that is applied to
250 * interrupts that begin execution with MSR[HV]=1 (so both MSR[HV] 0->1 and
251 * MSR[HV] 1->1).
253 * HAIL=1 is equivalent to AIL=3, for interrupts delivered with MSR[HV]=1.
255 * POWER10 behaviour is
256 * | LPCR[AIL] | LPCR[HAIL] | MSR[IR||DR] | MSR[HV] | new MSR[HV] | AIL |
257 * +-----------+------------+-------------+---------+-------------+-----+
258 * | a | h | 00/01/10 | 0 | 0 | 0 |
259 * | a | h | 11 | 0 | 0 | a |
260 * | a | h | x | 0 | 1 | h |
261 * | a | h | 00/01/10 | 1 | 1 | 0 |
262 * | a | h | 11 | 1 | 1 | h |
263 * +--------------------------------------------------------------------+
265 static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
266 target_ulong *new_msr, target_ulong *vector)
268 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
269 CPUPPCState *env = &cpu->env;
270 bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
271 bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
272 int ail = 0;
274 if (excp == POWERPC_EXCP_MCHECK ||
275 excp == POWERPC_EXCP_RESET ||
276 excp == POWERPC_EXCP_HV_MAINT) {
277 /* SRESET, MCE, HMI never apply AIL */
278 return;
281 if (!(pcc->lpcr_mask & LPCR_AIL)) {
282 /* This CPU does not have AIL */
283 return;
286 /* P8 & P9 */
287 if (!(pcc->lpcr_mask & LPCR_HAIL)) {
288 if (!mmu_all_on) {
289 /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
290 return;
292 if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
294 * AIL does not work if there is a MSR[HV] 0->1 transition and the
295 * partition is in HPT mode. For radix guests, such interrupts are
296 * allowed to be delivered to the hypervisor in ail mode.
298 return;
301 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
302 if (ail == 0) {
303 return;
305 if (ail == 1) {
306 /* AIL=1 is reserved, treat it like AIL=0 */
307 return;
310 /* P10 and up */
311 } else {
312 if (!mmu_all_on && !hv_escalation) {
314 * AIL works for HV interrupts even with guest MSR[IR/DR] disabled.
315 * Guest->guest and HV->HV interrupts do require MMU on.
317 return;
320 if (*new_msr & MSR_HVB) {
321 if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
322 /* HV interrupts depend on LPCR[HAIL] */
323 return;
325 ail = 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */
326 } else {
327 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
329 if (ail == 0) {
330 return;
332 if (ail == 1 || ail == 2) {
333 /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
334 return;
339 * AIL applies, so the new MSR gets IR and DR set, and an offset applied
340 * to the new IP.
342 *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
344 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
345 if (ail == 2) {
346 *vector |= 0x0000000000018000ull;
347 } else if (ail == 3) {
348 *vector |= 0xc000000000004000ull;
350 } else {
352 * scv AIL is a little different. AIL=2 does not change the address,
353 * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
355 if (ail == 3) {
356 *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */
357 *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
361 #endif
363 static void powerpc_set_excp_state(PowerPCCPU *cpu,
364 target_ulong vector, target_ulong msr)
366 CPUState *cs = CPU(cpu);
367 CPUPPCState *env = &cpu->env;
369 assert((msr & env->msr_mask) == msr);
372 * We don't use hreg_store_msr here as already have treated any
373 * special case that could occur. Just store MSR and update hflags
375 * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
376 * will prevent setting of the HV bit which some exceptions might need
377 * to do.
379 env->msr = msr;
380 hreg_compute_hflags(env);
381 env->nip = vector;
382 /* Reset exception state */
383 cs->exception_index = POWERPC_EXCP_NONE;
384 env->error_code = 0;
386 /* Reset the reservation */
387 env->reserve_addr = -1;
390 * Any interrupt is context synchronizing, check if TCG TLB needs
391 * a delayed flush on ppc64
393 check_tlb_flush(env, false);
396 static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
398 CPUState *cs = CPU(cpu);
399 CPUPPCState *env = &cpu->env;
400 target_ulong msr, new_msr, vector;
401 int srr0, srr1;
403 /* new srr1 value excluding must-be-zero bits */
404 msr = env->msr & ~0x783f0000ULL;
407 * new interrupt handler msr preserves existing ME unless
408 * explicitly overriden.
410 new_msr = env->msr & (((target_ulong)1 << MSR_ME));
412 /* target registers */
413 srr0 = SPR_SRR0;
414 srr1 = SPR_SRR1;
417 * Hypervisor emulation assistance interrupt only exists on server
418 * arch 2.05 server or later.
420 if (excp == POWERPC_EXCP_HV_EMU) {
421 excp = POWERPC_EXCP_PROGRAM;
424 vector = env->excp_vectors[excp];
425 if (vector == (target_ulong)-1ULL) {
426 cpu_abort(cs, "Raised an exception without defined vector %d\n",
427 excp);
430 vector |= env->excp_prefix;
432 switch (excp) {
433 case POWERPC_EXCP_CRITICAL: /* Critical input */
434 srr0 = SPR_40x_SRR2;
435 srr1 = SPR_40x_SRR3;
436 break;
437 case POWERPC_EXCP_MCHECK: /* Machine check exception */
438 if (msr_me == 0) {
440 * Machine check exception is not enabled. Enter
441 * checkstop state.
443 fprintf(stderr, "Machine check while not allowed. "
444 "Entering checkstop state\n");
445 if (qemu_log_separate()) {
446 qemu_log("Machine check while not allowed. "
447 "Entering checkstop state\n");
449 cs->halted = 1;
450 cpu_interrupt_exittb(cs);
453 /* machine check exceptions don't have ME set */
454 new_msr &= ~((target_ulong)1 << MSR_ME);
456 srr0 = SPR_40x_SRR2;
457 srr1 = SPR_40x_SRR3;
458 break;
459 case POWERPC_EXCP_DSI: /* Data storage exception */
460 trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
461 break;
462 case POWERPC_EXCP_ISI: /* Instruction storage exception */
463 trace_ppc_excp_isi(msr, env->nip);
464 break;
465 case POWERPC_EXCP_EXTERNAL: /* External input */
466 break;
467 case POWERPC_EXCP_ALIGN: /* Alignment exception */
468 break;
469 case POWERPC_EXCP_PROGRAM: /* Program exception */
470 switch (env->error_code & ~0xF) {
471 case POWERPC_EXCP_FP:
472 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
473 trace_ppc_excp_fp_ignore();
474 cs->exception_index = POWERPC_EXCP_NONE;
475 env->error_code = 0;
476 return;
478 env->spr[SPR_40x_ESR] = ESR_FP;
479 break;
480 case POWERPC_EXCP_INVAL:
481 trace_ppc_excp_inval(env->nip);
482 env->spr[SPR_40x_ESR] = ESR_PIL;
483 break;
484 case POWERPC_EXCP_PRIV:
485 env->spr[SPR_40x_ESR] = ESR_PPR;
486 break;
487 case POWERPC_EXCP_TRAP:
488 env->spr[SPR_40x_ESR] = ESR_PTR;
489 break;
490 default:
491 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
492 env->error_code);
493 break;
495 break;
496 case POWERPC_EXCP_SYSCALL: /* System call exception */
497 dump_syscall(env);
500 * We need to correct the NIP which in this case is supposed
501 * to point to the next instruction
503 env->nip += 4;
504 break;
505 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
506 trace_ppc_excp_print("FIT");
507 break;
508 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
509 trace_ppc_excp_print("WDT");
510 break;
511 case POWERPC_EXCP_DTLB: /* Data TLB error */
512 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
513 break;
514 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
515 trace_ppc_excp_print("PIT");
516 break;
517 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
518 cpu_abort(cs, "%s exception not implemented\n",
519 powerpc_excp_name(excp));
520 break;
521 default:
522 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
523 break;
526 /* Save PC */
527 env->spr[srr0] = env->nip;
529 /* Save MSR */
530 env->spr[srr1] = msr;
532 powerpc_set_excp_state(cpu, vector, new_msr);
535 static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
537 CPUState *cs = CPU(cpu);
538 CPUPPCState *env = &cpu->env;
539 target_ulong msr, new_msr, vector;
541 /* new srr1 value excluding must-be-zero bits */
542 msr = env->msr & ~0x783f0000ULL;
545 * new interrupt handler msr preserves existing ME unless
546 * explicitly overriden
548 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
551 * Hypervisor emulation assistance interrupt only exists on server
552 * arch 2.05 server or later.
554 if (excp == POWERPC_EXCP_HV_EMU) {
555 excp = POWERPC_EXCP_PROGRAM;
558 vector = env->excp_vectors[excp];
559 if (vector == (target_ulong)-1ULL) {
560 cpu_abort(cs, "Raised an exception without defined vector %d\n",
561 excp);
564 vector |= env->excp_prefix;
566 switch (excp) {
567 case POWERPC_EXCP_CRITICAL: /* Critical input */
568 break;
569 case POWERPC_EXCP_MCHECK: /* Machine check exception */
570 if (msr_me == 0) {
572 * Machine check exception is not enabled. Enter
573 * checkstop state.
575 fprintf(stderr, "Machine check while not allowed. "
576 "Entering checkstop state\n");
577 if (qemu_log_separate()) {
578 qemu_log("Machine check while not allowed. "
579 "Entering checkstop state\n");
581 cs->halted = 1;
582 cpu_interrupt_exittb(cs);
585 /* machine check exceptions don't have ME set */
586 new_msr &= ~((target_ulong)1 << MSR_ME);
588 break;
589 case POWERPC_EXCP_DSI: /* Data storage exception */
590 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
591 break;
592 case POWERPC_EXCP_ISI: /* Instruction storage exception */
593 trace_ppc_excp_isi(msr, env->nip);
594 msr |= env->error_code;
595 break;
596 case POWERPC_EXCP_EXTERNAL: /* External input */
597 break;
598 case POWERPC_EXCP_ALIGN: /* Alignment exception */
599 /* Get rS/rD and rA from faulting opcode */
601 * Note: the opcode fields will not be set properly for a
602 * direct store load/store, but nobody cares as nobody
603 * actually uses direct store segments.
605 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
606 break;
607 case POWERPC_EXCP_PROGRAM: /* Program exception */
608 switch (env->error_code & ~0xF) {
609 case POWERPC_EXCP_FP:
610 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
611 trace_ppc_excp_fp_ignore();
612 cs->exception_index = POWERPC_EXCP_NONE;
613 env->error_code = 0;
614 return;
618 * FP exceptions always have NIP pointing to the faulting
619 * instruction, so always use store_next and claim we are
620 * precise in the MSR.
622 msr |= 0x00100000;
623 break;
624 case POWERPC_EXCP_INVAL:
625 trace_ppc_excp_inval(env->nip);
626 msr |= 0x00080000;
627 break;
628 case POWERPC_EXCP_PRIV:
629 msr |= 0x00040000;
630 break;
631 case POWERPC_EXCP_TRAP:
632 msr |= 0x00020000;
633 break;
634 default:
635 /* Should never occur */
636 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
637 env->error_code);
638 break;
640 break;
641 case POWERPC_EXCP_SYSCALL: /* System call exception */
642 dump_syscall(env);
645 * We need to correct the NIP which in this case is supposed
646 * to point to the next instruction
648 env->nip += 4;
649 break;
650 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
651 case POWERPC_EXCP_DECR: /* Decrementer exception */
652 break;
653 case POWERPC_EXCP_DTLB: /* Data TLB error */
654 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
655 break;
656 case POWERPC_EXCP_RESET: /* System reset exception */
657 if (msr_pow) {
658 cpu_abort(cs, "Trying to deliver power-saving system reset "
659 "exception %d with no HV support\n", excp);
661 break;
662 case POWERPC_EXCP_TRACE: /* Trace exception */
663 break;
664 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
665 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
666 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
667 /* Swap temporary saved registers with GPRs */
668 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
669 new_msr |= (target_ulong)1 << MSR_TGPR;
670 hreg_swap_gpr_tgpr(env);
673 ppc_excp_debug_sw_tlb(env, excp);
675 msr |= env->crf[0] << 28;
676 msr |= env->error_code; /* key, D/I, S/L bits */
677 /* Set way using a LRU mechanism */
678 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
679 break;
680 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
681 case POWERPC_EXCP_DABR: /* Data address breakpoint */
682 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
683 case POWERPC_EXCP_SMI: /* System management interrupt */
684 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
685 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
686 cpu_abort(cs, "%s exception not implemented\n",
687 powerpc_excp_name(excp));
688 break;
689 default:
690 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
691 break;
695 * Sort out endianness of interrupt, this differs depending on the
696 * CPU, the HV mode, etc...
698 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
699 new_msr |= (target_ulong)1 << MSR_LE;
702 /* Save PC */
703 env->spr[SPR_SRR0] = env->nip;
705 /* Save MSR */
706 env->spr[SPR_SRR1] = msr;
708 powerpc_set_excp_state(cpu, vector, new_msr);
711 static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
713 CPUState *cs = CPU(cpu);
714 CPUPPCState *env = &cpu->env;
715 target_ulong msr, new_msr, vector;
717 /* new srr1 value excluding must-be-zero bits */
718 msr = env->msr & ~0x783f0000ULL;
721 * new interrupt handler msr preserves existing ME unless
722 * explicitly overriden
724 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
727 * Hypervisor emulation assistance interrupt only exists on server
728 * arch 2.05 server or later.
730 if (excp == POWERPC_EXCP_HV_EMU) {
731 excp = POWERPC_EXCP_PROGRAM;
734 vector = env->excp_vectors[excp];
735 if (vector == (target_ulong)-1ULL) {
736 cpu_abort(cs, "Raised an exception without defined vector %d\n",
737 excp);
740 vector |= env->excp_prefix;
742 switch (excp) {
743 case POWERPC_EXCP_MCHECK: /* Machine check exception */
744 if (msr_me == 0) {
746 * Machine check exception is not enabled. Enter
747 * checkstop state.
749 fprintf(stderr, "Machine check while not allowed. "
750 "Entering checkstop state\n");
751 if (qemu_log_separate()) {
752 qemu_log("Machine check while not allowed. "
753 "Entering checkstop state\n");
755 cs->halted = 1;
756 cpu_interrupt_exittb(cs);
759 /* machine check exceptions don't have ME set */
760 new_msr &= ~((target_ulong)1 << MSR_ME);
762 break;
763 case POWERPC_EXCP_DSI: /* Data storage exception */
764 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
765 break;
766 case POWERPC_EXCP_ISI: /* Instruction storage exception */
767 trace_ppc_excp_isi(msr, env->nip);
768 msr |= env->error_code;
769 break;
770 case POWERPC_EXCP_EXTERNAL: /* External input */
771 break;
772 case POWERPC_EXCP_ALIGN: /* Alignment exception */
773 /* Get rS/rD and rA from faulting opcode */
775 * Note: the opcode fields will not be set properly for a
776 * direct store load/store, but nobody cares as nobody
777 * actually uses direct store segments.
779 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
780 break;
781 case POWERPC_EXCP_PROGRAM: /* Program exception */
782 switch (env->error_code & ~0xF) {
783 case POWERPC_EXCP_FP:
784 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
785 trace_ppc_excp_fp_ignore();
786 cs->exception_index = POWERPC_EXCP_NONE;
787 env->error_code = 0;
788 return;
792 * FP exceptions always have NIP pointing to the faulting
793 * instruction, so always use store_next and claim we are
794 * precise in the MSR.
796 msr |= 0x00100000;
797 break;
798 case POWERPC_EXCP_INVAL:
799 trace_ppc_excp_inval(env->nip);
800 msr |= 0x00080000;
801 break;
802 case POWERPC_EXCP_PRIV:
803 msr |= 0x00040000;
804 break;
805 case POWERPC_EXCP_TRAP:
806 msr |= 0x00020000;
807 break;
808 default:
809 /* Should never occur */
810 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
811 env->error_code);
812 break;
814 break;
815 case POWERPC_EXCP_SYSCALL: /* System call exception */
817 int lev = env->error_code;
819 if (lev == 1 && cpu->vhyp) {
820 dump_hcall(env);
821 } else {
822 dump_syscall(env);
826 * We need to correct the NIP which in this case is supposed
827 * to point to the next instruction
829 env->nip += 4;
832 * The Virtual Open Firmware (VOF) relies on the 'sc 1'
833 * instruction to communicate with QEMU. The pegasos2 machine
834 * uses VOF and the 7xx CPUs, so although the 7xx don't have
835 * HV mode, we need to keep hypercall support.
837 if (lev == 1 && cpu->vhyp) {
838 PPCVirtualHypervisorClass *vhc =
839 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
840 vhc->hypercall(cpu->vhyp, cpu);
841 return;
844 break;
846 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
847 case POWERPC_EXCP_DECR: /* Decrementer exception */
848 break;
849 case POWERPC_EXCP_RESET: /* System reset exception */
850 if (msr_pow) {
851 cpu_abort(cs, "Trying to deliver power-saving system reset "
852 "exception %d with no HV support\n", excp);
854 break;
855 case POWERPC_EXCP_TRACE: /* Trace exception */
856 break;
857 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
858 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
859 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
860 ppc_excp_debug_sw_tlb(env, excp);
862 msr |= env->crf[0] << 28;
863 msr |= env->error_code; /* key, D/I, S/L bits */
864 /* Set way using a LRU mechanism */
865 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
867 break;
868 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
869 case POWERPC_EXCP_SMI: /* System management interrupt */
870 case POWERPC_EXCP_THERM: /* Thermal interrupt */
871 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
872 cpu_abort(cs, "%s exception not implemented\n",
873 powerpc_excp_name(excp));
874 break;
875 default:
876 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
877 break;
881 * Sort out endianness of interrupt, this differs depending on the
882 * CPU, the HV mode, etc...
884 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
885 new_msr |= (target_ulong)1 << MSR_LE;
888 /* Save PC */
889 env->spr[SPR_SRR0] = env->nip;
891 /* Save MSR */
892 env->spr[SPR_SRR1] = msr;
894 powerpc_set_excp_state(cpu, vector, new_msr);
897 static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
899 CPUState *cs = CPU(cpu);
900 CPUPPCState *env = &cpu->env;
901 target_ulong msr, new_msr, vector;
903 /* new srr1 value excluding must-be-zero bits */
904 msr = env->msr & ~0x783f0000ULL;
907 * new interrupt handler msr preserves existing ME unless
908 * explicitly overriden
910 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
913 * Hypervisor emulation assistance interrupt only exists on server
914 * arch 2.05 server or later.
916 if (excp == POWERPC_EXCP_HV_EMU) {
917 excp = POWERPC_EXCP_PROGRAM;
920 vector = env->excp_vectors[excp];
921 if (vector == (target_ulong)-1ULL) {
922 cpu_abort(cs, "Raised an exception without defined vector %d\n",
923 excp);
926 vector |= env->excp_prefix;
928 switch (excp) {
929 case POWERPC_EXCP_MCHECK: /* Machine check exception */
930 if (msr_me == 0) {
932 * Machine check exception is not enabled. Enter
933 * checkstop state.
935 fprintf(stderr, "Machine check while not allowed. "
936 "Entering checkstop state\n");
937 if (qemu_log_separate()) {
938 qemu_log("Machine check while not allowed. "
939 "Entering checkstop state\n");
941 cs->halted = 1;
942 cpu_interrupt_exittb(cs);
945 /* machine check exceptions don't have ME set */
946 new_msr &= ~((target_ulong)1 << MSR_ME);
948 break;
949 case POWERPC_EXCP_DSI: /* Data storage exception */
950 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
951 break;
952 case POWERPC_EXCP_ISI: /* Instruction storage exception */
953 trace_ppc_excp_isi(msr, env->nip);
954 msr |= env->error_code;
955 break;
956 case POWERPC_EXCP_EXTERNAL: /* External input */
957 break;
958 case POWERPC_EXCP_ALIGN: /* Alignment exception */
959 /* Get rS/rD and rA from faulting opcode */
961 * Note: the opcode fields will not be set properly for a
962 * direct store load/store, but nobody cares as nobody
963 * actually uses direct store segments.
965 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
966 break;
967 case POWERPC_EXCP_PROGRAM: /* Program exception */
968 switch (env->error_code & ~0xF) {
969 case POWERPC_EXCP_FP:
970 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
971 trace_ppc_excp_fp_ignore();
972 cs->exception_index = POWERPC_EXCP_NONE;
973 env->error_code = 0;
974 return;
978 * FP exceptions always have NIP pointing to the faulting
979 * instruction, so always use store_next and claim we are
980 * precise in the MSR.
982 msr |= 0x00100000;
983 break;
984 case POWERPC_EXCP_INVAL:
985 trace_ppc_excp_inval(env->nip);
986 msr |= 0x00080000;
987 break;
988 case POWERPC_EXCP_PRIV:
989 msr |= 0x00040000;
990 break;
991 case POWERPC_EXCP_TRAP:
992 msr |= 0x00020000;
993 break;
994 default:
995 /* Should never occur */
996 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
997 env->error_code);
998 break;
1000 break;
1001 case POWERPC_EXCP_SYSCALL: /* System call exception */
1003 int lev = env->error_code;
1005 if ((lev == 1) && cpu->vhyp) {
1006 dump_hcall(env);
1007 } else {
1008 dump_syscall(env);
1012 * We need to correct the NIP which in this case is supposed
1013 * to point to the next instruction
1015 env->nip += 4;
1018 * The Virtual Open Firmware (VOF) relies on the 'sc 1'
1019 * instruction to communicate with QEMU. The pegasos2 machine
1020 * uses VOF and the 74xx CPUs, so although the 74xx don't have
1021 * HV mode, we need to keep hypercall support.
1023 if ((lev == 1) && cpu->vhyp) {
1024 PPCVirtualHypervisorClass *vhc =
1025 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1026 vhc->hypercall(cpu->vhyp, cpu);
1027 return;
1030 break;
1032 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1033 case POWERPC_EXCP_DECR: /* Decrementer exception */
1034 break;
1035 case POWERPC_EXCP_RESET: /* System reset exception */
1036 if (msr_pow) {
1037 cpu_abort(cs, "Trying to deliver power-saving system reset "
1038 "exception %d with no HV support\n", excp);
1040 break;
1041 case POWERPC_EXCP_TRACE: /* Trace exception */
1042 break;
1043 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1044 break;
1045 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1046 case POWERPC_EXCP_SMI: /* System management interrupt */
1047 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1048 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
1049 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1050 cpu_abort(cs, "%s exception not implemented\n",
1051 powerpc_excp_name(excp));
1052 break;
1053 default:
1054 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1055 break;
1059 * Sort out endianness of interrupt, this differs depending on the
1060 * CPU, the HV mode, etc...
1062 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1063 new_msr |= (target_ulong)1 << MSR_LE;
1066 /* Save PC */
1067 env->spr[SPR_SRR0] = env->nip;
1069 /* Save MSR */
1070 env->spr[SPR_SRR1] = msr;
1072 powerpc_set_excp_state(cpu, vector, new_msr);
1075 static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
1077 CPUState *cs = CPU(cpu);
1078 CPUPPCState *env = &cpu->env;
1079 target_ulong msr, new_msr, vector;
1080 int srr0, srr1;
1082 msr = env->msr;
1085 * new interrupt handler msr preserves existing ME unless
1086 * explicitly overriden
1088 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
1090 /* target registers */
1091 srr0 = SPR_SRR0;
1092 srr1 = SPR_SRR1;
1095 * Hypervisor emulation assistance interrupt only exists on server
1096 * arch 2.05 server or later.
1098 if (excp == POWERPC_EXCP_HV_EMU) {
1099 excp = POWERPC_EXCP_PROGRAM;
1102 #ifdef TARGET_PPC64
1104 * SPEU and VPU share the same IVOR but they exist in different
1105 * processors. SPEU is e500v1/2 only and VPU is e6500 only.
1107 if (excp == POWERPC_EXCP_VPU) {
1108 excp = POWERPC_EXCP_SPEU;
1110 #endif
1112 vector = env->excp_vectors[excp];
1113 if (vector == (target_ulong)-1ULL) {
1114 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1115 excp);
1118 vector |= env->excp_prefix;
1120 switch (excp) {
1121 case POWERPC_EXCP_CRITICAL: /* Critical input */
1122 srr0 = SPR_BOOKE_CSRR0;
1123 srr1 = SPR_BOOKE_CSRR1;
1124 break;
1125 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1126 if (msr_me == 0) {
1128 * Machine check exception is not enabled. Enter
1129 * checkstop state.
1131 fprintf(stderr, "Machine check while not allowed. "
1132 "Entering checkstop state\n");
1133 if (qemu_log_separate()) {
1134 qemu_log("Machine check while not allowed. "
1135 "Entering checkstop state\n");
1137 cs->halted = 1;
1138 cpu_interrupt_exittb(cs);
1141 /* machine check exceptions don't have ME set */
1142 new_msr &= ~((target_ulong)1 << MSR_ME);
1144 /* FIXME: choose one or the other based on CPU type */
1145 srr0 = SPR_BOOKE_MCSRR0;
1146 srr1 = SPR_BOOKE_MCSRR1;
1148 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1149 env->spr[SPR_BOOKE_CSRR1] = msr;
1151 break;
1152 case POWERPC_EXCP_DSI: /* Data storage exception */
1153 trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
1154 break;
1155 case POWERPC_EXCP_ISI: /* Instruction storage exception */
1156 trace_ppc_excp_isi(msr, env->nip);
1157 break;
1158 case POWERPC_EXCP_EXTERNAL: /* External input */
1159 if (env->mpic_proxy) {
1160 /* IACK the IRQ on delivery */
1161 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1163 break;
1164 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1165 break;
1166 case POWERPC_EXCP_PROGRAM: /* Program exception */
1167 switch (env->error_code & ~0xF) {
1168 case POWERPC_EXCP_FP:
1169 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1170 trace_ppc_excp_fp_ignore();
1171 cs->exception_index = POWERPC_EXCP_NONE;
1172 env->error_code = 0;
1173 return;
1177 * FP exceptions always have NIP pointing to the faulting
1178 * instruction, so always use store_next and claim we are
1179 * precise in the MSR.
1181 msr |= 0x00100000;
1182 env->spr[SPR_BOOKE_ESR] = ESR_FP;
1183 break;
1184 case POWERPC_EXCP_INVAL:
1185 trace_ppc_excp_inval(env->nip);
1186 msr |= 0x00080000;
1187 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1188 break;
1189 case POWERPC_EXCP_PRIV:
1190 msr |= 0x00040000;
1191 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1192 break;
1193 case POWERPC_EXCP_TRAP:
1194 msr |= 0x00020000;
1195 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1196 break;
1197 default:
1198 /* Should never occur */
1199 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1200 env->error_code);
1201 break;
1203 break;
1204 case POWERPC_EXCP_SYSCALL: /* System call exception */
1205 dump_syscall(env);
1208 * We need to correct the NIP which in this case is supposed
1209 * to point to the next instruction
1211 env->nip += 4;
1212 break;
1213 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1214 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1215 case POWERPC_EXCP_DECR: /* Decrementer exception */
1216 break;
1217 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1218 /* FIT on 4xx */
1219 trace_ppc_excp_print("FIT");
1220 break;
1221 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1222 trace_ppc_excp_print("WDT");
1223 srr0 = SPR_BOOKE_CSRR0;
1224 srr1 = SPR_BOOKE_CSRR1;
1225 break;
1226 case POWERPC_EXCP_DTLB: /* Data TLB error */
1227 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1228 break;
1229 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
1230 if (env->flags & POWERPC_FLAG_DE) {
1231 /* FIXME: choose one or the other based on CPU type */
1232 srr0 = SPR_BOOKE_DSRR0;
1233 srr1 = SPR_BOOKE_DSRR1;
1235 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1236 env->spr[SPR_BOOKE_CSRR1] = msr;
1238 /* DBSR already modified by caller */
1239 } else {
1240 cpu_abort(cs, "Debug exception triggered on unsupported model\n");
1242 break;
1243 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
1244 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1245 break;
1246 case POWERPC_EXCP_RESET: /* System reset exception */
1247 if (msr_pow) {
1248 cpu_abort(cs, "Trying to deliver power-saving system reset "
1249 "exception %d with no HV support\n", excp);
1251 break;
1252 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
1253 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
1254 cpu_abort(cs, "%s exception not implemented\n",
1255 powerpc_excp_name(excp));
1256 break;
1257 default:
1258 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1259 break;
1262 #if defined(TARGET_PPC64)
1263 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1264 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
1265 new_msr |= (target_ulong)1 << MSR_CM;
1266 } else {
1267 vector = (uint32_t)vector;
1269 #endif
1271 /* Save PC */
1272 env->spr[srr0] = env->nip;
1274 /* Save MSR */
1275 env->spr[srr1] = msr;
1277 powerpc_set_excp_state(cpu, vector, new_msr);
1280 #ifdef TARGET_PPC64
1282 * When running under vhyp, hcalls are always intercepted and sent to the
1283 * vhc->hypercall handler.
1285 static bool books_vhyp_handles_hcall(PowerPCCPU *cpu)
1287 if (cpu->vhyp) {
1288 return true;
1290 return false;
1293 static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1295 CPUState *cs = CPU(cpu);
1296 CPUPPCState *env = &cpu->env;
1297 target_ulong msr, new_msr, vector;
1298 int srr0, srr1, lev = -1;
1300 /* new srr1 value excluding must-be-zero bits */
1301 msr = env->msr & ~0x783f0000ULL;
1304 * new interrupt handler msr preserves existing HV and ME unless
1305 * explicitly overriden
1307 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1309 /* target registers */
1310 srr0 = SPR_SRR0;
1311 srr1 = SPR_SRR1;
1314 * check for special resume at 0x100 from doze/nap/sleep/winkle on
1315 * P7/P8/P9
1317 if (env->resume_as_sreset) {
1318 excp = powerpc_reset_wakeup(cs, env, excp, &msr);
1322 * We don't want to generate a Hypervisor Emulation Assistance
1323 * Interrupt if we don't have HVB in msr_mask (PAPR mode).
1325 if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) {
1326 excp = POWERPC_EXCP_PROGRAM;
1329 vector = env->excp_vectors[excp];
1330 if (vector == (target_ulong)-1ULL) {
1331 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1332 excp);
1335 vector |= env->excp_prefix;
1337 switch (excp) {
1338 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1339 if (msr_me == 0) {
1341 * Machine check exception is not enabled. Enter
1342 * checkstop state.
1344 fprintf(stderr, "Machine check while not allowed. "
1345 "Entering checkstop state\n");
1346 if (qemu_log_separate()) {
1347 qemu_log("Machine check while not allowed. "
1348 "Entering checkstop state\n");
1350 cs->halted = 1;
1351 cpu_interrupt_exittb(cs);
1353 if (env->msr_mask & MSR_HVB) {
1355 * ISA specifies HV, but can be delivered to guest with HV
1356 * clear (e.g., see FWNMI in PAPR).
1358 new_msr |= (target_ulong)MSR_HVB;
1361 /* machine check exceptions don't have ME set */
1362 new_msr &= ~((target_ulong)1 << MSR_ME);
1364 break;
1365 case POWERPC_EXCP_DSI: /* Data storage exception */
1366 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1367 break;
1368 case POWERPC_EXCP_ISI: /* Instruction storage exception */
1369 trace_ppc_excp_isi(msr, env->nip);
1370 msr |= env->error_code;
1371 break;
1372 case POWERPC_EXCP_EXTERNAL: /* External input */
1374 bool lpes0;
1377 * LPES0 is only taken into consideration if we support HV
1378 * mode for this CPU.
1380 if (!env->has_hv_mode) {
1381 break;
1384 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1386 if (!lpes0) {
1387 new_msr |= (target_ulong)MSR_HVB;
1388 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1389 srr0 = SPR_HSRR0;
1390 srr1 = SPR_HSRR1;
1393 break;
1395 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1396 /* Get rS/rD and rA from faulting opcode */
1398 * Note: the opcode fields will not be set properly for a
1399 * direct store load/store, but nobody cares as nobody
1400 * actually uses direct store segments.
1402 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1403 break;
1404 case POWERPC_EXCP_PROGRAM: /* Program exception */
1405 switch (env->error_code & ~0xF) {
1406 case POWERPC_EXCP_FP:
1407 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1408 trace_ppc_excp_fp_ignore();
1409 cs->exception_index = POWERPC_EXCP_NONE;
1410 env->error_code = 0;
1411 return;
1415 * FP exceptions always have NIP pointing to the faulting
1416 * instruction, so always use store_next and claim we are
1417 * precise in the MSR.
1419 msr |= 0x00100000;
1420 break;
1421 case POWERPC_EXCP_INVAL:
1422 trace_ppc_excp_inval(env->nip);
1423 msr |= 0x00080000;
1424 break;
1425 case POWERPC_EXCP_PRIV:
1426 msr |= 0x00040000;
1427 break;
1428 case POWERPC_EXCP_TRAP:
1429 msr |= 0x00020000;
1430 break;
1431 default:
1432 /* Should never occur */
1433 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1434 env->error_code);
1435 break;
1437 break;
1438 case POWERPC_EXCP_SYSCALL: /* System call exception */
1439 lev = env->error_code;
1441 if ((lev == 1) && cpu->vhyp) {
1442 dump_hcall(env);
1443 } else {
1444 dump_syscall(env);
1448 * We need to correct the NIP which in this case is supposed
1449 * to point to the next instruction
1451 env->nip += 4;
1453 /* "PAPR mode" built-in hypercall emulation */
1454 if ((lev == 1) && books_vhyp_handles_hcall(cpu)) {
1455 PPCVirtualHypervisorClass *vhc =
1456 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1457 vhc->hypercall(cpu->vhyp, cpu);
1458 return;
1460 if (lev == 1) {
1461 new_msr |= (target_ulong)MSR_HVB;
1463 break;
1464 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
1465 lev = env->error_code;
1466 dump_syscall(env);
1467 env->nip += 4;
1468 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1469 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1471 vector += lev * 0x20;
1473 env->lr = env->nip;
1474 env->ctr = msr;
1475 break;
1476 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1477 case POWERPC_EXCP_DECR: /* Decrementer exception */
1478 break;
1479 case POWERPC_EXCP_RESET: /* System reset exception */
1480 /* A power-saving exception sets ME, otherwise it is unchanged */
1481 if (msr_pow) {
1482 /* indicate that we resumed from power save mode */
1483 msr |= 0x10000;
1484 new_msr |= ((target_ulong)1 << MSR_ME);
1486 if (env->msr_mask & MSR_HVB) {
1488 * ISA specifies HV, but can be delivered to guest with HV
1489 * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
1491 new_msr |= (target_ulong)MSR_HVB;
1492 } else {
1493 if (msr_pow) {
1494 cpu_abort(cs, "Trying to deliver power-saving system reset "
1495 "exception %d with no HV support\n", excp);
1498 break;
1499 case POWERPC_EXCP_DSEG: /* Data segment exception */
1500 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1501 case POWERPC_EXCP_TRACE: /* Trace exception */
1502 break;
1503 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
1504 msr |= env->error_code;
1505 /* fall through */
1506 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1507 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1508 case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
1509 case POWERPC_EXCP_HV_EMU:
1510 case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
1511 srr0 = SPR_HSRR0;
1512 srr1 = SPR_HSRR1;
1513 new_msr |= (target_ulong)MSR_HVB;
1514 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1515 break;
1516 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1517 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
1518 case POWERPC_EXCP_FU: /* Facility unavailable exception */
1519 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1520 break;
1521 case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
1522 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1523 srr0 = SPR_HSRR0;
1524 srr1 = SPR_HSRR1;
1525 new_msr |= (target_ulong)MSR_HVB;
1526 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1527 break;
1528 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1529 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
1530 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1531 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1532 case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
1533 case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */
1534 cpu_abort(cs, "%s exception not implemented\n",
1535 powerpc_excp_name(excp));
1536 break;
1537 default:
1538 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1539 break;
1542 /* Sanity check */
1543 if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
1544 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1545 "no HV support\n", excp);
1549 * Sort out endianness of interrupt, this differs depending on the
1550 * CPU, the HV mode, etc...
1552 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1553 new_msr |= (target_ulong)1 << MSR_LE;
1556 new_msr |= (target_ulong)1 << MSR_SF;
1558 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1559 /* Save PC */
1560 env->spr[srr0] = env->nip;
1562 /* Save MSR */
1563 env->spr[srr1] = msr;
1566 /* This can update new_msr and vector if AIL applies */
1567 ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
1569 powerpc_set_excp_state(cpu, vector, new_msr);
1571 #else
1572 static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1574 g_assert_not_reached();
1576 #endif
1578 static void powerpc_excp(PowerPCCPU *cpu, int excp)
1580 CPUState *cs = CPU(cpu);
1581 CPUPPCState *env = &cpu->env;
1583 if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1584 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1587 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1588 " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1589 excp, env->error_code);
1591 switch (env->excp_model) {
1592 case POWERPC_EXCP_40x:
1593 powerpc_excp_40x(cpu, excp);
1594 break;
1595 case POWERPC_EXCP_6xx:
1596 powerpc_excp_6xx(cpu, excp);
1597 break;
1598 case POWERPC_EXCP_7xx:
1599 powerpc_excp_7xx(cpu, excp);
1600 break;
1601 case POWERPC_EXCP_74xx:
1602 powerpc_excp_74xx(cpu, excp);
1603 break;
1604 case POWERPC_EXCP_BOOKE:
1605 powerpc_excp_booke(cpu, excp);
1606 break;
1607 case POWERPC_EXCP_970:
1608 case POWERPC_EXCP_POWER7:
1609 case POWERPC_EXCP_POWER8:
1610 case POWERPC_EXCP_POWER9:
1611 case POWERPC_EXCP_POWER10:
1612 powerpc_excp_books(cpu, excp);
1613 break;
1614 default:
1615 g_assert_not_reached();
1619 void ppc_cpu_do_interrupt(CPUState *cs)
1621 PowerPCCPU *cpu = POWERPC_CPU(cs);
1623 powerpc_excp(cpu, cs->exception_index);
1626 static void ppc_hw_interrupt(CPUPPCState *env)
1628 PowerPCCPU *cpu = env_archcpu(env);
1629 bool async_deliver;
1631 /* External reset */
1632 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
1633 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
1634 powerpc_excp(cpu, POWERPC_EXCP_RESET);
1635 return;
1637 /* Machine check exception */
1638 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
1639 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
1640 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
1641 return;
1643 #if 0 /* TODO */
1644 /* External debug exception */
1645 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
1646 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
1647 powerpc_excp(cpu, POWERPC_EXCP_DEBUG);
1648 return;
1650 #endif
1653 * For interrupts that gate on MSR:EE, we need to do something a
1654 * bit more subtle, as we need to let them through even when EE is
1655 * clear when coming out of some power management states (in order
1656 * for them to become a 0x100).
1658 async_deliver = (msr_ee != 0) || env->resume_as_sreset;
1660 /* Hypervisor decrementer exception */
1661 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
1662 /* LPCR will be clear when not supported so this will work */
1663 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1664 if ((async_deliver || msr_hv == 0) && hdice) {
1665 /* HDEC clears on delivery */
1666 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1667 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
1668 return;
1672 /* Hypervisor virtualization interrupt */
1673 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
1674 /* LPCR will be clear when not supported so this will work */
1675 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
1676 if ((async_deliver || msr_hv == 0) && hvice) {
1677 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
1678 return;
1682 /* External interrupt can ignore MSR:EE under some circumstances */
1683 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
1684 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1685 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1686 /* HEIC blocks delivery to the hypervisor */
1687 if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
1688 (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
1689 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
1690 return;
1693 if (msr_ce != 0) {
1694 /* External critical interrupt */
1695 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
1696 powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
1697 return;
1700 if (async_deliver != 0) {
1701 /* Watchdog timer on embedded PowerPC */
1702 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
1703 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
1704 powerpc_excp(cpu, POWERPC_EXCP_WDT);
1705 return;
1707 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
1708 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
1709 powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
1710 return;
1712 /* Fixed interval timer on embedded PowerPC */
1713 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
1714 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
1715 powerpc_excp(cpu, POWERPC_EXCP_FIT);
1716 return;
1718 /* Programmable interval timer on embedded PowerPC */
1719 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
1720 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
1721 powerpc_excp(cpu, POWERPC_EXCP_PIT);
1722 return;
1724 /* Decrementer exception */
1725 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
1726 if (ppc_decr_clear_on_delivery(env)) {
1727 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
1729 powerpc_excp(cpu, POWERPC_EXCP_DECR);
1730 return;
1732 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
1733 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1734 if (is_book3s_arch2x(env)) {
1735 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
1736 } else {
1737 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
1739 return;
1741 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
1742 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1743 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
1744 return;
1746 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
1747 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
1748 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
1749 return;
1751 /* Thermal interrupt */
1752 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
1753 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
1754 powerpc_excp(cpu, POWERPC_EXCP_THERM);
1755 return;
1759 if (env->resume_as_sreset) {
1761 * This is a bug ! It means that has_work took us out of halt without
1762 * anything to deliver while in a PM state that requires getting
1763 * out via a 0x100
1765 * This means we will incorrectly execute past the power management
1766 * instruction instead of triggering a reset.
1768 * It generally means a discrepancy between the wakeup conditions in the
1769 * processor has_work implementation and the logic in this function.
1771 cpu_abort(env_cpu(env),
1772 "Wakeup from PM state but interrupt Undelivered");
1776 void ppc_cpu_do_system_reset(CPUState *cs)
1778 PowerPCCPU *cpu = POWERPC_CPU(cs);
1780 powerpc_excp(cpu, POWERPC_EXCP_RESET);
1783 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
1785 PowerPCCPU *cpu = POWERPC_CPU(cs);
1786 CPUPPCState *env = &cpu->env;
1787 target_ulong msr = 0;
1790 * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
1791 * been set by KVM.
1793 msr = (1ULL << MSR_ME);
1794 msr |= env->msr & (1ULL << MSR_SF);
1795 if (ppc_interrupts_little_endian(cpu, false)) {
1796 msr |= (1ULL << MSR_LE);
1799 powerpc_set_excp_state(cpu, vector, msr);
1802 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1804 PowerPCCPU *cpu = POWERPC_CPU(cs);
1805 CPUPPCState *env = &cpu->env;
1807 if (interrupt_request & CPU_INTERRUPT_HARD) {
1808 ppc_hw_interrupt(env);
1809 if (env->pending_interrupts == 0) {
1810 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
1812 return true;
1814 return false;
1817 #endif /* !CONFIG_USER_ONLY */
1819 /*****************************************************************************/
1820 /* Exceptions processing helpers */
1822 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
1823 uint32_t error_code, uintptr_t raddr)
1825 CPUState *cs = env_cpu(env);
1827 cs->exception_index = exception;
1828 env->error_code = error_code;
1829 cpu_loop_exit_restore(cs, raddr);
1832 void raise_exception_err(CPUPPCState *env, uint32_t exception,
1833 uint32_t error_code)
1835 raise_exception_err_ra(env, exception, error_code, 0);
1838 void raise_exception(CPUPPCState *env, uint32_t exception)
1840 raise_exception_err_ra(env, exception, 0, 0);
1843 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
1844 uintptr_t raddr)
1846 raise_exception_err_ra(env, exception, 0, raddr);
1849 #ifdef CONFIG_TCG
1850 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1851 uint32_t error_code)
1853 raise_exception_err_ra(env, exception, error_code, 0);
1856 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1858 raise_exception_err_ra(env, exception, 0, 0);
1860 #endif
1862 #if !defined(CONFIG_USER_ONLY)
1863 #ifdef CONFIG_TCG
1864 void helper_store_msr(CPUPPCState *env, target_ulong val)
1866 uint32_t excp = hreg_store_msr(env, val, 0);
1868 if (excp != 0) {
1869 CPUState *cs = env_cpu(env);
1870 cpu_interrupt_exittb(cs);
1871 raise_exception(env, excp);
1875 #if defined(TARGET_PPC64)
1876 void helper_scv(CPUPPCState *env, uint32_t lev)
1878 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
1879 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
1880 } else {
1881 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
1885 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1887 CPUState *cs;
1889 cs = env_cpu(env);
1890 cs->halted = 1;
1892 /* Condition for waking up at 0x100 */
1893 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1894 (env->spr[SPR_PSSCR] & PSSCR_EC);
1896 #endif /* defined(TARGET_PPC64) */
1898 static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1900 CPUState *cs = env_cpu(env);
1902 /* MSR:POW cannot be set by any form of rfi */
1903 msr &= ~(1ULL << MSR_POW);
1905 /* MSR:TGPR cannot be set by any form of rfi */
1906 if (env->flags & POWERPC_FLAG_TGPR)
1907 msr &= ~(1ULL << MSR_TGPR);
1909 #if defined(TARGET_PPC64)
1910 /* Switching to 32-bit ? Crop the nip */
1911 if (!msr_is_64bit(env, msr)) {
1912 nip = (uint32_t)nip;
1914 #else
1915 nip = (uint32_t)nip;
1916 #endif
1917 /* XXX: beware: this is false if VLE is supported */
1918 env->nip = nip & ~((target_ulong)0x00000003);
1919 hreg_store_msr(env, msr, 1);
1920 trace_ppc_excp_rfi(env->nip, env->msr);
1922 * No need to raise an exception here, as rfi is always the last
1923 * insn of a TB
1925 cpu_interrupt_exittb(cs);
1926 /* Reset the reservation */
1927 env->reserve_addr = -1;
1929 /* Context synchronizing: check if TCG TLB needs flush */
1930 check_tlb_flush(env, false);
1933 void helper_rfi(CPUPPCState *env)
1935 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1938 #define MSR_BOOK3S_MASK
1939 #if defined(TARGET_PPC64)
1940 void helper_rfid(CPUPPCState *env)
1943 * The architecture defines a number of rules for which bits can
1944 * change but in practice, we handle this in hreg_store_msr()
1945 * which will be called by do_rfi(), so there is no need to filter
1946 * here
1948 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1951 void helper_rfscv(CPUPPCState *env)
1953 do_rfi(env, env->lr, env->ctr);
1956 void helper_hrfid(CPUPPCState *env)
1958 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1960 #endif
1962 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
1963 void helper_rfebb(CPUPPCState *env, target_ulong s)
1965 target_ulong msr = env->msr;
1968 * Handling of BESCR bits 32:33 according to PowerISA v3.1:
1970 * "If BESCR 32:33 != 0b00 the instruction is treated as if
1971 * the instruction form were invalid."
1973 if (env->spr[SPR_BESCR] & BESCR_INVALID) {
1974 raise_exception_err(env, POWERPC_EXCP_PROGRAM,
1975 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1978 env->nip = env->spr[SPR_EBBRR];
1980 /* Switching to 32-bit ? Crop the nip */
1981 if (!msr_is_64bit(env, msr)) {
1982 env->nip = (uint32_t)env->spr[SPR_EBBRR];
1985 if (s) {
1986 env->spr[SPR_BESCR] |= BESCR_GE;
1987 } else {
1988 env->spr[SPR_BESCR] &= ~BESCR_GE;
1991 #endif
1993 /*****************************************************************************/
1994 /* Embedded PowerPC specific helpers */
1995 void helper_40x_rfci(CPUPPCState *env)
1997 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
2000 void helper_rfci(CPUPPCState *env)
2002 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
2005 void helper_rfdi(CPUPPCState *env)
2007 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
2008 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
2011 void helper_rfmci(CPUPPCState *env)
2013 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
2014 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
2016 #endif /* CONFIG_TCG */
2017 #endif /* !defined(CONFIG_USER_ONLY) */
2019 #ifdef CONFIG_TCG
2020 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2021 uint32_t flags)
2023 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
2024 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
2025 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
2026 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
2027 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
2028 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2029 POWERPC_EXCP_TRAP, GETPC());
2033 #if defined(TARGET_PPC64)
2034 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2035 uint32_t flags)
2037 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
2038 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
2039 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
2040 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
2041 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
2042 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2043 POWERPC_EXCP_TRAP, GETPC());
2046 #endif
2047 #endif
2049 #if !defined(CONFIG_USER_ONLY)
2051 #ifdef CONFIG_TCG
2053 /* Embedded.Processor Control */
2054 static int dbell2irq(target_ulong rb)
2056 int msg = rb & DBELL_TYPE_MASK;
2057 int irq = -1;
2059 switch (msg) {
2060 case DBELL_TYPE_DBELL:
2061 irq = PPC_INTERRUPT_DOORBELL;
2062 break;
2063 case DBELL_TYPE_DBELL_CRIT:
2064 irq = PPC_INTERRUPT_CDOORBELL;
2065 break;
2066 case DBELL_TYPE_G_DBELL:
2067 case DBELL_TYPE_G_DBELL_CRIT:
2068 case DBELL_TYPE_G_DBELL_MC:
2069 /* XXX implement */
2070 default:
2071 break;
2074 return irq;
2077 void helper_msgclr(CPUPPCState *env, target_ulong rb)
2079 int irq = dbell2irq(rb);
2081 if (irq < 0) {
2082 return;
2085 env->pending_interrupts &= ~(1 << irq);
2088 void helper_msgsnd(target_ulong rb)
2090 int irq = dbell2irq(rb);
2091 int pir = rb & DBELL_PIRTAG_MASK;
2092 CPUState *cs;
2094 if (irq < 0) {
2095 return;
2098 qemu_mutex_lock_iothread();
2099 CPU_FOREACH(cs) {
2100 PowerPCCPU *cpu = POWERPC_CPU(cs);
2101 CPUPPCState *cenv = &cpu->env;
2103 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
2104 cenv->pending_interrupts |= 1 << irq;
2105 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2108 qemu_mutex_unlock_iothread();
2111 /* Server Processor Control */
2113 static bool dbell_type_server(target_ulong rb)
2116 * A Directed Hypervisor Doorbell message is sent only if the
2117 * message type is 5. All other types are reserved and the
2118 * instruction is a no-op
2120 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
2123 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
2125 if (!dbell_type_server(rb)) {
2126 return;
2129 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
2132 static void book3s_msgsnd_common(int pir, int irq)
2134 CPUState *cs;
2136 qemu_mutex_lock_iothread();
2137 CPU_FOREACH(cs) {
2138 PowerPCCPU *cpu = POWERPC_CPU(cs);
2139 CPUPPCState *cenv = &cpu->env;
2141 /* TODO: broadcast message to all threads of the same processor */
2142 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
2143 cenv->pending_interrupts |= 1 << irq;
2144 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2147 qemu_mutex_unlock_iothread();
2150 void helper_book3s_msgsnd(target_ulong rb)
2152 int pir = rb & DBELL_PROCIDTAG_MASK;
2154 if (!dbell_type_server(rb)) {
2155 return;
2158 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
2161 #if defined(TARGET_PPC64)
2162 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
2164 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
2166 if (!dbell_type_server(rb)) {
2167 return;
2170 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2174 * sends a message to other threads that are on the same
2175 * multi-threaded processor
2177 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
2179 int pir = env->spr_cb[SPR_PIR].default_value;
2181 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
2183 if (!dbell_type_server(rb)) {
2184 return;
2187 /* TODO: TCG supports only one thread */
2189 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
2191 #endif /* TARGET_PPC64 */
2193 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
2194 MMUAccessType access_type,
2195 int mmu_idx, uintptr_t retaddr)
2197 CPUPPCState *env = cs->env_ptr;
2198 uint32_t insn;
2200 /* Restore state and reload the insn we executed, for filling in DSISR. */
2201 cpu_restore_state(cs, retaddr, true);
2202 insn = cpu_ldl_code(env, env->nip);
2204 switch (env->mmu_model) {
2205 case POWERPC_MMU_SOFT_4xx:
2206 env->spr[SPR_40x_DEAR] = vaddr;
2207 break;
2208 case POWERPC_MMU_BOOKE:
2209 case POWERPC_MMU_BOOKE206:
2210 env->spr[SPR_BOOKE_DEAR] = vaddr;
2211 break;
2212 default:
2213 env->spr[SPR_DAR] = vaddr;
2214 break;
2217 cs->exception_index = POWERPC_EXCP_ALIGN;
2218 env->error_code = insn & 0x03FF0000;
2219 cpu_loop_exit(cs);
2221 #endif /* CONFIG_TCG */
2222 #endif /* !CONFIG_USER_ONLY */