ppc/spapr: implement H_SIGNAL_SYS_RESET

The H_SIGNAL_SYS_RESET hcall allows a guest CPU to raise a system reset
exception on CPUs within the same guest -- all CPUs, all-but-self, or a
specific CPU (including self).

This has not made its way to a PAPR release yet, but we have an hcall
number assigned.

  H_SIGNAL_SYS_RESET = 0x380

  Syntax:
    hcall(uint64 H_SIGNAL_SYS_RESET, int64 target);

  Generate a system reset NMI on the threads indicated by target.

  Values for target:
    -1 = target all online threads including the caller
    -2 = target all online threads except for the caller
    All other negative values: reserved
    Positive values: The thread to be targeted, obtained from the value
    of the "ibm,ppc-interrupt-server#s" property of the CPU in the OF
    device tree.

  Semantics:
    - Invalid target: return H_Parameter.
    - Otherwise: Generate a system reset NMI on target thread(s),
      return H_Success.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Nicholas Piggin 2016-12-05 16:50:21 +11:00 committed by David Gibson
parent d6e166c082
commit 1c7ad77e56
3 changed files with 47 additions and 3 deletions

View File

@ -2265,7 +2265,7 @@ static void spapr_machine_finalizefn(Object *obj)
g_free(spapr->kvm_type); 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); cpu_synchronize_state(cs);
ppc_cpu_do_system_reset(cs); ppc_cpu_do_system_reset(cs);
@ -2276,7 +2276,7 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
CPUState *cs; CPUState *cs;
CPU_FOREACH(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);
} }
} }

View File

@ -881,6 +881,46 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return ret; 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 { typedef struct {
uint32_t compat_pvr; uint32_t compat_pvr;
Error *err; Error *err;
@ -1097,6 +1137,7 @@ static void hypercall_register_types(void)
/* hcall-splpar */ /* hcall-splpar */
spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa); spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
spapr_register_hypercall(H_CEDE, h_cede); spapr_register_hypercall(H_CEDE, h_cede);
spapr_register_hypercall(H_SIGNAL_SYS_RESET, h_signal_sys_reset);
/* processor register resource access h-calls */ /* processor register resource access h-calls */
spapr_register_hypercall(H_SET_SPRG0, h_set_sprg0); spapr_register_hypercall(H_SET_SPRG0, h_set_sprg0);

View File

@ -347,7 +347,8 @@ struct sPAPRMachineState {
#define H_XIRR_X 0x2FC #define H_XIRR_X 0x2FC
#define H_RANDOM 0x300 #define H_RANDOM 0x300
#define H_SET_MODE 0x31C #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 /* The hcalls above are standardized in PAPR and implemented by pHyp
* as well. * as well.
@ -660,4 +661,6 @@ int spapr_rng_populate_dt(void *fdt);
#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020 #define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
#define SPAPR_LMB_FLAGS_RESERVED 0x00000080 #define SPAPR_LMB_FLAGS_RESERVED 0x00000080
void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
#endif /* HW_SPAPR_H */ #endif /* HW_SPAPR_H */