mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 04:21:09 -04:00
KVM: arm64: gic-v5: Support GICv5 interrupts with KVM_IRQ_LINE
Interrupts under GICv5 look quite different to those from older Arm GICs. Specifically, the type is encoded in the top bits of the interrupt ID. Extend KVM_IRQ_LINE to cope with GICv5 PPIs and SPIs. The requires subtly changing the KVM_IRQ_LINE API for GICv5 guests. For older Arm GICs, PPIs had to be in the range of 16-31, and SPIs had to be 32-1019, but this no longer holds true for GICv5. Instead, for a GICv5 guest support PPIs in the range of 0-127, and SPIs in the range 0-65535. The documentation is updated accordingly. The SPI range doesn't cover the full SPI range that a GICv5 system can potentially cope with (GICv5 provides up to 24-bits of SPI ID space, and we only have 16 bits to work with in KVM_IRQ_LINE). However, 65k SPIs is more than would be reasonably expected on systems for years to come. In order to use vgic_is_v5(), the kvm/arm_vgic.h header is added to kvm/arm.c. Note: As the GICv5 KVM implementation currently doesn't support injecting SPIs attempts to do so will fail. This restriction will by lifted as the GICv5 KVM support evolves. 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: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20260319154937.3619520-28-sascha.bischoff@arm.com Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
committed by
Marc Zyngier
parent
5a98d0e17e
commit
b88d05a893
@@ -907,10 +907,12 @@ The irq_type field has the following values:
|
||||
- KVM_ARM_IRQ_TYPE_CPU:
|
||||
out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
|
||||
- KVM_ARM_IRQ_TYPE_SPI:
|
||||
in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
|
||||
in-kernel GICv2/GICv3: SPI, irq_id between 32 and 1019 (incl.)
|
||||
(the vcpu_index field is ignored)
|
||||
in-kernel GICv5: SPI, irq_id between 0 and 65535 (incl.)
|
||||
- KVM_ARM_IRQ_TYPE_PPI:
|
||||
in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
|
||||
in-kernel GICv2/GICv3: PPI, irq_id between 16 and 31 (incl.)
|
||||
in-kernel GICv5: PPI, irq_id between 0 and 127 (incl.)
|
||||
|
||||
(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
#include <kvm/arm_hypercalls.h>
|
||||
#include <kvm/arm_pmu.h>
|
||||
#include <kvm/arm_psci.h>
|
||||
#include <kvm/arm_vgic.h>
|
||||
|
||||
#include <linux/irqchip/arm-gic-v5.h>
|
||||
|
||||
#include "sys_regs.h"
|
||||
|
||||
@@ -1479,16 +1482,29 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
|
||||
if (!vcpu)
|
||||
return -EINVAL;
|
||||
|
||||
if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS)
|
||||
if (vgic_is_v5(kvm)) {
|
||||
if (irq_num >= VGIC_V5_NR_PRIVATE_IRQS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Build a GICv5-style IntID here */
|
||||
irq_num = vgic_v5_make_ppi(irq_num);
|
||||
} else if (irq_num < VGIC_NR_SGIS ||
|
||||
irq_num >= VGIC_NR_PRIVATE_IRQS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return kvm_vgic_inject_irq(kvm, vcpu, irq_num, level, NULL);
|
||||
case KVM_ARM_IRQ_TYPE_SPI:
|
||||
if (!irqchip_in_kernel(kvm))
|
||||
return -ENXIO;
|
||||
|
||||
if (irq_num < VGIC_NR_PRIVATE_IRQS)
|
||||
return -EINVAL;
|
||||
if (vgic_is_v5(kvm)) {
|
||||
/* Build a GICv5-style IntID here */
|
||||
irq_num = vgic_v5_make_spi(irq_num);
|
||||
} else {
|
||||
if (irq_num < VGIC_NR_PRIVATE_IRQS)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return kvm_vgic_inject_irq(kvm, NULL, irq_num, level, NULL);
|
||||
}
|
||||
|
||||
@@ -86,6 +86,10 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
|
||||
*/
|
||||
struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid)
|
||||
{
|
||||
/* Non-private IRQs are not yet implemented for GICv5 */
|
||||
if (vgic_is_v5(kvm))
|
||||
return NULL;
|
||||
|
||||
/* SPIs */
|
||||
if (intid >= VGIC_NR_PRIVATE_IRQS &&
|
||||
intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
|
||||
|
||||
Reference in New Issue
Block a user