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>

+55 -33
+1
arch/x86/include/asm/apic.h
··· 238 238 extern void setup_secondary_APIC_clock(void); 239 239 extern int APIC_init_uniprocessor(void); 240 240 extern void enable_NMI_through_LVT0(void); 241 + extern int apic_force_enable(void); 241 242 242 243 /* 243 244 * On 32bit this is mach-xxx local
+54 -33
arch/x86/kernel/apic/apic.c
··· 1531 1531 return 0; 1532 1532 } 1533 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 1584 * Detect and initialize APIC 1536 1585 */ 1537 1586 static int __init detect_init_APIC(void) 1538 1587 { 1539 - u32 h, l, features; 1540 - 1541 1588 /* Disabled by kernel option? */ 1542 1589 if (disable_apic) 1543 1590 return -1; ··· 1614 1567 "you can enable it with \"lapic\"\n"); 1615 1568 return -1; 1616 1569 } 1617 - /* 1618 - * Some BIOSes disable the local APIC in the APIC_BASE 1619 - * MSR. This can only be done in software for Intel P6 or later 1620 - * and AMD K7 (Model > 1) or later. 1621 - */ 1622 - rdmsr(MSR_IA32_APICBASE, l, h); 1623 - if (!(l & MSR_IA32_APICBASE_ENABLE)) { 1624 - pr_info("Local APIC disabled by BIOS -- reenabling.\n"); 1625 - l &= ~MSR_IA32_APICBASE_BASE; 1626 - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; 1627 - wrmsr(MSR_IA32_APICBASE, l, h); 1628 - enabled_via_apicbase = 1; 1629 - } 1570 + if (apic_force_enable()) 1571 + return -1; 1572 + } else { 1573 + if (apic_verify()) 1574 + return -1; 1630 1575 } 1631 - /* 1632 - * The APIC feature bit should now be enabled 1633 - * in `cpuid' 1634 - */ 1635 - features = cpuid_edx(1); 1636 - if (!(features & (1 << X86_FEATURE_APIC))) { 1637 - pr_warning("Could not enable APIC!\n"); 1638 - return -1; 1639 - } 1640 - set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 1641 - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; 1642 - 1643 - /* The BIOS may have set up the APIC at some other address */ 1644 - rdmsr(MSR_IA32_APICBASE, l, h); 1645 - if (l & MSR_IA32_APICBASE_ENABLE) 1646 - mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; 1647 - 1648 - pr_info("Found and enabled local APIC!\n"); 1649 1576 1650 1577 apic_pm_activate(); 1651 1578