17 #include <linux/bitops.h>
19 #include <linux/module.h>
21 #include <linux/pci.h>
25 #include <asm/pgalloc.h>
30 #include <asm/setup.h>
38 static int __init mpf_checksum(
unsigned char *
mp,
int len)
56 char *bootup_cpu =
"";
63 apicid =
x86_init.mpparse.mpc_apic_id(m);
66 bootup_cpu =
" (Bootup-CPU)";
74 #ifdef CONFIG_X86_IO_APIC
86 x86_init.mpparse.mpc_oem_bus_info(m, str);
88 #if MAX_MP_BUSSES < 256
91 " is too large, max. supported is %d\n",
103 if (
x86_init.mpparse.mpc_oem_pci_bus)
104 x86_init.mpparse.mpc_oem_pci_bus(m);
125 " IRQ %02x, APIC ID %x, APIC INT %02x\n",
139 " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
147 static int __init smp_check_mpc(
struct mpc_table *mpc,
char *oem,
char *str)
156 if (mpf_checksum((
unsigned char *)mpc, mpc->
length)) {
160 if (mpc->
spec != 0x01 && mpc->
spec != 0x04) {
183 static void skip_entry(
unsigned char **
ptr,
int *
count,
int size)
189 static void __init smp_dump_mptable(
struct mpc_table *mpc,
unsigned char *mpt)
191 printk(
KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
204 int count =
sizeof(*mpc);
205 unsigned char *mpt = ((
unsigned char *)mpc) +
count;
207 if (!smp_check_mpc(mpc, oem, str))
221 x86_init.mpparse.smp_read_mpc_oem(mpc);
228 while (count < mpc->
length) {
233 MP_processor_info((
struct mpc_cpu *)mpt);
234 skip_entry(&mpt, &count,
sizeof(
struct mpc_cpu));
237 MP_bus_info((
struct mpc_bus *)mpt);
238 skip_entry(&mpt, &count,
sizeof(
struct mpc_bus));
242 skip_entry(&mpt, &count,
sizeof(
struct mpc_ioapic));
246 skip_entry(&mpt, &count,
sizeof(
struct mpc_intsrc));
250 skip_entry(&mpt, &count,
sizeof(
struct mpc_lintsrc));
254 smp_dump_mptable(mpc, mpt);
266 #ifdef CONFIG_X86_IO_APIC
268 static int __init ELCR_trigger(
unsigned int irq)
272 port = 0x4d0 + (irq >> 3);
273 return (
inb(port) >> (irq & 7)) & 1;
276 static void __init construct_default_ioirq_mptable(
int mpc_default_type)
280 int ELCR_fallback = 0;
297 if (mpc_default_type == 5) {
299 "falling back to ELCR\n");
301 if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
307 "Using ELCR to identify PCI interrupts\n");
312 for (i = 0; i < 16; i++) {
313 switch (mpc_default_type) {
315 if (i == 0 || i == 13)
335 intsrc.srcbusirq =
i;
336 intsrc.dstirq = i ? i : 2;
341 intsrc.srcbusirq = 0;
347 static void __init construct_ioapic_table(
int mpc_default_type)
354 switch (mpc_default_type) {
370 if (mpc_default_type > 4) {
378 ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
381 MP_ioapic_info(&ioapic);
386 construct_default_ioirq_mptable(mpc_default_type);
389 static inline void __init construct_ioapic_table(
int mpc_default_type) { }
392 static inline void __init construct_default_ISA_mptable(
int mpc_default_type)
409 processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
416 for (i = 0; i < 2; i++) {
421 construct_ioapic_table(mpc_default_type);
425 lintsrc.srcbusid = 0;
426 lintsrc.srcbusirq = 0;
428 for (i = 0; i < 2; i++) {
429 lintsrc.irqtype = linttypes[
i];
430 lintsrc.destapiclint =
i;
431 MP_lintsrc_info(&lintsrc);
437 static unsigned long __init get_mpc_size(
unsigned long physptr)
450 static int __init check_physptr(
struct mpf_intel *mpf,
unsigned int early)
455 size = get_mpc_size(mpf->
physptr);
461 if (!smp_read_mpc(mpc, early)) {
462 #ifdef CONFIG_X86_LOCAL_APIC
466 "... disabling SMP support. (tell your hw vendor)\n");
475 #ifdef CONFIG_X86_IO_APIC
485 "using default mptable. (tell your hw vendor)\n");
492 construct_default_ioirq_mptable(0);
521 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
544 construct_default_ISA_mptable(mpf->
feature1);
547 if (check_physptr(mpf, early))
564 static int __init smp_scan_config(
unsigned long base,
unsigned long length)
571 base, base + length - 1);
578 !mpf_checksum((
unsigned char *)bp, 16) &&
581 #ifdef CONFIG_X86_LOCAL_APIC
586 printk(
KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
589 sizeof(*mpf) - 1, mpf);
594 smp_reserve_memory(mpf);
616 if (smp_scan_config(0x0, 0x400) ||
617 smp_scan_config(639 * 0x400, 0x400) ||
618 smp_scan_config(0xF0000, 0x10000))
637 address = get_bios_ebda();
639 smp_scan_config(address, 0x400);
642 #ifdef CONFIG_X86_IO_APIC
661 if (
mp_irqs[i].irqflag != 0x0f)
680 #define SPARE_SLOT_NUM 20
689 print_mp_irq_info(m);
691 i = get_MP_intsrc_index(m);
695 print_mp_irq_info(&
mp_irqs[i]);
702 if (*nr_m_spare < SPARE_SLOT_NUM) {
707 m_spare[*nr_m_spare] =
m;
713 check_slot(
unsigned long mpc_new_phys,
unsigned long mpc_new_length,
int count)
715 if (!mpc_new_phys || count <= mpc_new_length) {
716 WARN(1,
"update_mptable: No spare slots (length: %x)\n", count);
728 unsigned long mpc_new_phys,
729 unsigned long mpc_new_length)
731 #ifdef CONFIG_X86_IO_APIC
734 int count =
sizeof(*mpc);
736 unsigned char *mpt = ((
unsigned char *)mpc) +
count;
739 while (count < mpc->length) {
742 skip_entry(&mpt, &count,
sizeof(
struct mpc_cpu));
745 skip_entry(&mpt, &count,
sizeof(
struct mpc_bus));
748 skip_entry(&mpt, &count,
sizeof(
struct mpc_ioapic));
751 check_irq_src((
struct mpc_intsrc *)mpt, &nr_m_spare);
752 skip_entry(&mpt, &count,
sizeof(
struct mpc_intsrc));
755 skip_entry(&mpt, &count,
sizeof(
struct mpc_lintsrc));
759 smp_dump_mptable(mpc, mpt);
764 #ifdef CONFIG_X86_IO_APIC
775 if (nr_m_spare > 0) {
779 m_spare[nr_m_spare] =
NULL;
783 if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
789 print_mp_irq_info(&
mp_irqs[i]);
802 static int __init update_mptable_setup(
char *str)
804 enable_update_mptable = 1;
810 early_param(
"update_mptable", update_mptable_setup);
813 static unsigned long mpc_new_length
__initdata = 4096;
816 static int __initdata alloc_mptable;
817 static int __init parse_alloc_mptable_opt(
char *
p)
819 enable_update_mptable = 1;
829 early_param(
"alloc_mptable", parse_alloc_mptable_opt);
833 if (enable_update_mptable && alloc_mptable)
837 static int __init update_mp_table(
void)
844 if (!enable_update_mptable)
862 if (!smp_check_mpc(mpc, oem, str))
868 if (mpc_new_phys && mpc->
length > mpc_new_length) {
870 printk(
KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
875 unsigned char old,
new;
878 old = mpf_checksum((
unsigned char *)mpc, mpc->
length);
880 new = mpf_checksum((
unsigned char *)mpc, mpc->
length);
882 printk(
KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
892 if (mpc_new_phys - mpf->
physptr) {
902 mpf->
checksum -= mpf_checksum((
unsigned char *)mpf, 16);
912 replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);