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 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"
21 #include "exec/helper-proto.h"
22 #include "exec/exec-all.h"
23 #include "exec/cpu_ldst.h"
25 #include "helper_regs.h"
28 //#define DEBUG_SOFTWARE_TLB
29 //#define DEBUG_EXCEPTIONS
31 #ifdef DEBUG_EXCEPTIONS
32 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
34 # define LOG_EXCP(...) do { } while (0)
37 /*****************************************************************************/
38 /* PowerPC Hypercall emulation */
40 void (*cpu_ppc_hypercall
)(PowerPCCPU
*);
42 /*****************************************************************************/
43 /* Exception processing */
44 #if defined(CONFIG_USER_ONLY)
45 void ppc_cpu_do_interrupt(CPUState
*cs
)
47 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
48 CPUPPCState
*env
= &cpu
->env
;
50 cs
->exception_index
= POWERPC_EXCP_NONE
;
54 static void ppc_hw_interrupt(CPUPPCState
*env
)
56 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
58 cs
->exception_index
= POWERPC_EXCP_NONE
;
61 #else /* defined(CONFIG_USER_ONLY) */
62 static inline void dump_syscall(CPUPPCState
*env
)
64 qemu_log_mask(CPU_LOG_INT
, "syscall r0=%016" PRIx64
" r3=%016" PRIx64
65 " r4=%016" PRIx64
" r5=%016" PRIx64
" r6=%016" PRIx64
66 " nip=" TARGET_FMT_lx
"\n",
67 ppc_dump_gpr(env
, 0), ppc_dump_gpr(env
, 3),
68 ppc_dump_gpr(env
, 4), ppc_dump_gpr(env
, 5),
69 ppc_dump_gpr(env
, 6), env
->nip
);
72 /* Note that this function should be greatly optimized
73 * when called with a constant excp, from ppc_hw_interrupt
75 static inline void powerpc_excp(PowerPCCPU
*cpu
, int excp_model
, int excp
)
77 CPUState
*cs
= CPU(cpu
);
78 CPUPPCState
*env
= &cpu
->env
;
79 target_ulong msr
, new_msr
, vector
;
80 int srr0
, srr1
, asrr0
, asrr1
;
81 int lpes0
, lpes1
, lev
, ail
;
84 /* XXX: find a suitable condition to enable the hypervisor mode */
85 lpes0
= (env
->spr
[SPR_LPCR
] >> 1) & 1;
86 lpes1
= (env
->spr
[SPR_LPCR
] >> 2) & 1;
88 /* Those values ensure we won't enter the hypervisor mode */
93 qemu_log_mask(CPU_LOG_INT
, "Raise exception at " TARGET_FMT_lx
94 " => %08x (%02x)\n", env
->nip
, excp
, env
->error_code
);
96 /* new srr1 value excluding must-be-zero bits */
97 if (excp_model
== POWERPC_EXCP_BOOKE
) {
100 msr
= env
->msr
& ~0x783f0000ULL
;
103 /* new interrupt handler msr */
104 new_msr
= env
->msr
& ((target_ulong
)1 << MSR_ME
);
106 /* target registers */
112 /* Exception targetting modifiers
114 * AIL is initialized here but can be cleared by
115 * selected exceptions
117 #if defined(TARGET_PPC64)
118 if (excp_model
== POWERPC_EXCP_POWER7
||
119 excp_model
== POWERPC_EXCP_POWER8
) {
120 if (excp_model
== POWERPC_EXCP_POWER8
) {
121 ail
= (env
->spr
[SPR_LPCR
] & LPCR_AIL
) >> LPCR_AIL_SHIFT
;
126 #endif /* defined(TARGET_PPC64) */
132 case POWERPC_EXCP_NONE
:
133 /* Should never happen */
135 case POWERPC_EXCP_CRITICAL
: /* Critical input */
136 switch (excp_model
) {
137 case POWERPC_EXCP_40x
:
141 case POWERPC_EXCP_BOOKE
:
142 srr0
= SPR_BOOKE_CSRR0
;
143 srr1
= SPR_BOOKE_CSRR1
;
145 case POWERPC_EXCP_G2
:
151 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
153 /* Machine check exception is not enabled.
154 * Enter checkstop state.
156 fprintf(stderr
, "Machine check while not allowed. "
157 "Entering checkstop state\n");
158 if (qemu_log_separate()) {
159 qemu_log("Machine check while not allowed. "
160 "Entering checkstop state\n");
163 cs
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
166 /* XXX: find a suitable condition to enable the hypervisor mode */
167 new_msr
|= (target_ulong
)MSR_HVB
;
171 /* machine check exceptions don't have ME set */
172 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
174 /* XXX: should also have something loaded in DAR / DSISR */
175 switch (excp_model
) {
176 case POWERPC_EXCP_40x
:
180 case POWERPC_EXCP_BOOKE
:
181 /* FIXME: choose one or the other based on CPU type */
182 srr0
= SPR_BOOKE_MCSRR0
;
183 srr1
= SPR_BOOKE_MCSRR1
;
184 asrr0
= SPR_BOOKE_CSRR0
;
185 asrr1
= SPR_BOOKE_CSRR1
;
191 case POWERPC_EXCP_DSI
: /* Data storage exception */
192 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx
" DAR=" TARGET_FMT_lx
193 "\n", env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
195 new_msr
|= (target_ulong
)MSR_HVB
;
198 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
199 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx
", nip=" TARGET_FMT_lx
200 "\n", msr
, env
->nip
);
202 new_msr
|= (target_ulong
)MSR_HVB
;
204 msr
|= env
->error_code
;
206 case POWERPC_EXCP_EXTERNAL
: /* External input */
210 new_msr
|= (target_ulong
)MSR_HVB
;
212 if (env
->mpic_proxy
) {
213 /* IACK the IRQ on delivery */
214 env
->spr
[SPR_BOOKE_EPR
] = ldl_phys(cs
->as
, env
->mpic_iack
);
217 case POWERPC_EXCP_ALIGN
: /* Alignment exception */
219 new_msr
|= (target_ulong
)MSR_HVB
;
221 /* XXX: this is false */
222 /* Get rS/rD and rA from faulting opcode */
223 env
->spr
[SPR_DSISR
] |= (cpu_ldl_code(env
, (env
->nip
- 4))
226 case POWERPC_EXCP_PROGRAM
: /* Program exception */
227 switch (env
->error_code
& ~0xF) {
228 case POWERPC_EXCP_FP
:
229 if ((msr_fe0
== 0 && msr_fe1
== 0) || msr_fp
== 0) {
230 LOG_EXCP("Ignore floating point exception\n");
231 cs
->exception_index
= POWERPC_EXCP_NONE
;
236 new_msr
|= (target_ulong
)MSR_HVB
;
239 if (msr_fe0
== msr_fe1
) {
244 case POWERPC_EXCP_INVAL
:
245 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx
"\n", env
->nip
);
247 new_msr
|= (target_ulong
)MSR_HVB
;
250 env
->spr
[SPR_BOOKE_ESR
] = ESR_PIL
;
252 case POWERPC_EXCP_PRIV
:
254 new_msr
|= (target_ulong
)MSR_HVB
;
257 env
->spr
[SPR_BOOKE_ESR
] = ESR_PPR
;
259 case POWERPC_EXCP_TRAP
:
261 new_msr
|= (target_ulong
)MSR_HVB
;
264 env
->spr
[SPR_BOOKE_ESR
] = ESR_PTR
;
267 /* Should never occur */
268 cpu_abort(cs
, "Invalid program exception %d. Aborting\n",
273 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
275 new_msr
|= (target_ulong
)MSR_HVB
;
278 case POWERPC_EXCP_SYSCALL
: /* System call exception */
280 lev
= env
->error_code
;
281 if ((lev
== 1) && cpu_ppc_hypercall
) {
282 cpu_ppc_hypercall(cpu
);
285 if (lev
== 1 || (lpes0
== 0 && lpes1
== 0)) {
286 new_msr
|= (target_ulong
)MSR_HVB
;
289 case POWERPC_EXCP_APU
: /* Auxiliary processor unavailable */
291 case POWERPC_EXCP_DECR
: /* Decrementer exception */
293 new_msr
|= (target_ulong
)MSR_HVB
;
296 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
298 LOG_EXCP("FIT exception\n");
300 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
301 LOG_EXCP("WDT exception\n");
302 switch (excp_model
) {
303 case POWERPC_EXCP_BOOKE
:
304 srr0
= SPR_BOOKE_CSRR0
;
305 srr1
= SPR_BOOKE_CSRR1
;
311 case POWERPC_EXCP_DTLB
: /* Data TLB error */
313 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
315 case POWERPC_EXCP_DEBUG
: /* Debug interrupt */
316 switch (excp_model
) {
317 case POWERPC_EXCP_BOOKE
:
318 /* FIXME: choose one or the other based on CPU type */
319 srr0
= SPR_BOOKE_DSRR0
;
320 srr1
= SPR_BOOKE_DSRR1
;
321 asrr0
= SPR_BOOKE_CSRR0
;
322 asrr1
= SPR_BOOKE_CSRR1
;
328 cpu_abort(cs
, "Debug exception is not implemented yet !\n");
330 case POWERPC_EXCP_SPEU
: /* SPE/embedded floating-point unavailable */
331 env
->spr
[SPR_BOOKE_ESR
] = ESR_SPV
;
333 case POWERPC_EXCP_EFPDI
: /* Embedded floating-point data interrupt */
335 cpu_abort(cs
, "Embedded floating point data exception "
336 "is not implemented yet !\n");
337 env
->spr
[SPR_BOOKE_ESR
] = ESR_SPV
;
339 case POWERPC_EXCP_EFPRI
: /* Embedded floating-point round interrupt */
341 cpu_abort(cs
, "Embedded floating point round exception "
342 "is not implemented yet !\n");
343 env
->spr
[SPR_BOOKE_ESR
] = ESR_SPV
;
345 case POWERPC_EXCP_EPERFM
: /* Embedded performance monitor interrupt */
348 "Performance counter exception is not implemented yet !\n");
350 case POWERPC_EXCP_DOORI
: /* Embedded doorbell interrupt */
352 case POWERPC_EXCP_DOORCI
: /* Embedded doorbell critical interrupt */
353 srr0
= SPR_BOOKE_CSRR0
;
354 srr1
= SPR_BOOKE_CSRR1
;
356 case POWERPC_EXCP_RESET
: /* System reset exception */
358 /* indicate that we resumed from power save mode */
361 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
365 /* XXX: find a suitable condition to enable the hypervisor mode */
366 new_msr
|= (target_ulong
)MSR_HVB
;
370 case POWERPC_EXCP_DSEG
: /* Data segment exception */
372 new_msr
|= (target_ulong
)MSR_HVB
;
375 case POWERPC_EXCP_ISEG
: /* Instruction segment exception */
377 new_msr
|= (target_ulong
)MSR_HVB
;
380 case POWERPC_EXCP_HDECR
: /* Hypervisor decrementer exception */
383 new_msr
|= (target_ulong
)MSR_HVB
;
384 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
386 case POWERPC_EXCP_TRACE
: /* Trace exception */
388 new_msr
|= (target_ulong
)MSR_HVB
;
391 case POWERPC_EXCP_HDSI
: /* Hypervisor data storage exception */
394 new_msr
|= (target_ulong
)MSR_HVB
;
395 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
397 case POWERPC_EXCP_HISI
: /* Hypervisor instruction storage exception */
400 new_msr
|= (target_ulong
)MSR_HVB
;
401 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
403 case POWERPC_EXCP_HDSEG
: /* Hypervisor data segment exception */
406 new_msr
|= (target_ulong
)MSR_HVB
;
407 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
409 case POWERPC_EXCP_HISEG
: /* Hypervisor instruction segment exception */
412 new_msr
|= (target_ulong
)MSR_HVB
;
413 new_msr
|= env
->msr
& ((target_ulong
)1 << MSR_RI
);
415 case POWERPC_EXCP_VPU
: /* Vector unavailable exception */
417 new_msr
|= (target_ulong
)MSR_HVB
;
420 case POWERPC_EXCP_VSXU
: /* VSX unavailable exception */
422 new_msr
|= (target_ulong
)MSR_HVB
;
425 case POWERPC_EXCP_FU
: /* Facility unavailable exception */
427 new_msr
|= (target_ulong
)MSR_HVB
;
430 case POWERPC_EXCP_PIT
: /* Programmable interval timer interrupt */
431 LOG_EXCP("PIT exception\n");
433 case POWERPC_EXCP_IO
: /* IO error exception */
435 cpu_abort(cs
, "601 IO error exception is not implemented yet !\n");
437 case POWERPC_EXCP_RUNM
: /* Run mode exception */
439 cpu_abort(cs
, "601 run mode exception is not implemented yet !\n");
441 case POWERPC_EXCP_EMUL
: /* Emulation trap exception */
443 cpu_abort(cs
, "602 emulation trap exception "
444 "is not implemented yet !\n");
446 case POWERPC_EXCP_IFTLB
: /* Instruction fetch TLB error */
447 if (lpes1
== 0) { /* XXX: check this */
448 new_msr
|= (target_ulong
)MSR_HVB
;
450 switch (excp_model
) {
451 case POWERPC_EXCP_602
:
452 case POWERPC_EXCP_603
:
453 case POWERPC_EXCP_603E
:
454 case POWERPC_EXCP_G2
:
456 case POWERPC_EXCP_7x5
:
458 case POWERPC_EXCP_74xx
:
461 cpu_abort(cs
, "Invalid instruction TLB miss exception\n");
465 case POWERPC_EXCP_DLTLB
: /* Data load TLB miss */
466 if (lpes1
== 0) { /* XXX: check this */
467 new_msr
|= (target_ulong
)MSR_HVB
;
469 switch (excp_model
) {
470 case POWERPC_EXCP_602
:
471 case POWERPC_EXCP_603
:
472 case POWERPC_EXCP_603E
:
473 case POWERPC_EXCP_G2
:
475 case POWERPC_EXCP_7x5
:
477 case POWERPC_EXCP_74xx
:
480 cpu_abort(cs
, "Invalid data load TLB miss exception\n");
484 case POWERPC_EXCP_DSTLB
: /* Data store TLB miss */
485 if (lpes1
== 0) { /* XXX: check this */
486 new_msr
|= (target_ulong
)MSR_HVB
;
488 switch (excp_model
) {
489 case POWERPC_EXCP_602
:
490 case POWERPC_EXCP_603
:
491 case POWERPC_EXCP_603E
:
492 case POWERPC_EXCP_G2
:
494 /* Swap temporary saved registers with GPRs */
495 if (!(new_msr
& ((target_ulong
)1 << MSR_TGPR
))) {
496 new_msr
|= (target_ulong
)1 << MSR_TGPR
;
497 hreg_swap_gpr_tgpr(env
);
500 case POWERPC_EXCP_7x5
:
502 #if defined(DEBUG_SOFTWARE_TLB)
503 if (qemu_log_enabled()) {
505 target_ulong
*miss
, *cmp
;
508 if (excp
== POWERPC_EXCP_IFTLB
) {
511 miss
= &env
->spr
[SPR_IMISS
];
512 cmp
= &env
->spr
[SPR_ICMP
];
514 if (excp
== POWERPC_EXCP_DLTLB
) {
520 miss
= &env
->spr
[SPR_DMISS
];
521 cmp
= &env
->spr
[SPR_DCMP
];
523 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx
" %cC "
524 TARGET_FMT_lx
" H1 " TARGET_FMT_lx
" H2 "
525 TARGET_FMT_lx
" %08x\n", es
, en
, *miss
, en
, *cmp
,
526 env
->spr
[SPR_HASH1
], env
->spr
[SPR_HASH2
],
530 msr
|= env
->crf
[0] << 28;
531 msr
|= env
->error_code
; /* key, D/I, S/L bits */
532 /* Set way using a LRU mechanism */
533 msr
|= ((env
->last_way
+ 1) & (env
->nb_ways
- 1)) << 17;
535 case POWERPC_EXCP_74xx
:
537 #if defined(DEBUG_SOFTWARE_TLB)
538 if (qemu_log_enabled()) {
540 target_ulong
*miss
, *cmp
;
543 if (excp
== POWERPC_EXCP_IFTLB
) {
546 miss
= &env
->spr
[SPR_TLBMISS
];
547 cmp
= &env
->spr
[SPR_PTEHI
];
549 if (excp
== POWERPC_EXCP_DLTLB
) {
555 miss
= &env
->spr
[SPR_TLBMISS
];
556 cmp
= &env
->spr
[SPR_PTEHI
];
558 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx
" %cC "
559 TARGET_FMT_lx
" %08x\n", es
, en
, *miss
, en
, *cmp
,
563 msr
|= env
->error_code
; /* key bit */
566 cpu_abort(cs
, "Invalid data store TLB miss exception\n");
570 case POWERPC_EXCP_FPA
: /* Floating-point assist exception */
572 cpu_abort(cs
, "Floating point assist exception "
573 "is not implemented yet !\n");
575 case POWERPC_EXCP_DABR
: /* Data address breakpoint */
577 cpu_abort(cs
, "DABR exception is not implemented yet !\n");
579 case POWERPC_EXCP_IABR
: /* Instruction address breakpoint */
581 cpu_abort(cs
, "IABR exception is not implemented yet !\n");
583 case POWERPC_EXCP_SMI
: /* System management interrupt */
585 cpu_abort(cs
, "SMI exception is not implemented yet !\n");
587 case POWERPC_EXCP_THERM
: /* Thermal interrupt */
589 cpu_abort(cs
, "Thermal management exception "
590 "is not implemented yet !\n");
592 case POWERPC_EXCP_PERFM
: /* Embedded performance monitor interrupt */
594 new_msr
|= (target_ulong
)MSR_HVB
;
598 "Performance counter exception is not implemented yet !\n");
600 case POWERPC_EXCP_VPUA
: /* Vector assist exception */
602 cpu_abort(cs
, "VPU assist exception is not implemented yet !\n");
604 case POWERPC_EXCP_SOFTP
: /* Soft patch exception */
607 "970 soft-patch exception is not implemented yet !\n");
609 case POWERPC_EXCP_MAINT
: /* Maintenance exception */
612 "970 maintenance exception is not implemented yet !\n");
614 case POWERPC_EXCP_MEXTBR
: /* Maskable external breakpoint */
616 cpu_abort(cs
, "Maskable external exception "
617 "is not implemented yet !\n");
619 case POWERPC_EXCP_NMEXTBR
: /* Non maskable external breakpoint */
621 cpu_abort(cs
, "Non maskable external exception "
622 "is not implemented yet !\n");
626 cpu_abort(cs
, "Invalid PowerPC exception %d. Aborting\n", excp
);
629 /* save current instruction location */
630 env
->spr
[srr0
] = env
->nip
- 4;
633 /* save next instruction location */
634 env
->spr
[srr0
] = env
->nip
;
638 env
->spr
[srr1
] = msr
;
639 /* If any alternate SRR register are defined, duplicate saved values */
641 env
->spr
[asrr0
] = env
->spr
[srr0
];
644 env
->spr
[asrr1
] = env
->spr
[srr1
];
647 if (env
->spr
[SPR_LPCR
] & LPCR_AIL
) {
648 new_msr
|= (1 << MSR_IR
) | (1 << MSR_DR
);
649 } else if (msr
& ((1 << MSR_IR
) | (1 << MSR_DR
))) {
650 /* If we disactivated any translation, flush TLBs */
655 if (excp_model
== POWERPC_EXCP_POWER7
||
656 excp_model
== POWERPC_EXCP_POWER8
) {
657 if (env
->spr
[SPR_LPCR
] & LPCR_ILE
) {
658 new_msr
|= (target_ulong
)1 << MSR_LE
;
660 } else if (msr_ile
) {
661 new_msr
|= (target_ulong
)1 << MSR_LE
;
665 new_msr
|= (target_ulong
)1 << MSR_LE
;
669 /* Jump to handler */
670 vector
= env
->excp_vectors
[excp
];
671 if (vector
== (target_ulong
)-1ULL) {
672 cpu_abort(cs
, "Raised an exception without defined vector %d\n",
675 vector
|= env
->excp_prefix
;
677 /* AIL only works if there is no HV transition and we are running with
678 * translations enabled
680 if (!((msr
>> MSR_IR
) & 1) || !((msr
>> MSR_DR
) & 1)) {
685 new_msr
|= (1 << MSR_IR
) | (1 << MSR_DR
);
690 case AIL_C000_0000_0000_4000
:
691 vector
|= 0xc000000000004000ull
;
694 cpu_abort(cs
, "Invalid AIL combination %d\n", ail
);
699 #if defined(TARGET_PPC64)
700 if (excp_model
== POWERPC_EXCP_BOOKE
) {
701 if (env
->spr
[SPR_BOOKE_EPCR
] & EPCR_ICM
) {
702 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
703 new_msr
|= (target_ulong
)1 << MSR_CM
;
705 vector
= (uint32_t)vector
;
708 if (!msr_isf
&& !(env
->mmu_model
& POWERPC_MMU_64
)) {
709 vector
= (uint32_t)vector
;
711 new_msr
|= (target_ulong
)1 << MSR_SF
;
715 /* XXX: we don't use hreg_store_msr here as already have treated
716 * any special case that could occur. Just store MSR and update hflags
718 env
->msr
= new_msr
& env
->msr_mask
;
719 hreg_compute_hflags(env
);
721 /* Reset exception state */
722 cs
->exception_index
= POWERPC_EXCP_NONE
;
725 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
726 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
727 /* XXX: The BookE changes address space when switching modes,
728 we should probably implement that as different MMU indexes,
729 but for the moment we do it the slow way and flush all. */
734 void ppc_cpu_do_interrupt(CPUState
*cs
)
736 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
737 CPUPPCState
*env
= &cpu
->env
;
739 powerpc_excp(cpu
, env
->excp_model
, cs
->exception_index
);
742 static void ppc_hw_interrupt(CPUPPCState
*env
)
744 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
747 CPUState
*cs
= CPU(cpu
);
749 qemu_log_mask(CPU_LOG_INT
, "%s: %p pending %08x req %08x me %d ee %d\n",
750 __func__
, env
, env
->pending_interrupts
,
751 cs
->interrupt_request
, (int)msr_me
, (int)msr_ee
);
754 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_RESET
)) {
755 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_RESET
);
756 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_RESET
);
759 /* Machine check exception */
760 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_MCK
)) {
761 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_MCK
);
762 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_MCHECK
);
766 /* External debug exception */
767 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DEBUG
)) {
768 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DEBUG
);
769 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_DEBUG
);
774 /* XXX: find a suitable condition to enable the hypervisor mode */
775 hdice
= env
->spr
[SPR_LPCR
] & 1;
779 if ((msr_ee
!= 0 || msr_hv
== 0 || msr_pr
!= 0) && hdice
!= 0) {
780 /* Hypervisor decrementer exception */
781 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_HDECR
)) {
782 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_HDECR
);
787 /* External critical interrupt */
788 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CEXT
)) {
789 /* Taking a critical external interrupt does not clear the external
790 * critical interrupt status
793 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_CEXT
);
795 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_CRITICAL
);
800 /* Watchdog timer on embedded PowerPC */
801 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_WDT
)) {
802 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_WDT
);
803 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_WDT
);
806 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CDOORBELL
)) {
807 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_CDOORBELL
);
808 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_DOORCI
);
811 /* Fixed interval timer on embedded PowerPC */
812 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_FIT
)) {
813 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_FIT
);
814 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_FIT
);
817 /* Programmable interval timer on embedded PowerPC */
818 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_PIT
)) {
819 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_PIT
);
820 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_PIT
);
823 /* Decrementer exception */
824 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DECR
)) {
825 if (ppc_decr_clear_on_delivery(env
)) {
826 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DECR
);
828 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_DECR
);
831 /* External interrupt */
832 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_EXT
)) {
833 /* Taking an external interrupt does not clear the external
837 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_EXT
);
839 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_EXTERNAL
);
842 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DOORBELL
)) {
843 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DOORBELL
);
844 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_DOORI
);
847 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_PERFM
)) {
848 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_PERFM
);
849 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_PERFM
);
852 /* Thermal interrupt */
853 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_THERM
)) {
854 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_THERM
);
855 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_THERM
);
861 void ppc_cpu_do_system_reset(CPUState
*cs
)
863 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
864 CPUPPCState
*env
= &cpu
->env
;
866 powerpc_excp(cpu
, env
->excp_model
, POWERPC_EXCP_RESET
);
868 #endif /* !CONFIG_USER_ONLY */
870 bool ppc_cpu_exec_interrupt(CPUState
*cs
, int interrupt_request
)
872 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
873 CPUPPCState
*env
= &cpu
->env
;
875 if (interrupt_request
& CPU_INTERRUPT_HARD
) {
876 ppc_hw_interrupt(env
);
877 if (env
->pending_interrupts
== 0) {
878 cs
->interrupt_request
&= ~CPU_INTERRUPT_HARD
;
885 #if defined(DEBUG_OP)
886 static void cpu_dump_rfi(target_ulong RA
, target_ulong msr
)
888 qemu_log("Return from exception at " TARGET_FMT_lx
" with flags "
889 TARGET_FMT_lx
"\n", RA
, msr
);
893 /*****************************************************************************/
894 /* Exceptions processing helpers */
896 void helper_raise_exception_err(CPUPPCState
*env
, uint32_t exception
,
899 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
902 printf("Raise exception %3x code : %d\n", exception
, error_code
);
904 cs
->exception_index
= exception
;
905 env
->error_code
= error_code
;
909 void helper_raise_exception(CPUPPCState
*env
, uint32_t exception
)
911 helper_raise_exception_err(env
, exception
, 0);
914 #if !defined(CONFIG_USER_ONLY)
915 void helper_store_msr(CPUPPCState
*env
, target_ulong val
)
919 val
= hreg_store_msr(env
, val
, 0);
921 cs
= CPU(ppc_env_get_cpu(env
));
922 cs
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
923 helper_raise_exception(env
, val
);
927 static inline void do_rfi(CPUPPCState
*env
, target_ulong nip
, target_ulong msr
,
928 target_ulong msrm
, int keep_msrh
)
930 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
932 #if defined(TARGET_PPC64)
933 if (msr_is_64bit(env
, msr
)) {
935 msr
&= (uint64_t)msrm
;
938 msr
= (uint32_t)(msr
& msrm
);
940 msr
|= env
->msr
& ~((uint64_t)0xFFFFFFFF);
945 msr
&= (uint32_t)msrm
;
947 /* XXX: beware: this is false if VLE is supported */
948 env
->nip
= nip
& ~((target_ulong
)0x00000003);
949 hreg_store_msr(env
, msr
, 1);
950 #if defined(DEBUG_OP)
951 cpu_dump_rfi(env
->nip
, env
->msr
);
953 /* No need to raise an exception here,
954 * as rfi is always the last insn of a TB
956 cs
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
959 void helper_rfi(CPUPPCState
*env
)
961 if (env
->excp_model
== POWERPC_EXCP_BOOKE
) {
962 do_rfi(env
, env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
],
963 ~((target_ulong
)0), 0);
965 do_rfi(env
, env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
],
966 ~((target_ulong
)0x783F0000), 1);
970 #if defined(TARGET_PPC64)
971 void helper_rfid(CPUPPCState
*env
)
973 do_rfi(env
, env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
],
974 ~((target_ulong
)0x783F0000), 0);
977 void helper_hrfid(CPUPPCState
*env
)
979 do_rfi(env
, env
->spr
[SPR_HSRR0
], env
->spr
[SPR_HSRR1
],
980 ~((target_ulong
)0x783F0000), 0);
984 /*****************************************************************************/
985 /* Embedded PowerPC specific helpers */
986 void helper_40x_rfci(CPUPPCState
*env
)
988 do_rfi(env
, env
->spr
[SPR_40x_SRR2
], env
->spr
[SPR_40x_SRR3
],
989 ~((target_ulong
)0xFFFF0000), 0);
992 void helper_rfci(CPUPPCState
*env
)
994 do_rfi(env
, env
->spr
[SPR_BOOKE_CSRR0
], env
->spr
[SPR_BOOKE_CSRR1
],
995 ~((target_ulong
)0), 0);
998 void helper_rfdi(CPUPPCState
*env
)
1000 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1001 do_rfi(env
, env
->spr
[SPR_BOOKE_DSRR0
], env
->spr
[SPR_BOOKE_DSRR1
],
1002 ~((target_ulong
)0), 0);
1005 void helper_rfmci(CPUPPCState
*env
)
1007 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1008 do_rfi(env
, env
->spr
[SPR_BOOKE_MCSRR0
], env
->spr
[SPR_BOOKE_MCSRR1
],
1009 ~((target_ulong
)0), 0);
1013 void helper_tw(CPUPPCState
*env
, target_ulong arg1
, target_ulong arg2
,
1016 if (!likely(!(((int32_t)arg1
< (int32_t)arg2
&& (flags
& 0x10)) ||
1017 ((int32_t)arg1
> (int32_t)arg2
&& (flags
& 0x08)) ||
1018 ((int32_t)arg1
== (int32_t)arg2
&& (flags
& 0x04)) ||
1019 ((uint32_t)arg1
< (uint32_t)arg2
&& (flags
& 0x02)) ||
1020 ((uint32_t)arg1
> (uint32_t)arg2
&& (flags
& 0x01))))) {
1021 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
1026 #if defined(TARGET_PPC64)
1027 void helper_td(CPUPPCState
*env
, target_ulong arg1
, target_ulong arg2
,
1030 if (!likely(!(((int64_t)arg1
< (int64_t)arg2
&& (flags
& 0x10)) ||
1031 ((int64_t)arg1
> (int64_t)arg2
&& (flags
& 0x08)) ||
1032 ((int64_t)arg1
== (int64_t)arg2
&& (flags
& 0x04)) ||
1033 ((uint64_t)arg1
< (uint64_t)arg2
&& (flags
& 0x02)) ||
1034 ((uint64_t)arg1
> (uint64_t)arg2
&& (flags
& 0x01))))) {
1035 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
1041 #if !defined(CONFIG_USER_ONLY)
1042 /*****************************************************************************/
1043 /* PowerPC 601 specific instructions (POWER bridge) */
1045 void helper_rfsvc(CPUPPCState
*env
)
1047 do_rfi(env
, env
->lr
, env
->ctr
, 0x0000FFFF, 0);
1050 /* Embedded.Processor Control */
1051 static int dbell2irq(target_ulong rb
)
1053 int msg
= rb
& DBELL_TYPE_MASK
;
1057 case DBELL_TYPE_DBELL
:
1058 irq
= PPC_INTERRUPT_DOORBELL
;
1060 case DBELL_TYPE_DBELL_CRIT
:
1061 irq
= PPC_INTERRUPT_CDOORBELL
;
1063 case DBELL_TYPE_G_DBELL
:
1064 case DBELL_TYPE_G_DBELL_CRIT
:
1065 case DBELL_TYPE_G_DBELL_MC
:
1074 void helper_msgclr(CPUPPCState
*env
, target_ulong rb
)
1076 int irq
= dbell2irq(rb
);
1082 env
->pending_interrupts
&= ~(1 << irq
);
1085 void helper_msgsnd(target_ulong rb
)
1087 int irq
= dbell2irq(rb
);
1088 int pir
= rb
& DBELL_PIRTAG_MASK
;
1096 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1097 CPUPPCState
*cenv
= &cpu
->env
;
1099 if ((rb
& DBELL_BRDCAST
) || (cenv
->spr
[SPR_BOOKE_PIR
] == pir
)) {
1100 cenv
->pending_interrupts
|= 1 << irq
;
1101 cpu_interrupt(cs
, CPU_INTERRUPT_HARD
);