diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2009-10-29 11:44:15 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:23 -0500 |
commit | 3ddea128ad75bd33e88780fe44f44c3717369b98 (patch) | |
tree | dbf54798bda23cb8c105c6fc3926d30bae3c6321 /arch/x86 | |
parent | 92c0d900159a4fa582e1c8ebcc1c4a8020defff5 (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.h | 6 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 30 |
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 | ||
87 | static inline int irqchip_in_kernel(struct kvm *kvm) | 87 | static 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 | ||
92 | void kvm_pic_reset(struct kvm_kpic_state *s); | 96 | void 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; |