diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-10-19 13:46:28 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-10-23 11:27:43 -0400 |
commit | 5a7ae78fd478624df3059cb6f55056b85d074acc (patch) | |
tree | bd5adc0bde70bc8e93e9ef1d1f124ecdff4538be /arch/x86/kernel/apic/apic.c | |
parent | d4429f608abde89e8bc1e24b43cd503feb95c496 (diff) |
x86: Allow platforms to force enable apic
Some embedded x86 platforms don't setup the APIC in the
BIOS/bootloader and would be forced to add "lapic" on the kernel
command line. That's a bit akward.
Split out the force enable code from detect_init_APIC() and allow
platform code to call it from the platform setup. That avoids the
command line parameter and possible replication of the MSR dance in
the force enable code.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <1287510389-8388-1-git-send-email-dirk.brandewie@gmail.com>
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 87 |
1 files changed, 54 insertions, 33 deletions
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 | ||