ia64/xen-unstable

changeset 19707:07cf79dfb59c

vtd: Fix apic pin to interrupt remapping table index

Originally, it calls xmalloc to set index in
ioapic_rte_to_remap_entry(). When make with debug=y, it may trigger
spinlock BUG_ON because allocate memory with interrupt disabled.

Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 03 12:59:44 2009 +0100 (2009-06-03)
parents 49e8816db57a
children c4b048ce6a4b
files xen/drivers/passthrough/vtd/intremap.c
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/intremap.c	Wed Jun 03 12:35:25 2009 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/intremap.c	Wed Jun 03 12:59:44 2009 +0100
     1.3 @@ -31,71 +31,40 @@
     1.4  #include "vtd.h"
     1.5  #include "extern.h"
     1.6  
     1.7 -#ifndef dest_SMI
     1.8 +#ifdef __ia64__
     1.9  #define dest_SMI -1
    1.10  #endif
    1.11  
    1.12 -/* The max number of IOAPIC (or IOSAPIC) pin. The typical values can be 24 or
    1.13 - * 48 on x86 and Itanium platforms. Here we use a biger number 256. This
    1.14 - * should be big enough. Actually now IREMAP_ENTRY_NR is also 256.
    1.15 - */
    1.16 -#define MAX_IOAPIC_PIN_NUM  256
    1.17 -
    1.18 -struct ioapicid_pin_intremap_index {
    1.19 -	struct list_head list;
    1.20 -	unsigned int ioapic_id;
    1.21 -	unsigned int pin;
    1.22 -	int intremap_index;
    1.23 -};
    1.24 -
    1.25 -static struct list_head ioapic_pin_to_intremap_index[MAX_IOAPIC_PIN_NUM];
    1.26 -
    1.27 -static int init_ioapic_pin_intremap_index(void)
    1.28 -{
    1.29 -    static int initialized = 0;
    1.30 -    int i;
    1.31 +/* apic_pin_2_ir_idx[apicid][pin] = interrupt remapping table index */
    1.32 +static unsigned int **apic_pin_2_ir_idx;
    1.33  
    1.34 -    if ( initialized == 1 )
    1.35 -        return 0;
    1.36 -
    1.37 -    for ( i = 0; i < MAX_IOAPIC_PIN_NUM; i++ )
    1.38 -        INIT_LIST_HEAD(&ioapic_pin_to_intremap_index[i]);
    1.39 -
    1.40 -    initialized = 1;
    1.41 -    return 0;
    1.42 -}
    1.43 +static int init_apic_pin_2_ir_idx(void)
    1.44 +{
    1.45 +    unsigned int *_apic_pin_2_ir_idx;
    1.46 +    unsigned int nr_pins, i;
    1.47  
    1.48 -static int get_ioapic_pin_intremap_index(unsigned int ioapic_id,
    1.49 -                                         unsigned int pin)
    1.50 -{
    1.51 -    struct ioapicid_pin_intremap_index *entry;
    1.52 -    struct list_head *pos, *tmp;
    1.53 +    nr_pins = 0;
    1.54 +    for ( i = 0; i < nr_ioapics; i++ )
    1.55 +        nr_pins += nr_ioapic_registers[i];
    1.56  
    1.57 -    list_for_each_safe ( pos, tmp, &ioapic_pin_to_intremap_index[pin] )
    1.58 +    _apic_pin_2_ir_idx = xmalloc_array(unsigned int, nr_pins);
    1.59 +    apic_pin_2_ir_idx = xmalloc_array(unsigned int *, nr_ioapics);
    1.60 +    if ( (_apic_pin_2_ir_idx == NULL) || (apic_pin_2_ir_idx == NULL) )
    1.61      {
    1.62 -        entry = list_entry(pos, struct ioapicid_pin_intremap_index, list);
    1.63 -        if ( entry->ioapic_id == ioapic_id )
    1.64 -            return entry->intremap_index;
    1.65 +        xfree(_apic_pin_2_ir_idx);
    1.66 +        xfree(apic_pin_2_ir_idx);
    1.67 +        return -ENOMEM;
    1.68      }
    1.69  
    1.70 -    return -1;
    1.71 -}
    1.72 -
    1.73 -static int set_ioapic_pin_intremap_index(unsigned int ioapic_id,
    1.74 -                                         unsigned int pin,
    1.75 -                                         int index)
    1.76 -{
    1.77 -    struct ioapicid_pin_intremap_index *entry;
    1.78 +    for ( i = 0; i < nr_pins; i++ )
    1.79 +        _apic_pin_2_ir_idx[i] = -1;
    1.80  
    1.81 -    entry = xmalloc(struct ioapicid_pin_intremap_index);
    1.82 -    if ( !entry )
    1.83 -        return -ENOMEM;
    1.84 -
    1.85 -    entry->ioapic_id = ioapic_id;
    1.86 -    entry->pin = pin;
    1.87 -    entry->intremap_index = index;
    1.88 -
    1.89 -    list_add_tail(&entry->list, &ioapic_pin_to_intremap_index[pin]);
    1.90 +    nr_pins = 0;
    1.91 +    for ( i = 0; i < nr_ioapics; i++ )
    1.92 +    {
    1.93 +        apic_pin_2_ir_idx[i] = &_apic_pin_2_ir_idx[nr_pins];
    1.94 +        nr_pins += nr_ioapic_registers[i];
    1.95 +    }
    1.96  
    1.97      return 0;
    1.98  }
    1.99 @@ -160,7 +129,7 @@ static int remap_entry_to_ioapic_rte(
   1.100  }
   1.101  
   1.102  static int ioapic_rte_to_remap_entry(struct iommu *iommu,
   1.103 -    int apic_id, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte,
   1.104 +    int apic, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte,
   1.105      unsigned int rte_upper, unsigned int value)
   1.106  {
   1.107      struct iremap_entry *iremap_entry = NULL, *iremap_entries;
   1.108 @@ -174,12 +143,12 @@ static int ioapic_rte_to_remap_entry(str
   1.109      remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
   1.110      spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
   1.111  
   1.112 -    index = get_ioapic_pin_intremap_index(apic_id, ioapic_pin);
   1.113 +    index = apic_pin_2_ir_idx[apic][ioapic_pin];
   1.114      if ( index < 0 )
   1.115      {
   1.116          ir_ctrl->iremap_index++;
   1.117          index = ir_ctrl->iremap_index;
   1.118 -        set_ioapic_pin_intremap_index(apic_id, ioapic_pin, index);
   1.119 +        apic_pin_2_ir_idx[apic][ioapic_pin] = index;
   1.120      }
   1.121  
   1.122      if ( index > IREMAP_ENTRY_NR - 1 )
   1.123 @@ -218,7 +187,7 @@ static int ioapic_rte_to_remap_entry(str
   1.124          new_ire.lo.res_1 = 0;
   1.125          new_ire.lo.vector = new_rte.vector;
   1.126          new_ire.lo.res_2 = 0;
   1.127 -        new_ire.hi.sid = apicid_to_bdf(apic_id);
   1.128 +        new_ire.hi.sid = apicid_to_bdf(IO_APIC_ID(apic));
   1.129  
   1.130          new_ire.hi.sq = 0;    /* comparing all 16-bit of SID */
   1.131          new_ire.hi.svt = 1;   /* requestor ID verification SID/SQ */
   1.132 @@ -356,8 +325,7 @@ void io_apic_write_remap_rte(
   1.133      *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);
   1.134      remap_rte->mask = saved_mask;
   1.135  
   1.136 -    ASSERT(ioapic_pin < MAX_IOAPIC_PIN_NUM);
   1.137 -    if ( ioapic_rte_to_remap_entry(iommu, IO_APIC_ID(apic), ioapic_pin,
   1.138 +    if ( ioapic_rte_to_remap_entry(iommu, apic, ioapic_pin,
   1.139                                     &old_rte, rte_upper, value) )
   1.140      {
   1.141          *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
   1.142 @@ -628,9 +596,7 @@ int enable_intremap(struct iommu *iommu)
   1.143      /* After set SIRTP, we should do globally invalidate the IEC */
   1.144      iommu_flush_iec_global(iommu);
   1.145  
   1.146 -    init_ioapic_pin_intremap_index();
   1.147 -
   1.148 -    return 0;
   1.149 +    return init_apic_pin_2_ir_idx();
   1.150  }
   1.151  
   1.152  void disable_intremap(struct iommu *iommu)