Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: Skip cpus with apic-ids >= 255 in !x2apic_mode x86, x2apic: Allow "nox2apic" to disable x2apic mode setup by BIOS x86, x2apic: Fallback to xapic when BIOS doesn't setup interrupt-remapping x86, acpi: Skip acpi x2apic entries if the x2apic feature is not present x86, apic: Add probe() for apic_flat x86: Simplify code by removing a !SMP #ifdefs from 'struct cpuinfo_x86' x86: Convert per-cpu counter icr_read_retry_count into a member of irq_stat x86: Add per-cpu stat counter for APIC ICR read tries pci, x86/io-apic: Allow PCI_IOAPIC to be user configurable on x86 x86: Fix the !CONFIG_NUMA build of the new CPU ID fixup code support x86: Add NumaChip support x86: Add x86_init platform override to fix up NUMA core numbering x86: Make flat_init_apic_ldr() available
This commit is contained in:
@@ -146,16 +146,26 @@ __setup("apicpmtimer", setup_apicpmtimer);
|
||||
int x2apic_mode;
|
||||
#ifdef CONFIG_X86_X2APIC
|
||||
/* x2apic enabled before OS handover */
|
||||
static int x2apic_preenabled;
|
||||
int x2apic_preenabled;
|
||||
static int x2apic_disabled;
|
||||
static int nox2apic;
|
||||
static __init int setup_nox2apic(char *str)
|
||||
{
|
||||
if (x2apic_enabled()) {
|
||||
pr_warning("Bios already enabled x2apic, "
|
||||
"can't enforce nox2apic");
|
||||
return 0;
|
||||
}
|
||||
int apicid = native_apic_msr_read(APIC_ID);
|
||||
|
||||
if (apicid >= 255) {
|
||||
pr_warning("Apicid: %08x, cannot enforce nox2apic\n",
|
||||
apicid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_warning("x2apic already enabled. will disable it\n");
|
||||
} else
|
||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||
|
||||
nox2apic = 1;
|
||||
|
||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||
return 0;
|
||||
}
|
||||
early_param("nox2apic", setup_nox2apic);
|
||||
@@ -250,6 +260,7 @@ u32 native_safe_apic_wait_icr_idle(void)
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
if (!send_status)
|
||||
break;
|
||||
inc_irq_stat(icr_read_retry_count);
|
||||
udelay(100);
|
||||
} while (timeout++ < 1000);
|
||||
|
||||
@@ -1431,6 +1442,45 @@ void __init bsp_end_local_APIC_setup(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_X2APIC
|
||||
/*
|
||||
* Need to disable xapic and x2apic at the same time and then enable xapic mode
|
||||
*/
|
||||
static inline void __disable_x2apic(u64 msr)
|
||||
{
|
||||
wrmsrl(MSR_IA32_APICBASE,
|
||||
msr & ~(X2APIC_ENABLE | XAPIC_ENABLE));
|
||||
wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE);
|
||||
}
|
||||
|
||||
static __init void disable_x2apic(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
if (!cpu_has_x2apic)
|
||||
return;
|
||||
|
||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||
if (msr & X2APIC_ENABLE) {
|
||||
u32 x2apic_id = read_apic_id();
|
||||
|
||||
if (x2apic_id >= 255)
|
||||
panic("Cannot disable x2apic, id: %08x\n", x2apic_id);
|
||||
|
||||
pr_info("Disabling x2apic\n");
|
||||
__disable_x2apic(msr);
|
||||
|
||||
if (nox2apic) {
|
||||
clear_cpu_cap(&cpu_data(0), X86_FEATURE_X2APIC);
|
||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||
}
|
||||
|
||||
x2apic_disabled = 1;
|
||||
x2apic_mode = 0;
|
||||
|
||||
register_lapic_address(mp_lapic_addr);
|
||||
}
|
||||
}
|
||||
|
||||
void check_x2apic(void)
|
||||
{
|
||||
if (x2apic_enabled()) {
|
||||
@@ -1441,15 +1491,20 @@ void check_x2apic(void)
|
||||
|
||||
void enable_x2apic(void)
|
||||
{
|
||||
int msr, msr2;
|
||||
u64 msr;
|
||||
|
||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||
if (x2apic_disabled) {
|
||||
__disable_x2apic(msr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!x2apic_mode)
|
||||
return;
|
||||
|
||||
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||
if (!(msr & X2APIC_ENABLE)) {
|
||||
printk_once(KERN_INFO "Enabling x2apic\n");
|
||||
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, msr2);
|
||||
wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_X86_X2APIC */
|
||||
@@ -1486,25 +1541,34 @@ void __init enable_IR_x2apic(void)
|
||||
ret = save_ioapic_entries();
|
||||
if (ret) {
|
||||
pr_info("Saving IO-APIC state failed: %d\n", ret);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
legacy_pic->mask_all();
|
||||
mask_ioapic_entries();
|
||||
|
||||
if (x2apic_preenabled && nox2apic)
|
||||
disable_x2apic();
|
||||
|
||||
if (dmar_table_init_ret)
|
||||
ret = -1;
|
||||
else
|
||||
ret = enable_IR();
|
||||
|
||||
if (!x2apic_supported())
|
||||
goto skip_x2apic;
|
||||
|
||||
if (ret < 0) {
|
||||
/* IR is required if there is APIC ID > 255 even when running
|
||||
* under KVM
|
||||
*/
|
||||
if (max_physical_apicid > 255 ||
|
||||
!hypervisor_x2apic_available())
|
||||
goto nox2apic;
|
||||
!hypervisor_x2apic_available()) {
|
||||
if (x2apic_preenabled)
|
||||
disable_x2apic();
|
||||
goto skip_x2apic;
|
||||
}
|
||||
/*
|
||||
* without IR all CPUs can be addressed by IOAPIC/MSI
|
||||
* only in physical mode
|
||||
@@ -1512,8 +1576,10 @@ void __init enable_IR_x2apic(void)
|
||||
x2apic_force_phys();
|
||||
}
|
||||
|
||||
if (ret == IRQ_REMAP_XAPIC_MODE)
|
||||
goto nox2apic;
|
||||
if (ret == IRQ_REMAP_XAPIC_MODE) {
|
||||
pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
|
||||
goto skip_x2apic;
|
||||
}
|
||||
|
||||
x2apic_enabled = 1;
|
||||
|
||||
@@ -1523,22 +1589,11 @@ void __init enable_IR_x2apic(void)
|
||||
pr_info("Enabled x2apic\n");
|
||||
}
|
||||
|
||||
nox2apic:
|
||||
skip_x2apic:
|
||||
if (ret < 0) /* IR enabling failed */
|
||||
restore_ioapic_entries();
|
||||
legacy_pic->restore_mask();
|
||||
local_irq_restore(flags);
|
||||
|
||||
out:
|
||||
if (x2apic_enabled || !x2apic_supported())
|
||||
return;
|
||||
|
||||
if (x2apic_preenabled)
|
||||
panic("x2apic: enabled by BIOS but kernel init failed.");
|
||||
else if (ret == IRQ_REMAP_XAPIC_MODE)
|
||||
pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
|
||||
else if (ret < 0)
|
||||
pr_info("x2apic not enabled, IRQ remapping init failed\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
Reference in New Issue
Block a user