@@ -291,6 +291,9 @@ bool ppc_cpu_debug_check_breakpoint(CPUState *cs);
bool ppc_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
G_NORETURN void powerpc_checkstop(CPUPPCState *env, const char *reason);
+bool is_prefix_insn_excp(CPUPPCState *env, int excp);
+void ppc_tcg_hv_emu(CPUPPCState *env, target_ulong *new_msr,
+ int *srr0, int *srr1);
#endif
FIELD(GER_MSK, XMSK, 0, 4)
@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qemu/log.h"
+#include "system/kvm.h"
#include "system/tcg.h"
#include "system/system.h"
#include "system/runstate.h"
@@ -1194,81 +1195,6 @@ static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu)
return false;
}
-#ifdef CONFIG_TCG
-static bool is_prefix_insn(CPUPPCState *env, uint32_t insn)
-{
- if (!(env->insns_flags2 & PPC2_ISA310)) {
- return false;
- }
- return ((insn & 0xfc000000) == 0x04000000);
-}
-
-static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
-{
- CPUPPCState *env = &cpu->env;
-
- if (!(env->insns_flags2 & PPC2_ISA310)) {
- return false;
- }
-
- if (!tcg_enabled()) {
- /*
- * This does not load instructions and set the prefix bit correctly
- * for injected interrupts with KVM. That may have to be discovered
- * and set by the KVM layer before injecting.
- */
- return false;
- }
-
- switch (excp) {
- case POWERPC_EXCP_MCHECK:
- if (!(env->error_code & PPC_BIT(42))) {
- /*
- * Fetch attempt caused a machine check, so attempting to fetch
- * again would cause a recursive machine check.
- */
- return false;
- }
- break;
- case POWERPC_EXCP_HDSI:
- /* HDSI PRTABLE_FAULT has the originating access type in error_code */
- if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
- (env->error_code == MMU_INST_FETCH)) {
- /*
- * Fetch failed due to partition scope translation, so prefix
- * indication is not relevant (and attempting to load the
- * instruction at NIP would cause recursive faults with the same
- * translation).
- */
- return false;
- }
- break;
-
- case POWERPC_EXCP_DSI:
- case POWERPC_EXCP_DSEG:
- case POWERPC_EXCP_ALIGN:
- case POWERPC_EXCP_PROGRAM:
- case POWERPC_EXCP_FPU:
- case POWERPC_EXCP_TRACE:
- case POWERPC_EXCP_HV_EMU:
- case POWERPC_EXCP_VPU:
- case POWERPC_EXCP_VSXU:
- case POWERPC_EXCP_FU:
- case POWERPC_EXCP_HV_FU:
- break;
- default:
- return false;
- }
-
- return is_prefix_insn(env, ppc_ldl_code(env, env->nip));
-}
-#else
-static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
-{
- return false;
-}
-#endif
-
static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
@@ -1310,7 +1236,15 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
}
vector |= env->excp_prefix;
- if (is_prefix_insn_excp(cpu, excp)) {
+ if (env->insns_flags2 & PPC2_ISA310) {
+ /* nothing to do */
+ } else if (kvm_enabled()) {
+ /*
+ * This does not load instructions and set the prefix bit correctly
+ * for injected interrupts with KVM. That may have to be discovered
+ * and set by the KVM layer before injecting.
+ */
+ } else if (tcg_enabled() && is_prefix_insn_excp(env, excp)) {
msr |= PPC_BIT(34);
}
@@ -1484,20 +1418,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
break;
#ifdef CONFIG_TCG
- case POWERPC_EXCP_HV_EMU: {
- uint32_t insn = ppc_ldl_code(env, env->nip);
- env->spr[SPR_HEIR] = insn;
- if (is_prefix_insn(env, insn)) {
- uint32_t insn2 = ppc_ldl_code(env, env->nip + 4);
- env->spr[SPR_HEIR] <<= 32;
- env->spr[SPR_HEIR] |= insn2;
- }
- srr0 = SPR_HSRR0;
- srr1 = SPR_HSRR1;
- new_msr |= (target_ulong)MSR_HVB;
- new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
+ case POWERPC_EXCP_HV_EMU:
+ ppc_tcg_hv_emu(env, &new_msr, &srr0, &srr1);
break;
- }
#endif
case POWERPC_EXCP_VPU: /* Vector unavailable exception */
case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
@@ -283,4 +283,75 @@ uint32_t ppc_ldl_code(CPUArchState *env, target_ulong addr)
return insn;
}
+static bool is_prefix_insn(CPUPPCState *env, uint32_t insn)
+{
+ if (!(env->insns_flags2 & PPC2_ISA310)) {
+ return false;
+ }
+ return ((insn & 0xfc000000) == 0x04000000);
+}
+
+bool is_prefix_insn_excp(CPUPPCState *env, int excp)
+{
+ switch (excp) {
+ case POWERPC_EXCP_MCHECK:
+ if (!(env->error_code & PPC_BIT(42))) {
+ /*
+ * Fetch attempt caused a machine check, so attempting to fetch
+ * again would cause a recursive machine check.
+ */
+ return false;
+ }
+ break;
+ case POWERPC_EXCP_HDSI:
+ /* HDSI PRTABLE_FAULT has the originating access type in error_code */
+ if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
+ (env->error_code == MMU_INST_FETCH)) {
+ /*
+ * Fetch failed due to partition scope translation, so prefix
+ * indication is not relevant (and attempting to load the
+ * instruction at NIP would cause recursive faults with the same
+ * translation).
+ */
+ return false;
+ }
+ break;
+
+ case POWERPC_EXCP_DSI:
+ case POWERPC_EXCP_DSEG:
+ case POWERPC_EXCP_ALIGN:
+ case POWERPC_EXCP_PROGRAM:
+ case POWERPC_EXCP_FPU:
+ case POWERPC_EXCP_TRACE:
+ case POWERPC_EXCP_HV_EMU:
+ case POWERPC_EXCP_VPU:
+ case POWERPC_EXCP_VSXU:
+ case POWERPC_EXCP_FU:
+ case POWERPC_EXCP_HV_FU:
+ break;
+ default:
+ return false;
+ }
+
+ return is_prefix_insn(env, ppc_ldl_code(env, env->nip));
+}
+
+void ppc_tcg_hv_emu(CPUPPCState *env, target_ulong *new_msr,
+ int *srr0, int *srr1)
+{
+ uint32_t insn = ppc_ldl_code(env, env->nip);
+
+ env->spr[SPR_HEIR] = insn;
+ if (is_prefix_insn(env, insn)) {
+ uint32_t insn2 = ppc_ldl_code(env, env->nip + 4);
+
+ env->spr[SPR_HEIR] <<= 32;
+ env->spr[SPR_HEIR] |= insn2;
+ }
+ *srr0 = SPR_HSRR0;
+ *srr1 = SPR_HSRR1;
+ *new_msr |= (target_ulong)MSR_HVB;
+ *new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
+}
+
#endif /* !CONFIG_USER_ONLY */
Make is_prefix_insn_excp() prototype but have it guarded by a tcg_enabled() check. Inline part of it in powerpc_excp_books(). Extract POWERPC_EXCP_HV_EMU handling code to ppc_tcg_hv_emu(), also exposing its prototype in "internal.h". Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> --- target/ppc/internal.h | 3 ++ target/ppc/excp_helper.c | 101 +++++------------------------------ target/ppc/tcg-excp_helper.c | 71 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 89 deletions(-)