From: Marc Zyngier maz@kernel.org
virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I97WGU
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/commit...
-----------------------------------------------------------
Let the GICv3 driver populate a has_nmi flag in the kvm_gic_info structure, and communicate it to the rest of KVM.
We disallow the use of NMI if trapping of the CPU interface is enabled, because life is definitely too short to write more emulation.
Signed-off-by: Marc Zyngier maz@kernel.org Signed-off-by: Xiang Chen chenxiang66@hisilicon.com Signed-off-by: caijian caijian11@h-partners.com --- arch/arm64/kvm/arm.c | 2 +- arch/arm64/kvm/sys_regs.c | 3 ++- arch/arm64/kvm/vgic/vgic-v3.c | 6 ++++++ drivers/irqchip/irq-gic-v3.c | 1 + include/linux/irqchip/arm-vgic-info.h | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index cdfdd08f4c10..9c6b4accb10b 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -192,7 +192,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) /* The maximum number of VCPUs is limited by the host's GIC model */ kvm->max_vcpus = kvm_arm_default_max_vcpus();
- if (system_uses_nmi()) + if (system_uses_nmi() && !static_branch_unlikely(&vgic_v3_cpuif_trap)) kvm->arch.pfr1_nmi = ID_AA64PFR1_EL1_NMI_IMP;
kvm_arm_init_hypercalls(kvm); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 5a6e64670feb..c92fd3aac0ba 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1580,7 +1580,8 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, u8 nmi;
nmi = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR1_EL1_NMI_SHIFT); - if (nmi > ID_AA64PFR1_EL1_NMI_IMP || (nmi && !system_uses_nmi())) + if (nmi > ID_AA64PFR1_EL1_NMI_IMP || + (nmi && (!system_uses_nmi() || static_branch_unlikely(&vgic_v3_cpuif_trap)))) return -EINVAL;
/* We can only differ with NMI, and anything else is an error */ diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index e82402dada77..69ca111e349d 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -724,6 +724,12 @@ int vgic_v3_probe(const struct gic_kvm_info *info) static_branch_enable(&vgic_v3_cpuif_trap); }
+ if (info->has_nmi) { + kvm_vgic_global_state.has_nmi = !static_branch_unlikely(&vgic_v3_cpuif_trap); + kvm_info("GICv3 NMI support %s\n", + kvm_vgic_global_state.has_nmi ? "enabled" : "disabled due to trapping"); + } + kvm_vgic_global_state.vctrl_base = NULL; kvm_vgic_global_state.type = VGIC_V3; kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index a9fda74a198f..7785faa6c7f7 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -2681,6 +2681,7 @@ static void __init gic_acpi_setup_kvm_info(void)
gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis; gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid; + gic_v3_kvm_info.has_nmi = has_v3_3_nmi(); #ifdef CONFIG_VIRT_VTIMER_IRQ_BYPASS gic_v3_kvm_info.has_vtimer = gic_data.rdists.has_vtimer; #endif diff --git a/include/linux/irqchip/arm-vgic-info.h b/include/linux/irqchip/arm-vgic-info.h index ac362587d2fb..aa2e9eaa9ad9 100644 --- a/include/linux/irqchip/arm-vgic-info.h +++ b/include/linux/irqchip/arm-vgic-info.h @@ -32,6 +32,8 @@ struct gic_kvm_info { bool has_v4; /* rvpeid support */ bool has_v4_1; + /* NMI support */ + bool has_nmi; #ifdef CONFIG_VIRT_VTIMER_IRQ_BYPASS /* vtimer irqbypass support */ bool has_vtimer;