From: Yanan Wang <wangyanan55(a)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(a)huawei.com>
Signed-off-by: Zhiqiang Ni <nizhiqiang1(a)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
--
2.43.0