Jan Beulich
2009-Jan-14 10:15 UTC
[Xen-devel] [PATCH] 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. The 3.3 changes needed are somewhat different (because of MSI there having an enabling flag), hence the respective patch (in cased desired - it is strictly needed only when MSI defaults to ''on'', as otherwise the explicit requesting of MSI on a machine that doesn''t have an APIC is pointless) is attached. Signed-off-by: Jan Beulich <jbeulich@novell.com> --- 2009-01-08.orig/xen/arch/x86/apic.c 2008-12-23 09:04:01.000000000 +0100 +++ 2009-01-08/xen/arch/x86/apic.c 2009-01-09 16:12:26.000000000 +0100 @@ -40,7 +40,7 @@ /* * Knob to control our willingness to enable the local APIC. */ -int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ +static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ /* * Debug level @@ -742,7 +742,7 @@ static void apic_pm_activate(void) static void __init lapic_disable(char *str) { enable_local_apic = -1; - clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); + setup_clear_cpu_cap(X86_FEATURE_APIC); } custom_param("nolapic", lapic_disable); --- 2009-01-08.orig/xen/arch/x86/cpu/common.c 2008-11-19 17:37:33.000000000 +0100 +++ 2009-01-08/xen/arch/x86/cpu/common.c 2009-01-09 16:05:08.000000000 +0100 @@ -29,6 +29,14 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM */ u64 host_pat = 0x050100070406; +static unsigned int __cpuinitdata cleared_caps[NCAPINTS]; + +void __init setup_clear_cpu_cap(unsigned int cap) +{ + __clear_bit(cap, boot_cpu_data.x86_capability); + __set_bit(cap, cleared_caps); +} + static void default_init(struct cpuinfo_x86 * c) { /* Not much we can do here... */ @@ -235,6 +243,7 @@ static void __init early_cpu_detect(void if (c->x86 >= 0x6) c->x86_model += ((tfms >> 16) & 0xF) << 4; c->x86_mask = tfms & 15; + cap0 &= ~cleared_caps[0]; if (cap0 & (1<<19)) c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; c->x86_capability[0] = cap0; /* Added for Xen bootstrap */ @@ -395,6 +404,9 @@ void __cpuinit identify_cpu(struct cpuin if (disable_pse) clear_bit(X86_FEATURE_PSE, c->x86_capability); + for (i = 0 ; i < NCAPINTS ; ++i) + c->x86_capability[i] &= ~cleared_caps[i]; + /* If the model name is still unset, do table lookup. */ if ( !c->x86_model_id[0] ) { char *p; --- 2009-01-08.orig/xen/arch/x86/io_apic.c 2008-12-23 09:04:01.000000000 +0100 +++ 2009-01-08/xen/arch/x86/io_apic.c 2009-01-09 12:43:35.000000000 +0100 @@ -84,7 +84,9 @@ int disable_timer_pin_1 __initdata; static struct irq_pin_list { int apic, pin, next; -} irq_2_pin[PIN_MAP_SIZE]; +} irq_2_pin[PIN_MAP_SIZE] = { + [0 ... PIN_MAP_SIZE-1].pin = -1 +}; static int irq_2_pin_free_entry = NR_IRQS; int vector_irq[NR_VECTORS] __read_mostly = { @@ -1018,11 +1020,6 @@ static void __init enable_IO_APIC(void) int i, apic; unsigned long flags; - for (i = 0; i < PIN_MAP_SIZE; i++) { - irq_2_pin[i].pin = -1; - irq_2_pin[i].next = 0; - } - /* Initialise dynamic irq_2_pin free list. */ for (i = NR_IRQS; i < PIN_MAP_SIZE; i++) irq_2_pin[i].next = i + 1; --- 2009-01-08.orig/xen/arch/x86/irq.c 2009-01-08 10:57:04.000000000 +0100 +++ 2009-01-08/xen/arch/x86/irq.c 2009-01-09 16:38:05.000000000 +0100 @@ -863,8 +863,8 @@ int map_domain_pirq( return -EINVAL; } - old_vector = d->arch.pirq_vector[pirq]; - old_pirq = d->arch.vector_pirq[vector]; + old_vector = domain_irq_to_vector(d, pirq); + old_pirq = domain_vector_to_irq(d, vector); if ( (old_vector && (old_vector != vector) ) || (old_pirq && (old_pirq != pirq)) ) @@ -888,6 +888,10 @@ int map_domain_pirq( { struct msi_info *msi = (struct msi_info *)data; + ret = -ENODEV; + if ( !cpu_has_apic ) + goto done; + pdev = pci_get_pdev(msi->bus, msi->devfn); ret = pci_enable_msi(msi, &msi_desc); if ( ret ) @@ -933,7 +937,7 @@ int unmap_domain_pirq(struct domain *d, ASSERT(spin_is_locked(&pcidevs_lock)); ASSERT(spin_is_locked(&d->event_lock)); - vector = d->arch.pirq_vector[pirq]; + vector = domain_irq_to_vector(d, pirq); if ( vector <= 0 ) { dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", @@ -954,7 +958,7 @@ int unmap_domain_pirq(struct domain *d, spin_lock_irqsave(&desc->lock, flags); - BUG_ON(vector != d->arch.pirq_vector[pirq]); + BUG_ON(vector != domain_irq_to_vector(d, pirq)); if ( msi_desc ) teardown_msi_vector(vector); --- 2009-01-08.orig/xen/arch/x86/physdev.c 2008-12-23 09:04:01.000000000 +0100 +++ 2009-01-08/xen/arch/x86/physdev.c 2009-01-09 12:09:05.000000000 +0100 @@ -103,14 +103,14 @@ static int physdev_map_pirq(struct physd spin_lock(&pcidevs_lock); /* Verify or get pirq. */ spin_lock(&d->event_lock); + pirq = domain_vector_to_irq(d, vector); if ( map->pirq < 0 ) { - if ( d->arch.vector_pirq[vector] ) + if ( pirq ) { dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n", d->domain_id, map->index, map->pirq, - d->arch.vector_pirq[vector]); - pirq = d->arch.vector_pirq[vector]; + pirq); if ( pirq < 0 ) { ret = -EBUSY; @@ -130,8 +130,7 @@ static int physdev_map_pirq(struct physd } else { - if ( d->arch.vector_pirq[vector] && - d->arch.vector_pirq[vector] != map->pirq ) + if ( pirq && pirq != map->pirq ) { dprintk(XENLOG_G_ERR, "dom%d: vector %d conflicts with irq %d\n", d->domain_id, map->index, map->pirq); --- 2009-01-08.orig/xen/include/asm-x86/irq.h 2008-12-23 09:04:01.000000000 +0100 +++ 2009-01-08/xen/include/asm-x86/irq.h 2009-01-09 12:12:22.000000000 +0100 @@ -61,8 +61,12 @@ int unmap_domain_pirq(struct domain *d, int get_free_pirq(struct domain *d, int type, int index); void free_domain_pirqs(struct domain *d); -#define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)]) -#define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)]) +#define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[irq] ?: \ + IO_APIC_IRQ(irq) ? 0 : LEGACY_VECTOR(irq)) +#define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[vec] ?: \ + ((vec) < FIRST_LEGACY_VECTOR || \ + (vec) > LAST_LEGACY_VECTOR) ? \ + 0 : LEGACY_IRQ_FROM_VECTOR(vec)) int pirq_guest_force_unbind(struct domain *d, int irq); --- 2009-01-08.orig/xen/include/asm-x86/processor.h 2008-12-23 09:04:01.000000000 +0100 +++ 2009-01-08/xen/include/asm-x86/processor.h 2009-01-09 15:52:17.000000000 +0100 @@ -191,6 +191,7 @@ extern int phys_proc_id[NR_CPUS]; extern int cpu_core_id[NR_CPUS]; extern void identify_cpu(struct cpuinfo_x86 *); +extern void setup_clear_cpu_cap(unsigned int); extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); extern void dodgy_tsc(void); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel