@@ -23,6 +23,7 @@
#include "hw/cpu/core.h"
#include "target/ppc/cpu.h"
#include "qom/object.h"
+#include "hw/ppc/mce.h"
#define TYPE_PNV_CORE "powernv-cpu-core"
OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
@@ -70,4 +71,7 @@ struct PnvQuad {
uint32_t quad_id;
MemoryRegion xscom_regs;
};
+
+void pnv_cpu_inject_mce(CPUState *cs, PPCMceInjectionParams *p);
+
#endif /* PPC_PNV_CORE_H */
@@ -1273,6 +1273,7 @@ int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
void ppc_cpu_do_interrupt(CPUState *cpu);
bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void ppc_cpu_do_system_reset(CPUState *cs);
+void ppc_cpu_do_machine_check(CPUState *cs);
void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector);
extern const VMStateDescription vmstate_ppc_cpu;
#endif
@@ -2001,6 +2001,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc);
+ PPCMceInjectionClass *mcec = PPC_MCE_INJECTION_CLASS(oc);
mc->desc = "IBM PowerNV (Non-Virtualized)";
mc->init = pnv_init;
@@ -2018,6 +2019,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
mc->default_ram_id = "pnv.ram";
ispc->print_info = pnv_pic_print_info;
nc->nmi_monitor_handler = pnv_nmi;
+ mcec->inject_mce = pnv_cpu_inject_mce;
object_class_property_add_bool(oc, "hb-mode",
pnv_machine_get_hb, pnv_machine_set_hb);
@@ -2080,6 +2082,7 @@ static const TypeInfo types[] = {
.interfaces = (InterfaceInfo[]) {
{ TYPE_INTERRUPT_STATS_PROVIDER },
{ TYPE_NMI },
+ { TYPE_PPC_MCE_INJECTION },
{ },
},
},
@@ -25,12 +25,39 @@
#include "target/ppc/cpu.h"
#include "hw/ppc/ppc.h"
#include "hw/ppc/pnv.h"
+#include "hw/ppc/mce.h"
#include "hw/ppc/pnv_core.h"
#include "hw/ppc/pnv_xscom.h"
#include "hw/ppc/xics.h"
#include "hw/qdev-properties.h"
#include "helper_regs.h"
+static void pnv_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);
+
+ ppc_cpu_do_machine_check(cs);
+
+ 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;
+ }
+
+ if (!params->recovered) {
+ env->msr &= ~MSR_RI;
+ }
+}
+
+void pnv_cpu_inject_mce(CPUState *cs, PPCMceInjectionParams *p)
+{
+ run_on_cpu(cs, pnv_cpu_inject_mce_on_cpu, RUN_ON_CPU_HOST_PTR(p));
+}
+
static const char *pnv_core_cpu_typename(PnvCore *pc)
{
const char *core_type = object_class_get_name(object_get_class(OBJECT(pc)));
@@ -379,6 +379,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
cs->halted = 1;
cpu_interrupt_exittb(cs);
}
+ if (msr_pow) {
+ /* indicate that we resumed from power save mode */
+ msr |= 0x10000;
+ }
if (env->msr_mask & MSR_HVB) {
/*
* ISA specifies HV, but can be delivered to guest with HV
@@ -1071,6 +1075,14 @@ void ppc_cpu_do_system_reset(CPUState *cs)
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
}
+void ppc_cpu_do_machine_check(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
+}
+
void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);