[PATCH] FC11: fix rh#491625 (Unable to run RHEL-5 Xen within KVM guest)

Marcelo Tosatti mtosatti at redhat.com
Wed Apr 8 22:00:15 UTC 2009


Following adds a fix for $subject. Please review.

Don't have commit access yet so unable to commit myself.

 TODO                                        |    7 +
 kernel.spec                                 |   15 +++
 linux-2.6-kvm-kconfig-irqchip.patch         |   69 ++++++++++++++++
 linux-2.6-kvm-mask-notifiers.patch          |  117 ++++++++++++++++++++++++++++
 linux-2.6-kvm-reset-pit-irq-on-unmask.patch |   67 ++++++++++++++++
 5 files changed, 275 insertions(+)

-------------- next part --------------
Index: F-11/TODO
===================================================================
--- F-11.orig/TODO
+++ F-11/TODO
@@ -102,3 +102,10 @@
 * linux-2.6.29-pat-fixes.patch:
 	http://bugs.freedesktop.org/show_bug.cgi?id=20803
 	ajax to follow up with jbarnes
+
+* linux-2.6-kvm-kconfig-irqchip.patch
+* linux-2.6-kvm-mask-notifiers.patch
+* linux-2.6-kvm-reset-pit-irq-on-unmask.patch:
+        https://bugzilla.redhat.com/show_bug.cgi?id=491625
+        Queued by Avi, needs to get into linux-2.6-stable.
+
Index: F-11/kernel.spec
===================================================================
--- F-11.orig/kernel.spec
+++ F-11/kernel.spec
@@ -720,6 +720,11 @@ Patch9101: linux-2.6-net-fix-another-gro
 # http://bugs.freedesktop.org/show_bug.cgi?id=20803
 Patch9210: linux-2.6.29-pat-fixes.patch
 
+# kvm fixes
+Patch9300: linux-2.6-kvm-kconfig-irqchip.patch
+Patch9301: linux-2.6-kvm-mask-notifiers.patch
+Patch9302: linux-2.6-kvm-reset-pit-irq-on-unmask.patch
+
 %endif
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1320,6 +1325,10 @@ ApplyPatch linux-2.6-net-fix-another-gro
 
 ApplyPatch linux-2.6.29-pat-fixes.patch
 
+ApplyPatch linux-2.6-kvm-kconfig-irqchip.patch
+ApplyPatch linux-2.6-kvm-mask-notifiers.patch
+ApplyPatch linux-2.6-kvm-reset-pit-irq-on-unmask.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -1905,6 +1914,12 @@ fi
 # and build.
 
 %changelog
