[PATCH v3 20/36] KVM: arm64: gic-v5: Init Private IRQs (PPIs) for GICv5
Sascha Bischoff
Sascha.Bischoff at arm.com
Fri Jan 9 09:04:45 PST 2026
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 Level has been picked for that).
Signed-off-by: Sascha Bischoff <sascha.bischoff at arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron at huawei.com>
---
arch/arm64/kvm/vgic/vgic-init.c | 39 +++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 653364299154e..973bbbe56062c 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;
lockdep_assert_held(&vcpu->kvm->arch.config_lock);
+ if (vgic_is_v5(vcpu->kvm))
+ num_private_irqs = VGIC_V5_NR_PRIVATE_IRQS;
+ else
+ num_private_irqs = VGIC_NR_PRIVATE_IRQS;
+
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,37 @@ 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 = FIELD_PREP(GICV5_HWIRQ_ID, i) |
+ FIELD_PREP(GICV5_HWIRQ_TYPE,
+ GICV5_HWIRQ_TYPE_PPI);
+
+ /* The only Edge architected PPI is the SW_PPI */
+ if (i == GICV5_ARCH_PPI_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) {
--
2.34.1
More information about the linux-arm-kernel
mailing list