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"
22 #include "exec/exec-all.h"
24 #include "helper_regs.h"
29 #include "exec/helper-proto.h"
30 #include "exec/cpu_ldst.h"
33 /*****************************************************************************/
34 /* Exception processing */
35 #if !defined(CONFIG_USER_ONLY)
37 static const char *powerpc_excp_name(int 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";
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),
134 static void ppc_excp_debug_sw_tlb(CPUPPCState
*env
, int excp
)
137 target_ulong
*miss
, *cmp
;
140 if (!qemu_loglevel_mask(CPU_LOG_MMU
)) {
144 if (excp
== POWERPC_EXCP_IFTLB
) {
147 miss
= &env
->spr
[SPR_IMISS
];
148 cmp
= &env
->spr
[SPR_ICMP
];
150 if (excp
== POWERPC_EXCP_DLTLB
) {
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
],
166 #if defined(TARGET_PPC64)
167 static int powerpc_reset_wakeup(CPUState
*cs
, CPUPPCState
*env
, int excp
,
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
) {
181 case POWERPC_EXCP_RESET
:
182 *msr
|= SRR1_WAKERESET
;
184 case POWERPC_EXCP_EXTERNAL
:
187 case POWERPC_EXCP_DECR
:
188 *msr
|= SRR1_WAKEDEC
;
190 case POWERPC_EXCP_SDOOR
:
191 *msr
|= SRR1_WAKEDBELL
;
193 case POWERPC_EXCP_SDOOR_HV
:
194 *msr
|= SRR1_WAKEHDBELL
;
196 case POWERPC_EXCP_HV_MAINT
:
197 *msr
|= SRR1_WAKEHMI
;
199 case POWERPC_EXCP_HVIRT
:
200 *msr
|= SRR1_WAKEHVI
;
203 cpu_abort(cs
, "Unsupported exception %d in Power Save mode\n",
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
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
);
274 if (excp
== POWERPC_EXCP_MCHECK
||
275 excp
== POWERPC_EXCP_RESET
||
276 excp
== POWERPC_EXCP_HV_MAINT
) {
277 /* SRESET, MCE, HMI never apply AIL */
281 if (!(pcc
->lpcr_mask
& LPCR_AIL
)) {
282 /* This CPU does not have AIL */
287 if (!(pcc
->lpcr_mask
& LPCR_HAIL
)) {
289 /* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
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.
301 ail
= (env
->spr
[SPR_LPCR
] & LPCR_AIL
) >> LPCR_AIL_SHIFT
;
306 /* AIL=1 is reserved, treat it like AIL=0 */
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.
320 if (*new_msr
& MSR_HVB
) {
321 if (!(env
->spr
[SPR_LPCR
] & LPCR_HAIL
)) {
322 /* HV interrupts depend on LPCR[HAIL] */
325 ail
= 3; /* HAIL=1 gives AIL=3 behaviour for HV interrupts */
327 ail
= (env
->spr
[SPR_LPCR
] & LPCR_AIL
) >> LPCR_AIL_SHIFT
;
332 if (ail
== 1 || ail
== 2) {
333 /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
339 * AIL applies, so the new MSR gets IR and DR set, and an offset applied
342 *new_msr
|= (1 << MSR_IR
) | (1 << MSR_DR
);
344 if (excp
!= POWERPC_EXCP_SYSCALL_VECTORED
) {
346 *vector
|= 0x0000000000018000ull
;
347 } else if (ail
== 3) {
348 *vector
|= 0xc000000000004000ull
;
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.
356 *vector
&= ~0x0000000000017000ull
; /* Un-apply the base offset */
357 *vector
|= 0xc000000000003000ull
; /* Apply scv's AIL=3 offset */
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
380 hreg_compute_hflags(env
);
382 /* Reset exception state */
383 cs
->exception_index
= POWERPC_EXCP_NONE
;
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
;
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 */
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",
430 vector
|= env
->excp_prefix
;
433 case POWERPC_EXCP_CRITICAL
: /* Critical input */
437 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
440 * Machine check exception is not enabled. Enter
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");
450 cpu_interrupt_exittb(cs
);
453 /* machine check exceptions don't have ME set */
454 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
459 case POWERPC_EXCP_DSI
: /* Data storage exception */
460 trace_ppc_excp_dsi(env
->spr
[SPR_40x_ESR
], env
->spr
[SPR_40x_DEAR
]);
462 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
463 trace_ppc_excp_isi(msr
, env
->nip
);
465 case POWERPC_EXCP_EXTERNAL
: /* External input */
467 case POWERPC_EXCP_ALIGN
: /* Alignment exception */
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
;
478 env
->spr
[SPR_40x_ESR
] = ESR_FP
;
480 case POWERPC_EXCP_INVAL
:
481 trace_ppc_excp_inval(env
->nip
);
482 env
->spr
[SPR_40x_ESR
] = ESR_PIL
;
484 case POWERPC_EXCP_PRIV
:
485 env
->spr
[SPR_40x_ESR
] = ESR_PPR
;
487 case POWERPC_EXCP_TRAP
:
488 env
->spr
[SPR_40x_ESR
] = ESR_PTR
;
491 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
496 case POWERPC_EXCP_SYSCALL
: /* System call exception */
500 * We need to correct the NIP which in this case is supposed
501 * to point to the next instruction
505 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
506 trace_ppc_excp_print("FIT");
508 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
509 trace_ppc_excp_print("WDT");
511 case POWERPC_EXCP_DTLB
: /* Data TLB error */
512 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
514 case POWERPC_EXCP_PIT
: /* Programmable interval timer interrupt */
515 trace_ppc_excp_print("PIT");
517 case POWERPC_EXCP_DEBUG
: /* Debug interrupt */
518 cpu_abort(cs
, "%s exception not implemented\n",
519 powerpc_excp_name(excp
));
522 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
527 env
->spr
[srr0
] = env
->nip
;
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",
564 vector
|= env
->excp_prefix
;
567 case POWERPC_EXCP_CRITICAL
: /* Critical input */
569 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
572 * Machine check exception is not enabled. Enter
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");
582 cpu_interrupt_exittb(cs
);
585 /* machine check exceptions don't have ME set */
586 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
589 case POWERPC_EXCP_DSI
: /* Data storage exception */
590 trace_ppc_excp_dsi(env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
592 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
593 trace_ppc_excp_isi(msr
, env
->nip
);
594 msr
|= env
->error_code
;
596 case POWERPC_EXCP_EXTERNAL
: /* External input */
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;
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
;
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.
624 case POWERPC_EXCP_INVAL
:
625 trace_ppc_excp_inval(env
->nip
);
628 case POWERPC_EXCP_PRIV
:
631 case POWERPC_EXCP_TRAP
:
635 /* Should never occur */
636 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
641 case POWERPC_EXCP_SYSCALL
: /* System call exception */
645 * We need to correct the NIP which in this case is supposed
646 * to point to the next instruction
650 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
651 case POWERPC_EXCP_DECR
: /* Decrementer exception */
653 case POWERPC_EXCP_DTLB
: /* Data TLB error */
654 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
656 case POWERPC_EXCP_RESET
: /* System reset exception */
658 cpu_abort(cs
, "Trying to deliver power-saving system reset "
659 "exception %d with no HV support\n", excp
);
662 case POWERPC_EXCP_TRACE
: /* Trace exception */
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;
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
));
690 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
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
;
703 env
->spr
[SPR_SRR0
] = env
->nip
;
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",
740 vector
|= env
->excp_prefix
;
743 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
746 * Machine check exception is not enabled. Enter
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");
756 cpu_interrupt_exittb(cs
);
759 /* machine check exceptions don't have ME set */
760 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
763 case POWERPC_EXCP_DSI
: /* Data storage exception */
764 trace_ppc_excp_dsi(env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
766 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
767 trace_ppc_excp_isi(msr
, env
->nip
);
768 msr
|= env
->error_code
;
770 case POWERPC_EXCP_EXTERNAL
: /* External input */
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;
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
;
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.
798 case POWERPC_EXCP_INVAL
:
799 trace_ppc_excp_inval(env
->nip
);
802 case POWERPC_EXCP_PRIV
:
805 case POWERPC_EXCP_TRAP
:
809 /* Should never occur */
810 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
815 case POWERPC_EXCP_SYSCALL
: /* System call exception */
817 int lev
= env
->error_code
;
819 if (lev
== 1 && cpu
->vhyp
) {
826 * We need to correct the NIP which in this case is supposed
827 * to point to the next instruction
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
);
846 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
847 case POWERPC_EXCP_DECR
: /* Decrementer exception */
849 case POWERPC_EXCP_RESET
: /* System reset exception */
851 cpu_abort(cs
, "Trying to deliver power-saving system reset "
852 "exception %d with no HV support\n", excp
);
855 case POWERPC_EXCP_TRACE
: /* Trace exception */
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;
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
));
876 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
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
;
889 env
->spr
[SPR_SRR0
] = env
->nip
;
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",
926 vector
|= env
->excp_prefix
;
929 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
932 * Machine check exception is not enabled. Enter
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");
942 cpu_interrupt_exittb(cs
);
945 /* machine check exceptions don't have ME set */
946 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
949 case POWERPC_EXCP_DSI
: /* Data storage exception */
950 trace_ppc_excp_dsi(env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
952 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
953 trace_ppc_excp_isi(msr
, env
->nip
);
954 msr
|= env
->error_code
;
956 case POWERPC_EXCP_EXTERNAL
: /* External input */
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;
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
;
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.
984 case POWERPC_EXCP_INVAL
:
985 trace_ppc_excp_inval(env
->nip
);
988 case POWERPC_EXCP_PRIV
:
991 case POWERPC_EXCP_TRAP
:
995 /* Should never occur */
996 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
1001 case POWERPC_EXCP_SYSCALL
: /* System call exception */
1003 int lev
= env
->error_code
;
1005 if ((lev
== 1) && cpu
->vhyp
) {
1012 * We need to correct the NIP which in this case is supposed
1013 * to point to the next instruction
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
);
1032 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
1033 case POWERPC_EXCP_DECR
: /* Decrementer exception */
1035 case POWERPC_EXCP_RESET
: /* System reset exception */
1037 cpu_abort(cs
, "Trying to deliver power-saving system reset "
1038 "exception %d with no HV support\n", excp
);
1041 case POWERPC_EXCP_TRACE
: /* Trace exception */
1043 case POWERPC_EXCP_VPU
: /* Vector unavailable exception */
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
));
1054 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
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
;
1067 env
->spr
[SPR_SRR0
] = env
->nip
;
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
;
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 */
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
;
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
;
1112 vector
= env
->excp_vectors
[excp
];
1113 if (vector
== (target_ulong
)-1ULL) {
1114 cpu_abort(cs
, "Raised an exception without defined vector %d\n",
1118 vector
|= env
->excp_prefix
;
1121 case POWERPC_EXCP_CRITICAL
: /* Critical input */
1122 srr0
= SPR_BOOKE_CSRR0
;
1123 srr1
= SPR_BOOKE_CSRR1
;
1125 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
1128 * Machine check exception is not enabled. Enter
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");
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
;
1152 case POWERPC_EXCP_DSI
: /* Data storage exception */
1153 trace_ppc_excp_dsi(env
->spr
[SPR_BOOKE_ESR
], env
->spr
[SPR_BOOKE_DEAR
]);
1155 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
1156 trace_ppc_excp_isi(msr
, env
->nip
);
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
);
1164 case POWERPC_EXCP_ALIGN
: /* Alignment exception */
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;
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.
1182 env
->spr
[SPR_BOOKE_ESR
] = ESR_FP
;
1184 case POWERPC_EXCP_INVAL
:
1185 trace_ppc_excp_inval(env
->nip
);
1187 env
->spr
[SPR_BOOKE_ESR
] = ESR_PIL
;
1189 case POWERPC_EXCP_PRIV
:
1191 env
->spr
[SPR_BOOKE_ESR
] = ESR_PPR
;
1193 case POWERPC_EXCP_TRAP
:
1195 env
->spr
[SPR_BOOKE_ESR
] = ESR_PTR
;
1198 /* Should never occur */
1199 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
1204 case POWERPC_EXCP_SYSCALL
: /* System call exception */
1208 * We need to correct the NIP which in this case is supposed
1209 * to point to the next instruction
1213 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
1214 case POWERPC_EXCP_APU
: /* Auxiliary processor unavailable */
1215 case POWERPC_EXCP_DECR
: /* Decrementer exception */
1217 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
1219 trace_ppc_excp_print("FIT");
1221 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
1222 trace_ppc_excp_print("WDT");
1223 srr0
= SPR_BOOKE_CSRR0
;
1224 srr1
= SPR_BOOKE_CSRR1
;
1226 case POWERPC_EXCP_DTLB
: /* Data TLB error */
1227 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
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 */
1240 cpu_abort(cs
, "Debug exception triggered on unsupported model\n");
1243 case POWERPC_EXCP_SPEU
: /* SPE/embedded floating-point unavailable/VPU */
1244 env
->spr
[SPR_BOOKE_ESR
] = ESR_SPV
;
1246 case POWERPC_EXCP_RESET
: /* System reset exception */
1248 cpu_abort(cs
, "Trying to deliver power-saving system reset "
1249 "exception %d with no HV support\n", excp
);
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
));
1258 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
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
;
1267 vector
= (uint32_t)vector
;
1272 env
->spr
[srr0
] = env
->nip
;
1275 env
->spr
[srr1
] = msr
;
1277 powerpc_set_excp_state(cpu
, vector
, new_msr
);
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
)
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 */
1314 * check for special resume at 0x100 from doze/nap/sleep/winkle on
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",
1335 vector
|= env
->excp_prefix
;
1338 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
1341 * Machine check exception is not enabled. Enter
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");
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
);
1365 case POWERPC_EXCP_DSI
: /* Data storage exception */
1366 trace_ppc_excp_dsi(env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
1368 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
1369 trace_ppc_excp_isi(msr
, env
->nip
);
1370 msr
|= env
->error_code
;
1372 case POWERPC_EXCP_EXTERNAL
: /* External input */
1377 * LPES0 is only taken into consideration if we support HV
1378 * mode for this CPU.
1380 if (!env
->has_hv_mode
) {
1384 lpes0
= !!(env
->spr
[SPR_LPCR
] & LPCR_LPES0
);
1387 new_msr
|= (target_ulong
)MSR_HVB
;
1388 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
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;
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;
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.
1421 case POWERPC_EXCP_INVAL
:
1422 trace_ppc_excp_inval(env
->nip
);
1425 case POWERPC_EXCP_PRIV
:
1428 case POWERPC_EXCP_TRAP
:
1432 /* Should never occur */
1433 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
1438 case POWERPC_EXCP_SYSCALL
: /* System call exception */
1439 lev
= env
->error_code
;
1441 if ((lev
== 1) && cpu
->vhyp
) {
1448 * We need to correct the NIP which in this case is supposed
1449 * to point to the next instruction
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
);
1461 new_msr
|= (target_ulong
)MSR_HVB
;
1464 case POWERPC_EXCP_SYSCALL_VECTORED
: /* scv exception */
1465 lev
= env
->error_code
;
1468 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_EE
);
1469 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
1471 vector
+= lev
* 0x20;
1476 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
1477 case POWERPC_EXCP_DECR
: /* Decrementer exception */
1479 case POWERPC_EXCP_RESET
: /* System reset exception */
1480 /* A power-saving exception sets ME, otherwise it is unchanged */
1482 /* indicate that we resumed from power save mode */
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
;
1494 cpu_abort(cs
, "Trying to deliver power-saving system reset "
1495 "exception %d with no HV support\n", excp
);
1499 case POWERPC_EXCP_DSEG
: /* Data segment exception */
1500 case POWERPC_EXCP_ISEG
: /* Instruction segment exception */
1501 case POWERPC_EXCP_TRACE
: /* Trace exception */
1503 case POWERPC_EXCP_HISI
: /* Hypervisor instruction storage exception */
1504 msr
|= env
->error_code
;
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 */
1513 new_msr
|= (target_ulong
)MSR_HVB
;
1514 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
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);
1521 case POWERPC_EXCP_HV_FU
: /* Hypervisor Facility Unavailable Exception */
1522 env
->spr
[SPR_HFSCR
] |= ((target_ulong
)env
->error_code
<< FSCR_IC_POS
);
1525 new_msr
|= (target_ulong
)MSR_HVB
;
1526 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
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
));
1538 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
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
) {
1560 env
->spr
[srr0
] = env
->nip
;
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
);
1572 static inline void powerpc_excp_books(PowerPCCPU
*cpu
, int excp
)
1574 g_assert_not_reached();
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
);
1595 case POWERPC_EXCP_6xx
:
1596 powerpc_excp_6xx(cpu
, excp
);
1598 case POWERPC_EXCP_7xx
:
1599 powerpc_excp_7xx(cpu
, excp
);
1601 case POWERPC_EXCP_74xx
:
1602 powerpc_excp_74xx(cpu
, excp
);
1604 case POWERPC_EXCP_BOOKE
:
1605 powerpc_excp_booke(cpu
, excp
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1694 /* External critical interrupt */
1695 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CEXT
)) {
1696 powerpc_excp(cpu
, POWERPC_EXCP_CRITICAL
);
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
);
1707 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CDOORBELL
)) {
1708 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_CDOORBELL
);
1709 powerpc_excp(cpu
, POWERPC_EXCP_DOORCI
);
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
);
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
);
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
);
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
);
1737 powerpc_excp(cpu
, POWERPC_EXCP_DOORI
);
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
);
1746 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_PERFM
)) {
1747 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_PERFM
);
1748 powerpc_excp(cpu
, POWERPC_EXCP_PERFM
);
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
);
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
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
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
;
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
,
1846 raise_exception_err_ra(env
, exception
, 0, raddr
);
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);
1862 #if !defined(CONFIG_USER_ONLY)
1864 void helper_store_msr(CPUPPCState
*env
, target_ulong val
)
1866 uint32_t excp
= hreg_store_msr(env
, val
, 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
);
1881 raise_exception_err(env
, POWERPC_EXCP_FU
, FSCR_IC_SCV
);
1885 void helper_pminsn(CPUPPCState
*env
, powerpc_pm_insn_t insn
)
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
;
1915 nip
= (uint32_t)nip
;
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
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
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
]);
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
];
1986 env
->spr
[SPR_BESCR
] |= BESCR_GE
;
1988 env
->spr
[SPR_BESCR
] &= ~BESCR_GE
;
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) */
2020 void helper_tw(CPUPPCState
*env
, target_ulong arg1
, target_ulong arg2
,
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
,
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());
2049 #if !defined(CONFIG_USER_ONLY)
2053 /* Embedded.Processor Control */
2054 static int dbell2irq(target_ulong rb
)
2056 int msg
= rb
& DBELL_TYPE_MASK
;
2060 case DBELL_TYPE_DBELL
:
2061 irq
= PPC_INTERRUPT_DOORBELL
;
2063 case DBELL_TYPE_DBELL_CRIT
:
2064 irq
= PPC_INTERRUPT_CDOORBELL
;
2066 case DBELL_TYPE_G_DBELL
:
2067 case DBELL_TYPE_G_DBELL_CRIT
:
2068 case DBELL_TYPE_G_DBELL_MC
:
2077 void helper_msgclr(CPUPPCState
*env
, target_ulong rb
)
2079 int irq
= dbell2irq(rb
);
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
;
2098 qemu_mutex_lock_iothread();
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
)) {
2129 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_HDOORBELL
);
2132 static void book3s_msgsnd_common(int pir
, int irq
)
2136 qemu_mutex_lock_iothread();
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
)) {
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
)) {
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
)) {
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
;
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
;
2208 case POWERPC_MMU_BOOKE
:
2209 case POWERPC_MMU_BOOKE206
:
2210 env
->spr
[SPR_BOOKE_DEAR
] = vaddr
;
2213 env
->spr
[SPR_DAR
] = vaddr
;
2217 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
2218 env
->error_code
= insn
& 0x03FF0000;
2221 #endif /* CONFIG_TCG */
2222 #endif /* !CONFIG_USER_ONLY */