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:
parent
d6e166c082
commit
1c7ad77e56
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user