* [PATCH 0/3] Fix racy in kvm_free_assigned_irq
@ 2008-12-30 12:13 Sheng Yang
2008-12-30 12:13 ` [PATCH 1/3] KVM: Remove duplicated prototype of kvm_arch_destroy_vm Sheng Yang
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Sheng Yang @ 2008-12-30 12:13 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] KVM: Remove duplicated prototype of kvm_arch_destroy_vm
2008-12-30 12:13 [PATCH 0/3] Fix racy in kvm_free_assigned_irq Sheng Yang
@ 2008-12-30 12:13 ` Sheng Yang
2008-12-30 12:13 ` [PATCH 2/3] KVM: Add kvm_arch_sync_events to sync with asynchronize events Sheng Yang
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Sheng Yang @ 2008-12-30 12:13 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_host.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index d63e9a4..76cc371 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -237,7 +237,6 @@ int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
int user_alloc);
long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg);
-void kvm_arch_destroy_vm(struct kvm *kvm);
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
--
1.5.4.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] KVM: Add kvm_arch_sync_events to sync with asynchronize events
2008-12-30 12:13 [PATCH 0/3] Fix racy in kvm_free_assigned_irq Sheng Yang
2008-12-30 12:13 ` [PATCH 1/3] KVM: Remove duplicated prototype of kvm_arch_destroy_vm Sheng Yang
@ 2008-12-30 12:13 ` Sheng Yang
2008-12-30 12:13 ` [PATCH 3/3] KVM: Fix racy in kvm_free_assigned_irq Sheng Yang
2008-12-30 12:25 ` [PATCH 0/3] " Avi Kivity
3 siblings, 0 replies; 5+ messages in thread
From: Sheng Yang @ 2008-12-30 12:13 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
kvm_arch_sync_events is introduced to quiet down all other events may happen
contemporary with VM destroy process, like IRQ handler and work struct for
assigned device.
For kvm_arch_sync_events is called at the very beginning of kvm_destroy_vm(), so
the state of KVM here is legal and can provide a environment to quiet down other
events.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
arch/ia64/kvm/kvm-ia64.c | 4 ++++
arch/powerpc/kvm/powerpc.c | 4 ++++
arch/s390/kvm/kvm-s390.c | 4 ++++
arch/x86/kvm/x86.c | 4 ++++
include/linux/kvm_host.h | 1 +
virt/kvm/kvm_main.c | 1 +
6 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index c2bf538..8e0af13 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1336,6 +1336,10 @@ static void kvm_release_vm_pages(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_iommu_unmap_guest(kvm);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 74b576a..26b1ae6 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -124,6 +124,10 @@ static void kvmppc_free_vcpus(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvmppc_free_vcpus(kvm);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 54b6534..cbfe91e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -212,6 +212,10 @@ static void kvm_free_vcpus(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_free_vcpus(kvm);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8ea3c7b..0a045fc 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4192,6 +4192,10 @@ static void kvm_free_vcpus(struct kvm *kvm)
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_free_all_assigned_devices(kvm);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 76cc371..04a2a47 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -284,6 +284,7 @@ void kvm_free_physmem(struct kvm *kvm);
struct kvm *kvm_arch_create_vm(void);
void kvm_arch_destroy_vm(struct kvm *kvm);
void kvm_free_all_assigned_devices(struct kvm *kvm);
+void kvm_arch_sync_events(struct kvm *kvm);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index ffd261d..d348788 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -848,6 +848,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
{
struct mm_struct *mm = kvm->mm;
+ kvm_arch_sync_events(kvm);
spin_lock(&kvm_lock);
list_del(&kvm->vm_list);
spin_unlock(&kvm_lock);
--
1.5.4.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] KVM: Fix racy in kvm_free_assigned_irq
2008-12-30 12:13 [PATCH 0/3] Fix racy in kvm_free_assigned_irq Sheng Yang
2008-12-30 12:13 ` [PATCH 1/3] KVM: Remove duplicated prototype of kvm_arch_destroy_vm Sheng Yang
2008-12-30 12:13 ` [PATCH 2/3] KVM: Add kvm_arch_sync_events to sync with asynchronize events Sheng Yang
@ 2008-12-30 12:13 ` Sheng Yang
2008-12-30 12:25 ` [PATCH 0/3] " Avi Kivity
3 siblings, 0 replies; 5+ messages in thread
From: Sheng Yang @ 2008-12-30 12:13 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
In the past, kvm_get_kvm() and kvm_put_kvm() was called in assigned device irq
handler and interrupt_work, in order to prevent cancel_work_sync() in
kvm_free_assigned_irq got a illegal state when waiting for interrupt_work done.
But it's tricky and still got two problems:
1. A bug ignored two conditions that cancel_work_sync() would return true result
in a additional kvm_put_kvm().
2. If interrupt type is MSI, we would got a window between cancel_work_sync()
and free_irq(), which interrupt would be injected again...
This patch discard the reference count used for irq handler and interrupt_work,
and ensure the legal state by moving the free function at the very beginning of
kvm_destroy_vm(). And the patch fix the second bug by disable irq before
cancel_work_sync(), which may result in nested disable of irq but OK for we are
going to free it.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
arch/x86/kvm/x86.c | 2 +-
virt/kvm/kvm_main.c | 26 ++++++++++++++++++--------
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0a045fc..56418ad 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4194,11 +4194,11 @@ static void kvm_free_vcpus(struct kvm *kvm)
void kvm_arch_sync_events(struct kvm *kvm)
{
+ kvm_free_all_assigned_devices(kvm);
}
void kvm_arch_destroy_vm(struct kvm *kvm)
{
- kvm_free_all_assigned_devices(kvm);
kvm_iommu_unmap_guest(kvm);
kvm_free_pit(kvm);
kfree(kvm->arch.vpic);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d348788..fc014b8 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -173,7 +173,6 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
assigned_dev->host_irq_disabled = false;
}
mutex_unlock(&assigned_dev->kvm->lock);
- kvm_put_kvm(assigned_dev->kvm);
}
static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
@@ -181,8 +180,6 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
struct kvm_assigned_dev_kernel *assigned_dev =
(struct kvm_assigned_dev_kernel *) dev_id;
- kvm_get_kvm(assigned_dev->kvm);
-
schedule_work(&assigned_dev->interrupt_work);
disable_irq_nosync(irq);
@@ -228,11 +225,24 @@ static void kvm_free_assigned_irq(struct kvm *kvm,
if (!assigned_dev->irq_requested_type)
return;
- if (cancel_work_sync(&assigned_dev->interrupt_work))
- /* We had pending work. That means we will have to take
- * care of kvm_put_kvm.
- */
- kvm_put_kvm(kvm);
+ /*
+ * In kvm_free_device_irq, cancel_work_sync return true if:
+ * 1. work is scheduled, and then cancelled.
+ * 2. work callback is executed.
+ *
+ * The first one ensured that the irq is disabled and no more events
+ * would happen. But for the second one, the irq may be enabled (e.g.
+ * for MSI). So we disable irq here to prevent further events.
+ *
+ * Notice this maybe result in nested disable if the interrupt type is
+ * INTx, but it's OK for we are going to free it.
+ *
+ * If this function is a part of VM destroy, please ensure that till
+ * now, the kvm state is still legal for probably we also have to wait
+ * interrupt_work done.
+ */
+ disable_irq_nosync(assigned_dev->host_irq);
+ cancel_work_sync(&assigned_dev->interrupt_work);
free_irq(assigned_dev->host_irq, (void *)assigned_dev);
--
1.5.4.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] Fix racy in kvm_free_assigned_irq
2008-12-30 12:13 [PATCH 0/3] Fix racy in kvm_free_assigned_irq Sheng Yang
` (2 preceding siblings ...)
2008-12-30 12:13 ` [PATCH 3/3] KVM: Fix racy in kvm_free_assigned_irq Sheng Yang
@ 2008-12-30 12:25 ` Avi Kivity
3 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2008-12-30 12:25 UTC (permalink / raw)
To: Sheng Yang; +Cc: kvm, Marcelo Tosatti
Sheng Yang wrote:
This looks good, but I'll let Marcelo (or any other interested party)
review this as well, since this is tricky stuff.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-12-30 12:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-30 12:13 [PATCH 0/3] Fix racy in kvm_free_assigned_irq Sheng Yang
2008-12-30 12:13 ` [PATCH 1/3] KVM: Remove duplicated prototype of kvm_arch_destroy_vm Sheng Yang
2008-12-30 12:13 ` [PATCH 2/3] KVM: Add kvm_arch_sync_events to sync with asynchronize events Sheng Yang
2008-12-30 12:13 ` [PATCH 3/3] KVM: Fix racy in kvm_free_assigned_irq Sheng Yang
2008-12-30 12:25 ` [PATCH 0/3] " Avi Kivity
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.