summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2008-02-25 09:28:31 +0100
committerAvi Kivity <avi@qumranet.com>2008-03-04 14:19:48 +0100
commit8c35f237fb5664d30aa90448c3d6cea0cbb43f35 (patch)
tree1de7e021aff7ac0593ed9307045f6dd4fa771995 /virt
parentKVM: Avoid infinite-frequency local apic timer (diff)
downloadlinux-8c35f237fb5664d30aa90448c3d6cea0cbb43f35.tar.xz
linux-8c35f237fb5664d30aa90448c3d6cea0cbb43f35.zip
KVM: Route irq 0 to vcpu 0 exclusively
Some Linux versions allow the timer interrupt to be processed by more than one cpu, leading to hangs due to tsc instability. Work around the issue by only disaptching the interrupt to vcpu 0. Problem analyzed (and patch tested) by Sheng Yang. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/ioapic.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 317f8e211cd2..4232fd75dd20 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -211,6 +211,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
case IOAPIC_LOWEST_PRIORITY:
vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
deliver_bitmask);
+#ifdef CONFIG_X86
+ if (irq == 0)
+ vcpu = ioapic->kvm->vcpus[0];
+#endif
if (vcpu != NULL)
ioapic_inj_irq(ioapic, vcpu, vector,
trig_mode, delivery_mode);
@@ -220,6 +224,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
break;
case IOAPIC_FIXED:
+#ifdef CONFIG_X86
+ if (irq == 0)
+ deliver_bitmask = 1;
+#endif
for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
if (!(deliver_bitmask & (1 << vcpu_id)))
continue;