In order to be able to call kvm_set_irq from an interrupt context, the IOAPIC lock can't be a (possibly sleeping) mutex. Convert it to a spinlock. Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> --- virt/kvm/ioapic.c | 40 +++++++++++++++++++++++++--------------- virt/kvm/ioapic.h | 2 +- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index fd52949..3d68826 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -192,8 +192,9 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) u32 mask = 1 << irq; union kvm_ioapic_redirect_entry entry; int ret = 1; + unsigned long flags; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); if (irq >= 0 && irq < IOAPIC_NUM_PINS) { entry = ioapic->redirtbl[irq]; level ^= entry.fields.polarity; @@ -210,7 +211,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) } trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0); } - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); return ret; } @@ -234,9 +235,9 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, * is dropped it will be put into irr and will be delivered * after ack notifier returns. */ - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i); - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); if (trigger_mode != IOAPIC_LEVEL_TRIG) continue; @@ -251,10 +252,11 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode) { struct kvm_ioapic *ioapic = kvm->arch.vioapic; + unsigned long flags; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); } static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev) @@ -273,6 +275,8 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, { struct kvm_ioapic *ioapic = to_ioapic(this); u32 result; + unsigned long flags; + if (!ioapic_in_range(ioapic, addr)) return -EOPNOTSUPP; @@ -280,7 +284,7 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, ASSERT(!(addr & 0xf)); /* check alignment */ addr &= 0xff; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); switch (addr) { case IOAPIC_REG_SELECT: result = ioapic->ioregsel; @@ -294,7 +298,7 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, result = 0; break; } - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); switch (len) { case 8: @@ -316,6 +320,8 @@ static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, { struct kvm_ioapic *ioapic = to_ioapic(this); u32 data; + unsigned long flags; + if (!ioapic_in_range(ioapic, addr)) return -EOPNOTSUPP; @@ -331,7 +337,7 @@ static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, } addr &= 0xff; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); switch (addr) { case IOAPIC_REG_SELECT: ioapic->ioregsel = data; @@ -349,7 +355,7 @@ static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, default: break; } - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); return 0; } @@ -378,7 +384,7 @@ int kvm_ioapic_init(struct kvm *kvm) ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL); if (!ioapic) return -ENOMEM; - mutex_init(&ioapic->lock); + spin_lock_init(&ioapic->lock); kvm->arch.vioapic = ioapic; kvm_ioapic_reset(ioapic); kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); @@ -393,23 +399,27 @@ int kvm_ioapic_init(struct kvm *kvm) int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) { struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); + unsigned long flags; + if (!ioapic) return -EINVAL; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); return 0; } int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) { struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); + unsigned long flags; + if (!ioapic) return -EINVAL; - mutex_lock(&ioapic->lock); + spin_lock_irqsave(&ioapic->lock, flags); memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); - mutex_unlock(&ioapic->lock); + spin_unlock_irqrestore(&ioapic->lock, flags); return 0; } diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 419c43b..5b4f756 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h @@ -45,7 +45,7 @@ struct kvm_ioapic { struct kvm_io_device dev; struct kvm *kvm; void (*ack_notifier)(void *opaque, int irq); - struct mutex lock; + spinlock_t lock; }; #ifdef DEBUG -- 1.6.5.2 -- 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