summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hw/ppc/spapr.c4
-rw-r--r--hw/ppc/spapr_hcall.c41
-rw-r--r--include/hw/ppc/spapr.h5
3 files changed, 47 insertions, 3 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cd95435c2f..74419f82f0 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2265,7 +2265,7 @@ static void spapr_machine_finalizefn(Object *obj)
g_free(spapr->kvm_type);
}
-static void ppc_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
+void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg)
{
cpu_synchronize_state(cs);
ppc_cpu_do_system_reset(cs);
@@ -2276,7 +2276,7 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
CPUState *cs;
CPU_FOREACH(cs) {
- async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
+ async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL);
}
}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 4fbcb038ed..51681f3dbe 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -881,6 +881,46 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return ret;
}
+#define H_SIGNAL_SYS_RESET_ALL -1
+#define H_SIGNAL_SYS_RESET_ALLBUTSELF -2
+
+static target_ulong h_signal_sys_reset(PowerPCCPU *cpu,
+ sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ target_long target = args[0];
+ CPUState *cs;
+
+ if (target < 0) {
+ /* Broadcast */
+ if (target < H_SIGNAL_SYS_RESET_ALLBUTSELF) {
+ return H_PARAMETER;
+ }
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *c = POWERPC_CPU(cs);
+
+ if (target == H_SIGNAL_SYS_RESET_ALLBUTSELF) {
+ if (c == cpu) {
+ continue;
+ }
+ }
+ run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL);
+ }
+ return H_SUCCESS;
+
+ } else {
+ /* Unicast */
+ CPU_FOREACH(cs) {
+ if (cpu->cpu_dt_id == target) {
+ run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL);
+ return H_SUCCESS;
+ }
+ }
+ return H_PARAMETER;
+ }
+}
+
typedef struct {
uint32_t compat_pvr;
Error *err;
@@ -1097,6 +1137,7 @@ static void hypercall_register_types(void)
/* hcall-splpar */
spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
spapr_register_hypercall(H_CEDE, h_cede);
+ spapr_register_hypercall(H_SIGNAL_SYS_RESET, h_signal_sys_reset);
/* processor register resource access h-calls */
spapr_register_hypercall(H_SET_SPRG0, h_set_sprg0);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 04d282110d..a2d8964f7e 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -347,7 +347,8 @@ struct sPAPRMachineState {
#define H_XIRR_X 0x2FC
#define H_RANDOM 0x300
#define H_SET_MODE 0x31C
-#define MAX_HCALL_OPCODE H_SET_MODE
+#define H_SIGNAL_SYS_RESET 0x380
+#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET
/* The hcalls above are standardized in PAPR and implemented by pHyp
* as well.
@@ -660,4 +661,6 @@ int spapr_rng_populate_dt(void *fdt);
#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
#define SPAPR_LMB_FLAGS_RESERVED 0x00000080
+void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
+
#endif /* HW_SPAPR_H */