summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Upton <oliver.upton@linux.dev>2023-12-19 07:58:55 +0100
committerMarc Zyngier <maz@kernel.org>2023-12-22 10:34:27 +0100
commit39084ba8d0fceb477a264e2bb8dfd3553876b84c (patch)
tree5047db163b6d2931c5840930e5a49119231e0fa9
parentKVM: arm64: vgic: Use common accessor for writes to ICPENDR (diff)
downloadlinux-39084ba8d0fceb477a264e2bb8dfd3553876b84c.tar.xz
linux-39084ba8d0fceb477a264e2bb8dfd3553876b84c.zip
KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
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
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v3.c35
1 files changed, 5 insertions, 30 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 111bd7f42729..2962ccd8013a 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -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. */