diff options
-rw-r--r-- | arch/x86/include/asm/apic.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 87 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 34 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 5 |
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); | |||
238 | extern void setup_secondary_APIC_clock(void); | 238 | extern void setup_secondary_APIC_clock(void); |
239 | extern int APIC_init_uniprocessor(void); | 239 | extern int APIC_init_uniprocessor(void); |
240 | extern void enable_NMI_through_LVT0(void); | 240 | extern void enable_NMI_through_LVT0(void); |
241 | extern 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; | |||
159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 159 | extern 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); |
161 | void setup_IO_APIC_irq_extra(u32 gsi); | 161 | void setup_IO_APIC_irq_extra(u32 gsi); |
162 | extern void ioapic_init_mappings(void); | 162 | extern void ioapic_and_gsi_init(void); |
163 | extern void ioapic_insert_resources(void); | 163 | extern void ioapic_insert_resources(void); |
164 | 164 | ||
165 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); | 165 | extern 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); | |||
168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
170 | 170 | ||
171 | extern void probe_nr_irqs_gsi(void); | ||
172 | extern int get_nr_irqs_gsi(void); | 171 | extern int get_nr_irqs_gsi(void); |
173 | 172 | ||
174 | extern void setup_ioapic_ids_from_mpc(void); | 173 | extern void setup_ioapic_ids_from_mpc(void); |
174 | extern void setup_ioapic_ids_from_mpc_nocheck(void); | ||
175 | 175 | ||
176 | struct mp_ioapic_gsi{ | 176 | struct 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 |
191 | static const int timer_through_8259 = 0; | 191 | static const int timer_through_8259 = 0; |
192 | static inline void ioapic_init_mappings(void) { } | 192 | static inline void ioapic_and_gsi_init(void) { } |
193 | static inline void ioapic_insert_resources(void) { } | 193 | static inline void ioapic_insert_resources(void) { } |
194 | static inline void probe_nr_irqs_gsi(void) { } | ||
195 | #define gsi_top (NR_IRQS_LEGACY) | 194 | #define gsi_top (NR_IRQS_LEGACY) |
196 | static inline int mp_find_ioapic(u32 gsi) { return 0; } | 195 | static 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 | |||
1534 | static 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 | |||
1559 | int 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 | */ |
1536 | static int __init detect_init_APIC(void) | 1585 | static 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 | 1937 | void __init setup_ioapic_ids_from_mpc_nocheck(void) | |
1938 | void __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 | |||
2035 | void __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 | ||
2047 | int no_timer_check __initdata; | 2051 | int 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 | ||
3642 | void __init probe_nr_irqs_gsi(void) | 3646 | static 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 | ||
3959 | void __init ioapic_init_mappings(void) | 3963 | void __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 | ||
3999 | void __init ioapic_insert_resources(void) | 4005 | void __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 | ||