From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@redhat.com>, kvm@vger.kernel.org
Cc: Gregory Haskins <gregory.haskins@gmail.com>,
Marcelo Tosatti <mtosatti@redhat.com>
Subject: [patch 4/4] KVM: switch irq injection/acking to irq_lock
Date: Wed, 20 May 2009 15:48:45 -0300 [thread overview]
Message-ID: <20090520185134.875726533@localhost.localdomain> (raw)
In-Reply-To: 20090520184841.954066003@localhost.localdomain
[-- Attachment #1: irqlock --]
[-- Type: text/plain, Size: 11937 bytes --]
Switch irq injection/acking to irq_lock, and change PIO/MMIO paths
so that the device search is protected by kvm->lock, but not the
read/write callbacks (which is responsability of the device).
Fix for http://article.gmane.org/gmane.comp.emulators.kvm.devel/32286.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: kvm/arch/x86/kvm/i8254.c
===================================================================
--- kvm.orig/arch/x86/kvm/i8254.c
+++ kvm/arch/x86/kvm/i8254.c
@@ -634,10 +634,10 @@ static void __inject_pit_timer_intr(stru
struct kvm_vcpu *vcpu;
int i;
- mutex_lock(&kvm->lock);
+ mutex_lock(&kvm->irq_lock);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 1);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 0);
- mutex_unlock(&kvm->lock);
+ mutex_unlock(&kvm->irq_lock);
/*
* Provides NMI watchdog support via Virtual Wire mode.
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -2077,10 +2077,10 @@ long kvm_arch_vm_ioctl(struct file *filp
goto out;
if (irqchip_in_kernel(kvm)) {
__s32 status;
- mutex_lock(&kvm->lock);
+ mutex_lock(&kvm->irq_lock);
status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
irq_event.irq, irq_event.level);
- mutex_unlock(&kvm->lock);
+ mutex_unlock(&kvm->irq_lock);
if (ioctl == KVM_IRQ_LINE_STATUS) {
irq_event.status = status;
if (copy_to_user(argp, &irq_event,
@@ -2326,12 +2326,11 @@ mmio:
*/
mutex_lock(&vcpu->kvm->lock);
mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 0);
+ mutex_unlock(&vcpu->kvm->lock);
if (mmio_dev) {
kvm_iodevice_read(mmio_dev, gpa, bytes, val);
- mutex_unlock(&vcpu->kvm->lock);
return X86EMUL_CONTINUE;
}
- mutex_unlock(&vcpu->kvm->lock);
vcpu->mmio_needed = 1;
vcpu->mmio_phys_addr = gpa;
@@ -2381,12 +2380,11 @@ mmio:
*/
mutex_lock(&vcpu->kvm->lock);
mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 1);
+ mutex_unlock(&vcpu->kvm->lock);
if (mmio_dev) {
kvm_iodevice_write(mmio_dev, gpa, bytes, val);
- mutex_unlock(&vcpu->kvm->lock);
return X86EMUL_CONTINUE;
}
- mutex_unlock(&vcpu->kvm->lock);
vcpu->mmio_needed = 1;
vcpu->mmio_phys_addr = gpa;
@@ -2709,7 +2707,6 @@ static void kernel_pio(struct kvm_io_dev
{
/* TODO: String I/O for in kernel device */
- mutex_lock(&vcpu->kvm->lock);
if (vcpu->arch.pio.in)
kvm_iodevice_read(pio_dev, vcpu->arch.pio.port,
vcpu->arch.pio.size,
@@ -2718,7 +2715,6 @@ static void kernel_pio(struct kvm_io_dev
kvm_iodevice_write(pio_dev, vcpu->arch.pio.port,
vcpu->arch.pio.size,
pd);
- mutex_unlock(&vcpu->kvm->lock);
}
static void pio_string_write(struct kvm_io_device *pio_dev,
@@ -2728,14 +2724,12 @@ static void pio_string_write(struct kvm_
void *pd = vcpu->arch.pio_data;
int i;
- mutex_lock(&vcpu->kvm->lock);
for (i = 0; i < io->cur_count; i++) {
kvm_iodevice_write(pio_dev, io->port,
io->size,
pd);
pd += io->size;
}
- mutex_unlock(&vcpu->kvm->lock);
}
static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
@@ -2772,7 +2766,9 @@ int kvm_emulate_pio(struct kvm_vcpu *vcp
val = kvm_register_read(vcpu, VCPU_REGS_RAX);
memcpy(vcpu->arch.pio_data, &val, 4);
+ mutex_lock(&vcpu->kvm->lock);
pio_dev = vcpu_find_pio_dev(vcpu, port, size, !in);
+ mutex_unlock(&vcpu->kvm->lock);
if (pio_dev) {
kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data);
complete_pio(vcpu);
@@ -2836,9 +2832,12 @@ int kvm_emulate_pio_string(struct kvm_vc
vcpu->arch.pio.guest_gva = address;
+ mutex_lock(&vcpu->kvm->lock);
pio_dev = vcpu_find_pio_dev(vcpu, port,
vcpu->arch.pio.cur_count,
!vcpu->arch.pio.in);
+ mutex_unlock(&vcpu->kvm->lock);
+
if (!vcpu->arch.pio.in) {
/* string PIO write */
ret = pio_copy_data(vcpu);
Index: kvm/virt/kvm/kvm_main.c
===================================================================
--- kvm.orig/virt/kvm/kvm_main.c
+++ kvm/virt/kvm/kvm_main.c
@@ -62,6 +62,12 @@
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
+/*
+ * Ordering of locks:
+ *
+ * kvm->lock --> kvm->irq_lock
+ */
+
DEFINE_SPINLOCK(kvm_lock);
LIST_HEAD(vm_list);
@@ -126,11 +132,7 @@ static void kvm_assigned_dev_interrupt_w
interrupt_work);
kvm = assigned_dev->kvm;
- /* This is taken to safely inject irq inside the guest. When
- * the interrupt injection (or the ioapic code) uses a
- * finer-grained lock, update this
- */
- mutex_lock(&kvm->lock);
+ mutex_lock(&kvm->irq_lock);
spin_lock_irq(&assigned_dev->assigned_dev_lock);
if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
struct kvm_guest_msix_entry *guest_entries =
@@ -159,7 +161,7 @@ static void kvm_assigned_dev_interrupt_w
}
spin_unlock_irq(&assigned_dev->assigned_dev_lock);
- mutex_unlock(&assigned_dev->kvm->lock);
+ mutex_unlock(&assigned_dev->kvm->irq_lock);
}
static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
@@ -215,7 +217,7 @@ static void kvm_assigned_dev_ack_irq(str
static void deassign_guest_irq(struct kvm *kvm,
struct kvm_assigned_dev_kernel *assigned_dev)
{
- kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier);
+ kvm_unregister_irq_ack_notifier(kvm, &assigned_dev->ack_notifier);
assigned_dev->ack_notifier.gsi = -1;
if (assigned_dev->irq_source_id != -1)
Index: kvm/virt/kvm/irq_comm.c
===================================================================
--- kvm.orig/virt/kvm/irq_comm.c
+++ kvm/virt/kvm/irq_comm.c
@@ -62,6 +62,8 @@ int kvm_irq_delivery_to_apic(struct kvm
int i, r = -1;
struct kvm_vcpu *vcpu, *lowest = NULL;
+ WARN_ON(!mutex_is_locked(&kvm->irq_lock));
+
if (irq->dest_mode == 0 && irq->dest_id == 0xff &&
kvm_is_dm_lowest_prio(irq))
printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
@@ -113,7 +115,7 @@ static int kvm_set_msi(struct kvm_kernel
return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
}
-/* This should be called with the kvm->lock mutex held
+/* This should be called with the kvm->irq_lock mutex held
* Return value:
* < 0 Interrupt was ignored (masked or not delivered for other reasons)
* = 0 Interrupt was coalesced (previous irq is still pending)
@@ -125,6 +127,8 @@ int kvm_set_irq(struct kvm *kvm, int irq
unsigned long *irq_state, sig_level;
int ret = -1;
+ WARN_ON(!mutex_is_locked(&kvm->irq_lock));
+
if (irq < KVM_IOAPIC_NUM_PINS) {
irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
@@ -174,19 +178,26 @@ void kvm_notify_acked_irq(struct kvm *kv
void kvm_register_irq_ack_notifier(struct kvm *kvm,
struct kvm_irq_ack_notifier *kian)
{
+ mutex_lock(&kvm->irq_lock);
hlist_add_head(&kian->link, &kvm->arch.irq_ack_notifier_list);
+ mutex_unlock(&kvm->irq_lock);
}
-void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian)
+void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
+ struct kvm_irq_ack_notifier *kian)
{
+ mutex_lock(&kvm->irq_lock);
hlist_del_init(&kian->link);
+ mutex_unlock(&kvm->irq_lock);
}
-/* The caller must hold kvm->lock mutex */
int kvm_request_irq_source_id(struct kvm *kvm)
{
unsigned long *bitmap = &kvm->arch.irq_sources_bitmap;
- int irq_source_id = find_first_zero_bit(bitmap,
+ int irq_source_id;
+
+ mutex_lock(&kvm->irq_lock);
+ irq_source_id = find_first_zero_bit(bitmap,
sizeof(kvm->arch.irq_sources_bitmap));
if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) {
@@ -196,6 +207,7 @@ int kvm_request_irq_source_id(struct kvm
ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID);
set_bit(irq_source_id, bitmap);
+ mutex_unlock(&kvm->irq_lock);
return irq_source_id;
}
@@ -206,6 +218,7 @@ void kvm_free_irq_source_id(struct kvm *
ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID);
+ mutex_lock(&kvm->irq_lock);
if (irq_source_id < 0 ||
irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) {
printk(KERN_ERR "kvm: IRQ source ID out of range!\n");
@@ -214,19 +227,24 @@ void kvm_free_irq_source_id(struct kvm *
for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++)
clear_bit(irq_source_id, &kvm->arch.irq_states[i]);
clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
+ mutex_unlock(&kvm->irq_lock);
}
void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn)
{
+ mutex_lock(&kvm->irq_lock);
kimn->irq = irq;
hlist_add_head(&kimn->link, &kvm->mask_notifier_list);
+ mutex_unlock(&kvm->irq_lock);
}
void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn)
{
+ mutex_lock(&kvm->irq_lock);
hlist_del(&kimn->link);
+ mutex_unlock(&kvm->irq_lock);
}
void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask)
@@ -234,6 +252,8 @@ void kvm_fire_mask_notifiers(struct kvm
struct kvm_irq_mask_notifier *kimn;
struct hlist_node *n;
+ WARN_ON(!mutex_is_locked(&kvm->irq_lock));
+
hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link)
if (kimn->irq == irq)
kimn->func(kimn, mask);
@@ -249,7 +269,9 @@ static void __kvm_free_irq_routing(struc
void kvm_free_irq_routing(struct kvm *kvm)
{
+ mutex_lock(&kvm->irq_lock);
__kvm_free_irq_routing(&kvm->irq_routing);
+ mutex_unlock(&kvm->irq_lock);
}
static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
@@ -323,13 +345,13 @@ int kvm_set_irq_routing(struct kvm *kvm,
e = NULL;
}
- mutex_lock(&kvm->lock);
+ mutex_lock(&kvm->irq_lock);
list_splice(&kvm->irq_routing, &tmp);
INIT_LIST_HEAD(&kvm->irq_routing);
list_splice(&irq_list, &kvm->irq_routing);
INIT_LIST_HEAD(&irq_list);
list_splice(&tmp, &irq_list);
- mutex_unlock(&kvm->lock);
+ mutex_unlock(&kvm->irq_lock);
r = 0;
Index: kvm/arch/x86/kvm/lapic.c
===================================================================
--- kvm.orig/arch/x86/kvm/lapic.c
+++ kvm/arch/x86/kvm/lapic.c
@@ -425,7 +425,9 @@ static void apic_set_eoi(struct kvm_lapi
trigger_mode = IOAPIC_LEVEL_TRIG;
else
trigger_mode = IOAPIC_EDGE_TRIG;
+ mutex_lock(&apic->vcpu->kvm->irq_lock);
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)
@@ -449,7 +451,9 @@ static void apic_send_ipi(struct kvm_lap
irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode,
irq.vector);
+ mutex_lock(&apic->vcpu->kvm->irq_lock);
kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq);
+ mutex_unlock(&apic->vcpu->kvm->irq_lock);
}
static u32 apic_get_tmcct(struct kvm_lapic *apic)
Index: kvm/include/linux/kvm_host.h
===================================================================
--- kvm.orig/include/linux/kvm_host.h
+++ kvm/include/linux/kvm_host.h
@@ -376,7 +376,8 @@ int kvm_set_irq(struct kvm *kvm, int irq
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
struct kvm_irq_ack_notifier *kian);
-void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian);
+void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
+ struct kvm_irq_ack_notifier *kian);
int kvm_request_irq_source_id(struct kvm *kvm);
void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
Index: kvm/virt/kvm/eventfd.c
===================================================================
--- kvm.orig/virt/kvm/eventfd.c
+++ kvm/virt/kvm/eventfd.c
@@ -52,10 +52,10 @@ irqfd_inject(struct work_struct *work)
struct _irqfd *irqfd = container_of(work, struct _irqfd, work);
struct kvm *kvm = irqfd->kvm;
- mutex_lock(&kvm->lock);
+ mutex_lock(&kvm->irq_lock);
kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1);
kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0);
- mutex_unlock(&kvm->lock);
+ mutex_unlock(&kvm->irq_lock);
}
static int
--
next prev parent reply other threads:[~2009-05-20 18:55 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-18 16:56 [patch 0/4] move irq protection role to separate kvm->irq_lock Marcelo Tosatti
2009-05-18 16:56 ` [patch 1/4] KVM: x86: grab pic lock in kvm_pic_clear_isr_ack Marcelo Tosatti
2009-05-18 16:56 ` [patch 2/4] KVM: move coalesced_mmio locking to its own device Marcelo Tosatti
2009-05-20 12:06 ` Avi Kivity
2009-05-20 14:09 ` Marcelo Tosatti
2009-05-20 14:29 ` Avi Kivity
2009-05-20 15:13 ` Marcelo Tosatti
2009-05-20 15:22 ` Marcelo Tosatti
2009-05-20 15:22 ` Avi Kivity
2009-05-20 18:48 ` [patch 0/4] move irq protection role to separate lock v2 Marcelo Tosatti
2009-05-20 18:48 ` [patch 1/4] KVM: x86: grab pic lock in kvm_pic_clear_isr_ack Marcelo Tosatti
2009-05-20 18:48 ` [patch 2/4] KVM: move coalesced_mmio locking to its own device Marcelo Tosatti
2009-05-24 14:04 ` Avi Kivity
2009-05-25 11:04 ` Marcelo Tosatti
2009-05-26 11:24 ` Avi Kivity
2009-05-26 13:15 ` Marcelo Tosatti
2009-05-26 13:27 ` Avi Kivity
2009-05-20 18:48 ` [patch 3/4] KVM: introduce irq_lock, use it to protect ioapic Marcelo Tosatti
2009-05-24 14:10 ` Avi Kivity
2009-05-25 11:11 ` Marcelo Tosatti
2009-05-26 11:33 ` Avi Kivity
2009-05-28 4:45 ` [patch 0/4] move irq protection role to separate lock v3 Marcelo Tosatti
2009-05-28 4:45 ` [patch 1/4] KVM: x86: grab pic lock in kvm_pic_clear_isr_ack Marcelo Tosatti
2009-05-28 4:45 ` [patch 2/4] KVM: move coalesced_mmio locking to its own device Marcelo Tosatti
2009-05-31 12:14 ` Avi Kivity
2009-06-01 21:23 ` Marcelo Tosatti
2009-06-01 21:43 ` Avi Kivity
2009-06-04 18:08 ` [patch 0/4] move irq protection role to separate lock v4 Marcelo Tosatti
2009-06-04 18:08 ` [patch 1/4] KVM: x86: grab pic lock in kvm_pic_clear_isr_ack Marcelo Tosatti
2009-06-04 18:08 ` [patch 2/4] KVM: move coalesced_mmio locking to its own device Marcelo Tosatti
2009-06-04 18:08 ` [patch 3/4] KVM: introduce irq_lock, use it to protect ioapic Marcelo Tosatti
2009-06-04 18:08 ` [patch 4/4] KVM: switch irq injection/acking data structures to irq_lock Marcelo Tosatti
2009-06-08 9:18 ` [patch 0/4] move irq protection role to separate lock v4 Avi Kivity
2009-05-28 4:45 ` [patch 3/4] KVM: introduce irq_lock, use it to protect ioapic Marcelo Tosatti
2009-05-28 4:45 ` [patch 4/4] KVM: switch irq injection/acking data structures to irq_lock Marcelo Tosatti
2009-05-20 18:48 ` Marcelo Tosatti [this message]
2009-05-21 4:50 ` [patch 0/4] move irq protection role to separate lock v2 Marcelo Tosatti
2009-05-21 6:55 ` Christian Bornträger
2009-05-21 7:26 ` Avi Kivity
2009-05-21 14:32 ` Marcelo Tosatti
2009-05-21 15:02 ` Avi Kivity
2009-05-18 16:56 ` [patch 3/4] KVM: introduce irq_lock, use it protect ioapic Marcelo Tosatti
2009-05-20 12:11 ` Avi Kivity
2009-05-20 14:11 ` Marcelo Tosatti
2009-05-20 14:29 ` Avi Kivity
2009-05-18 16:56 ` [patch 4/4] KVM: switch irq injection/acking to irq_lock Marcelo Tosatti
2009-05-20 12:15 ` Gregory Haskins
2009-05-20 14:16 ` Marcelo Tosatti
2009-05-24 14:53 ` Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090520185134.875726533@localhost.localdomain \
--to=mtosatti@redhat.com \
--cc=avi@redhat.com \
--cc=gregory.haskins@gmail.com \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.