]> xenbits.xensource.com Git - people/pauldu/linux.git/commitdiff
KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
authorOliver Upton <oliver.upton@linux.dev>
Tue, 19 Dec 2023 06:58:55 +0000 (06:58 +0000)
committerMarc Zyngier <maz@kernel.org>
Fri, 22 Dec 2023 09:34:27 +0000 (09:34 +0000)
User writes to ISPENDR for GICv3 are treated specially, as zeroes
actually clear the pending state for interrupts (unlike HW). Reimplement
it using the ISPENDR and ICPENDR user accessors.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20231219065855.1019608-4-oliver.upton@linux.dev
arch/arm64/kvm/vgic/vgic-mmio-v3.c

index 111bd7f4272926fea506dc141c2aa5106ded9716..2962ccd8013a28cb8bce17762c0fb71eb588bbe0 100644 (file)
@@ -357,38 +357,13 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
                                         gpa_t addr, unsigned int len,
                                         unsigned long val)
 {
-       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
-       int i;
-       unsigned long flags;
-
-       for (i = 0; i < len * 8; i++) {
-               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-               raw_spin_lock_irqsave(&irq->irq_lock, flags);
-
-               /*
-                * pending_latch is set irrespective of irq type
-                * (level or edge) to avoid dependency that VM should
-                * restore irq config before pending info.
-                */
-               irq->pending_latch = test_bit(i, &val);
-
-               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
-                       irq_set_irqchip_state(irq->host_irq,
-                                             IRQCHIP_STATE_PENDING,
-                                             irq->pending_latch);
-                       irq->pending_latch = false;
-               }
-
-               if (irq->pending_latch)
-                       vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
-               else
-                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+       int ret;
 
-               vgic_put_irq(vcpu->kvm, irq);
-       }
+       ret = vgic_uaccess_write_spending(vcpu, addr, len, val);
+       if (ret)
+               return ret;
 
-       return 0;
+       return vgic_uaccess_write_cpending(vcpu, addr, len, ~val);
 }
 
 /* We want to avoid outer shareable. */