On Wed, Aug 12, 2009 at 03:17:21PM +0300, Gleb Natapov wrote: > > Signed-off-by: Gleb Natapov <gleb@xxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html