[PATCH v4 08/13] ARM: KVM: vgic: retire queued, disabled interrupts
Will Deacon
will.deacon at arm.com
Mon Dec 3 08:24:18 EST 2012
On Sat, Nov 10, 2012 at 03:45:11PM +0000, Christoffer Dall wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
>
> 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 at arm.com>
> Signed-off-by: Christoffer Dall <c.dall at virtualopensystems.com>
> ---
> 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 d7cdec5..dda5623 100644
> --- a/arch/arm/kvm/vgic.c
> +++ b/arch/arm/kvm/vgic.c
> @@ -633,6 +633,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.
> @@ -696,6 +724,8 @@ static void __kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu)
>
> vcpu_id = vcpu->vcpu_id;
>
> + vgic_retire_disabled_irqs(vcpu);
Wouldn't it be better to do this when the interrupt is disabled, rather
than do the checking in the sync_to_cpu path?
Will
More information about the linux-arm-kernel
mailing list