From: Yanan Wang wangyanan55@huawei.com
virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAR5EZ CVE: NA
Using GICv4.1 is not a 100% win in all scenarios, sometimes we need to use different GIC version in different usecases. Given that there is not a straight forward way to check the GIC version that system is using (e.g., kernel messages may be overided with time elapses), let's add a module param in KVM such that userspace can check the GIC version simply by reading /sys/module/kvm/parameters/gic_version.
Signed-off-by: Yanan Wang wangyanan55@huawei.com Signed-off-by: Zhiqiang Ni nizhiqiang1@huawei.com --- arch/arm64/kvm/vgic/vgic-v3.c | 37 +++++++++++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic.h | 8 ++++++++ 2 files changed, 45 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index dab599e857b5..227fa1874c3b 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -20,6 +20,37 @@ static bool common_trap; static bool dir_trap; static bool gicv4_enable;
+enum gic_version global_gic_version = UNKNOWN_GIC_VERSION; +static const char * const gic_version_str[] = { + "GICv2", + "GICv3", + "GICv4", + "GICv4.1", + "unknown" +}; + +static int get_gic_version(char *buffer, const struct kernel_param *kp); +static const struct kernel_param_ops gic_version_ops = { + .get = get_gic_version, +}; + +static const char *gic_version; +module_param_cb(gic_version, &gic_version_ops, &gic_version, 0444); +MODULE_PARM_DESC(gic_version, "Version of current enabled GIC"); + +static int get_gic_version(char *buffer, const struct kernel_param *kp) +{ + int index = global_gic_version; + + if (index < 0 || index >= ARRAY_SIZE(gic_version_str)) { + kvm_err("Invalid GIC version enum %d\n", index); + return -EINVAL; + } + gic_version = gic_version_str[index]; + + return param_get_charp(buffer, kp); +} + void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) { struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3; @@ -654,6 +685,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info) kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1; kvm_vgic_global_state.can_emulate_gicv2 = false; kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2; + global_gic_version = GICV3;
/* GICv4 support? */ if (info->has_v4) { @@ -663,6 +695,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info) kvm_vgic_global_state.has_gicv4_1 ? ".1" : "", gicv4_enable ? "en" : "dis");
+ if (kvm_vgic_global_state.has_gicv4_1) + global_gic_version = GICV4_1; + else if (kvm_vgic_global_state.has_gicv4) + global_gic_version = GICV4; + #ifdef CONFIG_VIRT_VTIMER_IRQ_BYPASS kvm_vgic_global_state.has_direct_vtimer = info->has_vtimer && gicv4_enable; if (kvm_vgic_global_state.has_direct_vtimer) diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 5135c690839e..539909a681d7 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -157,6 +157,14 @@ static inline bool vgic_direct_sgi_or_ppi(struct vgic_irq *irq) #endif }
+enum gic_version { + GICV2, + GICV3, + GICV4, + GICV4_1, + UNKNOWN_GIC_VERSION +}; + /* * This struct provides an intermediate representation of the fields contained * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC