[PATCH 07/32] KVM: arm64: gic: Introduce interrupt type helpers
Marc Zyngier
maz at kernel.org
Mon Dec 15 08:05:04 PST 2025
On Mon, 15 Dec 2025 13:32:04 +0000,
Marc Zyngier <maz at kernel.org> wrote:
>
> I'd rather you have something that denotes the non-GICv5-ness of the
> implementation. irq_is_nv5_ppi()?
Actually, this is just as bad. I spent the past 30 minutes hacking on
this, and came up with this hack (which compiles, but probably doesn't
run). It is significantly more code, but I like that it treats all GIC
implementations more or less the same way.
It also clears the who [v]gic_is_v5() situation that made little
sense.
Let me know what you think.
M.
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index b0a5a6c6bf8da..c908d5ac4d678 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -62,11 +62,6 @@ static struct irq_ops arch_timer_irq_ops_vgic_v5 = {
.queue_irq_unlock = vgic_v5_ppi_queue_irq_unlock,
};
-static bool vgic_is_v5(struct kvm_vcpu *vcpu)
-{
- return vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V5;
-}
-
static int nr_timers(struct kvm_vcpu *vcpu)
{
if (!vcpu_has_nv(vcpu))
@@ -708,7 +703,7 @@ static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
phys_active |= ctx->irq.level;
- if (!vgic_is_v5(vcpu))
+ if (!vgic_is_v5(vcpu->kvm))
set_timer_irq_phys_active(ctx, phys_active);
else
set_timer_irq_phys_masked(ctx, true);
@@ -760,7 +755,7 @@ static void kvm_timer_vcpu_load_nested_switch(struct kvm_vcpu *vcpu,
if (!irqchip_in_kernel(vcpu->kvm))
return;
- ops = vgic_is_v5(vcpu) ? &arch_timer_irq_ops_vgic_v5 :
+ ops = vgic_is_v5(vcpu->kvm) ? &arch_timer_irq_ops_vgic_v5 :
&arch_timer_irq_ops;
/*
@@ -905,7 +900,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
if (static_branch_likely(&has_gic_active_state)) {
/* We don't do NV on GICv5, yet */
- if (vcpu_has_nv(vcpu) && !vgic_is_v5(vcpu))
+ if (vcpu_has_nv(vcpu) && !vgic_is_v5(vcpu->kvm))
kvm_timer_vcpu_load_nested_switch(vcpu, &map);
kvm_timer_vcpu_load_gic(map.direct_vtimer);
@@ -977,7 +972,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
kvm_timer_blocking(vcpu);
/* Unmask again on GICV5 */
- if (vgic_is_v5(vcpu)) {
+ if (vgic_is_v5(vcpu->kvm)) {
set_timer_irq_phys_masked(map.direct_vtimer, false);
if (map.direct_ptimer)
@@ -1623,7 +1618,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
return -EINVAL;
}
- ops = vgic_is_v5(vcpu) ? &arch_timer_irq_ops_vgic_v5 :
+ ops = vgic_is_v5(vcpu->kvm) ? &arch_timer_irq_ops_vgic_v5 :
&arch_timer_irq_ops;
get_timer_map(vcpu, &map);
@@ -1700,7 +1695,7 @@ int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
* The PPIs for the Arch Timers arch architecturally defined for
* GICv5. Reject anything that changes them from the specified value.
*/
- if (vgic_is_v5(vcpu) && vcpu->kvm->arch.timer_data.ppi[idx] != irq) {
+ if (vgic_is_v5(vcpu->kvm) && vcpu->kvm->arch.timer_data.ppi[idx] != irq) {
ret = -EINVAL;
goto out;
}
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index d74cc3543b9a4..19d8bf90f8f6c 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -225,7 +225,7 @@ bool vgic_v5_ppi_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
lockdep_assert_held(&irq->irq_lock);
- if (WARN_ON_ONCE(!irq_is_ppi_v5(irq->intid)))
+ if (WARN_ON_ONCE(!__irq_is_ppi(KVM_DEV_TYPE_ARM_VGIC_V5, irq->intid)))
return false;
vcpu = irq->target_vcpu;
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 62d7d4c5650e4..6d8e4cd661734 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -109,10 +109,10 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
if (WARN_ON(!vcpu))
return NULL;
- if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V5) {
+ if (vgic_is_v5(vcpu->kvm)) {
u32 int_num = FIELD_GET(GICV5_HWIRQ_ID, intid);
- if (irq_is_ppi_v5(intid)) {
+ if (__irq_is_ppi(KVM_DEV_TYPE_ARM_VGIC_V5, intid)) {
int_num = array_index_nospec(int_num, VGIC_V5_NR_PRIVATE_IRQS);
return &vcpu->arch.vgic_cpu.private_irqs[int_num];
}
@@ -600,15 +600,13 @@ static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
irq->hwintid = data->hwirq;
irq->ops = ops;
- if (vgic_is_v5(vcpu->kvm)) {
- /* Nothing for us to do */
- if (!irq_is_ppi_v5(irq->intid))
- return 0;
+ if (vgic_is_v5(vcpu->kvm) &&
+ !__irq_is_ppi(KVM_DEV_TYPE_ARM_VGIC_V5, irq->intid))
+ return 0;
- if (FIELD_GET(GICV5_HWIRQ_ID, irq->intid) == irq->hwintid) {
- if (!vgic_v5_set_ppi_dvi(vcpu, irq->hwintid, true))
- irq->directly_injected = true;
- }
+ if (FIELD_GET(GICV5_HWIRQ_ID, irq->intid) == irq->hwintid) {
+ if (!vgic_v5_set_ppi_dvi(vcpu, irq->hwintid, true))
+ irq->directly_injected = true;
}
return 0;
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 91969b3b80d04..d8a947a7eb941 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -500,11 +500,6 @@ static inline bool vgic_is_v3(struct kvm *kvm)
return kvm_vgic_global_state.type == VGIC_V3 || vgic_is_v3_compat(kvm);
}
-static inline bool vgic_is_v5(struct kvm *kvm)
-{
- return kvm_vgic_global_state.type == VGIC_V5 && !vgic_is_v3_compat(kvm);
-}
-
bool system_supports_direct_sgis(void);
bool vgic_supports_direct_msis(struct kvm *kvm);
bool vgic_supports_direct_sgis(struct kvm *kvm);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 6863e19d6eeb7..ae2897c539af7 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -36,22 +36,78 @@
/* GICv5 constants */
#define VGIC_V5_NR_PRIVATE_IRQS 128
-#define irq_is_ppi_legacy(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
-#define irq_is_spi_legacy(irq) ((irq) >= VGIC_NR_PRIVATE_IRQS && \
- (irq) <= VGIC_MAX_SPI)
-#define irq_is_lpi_legacy(irq) ((irq) > VGIC_MAX_SPI)
-
-#define irq_is_ppi_v5(irq) (FIELD_GET(GICV5_HWIRQ_TYPE, irq) == GICV5_HWIRQ_TYPE_PPI)
-#define irq_is_spi_v5(irq) (FIELD_GET(GICV5_HWIRQ_TYPE, irq) == GICV5_HWIRQ_TYPE_SPI)
-#define irq_is_lpi_v5(irq) (FIELD_GET(GICV5_HWIRQ_TYPE, irq) == GICV5_HWIRQ_TYPE_LPI)
-
-#define gic_is_v5(k) ((k)->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V5)
-
-#define irq_is_ppi(k, i) (gic_is_v5(k) ? irq_is_ppi_v5(i) : irq_is_ppi_legacy(i))
-#define irq_is_spi(k, i) (gic_is_v5(k) ? irq_is_spi_v5(i) : irq_is_spi_legacy(i))
-#define irq_is_lpi(k, i) (gic_is_v5(k) ? irq_is_lpi_v5(i) : irq_is_lpi_legacy(i))
-
-#define irq_is_private(k, i) (gic_is_v5(k) ? irq_is_ppi_v5(i) : i < VGIC_NR_PRIVATE_IRQS)
+#define is_v5_type(t, i) (FIELD_GET(GICV5_HWIRQ_TYPE, (i)) == (t))
+
+#define __irq_is_sgi(t, i) \
+ ({ \
+ bool __ret; \
+ \
+ switch (t) { \
+ case KVM_DEV_TYPE_ARM_VGIC_V5: \
+ __ret = false; \
+ break; \
+ default: \
+ __ret = (i) < VGIC_NR_SGIS; \
+ } \
+ \
+ __ret; \
+ })
+
+#define __irq_is_ppi(t, i) \
+ ({ \
+ bool __ret; \
+ \
+ switch (t) { \
+ case KVM_DEV_TYPE_ARM_VGIC_V5: \
+ __ret = is_v5_type(GICV5_HWIRQ_TYPE_PPI, (i)); \
+ break; \
+ default: \
+ __ret = (i) >= VGIC_NR_SGIS; \
+ __ret &= (i) < VGIC_NR_PRIVATE_IRQS; \
+ } \
+ \
+ __ret; \
+ })
+
+#define __irq_is_spi(t, i) \
+ ({ \
+ bool __ret; \
+ \
+ switch (t) { \
+ case KVM_DEV_TYPE_ARM_VGIC_V5: \
+ __ret = is_v5_type(GICV5_HWIRQ_TYPE_SPI, (i)); \
+ break; \
+ default: \
+ __ret = (i) <= VGIC_MAX_SPI; \
+ __ret &= (i) >= VGIC_NR_PRIVATE_IRQS; \
+ } \
+ \
+ __ret; \
+ })
+
+#define __irq_is_lpi(t, i) \
+ ({ \
+ bool __ret; \
+ \
+ switch (t) { \
+ case KVM_DEV_TYPE_ARM_VGIC_V5: \
+ __ret = is_v5_type(GICV5_HWIRQ_TYPE_LPI, (i)); \
+ break; \
+ default: \
+ __ret = (i) >= 8192; \
+ } \
+ \
+ __ret; \
+ })
+
+#define irq_is_sgi(k, i) __irq_is_sgi((k)->arch.vgic.vgic_model, i)
+#define irq_is_ppi(k, i) __irq_is_ppi((k)->arch.vgic.vgic_model, i)
+#define irq_is_spi(k, i) __irq_is_spi((k)->arch.vgic.vgic_model, i)
+#define irq_is_lpi(k, i) __irq_is_lpi((k)->arch.vgic.vgic_model, i)
+
+#define irq_is_private(k, i) (irq_is_ppi(k, i) || irq_is_sgi(k, i))
+
+#define vgic_is_v5(k) ((k)->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V5)
enum vgic_type {
VGIC_V2, /* Good ol' GICv2 */
--
Without deviation from the norm, progress is not possible.
More information about the linux-arm-kernel
mailing list