Re: [PATCH] ARM: KVM: vgic: retire queued, disabled interrupts

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

 



On Thu, Oct 18, 2012 at 11:39 AM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote:
> An interrupt may have been disabled after being made pending on the
> CPU interface (the classic case is a timer running while we're
> rebooting the guest - the interrupt would kick as soon as the CPU
> interface gets enabled, with deadly consequences).
>
> The solution is to examine already active LRs, and check the
> interrupt is still enabled. If not, just retire it.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
> ---
>  arch/arm/kvm/vgic.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
>
> diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
> index b669b85..de088cc 100644
> --- a/arch/arm/kvm/vgic.c
> +++ b/arch/arm/kvm/vgic.c
> @@ -648,6 +648,34 @@ static void vgic_update_state(struct kvm *kvm)
>
>  #define LR_PHYSID(lr)          (((lr) & VGIC_LR_PHYSID_CPUID) >> 10)
>  #define MK_LR_PEND(src, irq)   (VGIC_LR_PENDING_BIT | ((src) << 10) | (irq))
> +
> +/*
> + * An interrupt may have been disabled after being made pending on the
> + * CPU interface (the classic case is a timer running while we're
> + * rebooting the guest - the interrupt would kick as soon as the CPU
> + * interface gets enabled, with deadly consequences).
> + *
> + * The solution is to examine already active LRs, and check the
> + * interrupt is still enabled. If not, just retire it.
> + */
> +static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
> +{
> +       struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
> +       int lr;
> +
> +       for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
> +               int irq = vgic_cpu->vgic_lr[lr] & VGIC_LR_VIRTUALID;
> +
> +               if (!vgic_bitmap_get_irq_val(&dist->irq_enabled,
> +                                            vcpu->vcpu_id, irq)) {
> +                       vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
> +                       clear_bit(lr, vgic_cpu->lr_used);
> +                       vgic_cpu->vgic_lr[lr] &= ~VGIC_LR_STATE;
> +               }
> +       }
> +}
> +
>  /*
>   * Queue an interrupt to a CPU virtual interface. Return true on success,
>   * or false if it wasn't possible to queue it.
> @@ -715,6 +743,8 @@ static void __kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu)
>
>         vcpu_id = vcpu->vcpu_id;
>
> +       vgic_retire_disabled_irqs(vcpu);
> +
>         /*
>          * We may not have any pending interrupt, or the interrupts
>          * may have been serviced from another vcpu. In all cases,


looks perfect.

Thanks, applied.
-Christoffer
_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux