diff mbox series

[2/3] ppc/spapr: Implement mce injection

Message ID 20211013214042.618918-3-clg@kaod.org
State New
Headers show
Series ppc: Add QOM interface for machine check injection | expand

Commit Message

Cédric Le Goater Oct. 13, 2021, 9:40 p.m. UTC
From: Nicholas Piggin <npiggin@gmail.com>

This implements mce injection for spapr.

  (qemu) mce 0 0x200000 0x80 0xdeadbeef 1

    Disabling lock debugging due to kernel taint
    MCE: CPU0: machine check (Severe) Host SLB Multihit DAR: 00000000deadbeef [Recovered]
    MCE: CPU0: machine check (Severe) Host SLB Multihit [Recovered]
    MCE: CPU0: PID: 495 Comm: a NIP: [0000000130ee07c8]
    MCE: CPU0: Initiator CPU
    MCE: CPU0: Unknown
[   71.567193] MCE: CPU0: NIP: [c0000000000d7f6c] plpar_hcall_norets+0x1c/0x28
[   71.567249] MCE: CPU0: Initiator CPU
[   71.567308] MCE: CPU0: Unknown

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[ clg: - simplified injection and moved code under spapr_cpu_core.c ]
Message-Id: <20200325144147.221875-5-npiggin@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 include/hw/ppc/spapr_cpu_core.h |  2 ++
 hw/ppc/spapr.c                  |  4 ++++
 hw/ppc/spapr_cpu_core.c         | 27 +++++++++++++++++++++++++++
 3 files changed, 33 insertions(+)
diff mbox series

Patch

diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index dab3dfc76c0a..6734c7a89640 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -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;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 087449f93871..c4ff63a79313 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -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 },
         { }
     },
 };
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 58e7341cb784..360efc16b1d6 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -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);