On Wed, Aug 12, 2009 at 03:17:21PM +0300, Gleb Natapov wrote:
> 
> Signed-off-by: Gleb Natapov <[email protected]>
> ---
>  arch/ia64/kvm/kvm-ia64.c |    7 +---
>  arch/x86/kvm/i8259.c     |   22 +++++++++---
>  arch/x86/kvm/lapic.c     |    5 +--
>  arch/x86/kvm/x86.c       |   10 +----
>  virt/kvm/ioapic.c        |   80 
> +++++++++++++++++++++++++++++++++++-----------
>  virt/kvm/ioapic.h        |    4 ++
>  6 files changed, 86 insertions(+), 42 deletions(-)
> 
> diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
> index 0ad09f0..4a98314 100644
> --- a/arch/ia64/kvm/kvm-ia64.c
> +++ b/arch/ia64/kvm/kvm-ia64.c
> @@ -851,8 +851,7 @@ static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
>       r = 0;
>       switch (chip->chip_id) {
>       case KVM_IRQCHIP_IOAPIC:
> -             memcpy(&chip->chip.ioapic, ioapic_irqchip(kvm),
> -                             sizeof(struct kvm_ioapic_state));
> +             r = kvm_get_ioapic(kvm, &chip->chip.ioapic);
>               break;
>       default:
>               r = -EINVAL;
> @@ -868,9 +867,7 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, 
> struct kvm_irqchip *chip)
>       r = 0;
>       switch (chip->chip_id) {
>       case KVM_IRQCHIP_IOAPIC:
> -             memcpy(ioapic_irqchip(kvm),
> -                             &chip->chip.ioapic,
> -                             sizeof(struct kvm_ioapic_state));
> +             r = kvm_set_ioapic(kvm, &chip->chip.ioapic);
>               break;
>       default:
>               r = -EINVAL;
> diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
> index eb2b8b7..96ea7f7 100644
> --- a/arch/x86/kvm/i8259.c
> +++ b/arch/x86/kvm/i8259.c
> @@ -38,7 +38,15 @@ static void pic_clear_isr(struct kvm_kpic_state *s, int 
> irq)
>       s->isr_ack |= (1 << irq);
>       if (s != &s->pics_state->pics[0])
>               irq += 8;
> +     /*
> +      * We are dropping lock while calling ack notifiers since ack
> +      * notifier callbacks for assigned devices call into PIC recursively.
> +      * Other interrupt may be delivered to PIC while lock is dropped but
> +      * it should be safe since PIC state is already updated at this stage.
> +      */
> +     spin_unlock(&s->pics_state->lock);
>       kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq);
> +     spin_lock(&s->pics_state->lock);
>  }
>  
>  void kvm_pic_clear_isr_ack(struct kvm *kvm)
> @@ -176,16 +184,18 @@ int kvm_pic_set_irq(void *opaque, int irq, int level)
>  static inline void pic_intack(struct kvm_kpic_state *s, int irq)
>  {
>       s->isr |= 1 << irq;
> -     if (s->auto_eoi) {
> -             if (s->rotate_on_auto_eoi)
> -                     s->priority_add = (irq + 1) & 7;
> -             pic_clear_isr(s, irq);
> -     }
>       /*
>        * We don't clear a level sensitive interrupt here
>        */
>       if (!(s->elcr & (1 << irq)))
>               s->irr &= ~(1 << irq);
> +
> +     if (s->auto_eoi) {
> +             if (s->rotate_on_auto_eoi)
> +                     s->priority_add = (irq + 1) & 7;
> +             pic_clear_isr(s, irq);
> +     }
> +
>  }
>  
>  int kvm_pic_read_irq(struct kvm *kvm)
> @@ -282,9 +292,9 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 
> val)
>                               priority = get_priority(s, s->isr);
>                               if (priority != 8) {
>                                       irq = (priority + s->priority_add) & 7;
> -                                     pic_clear_isr(s, irq);
>                                       if (cmd == 5)
>                                               s->priority_add = (irq + 1) & 7;
> +                                     pic_clear_isr(s, irq);
>                                       pic_update_irq(s->pics_state);
>                               }
>                               break;
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index ce195f8..f24d4d0 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -471,11 +471,8 @@ static void apic_set_eoi(struct kvm_lapic *apic)
>               trigger_mode = IOAPIC_LEVEL_TRIG;
>       else
>               trigger_mode = IOAPIC_EDGE_TRIG;
> -     if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) {
> -             mutex_lock(&apic->vcpu->kvm->irq_lock);
> +     if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI))
>               kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
> -             mutex_unlock(&apic->vcpu->kvm->irq_lock);
> -     }
>  }
>  
>  static void apic_send_ipi(struct kvm_lapic *apic)
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 850cf56..75dcdad 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -2023,9 +2023,7 @@ static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, 
> struct kvm_irqchip *chip)
>                       sizeof(struct kvm_pic_state));
>               break;
>       case KVM_IRQCHIP_IOAPIC:
> -             memcpy(&chip->chip.ioapic,
> -                     ioapic_irqchip(kvm),
> -                     sizeof(struct kvm_ioapic_state));
> +             r = kvm_get_ioapic(kvm, &chip->chip.ioapic);
>               break;
>       default:
>               r = -EINVAL;
> @@ -2055,11 +2053,7 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, 
> struct kvm_irqchip *chip)
>               spin_unlock(&pic_irqchip(kvm)->lock);
>               break;
>       case KVM_IRQCHIP_IOAPIC:
> -             mutex_lock(&kvm->irq_lock);
> -             memcpy(ioapic_irqchip(kvm),
> -                     &chip->chip.ioapic,
> -                     sizeof(struct kvm_ioapic_state));
> -             mutex_unlock(&kvm->irq_lock);
> +             r = kvm_set_ioapic(kvm, &chip->chip.ioapic);
>               break;
>       default:
>               r = -EINVAL;
> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
> index fa05f67..e9de458 100644
> --- a/virt/kvm/ioapic.c
> +++ b/virt/kvm/ioapic.c
> @@ -182,6 +182,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int 
> irq, int level)
>       union kvm_ioapic_redirect_entry entry;
>       int ret = 1;
>  
> +     mutex_lock(&ioapic->lock);
>       if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
>               entry = ioapic->redirtbl[irq];
>               level ^= entry.fields.polarity;

But this is an RCU critical section now, right? 

If so, you can't sleep, must use a spinlock.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to