ia64/xen-unstable

changeset 11922:8e8128077259

Workaround for bigsmp APIC mode SMP linux guests - we cannot correctly deal
with timer interrupts being delivered to VCPUs other than 0, so spit a
warning and then subsequently ignore the target. This fixes the recent
issues Intel reported when booting SMP FC5 and FC6 kernels.

Needs a better fix at some point.

Signed-off-by: Steven Hand <steven@xensource.com>
author Steven Hand <steven@xensource.com>
date Fri Oct 20 11:43:14 2006 +0100 (2006-10-20)
parents 59b41031641d
children 1633f9a3a120
files xen/arch/x86/hvm/vioapic.c
line diff
     1.1 --- a/xen/arch/x86/hvm/vioapic.c	Fri Oct 20 11:00:08 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/vioapic.c	Fri Oct 20 11:43:14 2006 +0100
     1.3 @@ -42,6 +42,9 @@
     1.4  
     1.5  /* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */
     1.6  #define IRQ0_SPECIAL_ROUTING 1
     1.7 +#ifdef IRQ0_SPECIAL_ROUTING
     1.8 +static int redir_warning_done = 0; 
     1.9 +#endif
    1.10  
    1.11  #if defined(__ia64__)
    1.12  #define opt_hvm_debug_level opt_vmx_debug_level
    1.13 @@ -155,6 +158,7 @@ static void hvm_vioapic_update_imr(struc
    1.14         clear_bit(index, &s->imr);
    1.15  }
    1.16  
    1.17 +
    1.18  static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
    1.19                                        unsigned long addr,
    1.20                                        unsigned long length,
    1.21 @@ -179,21 +183,35 @@ static void hvm_vioapic_write_indirect(s
    1.22          {
    1.23              uint32_t redir_index = 0;
    1.24  
    1.25 +            redir_index = (s->ioregsel - 0x10) >> 1;
    1.26 +
    1.27              HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_write_indirect "
    1.28                "change redir index %x val %lx\n",
    1.29                redir_index, val);
    1.30  
    1.31 -            redir_index = (s->ioregsel - 0x10) >> 1;
    1.32 -
    1.33              if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
    1.34                  uint64_t redir_content;
    1.35  
    1.36                  redir_content = s->redirtbl[redir_index].value;
    1.37  
    1.38 -                if (s->ioregsel & 0x1)
    1.39 +                if (s->ioregsel & 0x1) {
    1.40 +#ifdef IRQ0_SPECIAL_ROUTING
    1.41 +                    if ( !redir_warning_done && (redir_index == 0) &&
    1.42 +                         ((val >> 24) != 0) ) {
    1.43 +                        /*
    1.44 +                         * Cannot yet handle delivering PIT interrupts to
    1.45 +                         * any VCPU != 0. Needs proper fixing, but for now
    1.46 +                         * simply spit a warning that we're going to ignore
    1.47 +                         * the target in practice & always deliver to VCPU 0
    1.48 +                         */
    1.49 +                        printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
    1.50 +                               "will be ignored.\n", val >> 24); 
    1.51 +                        redir_warning_done = 1;
    1.52 +                    }
    1.53 +#endif
    1.54                      redir_content = (((uint64_t)val & 0xffffffff) << 32) |
    1.55                                      (redir_content & 0xffffffff);
    1.56 -                else
    1.57 +                } else
    1.58                      redir_content = ((redir_content >> 32) << 32) |
    1.59                                      (val & 0xffffffff);
    1.60                  s->redirtbl[redir_index].value = redir_content;
    1.61 @@ -409,6 +427,8 @@ static void ioapic_deliver(hvm_vioapic_t
    1.62      uint8_t vector = s->redirtbl[irqno].RedirForm.vector;
    1.63      uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
    1.64      uint32_t deliver_bitmask;
    1.65 +    struct vlapic *target;
    1.66 +
    1.67  
    1.68      HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
    1.69        "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
    1.70 @@ -427,9 +447,8 @@ static void ioapic_deliver(hvm_vioapic_t
    1.71      switch (delivery_mode) {
    1.72      case dest_LowestPrio:
    1.73      {
    1.74 -        struct vlapic* target;
    1.75 -
    1.76  #ifdef IRQ0_SPECIAL_ROUTING
    1.77 +        /* Force round-robin to pick VCPU 0 */
    1.78          if (irqno == 0)
    1.79              target = s->lapic_info[0];
    1.80          else
    1.81 @@ -450,19 +469,17 @@ static void ioapic_deliver(hvm_vioapic_t
    1.82      {
    1.83          uint8_t bit;
    1.84          for (bit = 0; bit < s->lapic_count; bit++) {
    1.85 -            if (deliver_bitmask & (1 << bit)) {
    1.86 +            if ( !(deliver_bitmask & (1 << bit)) )
    1.87 +                continue;
    1.88  #ifdef IRQ0_SPECIAL_ROUTING
    1.89 -                if ( (irqno == 0) && (bit !=0) )
    1.90 -                {
    1.91 -                    printk("PIT irq to bit %x\n", bit);
    1.92 -                    domain_crash_synchronous();
    1.93 -                }
    1.94 +            /* Do not deliver timer interrupts to VCPU != 0 */
    1.95 +            if ( (irqno == 0) && (bit !=0 ) )
    1.96 +                target = s->lapic_info[0];
    1.97 +            else
    1.98  #endif
    1.99 -                if (s->lapic_info[bit]) {
   1.100 -                    ioapic_inj_irq(s, s->lapic_info[bit],
   1.101 -                                vector, trig_mode, delivery_mode);
   1.102 -                }
   1.103 -            }
   1.104 +                target = s->lapic_info[bit];
   1.105 +            if (target)
   1.106 +                ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
   1.107          }
   1.108          break;
   1.109      }