소스 검색

KVM: cleanup the failure path of KVM_CREATE_IRQCHIP ioctrl

If we fail to init ioapic device or the fail to setup the default irq
routing, the device register by kvm_create_pic() and kvm_ioapic_init()
remain unregister. This patch fixed to do this.

Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Wei Yongjun 15 년 전
부모
커밋
72bb2fcd23
5개의 변경된 파일28개의 추가작업 그리고 4개의 파일을 삭제
  1. 11 0
      arch/x86/kvm/i8259.c
  2. 1 0
      arch/x86/kvm/irq.h
  3. 4 4
      arch/x86/kvm/x86.c
  4. 11 0
      virt/kvm/ioapic.c
  5. 1 0
      virt/kvm/ioapic.h

+ 11 - 0
arch/x86/kvm/i8259.c

@@ -543,3 +543,14 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
 
 
 	return s;
 	return s;
 }
 }
+
+void kvm_destroy_pic(struct kvm *kvm)
+{
+	struct kvm_pic *vpic = kvm->arch.vpic;
+
+	if (vpic) {
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
+		kvm->arch.vpic = NULL;
+		kfree(vpic);
+	}
+}

+ 1 - 0
arch/x86/kvm/irq.h

@@ -75,6 +75,7 @@ struct kvm_pic {
 };
 };
 
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
+void kvm_destroy_pic(struct kvm *kvm);
 int kvm_pic_read_irq(struct kvm *kvm);
 int kvm_pic_read_irq(struct kvm *kvm);
 void kvm_pic_update_irq(struct kvm_pic *s);
 void kvm_pic_update_irq(struct kvm_pic *s);
 void kvm_pic_clear_isr_ack(struct kvm *kvm);
 void kvm_pic_clear_isr_ack(struct kvm *kvm);

+ 4 - 4
arch/x86/kvm/x86.c

@@ -2771,6 +2771,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		if (vpic) {
 		if (vpic) {
 			r = kvm_ioapic_init(kvm);
 			r = kvm_ioapic_init(kvm);
 			if (r) {
 			if (r) {
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev);
 				kfree(vpic);
 				kfree(vpic);
 				goto create_irqchip_unlock;
 				goto create_irqchip_unlock;
 			}
 			}
@@ -2782,10 +2784,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		r = kvm_setup_default_irq_routing(kvm);
 		r = kvm_setup_default_irq_routing(kvm);
 		if (r) {
 		if (r) {
 			mutex_lock(&kvm->irq_lock);
 			mutex_lock(&kvm->irq_lock);
-			kfree(kvm->arch.vpic);
-			kfree(kvm->arch.vioapic);
-			kvm->arch.vpic = NULL;
-			kvm->arch.vioapic = NULL;
+			kvm_ioapic_destroy(kvm);
+			kvm_destroy_pic(kvm);
 			mutex_unlock(&kvm->irq_lock);
 			mutex_unlock(&kvm->irq_lock);
 		}
 		}
 	create_irqchip_unlock:
 	create_irqchip_unlock:

+ 11 - 0
virt/kvm/ioapic.c

@@ -401,6 +401,17 @@ int kvm_ioapic_init(struct kvm *kvm)
 	return ret;
 	return ret;
 }
 }
 
 
+void kvm_ioapic_destroy(struct kvm *kvm)
+{
+	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+
+	if (ioapic) {
+		kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &ioapic->dev);
+		kvm->arch.vioapic = NULL;
+		kfree(ioapic);
+	}
+}
+
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
 {
 {
 	struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
 	struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);

+ 1 - 0
virt/kvm/ioapic.h

@@ -72,6 +72,7 @@ int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
 int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
 int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
 int kvm_ioapic_init(struct kvm *kvm);
 int kvm_ioapic_init(struct kvm *kvm);
+void kvm_ioapic_destroy(struct kvm *kvm);
 int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
 int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
 void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
 void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,