summaryrefslogtreecommitdiff
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorSascha Bischoff <Sascha.Bischoff@arm.com>2025-06-27 10:09:01 +0000
committerOliver Upton <oliver.upton@linux.dev>2025-07-08 14:41:06 -0700
commit1ec38ce3d024bebdff2a9ffb526e4d198605204d (patch)
treed9170d0ea87cf5d07a2e3c7cff858b1ed6db0b4b /drivers/irqchip
parent244e9a89ca765cc2395fc7a83833fb79731299fc (diff)
irqchip/gic-v5: Populate struct gic_kvm_info
Populate the gic_kvm_info struct based on support for FEAT_GCIE_LEGACY. The struct is used by KVM to probe for a compatible GIC. Co-authored-by: Timothy Hayes <timothy.hayes@arm.com> Signed-off-by: Timothy Hayes <timothy.hayes@arm.com> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org> Link: https://lore.kernel.org/r/20250627100847.1022515-3-sascha.bischoff@arm.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic-v5.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index 0e4789818131..4bd224f359a7 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -13,6 +13,7 @@
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-v5.h>
+#include <linux/irqchip/arm-vgic-info.h>
#include <asm/cpufeature.h>
#include <asm/exception.h>
@@ -1058,6 +1059,36 @@ static void gicv5_set_cpuif_idbits(void)
}
}
+#ifdef CONFIG_KVM
+static struct gic_kvm_info gic_v5_kvm_info __initdata;
+
+static bool __init gicv5_cpuif_has_gcie_legacy(void)
+{
+ u64 idr0 = read_sysreg_s(SYS_ICC_IDR0_EL1);
+ return !!FIELD_GET(ICC_IDR0_EL1_GCIE_LEGACY, idr0);
+}
+
+static void __init gic_of_setup_kvm_info(struct device_node *node)
+{
+ gic_v5_kvm_info.type = GIC_V5;
+ gic_v5_kvm_info.has_gcie_v3_compat = gicv5_cpuif_has_gcie_legacy();
+
+ /* GIC Virtual CPU interface maintenance interrupt */
+ gic_v5_kvm_info.no_maint_irq_mask = false;
+ gic_v5_kvm_info.maint_irq = irq_of_parse_and_map(node, 0);
+ if (!gic_v5_kvm_info.maint_irq) {
+ pr_warn("cannot find GICv5 virtual CPU interface maintenance interrupt\n");
+ return;
+ }
+
+ vgic_set_kvm_info(&gic_v5_kvm_info);
+}
+#else
+static inline void __init gic_of_setup_kvm_info(struct device_node *node)
+{
+}
+#endif // CONFIG_KVM
+
static int __init gicv5_of_init(struct device_node *node, struct device_node *parent)
{
int ret = gicv5_irs_of_probe(node);
@@ -1090,6 +1121,8 @@ static int __init gicv5_of_init(struct device_node *node, struct device_node *pa
gicv5_irs_its_probe();
+ gic_of_setup_kvm_info(node);
+
return 0;
out_int: