Skip to content

Commit 13886f3

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: vgic: Use common accessor for writes to ISPENDR
Perhaps unsurprisingly, there is a considerable amount of duplicate code between the MMIO and user accessors for ISPENDR. At the same time there are some important differences between user and guest MMIO, like how SGIs can only be made pending from userspace. Fold user and MMIO accessors into a common helper, maintaining the distinction between the two. Signed-off-by: Oliver Upton <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 7b95382 commit 13886f3

File tree

1 file changed

+21
-29
lines changed

1 file changed

+21
-29
lines changed

arch/arm64/kvm/vgic/vgic-mmio.c

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,8 @@ static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
301301
vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
302302
}
303303

304-
void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
305-
gpa_t addr, unsigned int len,
306-
unsigned long val)
304+
static void __set_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
305+
unsigned long val, bool is_user)
307306
{
308307
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
309308
int i;
@@ -312,14 +311,22 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
312311
for_each_set_bit(i, &val, len * 8) {
313312
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
314313

315-
/* GICD_ISPENDR0 SGI bits are WI */
316-
if (is_vgic_v2_sgi(vcpu, irq)) {
314+
/* GICD_ISPENDR0 SGI bits are WI when written from the guest. */
315+
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
317316
vgic_put_irq(vcpu->kvm, irq);
318317
continue;
319318
}
320319

321320
raw_spin_lock_irqsave(&irq->irq_lock, flags);
322321

322+
/*
323+
* GICv2 SGIs are terribly broken. We can't restore
324+
* the source of the interrupt, so just pick the vcpu
325+
* itself as the source...
326+
*/
327+
if (is_vgic_v2_sgi(vcpu, irq))
328+
irq->source |= BIT(vcpu->vcpu_id);
329+
323330
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
324331
/* HW SGI? Ask the GIC to inject it */
325332
int err;
@@ -335,41 +342,26 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
335342
}
336343

337344
irq->pending_latch = true;
338-
if (irq->hw)
345+
if (irq->hw && !is_user)
339346
vgic_irq_set_phys_active(irq, true);
340347

341348
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
342349
vgic_put_irq(vcpu->kvm, irq);
343350
}
344351
}
345352

353+
void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
354+
gpa_t addr, unsigned int len,
355+
unsigned long val)
356+
{
357+
__set_pending(vcpu, addr, len, val, false);
358+
}
359+
346360
int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
347361
gpa_t addr, unsigned int len,
348362
unsigned long val)
349363
{
350-
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
351-
int i;
352-
unsigned long flags;
353-
354-
for_each_set_bit(i, &val, len * 8) {
355-
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
356-
357-
raw_spin_lock_irqsave(&irq->irq_lock, flags);
358-
irq->pending_latch = true;
359-
360-
/*
361-
* GICv2 SGIs are terribly broken. We can't restore
362-
* the source of the interrupt, so just pick the vcpu
363-
* itself as the source...
364-
*/
365-
if (is_vgic_v2_sgi(vcpu, irq))
366-
irq->source |= BIT(vcpu->vcpu_id);
367-
368-
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
369-
370-
vgic_put_irq(vcpu->kvm, irq);
371-
}
372-
364+
__set_pending(vcpu, addr, len, val, true);
373365
return 0;
374366
}
375367

0 commit comments

Comments
 (0)