[PATCH v2 20/36] KVM: arm64: gic-v5: Init Private IRQs (PPIs) for GICv5
Sascha Bischoff
Sascha.Bischoff at arm.com
Fri Dec 19 07:52:42 PST 2025
Initialise the private interrupts (PPIs, only) for GICv5. This means
that a GICv5-style intid is generated (which encodes the PPI type in
the top bits) instead of the 0-based index that is used for older
GICs.
Additionally, set all of the GICv5 PPIs to use Level for the handling
mode, with the exception of the SW_PPI which uses Edge. This matches
the architecturally-defined set in the GICv5 specification (the CTIIRQ
handling mode is IMPDEF, so pick Level has been picked for that).
Signed-off-by: Sascha Bischoff <sascha.bischoff at arm.com>
---
arch/arm64/kvm/vgic/vgic-init.c | 41 +++++++++++++++++++++++-------
include/linux/irqchip/arm-gic-v5.h | 2 ++
2 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index bcc2c79f7833c..03f45816464b0 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -263,13 +263,19 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
int i;
+ u32 num_private_irqs;
+
+ if (vgic_is_v5(vcpu->kvm))
+ num_private_irqs = VGIC_V5_NR_PRIVATE_IRQS;
+ else
+ num_private_irqs = VGIC_NR_PRIVATE_IRQS;
lockdep_assert_held(&vcpu->kvm->arch.config_lock);
if (vgic_cpu->private_irqs)
return 0;
- vgic_cpu->private_irqs = kcalloc(VGIC_NR_PRIVATE_IRQS,
+ vgic_cpu->private_irqs = kcalloc(num_private_irqs,
sizeof(struct vgic_irq),
GFP_KERNEL_ACCOUNT);
@@ -280,22 +286,39 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
* Enable and configure all SGIs to be edge-triggered and
* configure all PPIs as level-triggered.
*/
- for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+ for (i = 0; i < num_private_irqs; i++) {
struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
INIT_LIST_HEAD(&irq->ap_list);
raw_spin_lock_init(&irq->irq_lock);
- irq->intid = i;
irq->vcpu = NULL;
irq->target_vcpu = vcpu;
refcount_set(&irq->refcount, 0);
- if (vgic_irq_is_sgi(i)) {
- /* SGIs */
- irq->enabled = 1;
- irq->config = VGIC_CONFIG_EDGE;
+ if (!vgic_is_v5(vcpu->kvm)) {
+ irq->intid = i;
+ if (vgic_irq_is_sgi(i)) {
+ /* SGIs */
+ irq->enabled = 1;
+ irq->config = VGIC_CONFIG_EDGE;
+ } else {
+ /* PPIs */
+ irq->config = VGIC_CONFIG_LEVEL;
+ }
} else {
- /* PPIs */
- irq->config = VGIC_CONFIG_LEVEL;
+ irq->intid = i | FIELD_PREP(GICV5_HWIRQ_TYPE,
+ GICV5_HWIRQ_TYPE_PPI);
+
+ /*
+ * The only architected PPI that is Edge is
+ * the SW PPI.
+ */
+ if (irq->intid == GICV5_SW_PPI)
+ irq->config = VGIC_CONFIG_EDGE;
+ else
+ irq->config = VGIC_CONFIG_LEVEL;
+
+ /* Register the GICv5-specific PPI ops */
+ vgic_v5_set_ppi_ops(irq);
}
switch (type) {
diff --git a/include/linux/irqchip/arm-gic-v5.h b/include/linux/irqchip/arm-gic-v5.h
index d2780fc99c344..2ab7ec718aaea 100644
--- a/include/linux/irqchip/arm-gic-v5.h
+++ b/include/linux/irqchip/arm-gic-v5.h
@@ -13,6 +13,8 @@
#define GICV5_IPIS_PER_CPU MAX_IPI
+#define GICV5_SW_PPI 0x20000003
+
/*
* INTID handling
*/
--
2.34.1
More information about the linux-arm-kernel
mailing list