Re: [PATCH] KVM: arm/arm64: vgic-v3: Retire pending interrupts on disabling LPIs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marc,

On 4/2/19 9:24 AM, Marc Zyngier wrote:
> When disabling LPIs (for example on reset) at the redistributor
> level, it is expected that LPIs that was pending in the CPU
> interface are eventually retired.
> 
> Currently, this is not what is happening, and these LPIs will
> stay in the ap_list, eventually being acknowledged by the vcpu
> (which didn't quite expect this behaviour).
> 
> The fix is thus to retire these LPIs from the list of pending
> interrupts as we disable LPIs.
> 
> Reported-by: Heyi Guo <guoheyi@xxxxxxxxxx>
> Fixes: 0e4e82f154e3 ("KVM: arm64: vgic-its: Enable ITS emulation as a virtual MSI controller")
> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
> ---
> Heyi,
> 
> Can you please give this alternative patch a go on your setup?
> This should be a much better fit than my original hack.
> 
> Thanks,
> 
>         M.
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c |  3 +++
>  virt/kvm/arm/vgic/vgic.c         | 24 ++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h         |  1 +
>  3 files changed, 28 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 4a12322bf7df..9f4843fe9cda 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -200,6 +200,9 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,
>  
>  	vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS;
>  
> +	if (was_enabled && !vgic_cpu->lpis_enabled)
> +		vgic_flush_pending_lpis(vcpu);
> +
>  	if (!was_enabled && vgic_cpu->lpis_enabled)
>  		vgic_enable_lpis(vcpu);
>  }
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 3af69f2a3866..3f429cf2f694 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -151,6 +151,30 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
>  	kfree(irq);
>  }
>  
> +void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq, *tmp;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
Do you need to hold the lpi_list_lock here as it is taken in vgic_put_irq.
> +	raw_spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
> +		if (irq->intid >= VGIC_MIN_LPI) {
> +			raw_spin_lock(&irq->irq_lock);
> +			list_del(&irq->ap_list);
> +			irq->vcpu = NULL;
> +			raw_spin_unlock(&irq->irq_lock);
> +			vgic_put_irq(vcpu->kvm, irq);
> +		}
> +	}
> +
> +	raw_spin_unlock(&vgic_cpu->ap_list_lock);
> +	raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
A concern I have is how does this live with
vgic_v3_save_pending_tables/its_sync_lpi_pending_table ctrl flow. I need
to trace things.

Thanks

Eric
> +}
> +
>  void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending)
>  {
>  	WARN_ON(irq_set_irqchip_state(irq->host_irq,
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index a90024718ca4..abeeffabc456 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -238,6 +238,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu);
>  bool vgic_has_its(struct kvm *kvm);
>  int kvm_vgic_register_its_device(void);
>  void vgic_enable_lpis(struct kvm_vcpu *vcpu);
> +void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu);
>  int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
>  int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> 



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux