The KVM FWNMI capability should be enabled with the "ibm,nmi-register"
rtas call. Although MCEs from KVM will be delivered as architected
interrupts to the guest before "ibm,nmi-register" is called, KVM has
different behaviour depending on whether the guest has enabled FWNMI
(it attempts to do more recovery on behalf of a non-FWNMI guest).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
hw/ppc/spapr_caps.c | 7 ++++---
hw/ppc/spapr_rtas.c | 7 +++++++
target/ppc/kvm.c | 7 +++++++
target/ppc/kvm_ppc.h | 6 ++++++
4 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 679ae7959f..eb54f94227 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -517,9 +517,10 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
}
if (kvm_enabled()) {
- if (kvmppc_set_fwnmi() < 0) {
- error_setg(errp, "Firmware Assisted Non-Maskable Interrupts(FWNMI) "
- "not supported by KVM");
+ if (!kvmppc_get_fwnmi()) {
+ error_setg(errp,
+"Firmware Assisted Non-Maskable Interrupts(FWNMI) not supported by KVM.");
+ error_append_hint(errp, "Try appending -machine cap-fwnmi=off\n");
}
}
}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 9fb8c8632a..29abe66d01 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -437,6 +437,13 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
return;
}
+ if (kvm_enabled()) {
+ if (kvmppc_set_fwnmi() < 0) {
+ rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
+ return;
+ }
+ }
+
spapr->fwnmi_system_reset_addr = sreset_addr;
spapr->fwnmi_machine_check_addr = mce_addr;
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 597f72be1b..03d0667e8f 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -88,6 +88,7 @@ static int cap_ppc_safe_indirect_branch;
static int cap_ppc_count_cache_flush_assist;
static int cap_ppc_nested_kvm_hv;
static int cap_large_decr;
+static int cap_fwnmi;
static uint32_t debug_inst_opcode;
@@ -136,6 +137,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
kvmppc_get_cpu_characteristics(s);
cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
cap_large_decr = kvmppc_get_dec_bits();
+ cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI);
/*
* Note: setting it to false because there is not such capability
* in KVM at this moment.
@@ -2064,6 +2066,11 @@ void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
}
}
+bool kvmppc_get_fwnmi(void)
+{
+ return cap_fwnmi;
+}
+
int kvmppc_set_fwnmi(void)
{
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 332fa0aa1c..fcaf745516 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -27,6 +27,7 @@ void kvmppc_enable_h_page_init(void);
void kvmppc_set_papr(PowerPCCPU *cpu);
int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
+bool kvmppc_get_fwnmi(void);
int kvmppc_set_fwnmi(void);
int kvmppc_smt_threads(void);
void kvmppc_error_append_smt_possible_hint(Error *const *errp);
@@ -163,6 +164,11 @@ static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
}
+static inline bool kvmppc_get_fwnmi(void)
+{
+ return false;
+}
+
static inline int kvmppc_set_fwnmi(void)
{
return -1;
--
2.23.0
On Thu, 26 Mar 2020 00:29:03 +1000
Nicholas Piggin <npiggin@gmail.com> wrote:
> The KVM FWNMI capability should be enabled with the "ibm,nmi-register"
> rtas call. Although MCEs from KVM will be delivered as architected
> interrupts to the guest before "ibm,nmi-register" is called, KVM has
> different behaviour depending on whether the guest has enabled FWNMI
> (it attempts to do more recovery on behalf of a non-FWNMI guest).
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
Reviewed-by: Greg Kurz <groug@kaod.org>
> hw/ppc/spapr_caps.c | 7 ++++---
> hw/ppc/spapr_rtas.c | 7 +++++++
> target/ppc/kvm.c | 7 +++++++
> target/ppc/kvm_ppc.h | 6 ++++++
> 4 files changed, 24 insertions(+), 3 deletions(-)
>
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 679ae7959f..eb54f94227 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -517,9 +517,10 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
> }
>
> if (kvm_enabled()) {
> - if (kvmppc_set_fwnmi() < 0) {
> - error_setg(errp, "Firmware Assisted Non-Maskable Interrupts(FWNMI) "
> - "not supported by KVM");
> + if (!kvmppc_get_fwnmi()) {
> + error_setg(errp,
> +"Firmware Assisted Non-Maskable Interrupts(FWNMI) not supported by KVM.");
> + error_append_hint(errp, "Try appending -machine cap-fwnmi=off\n");
> }
> }
> }
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index 9fb8c8632a..29abe66d01 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -437,6 +437,13 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
> return;
> }
>
> + if (kvm_enabled()) {
> + if (kvmppc_set_fwnmi() < 0) {
> + rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
> + return;
> + }
> + }
> +
> spapr->fwnmi_system_reset_addr = sreset_addr;
> spapr->fwnmi_machine_check_addr = mce_addr;
>
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index 597f72be1b..03d0667e8f 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -88,6 +88,7 @@ static int cap_ppc_safe_indirect_branch;
> static int cap_ppc_count_cache_flush_assist;
> static int cap_ppc_nested_kvm_hv;
> static int cap_large_decr;
> +static int cap_fwnmi;
>
> static uint32_t debug_inst_opcode;
>
> @@ -136,6 +137,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
> kvmppc_get_cpu_characteristics(s);
> cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
> cap_large_decr = kvmppc_get_dec_bits();
> + cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI);
> /*
> * Note: setting it to false because there is not such capability
> * in KVM at this moment.
> @@ -2064,6 +2066,11 @@ void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
> }
> }
>
> +bool kvmppc_get_fwnmi(void)
> +{
> + return cap_fwnmi;
> +}
> +
> int kvmppc_set_fwnmi(void)
> {
> PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
> index 332fa0aa1c..fcaf745516 100644
> --- a/target/ppc/kvm_ppc.h
> +++ b/target/ppc/kvm_ppc.h
> @@ -27,6 +27,7 @@ void kvmppc_enable_h_page_init(void);
> void kvmppc_set_papr(PowerPCCPU *cpu);
> int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
> void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
> +bool kvmppc_get_fwnmi(void);
> int kvmppc_set_fwnmi(void);
> int kvmppc_smt_threads(void);
> void kvmppc_error_append_smt_possible_hint(Error *const *errp);
> @@ -163,6 +164,11 @@ static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
> {
> }
>
> +static inline bool kvmppc_get_fwnmi(void)
> +{
> + return false;
> +}
> +
> static inline int kvmppc_set_fwnmi(void)
> {
> return -1;
On Thu, Mar 26, 2020 at 12:29:03AM +1000, Nicholas Piggin wrote:
65;5803;1c> The KVM FWNMI capability should be enabled with the "ibm,nmi-register"
> rtas call. Although MCEs from KVM will be delivered as architected
> interrupts to the guest before "ibm,nmi-register" is called, KVM has
> different behaviour depending on whether the guest has enabled FWNMI
> (it attempts to do more recovery on behalf of a non-FWNMI guest).
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Applied to ppc-for-5.0.
> ---
> hw/ppc/spapr_caps.c | 7 ++++---
> hw/ppc/spapr_rtas.c | 7 +++++++
> target/ppc/kvm.c | 7 +++++++
> target/ppc/kvm_ppc.h | 6 ++++++
> 4 files changed, 24 insertions(+), 3 deletions(-)
>
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 679ae7959f..eb54f94227 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -517,9 +517,10 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
> }
>
> if (kvm_enabled()) {
> - if (kvmppc_set_fwnmi() < 0) {
> - error_setg(errp, "Firmware Assisted Non-Maskable Interrupts(FWNMI) "
> - "not supported by KVM");
> + if (!kvmppc_get_fwnmi()) {
> + error_setg(errp,
> +"Firmware Assisted Non-Maskable Interrupts(FWNMI) not supported by KVM.");
> + error_append_hint(errp, "Try appending -machine cap-fwnmi=off\n");
> }
> }
> }
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index 9fb8c8632a..29abe66d01 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -437,6 +437,13 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
> return;
> }
>
> + if (kvm_enabled()) {
> + if (kvmppc_set_fwnmi() < 0) {
> + rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
> + return;
> + }
> + }
> +
> spapr->fwnmi_system_reset_addr = sreset_addr;
> spapr->fwnmi_machine_check_addr = mce_addr;
>
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index 597f72be1b..03d0667e8f 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -88,6 +88,7 @@ static int cap_ppc_safe_indirect_branch;
> static int cap_ppc_count_cache_flush_assist;
> static int cap_ppc_nested_kvm_hv;
> static int cap_large_decr;
> +static int cap_fwnmi;
>
> static uint32_t debug_inst_opcode;
>
> @@ -136,6 +137,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
> kvmppc_get_cpu_characteristics(s);
> cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
> cap_large_decr = kvmppc_get_dec_bits();
> + cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI);
> /*
> * Note: setting it to false because there is not such capability
> * in KVM at this moment.
> @@ -2064,6 +2066,11 @@ void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
> }
> }
>
> +bool kvmppc_get_fwnmi(void)
> +{
> + return cap_fwnmi;
> +}
> +
> int kvmppc_set_fwnmi(void)
> {
> PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
> index 332fa0aa1c..fcaf745516 100644
> --- a/target/ppc/kvm_ppc.h
> +++ b/target/ppc/kvm_ppc.h
> @@ -27,6 +27,7 @@ void kvmppc_enable_h_page_init(void);
> void kvmppc_set_papr(PowerPCCPU *cpu);
> int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
> void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
> +bool kvmppc_get_fwnmi(void);
> int kvmppc_set_fwnmi(void);
> int kvmppc_smt_threads(void);
> void kvmppc_error_append_smt_possible_hint(Error *const *errp);
> @@ -163,6 +164,11 @@ static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
> {
> }
>
> +static inline bool kvmppc_get_fwnmi(void)
> +{
> + return false;
> +}
> +
> static inline int kvmppc_set_fwnmi(void)
> {
> return -1;
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
© 2016 - 2026 Red Hat, Inc.