Message ID | 20161205035647.17406-1-npiggin@gmail.com |
---|---|
State | New |
Headers | show |
On Mon, Dec 05, 2016 at 02:56:47PM +1100, Nicholas Piggin wrote: > 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> This is much too late for qemu-2.8, so can you please rebase this onto my ppc-for-2.9 branch - it doesn't apply clean there. > --- > Hi, > > I have taken into account feedback since last posting, the comments > were appreciated. > > http://lists.nongnu.org/archive/html/qemu-devel/2016-10/msg04881.html > > - Improved changelog description. > - Shared code with QEMU NMI injection. > - Move hcall-specific parameter definitions out of header. > - Added an "unofficial" PAPR specification to changelog. > > There is interest to improve the community process with PAPR > development, but I can't say if/when/how, so this is the best I can do. > > * Some additional background information follows * > > The Linux powerpc branch has a corresponding change to add this hcall > definition: > > https://git.kernel.org/cgit/linux/kernel/git/powerpc/linux.git/commit/?h=next&id=53ce299615e587e900548eb6b384c3081b71bbfa > > The motivation is to allow a crash or debug event to pull stuck > (interrupts disabled) CPUs into the crash/debug handlers. This is in > response to a problem encountered in the wild on a customer machine. > Linux guest patches to that end were posted for review: > > https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-November/150684.html > > Additionally, there is ongoing firmware effort to provide a similar > service for non-virtualized environments: > > https://lists.ozlabs.org/pipermail/skiboot/2016-November/005481.html > > Thanks, > Nick > > hw/ppc/spapr.c | 4 ++-- > hw/ppc/spapr_hcall.c | 41 +++++++++++++++++++++++++++++++++++++++++ > include/hw/ppc/spapr.h | 5 ++++- > 3 files changed, 47 insertions(+), 3 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 208ef7b..5d2adf8 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -2252,7 +2252,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); > @@ -2263,7 +2263,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 9a9bedf..b61ac9d 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 cpu_version; > Error *err; > @@ -1101,6 +1141,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 bd5bcf7..443c425 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. > @@ -662,4 +663,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 */
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 208ef7b..5d2adf8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2252,7 +2252,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); @@ -2263,7 +2263,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 9a9bedf..b61ac9d 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 cpu_version; Error *err; @@ -1101,6 +1141,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 bd5bcf7..443c425 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. @@ -662,4 +663,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 */
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> --- Hi, I have taken into account feedback since last posting, the comments were appreciated. http://lists.nongnu.org/archive/html/qemu-devel/2016-10/msg04881.html - Improved changelog description. - Shared code with QEMU NMI injection. - Move hcall-specific parameter definitions out of header. - Added an "unofficial" PAPR specification to changelog. There is interest to improve the community process with PAPR development, but I can't say if/when/how, so this is the best I can do. * Some additional background information follows * The Linux powerpc branch has a corresponding change to add this hcall definition: https://git.kernel.org/cgit/linux/kernel/git/powerpc/linux.git/commit/?h=next&id=53ce299615e587e900548eb6b384c3081b71bbfa The motivation is to allow a crash or debug event to pull stuck (interrupts disabled) CPUs into the crash/debug handlers. This is in response to a problem encountered in the wild on a customer machine. Linux guest patches to that end were posted for review: https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-November/150684.html Additionally, there is ongoing firmware effort to provide a similar service for non-virtualized environments: https://lists.ozlabs.org/pipermail/skiboot/2016-November/005481.html Thanks, Nick hw/ppc/spapr.c | 4 ++-- hw/ppc/spapr_hcall.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 5 ++++- 3 files changed, 47 insertions(+), 3 deletions(-)