Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: gic: Introduce interrupt type helpers

GICv5 has moved from using interrupt ranges for different interrupt
types to using some of the upper bits of the interrupt ID to denote
the interrupt type. This is not compatible with older GICs (which rely
on ranges of interrupts to determine the type), and hence a set of
helpers is introduced. These helpers take a struct kvm*, and use the
vgic model to determine how to interpret the interrupt ID.

Helpers are introduced for PPIs, SPIs, and LPIs. Additionally, a
helper is introduced to determine if an interrupt is private - SGIs
and PPIs for older GICs, and PPIs only for GICv5.

Additionally, vgic_is_v5() is introduced (which unsurpisingly returns
true when running a GICv5 guest), and the existing vgic_is_v3() check
is moved from vgic.h to arm_vgic.h (to live alongside the vgic_is_v5()
one), and has been converted into a macro.

The helpers are plumbed into the core vgic code, as well as the Arch
Timer and PMU code.

There should be no functional changes as part of this change.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20260319154937.3619520-10-sascha.bischoff@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Sascha Bischoff and committed by
Marc Zyngier
eb8bce08 c547c51f

+110 -22
+1 -1
arch/arm64/kvm/arch_timer.c
··· 1603 1603 if (get_user(irq, uaddr)) 1604 1604 return -EFAULT; 1605 1605 1606 - if (!(irq_is_ppi(irq))) 1606 + if (!(irq_is_ppi(vcpu->kvm, irq))) 1607 1607 return -EINVAL; 1608 1608 1609 1609 mutex_lock(&vcpu->kvm->arch.config_lock);
+4 -3
arch/arm64/kvm/pmu-emul.c
··· 939 939 * number against the dimensions of the vgic and make sure 940 940 * it's valid. 941 941 */ 942 - if (!irq_is_ppi(irq) && !vgic_valid_spi(vcpu->kvm, irq)) 942 + if (!irq_is_ppi(vcpu->kvm, irq) && 943 + !vgic_valid_spi(vcpu->kvm, irq)) 943 944 return -EINVAL; 944 945 } else if (kvm_arm_pmu_irq_initialized(vcpu)) { 945 946 return -EINVAL; ··· 992 991 if (!kvm_arm_pmu_irq_initialized(vcpu)) 993 992 continue; 994 993 995 - if (irq_is_ppi(irq)) { 994 + if (irq_is_ppi(vcpu->kvm, irq)) { 996 995 if (vcpu->arch.pmu.irq_num != irq) 997 996 return false; 998 997 } else { ··· 1143 1142 return -EFAULT; 1144 1143 1145 1144 /* The PMU overflow interrupt can be a PPI or a valid SPI. */ 1146 - if (!(irq_is_ppi(irq) || irq_is_spi(irq))) 1145 + if (!(irq_is_ppi(vcpu->kvm, irq) || irq_is_spi(vcpu->kvm, irq))) 1147 1146 return -EINVAL; 1148 1147 1149 1148 if (!pmu_irq_is_valid(kvm, irq))
+1 -1
arch/arm64/kvm/vgic/vgic-kvm-device.c
··· 639 639 if (vgic_initialized(dev->kvm)) 640 640 return -EBUSY; 641 641 642 - if (!irq_is_ppi(val)) 642 + if (!irq_is_ppi(dev->kvm, val)) 643 643 return -EINVAL; 644 644 645 645 dev->kvm->arch.vgic.mi_intid = val;
+7 -7
arch/arm64/kvm/vgic/vgic.c
··· 94 94 } 95 95 96 96 /* LPIs */ 97 - if (intid >= VGIC_MIN_LPI) 97 + if (irq_is_lpi(kvm, intid)) 98 98 return vgic_get_lpi(kvm, intid); 99 99 100 100 return NULL; ··· 123 123 124 124 static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) 125 125 { 126 - if (irq->intid < VGIC_MIN_LPI) 126 + if (!irq_is_lpi(kvm, irq->intid)) 127 127 return false; 128 128 129 129 return refcount_dec_and_test(&irq->refcount); ··· 148 148 * Acquire/release it early on lockdep kernels to make locking issues 149 149 * in rare release paths a bit more obvious. 150 150 */ 151 - if (IS_ENABLED(CONFIG_LOCKDEP) && irq->intid >= VGIC_MIN_LPI) { 151 + if (IS_ENABLED(CONFIG_LOCKDEP) && irq_is_lpi(kvm, irq->intid)) { 152 152 guard(spinlock_irqsave)(&dist->lpi_xa.xa_lock); 153 153 } 154 154 ··· 186 186 raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags); 187 187 188 188 list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) { 189 - if (irq->intid >= VGIC_MIN_LPI) { 189 + if (irq_is_lpi(vcpu->kvm, irq->intid)) { 190 190 raw_spin_lock(&irq->irq_lock); 191 191 list_del(&irq->ap_list); 192 192 irq->vcpu = NULL; ··· 521 521 if (ret) 522 522 return ret; 523 523 524 - if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS) 524 + if (!vcpu && irq_is_private(kvm, intid)) 525 525 return -EINVAL; 526 526 527 527 trace_vgic_update_irq_pending(vcpu ? vcpu->vcpu_idx : 0, intid, level); 528 528 529 - if (intid < VGIC_NR_PRIVATE_IRQS) 529 + if (irq_is_private(kvm, intid)) 530 530 irq = vgic_get_vcpu_irq(vcpu, intid); 531 531 else 532 532 irq = vgic_get_irq(kvm, intid); ··· 700 700 return -EAGAIN; 701 701 702 702 /* SGIs and LPIs cannot be wired up to any device */ 703 - if (!irq_is_ppi(intid) && !vgic_valid_spi(vcpu->kvm, intid)) 703 + if (!irq_is_ppi(vcpu->kvm, intid) && !vgic_valid_spi(vcpu->kvm, intid)) 704 704 return -EINVAL; 705 705 706 706 irq = vgic_get_vcpu_irq(vcpu, intid);
-5
arch/arm64/kvm/vgic/vgic.h
··· 454 454 void vgic_v3_handle_nested_maint_irq(struct kvm_vcpu *vcpu); 455 455 void vgic_v3_nested_update_mi(struct kvm_vcpu *vcpu); 456 456 457 - static inline bool vgic_is_v3(struct kvm *kvm) 458 - { 459 - return kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3; 460 - } 461 - 462 457 static inline bool vgic_host_has_gicv3(void) 463 458 { 464 459 /*
+97 -5
include/kvm/arm_vgic.h
··· 19 19 #include <linux/jump_label.h> 20 20 21 21 #include <linux/irqchip/arm-gic-v4.h> 22 + #include <linux/irqchip/arm-gic-v5.h> 22 23 23 24 #define VGIC_V3_MAX_CPUS 512 24 25 #define VGIC_V2_MAX_CPUS 8 ··· 32 31 #define VGIC_MIN_LPI 8192 33 32 #define KVM_IRQCHIP_NUM_PINS (1020 - 32) 34 33 35 - #define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS) 36 - #define irq_is_spi(irq) ((irq) >= VGIC_NR_PRIVATE_IRQS && \ 37 - (irq) <= VGIC_MAX_SPI) 34 + #define is_v5_type(t, i) (FIELD_GET(GICV5_HWIRQ_TYPE, (i)) == (t)) 35 + 36 + #define __irq_is_sgi(t, i) \ 37 + ({ \ 38 + bool __ret; \ 39 + \ 40 + switch (t) { \ 41 + case KVM_DEV_TYPE_ARM_VGIC_V5: \ 42 + __ret = false; \ 43 + break; \ 44 + default: \ 45 + __ret = (i) < VGIC_NR_SGIS; \ 46 + } \ 47 + \ 48 + __ret; \ 49 + }) 50 + 51 + #define __irq_is_ppi(t, i) \ 52 + ({ \ 53 + bool __ret; \ 54 + \ 55 + switch (t) { \ 56 + case KVM_DEV_TYPE_ARM_VGIC_V5: \ 57 + __ret = is_v5_type(GICV5_HWIRQ_TYPE_PPI, (i)); \ 58 + break; \ 59 + default: \ 60 + __ret = (i) >= VGIC_NR_SGIS; \ 61 + __ret &= (i) < VGIC_NR_PRIVATE_IRQS; \ 62 + } \ 63 + \ 64 + __ret; \ 65 + }) 66 + 67 + #define __irq_is_spi(t, i) \ 68 + ({ \ 69 + bool __ret; \ 70 + \ 71 + switch (t) { \ 72 + case KVM_DEV_TYPE_ARM_VGIC_V5: \ 73 + __ret = is_v5_type(GICV5_HWIRQ_TYPE_SPI, (i)); \ 74 + break; \ 75 + default: \ 76 + __ret = (i) <= VGIC_MAX_SPI; \ 77 + __ret &= (i) >= VGIC_NR_PRIVATE_IRQS; \ 78 + } \ 79 + \ 80 + __ret; \ 81 + }) 82 + 83 + #define __irq_is_lpi(t, i) \ 84 + ({ \ 85 + bool __ret; \ 86 + \ 87 + switch (t) { \ 88 + case KVM_DEV_TYPE_ARM_VGIC_V5: \ 89 + __ret = is_v5_type(GICV5_HWIRQ_TYPE_LPI, (i)); \ 90 + break; \ 91 + default: \ 92 + __ret = (i) >= 8192; \ 93 + } \ 94 + \ 95 + __ret; \ 96 + }) 97 + 98 + #define irq_is_sgi(k, i) __irq_is_sgi((k)->arch.vgic.vgic_model, i) 99 + #define irq_is_ppi(k, i) __irq_is_ppi((k)->arch.vgic.vgic_model, i) 100 + #define irq_is_spi(k, i) __irq_is_spi((k)->arch.vgic.vgic_model, i) 101 + #define irq_is_lpi(k, i) __irq_is_lpi((k)->arch.vgic.vgic_model, i) 102 + 103 + #define irq_is_private(k, i) (irq_is_ppi(k, i) || irq_is_sgi(k, i)) 104 + 105 + #define vgic_v5_get_hwirq_id(x) FIELD_GET(GICV5_HWIRQ_ID, (x)) 106 + #define vgic_v5_set_hwirq_id(x) FIELD_PREP(GICV5_HWIRQ_ID, (x)) 107 + 108 + #define __vgic_v5_set_type(t) (FIELD_PREP(GICV5_HWIRQ_TYPE, GICV5_HWIRQ_TYPE_##t)) 109 + #define vgic_v5_make_ppi(x) (__vgic_v5_set_type(PPI) | vgic_v5_set_hwirq_id(x)) 110 + #define vgic_v5_make_spi(x) (__vgic_v5_set_type(SPI) | vgic_v5_set_hwirq_id(x)) 111 + #define vgic_v5_make_lpi(x) (__vgic_v5_set_type(LPI) | vgic_v5_set_hwirq_id(x)) 112 + 113 + #define __vgic_is_v(k, v) ((k)->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V##v) 114 + #define vgic_is_v3(k) (__vgic_is_v(k, 3)) 115 + #define vgic_is_v5(k) (__vgic_is_v(k, 5)) 38 116 39 117 enum vgic_type { 40 118 VGIC_V2, /* Good ol' GICv2 */ ··· 497 417 498 418 #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel)) 499 419 #define vgic_initialized(k) ((k)->arch.vgic.initialized) 500 - #define vgic_valid_spi(k, i) (((i) >= VGIC_NR_PRIVATE_IRQS) && \ 501 - ((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) 420 + #define vgic_valid_spi(k, i) \ 421 + ({ \ 422 + bool __ret = irq_is_spi(k, i); \ 423 + \ 424 + switch ((k)->arch.vgic.vgic_model) { \ 425 + case KVM_DEV_TYPE_ARM_VGIC_V5: \ 426 + __ret &= FIELD_GET(GICV5_HWIRQ_ID, i) < (k)->arch.vgic.nr_spis; \ 427 + break; \ 428 + default: \ 429 + __ret &= (i) < ((k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS); \ 430 + } \ 431 + \ 432 + __ret; \ 433 + }) 502 434 503 435 bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu); 504 436 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);