diff options
author | Oliver Upton <oliver.upton@linux.dev> | 2023-12-19 07:58:55 +0100 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2023-12-22 10:34:27 +0100 |
commit | 39084ba8d0fceb477a264e2bb8dfd3553876b84c (patch) | |
tree | 5047db163b6d2931c5840930e5a49119231e0fa9 /arch/arm64/kvm/vgic/vgic-mmio-v3.c | |
parent | KVM: arm64: vgic: Use common accessor for writes to ICPENDR (diff) | |
download | linux-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
Diffstat (limited to 'arch/arm64/kvm/vgic/vgic-mmio-v3.c')
-rw-r--r-- | arch/arm64/kvm/vgic/vgic-mmio-v3.c | 35 |
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. */ |