From: Yanan Wang wangyanan55@huawei.com
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 overridden 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 | 32 ++++++++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic.h | 9 +++++++++ 2 files changed, 41 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index dab599e857b5..1f37ae886f86 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -20,6 +20,32 @@ static bool common_trap; static bool dir_trap; static bool gicv4_enable;
+enum GIC_VERSION global_gic_version = UNKNOWN_GIC_VERSION; + +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); + +static int get_gic_version(char *buffer, const struct kernel_param *kp) +{ + int index = global_gic_version; + const char * const gic_version_str[] = { + "GICv2", + "GICv3", + "GICv4", + "GICv4.1", + "unknown" + }; + + 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 +680,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 +690,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 f78c026c20f0..a9e420eece0c 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -157,6 +157,15 @@ static inline bool vgic_direct_sgi_or_ppi(struct vgic_irq *irq) #endif }
+enum GIC_VERSION { + GICV2, + GICV3, + GICV4, + GICV4_1, + UNKNOWN_GIC_VERSION +}; +extern enum GIC_VERSION global_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