ia64/xen-unstable

changeset 19039:59274c49a029

x86: restore ability to work on systems without APIC

This got broken with the default-enabling of MSI. Apart from fixing
the base issue, the patch also addresses
- the 'i' command crashing where there is no IO-APIC,
- the 'i' command needlessly printing information for all 256 vectors
when the use of IO-APIC(s) is disabled, and
- the need to specify both "nolapic" and "noapic" when "nolapic" alone
should already have the intended effect.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 14 10:55:40 2009 +0000 (2009-01-14)
parents cc542ebe4853
children 3fb43f23f64c
files xen/arch/x86/apic.c xen/arch/x86/cpu/common.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/physdev.c xen/include/asm-x86/irq.h xen/include/asm-x86/processor.h
line diff
     1.1 --- a/xen/arch/x86/apic.c	Wed Jan 14 10:52:39 2009 +0000
     1.2 +++ b/xen/arch/x86/apic.c	Wed Jan 14 10:55:40 2009 +0000
     1.3 @@ -40,7 +40,7 @@
     1.4  /*
     1.5   * Knob to control our willingness to enable the local APIC.
     1.6   */
     1.7 -int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
     1.8 +static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
     1.9  
    1.10  /*
    1.11   * Debug level
    1.12 @@ -742,7 +742,7 @@ static void apic_pm_activate(void)
    1.13  static void __init lapic_disable(char *str)
    1.14  {
    1.15      enable_local_apic = -1;
    1.16 -    clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
    1.17 +    setup_clear_cpu_cap(X86_FEATURE_APIC);
    1.18  }
    1.19  custom_param("nolapic", lapic_disable);
    1.20  
     2.1 --- a/xen/arch/x86/cpu/common.c	Wed Jan 14 10:52:39 2009 +0000
     2.2 +++ b/xen/arch/x86/cpu/common.c	Wed Jan 14 10:55:40 2009 +0000
     2.3 @@ -29,6 +29,14 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM
     2.4   */
     2.5  u64 host_pat = 0x050100070406;
     2.6  
     2.7 +static unsigned int __cpuinitdata cleared_caps[NCAPINTS];
     2.8 +
     2.9 +void __init setup_clear_cpu_cap(unsigned int cap)
    2.10 +{
    2.11 +	__clear_bit(cap, boot_cpu_data.x86_capability);
    2.12 +	__set_bit(cap, cleared_caps);
    2.13 +}
    2.14 +
    2.15  static void default_init(struct cpuinfo_x86 * c)
    2.16  {
    2.17  	/* Not much we can do here... */
    2.18 @@ -235,6 +243,7 @@ static void __init early_cpu_detect(void
    2.19  		if (c->x86 >= 0x6)
    2.20  			c->x86_model += ((tfms >> 16) & 0xF) << 4;
    2.21  		c->x86_mask = tfms & 15;
    2.22 +		cap0 &= ~cleared_caps[0];
    2.23  		if (cap0 & (1<<19))
    2.24  			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
    2.25  		c->x86_capability[0] = cap0; /* Added for Xen bootstrap */
    2.26 @@ -395,6 +404,9 @@ void __cpuinit identify_cpu(struct cpuin
    2.27  	if (disable_pse)
    2.28  		clear_bit(X86_FEATURE_PSE, c->x86_capability);
    2.29  
    2.30 +	for (i = 0 ; i < NCAPINTS ; ++i)
    2.31 +		c->x86_capability[i] &= ~cleared_caps[i];
    2.32 +
    2.33  	/* If the model name is still unset, do table lookup. */
    2.34  	if ( !c->x86_model_id[0] ) {
    2.35  		char *p;
     3.1 --- a/xen/arch/x86/io_apic.c	Wed Jan 14 10:52:39 2009 +0000
     3.2 +++ b/xen/arch/x86/io_apic.c	Wed Jan 14 10:55:40 2009 +0000
     3.3 @@ -84,7 +84,9 @@ int disable_timer_pin_1 __initdata;
     3.4  
     3.5  static struct irq_pin_list {
     3.6      int apic, pin, next;
     3.7 -} irq_2_pin[PIN_MAP_SIZE];
     3.8 +} irq_2_pin[PIN_MAP_SIZE] = {
     3.9 +    [0 ... PIN_MAP_SIZE-1].pin = -1
    3.10 +};
    3.11  static int irq_2_pin_free_entry = NR_IRQS;
    3.12  
    3.13  int vector_irq[NR_VECTORS] __read_mostly = {
    3.14 @@ -1018,11 +1020,6 @@ static void __init enable_IO_APIC(void)
    3.15      int i, apic;
    3.16      unsigned long flags;
    3.17  
    3.18 -    for (i = 0; i < PIN_MAP_SIZE; i++) {
    3.19 -        irq_2_pin[i].pin = -1;
    3.20 -        irq_2_pin[i].next = 0;
    3.21 -    }
    3.22 -
    3.23      /* Initialise dynamic irq_2_pin free list. */
    3.24      for (i = NR_IRQS; i < PIN_MAP_SIZE; i++)
    3.25          irq_2_pin[i].next = i + 1;
     4.1 --- a/xen/arch/x86/irq.c	Wed Jan 14 10:52:39 2009 +0000
     4.2 +++ b/xen/arch/x86/irq.c	Wed Jan 14 10:55:40 2009 +0000
     4.3 @@ -867,8 +867,8 @@ int map_domain_pirq(
     4.4          return -EINVAL;
     4.5      }
     4.6  
     4.7 -    old_vector = d->arch.pirq_vector[pirq];
     4.8 -    old_pirq = d->arch.vector_pirq[vector];
     4.9 +    old_vector = domain_irq_to_vector(d, pirq);
    4.10 +    old_pirq = domain_vector_to_irq(d, vector);
    4.11  
    4.12      if ( (old_vector && (old_vector != vector) ) ||
    4.13           (old_pirq && (old_pirq != pirq)) )
    4.14 @@ -892,6 +892,10 @@ int map_domain_pirq(
    4.15      {
    4.16          struct msi_info *msi = (struct msi_info *)data;
    4.17  
    4.18 +        ret = -ENODEV;
    4.19 +        if ( !cpu_has_apic )
    4.20 +            goto done;
    4.21 +
    4.22          pdev = pci_get_pdev(msi->bus, msi->devfn);
    4.23          ret = pci_enable_msi(msi, &msi_desc);
    4.24          if ( ret )
    4.25 @@ -937,7 +941,7 @@ int unmap_domain_pirq(struct domain *d, 
    4.26      ASSERT(spin_is_locked(&pcidevs_lock));
    4.27      ASSERT(spin_is_locked(&d->event_lock));
    4.28  
    4.29 -    vector = d->arch.pirq_vector[pirq];
    4.30 +    vector = domain_irq_to_vector(d, pirq);
    4.31      if ( vector <= 0 )
    4.32      {
    4.33          dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n",
    4.34 @@ -958,7 +962,7 @@ int unmap_domain_pirq(struct domain *d, 
    4.35  
    4.36      spin_lock_irqsave(&desc->lock, flags);
    4.37  
    4.38 -    BUG_ON(vector != d->arch.pirq_vector[pirq]);
    4.39 +    BUG_ON(vector != domain_irq_to_vector(d, pirq));
    4.40  
    4.41      if ( msi_desc )
    4.42          teardown_msi_vector(vector);
     5.1 --- a/xen/arch/x86/physdev.c	Wed Jan 14 10:52:39 2009 +0000
     5.2 +++ b/xen/arch/x86/physdev.c	Wed Jan 14 10:55:40 2009 +0000
     5.3 @@ -103,14 +103,14 @@ static int physdev_map_pirq(struct physd
     5.4      spin_lock(&pcidevs_lock);
     5.5      /* Verify or get pirq. */
     5.6      spin_lock(&d->event_lock);
     5.7 +    pirq = domain_vector_to_irq(d, vector);
     5.8      if ( map->pirq < 0 )
     5.9      {
    5.10 -        if ( d->arch.vector_pirq[vector] )
    5.11 +        if ( pirq )
    5.12          {
    5.13              dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n",
    5.14                      d->domain_id, map->index, map->pirq,
    5.15 -                    d->arch.vector_pirq[vector]);
    5.16 -            pirq = d->arch.vector_pirq[vector];
    5.17 +                    pirq);
    5.18              if ( pirq < 0 )
    5.19              {
    5.20                  ret = -EBUSY;
    5.21 @@ -130,8 +130,7 @@ static int physdev_map_pirq(struct physd
    5.22      }
    5.23      else
    5.24      {
    5.25 -        if ( d->arch.vector_pirq[vector] &&
    5.26 -             d->arch.vector_pirq[vector] != map->pirq )
    5.27 +        if ( pirq && pirq != map->pirq )
    5.28          {
    5.29              dprintk(XENLOG_G_ERR, "dom%d: vector %d conflicts with irq %d\n",
    5.30                      d->domain_id, map->index, map->pirq);
     6.1 --- a/xen/include/asm-x86/irq.h	Wed Jan 14 10:52:39 2009 +0000
     6.2 +++ b/xen/include/asm-x86/irq.h	Wed Jan 14 10:55:40 2009 +0000
     6.3 @@ -61,8 +61,12 @@ int unmap_domain_pirq(struct domain *d, 
     6.4  int get_free_pirq(struct domain *d, int type, int index);
     6.5  void free_domain_pirqs(struct domain *d);
     6.6  
     6.7 -#define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)])
     6.8 -#define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)])
     6.9 +#define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[irq] ?: \
    6.10 +                                      IO_APIC_IRQ(irq) ? 0 : LEGACY_VECTOR(irq))
    6.11 +#define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[vec] ?: \
    6.12 +                                      ((vec) < FIRST_LEGACY_VECTOR || \
    6.13 +                                       (vec) > LAST_LEGACY_VECTOR) ? \
    6.14 +                                      0 : LEGACY_IRQ_FROM_VECTOR(vec))
    6.15  
    6.16  int pirq_guest_force_unbind(struct domain *d, int irq);
    6.17  
     7.1 --- a/xen/include/asm-x86/processor.h	Wed Jan 14 10:52:39 2009 +0000
     7.2 +++ b/xen/include/asm-x86/processor.h	Wed Jan 14 10:55:40 2009 +0000
     7.3 @@ -191,6 +191,7 @@ extern int phys_proc_id[NR_CPUS];
     7.4  extern int cpu_core_id[NR_CPUS];
     7.5  
     7.6  extern void identify_cpu(struct cpuinfo_x86 *);
     7.7 +extern void setup_clear_cpu_cap(unsigned int);
     7.8  extern void print_cpu_info(struct cpuinfo_x86 *);
     7.9  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
    7.10  extern void dodgy_tsc(void);