aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/apic.h1
-rw-r--r--arch/x86/include/asm/io_apic.h7
-rw-r--r--arch/x86/kernel/apic/apic.c87
-rw-r--r--arch/x86/kernel/apic/io_apic.c34
-rw-r--r--arch/x86/kernel/setup.c5
5 files changed, 79 insertions, 55 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f6ce0bda3b98..cf12007796db 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -238,6 +238,7 @@ extern void setup_boot_APIC_clock(void);
238extern void setup_secondary_APIC_clock(void); 238extern void setup_secondary_APIC_clock(void);
239extern int APIC_init_uniprocessor(void); 239extern int APIC_init_uniprocessor(void);
240extern void enable_NMI_through_LVT0(void); 240extern void enable_NMI_through_LVT0(void);
241extern int apic_force_enable(void);
241 242
242/* 243/*
243 * On 32bit this is mach-xxx local 244 * On 32bit this is mach-xxx local
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index a6b28d017c2f..107f2d8c6570 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -159,7 +159,7 @@ struct io_apic_irq_attr;
159extern int io_apic_set_pci_routing(struct device *dev, int irq, 159extern int io_apic_set_pci_routing(struct device *dev, int irq,
160 struct io_apic_irq_attr *irq_attr); 160 struct io_apic_irq_attr *irq_attr);
161void setup_IO_APIC_irq_extra(u32 gsi); 161void setup_IO_APIC_irq_extra(u32 gsi);
162extern void ioapic_init_mappings(void); 162extern void ioapic_and_gsi_init(void);
163extern void ioapic_insert_resources(void); 163extern void ioapic_insert_resources(void);
164 164
165extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); 165extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
@@ -168,10 +168,10 @@ extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
168extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); 168extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
169extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); 169extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
170 170
171extern void probe_nr_irqs_gsi(void);
172extern int get_nr_irqs_gsi(void); 171extern int get_nr_irqs_gsi(void);
173 172
174extern void setup_ioapic_ids_from_mpc(void); 173extern void setup_ioapic_ids_from_mpc(void);
174extern void setup_ioapic_ids_from_mpc_nocheck(void);
175 175
176struct mp_ioapic_gsi{ 176struct mp_ioapic_gsi{
177 u32 gsi_base; 177 u32 gsi_base;
@@ -189,9 +189,8 @@ extern void __init pre_init_apic_IRQ0(void);
189#define io_apic_assign_pci_irqs 0 189#define io_apic_assign_pci_irqs 0
190#define setup_ioapic_ids_from_mpc x86_init_noop 190#define setup_ioapic_ids_from_mpc x86_init_noop
191static const int timer_through_8259 = 0; 191static const int timer_through_8259 = 0;
192static inline void ioapic_init_mappings(void) { } 192static inline void ioapic_and_gsi_init(void) { }
193static inline void ioapic_insert_resources(void) { } 193static inline void ioapic_insert_resources(void) { }
194static inline void probe_nr_irqs_gsi(void) { }
195#define gsi_top (NR_IRQS_LEGACY) 194#define gsi_top (NR_IRQS_LEGACY)
196static inline int mp_find_ioapic(u32 gsi) { return 0; } 195static inline int mp_find_ioapic(u32 gsi) { return 0; }
197 196
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 3f838d537392..c48a64510844 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1530,13 +1530,60 @@ static int __init detect_init_APIC(void)
1530 return 0; 1530 return 0;
1531} 1531}
1532#else 1532#else
1533
1534static int apic_verify(void)
1535{
1536 u32 features, h, l;
1537
1538 /*
1539 * The APIC feature bit should now be enabled
1540 * in `cpuid'
1541 */
1542 features = cpuid_edx(1);
1543 if (!(features & (1 << X86_FEATURE_APIC))) {
1544 pr_warning("Could not enable APIC!\n");
1545 return -1;
1546 }
1547 set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1548 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
1549
1550 /* The BIOS may have set up the APIC at some other address */
1551 rdmsr(MSR_IA32_APICBASE, l, h);
1552 if (l & MSR_IA32_APICBASE_ENABLE)
1553 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1554
1555 pr_info("Found and enabled local APIC!\n");
1556 return 0;
1557}
1558
1559int apic_force_enable(void)
1560{
1561 u32 h, l;
1562
1563 if (disable_apic)
1564 return -1;
1565
1566 /*
1567 * Some BIOSes disable the local APIC in the APIC_BASE
1568 * MSR. This can only be done in software for Intel P6 or later
1569 * and AMD K7 (Model > 1) or later.
1570 */
1571 rdmsr(MSR_IA32_APICBASE, l, h);
1572 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
1573 pr_info("Local APIC disabled by BIOS -- reenabling.\n");
1574 l &= ~MSR_IA32_APICBASE_BASE;
1575 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
1576 wrmsr(MSR_IA32_APICBASE, l, h);
1577 enabled_via_apicbase = 1;
1578 }
1579 return apic_verify();
1580}
1581
1533/* 1582/*
1534 * Detect and initialize APIC 1583 * Detect and initialize APIC
1535 */ 1584 */
1536static int __init detect_init_APIC(void) 1585static int __init detect_init_APIC(void)
1537{ 1586{
1538 u32 h, l, features;
1539
1540 /* Disabled by kernel option? */ 1587 /* Disabled by kernel option? */
1541 if (disable_apic) 1588 if (disable_apic)
1542 return -1; 1589 return -1;
@@ -1566,38 +1613,12 @@ static int __init detect_init_APIC(void)
1566 "you can enable it with \"lapic\"\n"); 1613 "you can enable it with \"lapic\"\n");
1567 return -1; 1614 return -1;
1568 } 1615 }
1569 /* 1616 if (apic_force_enable())
1570 * Some BIOSes disable the local APIC in the APIC_BASE 1617 return -1;
1571 * MSR. This can only be done in software for Intel P6 or later 1618 } else {
1572 * and AMD K7 (Model > 1) or later. 1619 if (apic_verify())
1573 */ 1620 return -1;
1574 rdmsr(MSR_IA32_APICBASE, l, h);
1575 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
1576 pr_info("Local APIC disabled by BIOS -- reenabling.\n");
1577 l &= ~MSR_IA32_APICBASE_BASE;
1578 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
1579 wrmsr(MSR_IA32_APICBASE, l, h);
1580 enabled_via_apicbase = 1;
1581 }
1582 }
1583 /*
1584 * The APIC feature bit should now be enabled
1585 * in `cpuid'
1586 */
1587 features = cpuid_edx(1);
1588 if (!(features & (1 << X86_FEATURE_APIC))) {
1589 pr_warning("Could not enable APIC!\n");
1590 return -1;
1591 } 1621 }
1592 set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1593 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
1594
1595 /* The BIOS may have set up the APIC at some other address */
1596 rdmsr(MSR_IA32_APICBASE, l, h);
1597 if (l & MSR_IA32_APICBASE_ENABLE)
1598 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1599
1600 pr_info("Found and enabled local APIC!\n");
1601 1622
1602 apic_pm_activate(); 1623 apic_pm_activate();
1603 1624
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 7cc0a721f628..4abf08aab3d4 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1934,8 +1934,7 @@ void disable_IO_APIC(void)
1934 * 1934 *
1935 * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 1935 * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
1936 */ 1936 */
1937 1937void __init setup_ioapic_ids_from_mpc_nocheck(void)
1938void __init setup_ioapic_ids_from_mpc(void)
1939{ 1938{
1940 union IO_APIC_reg_00 reg_00; 1939 union IO_APIC_reg_00 reg_00;
1941 physid_mask_t phys_id_present_map; 1940 physid_mask_t phys_id_present_map;
@@ -1944,15 +1943,6 @@ void __init setup_ioapic_ids_from_mpc(void)
1944 unsigned char old_id; 1943 unsigned char old_id;
1945 unsigned long flags; 1944 unsigned long flags;
1946 1945
1947 if (acpi_ioapic)
1948 return;
1949 /*
1950 * Don't check I/O APIC IDs for xAPIC systems. They have
1951 * no meaning without the serial APIC bus.
1952 */
1953 if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
1954 || APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
1955 return;
1956 /* 1946 /*
1957 * This is broken; anything with a real cpu count has to 1947 * This is broken; anything with a real cpu count has to
1958 * circumvent this idiocy regardless. 1948 * circumvent this idiocy regardless.
@@ -2006,7 +1996,6 @@ void __init setup_ioapic_ids_from_mpc(void)
2006 physids_or(phys_id_present_map, phys_id_present_map, tmp); 1996 physids_or(phys_id_present_map, phys_id_present_map, tmp);
2007 } 1997 }
2008 1998
2009
2010 /* 1999 /*
2011 * We need to adjust the IRQ routing table 2000 * We need to adjust the IRQ routing table
2012 * if the ID changed. 2001 * if the ID changed.
@@ -2042,6 +2031,21 @@ void __init setup_ioapic_ids_from_mpc(void)
2042 apic_printk(APIC_VERBOSE, " ok.\n"); 2031 apic_printk(APIC_VERBOSE, " ok.\n");
2043 } 2032 }
2044} 2033}
2034
2035void __init setup_ioapic_ids_from_mpc(void)
2036{
2037
2038 if (acpi_ioapic)
2039 return;
2040 /*
2041 * Don't check I/O APIC IDs for xAPIC systems. They have
2042 * no meaning without the serial APIC bus.
2043 */
2044 if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
2045 || APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
2046 return;
2047 setup_ioapic_ids_from_mpc_nocheck();
2048}
2045#endif 2049#endif
2046 2050
2047int no_timer_check __initdata; 2051int no_timer_check __initdata;
@@ -3639,7 +3643,7 @@ int __init io_apic_get_redir_entries (int ioapic)
3639 return reg_01.bits.entries + 1; 3643 return reg_01.bits.entries + 1;
3640} 3644}
3641 3645
3642void __init probe_nr_irqs_gsi(void) 3646static void __init probe_nr_irqs_gsi(void)
3643{ 3647{
3644 int nr; 3648 int nr;
3645 3649
@@ -3956,7 +3960,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
3956 return res; 3960 return res;
3957} 3961}
3958 3962
3959void __init ioapic_init_mappings(void) 3963void __init ioapic_and_gsi_init(void)
3960{ 3964{
3961 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; 3965 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
3962 struct resource *ioapic_res; 3966 struct resource *ioapic_res;
@@ -3994,6 +3998,8 @@ fake_ioapic_page:
3994 ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; 3998 ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
3995 ioapic_res++; 3999 ioapic_res++;
3996 } 4000 }
4001
4002 probe_nr_irqs_gsi();
3997} 4003}
3998 4004
3999void __init ioapic_insert_resources(void) 4005void __init ioapic_insert_resources(void)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index df172c1e8238..0afb8c7e3803 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1035,10 +1035,7 @@ void __init setup_arch(char **cmdline_p)
1035#endif 1035#endif
1036 1036
1037 init_apic_mappings(); 1037 init_apic_mappings();
1038 ioapic_init_mappings(); 1038 ioapic_and_gsi_init();
1039
1040 /* need to wait for io_apic is mapped */
1041 probe_nr_irqs_gsi();
1042 1039
1043 kvm_guest_init(); 1040 kvm_guest_init();
1044 1041