@@ -9,6 +9,7 @@
#ifndef HW_SPAPR_CPU_CORE_H
#define HW_SPAPR_CPU_CORE_H
+#include "hw/ppc/mce.h"
#include "hw/cpu/core.h"
#include "hw/qdev-core.h"
#include "target/ppc/cpu-qom.h"
@@ -40,6 +41,7 @@ const char *spapr_get_cpu_core_type(const char *cpu_type);
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
target_ulong r1, target_ulong r3,
target_ulong r4);
+void spapr_cpu_inject_mce(CPUState *cs, PPCMceInjectionParams *p);
typedef struct SpaprCpuState {
uint64_t vpa_addr;
@@ -56,6 +56,7 @@
#include "hw/core/cpu.h"
#include "hw/ppc/ppc.h"
+#include "hw/ppc/mce.h"
#include "hw/loader.h"
#include "hw/ppc/fdt.h"
@@ -4522,6 +4523,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc);
+ PPCMceInjectionClass *mcec = PPC_MCE_INJECTION_CLASS(oc);
mc->desc = "pSeries Logical Partition (PAPR compliant)";
mc->ignore_boot_device_suffixes = true;
@@ -4615,6 +4617,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
vmc->client_architecture_support = spapr_vof_client_architecture_support;
vmc->quiesce = spapr_vof_quiesce;
vmc->setprop = spapr_vof_setprop;
+ mcec->inject_mce = spapr_cpu_inject_mce;
}
static const TypeInfo spapr_machine_info = {
@@ -4635,6 +4638,7 @@ static const TypeInfo spapr_machine_info = {
{ TYPE_INTERRUPT_STATS_PROVIDER },
{ TYPE_XIVE_FABRIC },
{ TYPE_VOF_MACHINE_IF },
+ { TYPE_PPC_MCE_INJECTION },
{ }
},
};
@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "hw/cpu/core.h"
+#include "hw/core/cpu.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
@@ -19,12 +20,38 @@
#include "sysemu/kvm.h"
#include "target/ppc/kvm_ppc.h"
#include "hw/ppc/ppc.h"
+#include "hw/ppc/mce.h"
#include "target/ppc/mmu-hash64.h"
#include "sysemu/numa.h"
#include "sysemu/reset.h"
#include "sysemu/hw_accel.h"
#include "qemu/error-report.h"
+static void spapr_cpu_inject_mce_on_cpu(CPUState *cs, run_on_cpu_data data)
+{
+ PPCMceInjectionParams *params = (PPCMceInjectionParams *) data.host_ptr;
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ uint64_t srr1_mce_bits = PPC_BITMASK(42, 45) | PPC_BIT(36);
+
+ cpu_synchronize_state(cs);
+
+ env->spr[SPR_SRR0] = env->nip;
+ env->spr[SPR_SRR1] = (env->msr & ~srr1_mce_bits) |
+ (params->srr1_mask & srr1_mce_bits);
+ if (params->dsisr) {
+ env->spr[SPR_DSISR] = params->dsisr;
+ env->spr[SPR_DAR] = params->dar;
+ }
+
+ spapr_mce_req_event(cpu, params->recovered);
+}
+
+void spapr_cpu_inject_mce(CPUState *cs, PPCMceInjectionParams *p)
+{
+ run_on_cpu(cs, spapr_cpu_inject_mce_on_cpu, RUN_ON_CPU_HOST_PTR(p));
+}
+
static void spapr_reset_vcpu(PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);