Re: [PATCH v3 7/8] Move IO APIC to its own lock.

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

 



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

[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