@@ -386,9 +386,9 @@ static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
386386 vgic_irq_set_phys_active (irq , false);
387387}
388388
389- void vgic_mmio_write_cpending (struct kvm_vcpu * vcpu ,
390- gpa_t addr , unsigned int len ,
391- unsigned long val )
389+ static void __clear_pending (struct kvm_vcpu * vcpu ,
390+ gpa_t addr , unsigned int len ,
391+ unsigned long val , bool is_user )
392392{
393393 u32 intid = VGIC_ADDR_TO_INTID (addr , 1 );
394394 int i ;
@@ -397,14 +397,22 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
397397 for_each_set_bit (i , & val , len * 8 ) {
398398 struct vgic_irq * irq = vgic_get_irq (vcpu -> kvm , vcpu , intid + i );
399399
400- /* GICD_ICPENDR0 SGI bits are WI */
401- if (is_vgic_v2_sgi (vcpu , irq )) {
400+ /* GICD_ICPENDR0 SGI bits are WI when written from the guest. */
401+ if (is_vgic_v2_sgi (vcpu , irq ) && ! is_user ) {
402402 vgic_put_irq (vcpu -> kvm , irq );
403403 continue ;
404404 }
405405
406406 raw_spin_lock_irqsave (& irq -> irq_lock , flags );
407407
408+ /*
409+ * More fun with GICv2 SGIs! If we're clearing one of them
410+ * from userspace, which source vcpu to clear? Let's not
411+ * even think of it, and blow the whole set.
412+ */
413+ if (is_vgic_v2_sgi (vcpu , irq ))
414+ irq -> source = 0 ;
415+
408416 if (irq -> hw && vgic_irq_is_sgi (irq -> intid )) {
409417 /* HW SGI? Ask the GIC to clear its pending bit */
410418 int err ;
@@ -419,7 +427,7 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
419427 continue ;
420428 }
421429
422- if (irq -> hw )
430+ if (irq -> hw && ! is_user )
423431 vgic_hw_irq_cpending (vcpu , irq );
424432 else
425433 irq -> pending_latch = false;
@@ -429,33 +437,18 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
429437 }
430438}
431439
440+ void vgic_mmio_write_cpending (struct kvm_vcpu * vcpu ,
441+ gpa_t addr , unsigned int len ,
442+ unsigned long val )
443+ {
444+ __clear_pending (vcpu , addr , len , val , false);
445+ }
446+
432447int vgic_uaccess_write_cpending (struct kvm_vcpu * vcpu ,
433448 gpa_t addr , unsigned int len ,
434449 unsigned long val )
435450{
436- u32 intid = VGIC_ADDR_TO_INTID (addr , 1 );
437- int i ;
438- unsigned long flags ;
439-
440- for_each_set_bit (i , & val , len * 8 ) {
441- struct vgic_irq * irq = vgic_get_irq (vcpu -> kvm , vcpu , intid + i );
442-
443- raw_spin_lock_irqsave (& irq -> irq_lock , flags );
444- /*
445- * More fun with GICv2 SGIs! If we're clearing one of them
446- * from userspace, which source vcpu to clear? Let's not
447- * even think of it, and blow the whole set.
448- */
449- if (is_vgic_v2_sgi (vcpu , irq ))
450- irq -> source = 0 ;
451-
452- irq -> pending_latch = false;
453-
454- raw_spin_unlock_irqrestore (& irq -> irq_lock , flags );
455-
456- vgic_put_irq (vcpu -> kvm , irq );
457- }
458-
451+ __clear_pending (vcpu , addr , len , val , true);
459452 return 0 ;
460453}
461454
0 commit comments