+* Wed Apr 08 2009 Marcelo Tosatti <mtosatti at redhat.com>
+- linux-2.6-kvm-kconfig-irqchip.patch
+  linux-2.6-kvm-mask-notifiers.patch
+  linux-2.6-kvm-reset-pit-irq-on-unmask.patch:
+    Fixes PIT bug with Xen on KVM (rh#491625).
+
 * Wed Apr 08 2009 Dave Jones <davej at redhat.com> 2.6.29.1-58
 - disable MMIOTRACE in non-debug builds (#494584)
 
Index: F-11/linux-2.6-kvm-mask-notifiers.patch
===================================================================
--- /dev/null
+++ F-11/linux-2.6-kvm-mask-notifiers.patch
@@ -0,0 +1,117 @@
+b018d32632d3c59d3618e23128e4312fe8e48d64
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index 3cf0ede..99963f3 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -127,6 +127,10 @@ struct kvm {
+ 	struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
+ #endif
+ 
++#ifdef CONFIG_HAVE_KVM_IRQCHIP
++	struct hlist_head mask_notifier_list;
++#endif
++
+ #ifdef KVM_ARCH_WANT_MMU_NOTIFIER
+ 	struct mmu_notifier mmu_notifier;
+ 	unsigned long mmu_notifier_seq;
+@@ -320,6 +324,19 @@ struct kvm_assigned_dev_kernel {
+ 	struct pci_dev *dev;
+ 	struct kvm *kvm;
+ };
++
++struct kvm_irq_mask_notifier {
++	void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked);
++	int irq;
++	struct hlist_node link;
++};
++
++void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
++				    struct kvm_irq_mask_notifier *kimn);
++void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
++				      struct kvm_irq_mask_notifier *kimn);
++void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
++
+ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
+ void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
+ void kvm_register_irq_ack_notifier(struct kvm *kvm,
+diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
+index 23b81cf..e85a2bc 100644
+--- a/virt/kvm/ioapic.c
++++ b/virt/kvm/ioapic.c
+@@ -101,6 +101,7 @@ static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
+ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
+ {
+ 	unsigned index;
++	bool mask_before, mask_after;
+ 
+ 	switch (ioapic->ioregsel) {
+ 	case IOAPIC_REG_VERSION:
+@@ -120,6 +121,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
+ 		ioapic_debug("change redir index %x val %x\n", index, val);
+ 		if (index >= IOAPIC_NUM_PINS)
+ 			return;
++		mask_before = ioapic->redirtbl[index].fields.mask;
+ 		if (ioapic->ioregsel & 1) {
+ 			ioapic->redirtbl[index].bits &= 0xffffffff;
+ 			ioapic->redirtbl[index].bits |= (u64) val << 32;
+@@ -128,6 +130,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
+ 			ioapic->redirtbl[index].bits |= (u32) val;
+ 			ioapic->redirtbl[index].fields.remote_irr = 0;
+ 		}
++		mask_after = ioapic->redirtbl[index].fields.mask;
++		if (mask_before != mask_after)
++			kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
+ 		if (ioapic->irr & (1 << index))
+ 			ioapic_service(ioapic, index);
+ 		break;
+@@ -426,3 +431,4 @@ int kvm_ioapic_init(struct kvm *kvm)
+ 	kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev);
+ 	return 0;
+ }
++
+diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
+index aa5d1e5..5162a41 100644
+--- a/virt/kvm/irq_comm.c
++++ b/virt/kvm/irq_comm.c
+@@ -99,3 +99,27 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)
+ 		clear_bit(irq_source_id, &kvm->arch.irq_states[i]);
+ 	clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
+ }
++
++void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
++				    struct kvm_irq_mask_notifier *kimn)
++{
++	kimn->irq = irq;
++	hlist_add_head(&kimn->link, &kvm->mask_notifier_list);
++}
++
++void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
++				      struct kvm_irq_mask_notifier *kimn)
++{
++	hlist_del(&kimn->link);
++}
++
++void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask)
++{
++	struct kvm_irq_mask_notifier *kimn;
++	struct hlist_node *n;
++
++	hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link)
++		if (kimn->irq == irq)
++			kimn->func(kimn, mask);
++}
++
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index dcbfc68..785c1e3 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -831,6 +831,9 @@ static struct kvm *kvm_create_vm(void)
+ 
+ 	if (IS_ERR(kvm))
+ 		goto out;
++#ifdef CONFIG_HAVE_KVM_IRQCHIP
++	INIT_HLIST_HEAD(&kvm->mask_notifier_list);
++#endif
+ 
+ #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
+ 	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
Index: F-11/linux-2.6-kvm-reset-pit-irq-on-unmask.patch
===================================================================
--- /dev/null
+++ F-11/linux-2.6-kvm-reset-pit-irq-on-unmask.patch
@@ -0,0 +1,67 @@
+commit 4780c65904f0fc4e312ee2da9383eacbe04e61ea
+Author: Avi Kivity <avi at redhat.com>
+Date:   Sun Jan 4 18:06:06 2009 +0200
+
+    KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked
+    
+    While the PIT is masked the guest cannot ack the irq, so the reinject logic
+    will never allow the interrupt to be injected.
+    
+    Fix by resetting the reinjection counters on unmask.
+    
+    Unbreaks Xen.
+    
+    Signed-off-by: Avi Kivity <avi at redhat.com>
+
+diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
+index 69d1bbf..c13bb92 100644
+--- a/arch/x86/kvm/i8254.c
++++ b/arch/x86/kvm/i8254.c
+@@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit)
+ 	pit->pit_state.irq_ack = 1;
+ }
+ 
++static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
++{
++	struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier);
++
++	if (!mask) {
++		atomic_set(&pit->pit_state.pit_timer.pending, 0);
++		pit->pit_state.irq_ack = 1;
++	}
++}
++
+ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+ {
+ 	struct kvm_pit *pit;
+@@ -586,6 +596,9 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+ 
+ 	kvm_pit_reset(pit);
+ 
++	pit->mask_notifier.func = pit_mask_notifer;
++	kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
++
+ 	return pit;
+ }
+ 
+@@ -594,6 +607,8 @@ void kvm_free_pit(struct kvm *kvm)
+ 	struct hrtimer *timer;
+ 
+ 	if (kvm->arch.vpit) {
++		kvm_unregister_irq_mask_notifier(kvm, 0,
++					       &kvm->arch.vpit->mask_notifier);
+ 		mutex_lock(&kvm->arch.vpit->pit_state.lock);
+ 		timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
+ 		hrtimer_cancel(timer);
+diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
+index 76959c4..6acbe4b 100644
+--- a/arch/x86/kvm/i8254.h
++++ b/arch/x86/kvm/i8254.h
+@@ -46,6 +46,7 @@ struct kvm_pit {
+ 	struct kvm *kvm;
+ 	struct kvm_kpit_state pit_state;
+ 	int irq_source_id;
++	struct kvm_irq_mask_notifier mask_notifier;
+ };
+ 
+ #define KVM_PIT_BASE_ADDRESS	    0x40
Index: F-11/linux-2.6-kvm-kconfig-irqchip.patch
===================================================================
--- /dev/null
+++ F-11/linux-2.6-kvm-kconfig-irqchip.patch
@@ -0,0 +1,69 @@
+commit 1dae8e15bb85de0116ed43cd3d798a035044954c
+Author: Avi Kivity <avi at redhat.com>
+Date:   Sun Jan 4 18:04:18 2009 +0200
+
+    KVM: Add CONFIG_HAVE_KVM_IRQCHIP
+    
+    Two KVM archs support irqchips and two don't.  Add a Kconfig item to
+    make selecting between the two models easier.
+    
+    Signed-off-by: Avi Kivity <avi at redhat.com>
+
+diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
+index f833a0b..0a2d6b8 100644
+--- a/arch/ia64/kvm/Kconfig
++++ b/arch/ia64/kvm/Kconfig
+@@ -4,6 +4,10 @@
+ config HAVE_KVM
+ 	bool
+ 
++config HAVE_KVM_IRQCHIP
++       bool
++       default y
++
+ menuconfig VIRTUALIZATION
+ 	bool "Virtualization"
+ 	depends on HAVE_KVM || IA64
+diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
+index 1465705..5a152a5 100644
+--- a/arch/powerpc/kvm/Kconfig
++++ b/arch/powerpc/kvm/Kconfig
+@@ -2,6 +2,9 @@
+ # KVM configuration
+ #
+ 
++config HAVE_KVM_IRQCHIP
++       bool
++
+ menuconfig VIRTUALIZATION
+ 	bool "Virtualization"
+ 	---help---
+diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
+index e051cad..3e260b7 100644
+--- a/arch/s390/kvm/Kconfig
++++ b/arch/s390/kvm/Kconfig
+@@ -4,6 +4,9 @@
+ config HAVE_KVM
+        bool
+ 
++config HAVE_KVM_IRQCHIP
++       bool
++
+ menuconfig VIRTUALIZATION
+ 	bool "Virtualization"
+ 	default y
+diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
+index b81125f..0a303c3 100644
+--- a/arch/x86/kvm/Kconfig
++++ b/arch/x86/kvm/Kconfig
+@@ -4,6 +4,10 @@
+ config HAVE_KVM
+        bool
+ 
++config HAVE_KVM_IRQCHIP
++       bool
++       default y
++
+ menuconfig VIRTUALIZATION
+ 	bool "Virtualization"
+ 	depends on HAVE_KVM || X86


More information about the Fedora-kernel-list mailing list