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:
Linus Torvalds
2012-01-06 13:58:21 -08:00
29 changed files with 639 additions and 76 deletions

View File

@@ -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