aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr_hcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc/spapr_hcall.c')
-rw-r--r--hw/ppc/spapr_hcall.c41
1 files changed, 41 insertions, 0 deletions
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);