diff -Naur -X /root/bin/dontdiff a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig 2004-08-10 10:41:57.000000000 -0700 +++ b/arch/i386/Kconfig 2004-08-10 10:57:11.000000000 -0700 @@ -482,6 +482,20 @@ This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. +config X86_MPS + bool "Use MPS tables for config" + depends on SMP + depends on X86_LOCAL_APIC || X86_VOYAGER && !X86_VISWS + default y + help + MPS is one interface used to discover CPUs and IOAPICs. ACPI is the + other. One of these must be chosen for SMP to work. + +config X86_MPPARSE + bool + depends on X86_LOCAL_APIC && !X86_VISWS + default y + config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on SMP @@ -1298,16 +1312,6 @@ on the VM subsystem for higher order allocations. This option will also use IRQ stacks to compensate for the reduced stackspace. -config X86_FIND_SMP_CONFIG - bool - depends on X86_LOCAL_APIC || X86_VOYAGER - default y - -config X86_MPPARSE - bool - depends on X86_LOCAL_APIC && !X86_VISWS - default y - endmenu source "security/Kconfig" diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c --- a/arch/i386/kernel/acpi/boot.c 2004-08-10 10:44:03.000000000 -0700 +++ b/arch/i386/kernel/acpi/boot.c 2004-08-10 11:00:02.094581232 -0700 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,9 @@ #include #include #include +#include #include +#include #ifdef CONFIG_X86_64 @@ -76,6 +79,9 @@ int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; +int acpi_nr_isos; +struct acpi_iso_entry acpi_isos[ACPI_MAX_ISOS]; + #ifdef CONFIG_X86_LOCAL_APIC static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #endif @@ -225,7 +231,7 @@ if (processor->flags.enabled == 0) return 0; - mp_register_lapic ( + acpi_register_lapic ( processor->id, /* APIC ID */ processor->flags.enabled); /* Enabled? */ @@ -285,7 +291,7 @@ acpi_table_print_madt_entry(header); - mp_register_ioapic ( + acpi_register_io_apic ( ioapic->id, ioapic->address, ioapic->global_irq_base); @@ -312,15 +318,11 @@ if (acpi_sci_flags.polarity) polarity = acpi_sci_flags.polarity; - /* - * mp_config_acpi_legacy_irqs() already setup IRQs < 16 - * If GSI is < 16, this will update its flags, - * else it will create a new mp_irqs[] entry. - */ - mp_override_legacy_irq(gsi, polarity, trigger, gsi); + /* Register this override */ + acpi_override_legacy_irq(gsi, polarity, trigger, gsi); /* - * stash over-ride to indicate we've been here + * Stash over-ride to indicate we've been here * and for later update of acpi_fadt */ acpi_sci_override_gsi = gsi; @@ -352,7 +354,7 @@ return 0; } - mp_override_legacy_irq ( + acpi_override_legacy_irq ( intsrc->bus_irq, intsrc->flags.polarity, intsrc->flags.trigger, @@ -375,7 +377,7 @@ acpi_table_print_madt_entry(header); - /* TBD: Support nimsrc entries? */ + /* TBD: Support nmisrc entries? */ return 0; } @@ -463,7 +465,7 @@ #ifdef CONFIG_X86_IO_APIC if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { - mp_register_gsi(gsi, edge_level, active_high_low); + acpi_register_io_apic_gsi(gsi, edge_level, active_high_low); } #endif acpi_gsi_to_irq(gsi, &irq); @@ -615,6 +617,51 @@ } #ifdef CONFIG_X86_LOCAL_APIC + +#ifdef CONFIG_X86_IO_APIC +static void +acpi_apicid_changed(u8 apic, u8 oldid, u8 newid) +{ + u8 other_apic; + + for (other_apic = 0; other_apic < nr_ioapics; other_apic++) + if (acpi_ioapic_routing[other_apic].apic_id == newid) { + acpi_ioapic_routing[other_apic].apic_id = oldid; + break; + } + + acpi_ioapic_routing[apic].apic_id = newid; +} + +void acpi_setup_io_apic_irqs(void); + +static int +acpi_find_isa_irq_pin(int irq, int type) +{ + int i; + int pin = irq; + + /* ACPI ISA pins should be identity-mapped, except for ISOs */ + for (i = 0; i < acpi_nr_isos; i++) { + if (irq == acpi_isos[i].source) { + pin = acpi_isos[i].gsi; + break; + } + } + + return pin; +} +#endif + +static struct smp_enumerator acpi_enum = +{ +#ifdef CONFIG_X86_IO_APIC + .apicid_changed = acpi_apicid_changed, + .setup_io_apic_irqs = acpi_setup_io_apic_irqs, + .find_isa_irq_pin = acpi_find_isa_irq_pin, +#endif +}; + /* * Parse LAPIC entries in MADT * returns 0 on success, < 0 on error @@ -635,25 +682,22 @@ return count; } - mp_register_lapic_address(acpi_lapic_addr); + acpi_register_lapic_address(acpi_lapic_addr); count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, MAX_APICS); if (!count) { printk(KERN_ERR PREFIX "No LAPIC entries present\n"); - /* TBD: Cleanup to allow fallback to MPS */ return -ENODEV; } else if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ return count; } count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ return count; } return 0; @@ -702,7 +746,6 @@ count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ return count; } @@ -713,13 +756,9 @@ if (!acpi_sci_override_gsi) acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); - /* Fill in identity legacy mapings where no override */ - mp_config_acpi_legacy_irqs(); - count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ return count; } @@ -759,6 +798,7 @@ acpi_ioapic = 1; smp_found_config = 1; + smp_enumerator_register(&acpi_enum); clustered_apic_check(); } } diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c 2004-08-10 10:44:51.000000000 -0700 +++ b/arch/i386/kernel/apic.c 2004-08-10 11:00:57.573696634 -0700 @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -39,6 +39,8 @@ #include "io_ports.h" +int pic_mode; + static void apic_pm_activate(void); void __init apic_intr_init(void) @@ -547,7 +549,7 @@ */ rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + l |= MSR_IA32_APICBASE_ENABLE | smp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); @@ -688,12 +690,12 @@ return -1; } set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + smp_lapic_addr = APIC_DEFAULT_PHYS_BASE; /* The BIOS may have set up the APIC at some other address */ rdmsr(MSR_IA32_APICBASE, l, h); if (l & MSR_IA32_APICBASE_ENABLE) - mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; + smp_lapic_addr = l & MSR_IA32_APICBASE_BASE; if (nmi_watchdog != NMI_NONE) nmi_watchdog = NMI_LOCAL_APIC; @@ -716,25 +718,22 @@ /* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another - * one for the IO-APIC. + * one for the IO-APIC. Otherwise, the SMP enumerator should + * have already called smp_set_lapic_address. */ if (!smp_found_config && detect_init_APIC()) { apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); apic_phys = __pa(apic_phys); - } else - apic_phys = mp_lapic_addr; - - set_fixmap_nocache(FIX_APIC_BASE, apic_phys); - Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); + smp_set_lapic_address(apic_phys); + } /* - * Fetch the APIC ID of the BSP in case we have a - * default configuration (or the MP table is broken). + * Fetch the APIC ID of the BSP */ if (boot_cpu_physical_apicid == -1U) boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); -#ifdef CONFIG_X86_IO_APIC +#ifdef CONFIG_X86_IO_APIC_DONTNEED { unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; int i; diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c 2004-08-10 10:44:44.000000000 -0700 +++ b/arch/i386/kernel/i386_ksyms.c 2004-08-10 11:00:51.402573669 -0700 @@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(flush_tlb_all); #endif -#ifdef CONFIG_X86_IO_APIC +#ifdef CONFIG_X86_MPS EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); #endif diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c 2004-08-10 10:42:17.000000000 -0700 +++ b/arch/i386/kernel/io_apic.c 2004-08-10 10:57:46.000000000 -0700 @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -249,9 +250,6 @@ # ifdef CONFIG_BALANCED_IRQ_DEBUG # define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) # define Dprintk(x...) do { TDprintk(x); } while (0) -# else -# define TDprintk(x...) -# define Dprintk(x...) # endif extern cpumask_t irq_affinity[NR_IRQS]; @@ -694,6 +692,7 @@ __setup("noapic", ioapic_setup); +#ifdef CONFIG_X86_MPS static int __init ioapic_pirq_setup(char *str) { int i, max; @@ -722,6 +721,10 @@ __setup("pirq=", ioapic_pirq_setup); +/* DELETE */ +extern struct mps_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; +extern int mp_irq_entries; + /* * Find the IRQ entry number of a certain pin. */ @@ -731,7 +734,7 @@ for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].mpc_irqtype == type && - (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid || + (mp_irqs[i].mpc_dstapic == smp_ioapics[apic].apicid || mp_irqs[i].mpc_dstapic == MP_APIC_ALL) && mp_irqs[i].mpc_dstirq == pin) return i; @@ -742,7 +745,7 @@ /* * Find the pin to which IRQ[irq] (ISA) is connected */ -static int __init find_isa_irq_pin(int irq, int type) +int __init mps_find_isa_irq_pin(int irq, int type) { int i; @@ -782,7 +785,7 @@ int lbus = mp_irqs[i].mpc_srcbus; for (apic = 0; apic < nr_ioapics; apic++) - if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic || + if (smp_ioapics[apic].apicid == mp_irqs[i].mpc_dstapic || mp_irqs[i].mpc_dstapic == MP_APIC_ALL) break; @@ -807,6 +810,7 @@ } return best_guess; } +#endif /* * This function currently is only a helper for the i386 smp boot process where @@ -815,23 +819,16 @@ */ void __init setup_ioapic_dest(void) { - int pin, ioapic, irq, irq_entry; + int irq; if (skip_ioapic_setup == 1) return; - for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { - for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { - irq_entry = find_irq_entry(ioapic, pin, mp_INT); - if (irq_entry == -1) - continue; - irq = pin_2_irq(irq_entry, ioapic, pin); - set_ioapic_affinity_irq(irq, TARGET_CPUS); - } - - } + for (irq = 0; irq < NR_IRQS; irq++) + set_ioapic_affinity_irq(irq, TARGET_CPUS); } +#ifdef CONFIG_X86_MPS /* * EISA Edge/Level control register, ELCR */ @@ -887,7 +884,7 @@ */ switch (mp_irqs[idx].mpc_irqflag & 3) { - case 0: /* conforms, ie. bus-type dependent polarity */ + case POLARITY_CONFORMS: /* bus-type dependent polarity */ { switch (mp_bus_id_to_type[bus]) { @@ -925,18 +922,18 @@ } break; } - case 1: /* high active */ + case POLARITY_ACTIVE_HIGH: { polarity = 0; break; } - case 2: /* reserved */ + case POLARITY_RESERVED: { printk(KERN_WARNING "broken BIOS!!\n"); polarity = 1; break; } - case 3: /* low active */ + case POLARITY_ACTIVE_LOW: { polarity = 1; break; @@ -961,7 +958,7 @@ */ switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) { - case 0: /* conforms, ie. bus-type dependent */ + case TRIGGER_CONFORMS: /* bus-type dependent */ { switch (mp_bus_id_to_type[bus]) { @@ -999,18 +996,18 @@ } break; } - case 1: /* edge */ + case TRIGGER_EDGE: { trigger = 0; break; } - case 2: /* reserved */ + case TRIGGER_RESERVED: { printk(KERN_WARNING "broken BIOS!!\n"); trigger = 1; break; } - case 3: /* level */ + case TRIGGER_LEVEL: { trigger = 1; break; @@ -1110,6 +1107,7 @@ */ return 0; } +#endif /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; @@ -1147,10 +1145,7 @@ static struct hw_interrupt_type ioapic_level_type; static struct hw_interrupt_type ioapic_edge_type; -#define IOAPIC_AUTO -1 -#define IOAPIC_EDGE 0 -#define IOAPIC_LEVEL 1 - +#ifdef CONFIG_X86_MPS static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) { if (use_pci_vector() && !platform_legacy_irq(irq)) { @@ -1170,7 +1165,7 @@ } } -void __init setup_IO_APIC_irqs(void) +void __init mps_setup_io_apic_irqs(void) { struct IO_APIC_route_entry entry; int apic, pin, idx, irq, first_notcon = 1, vector; @@ -1195,10 +1190,10 @@ idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { if (first_notcon) { - printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); + printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", smp_ioapics[apic].apicid, pin); first_notcon = 0; } else - printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin); + printk(", %d-%d", smp_ioapics[apic].apicid, pin); continue; } @@ -1241,6 +1236,7 @@ if (!first_notcon) printk(" not connected.\n"); } +#endif /* * Set up the 8259A-master output pin: @@ -1299,10 +1295,12 @@ union IO_APIC_reg_03 reg_03; unsigned long flags; +#ifdef CONFIG_X86_MPS printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); +#endif for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", - mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]); + smp_ioapics[i].apicid, nr_ioapic_registers[i]); /* * We are a bit conservative about what we expect. We have to @@ -1321,7 +1319,7 @@ reg_03.raw = io_apic_read(apic, 3); spin_unlock_irqrestore(&ioapic_lock, flags); - printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); + printk(KERN_DEBUG "IO APIC #%d......\n", smp_ioapics[apic].apicid); printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); @@ -1612,22 +1610,62 @@ disconnect_bsp_APIC(); } +#ifndef CONFIG_X86_NUMAQ +/* + * We must ensure apic <--> irq_entries stay in sync. + */ +static void __init +io_apic_swap_ids(int apic, int oldid, int newid) +{ + int other_apic; + + if (oldid == newid) + return; + + /* The MP enumerator code needs to know an apicid is changed */ + smp_enum.apicid_changed(apic, oldid, newid); + + for (other_apic = 0; other_apic < nr_ioapics; other_apic++) + if (smp_ioapics[other_apic].apicid == newid) { + smp_ioapics[other_apic].apicid = oldid; + break; + } + + smp_ioapics[apic].apicid = newid; +} +#endif + /* - * function to set the IO-APIC physical IDs based on the - * values stored in the MPC table. + * Every APIC in a system must have a unique ID or we get lots of nice + * 'stuck on smp_invalidate_needed IPI wait' messages. + * According to the MPS spec section 3.6.6, we should assign apicids + * by the following method: + * + * 1) Use the hw value (if no conflict) + * 2) Use the value from the BIOS (if no conflict) + * 3) Pick a free apicid and use that + * + * The P4 platform supports up to 256 APIC IDs on two separate APIC + * buses (one for LAPICs, one for IOAPICs), where predecessors only + * supports up to 16 on one shared APIC bus. + * + * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full + * advantage of new APIC bus architecture. * * by Matt Domsch Tue Dec 21 12:25:05 CST 1999 + * re-arched for MPS/ACPI coexistance by Andy Grover */ - #ifndef CONFIG_X86_NUMAQ -static void __init setup_ioapic_ids_from_mpc(void) +static void __init setup_ioapic_ids (void) { union IO_APIC_reg_00 reg_00; physid_mask_t phys_id_present_map; + physid_mask_t tmp; + unsigned long flags; + int unique_id; + int bios_id; int apic; int i; - unsigned char old_id; - unsigned long flags; /* * This is broken; anything with a real cpu count has to @@ -1635,92 +1673,83 @@ */ phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map); - /* - * Set the IOAPIC ID to the value stored in the MPC table. - */ for (apic = 0; apic < nr_ioapics; apic++) { - /* Read the register 0 value */ + bios_id = smp_ioapics[apic].apicid; + spin_lock_irqsave(&ioapic_lock, flags); reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - - old_id = mp_ioapics[apic].mpc_apicid; - - if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) { - printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", - apic, mp_ioapics[apic].mpc_apicid); - printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - reg_00.bits.ID); - mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; - } /* Don't check I/O APIC IDs for some xAPIC systems. They have * no meaning without the serial APIC bus. */ if (NO_IOAPIC_CHECK) continue; - /* - * Sanity check, is the ID really free? Every APIC in a - * system must have a unique ID or we get lots of nice - * 'stuck on smp_invalidate_needed IPI wait' messages. - */ - if (check_apicid_used(phys_id_present_map, - mp_ioapics[apic].mpc_apicid)) { - printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", - apic, mp_ioapics[apic].mpc_apicid); - for (i = 0; i < get_physical_broadcast(); i++) - if (!physid_isset(i, phys_id_present_map)) - break; - if (i >= get_physical_broadcast()) - panic("Max APIC ID exceeded!\n"); - printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - i); - physid_set(i, phys_id_present_map); - mp_ioapics[apic].mpc_apicid = i; - } else { - physid_mask_t tmp; - tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid); - printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid); - physids_or(phys_id_present_map, phys_id_present_map, tmp); + + /* 1) Try what was in the HW's ID register */ + unique_id = reg_00.bits.ID; + + if (!check_apicid_used(phys_id_present_map, unique_id)) { + Dprintk("Using HW apicid value %d for IOAPIC %d\n", + unique_id, apic); + goto success; } + /* 2) Try the BIOS apicid value */ + unique_id = bios_id; - /* - * We need to adjust the IRQ routing table - * if the ID changed. - */ - if (old_id != mp_ioapics[apic].mpc_apicid) - for (i = 0; i < mp_irq_entries; i++) - if (mp_irqs[i].mpc_dstapic == old_id) - mp_irqs[i].mpc_dstapic - = mp_ioapics[apic].mpc_apicid; + if (unique_id >= get_physical_broadcast()) { + printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, n", + apic, unique_id); + } + else if (!check_apicid_used(phys_id_present_map, unique_id)) { + Dprintk("Using BIOS apicid value %d for IOAPIC %d\n", + unique_id, apic); + goto success; + } - /* - * Read the right value from the MPC table and - * write it into the ID register. - */ - printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mp_ioapics[apic].mpc_apicid); + /* 3) Get an unassigned apicid and use that */ + for (i = 0; i < get_physical_broadcast(); i++) { + if (!check_apicid_used(phys_id_present_map, i)) + break; + } - reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; - spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0, reg_00.raw); - spin_unlock_irqrestore(&ioapic_lock, flags); + if (i == get_physical_broadcast()) + panic("Max apic_id exceeded!\n"); + + unique_id = i; + + printk(KERN_WARNING "IOAPIC[%d]: apic_ids in HW (%d) and BIOS (%d)" + " already used, using free id %d\n", apic, reg_00.bits.ID, + bios_id, unique_id); +success: + tmp = apicid_to_cpu_present(unique_id); + physids_or(phys_id_present_map, phys_id_present_map, tmp); + + /* sync new apicid with interrupt entries */ + if (unique_id != bios_id) + io_apic_swap_ids(apic, bios_id, unique_id); + } + + /* apicids are now properly allocated. Program the HW */ + for (apic = 0; apic < nr_ioapics; apic++) { + reg_00.bits.ID = smp_ioapics[apic].apicid; - /* - * Sanity check - */ spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(apic, 0, reg_00.raw); reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); - else - printk(" ok.\n"); + + /* Sanity check */ + if (reg_00.bits.ID != smp_ioapics[apic].apicid) + panic("IOAPIC[%d]: Unable to change apic_id!\n", apic); + + printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", apic, + smp_ioapics[apic].apicid); } } #else -static void __init setup_ioapic_ids_from_mpc(void) { } +static void __init setup_ioapic_ids(void) { } #endif /* @@ -2052,7 +2081,7 @@ unsigned char save_control, save_freq_select; unsigned long flags; - pin = find_isa_irq_pin(8, mp_INT); + pin = smp_enum.find_isa_irq_pin(8, mp_INT); if (pin == -1) return; @@ -2130,8 +2159,8 @@ timer_ack = 1; enable_8259A_irq(0); - pin1 = find_isa_irq_pin(0, mp_INT); - pin2 = find_isa_irq_pin(0, mp_ExtINT); + pin1 = smp_enum.find_isa_irq_pin(0, mp_INT); + pin2 = smp_enum.find_isa_irq_pin(0, mp_ExtINT); printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); @@ -2238,10 +2267,9 @@ /* * Set up IO-APIC IRQ routing. */ - if (!acpi_ioapic) - setup_ioapic_ids_from_mpc(); + setup_ioapic_ids(); sync_Arb_IDs(); - setup_IO_APIC_irqs(); + smp_enum.setup_io_apic_irqs(); init_IO_APIC_traps(); check_timer(); if (!acpi_ioapic) @@ -2268,77 +2296,6 @@ #ifdef CONFIG_ACPI_BOOT -int __init io_apic_get_unique_id (int ioapic, int apic_id) -{ - union IO_APIC_reg_00 reg_00; - static physid_mask_t apic_id_map = PHYSID_MASK_NONE; - physid_mask_t tmp; - unsigned long flags; - int i = 0; - - /* - * The P4 platform supports up to 256 APIC IDs on two separate APIC - * buses (one for LAPICs, one for IOAPICs), where predecessors only - * supports up to 16 on one shared APIC bus. - * - * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full - * advantage of new APIC bus architecture. - */ - - if (physids_empty(apic_id_map)) - apic_id_map = ioapic_phys_id_map(phys_cpu_present_map); - - spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic, 0); - spin_unlock_irqrestore(&ioapic_lock, flags); - - if (apic_id >= get_physical_broadcast()) { - printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " - "%d\n", ioapic, apic_id, reg_00.bits.ID); - apic_id = reg_00.bits.ID; - } - - /* - * Every APIC in a system must have a unique ID or we get lots of nice - * 'stuck on smp_invalidate_needed IPI wait' messages. - */ - if (check_apicid_used(apic_id_map, apic_id)) { - - for (i = 0; i < get_physical_broadcast(); i++) { - if (!check_apicid_used(apic_id_map, i)) - break; - } - - if (i == get_physical_broadcast()) - panic("Max apic_id exceeded!\n"); - - printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " - "trying %d\n", ioapic, apic_id, i); - - apic_id = i; - } - - tmp = apicid_to_cpu_present(apic_id); - physids_or(apic_id_map, apic_id_map, tmp); - - if (reg_00.bits.ID != apic_id) { - reg_00.bits.ID = apic_id; - - spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, reg_00.raw); - reg_00.raw = io_apic_read(ioapic, 0); - spin_unlock_irqrestore(&ioapic_lock, flags); - - /* Sanity check */ - if (reg_00.bits.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); - } - - printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); - - return apic_id; -} - int __init io_apic_get_version (int ioapic) { @@ -2365,6 +2322,91 @@ return reg_01.bits.entries; } +int acpi_find_ioapic(int gsi); + +/* + * Setup ISA IRQs. PCI IRQs are setup later, when enabled. + */ +void acpi_setup_io_apic_irqs(void) +{ + struct IO_APIC_route_entry entry; + unsigned long flags; + int ioapic = -1; + int pin; + int irq; + int trigger; + int polarity; + + /* + * Locate the IOAPIC that manages the ISA IRQs (0-15). + */ + ioapic = acpi_find_ioapic(0); + if (ioapic < 0) { + Dprintk("ACPI: Could not find IRQ 0 IOAPIC!\n"); + return; + } + + /* + * Identity-map the 16 ISA IRQs to pins on APIC 0, + * unless there is an interrupt source override (ISO) + */ + for (irq = 0; irq < 16; irq++) + { + int idx; + int overridden = FALSE; + + pin = irq; + trigger = IOAPIC_EDGE; + polarity = IOAPIC_HIGH; + + for (idx = 0; idx < acpi_nr_isos; idx++) { + if (irq == acpi_isos[idx].source) { + trigger = acpi_isos[idx].trigger; + polarity = acpi_isos[idx].polarity; + pin = acpi_isos[idx].gsi; + break; + } + /* abort if there is an override to this pin */ + if (irq == acpi_isos[idx].gsi) { + overridden = TRUE; + break; + } + } + + if (overridden) { + printk(KERN_DEBUG "ACPI: pin %d used by override, leave it.\n", pin); + continue; + } + + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); + entry.trigger = trigger; + entry.polarity = polarity; + entry.mask = 1; + entry.vector = assign_irq_vector(pin); + + if (trigger == IOAPIC_LEVEL) { + irq_desc[irq].handler = &ioapic_level_type; + } else { + irq_desc[irq].handler = &ioapic_edge_type; + } + set_intr_gate(entry.vector, interrupt[irq]); + + add_pin_to_irq(irq, ioapic, pin); + + disable_8259A_irq(irq); + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); + } +} + + int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low) { @@ -2402,7 +2444,7 @@ Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", ioapic, - mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); + smp_ioapics[ioapic].apicid, pin, entry.vector, irq, edge_level, active_high_low); if (use_pci_vector() && !platform_legacy_irq(irq)) irq = IO_APIC_VECTOR(irq); diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2004-08-10 10:42:00.000000000 -0700 +++ b/arch/i386/kernel/Makefile 2004-08-10 10:57:16.000000000 -0700 @@ -21,7 +21,7 @@ obj-$(CONFIG_X86_SMP) += smp.o smpboot.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o +obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o smpenum.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c 2004-08-10 10:42:15.000000000 -0700 +++ b/arch/i386/kernel/mpparse.c 2004-08-10 10:57:44.000000000 -0700 @@ -29,57 +29,35 @@ #include #include #include +#include #include #include #include #include + +#ifdef CONFIG_X86_MPS + /* Have we found an MP table */ -int smp_found_config; -unsigned int __initdata maxcpus = NR_CPUS; +int mps_found_config; + +extern int pic_mode; + +/* # of MP IRQ source entries */ +struct mps_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; +int mp_irq_entries; /* * Various Linux-internal data structures created from the * MP-table. */ -int apic_version [MAX_APICS]; int mp_bus_id_to_type [MAX_MP_BUSSES]; int mp_bus_id_to_node [MAX_MP_BUSSES]; int mp_bus_id_to_local [MAX_MP_BUSSES]; int quad_local_to_mp_bus_id [NR_CPUS/4][4]; int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; -int mp_current_pci_id; - -/* I/O APIC entries */ -struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; - -/* # of MP IRQ source entries */ -struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; - -/* MP IRQ source entries */ -int mp_irq_entries; - -int nr_ioapics; - -int pic_mode; -unsigned long mp_lapic_addr; - -/* Processor that is doing the boot up */ -unsigned int boot_cpu_physical_apicid = -1U; -unsigned int boot_cpu_logical_apicid = -1U; -/* Internal processor count */ -static unsigned int __initdata num_processors; - -/* Bitmask of physically existing CPUs */ -physid_mask_t phys_cpu_present_map; - -u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; - -/* - * Intel MP BIOS table parsing routines: - */ - +int mps_current_pci_id; /* * Checksum an MP configuration block. @@ -95,147 +73,35 @@ return sum & 0xFF; } -/* - * Have to match translation table entries to main table entries by counter - * hence the mpc_record variable .... can't see a less disgusting way of - * doing this .... - */ +extern int mps_record; +extern struct mps_config_translation *translation_table[MAX_MPC_ENTRY]; -static int mpc_record; -static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; -#ifdef CONFIG_X86_NUMAQ -static int MP_valid_apicid(int apicid, int version) -{ - return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf; -} -#else -static int MP_valid_apicid(int apicid, int version) +static void __init mps_processor_info (struct mps_config_processor *m) { - if (version >= 0x14) - return apicid < 0xff; - else - return apicid < 0xf; + if (m->mpc_cpuflag & CPU_ENABLED) + smp_processor_register(m->mpc_apicid, m->mpc_apicver); } -#endif - -void __init MP_processor_info (struct mpc_config_processor *m) -{ - int ver, apicid; - physid_mask_t tmp; - - if (!(m->mpc_cpuflag & CPU_ENABLED)) - return; - - apicid = mpc_apic_id(m, translation_table[mpc_record]); - - if (m->mpc_featureflag&(1<<0)) - Dprintk(" Floating point unit present.\n"); - if (m->mpc_featureflag&(1<<7)) - Dprintk(" Machine Exception supported.\n"); - if (m->mpc_featureflag&(1<<8)) - Dprintk(" 64 bit compare & exchange supported.\n"); - if (m->mpc_featureflag&(1<<9)) - Dprintk(" Internal APIC present.\n"); - if (m->mpc_featureflag&(1<<11)) - Dprintk(" SEP present.\n"); - if (m->mpc_featureflag&(1<<12)) - Dprintk(" MTRR present.\n"); - if (m->mpc_featureflag&(1<<13)) - Dprintk(" PGE present.\n"); - if (m->mpc_featureflag&(1<<14)) - Dprintk(" MCA present.\n"); - if (m->mpc_featureflag&(1<<15)) - Dprintk(" CMOV present.\n"); - if (m->mpc_featureflag&(1<<16)) - Dprintk(" PAT present.\n"); - if (m->mpc_featureflag&(1<<17)) - Dprintk(" PSE present.\n"); - if (m->mpc_featureflag&(1<<18)) - Dprintk(" PSN present.\n"); - if (m->mpc_featureflag&(1<<19)) - Dprintk(" Cache Line Flush Instruction present.\n"); - /* 20 Reserved */ - if (m->mpc_featureflag&(1<<21)) - Dprintk(" Debug Trace and EMON Store present.\n"); - if (m->mpc_featureflag&(1<<22)) - Dprintk(" ACPI Thermal Throttle Registers present.\n"); - if (m->mpc_featureflag&(1<<23)) - Dprintk(" MMX present.\n"); - if (m->mpc_featureflag&(1<<24)) - Dprintk(" FXSR present.\n"); - if (m->mpc_featureflag&(1<<25)) - Dprintk(" XMM present.\n"); - if (m->mpc_featureflag&(1<<26)) - Dprintk(" Willamette New Instructions present.\n"); - if (m->mpc_featureflag&(1<<27)) - Dprintk(" Self Snoop present.\n"); - if (m->mpc_featureflag&(1<<28)) - Dprintk(" HT present.\n"); - if (m->mpc_featureflag&(1<<29)) - Dprintk(" Thermal Monitor present.\n"); - /* 30, 31 Reserved */ - - - if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { - Dprintk(" Bootup CPU\n"); - boot_cpu_physical_apicid = m->mpc_apicid; - boot_cpu_logical_apicid = apicid; - } - - if (num_processors >= NR_CPUS) { - printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." - " Processor ignored.\n", NR_CPUS); - return; - } - if (num_processors >= maxcpus) { - printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." - " Processor ignored.\n", maxcpus); - return; - } - num_processors++; - ver = m->mpc_apicver; - if (!MP_valid_apicid(apicid, ver)) { - printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", - m->mpc_apicid, MAX_APICS); - --num_processors; - return; - } - - tmp = apicid_to_cpu_present(apicid); - physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp); - - /* - * Validate version - */ - if (ver == 0x0) { - printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); - ver = 0x10; - } - apic_version[m->mpc_apicid] = ver; - bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; -} - -static void __init MP_bus_info (struct mpc_config_bus *m) +static void __init mps_bus_info (struct mps_config_bus *m) { char str[7]; memcpy(str, m->mpc_bustype, 6); str[6] = 0; - mpc_oem_bus_info(m, str, translation_table[mpc_record]); + mps_oem_bus_info(m, str, translation_table[mps_record]); if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) { - mpc_oem_pci_bus(m, translation_table[mpc_record]); + mpc_oem_pci_bus(m, translation_table[mps_record]); mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; - mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; - mp_current_pci_id++; + mp_bus_id_to_pci_bus[m->mpc_busid] = mps_current_pci_id; + mps_current_pci_id++; } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) { @@ -245,7 +111,7 @@ } } -static void __init MP_ioapic_info (struct mpc_config_ioapic *m) +static void __init mps_ioapic_info (struct mps_config_ioapic *m) { if (!(m->mpc_flags & MPC_APIC_USABLE)) return; @@ -262,11 +128,11 @@ " found in MP table, skipping!\n"); return; } - mp_ioapics[nr_ioapics] = *m; - nr_ioapics++; + + smp_ioapic_register(m->mpc_apicid, m->mpc_apicaddr); } -static void __init MP_intsrc_info (struct mpc_config_intsrc *m) +static void __init MP_intsrc_info (struct mps_config_intsrc *m) { mp_irqs [mp_irq_entries] = *m; Dprintk("Int: type %d, pol %d, trig %d, bus %d," @@ -278,7 +144,7 @@ panic("Max # of irq sources exceeded!!\n"); } -static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) +static void __init MP_lintsrc_info (struct mps_config_lintsrc *m) { Dprintk("Lint: type %d, pol %d, trig %d, bus %d," " IRQ %02x, APIC ID %x, APIC LINT %02x\n", @@ -301,14 +167,14 @@ } #ifdef CONFIG_X86_NUMAQ -static void __init MP_translation_info (struct mpc_config_translation *m) +static void __init MP_translation_info (struct mps_config_translation *m) { - printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); + printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mps_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); - if (mpc_record >= MAX_MPC_ENTRY) + if (mps_record >= MAX_MPC_ENTRY) printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); else - translation_table[mpc_record] = m; /* stash this for later */ + translation_table[mps_record] = m; /* stash this for later */ if (m->trans_quad+1 > numnodes) numnodes = m->trans_quad+1; } @@ -317,13 +183,13 @@ * Read/parse the MPC oem tables */ -static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ +static void __init mps_read_mpc_oem(struct mp_config_oemtable *oemtable, \ unsigned short oemsize) { int count = sizeof (*oemtable); /* the header size */ unsigned char *oemptr = ((unsigned char *)oemtable)+count; - mpc_record = 0; + mps_record = 0; printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4)) { @@ -343,12 +209,12 @@ switch (*oemptr) { case MP_TRANSLATION: { - struct mpc_config_translation *m= - (struct mpc_config_translation *)oemptr; + struct mps_config_translation *m= + (struct mps_config_translation *)oemptr; MP_translation_info(m); oemptr += sizeof(*m); count += sizeof(*m); - ++mpc_record; + ++mps_record; break; } default: @@ -375,12 +241,13 @@ * Read/parse the MPC */ -static int __init smp_read_mpc(struct mp_config_table *mpc) +static int __init mps_parse_table(struct mp_config_table *mpc) { char str[16]; char oem[10]; int count=sizeof(*mpc); unsigned char *mpt=((unsigned char *)mpc)+count; + int found_processor = 0; if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) { printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n", @@ -413,51 +280,52 @@ printk("APIC at: 0x%lX\n",mpc->mpc_lapic); /* - * Save the local APIC address (it might be non-default) -- but only - * if we're not using ACPI. + * Save the local APIC address (it might be non-default) */ - if (!acpi_lapic) - mp_lapic_addr = mpc->mpc_lapic; + smp_set_lapic_address(mpc->mpc_lapic); /* * Now process the configuration blocks. */ - mpc_record = 0; + mps_record = 0; while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: { - struct mpc_config_processor *m= - (struct mpc_config_processor *)mpt; - /* ACPI may have already provided this data */ - if (!acpi_lapic) - MP_processor_info(m); + struct mps_config_processor *m= + (struct mps_config_processor *)mpt; + + if (!acpi_lapic) { + mps_processor_info(m); + found_processor++; + } + mpt += sizeof(*m); count += sizeof(*m); break; } case MP_BUS: { - struct mpc_config_bus *m= - (struct mpc_config_bus *)mpt; - MP_bus_info(m); + struct mps_config_bus *m= + (struct mps_config_bus *)mpt; + mps_bus_info(m); mpt += sizeof(*m); count += sizeof(*m); break; } case MP_IOAPIC: { - struct mpc_config_ioapic *m= - (struct mpc_config_ioapic *)mpt; - MP_ioapic_info(m); + struct mps_config_ioapic *m= + (struct mps_config_ioapic *)mpt; + mps_ioapic_info(m); mpt+=sizeof(*m); count+=sizeof(*m); break; } case MP_INTSRC: { - struct mpc_config_intsrc *m= - (struct mpc_config_intsrc *)mpt; + struct mps_config_intsrc *m= + (struct mps_config_intsrc *)mpt; MP_intsrc_info(m); mpt+=sizeof(*m); @@ -466,8 +334,8 @@ } case MP_LINTSRC: { - struct mpc_config_lintsrc *m= - (struct mpc_config_lintsrc *)mpt; + struct mps_config_lintsrc *m= + (struct mps_config_lintsrc *)mpt; MP_lintsrc_info(m); mpt+=sizeof(*m); count+=sizeof(*m); @@ -479,12 +347,12 @@ break; } } - ++mpc_record; + ++mps_record; } clustered_apic_check(); - if (!num_processors) + if (!found_processor) printk(KERN_ERR "SMP mptable: no processors registered!\n"); - return num_processors; + return found_processor; } static int __init ELCR_trigger(unsigned int irq) @@ -497,14 +365,14 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) { - struct mpc_config_intsrc intsrc; + struct mps_config_intsrc intsrc; int i; int ELCR_fallback = 0; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqflag = 0; /* conforming */ intsrc.mpc_srcbus = 0; - intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; + intsrc.mpc_dstapic = smp_ioapic_to_ioapicid(0); intsrc.mpc_irqtype = mp_INT; @@ -563,34 +431,22 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) { - struct mpc_config_processor processor; - struct mpc_config_bus bus; - struct mpc_config_ioapic ioapic; - struct mpc_config_lintsrc lintsrc; + struct mps_config_bus bus; + struct mps_config_lintsrc lintsrc; int linttypes[2] = { mp_ExtINT, mp_NMI }; int i; /* * local APIC has default address */ - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + smp_set_lapic_address(APIC_DEFAULT_PHYS_BASE); /* * 2 CPUs, numbered 0 & 1. */ - processor.mpc_type = MP_PROCESSOR; /* Either an integrated APIC or a discrete 82489DX. */ - processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; - processor.mpc_cpuflag = CPU_ENABLED; - processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | - (boot_cpu_data.x86_model << 4) | - boot_cpu_data.x86_mask; - processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; - processor.mpc_reserved[0] = 0; - processor.mpc_reserved[1] = 0; for (i = 0; i < 2; i++) { - processor.mpc_apicid = i; - MP_processor_info(&processor); + smp_processor_register(i, (mpc_default_type > 4 ? 0x10 : 0x01)); } bus.mpc_type = MP_BUS; @@ -614,19 +470,14 @@ case 7: memcpy(bus.mpc_bustype, "MCA ", 6); } - MP_bus_info(&bus); + mps_bus_info(&bus); if (mpc_default_type > 4) { bus.mpc_busid = 1; memcpy(bus.mpc_bustype, "PCI ", 6); - MP_bus_info(&bus); + mps_bus_info(&bus); } - ioapic.mpc_type = MP_IOAPIC; - ioapic.mpc_apicid = 2; - ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; - ioapic.mpc_flags = MPC_APIC_USABLE; - ioapic.mpc_apicaddr = 0xFEC00000; - MP_ioapic_info(&ioapic); + smp_ioapic_register(2, 0xFEC00000); /* * We set up most of the low 16 IO-APIC pins according to MPS rules. @@ -647,10 +498,49 @@ static struct intel_mp_floating *mpf_found; +static void mps_apicid_changed(u8 apic, u8 oldid, u8 newid) +{ + int i; + + for (i = 0; i < mp_irq_entries; i++) { + if (mp_irqs[i].mpc_dstapic == oldid) + mp_irqs[i].mpc_dstapic = newid; + else if (mp_irqs[i].mpc_dstapic == newid) + mp_irqs[i].mpc_dstapic = oldid; + } +} + +static int mps_find_isa_irq_pin(int irq, int type) +{ + int i; + + for (i = 0; i < mp_irq_entries; i++) { + int lbus = mp_irqs[i].mpc_srcbus; + + if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || + mp_bus_id_to_type[lbus] == MP_BUS_EISA || + mp_bus_id_to_type[lbus] == MP_BUS_MCA || + mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + ) && + (mp_irqs[i].mpc_irqtype == type) && + (mp_irqs[i].mpc_srcbusirq == irq)) + + return mp_irqs[i].mpc_dstirq; + } + return -1; +} + +static struct smp_enumerator mps_enum = +{ + .apicid_changed = mps_apicid_changed, + .setup_io_apic_irqs = mps_setup_io_apic_irqs, + .find_isa_irq_pin = mps_find_isa_irq_pin, +}; + /* * Scan the memory blocks for an SMP configuration block. */ -void __init get_smp_config (void) +void __init get_mps_config (void) { struct intel_mp_floating *mpf = mpf_found; @@ -660,11 +550,7 @@ * ACPI supports both logical (e.g. Hyper-Threading) and physical * processors, where MPS only supports physical. */ - if (acpi_lapic && acpi_ioapic) { - printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); - return; - } - else if (acpi_lapic) + if (acpi_lapic) printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); @@ -690,8 +576,9 @@ * Read the physical hardware table. Anything here will * override the defaults. */ - if (!smp_read_mpc((void *)mpf->mpf_physptr)) { + if (!mps_parse_table((void *)mpf->mpf_physptr)) { smp_found_config = 0; + mps_found_config = 0; printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); return; @@ -702,14 +589,14 @@ * ISA defaults and hope it will work. */ if (!mp_irq_entries) { - struct mpc_config_bus bus; + struct mps_config_bus bus; printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); bus.mpc_type = MP_BUS; bus.mpc_busid = 0; memcpy(bus.mpc_bustype, "ISA ", 6); - MP_bus_info(&bus); + mps_bus_info(&bus); construct_default_ioirq_mptable(0); } @@ -717,13 +604,14 @@ } else BUG(); - printk(KERN_INFO "Processors: %d\n", num_processors); /* * Only use the first configuration found. */ + smp_enumerator_register(&mps_enum); + smp_found_config = 1; } -static int __init smp_scan_config (unsigned long base, unsigned long length) +static int __init mps_scan_config (unsigned long base, unsigned long length) { unsigned long *bp = phys_to_virt(base); struct intel_mp_floating *mpf; @@ -740,7 +628,7 @@ ((mpf->mpf_specification == 1) || (mpf->mpf_specification == 4)) ) { - smp_found_config = 1; + mps_found_config = 1; printk(KERN_INFO "found SMP MP-table at %08lx\n", virt_to_phys(mpf)); reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); @@ -770,7 +658,7 @@ return 0; } -void __init find_smp_config (void) +void __init find_mps_config (void) { unsigned int address; @@ -782,9 +670,9 @@ * 2) Scan the top 1K of base RAM * 3) Scan the 64K of bios */ - if (smp_scan_config(0x0,0x400) || - smp_scan_config(639*0x400,0x400) || - smp_scan_config(0xF0000,0x10000)) + if (mps_scan_config(0x0,0x400) || + mps_scan_config(639*0x400,0x400) || + mps_scan_config(0xF0000,0x10000)) return; /* * If it is an SMP machine we should know now, unless the @@ -805,9 +693,10 @@ address = get_bios_ebda(); if (address) - smp_scan_config(address, 0x400); + mps_scan_config(address, 0x400); } +#endif /* CONFIG_X86_MPS */ /* -------------------------------------------------------------------------- ACPI-based MP Configuration @@ -815,26 +704,19 @@ #ifdef CONFIG_ACPI_BOOT -void __init mp_register_lapic_address ( +void __init acpi_register_lapic_address ( u64 address) { - mp_lapic_addr = (unsigned long) address; - - set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); - - if (boot_cpu_physical_apicid == -1U) - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); - - Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); + smp_set_lapic_address((unsigned long) address); } -void __init mp_register_lapic ( +void __init acpi_register_lapic ( u8 id, u8 enabled) { - struct mpc_config_processor processor; - int boot_cpu = 0; + if (!enabled) + return; if (MAX_APICS - id <= 0) { printk(KERN_WARNING "Processor #%d invalid (max %d)\n", @@ -842,21 +724,8 @@ return; } - if (id == boot_cpu_physical_apicid) - boot_cpu = 1; - - processor.mpc_type = MP_PROCESSOR; - processor.mpc_apicid = id; - processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR)); - processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); - processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); - processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | - (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; - processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; - processor.mpc_reserved[0] = 0; - processor.mpc_reserved[1] = 0; - - MP_processor_info(&processor); + /* pass in bogus version for now, until we can read the apic */ + smp_processor_register(id, 0x10); } #if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT)) @@ -864,23 +733,18 @@ #define MP_ISA_BUS 0 #define MP_MAX_IOAPIC_PIN 127 -struct mp_ioapic_routing { - int apic_id; - int gsi_base; - int gsi_end; - u32 pin_programmed[4]; -} mp_ioapic_routing[MAX_IO_APICS]; +struct acpi_ioapic_routing acpi_ioapic_routing[MAX_IO_APICS]; -static int mp_find_ioapic ( +int acpi_find_ioapic ( int gsi) { int i = 0; /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { - if ((gsi >= mp_ioapic_routing[i].gsi_base) - && (gsi <= mp_ioapic_routing[i].gsi_end)) + if ((gsi >= acpi_ioapic_routing[i].gsi_base) + && (gsi <= acpi_ioapic_routing[i].gsi_end)) return i; } @@ -888,170 +752,120 @@ return -1; } - -void __init mp_register_ioapic ( + +void __init acpi_register_io_apic ( u8 id, u32 address, u32 gsi_base) { - int idx = 0; + static int idx; - if (nr_ioapics >= MAX_IO_APICS) { - printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " - "(found %d)\n", MAX_IO_APICS, nr_ioapics); - panic("Recompile kernel with bigger MAX_IO_APICS!\n"); - } if (!address) { printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" - " found in MADT table, skipping!\n"); + " found in MADT, skipping!\n"); return; } - idx = nr_ioapics++; + smp_ioapic_register(id, address); - mp_ioapics[idx].mpc_type = MP_IOAPIC; - mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; - mp_ioapics[idx].mpc_apicaddr = address; - - set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); - mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); - /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ - mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; - mp_ioapic_routing[idx].gsi_base = gsi_base; - mp_ioapic_routing[idx].gsi_end = gsi_base + + acpi_ioapic_routing[idx].apic_id = id; + acpi_ioapic_routing[idx].gsi_base = gsi_base; + acpi_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); - printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " - "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, - mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, - mp_ioapic_routing[idx].gsi_base, - mp_ioapic_routing[idx].gsi_end); - - return; + printk("IOAPIC[%d]: address 0x%x, " + "GSI %d-%d\n", idx, address, + acpi_ioapic_routing[idx].gsi_base, + acpi_ioapic_routing[idx].gsi_end); + idx++; } -void __init mp_override_legacy_irq ( +void __init acpi_override_legacy_irq ( u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { - struct mpc_config_intsrc intsrc; int ioapic = -1; - int pin = -1; - - /* - * Convert 'gsi' to 'ioapic.pin'. - */ - ioapic = mp_find_ioapic(gsi); - if (ioapic < 0) - return; - pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + int ioapic_trigger; + int ioapic_polarity; - /* - * TBD: This check is for faulty timer entries, where the override - * erroneously sets the trigger to level, resulting in a HUGE - * increase of timer interrupts! - */ - if ((bus_irq == 0) && (trigger == 3)) - trigger = 1; - - intsrc.mpc_type = MP_INTSRC; - intsrc.mpc_irqtype = mp_INT; - intsrc.mpc_irqflag = (trigger << 2) | polarity; - intsrc.mpc_srcbus = MP_ISA_BUS; - intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ - intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ - intsrc.mpc_dstirq = pin; /* INTIN# */ - - Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", - intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, - (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, - intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); - - mp_irqs[mp_irq_entries] = intsrc; - if (++mp_irq_entries == MAX_IRQ_SOURCES) - panic("Max # of irq sources exceeded!\n"); - - return; -} - - -void __init mp_config_acpi_legacy_irqs (void) -{ - struct mpc_config_intsrc intsrc; - int i = 0; - int ioapic = -1; - - /* - * Fabricate the legacy ISA bus (bus #31). - */ - mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; - Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); - - /* - * Locate the IOAPIC that manages the ISA IRQs (0-15). - */ - ioapic = mp_find_ioapic(0); - if (ioapic < 0) - return; + if (acpi_nr_isos >= ACPI_MAX_ISOS) { + printk(KERN_CRIT "Max # of ACPI ISOs (%d) exceeded (found %d).\n", + ACPI_MAX_ISOS, acpi_nr_isos); + panic("Recompile kernel with bigger ACPI_MAX_ISOS!.\n"); + } - intsrc.mpc_type = MP_INTSRC; - intsrc.mpc_irqflag = 0; /* Conforming */ - intsrc.mpc_srcbus = MP_ISA_BUS; - intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; + /* these had better always be on the first ioapic */ + ioapic = acpi_find_ioapic(gsi); + if (ioapic != 0) + BUG(); + if (acpi_ioapic_routing[ioapic].gsi_base) + BUG(); - /* - * Use the default configuration for the IRQs 0-15. Unless - * overriden by (MADT) interrupt source override entries. + /* + * convert ACPI MADT 2-bit trigger/polarity values to + * 1-bit IOAPIC trigger/polarity values: */ - for (i = 0; i < 16; i++) { - int idx; - - for (idx = 0; idx < mp_irq_entries; idx++) { - struct mpc_config_intsrc *irq = mp_irqs + idx; - - /* Do we already have a mapping for this ISA IRQ? */ - if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) - break; + switch (trigger) + { + case TRIGGER_CONFORMS: + case TRIGGER_EDGE: + ioapic_trigger = IOAPIC_EDGE; + break; + case TRIGGER_RESERVED: + printk(KERN_WARNING "broken BIOS!!\n"); + case TRIGGER_LEVEL: + ioapic_trigger = IOAPIC_LEVEL; + break; + default: + printk(KERN_WARNING "broken BIOS!!\n"); + ioapic_trigger = IOAPIC_EDGE; + break; + } - /* Do we already have a mapping for this IOAPIC pin */ - if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && - (irq->mpc_dstirq == i)) - break; - } + switch (polarity) + { + case POLARITY_CONFORMS: + case POLARITY_ACTIVE_HIGH: + ioapic_polarity = IOAPIC_HIGH; + break; + case POLARITY_RESERVED: + printk(KERN_WARNING "broken BIOS!!\n"); + case POLARITY_ACTIVE_LOW: + ioapic_polarity = IOAPIC_LOW; + break; + default: + printk(KERN_WARNING "broken BIOS!!\n"); + ioapic_polarity = IOAPIC_HIGH; + break; + } - if (idx != mp_irq_entries) { - printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); - continue; /* IRQ already used */ - } + /* + * This check is for faulty timer entries, where the override + * erroneously sets the trigger to level, resulting in a HUGE + * increase of timer interrupts! + */ + if ((bus_irq == 0) && (ioapic_trigger == IOAPIC_LEVEL)) + ioapic_trigger = IOAPIC_EDGE; + + acpi_isos[acpi_nr_isos].source = bus_irq; + acpi_isos[acpi_nr_isos].polarity = ioapic_polarity; + acpi_isos[acpi_nr_isos].trigger = ioapic_trigger; + acpi_isos[acpi_nr_isos].gsi = gsi; - intsrc.mpc_irqtype = mp_INT; - intsrc.mpc_srcbusirq = i; /* Identity mapped */ - intsrc.mpc_dstirq = i; - - Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " - "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, - (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, - intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, - intsrc.mpc_dstirq); - - mp_irqs[mp_irq_entries] = intsrc; - if (++mp_irq_entries == MAX_IRQ_SOURCES) - panic("Max # of irq sources exceeded!\n"); - } + acpi_nr_isos++; } int (*platform_rename_gsi)(int ioapic, int gsi); -void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) +void acpi_register_io_apic_gsi (u32 gsi, int edge_level, int active_high_low) { int ioapic = -1; int ioapic_pin = 0; @@ -1063,13 +877,13 @@ return; #endif - ioapic = mp_find_ioapic(gsi); + ioapic = acpi_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); return; } - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + ioapic_pin = gsi - acpi_ioapic_routing[ioapic].gsi_base; if (platform_rename_gsi) gsi = platform_rename_gsi(ioapic, gsi); @@ -1083,17 +897,17 @@ idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); if (idx > 3) { printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + "%d-%d\n", acpi_ioapic_routing[ioapic].apic_id, ioapic_pin); return; } - if ((1< #include -#include #include unsigned int nmi_watchdog = NMI_NONE; diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c --- a/arch/i386/kernel/reboot.c 2004-08-10 10:42:12.000000000 -0700 +++ b/arch/i386/kernel/reboot.c 2004-08-10 10:57:39.000000000 -0700 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "mach_reboot.h" diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c 2004-08-10 10:42:33.000000000 -0700 +++ b/arch/i386/kernel/setup.c 2004-08-10 10:58:19.000000000 -0700 @@ -41,6 +41,7 @@ #include #include