aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2009-10-29 11:44:15 -0400
committerAvi Kivity <avi@redhat.com>2009-12-03 02:32:23 -0500
commit3ddea128ad75bd33e88780fe44f44c3717369b98 (patch)
treedbf54798bda23cb8c105c6fc3926d30bae3c6321 /arch/x86
parent92c0d900159a4fa582e1c8ebcc1c4a8020defff5 (diff)
KVM: x86: disallow multiple KVM_CREATE_IRQCHIP
Otherwise kvm will leak memory on multiple KVM_CREATE_IRQCHIP. Also serialize multiple accesses with kvm->lock. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kvm/irq.h6
-rw-r--r--arch/x86/kvm/x86.c30
2 files changed, 27 insertions, 9 deletions
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index c025a2362aae..be399e207d57 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -86,7 +86,11 @@ static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
86 86
87static inline int irqchip_in_kernel(struct kvm *kvm) 87static inline int irqchip_in_kernel(struct kvm *kvm)
88{ 88{
89 return pic_irqchip(kvm) != NULL; 89 int ret;
90
91 ret = (pic_irqchip(kvm) != NULL);
92 smp_rmb();
93 return ret;
90} 94}
91 95
92void kvm_pic_reset(struct kvm_kpic_state *s); 96void kvm_pic_reset(struct kvm_kpic_state *s);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 719f31eecd3d..97f6f9565ac9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2362,25 +2362,39 @@ long kvm_arch_vm_ioctl(struct file *filp,
2362 if (r) 2362 if (r)
2363 goto out; 2363 goto out;
2364 break; 2364 break;
2365 case KVM_CREATE_IRQCHIP: 2365 case KVM_CREATE_IRQCHIP: {
2366 struct kvm_pic *vpic;
2367
2368 mutex_lock(&kvm->lock);
2369 r = -EEXIST;
2370 if (kvm->arch.vpic)
2371 goto create_irqchip_unlock;
2366 r = -ENOMEM; 2372 r = -ENOMEM;
2367 kvm->arch.vpic = kvm_create_pic(kvm); 2373 vpic = kvm_create_pic(kvm);
2368 if (kvm->arch.vpic) { 2374 if (vpic) {
2369 r = kvm_ioapic_init(kvm); 2375 r = kvm_ioapic_init(kvm);
2370 if (r) { 2376 if (r) {
2371 kfree(kvm->arch.vpic); 2377 kfree(vpic);
2372 kvm->arch.vpic = NULL; 2378 goto create_irqchip_unlock;
2373 goto out;
2374 } 2379 }
2375 } else 2380 } else
2376 goto out; 2381 goto create_irqchip_unlock;
2382 smp_wmb();
2383 kvm->arch.vpic = vpic;
2384 smp_wmb();
2377 r = kvm_setup_default_irq_routing(kvm); 2385 r = kvm_setup_default_irq_routing(kvm);
2378 if (r) { 2386 if (r) {
2387 mutex_lock(&kvm->irq_lock);
2379 kfree(kvm->arch.vpic); 2388 kfree(kvm->arch.vpic);
2380 kfree(kvm->arch.vioapic); 2389 kfree(kvm->arch.vioapic);
2381 goto out; 2390 kvm->arch.vpic = NULL;
2391 kvm->arch.vioapic = NULL;
2392 mutex_unlock(&kvm->irq_lock);
2382 } 2393 }
2394 create_irqchip_unlock:
2395 mutex_unlock(&kvm->lock);
2383 break; 2396 break;
2397 }
2384 case KVM_CREATE_PIT: 2398 case KVM_CREATE_PIT:
2385 u.pit_config.flags = KVM_PIT_SPEAKER_DUMMY; 2399 u.pit_config.flags = KVM_PIT_SPEAKER_DUMMY;
2386 goto create_pit; 2400 goto create_pit;