[HVM] Fix timer interrupt delivery on x64 Vista.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 10:08:38 +0000 (10:08 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 10:08:38 +0000 (10:08 +0000)
x64 SMP Vista HVM guest uses HPET as the main system timer, and it
uses physical destination mode with broadcast to deliver the interrupts
generated by HPET. In current code, timer interrupts are injected only
to VCPU0 in vioapic.c, but this doesn't satisfy x64 SMP Vista -- when
it boots, it complains "a clock interrupt was not received on a
secondary processor within the allocated time interval" with Bug Check
0x101.

Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
xen/arch/x86/domain.c
xen/arch/x86/hvm/vioapic.c

index b03824f5ca39992fcd64b30f6c2eb52fdd62f96e..e23c85bbaa90a2905ef860a20eb2210caca9c8bd 100644 (file)
@@ -1047,7 +1047,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
 
     local_irq_disable();
 
-    if ( is_hvm_vcpu(prev) )
+    if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) )
         pt_freeze_time(prev);
 
     set_current(next);
index 843c76a6ddc314a1ade265e43911349ea8f6d653..6f68a85b77d2f74f48d1f8f5f21d39f9315054cd 100644 (file)
@@ -309,6 +309,13 @@ static uint32_t ioapic_get_delivery_bitmask(
     return mask;
 }
 
+static inline int pit_channel0_enabled(void)
+{
+    PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
+    struct periodic_time *pt = &pit->channels[0].pt;
+    return pt->enabled;
+}
+
 static void vioapic_deliver(struct vioapic *vioapic, int irq)
 {
     uint16_t dest = vioapic->redirtbl[irq].fields.dest_id;
@@ -341,7 +348,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
     {
 #ifdef IRQ0_SPECIAL_ROUTING
         /* Force round-robin to pick VCPU 0 */
-        if ( irq == hvm_isa_irq_to_gsi(0) )
+        if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
         {
             v = vioapic_domain(vioapic)->vcpu[0];
             target = v ? vcpu_vlapic(v) : NULL;
@@ -374,7 +381,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
             deliver_bitmask &= ~(1 << bit);
 #ifdef IRQ0_SPECIAL_ROUTING
             /* Do not deliver timer interrupts to VCPU != 0 */
-            if ( irq == hvm_isa_irq_to_gsi(0) )
+            if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
                 v = vioapic_domain(vioapic)->vcpu[0];
             else
 #endif