[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: eliminate hard-coded NR_IRQS
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1243417131 -3600 # Node ID 6705898f768d57fa44588cc061ac88e8045fb434 # Parent fcc71d02340809901b656eb4134383f36a7c7875 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@xxxxxxxxxx> --- xen/arch/x86/apic.c | 30 ------------ xen/arch/x86/domain.c | 8 +++ xen/arch/x86/domain_build.c | 2 xen/arch/x86/i8259.c | 3 + xen/arch/x86/io_apic.c | 85 +++++++++++++++++++++++++--------- xen/arch/x86/irq.c | 27 +++++----- xen/arch/x86/physdev.c | 10 +--- xen/common/domain.c | 25 ++++++++++ xen/common/domctl.c | 8 +-- xen/common/event_channel.c | 2 xen/drivers/passthrough/io.c | 62 +++++++++++++++++------- xen/drivers/passthrough/pci.c | 8 +-- xen/drivers/passthrough/vtd/x86/vtd.c | 6 +- xen/include/asm-x86/config.h | 6 -- xen/include/asm-x86/domain.h | 2 xen/include/asm-x86/io_apic.h | 3 + xen/include/asm-x86/irq.h | 2 xen/include/xen/hvm/irq.h | 17 ++++-- xen/include/xen/iommu.h | 1 xen/include/xen/irq.h | 6 ++ xen/include/xen/sched.h | 5 +- 21 files changed, 201 insertions(+), 117 deletions(-) diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/apic.c --- a/xen/arch/x86/apic.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/apic.c Wed May 27 10:38:51 2009 +0100 @@ -890,35 +890,7 @@ __next: if (boot_cpu_physical_apicid == -1U) boot_cpu_physical_apicid = get_apic_id(); -#ifdef CONFIG_X86_IO_APIC - { - unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; - int i; - - for (i = 0; i < nr_ioapics; i++) { - if (smp_found_config) { - ioapic_phys = mp_ioapics[i].mpc_apicaddr; - if (!ioapic_phys) { - printk(KERN_ERR - "WARNING: bogus zero IO-APIC " - "address found in MPTABLE, " - "disabling IO/APIC support!\n"); - smp_found_config = 0; - skip_ioapic_setup = 1; - goto fake_ioapic_page; - } - } else { -fake_ioapic_page: - ioapic_phys = __pa(alloc_xenheap_page()); - clear_page(__va(ioapic_phys)); - } - set_fixmap_nocache(idx, ioapic_phys); - apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", - __fix_to_virt(idx), ioapic_phys); - idx++; - } - } -#endif + init_ioapic_mappings(); } /***************************************************************************** diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/domain.c Wed May 27 10:38:51 2009 +0100 @@ -454,6 +454,12 @@ int arch_domain_create(struct domain *d, share_xen_page_with_guest( virt_to_page(d->shared_info), d, XENSHARE_writable); + d->arch.pirq_vector = xmalloc_array(s16, d->nr_pirqs); + if ( !d->arch.pirq_vector ) + goto fail; + memset(d->arch.pirq_vector, 0, + d->nr_pirqs * sizeof(*d->arch.pirq_vector)); + if ( (rc = iommu_domain_init(d)) != 0 ) goto fail; @@ -488,6 +494,7 @@ int arch_domain_create(struct domain *d, fail: d->is_dying = DOMDYING_dead; + xfree(d->arch.pirq_vector); free_xenheap_page(d->shared_info); if ( paging_initialised ) paging_final_teardown(d); @@ -523,6 +530,7 @@ void arch_domain_destroy(struct domain * #endif free_xenheap_page(d->shared_info); + xfree(d->arch.pirq_vector); } unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4) diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/domain_build.c Wed May 27 10:38:51 2009 +0100 @@ -1000,7 +1000,7 @@ int __init construct_dom0( /* DOM0 is permitted full I/O capabilities. */ rc |= ioports_permit_access(dom0, 0, 0xFFFF); rc |= iomem_permit_access(dom0, 0UL, ~0UL); - rc |= irqs_permit_access(dom0, 0, NR_IRQS-1); + rc |= irqs_permit_access(dom0, 0, d->nr_pirqs - 1); /* * Modify I/O port access permissions. diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/i8259.c --- a/xen/arch/x86/i8259.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/i8259.c Wed May 27 10:38:51 2009 +0100 @@ -403,6 +403,9 @@ void __init init_IRQ(void) set_intr_gate(i, interrupt[i]); } + irq_vector = xmalloc_array(u8, nr_irqs); + memset(irq_vector, 0, nr_irqs * sizeof(*irq_vector)); + for ( i = 0; i < 16; i++ ) { vector_irq[LEGACY_VECTOR(i)] = i; diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/io_apic.c --- a/xen/arch/x86/io_apic.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/io_apic.c Wed May 27 10:38:51 2009 +0100 @@ -71,8 +71,8 @@ int disable_timer_pin_1 __initdata; * Rough estimation of how many shared IRQs there are, can * be changed anytime. */ -#define MAX_PLUS_SHARED_IRQS NR_IRQS -#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) +#define MAX_PLUS_SHARED_IRQS nr_irqs +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + nr_irqs) /* * This is performance-critical, we want to do it O(1) @@ -82,11 +82,10 @@ int disable_timer_pin_1 __initdata; */ static struct irq_pin_list { - int apic, pin, next; -} irq_2_pin[PIN_MAP_SIZE] = { - [0 ... PIN_MAP_SIZE-1].pin = -1 -}; -static int irq_2_pin_free_entry = NR_IRQS; + int apic, pin; + unsigned int next; +} *irq_2_pin; +static unsigned int irq_2_pin_free_entry; /* * The common case is 1:1 IRQ<->pin mappings. Sometimes there are @@ -663,7 +662,7 @@ static inline int IO_APIC_irq_trigger(in } /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ -u8 irq_vector[NR_IRQS] __read_mostly; +u8 *irq_vector __read_mostly = (u8 *)(1UL << (BITS_PER_LONG - 1)); static struct hw_interrupt_type ioapic_level_type; static struct hw_interrupt_type ioapic_edge_type; @@ -929,7 +928,7 @@ void /*__init*/ __print_IO_APIC(void) } printk(KERN_INFO "Using vector-based indexing\n"); printk(KERN_DEBUG "IRQ to pin mappings:\n"); - for (i = 0; i < NR_IRQS; i++) { + for (i = 0; i < nr_irqs; i++) { struct irq_pin_list *entry = irq_2_pin + i; if (entry->pin < 0) continue; @@ -961,24 +960,16 @@ void print_IO_APIC_keyhandler(unsigned c static void __init enable_IO_APIC(void) { - union IO_APIC_reg_01 reg_01; int i8259_apic, i8259_pin; int i, apic; unsigned long flags; /* Initialise dynamic irq_2_pin free list. */ - for (i = NR_IRQS; i < PIN_MAP_SIZE; i++) + irq_2_pin = xmalloc_array(struct irq_pin_list, PIN_MAP_SIZE); + memset(irq_2_pin, 0, nr_irqs * sizeof(*irq_2_pin)); + for (i = irq_2_pin_free_entry = nr_irqs; i < PIN_MAP_SIZE; i++) irq_2_pin[i].next = i + 1; - /* - * The number of IO-APIC IRQ registers (== #pins): - */ - for (apic = 0; apic < nr_ioapics; apic++) { - spin_lock_irqsave(&ioapic_lock, flags); - reg_01.raw = io_apic_read(apic, 1); - spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[apic] = reg_01.bits.entries+1; - } for(apic = 0; apic < nr_ioapics; apic++) { int pin; /* See if any of the pins is in ExtINT mode */ @@ -2174,7 +2165,7 @@ void dump_ioapic_irq_info(void) unsigned int irq, pin, printed = 0; unsigned long flags; - for ( irq = 0; irq < NR_IRQS; irq++ ) + for ( irq = 0; irq < nr_irqs; irq++ ) { entry = &irq_2_pin[irq]; if ( entry->pin == -1 ) @@ -2210,3 +2201,55 @@ void dump_ioapic_irq_info(void) } } } + +void __init init_ioapic_mappings(void) +{ + unsigned long ioapic_phys; + unsigned int i, idx = FIX_IO_APIC_BASE_0; + union IO_APIC_reg_01 reg_01; + + if ( smp_found_config ) + nr_irqs = 0; + for ( i = 0; i < nr_ioapics; i++ ) + { + if ( smp_found_config ) + { + ioapic_phys = mp_ioapics[i].mpc_apicaddr; + if ( !ioapic_phys ) + { + printk(KERN_ERR "WARNING: bogus zero IO-APIC address " + "found in MPTABLE, disabling IO/APIC support!\n"); + smp_found_config = 0; + skip_ioapic_setup = 1; + goto fake_ioapic_page; + } + } + else + { + fake_ioapic_page: + ioapic_phys = __pa(alloc_xenheap_page()); + clear_page(__va(ioapic_phys)); + } + set_fixmap_nocache(idx, ioapic_phys); + apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", + __fix_to_virt(idx), ioapic_phys); + idx++; + + if ( smp_found_config ) + { + /* The number of IO-APIC IRQ registers (== #pins): */ + reg_01.raw = io_apic_read(i, 1); + nr_ioapic_registers[i] = reg_01.bits.entries + 1; + nr_irqs += nr_ioapic_registers[i]; + } + } + if ( !smp_found_config || skip_ioapic_setup || nr_irqs < 16 ) + nr_irqs = 16; + else if ( nr_irqs > PAGE_SIZE * 8 ) + { + /* for PHYSDEVOP_pirq_eoi_gmfn guest assumptions */ + printk(KERN_WARNING "Limiting number of IRQs found (%u) to %lu\n", + nr_irqs, PAGE_SIZE * 8); + nr_irqs = PAGE_SIZE * 8; + } +} diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/irq.c Wed May 27 10:38:51 2009 +0100 @@ -26,6 +26,7 @@ int opt_noirqbalance = 0; int opt_noirqbalance = 0; boolean_param("noirqbalance", opt_noirqbalance); +unsigned int __read_mostly nr_irqs = 16; irq_desc_t irq_desc[NR_VECTORS]; static DEFINE_SPINLOCK(vector_lock); @@ -79,7 +80,7 @@ int assign_irq_vector(int irq) static unsigned current_vector = FIRST_DYNAMIC_VECTOR; unsigned vector; - BUG_ON(irq >= NR_IRQS); + BUG_ON(irq >= nr_irqs && irq != AUTO_ASSIGN_IRQ); spin_lock(&vector_lock); @@ -526,7 +527,7 @@ static void __pirq_guest_eoi(struct doma int pirq_guest_eoi(struct domain *d, int irq) { - if ( (irq < 0) || (irq >= NR_IRQS) ) + if ( (irq < 0) || (irq >= d->nr_pirqs) ) return -EINVAL; __pirq_guest_eoi(d, irq); @@ -536,11 +537,11 @@ int pirq_guest_eoi(struct domain *d, int int pirq_guest_unmask(struct domain *d) { - unsigned int irq; - - for ( irq = find_first_bit(d->pirq_mask, NR_IRQS); - irq < NR_IRQS; - irq = find_next_bit(d->pirq_mask, NR_IRQS, irq+1) ) + unsigned int irq, nr = d->nr_pirqs; + + for ( irq = find_first_bit(d->pirq_mask, nr); + irq < nr; + irq = find_next_bit(d->pirq_mask, nr, irq+1) ) { if ( !test_bit(d->pirq_to_evtchn[irq], &shared_info(d, evtchn_mask)) ) __pirq_guest_eoi(d, irq); @@ -885,15 +886,15 @@ int get_free_pirq(struct domain *d, int if ( type == MAP_PIRQ_TYPE_GSI ) { - for ( i = 16; i < NR_IRQS; i++ ) + for ( i = 16; i < nr_irqs; i++ ) if ( !d->arch.pirq_vector[i] ) break; - if ( i == NR_IRQS ) + if ( i == nr_irqs ) return -ENOSPC; } else { - for ( i = NR_IRQS - 1; i >= 16; i-- ) + for ( i = d->nr_pirqs - 1; i >= 16; i-- ) if ( !d->arch.pirq_vector[i] ) break; if ( i == 16 ) @@ -919,7 +920,7 @@ int map_domain_pirq( if ( !IS_PRIV(current->domain) ) return -EPERM; - if ( pirq < 0 || pirq >= NR_IRQS || vector < 0 || vector >= NR_VECTORS ) + if ( pirq < 0 || pirq >= d->nr_pirqs || vector < 0 || vector >= NR_VECTORS ) { dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n", d->domain_id, pirq, vector); @@ -991,7 +992,7 @@ int unmap_domain_pirq(struct domain *d, bool_t forced_unbind; struct msi_desc *msi_desc = NULL; - if ( (pirq < 0) || (pirq >= NR_IRQS) ) + if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) return -EINVAL; if ( !IS_PRIV(current->domain) ) @@ -1063,7 +1064,7 @@ void free_domain_pirqs(struct domain *d) spin_lock(&pcidevs_lock); spin_lock(&d->event_lock); - for ( i = 0; i < NR_IRQS; i++ ) + for ( i = 0; i < d->nr_pirqs; i++ ) if ( d->arch.pirq_vector[i] > 0 ) unmap_domain_pirq(d, i); diff -r fcc71d023408 -r 6705898f768d xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/arch/x86/physdev.c Wed May 27 10:38:51 2009 +0100 @@ -55,7 +55,7 @@ static int physdev_map_pirq(struct physd switch ( map->type ) { case MAP_PIRQ_TYPE_GSI: - if ( map->index < 0 || map->index >= NR_IRQS ) + if ( map->index < 0 || map->index >= nr_irqs ) { dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n", d->domain_id, map->index); @@ -196,7 +196,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H if ( copy_from_guest(&eoi, arg, 1) != 0 ) break; ret = -EINVAL; - if ( eoi.irq < 0 || eoi.irq >= NR_IRQS ) + if ( eoi.irq < 0 || eoi.irq >= v->domain->nr_pirqs ) break; if ( v->domain->arch.pirq_eoi_map ) evtchn_unmask(v->domain->pirq_to_evtchn[eoi.irq]); @@ -207,8 +207,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H case PHYSDEVOP_pirq_eoi_gmfn: { struct physdev_pirq_eoi_gmfn info; unsigned long mfn; - - BUILD_BUG_ON(NR_IRQS > (PAGE_SIZE * 8)); ret = -EFAULT; if ( copy_from_guest(&info, arg, 1) != 0 ) @@ -254,7 +252,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H break; irq = irq_status_query.irq; ret = -EINVAL; - if ( (irq < 0) || (irq >= NR_IRQS) ) + if ( (irq < 0) || (irq >= v->domain->nr_pirqs) ) break; irq_status_query.flags = 0; /* @@ -346,7 +344,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H irq = irq_op.irq; ret = -EINVAL; - if ( (irq < 0) || (irq >= NR_IRQS) ) + if ( (irq < 0) || (irq >= nr_irqs) ) break; irq_op.vector = assign_irq_vector(irq); diff -r fcc71d023408 -r 6705898f768d xen/common/domain.c --- a/xen/common/domain.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/common/domain.c Wed May 27 10:38:51 2009 +0100 @@ -8,6 +8,7 @@ #include <xen/compat.h> #include <xen/init.h> #include <xen/lib.h> +#include <xen/ctype.h> #include <xen/errno.h> #include <xen/sched.h> #include <xen/domain.h> @@ -198,6 +199,16 @@ struct vcpu *alloc_idle_vcpu(unsigned in return v; } +static unsigned int extra_dom0_irqs, extra_domU_irqs = 8; +static void __init parse_extra_guest_irqs(const char *s) +{ + if ( isdigit(*s) ) + extra_domU_irqs = simple_strtoul(s, &s, 0); + if ( *s == ',' && isdigit(*++s) ) + extra_dom0_irqs = simple_strtoul(s, &s, 0); +} +custom_param("extra_guest_irqs", parse_extra_guest_irqs); + struct domain *domain_create( domid_t domid, unsigned int domcr_flags, ssidref_t ssidref) { @@ -244,9 +255,19 @@ struct domain *domain_create( d->is_paused_by_controller = 1; atomic_inc(&d->pause_count); + d->nr_pirqs = nr_irqs + + (domid ? extra_domU_irqs : + extra_dom0_irqs ?: nr_irqs); if ( evtchn_init(d) != 0 ) goto fail; init_status |= INIT_evtchn; + d->pirq_to_evtchn = xmalloc_array(u16, d->nr_pirqs); + d->pirq_mask = xmalloc_array(unsigned long, + BITS_TO_LONGS(d->nr_pirqs)); + if ( !d->pirq_to_evtchn || !d->pirq_mask ) + goto fail; + memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn)); + bitmap_zero(d->pirq_mask, d->nr_pirqs); if ( grant_table_create(d) != 0 ) goto fail; @@ -289,7 +310,11 @@ struct domain *domain_create( if ( init_status & INIT_gnttab ) grant_table_destroy(d); if ( init_status & INIT_evtchn ) + { + xfree(d->pirq_mask); + xfree(d->pirq_to_evtchn); evtchn_destroy(d); + } if ( init_status & INIT_rangeset ) rangeset_domain_destroy(d); if ( init_status & INIT_xsm ) diff -r fcc71d023408 -r 6705898f768d xen/common/domctl.c --- a/xen/common/domctl.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/common/domctl.c Wed May 27 10:38:51 2009 +0100 @@ -774,16 +774,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc struct domain *d; unsigned int pirq = op->u.irq_permission.pirq; - ret = -EINVAL; - if ( pirq >= NR_IRQS ) - break; - ret = -ESRCH; d = rcu_lock_domain_by_id(op->domain); if ( d == NULL ) break; - if ( op->u.irq_permission.allow_access ) + if ( pirq >= d->nr_pirqs ) + ret = -EINVAL; + else if ( op->u.irq_permission.allow_access ) ret = irq_permit_access(d, pirq); else ret = irq_deny_access(d, pirq); diff -r fcc71d023408 -r 6705898f768d xen/common/event_channel.c --- a/xen/common/event_channel.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/common/event_channel.c Wed May 27 10:38:51 2009 +0100 @@ -302,7 +302,7 @@ static long evtchn_bind_pirq(evtchn_bind int port, pirq = bind->pirq; long rc; - if ( (pirq < 0) || (pirq >= ARRAY_SIZE(d->pirq_to_evtchn)) ) + if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) return -EINVAL; if ( !irq_access_permitted(d, pirq) ) diff -r fcc71d023408 -r 6705898f768d xen/drivers/passthrough/io.c --- a/xen/drivers/passthrough/io.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/drivers/passthrough/io.c Wed May 27 10:38:51 2009 +0100 @@ -38,9 +38,10 @@ static void pt_irq_time_out(void *data) struct dev_intx_gsi_link *digl; struct hvm_girq_dpci_mapping *girq; uint32_t device, intx; - DECLARE_BITMAP(machine_gsi_map, NR_IRQS); - - bitmap_zero(machine_gsi_map, NR_IRQS); + unsigned int nr_pirqs = irq_map->dom->nr_pirqs; + DECLARE_BITMAP(machine_gsi_map, nr_pirqs); + + bitmap_zero(machine_gsi_map, nr_pirqs); spin_lock(&irq_map->dom->event_lock); @@ -59,9 +60,9 @@ static void pt_irq_time_out(void *data) hvm_pci_intx_deassert(irq_map->dom, device, intx); } - for ( machine_gsi = find_first_bit(machine_gsi_map, NR_IRQS); - machine_gsi < NR_IRQS; - machine_gsi = find_next_bit(machine_gsi_map, NR_IRQS, + for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs); + machine_gsi < nr_pirqs; + machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs, machine_gsi + 1) ) { clear_bit(machine_gsi, dpci->dirq_mask); @@ -71,13 +72,21 @@ static void pt_irq_time_out(void *data) spin_unlock(&irq_map->dom->event_lock); - for ( machine_gsi = find_first_bit(machine_gsi_map, NR_IRQS); - machine_gsi < NR_IRQS; - machine_gsi = find_next_bit(machine_gsi_map, NR_IRQS, + for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs); + machine_gsi < nr_pirqs; + machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs, machine_gsi + 1) ) { pirq_guest_eoi(irq_map->dom, machine_gsi); } +} + +void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci) +{ + xfree(dpci->mirq); + xfree(dpci->dirq_mask); + xfree(dpci->mapping); + xfree(dpci); } int pt_irq_create_bind_vtd( @@ -90,7 +99,7 @@ int pt_irq_create_bind_vtd( struct hvm_girq_dpci_mapping *girq; int rc, pirq = pt_irq_bind->machine_irq; - if ( pirq < 0 || pirq >= NR_IRQS ) + if ( pirq < 0 || pirq >= d->nr_pirqs ) return -EINVAL; spin_lock(&d->event_lock); @@ -105,16 +114,33 @@ int pt_irq_create_bind_vtd( return -ENOMEM; } memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci)); - for ( int i = 0; i < NR_IRQS; i++ ) - { + hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping, + d->nr_pirqs); + hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long, + BITS_TO_LONGS(d->nr_pirqs)); + hvm_irq_dpci->mapping = xmalloc_array(unsigned long, + BITS_TO_LONGS(d->nr_pirqs)); + if ( !hvm_irq_dpci->mirq || + !hvm_irq_dpci->dirq_mask || + !hvm_irq_dpci->mapping ) + { + spin_unlock(&d->event_lock); + free_hvm_irq_dpci(hvm_irq_dpci); + return -ENOMEM; + } + memset(hvm_irq_dpci->mirq, 0, + d->nr_pirqs * sizeof(*hvm_irq_dpci->mirq)); + bitmap_zero(hvm_irq_dpci->dirq_mask, d->nr_pirqs); + bitmap_zero(hvm_irq_dpci->mapping, d->nr_pirqs); + for ( int i = 0; i < d->nr_pirqs; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list); + for ( int i = 0; i < NR_HVM_IRQS; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]); - } if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 ) { spin_unlock(&d->event_lock); - xfree(hvm_irq_dpci); + free_hvm_irq_dpci(hvm_irq_dpci); return -EINVAL; } } @@ -364,7 +390,7 @@ static void __msi_pirq_eoi(struct domain struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; irq_desc_t *desc; - if ( ( pirq >= 0 ) && ( pirq < NR_IRQS ) && + if ( ( pirq >= 0 ) && ( pirq < d->nr_pirqs ) && test_bit(pirq, hvm_irq_dpci->mapping) && ( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI) ) { @@ -414,9 +440,9 @@ void hvm_dirq_assist(struct vcpu *v) if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) return; - for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS); - irq < NR_IRQS; - irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) ) + for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs); + irq < d->nr_pirqs; + irq = find_next_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs, irq + 1) ) { if ( !test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask) ) continue; diff -r fcc71d023408 -r 6705898f768d xen/drivers/passthrough/pci.c --- a/xen/drivers/passthrough/pci.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/drivers/passthrough/pci.c Wed May 27 10:38:51 2009 +0100 @@ -201,9 +201,9 @@ static void pci_clean_dpci_irqs(struct d hvm_irq_dpci = domain_get_irq_dpci(d); if ( hvm_irq_dpci != NULL ) { - for ( i = find_first_bit(hvm_irq_dpci->mapping, NR_IRQS); - i < NR_IRQS; - i = find_next_bit(hvm_irq_dpci->mapping, NR_IRQS, i + 1) ) + for ( i = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs); + i < d->nr_pirqs; + i = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, i + 1) ) { pirq_guest_unbind(d, i); kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]); @@ -219,7 +219,7 @@ static void pci_clean_dpci_irqs(struct d } d->arch.hvm_domain.irq.dpci = NULL; - xfree(hvm_irq_dpci); + free_hvm_irq_dpci(hvm_irq_dpci); } spin_unlock(&d->event_lock); } diff -r fcc71d023408 -r 6705898f768d xen/drivers/passthrough/vtd/x86/vtd.c --- a/xen/drivers/passthrough/vtd/x86/vtd.c Wed May 27 08:19:30 2009 +0100 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c Wed May 27 10:38:51 2009 +0100 @@ -130,9 +130,9 @@ void hvm_dpci_isairq_eoi(struct domain * return; } /* Multiple mirq may be mapped to one isa irq */ - for ( i = find_first_bit(dpci->mapping, NR_IRQS); - i < NR_IRQS; - i = find_next_bit(dpci->mapping, NR_IRQS, i + 1) ) + for ( i = find_first_bit(dpci->mapping, d->nr_pirqs); + i < d->nr_pirqs; + i = find_next_bit(dpci->mapping, d->nr_pirqs, i + 1) ) { list_for_each_entry_safe ( digl, tmp, &dpci->mirq[i].digl_list, list ) diff -r fcc71d023408 -r 6705898f768d xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/asm-x86/config.h Wed May 27 10:38:51 2009 +0100 @@ -50,12 +50,6 @@ #define NR_CPUS MAX_PHYS_CPUS #else #define NR_CPUS 32 -#endif - -#ifdef MAX_PHYS_IRQS -#define NR_IRQS MAX_PHYS_IRQS -#else -#define NR_IRQS 256 #endif #if defined(__i386__) && (NR_CPUS > 32) diff -r fcc71d023408 -r 6705898f768d xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/asm-x86/domain.h Wed May 27 10:38:51 2009 +0100 @@ -263,7 +263,7 @@ struct arch_domain /* NB. protected by d->event_lock and by irq_desc[vector].lock */ int vector_pirq[NR_VECTORS]; - s16 pirq_vector[NR_IRQS]; + s16 *pirq_vector; /* Shared page for notifying that explicit PIRQ EOI is required. */ unsigned long *pirq_eoi_map; diff -r fcc71d023408 -r 6705898f768d xen/include/asm-x86/io_apic.h --- a/xen/include/asm-x86/io_apic.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/asm-x86/io_apic.h Wed May 27 10:38:51 2009 +0100 @@ -175,11 +175,14 @@ extern int timer_uses_ioapic_pin_0; extern int timer_uses_ioapic_pin_0; #endif /*CONFIG_ACPI_BOOT*/ +extern void init_ioapic_mappings(void); + extern int (*ioapic_renumber_irq)(int ioapic, int irq); extern void ioapic_suspend(void); extern void ioapic_resume(void); #else /* !CONFIG_X86_IO_APIC */ +static inline void init_ioapic_mappings(void) {} static inline void ioapic_suspend(void) {} static inline void ioapic_resume(void) {} #endif diff -r fcc71d023408 -r 6705898f768d xen/include/asm-x86/irq.h --- a/xen/include/asm-x86/irq.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/asm-x86/irq.h Wed May 27 10:38:51 2009 +0100 @@ -18,7 +18,7 @@ #define vector_to_irq(vec) (vector_irq[vec]) extern int vector_irq[NR_VECTORS]; -extern u8 irq_vector[NR_IRQS]; +extern u8 *irq_vector; #define platform_legacy_irq(irq) ((irq) < 16) diff -r fcc71d023408 -r 6705898f768d xen/include/xen/hvm/irq.h --- a/xen/include/xen/hvm/irq.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/xen/hvm/irq.h Wed May 27 10:38:51 2009 +0100 @@ -68,21 +68,26 @@ struct hvm_girq_dpci_mapping { #define NR_ISAIRQS 16 #define NR_LINK 4 +#if defined(__i386__) || defined(__x86_64__) +# define NR_HVM_IRQS VIOAPIC_NUM_PINS +#elif defined(__ia64__) +# define NR_HVM_IRQS VIOSAPIC_NUM_PINS +#endif /* Protected by domain's event_lock */ struct hvm_irq_dpci { /* Machine IRQ to guest device/intx mapping. */ - DECLARE_BITMAP(mapping, NR_IRQS); - struct hvm_mirq_dpci_mapping mirq[NR_IRQS]; + unsigned long *mapping; + struct hvm_mirq_dpci_mapping *mirq; + unsigned long *dirq_mask; /* Guest IRQ to guest device/intx mapping. */ - struct list_head girq[NR_IRQS]; - uint8_t msi_gvec_pirq[NR_VECTORS]; - DECLARE_BITMAP(dirq_mask, NR_IRQS); + struct list_head girq[NR_HVM_IRQS]; + uint8_t msi_gvec_pirq[0x100]; /* Record of mapped ISA IRQs */ DECLARE_BITMAP(isairq_map, NR_ISAIRQS); /* Record of mapped Links */ uint8_t link_cnt[NR_LINK]; - struct timer hvm_timer[NR_IRQS]; + struct timer hvm_timer[NR_VECTORS]; }; /* Modify state of a PCI INTx wire. */ diff -r fcc71d023408 -r 6705898f768d xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/xen/iommu.h Wed May 27 10:38:51 2009 +0100 @@ -91,6 +91,7 @@ void hvm_dpci_isairq_eoi(struct domain * void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq); struct hvm_irq_dpci *domain_get_irq_dpci(struct domain *domain); int domain_set_irq_dpci(struct domain *domain, struct hvm_irq_dpci *dpci); +void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci); #define PT_IRQ_TIME_OUT MILLISECS(8) #define VTDPREFIX "[VT-D]" diff -r fcc71d023408 -r 6705898f768d xen/include/xen/irq.h --- a/xen/include/xen/irq.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/xen/irq.h Wed May 27 10:38:51 2009 +0100 @@ -48,6 +48,12 @@ typedef struct hw_interrupt_type hw_irq_ typedef struct hw_interrupt_type hw_irq_controller; #include <asm/irq.h> + +#ifdef NR_IRQS +# define nr_irqs NR_IRQS +#else +extern unsigned int nr_irqs; +#endif struct msi_desc; /* diff -r fcc71d023408 -r 6705898f768d xen/include/xen/sched.h --- a/xen/include/xen/sched.h Wed May 27 08:19:30 2009 +0100 +++ b/xen/include/xen/sched.h Wed May 27 10:38:51 2009 +0100 @@ -200,8 +200,9 @@ struct domain * domain's event-channel spinlock. Read accesses can also synchronise on * the lock, but races don't usually matter. */ - u16 pirq_to_evtchn[NR_IRQS]; - DECLARE_BITMAP(pirq_mask, NR_IRQS); + unsigned int nr_pirqs; + u16 *pirq_to_evtchn; + unsigned long *pirq_mask; /* I/O capabilities (access to IRQs and memory-mapped I/O). */ struct rangeset *iomem_caps; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |