diff options
| -rw-r--r-- | arch/x86/include/asm/apic.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 87 |
2 files changed, 55 insertions, 33 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 286de34b0ed6..ad50aaae396f 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/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 850657d1b0ed..463839645f9b 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -1531,13 +1531,60 @@ static int __init detect_init_APIC(void) | |||
| 1531 | return 0; | 1531 | return 0; |
| 1532 | } | 1532 | } |
| 1533 | #else | 1533 | #else |
| 1534 | |||
| 1535 | static int apic_verify(void) | ||
| 1536 | { | ||
| 1537 | u32 features, h, l; | ||
| 1538 | |||
| 1539 | /* | ||
| 1540 | * The APIC feature bit should now be enabled | ||
| 1541 | * in `cpuid' | ||
| 1542 | */ | ||
| 1543 | features = cpuid_edx(1); | ||
| 1544 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
| 1545 | pr_warning("Could not enable APIC!\n"); | ||
| 1546 | return -1; | ||
| 1547 | } | ||
| 1548 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
| 1549 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
| 1550 | |||
| 1551 | /* The BIOS may have set up the APIC at some other address */ | ||
| 1552 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
| 1553 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
| 1554 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
| 1555 | |||
| 1556 | pr_info("Found and enabled local APIC!\n"); | ||
| 1557 | return 0; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | int apic_force_enable(void) | ||
| 1561 | { | ||
| 1562 | u32 h, l; | ||
| 1563 | |||
| 1564 | if (disable_apic) | ||
| 1565 | return -1; | ||
| 1566 | |||
| 1567 | /* | ||
| 1568 | * Some BIOSes disable the local APIC in the APIC_BASE | ||
| 1569 | * MSR. This can only be done in software for Intel P6 or later | ||
| 1570 | * and AMD K7 (Model > 1) or later. | ||
| 1571 | */ | ||
| 1572 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
| 1573 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
| 1574 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
| 1575 | l &= ~MSR_IA32_APICBASE_BASE; | ||
| 1576 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
| 1577 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
| 1578 | enabled_via_apicbase = 1; | ||
| 1579 | } | ||
| 1580 | return apic_verify(); | ||
| 1581 | } | ||
| 1582 | |||
| 1534 | /* | 1583 | /* |
| 1535 | * Detect and initialize APIC | 1584 | * Detect and initialize APIC |
| 1536 | */ | 1585 | */ |
| 1537 | static int __init detect_init_APIC(void) | 1586 | static int __init detect_init_APIC(void) |
| 1538 | { | 1587 | { |
| 1539 | u32 h, l, features; | ||
| 1540 | |||
| 1541 | /* Disabled by kernel option? */ | 1588 | /* Disabled by kernel option? */ |
| 1542 | if (disable_apic) | 1589 | if (disable_apic) |
| 1543 | return -1; | 1590 | return -1; |
| @@ -1567,38 +1614,12 @@ static int __init detect_init_APIC(void) | |||
| 1567 | "you can enable it with \"lapic\"\n"); | 1614 | "you can enable it with \"lapic\"\n"); |
| 1568 | return -1; | 1615 | return -1; |
| 1569 | } | 1616 | } |
| 1570 | /* | 1617 | if (apic_force_enable()) |
| 1571 | * Some BIOSes disable the local APIC in the APIC_BASE | 1618 | return -1; |
| 1572 | * MSR. This can only be done in software for Intel P6 or later | 1619 | } else { |
| 1573 | * and AMD K7 (Model > 1) or later. | 1620 | if (apic_verify()) |
| 1574 | */ | 1621 | return -1; |
| 1575 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
| 1576 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
| 1577 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
| 1578 | l &= ~MSR_IA32_APICBASE_BASE; | ||
| 1579 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
| 1580 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
| 1581 | enabled_via_apicbase = 1; | ||
| 1582 | } | ||
| 1583 | } | ||
| 1584 | /* | ||
| 1585 | * The APIC feature bit should now be enabled | ||
| 1586 | * in `cpuid' | ||
| 1587 | */ | ||
| 1588 | features = cpuid_edx(1); | ||
| 1589 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
| 1590 | pr_warning("Could not enable APIC!\n"); | ||
| 1591 | return -1; | ||
| 1592 | } | 1622 | } |
| 1593 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
| 1594 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
| 1595 | |||
| 1596 | /* The BIOS may have set up the APIC at some other address */ | ||
| 1597 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
| 1598 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
| 1599 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
| 1600 | |||
| 1601 | pr_info("Found and enabled local APIC!\n"); | ||
| 1602 | 1623 | ||
| 1603 | apic_pm_activate(); | 1624 | apic_pm_activate(); |
| 1604 | 1625 | ||
