ia64/xen-unstable

changeset 19650:6705898f768d

x86: eliminate hard-coded NR_IRQS

... splitting it into global nr_irqs (determined at boot time) and
per- domain nr_pirqs (derived from nr_irqs and a possibly command line
specified value, which probably should later become a per-domain
config setting).

This has the (desirable imo) side effect of reducing the size of
struct hvm_irq_dpci from requiring an order-3 page to order-2 (on
x86-64), which nevertheless still is too large.

However, there is now a variable size bit array on the stack in
pt_irq_time_out() - while for the moment this probably is okay, it
certainly doesn't look nice. However, replacing this with a static
(pre-)allocation also seems less than ideal, because that would
require at least min(d->nr_pirqs, NR_VECTORS) bit arrays of
d->nr_pirqs bits, since this bit array is used outside of the
serialized code region in that function, and keeping the domain's
event lock acquired across pirq_guest_eoi() doesn't look like a good
idea either.

The IRQ- and vector-indexed arrays hanging off struct hvm_irq_dpci
could in fact be changed further to dynamically use the smaller of the
two ranges for indexing, since there are other assumptions about a
one-to-one relationship between IRQs and vectors here and elsewhere.

Additionally, it seems to me that struct hvm_mirq_dpci_mapping's
digl_list and gmsi fields could really be overlayed, which would yield
significant savings since this structure gets always instanciated in
form of d->nr_pirqs (as per the above could also be the smaller of
this and NR_VECTORS) dimensioned arrays.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed May 27 10:38:51 2009 +0100 (2009-05-27)
parents fcc71d023408
children 822ea2bf0c54
files xen/arch/x86/apic.c xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/i8259.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/physdev.c xen/common/domain.c xen/common/domctl.c xen/common/event_channel.c xen/drivers/passthrough/io.c xen/drivers/passthrough/pci.c xen/drivers/passthrough/vtd/x86/vtd.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/io_apic.h xen/include/asm-x86/irq.h xen/include/xen/hvm/irq.h xen/include/xen/iommu.h xen/include/xen/irq.h xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/apic.c	Wed May 27 08:19:30 2009 +0100
     1.2 +++ b/xen/arch/x86/apic.c	Wed May 27 10:38:51 2009 +0100
     1.3 @@ -890,35 +890,7 @@ void __init init_apic_mappings(void)
     1.4      if (boot_cpu_physical_apicid == -1U)
     1.5          boot_cpu_physical_apicid = get_apic_id();
     1.6  
     1.7 -#ifdef CONFIG_X86_IO_APIC
     1.8 -    {
     1.9 -        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
    1.10 -        int i;
    1.11 -
    1.12 -        for (i = 0; i < nr_ioapics; i++) {
    1.13 -            if (smp_found_config) {
    1.14 -                ioapic_phys = mp_ioapics[i].mpc_apicaddr;
    1.15 -                if (!ioapic_phys) {
    1.16 -                    printk(KERN_ERR
    1.17 -                           "WARNING: bogus zero IO-APIC "
    1.18 -                           "address found in MPTABLE, "
    1.19 -                           "disabling IO/APIC support!\n");
    1.20 -                    smp_found_config = 0;
    1.21 -                    skip_ioapic_setup = 1;
    1.22 -                    goto fake_ioapic_page;
    1.23 -                }
    1.24 -            } else {
    1.25 -fake_ioapic_page:
    1.26 -                ioapic_phys = __pa(alloc_xenheap_page());
    1.27 -                clear_page(__va(ioapic_phys));
    1.28 -            }
    1.29 -            set_fixmap_nocache(idx, ioapic_phys);
    1.30 -            apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n",
    1.31 -                        __fix_to_virt(idx), ioapic_phys);
    1.32 -            idx++;
    1.33 -        }
    1.34 -    }
    1.35 -#endif
    1.36 +    init_ioapic_mappings();
    1.37  }
    1.38  
    1.39  /*****************************************************************************
     2.1 --- a/xen/arch/x86/domain.c	Wed May 27 08:19:30 2009 +0100
     2.2 +++ b/xen/arch/x86/domain.c	Wed May 27 10:38:51 2009 +0100
     2.3 @@ -454,6 +454,12 @@ int arch_domain_create(struct domain *d,
     2.4          share_xen_page_with_guest(
     2.5              virt_to_page(d->shared_info), d, XENSHARE_writable);
     2.6  
     2.7 +        d->arch.pirq_vector = xmalloc_array(s16, d->nr_pirqs);
     2.8 +        if ( !d->arch.pirq_vector )
     2.9 +            goto fail;
    2.10 +        memset(d->arch.pirq_vector, 0,
    2.11 +               d->nr_pirqs * sizeof(*d->arch.pirq_vector));
    2.12 +
    2.13          if ( (rc = iommu_domain_init(d)) != 0 )
    2.14              goto fail;
    2.15  
    2.16 @@ -488,6 +494,7 @@ int arch_domain_create(struct domain *d,
    2.17  
    2.18   fail:
    2.19      d->is_dying = DOMDYING_dead;
    2.20 +    xfree(d->arch.pirq_vector);
    2.21      free_xenheap_page(d->shared_info);
    2.22      if ( paging_initialised )
    2.23          paging_final_teardown(d);
    2.24 @@ -523,6 +530,7 @@ void arch_domain_destroy(struct domain *
    2.25  #endif
    2.26  
    2.27      free_xenheap_page(d->shared_info);
    2.28 +    xfree(d->arch.pirq_vector);
    2.29  }
    2.30  
    2.31  unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4)
     3.1 --- a/xen/arch/x86/domain_build.c	Wed May 27 08:19:30 2009 +0100
     3.2 +++ b/xen/arch/x86/domain_build.c	Wed May 27 10:38:51 2009 +0100
     3.3 @@ -1000,7 +1000,7 @@ int __init construct_dom0(
     3.4      /* DOM0 is permitted full I/O capabilities. */
     3.5      rc |= ioports_permit_access(dom0, 0, 0xFFFF);
     3.6      rc |= iomem_permit_access(dom0, 0UL, ~0UL);
     3.7 -    rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
     3.8 +    rc |= irqs_permit_access(dom0, 0, d->nr_pirqs - 1);
     3.9  
    3.10      /*
    3.11       * Modify I/O port access permissions.
     4.1 --- a/xen/arch/x86/i8259.c	Wed May 27 08:19:30 2009 +0100
     4.2 +++ b/xen/arch/x86/i8259.c	Wed May 27 10:38:51 2009 +0100
     4.3 @@ -403,6 +403,9 @@ void __init init_IRQ(void)
     4.4              set_intr_gate(i, interrupt[i]);
     4.5      }
     4.6  
     4.7 +    irq_vector = xmalloc_array(u8, nr_irqs);
     4.8 +    memset(irq_vector, 0, nr_irqs * sizeof(*irq_vector));
     4.9 +
    4.10      for ( i = 0; i < 16; i++ )
    4.11      {
    4.12          vector_irq[LEGACY_VECTOR(i)] = i;
     5.1 --- a/xen/arch/x86/io_apic.c	Wed May 27 08:19:30 2009 +0100
     5.2 +++ b/xen/arch/x86/io_apic.c	Wed May 27 10:38:51 2009 +0100
     5.3 @@ -71,8 +71,8 @@ int disable_timer_pin_1 __initdata;
     5.4   * Rough estimation of how many shared IRQs there are, can
     5.5   * be changed anytime.
     5.6   */
     5.7 -#define MAX_PLUS_SHARED_IRQS NR_IRQS
     5.8 -#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
     5.9 +#define MAX_PLUS_SHARED_IRQS nr_irqs
    5.10 +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + nr_irqs)
    5.11  
    5.12  /*
    5.13   * This is performance-critical, we want to do it O(1)
    5.14 @@ -82,11 +82,10 @@ int disable_timer_pin_1 __initdata;
    5.15   */
    5.16  
    5.17  static struct irq_pin_list {
    5.18 -    int apic, pin, next;
    5.19 -} irq_2_pin[PIN_MAP_SIZE] = {
    5.20 -    [0 ... PIN_MAP_SIZE-1].pin = -1
    5.21 -};
    5.22 -static int irq_2_pin_free_entry = NR_IRQS;
    5.23 +    int apic, pin;
    5.24 +    unsigned int next;
    5.25 +} *irq_2_pin;
    5.26 +static unsigned int irq_2_pin_free_entry;
    5.27  
    5.28  /*
    5.29   * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
    5.30 @@ -663,7 +662,7 @@ static inline int IO_APIC_irq_trigger(in
    5.31  }
    5.32  
    5.33  /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
    5.34 -u8 irq_vector[NR_IRQS] __read_mostly;
    5.35 +u8 *irq_vector __read_mostly = (u8 *)(1UL << (BITS_PER_LONG - 1));
    5.36  
    5.37  static struct hw_interrupt_type ioapic_level_type;
    5.38  static struct hw_interrupt_type ioapic_edge_type;
    5.39 @@ -929,7 +928,7 @@ void /*__init*/ __print_IO_APIC(void)
    5.40      }
    5.41      printk(KERN_INFO "Using vector-based indexing\n");
    5.42      printk(KERN_DEBUG "IRQ to pin mappings:\n");
    5.43 -    for (i = 0; i < NR_IRQS; i++) {
    5.44 +    for (i = 0; i < nr_irqs; i++) {
    5.45          struct irq_pin_list *entry = irq_2_pin + i;
    5.46          if (entry->pin < 0)
    5.47              continue;
    5.48 @@ -961,24 +960,16 @@ void print_IO_APIC_keyhandler(unsigned c
    5.49  
    5.50  static void __init enable_IO_APIC(void)
    5.51  {
    5.52 -    union IO_APIC_reg_01 reg_01;
    5.53      int i8259_apic, i8259_pin;
    5.54      int i, apic;
    5.55      unsigned long flags;
    5.56  
    5.57      /* Initialise dynamic irq_2_pin free list. */
    5.58 -    for (i = NR_IRQS; i < PIN_MAP_SIZE; i++)
    5.59 +    irq_2_pin = xmalloc_array(struct irq_pin_list, PIN_MAP_SIZE);
    5.60 +    memset(irq_2_pin, 0, nr_irqs * sizeof(*irq_2_pin));
    5.61 +    for (i = irq_2_pin_free_entry = nr_irqs; i < PIN_MAP_SIZE; i++)
    5.62          irq_2_pin[i].next = i + 1;
    5.63  
    5.64 -    /*
    5.65 -     * The number of IO-APIC IRQ registers (== #pins):
    5.66 -     */
    5.67 -    for (apic = 0; apic < nr_ioapics; apic++) {
    5.68 -        spin_lock_irqsave(&ioapic_lock, flags);
    5.69 -        reg_01.raw = io_apic_read(apic, 1);
    5.70 -        spin_unlock_irqrestore(&ioapic_lock, flags);
    5.71 -        nr_ioapic_registers[apic] = reg_01.bits.entries+1;
    5.72 -    }
    5.73      for(apic = 0; apic < nr_ioapics; apic++) {
    5.74          int pin;
    5.75          /* See if any of the pins is in ExtINT mode */
    5.76 @@ -2174,7 +2165,7 @@ void dump_ioapic_irq_info(void)
    5.77      unsigned int irq, pin, printed = 0;
    5.78      unsigned long flags;
    5.79  
    5.80 -    for ( irq = 0; irq < NR_IRQS; irq++ )
    5.81 +    for ( irq = 0; irq < nr_irqs; irq++ )
    5.82      {
    5.83          entry = &irq_2_pin[irq];
    5.84          if ( entry->pin == -1 )
    5.85 @@ -2210,3 +2201,55 @@ void dump_ioapic_irq_info(void)
    5.86          }
    5.87      }
    5.88  }
    5.89 +
    5.90 +void __init init_ioapic_mappings(void)
    5.91 +{
    5.92 +    unsigned long ioapic_phys;
    5.93 +    unsigned int i, idx = FIX_IO_APIC_BASE_0;
    5.94 +    union IO_APIC_reg_01 reg_01;
    5.95 +
    5.96 +    if ( smp_found_config )
    5.97 +        nr_irqs = 0;
    5.98 +    for ( i = 0; i < nr_ioapics; i++ )
    5.99 +    {
   5.100 +        if ( smp_found_config )
   5.101 +        {
   5.102 +            ioapic_phys = mp_ioapics[i].mpc_apicaddr;
   5.103 +            if ( !ioapic_phys )
   5.104 +            {
   5.105 +                printk(KERN_ERR "WARNING: bogus zero IO-APIC address "
   5.106 +                       "found in MPTABLE, disabling IO/APIC support!\n");
   5.107 +                smp_found_config = 0;
   5.108 +                skip_ioapic_setup = 1;
   5.109 +                goto fake_ioapic_page;
   5.110 +            }
   5.111 +        }
   5.112 +        else
   5.113 +        {
   5.114 + fake_ioapic_page:
   5.115 +            ioapic_phys = __pa(alloc_xenheap_page());
   5.116 +            clear_page(__va(ioapic_phys));
   5.117 +        }
   5.118 +        set_fixmap_nocache(idx, ioapic_phys);
   5.119 +        apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n",
   5.120 +                    __fix_to_virt(idx), ioapic_phys);
   5.121 +        idx++;
   5.122 +
   5.123 +        if ( smp_found_config )
   5.124 +        {
   5.125 +            /* The number of IO-APIC IRQ registers (== #pins): */
   5.126 +            reg_01.raw = io_apic_read(i, 1);
   5.127 +            nr_ioapic_registers[i] = reg_01.bits.entries + 1;
   5.128 +            nr_irqs += nr_ioapic_registers[i];
   5.129 +        }
   5.130 +    }
   5.131 +    if ( !smp_found_config || skip_ioapic_setup || nr_irqs < 16 )
   5.132 +        nr_irqs = 16;
   5.133 +    else if ( nr_irqs > PAGE_SIZE * 8 )
   5.134 +    {
   5.135 +        /* for PHYSDEVOP_pirq_eoi_gmfn guest assumptions */
   5.136 +        printk(KERN_WARNING "Limiting number of IRQs found (%u) to %lu\n",
   5.137 +               nr_irqs, PAGE_SIZE * 8);
   5.138 +        nr_irqs = PAGE_SIZE * 8;
   5.139 +    }
   5.140 +}
     6.1 --- a/xen/arch/x86/irq.c	Wed May 27 08:19:30 2009 +0100
     6.2 +++ b/xen/arch/x86/irq.c	Wed May 27 10:38:51 2009 +0100
     6.3 @@ -26,6 +26,7 @@
     6.4  int opt_noirqbalance = 0;
     6.5  boolean_param("noirqbalance", opt_noirqbalance);
     6.6  
     6.7 +unsigned int __read_mostly nr_irqs = 16;
     6.8  irq_desc_t irq_desc[NR_VECTORS];
     6.9  
    6.10  static DEFINE_SPINLOCK(vector_lock);
    6.11 @@ -79,7 +80,7 @@ int assign_irq_vector(int irq)
    6.12      static unsigned current_vector = FIRST_DYNAMIC_VECTOR;
    6.13      unsigned vector;
    6.14  
    6.15 -    BUG_ON(irq >= NR_IRQS);
    6.16 +    BUG_ON(irq >= nr_irqs && irq != AUTO_ASSIGN_IRQ);
    6.17  
    6.18      spin_lock(&vector_lock);
    6.19  
    6.20 @@ -526,7 +527,7 @@ static void __pirq_guest_eoi(struct doma
    6.21  
    6.22  int pirq_guest_eoi(struct domain *d, int irq)
    6.23  {
    6.24 -    if ( (irq < 0) || (irq >= NR_IRQS) )
    6.25 +    if ( (irq < 0) || (irq >= d->nr_pirqs) )
    6.26          return -EINVAL;
    6.27  
    6.28      __pirq_guest_eoi(d, irq);
    6.29 @@ -536,11 +537,11 @@ int pirq_guest_eoi(struct domain *d, int
    6.30  
    6.31  int pirq_guest_unmask(struct domain *d)
    6.32  {
    6.33 -    unsigned int   irq;
    6.34 +    unsigned int irq, nr = d->nr_pirqs;
    6.35  
    6.36 -    for ( irq = find_first_bit(d->pirq_mask, NR_IRQS);
    6.37 -          irq < NR_IRQS;
    6.38 -          irq = find_next_bit(d->pirq_mask, NR_IRQS, irq+1) )
    6.39 +    for ( irq = find_first_bit(d->pirq_mask, nr);
    6.40 +          irq < nr;
    6.41 +          irq = find_next_bit(d->pirq_mask, nr, irq+1) )
    6.42      {
    6.43          if ( !test_bit(d->pirq_to_evtchn[irq], &shared_info(d, evtchn_mask)) )
    6.44              __pirq_guest_eoi(d, irq);
    6.45 @@ -885,15 +886,15 @@ int get_free_pirq(struct domain *d, int 
    6.46  
    6.47      if ( type == MAP_PIRQ_TYPE_GSI )
    6.48      {
    6.49 -        for ( i = 16; i < NR_IRQS; i++ )
    6.50 +        for ( i = 16; i < nr_irqs; i++ )
    6.51              if ( !d->arch.pirq_vector[i] )
    6.52                  break;
    6.53 -        if ( i == NR_IRQS )
    6.54 +        if ( i == nr_irqs )
    6.55              return -ENOSPC;
    6.56      }
    6.57      else
    6.58      {
    6.59 -        for ( i = NR_IRQS - 1; i >= 16; i-- )
    6.60 +        for ( i = d->nr_pirqs - 1; i >= 16; i-- )
    6.61              if ( !d->arch.pirq_vector[i] )
    6.62                  break;
    6.63          if ( i == 16 )
    6.64 @@ -919,7 +920,7 @@ int map_domain_pirq(
    6.65      if ( !IS_PRIV(current->domain) )
    6.66          return -EPERM;
    6.67  
    6.68 -    if ( pirq < 0 || pirq >= NR_IRQS || vector < 0 || vector >= NR_VECTORS )
    6.69 +    if ( pirq < 0 || pirq >= d->nr_pirqs || vector < 0 || vector >= NR_VECTORS )
    6.70      {
    6.71          dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n",
    6.72                  d->domain_id, pirq, vector);
    6.73 @@ -991,7 +992,7 @@ int unmap_domain_pirq(struct domain *d, 
    6.74      bool_t forced_unbind;
    6.75      struct msi_desc *msi_desc = NULL;
    6.76  
    6.77 -    if ( (pirq < 0) || (pirq >= NR_IRQS) )
    6.78 +    if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
    6.79          return -EINVAL;
    6.80  
    6.81      if ( !IS_PRIV(current->domain) )
    6.82 @@ -1063,7 +1064,7 @@ void free_domain_pirqs(struct domain *d)
    6.83      spin_lock(&pcidevs_lock);
    6.84      spin_lock(&d->event_lock);
    6.85  
    6.86 -    for ( i = 0; i < NR_IRQS; i++ )
    6.87 +    for ( i = 0; i < d->nr_pirqs; i++ )
    6.88          if ( d->arch.pirq_vector[i] > 0 )
    6.89              unmap_domain_pirq(d, i);
    6.90  
     7.1 --- a/xen/arch/x86/physdev.c	Wed May 27 08:19:30 2009 +0100
     7.2 +++ b/xen/arch/x86/physdev.c	Wed May 27 10:38:51 2009 +0100
     7.3 @@ -55,7 +55,7 @@ static int physdev_map_pirq(struct physd
     7.4      switch ( map->type )
     7.5      {
     7.6          case MAP_PIRQ_TYPE_GSI:
     7.7 -            if ( map->index < 0 || map->index >= NR_IRQS )
     7.8 +            if ( map->index < 0 || map->index >= nr_irqs )
     7.9              {
    7.10                  dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n",
    7.11                          d->domain_id, map->index);
    7.12 @@ -196,7 +196,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
    7.13          if ( copy_from_guest(&eoi, arg, 1) != 0 )
    7.14              break;
    7.15          ret = -EINVAL;
    7.16 -        if ( eoi.irq < 0 || eoi.irq >= NR_IRQS )
    7.17 +        if ( eoi.irq < 0 || eoi.irq >= v->domain->nr_pirqs )
    7.18              break;
    7.19          if ( v->domain->arch.pirq_eoi_map )
    7.20              evtchn_unmask(v->domain->pirq_to_evtchn[eoi.irq]);
    7.21 @@ -208,8 +208,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
    7.22          struct physdev_pirq_eoi_gmfn info;
    7.23          unsigned long mfn;
    7.24  
    7.25 -        BUILD_BUG_ON(NR_IRQS > (PAGE_SIZE * 8));
    7.26 -
    7.27          ret = -EFAULT;
    7.28          if ( copy_from_guest(&info, arg, 1) != 0 )
    7.29              break;
    7.30 @@ -254,7 +252,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
    7.31              break;
    7.32          irq = irq_status_query.irq;
    7.33          ret = -EINVAL;
    7.34 -        if ( (irq < 0) || (irq >= NR_IRQS) )
    7.35 +        if ( (irq < 0) || (irq >= v->domain->nr_pirqs) )
    7.36              break;
    7.37          irq_status_query.flags = 0;
    7.38          /*
    7.39 @@ -346,7 +344,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
    7.40  
    7.41          irq = irq_op.irq;
    7.42          ret = -EINVAL;
    7.43 -        if ( (irq < 0) || (irq >= NR_IRQS) )
    7.44 +        if ( (irq < 0) || (irq >= nr_irqs) )
    7.45              break;
    7.46  
    7.47          irq_op.vector = assign_irq_vector(irq);
     8.1 --- a/xen/common/domain.c	Wed May 27 08:19:30 2009 +0100
     8.2 +++ b/xen/common/domain.c	Wed May 27 10:38:51 2009 +0100
     8.3 @@ -8,6 +8,7 @@
     8.4  #include <xen/compat.h>
     8.5  #include <xen/init.h>
     8.6  #include <xen/lib.h>
     8.7 +#include <xen/ctype.h>
     8.8  #include <xen/errno.h>
     8.9  #include <xen/sched.h>
    8.10  #include <xen/domain.h>
    8.11 @@ -198,6 +199,16 @@ struct vcpu *alloc_idle_vcpu(unsigned in
    8.12      return v;
    8.13  }
    8.14  
    8.15 +static unsigned int extra_dom0_irqs, extra_domU_irqs = 8;
    8.16 +static void __init parse_extra_guest_irqs(const char *s)
    8.17 +{
    8.18 +    if ( isdigit(*s) )
    8.19 +        extra_domU_irqs = simple_strtoul(s, &s, 0);
    8.20 +    if ( *s == ',' && isdigit(*++s) )
    8.21 +        extra_dom0_irqs = simple_strtoul(s, &s, 0);
    8.22 +}
    8.23 +custom_param("extra_guest_irqs", parse_extra_guest_irqs);
    8.24 +
    8.25  struct domain *domain_create(
    8.26      domid_t domid, unsigned int domcr_flags, ssidref_t ssidref)
    8.27  {
    8.28 @@ -244,9 +255,19 @@ struct domain *domain_create(
    8.29          d->is_paused_by_controller = 1;
    8.30          atomic_inc(&d->pause_count);
    8.31  
    8.32 +        d->nr_pirqs = nr_irqs +
    8.33 +                      (domid ? extra_domU_irqs :
    8.34 +                               extra_dom0_irqs ?: nr_irqs);
    8.35          if ( evtchn_init(d) != 0 )
    8.36              goto fail;
    8.37          init_status |= INIT_evtchn;
    8.38 +        d->pirq_to_evtchn = xmalloc_array(u16, d->nr_pirqs);
    8.39 +        d->pirq_mask = xmalloc_array(unsigned long,
    8.40 +                                     BITS_TO_LONGS(d->nr_pirqs));
    8.41 +        if ( !d->pirq_to_evtchn || !d->pirq_mask )
    8.42 +            goto fail;
    8.43 +        memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn));
    8.44 +        bitmap_zero(d->pirq_mask, d->nr_pirqs);
    8.45  
    8.46          if ( grant_table_create(d) != 0 )
    8.47              goto fail;
    8.48 @@ -289,7 +310,11 @@ struct domain *domain_create(
    8.49      if ( init_status & INIT_gnttab )
    8.50          grant_table_destroy(d);
    8.51      if ( init_status & INIT_evtchn )
    8.52 +    {
    8.53 +        xfree(d->pirq_mask);
    8.54 +        xfree(d->pirq_to_evtchn);
    8.55          evtchn_destroy(d);
    8.56 +    }
    8.57      if ( init_status & INIT_rangeset )
    8.58          rangeset_domain_destroy(d);
    8.59      if ( init_status & INIT_xsm )
     9.1 --- a/xen/common/domctl.c	Wed May 27 08:19:30 2009 +0100
     9.2 +++ b/xen/common/domctl.c	Wed May 27 10:38:51 2009 +0100
     9.3 @@ -774,16 +774,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
     9.4          struct domain *d;
     9.5          unsigned int pirq = op->u.irq_permission.pirq;
     9.6  
     9.7 -        ret = -EINVAL;
     9.8 -        if ( pirq >= NR_IRQS )
     9.9 -            break;
    9.10 -
    9.11          ret = -ESRCH;
    9.12          d = rcu_lock_domain_by_id(op->domain);
    9.13          if ( d == NULL )
    9.14              break;
    9.15  
    9.16 -        if ( op->u.irq_permission.allow_access )
    9.17 +        if ( pirq >= d->nr_pirqs )
    9.18 +            ret = -EINVAL;
    9.19 +        else if ( op->u.irq_permission.allow_access )
    9.20              ret = irq_permit_access(d, pirq);
    9.21          else
    9.22              ret = irq_deny_access(d, pirq);
    10.1 --- a/xen/common/event_channel.c	Wed May 27 08:19:30 2009 +0100
    10.2 +++ b/xen/common/event_channel.c	Wed May 27 10:38:51 2009 +0100
    10.3 @@ -302,7 +302,7 @@ static long evtchn_bind_pirq(evtchn_bind
    10.4      int            port, pirq = bind->pirq;
    10.5      long           rc;
    10.6  
    10.7 -    if ( (pirq < 0) || (pirq >= ARRAY_SIZE(d->pirq_to_evtchn)) )
    10.8 +    if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
    10.9          return -EINVAL;
   10.10  
   10.11      if ( !irq_access_permitted(d, pirq) )
    11.1 --- a/xen/drivers/passthrough/io.c	Wed May 27 08:19:30 2009 +0100
    11.2 +++ b/xen/drivers/passthrough/io.c	Wed May 27 10:38:51 2009 +0100
    11.3 @@ -38,9 +38,10 @@ static void pt_irq_time_out(void *data)
    11.4      struct dev_intx_gsi_link *digl;
    11.5      struct hvm_girq_dpci_mapping *girq;
    11.6      uint32_t device, intx;
    11.7 -    DECLARE_BITMAP(machine_gsi_map, NR_IRQS);
    11.8 +    unsigned int nr_pirqs = irq_map->dom->nr_pirqs;
    11.9 +    DECLARE_BITMAP(machine_gsi_map, nr_pirqs);
   11.10  
   11.11 -    bitmap_zero(machine_gsi_map, NR_IRQS);
   11.12 +    bitmap_zero(machine_gsi_map, nr_pirqs);
   11.13  
   11.14      spin_lock(&irq_map->dom->event_lock);
   11.15  
   11.16 @@ -59,9 +60,9 @@ static void pt_irq_time_out(void *data)
   11.17          hvm_pci_intx_deassert(irq_map->dom, device, intx);
   11.18      }
   11.19  
   11.20 -    for ( machine_gsi = find_first_bit(machine_gsi_map, NR_IRQS);
   11.21 -          machine_gsi < NR_IRQS;
   11.22 -          machine_gsi = find_next_bit(machine_gsi_map, NR_IRQS,
   11.23 +    for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs);
   11.24 +          machine_gsi < nr_pirqs;
   11.25 +          machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs,
   11.26                                        machine_gsi + 1) )
   11.27      {
   11.28          clear_bit(machine_gsi, dpci->dirq_mask);
   11.29 @@ -71,15 +72,23 @@ static void pt_irq_time_out(void *data)
   11.30  
   11.31      spin_unlock(&irq_map->dom->event_lock);
   11.32  
   11.33 -    for ( machine_gsi = find_first_bit(machine_gsi_map, NR_IRQS);
   11.34 -          machine_gsi < NR_IRQS;
   11.35 -          machine_gsi = find_next_bit(machine_gsi_map, NR_IRQS,
   11.36 +    for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs);
   11.37 +          machine_gsi < nr_pirqs;
   11.38 +          machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs,
   11.39                                        machine_gsi + 1) )
   11.40      {
   11.41          pirq_guest_eoi(irq_map->dom, machine_gsi);
   11.42      }
   11.43  }
   11.44  
   11.45 +void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci)
   11.46 +{
   11.47 +    xfree(dpci->mirq);
   11.48 +    xfree(dpci->dirq_mask);
   11.49 +    xfree(dpci->mapping);
   11.50 +    xfree(dpci);
   11.51 +}
   11.52 +
   11.53  int pt_irq_create_bind_vtd(
   11.54      struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
   11.55  {
   11.56 @@ -90,7 +99,7 @@ int pt_irq_create_bind_vtd(
   11.57      struct hvm_girq_dpci_mapping *girq;
   11.58      int rc, pirq = pt_irq_bind->machine_irq;
   11.59  
   11.60 -    if ( pirq < 0 || pirq >= NR_IRQS )
   11.61 +    if ( pirq < 0 || pirq >= d->nr_pirqs )
   11.62          return -EINVAL;
   11.63  
   11.64      spin_lock(&d->event_lock);
   11.65 @@ -105,16 +114,33 @@ int pt_irq_create_bind_vtd(
   11.66              return -ENOMEM;
   11.67          }
   11.68          memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
   11.69 -        for ( int i = 0; i < NR_IRQS; i++ )
   11.70 +        hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping,
   11.71 +                                           d->nr_pirqs);
   11.72 +        hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long,
   11.73 +                                                BITS_TO_LONGS(d->nr_pirqs));
   11.74 +        hvm_irq_dpci->mapping = xmalloc_array(unsigned long,
   11.75 +                                              BITS_TO_LONGS(d->nr_pirqs));
   11.76 +        if ( !hvm_irq_dpci->mirq ||
   11.77 +             !hvm_irq_dpci->dirq_mask ||
   11.78 +             !hvm_irq_dpci->mapping )
   11.79          {
   11.80 +            spin_unlock(&d->event_lock);
   11.81 +            free_hvm_irq_dpci(hvm_irq_dpci);
   11.82 +            return -ENOMEM;
   11.83 +        }
   11.84 +        memset(hvm_irq_dpci->mirq, 0,
   11.85 +               d->nr_pirqs * sizeof(*hvm_irq_dpci->mirq));
   11.86 +        bitmap_zero(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
   11.87 +        bitmap_zero(hvm_irq_dpci->mapping, d->nr_pirqs);
   11.88 +        for ( int i = 0; i < d->nr_pirqs; i++ )
   11.89              INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list);
   11.90 +        for ( int i = 0; i < NR_HVM_IRQS; i++ )
   11.91              INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
   11.92 -        }
   11.93  
   11.94          if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 )
   11.95          {
   11.96              spin_unlock(&d->event_lock);
   11.97 -            xfree(hvm_irq_dpci);
   11.98 +            free_hvm_irq_dpci(hvm_irq_dpci);
   11.99              return -EINVAL;
  11.100          }
  11.101      }
  11.102 @@ -364,7 +390,7 @@ static void __msi_pirq_eoi(struct domain
  11.103      struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
  11.104      irq_desc_t *desc;
  11.105  
  11.106 -    if ( ( pirq >= 0 ) && ( pirq < NR_IRQS ) &&
  11.107 +    if ( ( pirq >= 0 ) && ( pirq < d->nr_pirqs ) &&
  11.108           test_bit(pirq, hvm_irq_dpci->mapping) &&
  11.109           ( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI) )
  11.110      {
  11.111 @@ -414,9 +440,9 @@ void hvm_dirq_assist(struct vcpu *v)
  11.112      if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
  11.113          return;
  11.114  
  11.115 -    for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS);
  11.116 -          irq < NR_IRQS;
  11.117 -          irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) )
  11.118 +    for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
  11.119 +          irq < d->nr_pirqs;
  11.120 +          irq = find_next_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs, irq + 1) )
  11.121      {
  11.122          if ( !test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask) )
  11.123              continue;
    12.1 --- a/xen/drivers/passthrough/pci.c	Wed May 27 08:19:30 2009 +0100
    12.2 +++ b/xen/drivers/passthrough/pci.c	Wed May 27 10:38:51 2009 +0100
    12.3 @@ -201,9 +201,9 @@ static void pci_clean_dpci_irqs(struct d
    12.4      hvm_irq_dpci = domain_get_irq_dpci(d);
    12.5      if ( hvm_irq_dpci != NULL )
    12.6      {
    12.7 -        for ( i = find_first_bit(hvm_irq_dpci->mapping, NR_IRQS);
    12.8 -              i < NR_IRQS;
    12.9 -              i = find_next_bit(hvm_irq_dpci->mapping, NR_IRQS, i + 1) )
   12.10 +        for ( i = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
   12.11 +              i < d->nr_pirqs;
   12.12 +              i = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, i + 1) )
   12.13          {
   12.14              pirq_guest_unbind(d, i);
   12.15              kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);
   12.16 @@ -219,7 +219,7 @@ static void pci_clean_dpci_irqs(struct d
   12.17          }
   12.18  
   12.19          d->arch.hvm_domain.irq.dpci = NULL;
   12.20 -        xfree(hvm_irq_dpci);
   12.21 +        free_hvm_irq_dpci(hvm_irq_dpci);
   12.22      }
   12.23      spin_unlock(&d->event_lock);
   12.24  }
    13.1 --- a/xen/drivers/passthrough/vtd/x86/vtd.c	Wed May 27 08:19:30 2009 +0100
    13.2 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c	Wed May 27 10:38:51 2009 +0100
    13.3 @@ -130,9 +130,9 @@ void hvm_dpci_isairq_eoi(struct domain *
    13.4          return;
    13.5      }
    13.6      /* Multiple mirq may be mapped to one isa irq */
    13.7 -    for ( i = find_first_bit(dpci->mapping, NR_IRQS);
    13.8 -          i < NR_IRQS;
    13.9 -          i = find_next_bit(dpci->mapping, NR_IRQS, i + 1) )
   13.10 +    for ( i = find_first_bit(dpci->mapping, d->nr_pirqs);
   13.11 +          i < d->nr_pirqs;
   13.12 +          i = find_next_bit(dpci->mapping, d->nr_pirqs, i + 1) )
   13.13      {
   13.14          list_for_each_entry_safe ( digl, tmp,
   13.15              &dpci->mirq[i].digl_list, list )
    14.1 --- a/xen/include/asm-x86/config.h	Wed May 27 08:19:30 2009 +0100
    14.2 +++ b/xen/include/asm-x86/config.h	Wed May 27 10:38:51 2009 +0100
    14.3 @@ -52,12 +52,6 @@
    14.4  #define NR_CPUS 32
    14.5  #endif
    14.6  
    14.7 -#ifdef MAX_PHYS_IRQS
    14.8 -#define NR_IRQS MAX_PHYS_IRQS
    14.9 -#else
   14.10 -#define NR_IRQS 256
   14.11 -#endif
   14.12 -
   14.13  #if defined(__i386__) && (NR_CPUS > 32)
   14.14  #error "Maximum of 32 physical processors supported by Xen on x86_32"
   14.15  #endif
    15.1 --- a/xen/include/asm-x86/domain.h	Wed May 27 08:19:30 2009 +0100
    15.2 +++ b/xen/include/asm-x86/domain.h	Wed May 27 10:38:51 2009 +0100
    15.3 @@ -263,7 +263,7 @@ struct arch_domain
    15.4  
    15.5      /* NB. protected by d->event_lock and by irq_desc[vector].lock */
    15.6      int vector_pirq[NR_VECTORS];
    15.7 -    s16 pirq_vector[NR_IRQS];
    15.8 +    s16 *pirq_vector;
    15.9  
   15.10      /* Shared page for notifying that explicit PIRQ EOI is required. */
   15.11      unsigned long *pirq_eoi_map;
    16.1 --- a/xen/include/asm-x86/io_apic.h	Wed May 27 08:19:30 2009 +0100
    16.2 +++ b/xen/include/asm-x86/io_apic.h	Wed May 27 10:38:51 2009 +0100
    16.3 @@ -175,11 +175,14 @@ extern int io_apic_set_pci_routing (int 
    16.4  extern int timer_uses_ioapic_pin_0;
    16.5  #endif /*CONFIG_ACPI_BOOT*/
    16.6  
    16.7 +extern void init_ioapic_mappings(void);
    16.8 +
    16.9  extern int (*ioapic_renumber_irq)(int ioapic, int irq);
   16.10  extern void ioapic_suspend(void);
   16.11  extern void ioapic_resume(void);
   16.12  
   16.13  #else  /* !CONFIG_X86_IO_APIC */
   16.14 +static inline void init_ioapic_mappings(void) {}
   16.15  static inline void ioapic_suspend(void) {}
   16.16  static inline void ioapic_resume(void) {}
   16.17  #endif
    17.1 --- a/xen/include/asm-x86/irq.h	Wed May 27 08:19:30 2009 +0100
    17.2 +++ b/xen/include/asm-x86/irq.h	Wed May 27 10:38:51 2009 +0100
    17.3 @@ -18,7 +18,7 @@
    17.4  #define vector_to_irq(vec)  (vector_irq[vec])
    17.5  
    17.6  extern int vector_irq[NR_VECTORS];
    17.7 -extern u8 irq_vector[NR_IRQS];
    17.8 +extern u8 *irq_vector;
    17.9  
   17.10  #define platform_legacy_irq(irq)	((irq) < 16)
   17.11  
    18.1 --- a/xen/include/xen/hvm/irq.h	Wed May 27 08:19:30 2009 +0100
    18.2 +++ b/xen/include/xen/hvm/irq.h	Wed May 27 10:38:51 2009 +0100
    18.3 @@ -68,21 +68,26 @@ struct hvm_girq_dpci_mapping {
    18.4  
    18.5  #define NR_ISAIRQS  16
    18.6  #define NR_LINK     4
    18.7 +#if defined(__i386__) || defined(__x86_64__)
    18.8 +# define NR_HVM_IRQS VIOAPIC_NUM_PINS
    18.9 +#elif defined(__ia64__)
   18.10 +# define NR_HVM_IRQS VIOSAPIC_NUM_PINS
   18.11 +#endif
   18.12  
   18.13  /* Protected by domain's event_lock */
   18.14  struct hvm_irq_dpci {
   18.15      /* Machine IRQ to guest device/intx mapping. */
   18.16 -    DECLARE_BITMAP(mapping, NR_IRQS);
   18.17 -    struct hvm_mirq_dpci_mapping mirq[NR_IRQS];
   18.18 +    unsigned long *mapping;
   18.19 +    struct hvm_mirq_dpci_mapping *mirq;
   18.20 +    unsigned long *dirq_mask;
   18.21      /* Guest IRQ to guest device/intx mapping. */
   18.22 -    struct list_head girq[NR_IRQS];
   18.23 -    uint8_t msi_gvec_pirq[NR_VECTORS];
   18.24 -    DECLARE_BITMAP(dirq_mask, NR_IRQS);
   18.25 +    struct list_head girq[NR_HVM_IRQS];
   18.26 +    uint8_t msi_gvec_pirq[0x100];
   18.27      /* Record of mapped ISA IRQs */
   18.28      DECLARE_BITMAP(isairq_map, NR_ISAIRQS);
   18.29      /* Record of mapped Links */
   18.30      uint8_t link_cnt[NR_LINK];
   18.31 -    struct timer hvm_timer[NR_IRQS];
   18.32 +    struct timer hvm_timer[NR_VECTORS];
   18.33  };
   18.34  
   18.35  /* Modify state of a PCI INTx wire. */
    19.1 --- a/xen/include/xen/iommu.h	Wed May 27 08:19:30 2009 +0100
    19.2 +++ b/xen/include/xen/iommu.h	Wed May 27 10:38:51 2009 +0100
    19.3 @@ -91,6 +91,7 @@ struct iommu_flush *iommu_get_flush(stru
    19.4  void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq);
    19.5  struct hvm_irq_dpci *domain_get_irq_dpci(struct domain *domain);
    19.6  int domain_set_irq_dpci(struct domain *domain, struct hvm_irq_dpci *dpci);
    19.7 +void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci);
    19.8  
    19.9  #define PT_IRQ_TIME_OUT MILLISECS(8)
   19.10  #define VTDPREFIX "[VT-D]"
    20.1 --- a/xen/include/xen/irq.h	Wed May 27 08:19:30 2009 +0100
    20.2 +++ b/xen/include/xen/irq.h	Wed May 27 10:38:51 2009 +0100
    20.3 @@ -49,6 +49,12 @@ typedef struct hw_interrupt_type hw_irq_
    20.4  
    20.5  #include <asm/irq.h>
    20.6  
    20.7 +#ifdef NR_IRQS
    20.8 +# define nr_irqs NR_IRQS
    20.9 +#else
   20.10 +extern unsigned int nr_irqs;
   20.11 +#endif
   20.12 +
   20.13  struct msi_desc;
   20.14  /*
   20.15   * This is the "IRQ descriptor", which contains various information
    21.1 --- a/xen/include/xen/sched.h	Wed May 27 08:19:30 2009 +0100
    21.2 +++ b/xen/include/xen/sched.h	Wed May 27 10:38:51 2009 +0100
    21.3 @@ -200,8 +200,9 @@ struct domain
    21.4       * domain's event-channel spinlock. Read accesses can also synchronise on 
    21.5       * the lock, but races don't usually matter.
    21.6       */
    21.7 -    u16              pirq_to_evtchn[NR_IRQS];
    21.8 -    DECLARE_BITMAP(pirq_mask, NR_IRQS);
    21.9 +    unsigned int     nr_pirqs;
   21.10 +    u16             *pirq_to_evtchn;
   21.11 +    unsigned long   *pirq_mask;
   21.12  
   21.13      /* I/O capabilities (access to IRQs and memory-mapped I/O). */
   21.14      struct rangeset *iomem_caps;