From a1dafe857db56c35878c71560089a4694ac841fd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 7 Jan 2015 15:31:28 +0800 Subject: iommu, x86: Restructure setup of the irq remapping feature enable_IR_x2apic() calls setup_irq_remapping_ops() which by default installs the intel dmar remapping ops and then calls the amd iommu irq remapping prepare callback to figure out whether we are running on an AMD machine with irq remapping hardware. Right after that it calls irq_remapping_prepare() which pointlessly checks: if (!remap_ops || !remap_ops->prepare) return -ENODEV; and then calls remap_ops->prepare() which is silly in the AMD case as it got called from setup_irq_remapping_ops() already a few microseconds ago. Simplify this and just collapse everything into irq_remapping_prepare(). The irq_remapping_prepare() remains still silly as it assigns blindly the intel ops, but that's not scope of this patch. The scope here is to move the preperatory work, i.e. memory allocations out of the atomic section which is required to enable irq remapping. Signed-off-by: Thomas Gleixner Tested-by: Borislav Petkov Acked-and-tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Joerg Roedel Cc: H. Peter Anvin Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20141205084147.232633738@linutronix.de Link: http://lkml.kernel.org/r/1420615903-28253-2-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Jiang Liu Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/irq_remapping.h | 2 -- arch/x86/kernel/apic/apic.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index b7747c4c2cf2..f1b619e5a50d 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -33,7 +33,6 @@ struct irq_cfg; #ifdef CONFIG_IRQ_REMAP -extern void setup_irq_remapping_ops(void); extern int irq_remapping_supported(void); extern void set_irq_remapping_broken(void); extern int irq_remapping_prepare(void); @@ -60,7 +59,6 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip); #else /* CONFIG_IRQ_REMAP */ -static inline void setup_irq_remapping_ops(void) { } static inline int irq_remapping_supported(void) { return 0; } static inline void set_irq_remapping_broken(void) { } static inline int irq_remapping_prepare(void) { return -ENODEV; } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 29b5b18afa27..141f1031013d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1597,9 +1597,6 @@ void __init enable_IR_x2apic(void) int ret, x2apic_enabled = 0; int hardware_init_ret; - /* Make sure irq_remap_ops are initialized */ - setup_irq_remapping_ops(); - hardware_init_ret = irq_remapping_prepare(); if (hardware_init_ret && !x2apic_supported()) return; -- cgit v1.2.3-70-g09d2 From f7ccadac2d3fe373d14a5917c86c499770ebbffc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 14 Jan 2015 18:31:33 +0100 Subject: x86/apic: Clear stale x2apic mode If x2apic got disabled on the kernel command line, then the following issue can happen: enable_IR_x2apic() .... x2apic_mode = 1; enable_x2apic(); if (x2apic_disabled) { __disable_x2apic(); return; } That leaves X2APIC disabled in hardware, but x2apic_mode stays 1. So all other code which checks x2apic_mode gets the wrong information. Set x2apic_mode to 0 after disabling it in hardware. This is just a hotfix. The proper solution is to rework this code so it has seperate functions for the initial setup on the boot processor and the secondary cpus, but that's beyond the scope of this fix. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig --- arch/x86/kernel/apic/apic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 141f1031013d..8a81a681836e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1559,6 +1559,7 @@ void enable_x2apic(void) rdmsrl(MSR_IA32_APICBASE, msr); if (x2apic_disabled) { __disable_x2apic(msr); + x2apic_mode = 0; return; } -- cgit v1.2.3-70-g09d2 From 2599094f6e381128cc274311758add604c1e108a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:31 +0800 Subject: x86/apic: Panic if kernel doesn't support x2apic but BIOS has enabled x2apic When kernel doesn't support X2APIC but BIOS has enabled X2APIC, system may panic or hang without useful messages. On the other hand, it's hard to dynamically disable X2APIC when CONFIG_X86_X2APIC is disabled. So panic with a clear message in such a case. Now system panics as below when X2APIC is disabled and interrupt remapping is enabled: [ 0.316118] LAPIC pending interrupts after 512 EOI [ 0.322126] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 [ 0.368655] Kernel panic - not syncing: timer doesn't work through Interrupt-remapped IO-APIC [ 0.378300] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.18.0+ #340 [ 0.385300] Hardware name: Intel Corporation BRICKLAND/BRICKLAND, BIOS BRIVTIN1.86B.0051.L05.1406240953 06/24/2014 [ 0.396997] ffff88046dc03000 ffff88046c307dd8 ffffffff8179dada 00000000000043f2 [ 0.405629] ffffffff81a92158 ffff88046c307e58 ffffffff8179b757 0000000000000002 [ 0.414261] 0000000000000008 ffff88046c307e68 ffff88046c307e08 ffffffff813ad82b [ 0.422890] Call Trace: [ 0.425711] [] dump_stack+0x45/0x57 [ 0.431533] [] panic+0xc1/0x1f5 [ 0.436978] [] ? delay_tsc+0x3b/0x70 [ 0.442910] [] panic_if_irq_remap+0x1c/0x20 [ 0.449524] [] setup_IO_APIC+0x405/0x82e [ 0.464979] [] native_smp_prepare_cpus+0x2d9/0x31c [ 0.472274] [] kernel_init_freeable+0xd6/0x223 [ 0.479170] [] ? rest_init+0x80/0x80 [ 0.485099] [] kernel_init+0xe/0xf0 [ 0.490932] [] ret_from_fork+0x7c/0xb0 [ 0.497054] [] ? rest_init+0x80/0x80 [ 0.502983] ---[ end Kernel panic - not syncing: timer doesn't work through Interrupt-remapped IO-APIC System hangs as below when X2APIC and interrupt remapping are both disabled: [ 1.102782] pci 0000:00:02.0: System wakeup disabled by ACPI [ 1.109351] pci 0000:00:03.0: System wakeup disabled by ACPI [ 1.115915] pci 0000:00:03.2: System wakeup disabled by ACPI [ 1.122479] pci 0000:00:03.3: System wakeup disabled by ACPI [ 1.132274] pci 0000:00:1c.0: Enabling MPC IRBNCE [ 1.137620] pci 0000:00:1c.0: Intel PCH root port ACS workaround enabled [ 1.145239] pci 0000:00:1c.0: System wakeup disabled by ACPI [ 1.151790] pci 0000:00:1c.7: Enabling MPC IRBNCE [ 1.157128] pci 0000:00:1c.7: Intel PCH root port ACS workaround enabled [ 1.164748] pci 0000:00:1c.7: System wakeup disabled by ACPI [ 1.171447] pci 0000:00:1e.0: System wakeup disabled by ACPI [ 1.178612] acpiphp: Slot [8] registered [ 1.183095] pci 0000:00:02.0: PCI bridge to [bus 01] [ 1.188867] acpiphp: Slot [2] registered With this patch applied, the system panics in both cases with a proper panic message. Signed-off-by: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-5-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 8a81a681836e..544673304de0 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1598,6 +1598,14 @@ void __init enable_IR_x2apic(void) int ret, x2apic_enabled = 0; int hardware_init_ret; + if (!IS_ENABLED(CONFIG_X86_X2APIC)) { + u64 msr; + + rdmsrl(MSR_IA32_APICBASE, msr); + if (msr & X2APIC_ENABLE) + panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); + } + hardware_init_ret = irq_remapping_prepare(); if (hardware_init_ret && !x2apic_supported()) return; -- cgit v1.2.3-70-g09d2 From 7f530a2771fe7ea6a068340c9e22f814edfcc3c4 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:32 +0800 Subject: x86/apic: Kill useless variable x2apic_enabled in function enable_IR_x2apic() Local variable x2apic_enabled has been assigned to but never referred, so kill it. Signed-off-by: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-6-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 544673304de0..2dbd3a0ae9f1 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1595,7 +1595,7 @@ int __init enable_IR(void) void __init enable_IR_x2apic(void) { unsigned long flags; - int ret, x2apic_enabled = 0; + int ret; int hardware_init_ret; if (!IS_ENABLED(CONFIG_X86_X2APIC)) { @@ -1653,8 +1653,6 @@ void __init enable_IR_x2apic(void) goto skip_x2apic; } - x2apic_enabled = 1; - if (x2apic_supported() && !x2apic_mode) { x2apic_mode = 1; enable_x2apic(); -- cgit v1.2.3-70-g09d2 From 89356cf20ecb0b9975b1dad9ed605dd4c6e68bcd Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:33 +0800 Subject: x86/apic: Correctly detect X2APIC status in function enable_IR() X2APIC will be disabled if user specifies "nox2apic" on kernel command line, even when x2apic_preenabled is true. So correctly detect X2APIC status by using x2apic_enabled() instead of x2apic_preenabled. Signed-off-by: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-7-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 2dbd3a0ae9f1..11358df3bd08 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1581,7 +1581,7 @@ int __init enable_IR(void) return -1; } - if (!x2apic_preenabled && skip_ioapic_setup) { + if (!x2apic_enabled() && skip_ioapic_setup) { pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n"); return -1; -- cgit v1.2.3-70-g09d2 From 07806c50bddd2f0493f97584198733946952409c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:34 +0800 Subject: x86/apic: Refine enable_IR_x2apic() and related functions Refine enable_IR_x2apic() and related functions for better readability. [ tglx: Removed the XAPIC mode change and split it out into a seperate patch. Added comments. ] Signed-off-by: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-8-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 92 +++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 11358df3bd08..fa77be8d0b17 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1573,7 +1573,7 @@ void enable_x2apic(void) } #endif /* CONFIG_X86_X2APIC */ -int __init enable_IR(void) +static int __init try_to_enable_IR(void) { #ifdef CONFIG_IRQ_REMAP if (!irq_remapping_supported()) { @@ -1586,17 +1586,51 @@ int __init enable_IR(void) "io-apic setup\n"); return -1; } - +#endif return irq_remapping_enable(); +} + +static __init void try_to_enable_x2apic(int ir_stat) +{ +#ifdef CONFIG_X86_X2APIC + if (!x2apic_supported()) + return; + + if (ir_stat < 0) { + /* IR is required if there is APIC ID > 255 even when running + * under KVM + */ + if (max_physical_apicid > 255 || + !hypervisor_x2apic_available()) { + pr_info("IRQ remapping doesn't support X2APIC mode, disable x2apic.\n"); + if (x2apic_preenabled) + disable_x2apic(); + return; + } + + /* + * without IR all CPUs can be addressed by IOAPIC/MSI + * only in physical mode + */ + x2apic_force_phys(); + + } else if (ir_stat == IRQ_REMAP_XAPIC_MODE) { + pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); + return; + } + + if (!x2apic_mode) { + x2apic_mode = 1; + enable_x2apic(); + pr_info("Enabled x2apic\n"); + } #endif - return -1; } void __init enable_IR_x2apic(void) { unsigned long flags; - int ret; - int hardware_init_ret; + int ret, ir_stat; if (!IS_ENABLED(CONFIG_X86_X2APIC)) { u64 msr; @@ -1606,8 +1640,8 @@ void __init enable_IR_x2apic(void) panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); } - hardware_init_ret = irq_remapping_prepare(); - if (hardware_init_ret && !x2apic_supported()) + ir_stat = irq_remapping_prepare(); + if (ir_stat < 0 && !x2apic_supported()) return; ret = save_ioapic_entries(); @@ -1622,45 +1656,13 @@ void __init enable_IR_x2apic(void) if (x2apic_preenabled && nox2apic) disable_x2apic(); + /* If irq_remapping_prepare() succeded, try to enable it */ + if (ir_stat >= 0) + ir_stat = try_to_enable_IR(); + /* ir_stat contains the remap mode or an error code */ + try_to_enable_x2apic(ir_stat); - if (hardware_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()) { - if (x2apic_preenabled) - disable_x2apic(); - goto skip_x2apic; - } - /* - * without IR all CPUs can be addressed by IOAPIC/MSI - * only in physical mode - */ - x2apic_force_phys(); - } - - if (ret == IRQ_REMAP_XAPIC_MODE) { - pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); - goto skip_x2apic; - } - - if (x2apic_supported() && !x2apic_mode) { - x2apic_mode = 1; - enable_x2apic(); - pr_info("Enabled x2apic\n"); - } - -skip_x2apic: - if (ret < 0) /* IR enabling failed */ + if (ir_stat < 0) restore_ioapic_entries(); legacy_pic->restore_mask(); local_irq_restore(flags); -- cgit v1.2.3-70-g09d2 From ef1b2b8ad13858ab2f87c05261b8ce3253f90af9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:34 +0800 Subject: x86/apic: Handle XAPIC remap mode proper. If remapping is in XAPIC mode, the setup code just skips X2APIC initialization without checking max CPU APIC ID in system, which may cause problem if system has a CPU with APIC ID bigger than 255. Handle IR in XAPIC mode the same way as if remapping is disabled. [ tglx: Split out from previous patch ] Signed-off-by: Jiang Liu Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-8-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fa77be8d0b17..04aec6bc7481 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1596,7 +1596,7 @@ static __init void try_to_enable_x2apic(int ir_stat) if (!x2apic_supported()) return; - if (ir_stat < 0) { + if (ir_stat != IRQ_REMAP_X2APIC_MODE) { /* IR is required if there is APIC ID > 255 even when running * under KVM */ @@ -1613,10 +1613,6 @@ static __init void try_to_enable_x2apic(int ir_stat) * only in physical mode */ x2apic_force_phys(); - - } else if (ir_stat == IRQ_REMAP_XAPIC_MODE) { - pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); - return; } if (!x2apic_mode) { -- cgit v1.2.3-70-g09d2 From 5fcee53ce705d49c766f8a302c7e93bdfc33c124 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:38 +0800 Subject: x86/apic: Only disable CPU x2apic mode when necessary When interrupt remapping hardware is not in X2APIC, CPU X2APIC mode will be disabled if: 1) Maximum CPU APIC ID is bigger than 255 2) hypervisior doesn't support x2apic mode. But we should only check whether hypervisor supports X2APIC mode when hypervisor(CONFIG_HYPERVISOR_GUEST) is enabled, otherwise X2APIC will always be disabled when CONFIG_HYPERVISOR_GUEST is disabled and IR doesn't work in X2APIC mode. Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-12-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 04aec6bc7481..2f16116ced90 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1601,7 +1601,8 @@ static __init void try_to_enable_x2apic(int ir_stat) * under KVM */ if (max_physical_apicid > 255 || - !hypervisor_x2apic_available()) { + (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && + !hypervisor_x2apic_available())) { pr_info("IRQ remapping doesn't support X2APIC mode, disable x2apic.\n"); if (x2apic_preenabled) disable_x2apic(); -- cgit v1.2.3-70-g09d2 From c392f56c946033bd136043079a62b9188888828d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:40 +0800 Subject: iommu/irq_remapping: Kill function irq_remapping_supported() and related code Simplify irq_remapping code by killing irq_remapping_supported() and related interfaces. Joerg posted a similar patch at https://lkml.org/lkml/2014/12/15/490, so assume an signed-off from Joerg. Signed-off-by: Jiang Liu Signed-off-by: Joerg Roedel Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-14-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/irq_remapping.h | 2 -- arch/x86/kernel/apic/apic.c | 7 +------ drivers/iommu/amd_iommu.c | 1 - drivers/iommu/amd_iommu_init.c | 5 ----- drivers/iommu/amd_iommu_proto.h | 1 - drivers/iommu/intel_irq_remapping.c | 6 ------ drivers/iommu/irq_remapping.c | 12 ++---------- drivers/iommu/irq_remapping.h | 3 --- 8 files changed, 3 insertions(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index f1b619e5a50d..6224d316c405 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -33,7 +33,6 @@ struct irq_cfg; #ifdef CONFIG_IRQ_REMAP -extern int irq_remapping_supported(void); extern void set_irq_remapping_broken(void); extern int irq_remapping_prepare(void); extern int irq_remapping_enable(void); @@ -59,7 +58,6 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip); #else /* CONFIG_IRQ_REMAP */ -static inline int irq_remapping_supported(void) { return 0; } static inline void set_irq_remapping_broken(void) { } static inline int irq_remapping_prepare(void) { return -ENODEV; } static inline int irq_remapping_enable(void) { return -ENODEV; } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 2f16116ced90..35e6d09294ed 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1575,12 +1575,7 @@ void enable_x2apic(void) static int __init try_to_enable_IR(void) { -#ifdef CONFIG_IRQ_REMAP - if (!irq_remapping_supported()) { - pr_debug("intr-remapping not supported\n"); - return -1; - } - +#ifdef CONFIG_X86_IO_APIC if (!x2apic_enabled() && skip_ioapic_setup) { pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n"); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 98024856df07..59de6364a910 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4284,7 +4284,6 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id) } struct irq_remap_ops amd_iommu_irq_ops = { - .supported = amd_iommu_supported, .prepare = amd_iommu_prepare, .enable = amd_iommu_enable, .disable = amd_iommu_disable, diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 0039f87f48b8..970979ecbebb 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2129,11 +2129,6 @@ int __init amd_iommu_prepare(void) return iommu_go_to_state(IOMMU_ACPI_FINISHED); } -int __init amd_iommu_supported(void) -{ - return amd_iommu_irq_remap ? 1 : 0; -} - int __init amd_iommu_enable(void) { int ret; diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index 95ed6deae47f..861af9d8338a 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -33,7 +33,6 @@ extern void amd_iommu_init_notifier(void); extern void amd_iommu_init_api(void); /* Needed for interrupt remapping */ -extern int amd_iommu_supported(void); extern int amd_iommu_prepare(void); extern int amd_iommu_enable(void); extern void amd_iommu_disable(void); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9d67c12c2ffb..fb72bd5f438c 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -567,11 +567,6 @@ static int __init dmar_x2apic_optout(void) return dmar->flags & DMAR_X2APIC_OPT_OUT; } -static int __init intel_irq_remapping_supported(void) -{ - return 1; -} - static void __init intel_cleanup_irq_remapping(void) { struct dmar_drhd_unit *drhd; @@ -1216,7 +1211,6 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id) } struct irq_remap_ops intel_irq_remap_ops = { - .supported = intel_irq_remapping_supported, .prepare = intel_prepare_irq_remapping, .enable = intel_enable_irq_remapping, .disable = disable_irq_remapping, diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 91d5884d3ed9..e7449b42504d 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -199,19 +199,11 @@ void set_irq_remapping_broken(void) irq_remap_broken = 1; } -int irq_remapping_supported(void) +int __init irq_remapping_prepare(void) { if (disable_irq_remap) - return 0; - - if (!remap_ops || !remap_ops->supported) - return 0; + return -ENOSYS; - return remap_ops->supported(); -} - -int __init irq_remapping_prepare(void) -{ remap_ops = &intel_irq_remap_ops; #ifdef CONFIG_AMD_IOMMU diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index fde250f86e60..a8edfea0ab5d 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -38,9 +38,6 @@ extern int no_x2apic_optout; extern int irq_remapping_enabled; struct irq_remap_ops { - /* Check whether Interrupt Remapping is supported */ - int (*supported)(void); - /* Initializes hardware and makes it ready for remapping interrupts */ int (*prepare)(void); -- cgit v1.2.3-70-g09d2 From 8d80696060eedf49c080c0f2cf39a20ae7e787f9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:09 +0000 Subject: x86/apic: Avoid open coded x2apic detection enable_IR_x2apic() grew a open coded x2apic detection. Implement a proper helper function which shares the code with the already existing x2apic_enabled(). Made it use rdmsrl_safe as suggested by Boris. Signed-off-by: Thomas Gleixner Cc: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211702.285038186@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 19 ++++++++++--------- arch/x86/kernel/apic/apic.c | 5 +---- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 465b309af254..1a8ba26c2fbd 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -108,6 +108,15 @@ extern u64 native_apic_icr_read(void); extern int x2apic_mode; +static inline bool apic_is_x2apic_enabled(void) +{ + u64 msr; + + if (rdmsrl_safe(MSR_IA32_APICBASE, &msr)) + return false; + return msr & X2APIC_ENABLE; +} + #ifdef CONFIG_X86_X2APIC /* * Make previous memory operations globally visible before @@ -175,15 +184,7 @@ extern void check_x2apic(void); extern void enable_x2apic(void); static inline int x2apic_enabled(void) { - u64 msr; - - if (!cpu_has_x2apic) - return 0; - - rdmsrl(MSR_IA32_APICBASE, msr); - if (msr & X2APIC_ENABLE) - return 1; - return 0; + return cpu_has_x2apic && apic_is_x2apic_enabled(); } #define x2apic_supported() (cpu_has_x2apic) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 35e6d09294ed..7ecfce13be05 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1625,10 +1625,7 @@ void __init enable_IR_x2apic(void) int ret, ir_stat; if (!IS_ENABLED(CONFIG_X86_X2APIC)) { - u64 msr; - - rdmsrl(MSR_IA32_APICBASE, msr); - if (msr & X2APIC_ENABLE) + if (apic_is_x2apic_enabled()) panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); } -- cgit v1.2.3-70-g09d2 From 81a46dd8249d7fa72a8557e58a38aa984e6b5e16 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:11 +0000 Subject: x86/apic: Make x2apic_mode depend on CONFIG_X86_X2APIC No point in having a static variable around which is always 0. Let the compiler optimize code out if disabled. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211702.363274310@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 8 ++++---- arch/x86/kernel/apic/apic.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 1a8ba26c2fbd..d2225fdc953e 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -106,8 +106,6 @@ extern u32 native_safe_apic_wait_icr_idle(void); extern void native_apic_icr_write(u32 low, u32 id); extern u64 native_apic_icr_read(void); -extern int x2apic_mode; - static inline bool apic_is_x2apic_enabled(void) { u64 msr; @@ -178,6 +176,7 @@ static inline u64 native_x2apic_icr_read(void) return val; } +extern int x2apic_mode; extern int x2apic_phys; extern int x2apic_preenabled; extern void check_x2apic(void); @@ -210,8 +209,9 @@ static inline void x2apic_force_phys(void) { } -#define x2apic_preenabled 0 -#define x2apic_supported() 0 +#define x2apic_mode (0) +#define x2apic_preenabled (0) +#define x2apic_supported() (0) #endif extern void enable_IR_x2apic(void); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 7ecfce13be05..a7d3b64ff3e5 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -161,8 +161,8 @@ static __init int setup_apicpmtimer(char *s) __setup("apicpmtimer", setup_apicpmtimer); #endif -int x2apic_mode; #ifdef CONFIG_X86_X2APIC +int x2apic_mode; /* x2apic enabled before OS handover */ int x2apic_preenabled; static int x2apic_disabled; -- cgit v1.2.3-70-g09d2 From bfb050702990d6a2033d072cb2af583aee5c6fc5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:12 +0000 Subject: x86/apic: Move x2apic code to one place Having several disjunct pieces of code for x2apic support makes reading the code unnecessarily hard. Move it to one ifdeffed section. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211702.445212133@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 58 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a7d3b64ff3e5..ff2a8b8ffa0a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -134,9 +134,6 @@ static inline void imcr_apic_to_pic(void) */ static int force_enable_local_apic __initdata; -/* Control whether x2APIC mode is enabled or not */ -static bool nox2apic __initdata; - /* * APIC command line parameters */ @@ -161,33 +158,6 @@ static __init int setup_apicpmtimer(char *s) __setup("apicpmtimer", setup_apicpmtimer); #endif -#ifdef CONFIG_X86_X2APIC -int x2apic_mode; -/* x2apic enabled before OS handover */ -int x2apic_preenabled; -static int x2apic_disabled; -static int __init setup_nox2apic(char *str) -{ - if (x2apic_enabled()) { - 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 = true; - - return 0; -} -early_param("nox2apic", setup_nox2apic); -#endif - unsigned long mp_lapic_addr; int disable_apic; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ @@ -1504,7 +1474,35 @@ void __init bsp_end_local_APIC_setup(void) } +/* Control whether x2APIC mode is enabled or not */ +static bool nox2apic __initdata; + #ifdef CONFIG_X86_X2APIC +int x2apic_mode; +/* x2apic enabled before OS handover */ +int x2apic_preenabled; +static int x2apic_disabled; +static int __init setup_nox2apic(char *str) +{ + if (x2apic_enabled()) { + 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 = true; + + return 0; +} +early_param("nox2apic", setup_nox2apic); + /* * Need to disable xapic and x2apic at the same time and then enable xapic mode */ -- cgit v1.2.3-70-g09d2 From 2ca5b40479246087695d9e6343075b47ee6887ea Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:14 +0000 Subject: x86/ioapic: Check x2apic really The x2apic_preenabled flag is just a horrible hack and if X2APIC support is disabled it does not reflect the actual hardware state. Check the hardware instead. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211702.541280622@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 2 -- arch/x86/kernel/apic/apic.c | 4 +++- arch/x86/kernel/apic/io_apic.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index d2225fdc953e..392bbcf35471 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -178,7 +178,6 @@ static inline u64 native_x2apic_icr_read(void) extern int x2apic_mode; extern int x2apic_phys; -extern int x2apic_preenabled; extern void check_x2apic(void); extern void enable_x2apic(void); static inline int x2apic_enabled(void) @@ -210,7 +209,6 @@ static inline void x2apic_force_phys(void) } #define x2apic_mode (0) -#define x2apic_preenabled (0) #define x2apic_supported() (0) #endif diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index ff2a8b8ffa0a..08144f5c1236 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1480,7 +1480,7 @@ static bool nox2apic __initdata; #ifdef CONFIG_X86_X2APIC int x2apic_mode; /* x2apic enabled before OS handover */ -int x2apic_preenabled; +static int x2apic_preenabled; static int x2apic_disabled; static int __init setup_nox2apic(char *str) { @@ -1569,6 +1569,8 @@ void enable_x2apic(void) wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); } } +#else +#define x2apic_preenabled (0) #endif /* CONFIG_X86_X2APIC */ static int __init try_to_enable_IR(void) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3f5f60406ab1..e5e00f509f03 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2295,7 +2295,7 @@ static inline void __init check_timer(void) } local_irq_disable(); apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); - if (x2apic_preenabled) + if (apic_is_x2apic_enabled()) apic_printk(APIC_QUIET, KERN_INFO "Perhaps problem with the pre-enabled x2apic mode\n" "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); -- cgit v1.2.3-70-g09d2 From 9aa16365275a272283acbda665634ca3dc8b46fe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:16 +0000 Subject: x86/apic: Make disable x2apic work really If x2apic_preenabled is not enabled, then disable_x2apic() is not called from various places which results in x2apic_disabled not being set. So other code pathes can happily reenable the x2apic. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211702.621431109@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 08144f5c1236..fdc6c60faa6b 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1479,8 +1479,6 @@ static bool nox2apic __initdata; #ifdef CONFIG_X86_X2APIC int x2apic_mode; -/* x2apic enabled before OS handover */ -static int x2apic_preenabled; static int x2apic_disabled; static int __init setup_nox2apic(char *str) { @@ -1535,18 +1533,19 @@ static __init void disable_x2apic(void) setup_clear_cpu_cap(X86_FEATURE_X2APIC); } - x2apic_disabled = 1; x2apic_mode = 0; register_lapic_address(mp_lapic_addr); } + + x2apic_disabled = 1; } void check_x2apic(void) { if (x2apic_enabled()) { pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); - x2apic_preenabled = x2apic_mode = 1; + x2apic_mode = 1; } } @@ -1569,8 +1568,6 @@ void enable_x2apic(void) wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); } } -#else -#define x2apic_preenabled (0) #endif /* CONFIG_X86_X2APIC */ static int __init try_to_enable_IR(void) @@ -1599,8 +1596,7 @@ static __init void try_to_enable_x2apic(int ir_stat) (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && !hypervisor_x2apic_available())) { pr_info("IRQ remapping doesn't support X2APIC mode, disable x2apic.\n"); - if (x2apic_preenabled) - disable_x2apic(); + disable_x2apic(); return; } @@ -1643,7 +1639,7 @@ void __init enable_IR_x2apic(void) legacy_pic->mask_all(); mask_ioapic_entries(); - if (x2apic_preenabled && nox2apic) + if (nox2apic) disable_x2apic(); /* If irq_remapping_prepare() succeded, try to enable it */ if (ir_stat >= 0) -- cgit v1.2.3-70-g09d2 From d524165cb8dbb2ce5916cd7682236b9324ae2644 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:17 +0000 Subject: x86/apic: Check x2apic early No point in delaying the x2apic detection for the CONFIG_X86_X2APIC=n case to enable_IR_x2apic(). We rather detect that before we try to setup anything there. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211702.702479404@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 2 +- arch/x86/kernel/apic/apic.c | 34 ++++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 392bbcf35471..ca8deb484d03 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -178,7 +178,7 @@ static inline u64 native_x2apic_icr_read(void) extern int x2apic_mode; extern int x2apic_phys; -extern void check_x2apic(void); +extern void __init check_x2apic(void); extern void enable_x2apic(void); static inline int x2apic_enabled(void) { diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fdc6c60faa6b..d5c35346b556 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1541,14 +1541,6 @@ static __init void disable_x2apic(void) x2apic_disabled = 1; } -void check_x2apic(void) -{ - if (x2apic_enabled()) { - pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); - x2apic_mode = 1; - } -} - void enable_x2apic(void) { u64 msr; @@ -1568,7 +1560,26 @@ void enable_x2apic(void) wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); } } -#endif /* CONFIG_X86_X2APIC */ + +void __init check_x2apic(void) +{ + if (x2apic_enabled()) { + pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); + x2apic_mode = 1; + } +} +#else /* CONFIG_X86_X2APIC */ +static int __init validate_x2apic(void) +{ + if (!apic_is_x2apic_enabled()) + return 0; + /* + * Checkme: Can we simply turn off x2apic here instead of panic? + */ + panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); +} +early_initcall(validate_x2apic); +#endif /* !CONFIG_X86_X2APIC */ static int __init try_to_enable_IR(void) { @@ -1620,11 +1631,6 @@ void __init enable_IR_x2apic(void) unsigned long flags; int ret, ir_stat; - if (!IS_ENABLED(CONFIG_X86_X2APIC)) { - if (apic_is_x2apic_enabled()) - panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); - } - ir_stat = irq_remapping_prepare(); if (ir_stat < 0 && !x2apic_supported()) return; -- cgit v1.2.3-70-g09d2 From 55eae7de727e9ecc814853ec364fbbb352c337df Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:19 +0000 Subject: x86/x2apic: Move code in conditional region No point in having try_to_enable_x2apic() outside of the CONFIG_X86_X2APIC section and having inline functions and more ifdefs to deal with it. Move the code into the existing ifdef section and remove the inline cruft. Fixup the printk about not enabling interrupt remapping as suggested by Boris. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211702.795388613@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 24 +++------------- arch/x86/kernel/apic/apic.c | 67 ++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index ca8deb484d03..951caa17d8ba 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -186,27 +186,11 @@ static inline int x2apic_enabled(void) } #define x2apic_supported() (cpu_has_x2apic) -static inline void x2apic_force_phys(void) -{ - x2apic_phys = 1; -} #else -static inline void disable_x2apic(void) -{ -} -static inline void check_x2apic(void) -{ -} -static inline void enable_x2apic(void) -{ -} -static inline int x2apic_enabled(void) -{ - return 0; -} -static inline void x2apic_force_phys(void) -{ -} +static inline void disable_x2apic(void) { } +static inline void check_x2apic(void) { } +static inline void enable_x2apic(void) { } +static inline int x2apic_enabled(void) { return 0; } #define x2apic_mode (0) #define x2apic_supported() (0) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d5c35346b556..bda56eea929c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1561,41 +1561,8 @@ void enable_x2apic(void) } } -void __init check_x2apic(void) -{ - if (x2apic_enabled()) { - pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); - x2apic_mode = 1; - } -} -#else /* CONFIG_X86_X2APIC */ -static int __init validate_x2apic(void) -{ - if (!apic_is_x2apic_enabled()) - return 0; - /* - * Checkme: Can we simply turn off x2apic here instead of panic? - */ - panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); -} -early_initcall(validate_x2apic); -#endif /* !CONFIG_X86_X2APIC */ - -static int __init try_to_enable_IR(void) -{ -#ifdef CONFIG_X86_IO_APIC - if (!x2apic_enabled() && skip_ioapic_setup) { - pr_info("Skipped enabling intr-remap because of skipping " - "io-apic setup\n"); - return -1; - } -#endif - return irq_remapping_enable(); -} - static __init void try_to_enable_x2apic(int ir_stat) { -#ifdef CONFIG_X86_X2APIC if (!x2apic_supported()) return; @@ -1615,7 +1582,7 @@ static __init void try_to_enable_x2apic(int ir_stat) * without IR all CPUs can be addressed by IOAPIC/MSI * only in physical mode */ - x2apic_force_phys(); + x2apic_phys = 1; } if (!x2apic_mode) { @@ -1623,7 +1590,39 @@ static __init void try_to_enable_x2apic(int ir_stat) enable_x2apic(); pr_info("Enabled x2apic\n"); } +} + +void __init check_x2apic(void) +{ + if (x2apic_enabled()) { + pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); + x2apic_mode = 1; + } +} +#else /* CONFIG_X86_X2APIC */ +static int __init validate_x2apic(void) +{ + if (!apic_is_x2apic_enabled()) + return 0; + /* + * Checkme: Can we simply turn off x2apic here instead of panic? + */ + panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); +} +early_initcall(validate_x2apic); + +static inline void try_to_enable_x2apic(int ir_stat) { } +#endif /* !CONFIG_X86_X2APIC */ + +static int __init try_to_enable_IR(void) +{ +#ifdef CONFIG_X86_IO_APIC + if (!x2apic_enabled() && skip_ioapic_setup) { + pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n"); + return -1; + } #endif + return irq_remapping_enable(); } void __init enable_IR_x2apic(void) -- cgit v1.2.3-70-g09d2 From 62e61633daeb0b53f0506aa6e170e2e4cc75cd65 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:21 +0000 Subject: x86/x2apic: Clarify remapping mode for x2apic enablement Rename the argument of try_to_enable_x2apic() so the purpose becomes more clear. Make the pr_warning more consistent and avoid the double print of "disabling". Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211702.876012628@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index bda56eea929c..06b75216d171 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1561,19 +1561,19 @@ void enable_x2apic(void) } } -static __init void try_to_enable_x2apic(int ir_stat) +static __init void try_to_enable_x2apic(int remap_mode) { if (!x2apic_supported()) return; - if (ir_stat != IRQ_REMAP_X2APIC_MODE) { + if (remap_mode != IRQ_REMAP_X2APIC_MODE) { /* IR is required if there is APIC ID > 255 even when running * under KVM */ if (max_physical_apicid > 255 || (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && !hypervisor_x2apic_available())) { - pr_info("IRQ remapping doesn't support X2APIC mode, disable x2apic.\n"); + pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); disable_x2apic(); return; } @@ -1611,7 +1611,7 @@ static int __init validate_x2apic(void) } early_initcall(validate_x2apic); -static inline void try_to_enable_x2apic(int ir_stat) { } +static inline void try_to_enable_x2apic(int remap_mode) { } #endif /* !CONFIG_X86_X2APIC */ static int __init try_to_enable_IR(void) -- cgit v1.2.3-70-g09d2 From 12e189d3cfa4c64de758bde18626184bf32c65fc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:22 +0000 Subject: x86/x2apic: Add proper state tracking Having 3 different variables to track the state is just silly and error prone. Add a proper state tracking variable which covers the three possible states: ON/OFF/DISABLED. We cannot use x2apic_mode for this as this would require to change all users of x2apic_mode with explicit comparisons for a state value instead of treating it as boolean. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211702.955392443@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 06b75216d171..b374b0de342b 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1480,6 +1480,14 @@ static bool nox2apic __initdata; #ifdef CONFIG_X86_X2APIC int x2apic_mode; static int x2apic_disabled; + +enum { + X2APIC_OFF, + X2APIC_ON, + X2APIC_DISABLED, +}; +static int x2apic_state; + static int __init setup_nox2apic(char *str) { if (x2apic_enabled()) { @@ -1496,7 +1504,7 @@ static int __init setup_nox2apic(char *str) setup_clear_cpu_cap(X86_FEATURE_X2APIC); nox2apic = true; - + x2apic_state = X2APIC_DISABLED; return 0; } early_param("nox2apic", setup_nox2apic); @@ -1539,6 +1547,7 @@ static __init void disable_x2apic(void) } x2apic_disabled = 1; + x2apic_state = X2APIC_DISABLED; } void enable_x2apic(void) @@ -1559,6 +1568,7 @@ void enable_x2apic(void) printk_once(KERN_INFO "Enabling x2apic\n"); wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); } + x2apic_state = X2APIC_ON; } static __init void try_to_enable_x2apic(int remap_mode) @@ -1597,6 +1607,9 @@ void __init check_x2apic(void) if (x2apic_enabled()) { pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); x2apic_mode = 1; + x2apic_state = X2APIC_ON; + } else if (!cpu_has_x2apic) { + x2apic_state = X2APIC_DISABLED; } } #else /* CONFIG_X86_X2APIC */ -- cgit v1.2.3-70-g09d2 From 44e25ff9e6912347a1a54c757fc75681d0dc42d0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:24 +0000 Subject: x86/x2apic: Disable x2apic from nox2apic setup There is no point in postponing the hardware disablement of x2apic. It can be disabled right away in the nox2apic setup function. Disable it right away and set the state to DISABLED . This allows to remove all the nox2apic conditionals all over the place. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211703.051214090@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 1 - arch/x86/kernel/apic/apic.c | 59 ++++++++++++++++++--------------------------- 2 files changed, 24 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 951caa17d8ba..5d7488e9b66e 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -187,7 +187,6 @@ static inline int x2apic_enabled(void) #define x2apic_supported() (cpu_has_x2apic) #else -static inline void disable_x2apic(void) { } static inline void check_x2apic(void) { } static inline void enable_x2apic(void) { } static inline int x2apic_enabled(void) { return 0; } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b374b0de342b..90b8ac5df250 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1474,12 +1474,8 @@ void __init bsp_end_local_APIC_setup(void) } -/* Control whether x2APIC mode is enabled or not */ -static bool nox2apic __initdata; - #ifdef CONFIG_X86_X2APIC int x2apic_mode; -static int x2apic_disabled; enum { X2APIC_OFF, @@ -1488,6 +1484,19 @@ enum { }; static int x2apic_state; +static inline void __x2apic_disable(void) +{ + u64 msr; + + rdmsrl(MSR_IA32_APICBASE, msr); + if (!(msr & X2APIC_ENABLE)) + return; + /* Disable xapic and x2apic first and then reenable xapic mode */ + wrmsrl(MSR_IA32_APICBASE, msr & ~(X2APIC_ENABLE | XAPIC_ENABLE)); + wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE); + printk_once(KERN_INFO "x2apic disabled\n"); +} + static int __init setup_nox2apic(char *str) { if (x2apic_enabled()) { @@ -1498,28 +1507,17 @@ static int __init setup_nox2apic(char *str) apicid); return 0; } - - pr_warning("x2apic already enabled. will disable it\n"); - } else - setup_clear_cpu_cap(X86_FEATURE_X2APIC); - - nox2apic = true; + pr_warning("x2apic already enabled.\n"); + __x2apic_disable(); + } + setup_clear_cpu_cap(X86_FEATURE_X2APIC); x2apic_state = X2APIC_DISABLED; + x2apic_mode = 0; return 0; } early_param("nox2apic", setup_nox2apic); -/* - * 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) +static __init void x2apic_disable(void) { u64 msr; @@ -1533,20 +1531,13 @@ static __init void disable_x2apic(void) 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_disable(); x2apic_mode = 0; register_lapic_address(mp_lapic_addr); } - x2apic_disabled = 1; x2apic_state = X2APIC_DISABLED; } @@ -1554,9 +1545,8 @@ void enable_x2apic(void) { u64 msr; - rdmsrl(MSR_IA32_APICBASE, msr); - if (x2apic_disabled) { - __disable_x2apic(msr); + if (x2apic_state == X2APIC_DISABLED) { + __x2apic_disable(); x2apic_mode = 0; return; } @@ -1564,6 +1554,7 @@ void enable_x2apic(void) if (!x2apic_mode) return; + rdmsrl(MSR_IA32_APICBASE, msr); if (!(msr & X2APIC_ENABLE)) { printk_once(KERN_INFO "Enabling x2apic\n"); wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); @@ -1584,7 +1575,7 @@ static __init void try_to_enable_x2apic(int remap_mode) (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && !hypervisor_x2apic_available())) { pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); - disable_x2apic(); + x2apic_disable(); return; } @@ -1657,8 +1648,6 @@ void __init enable_IR_x2apic(void) legacy_pic->mask_all(); mask_ioapic_entries(); - if (nox2apic) - disable_x2apic(); /* If irq_remapping_prepare() succeded, try to enable it */ if (ir_stat >= 0) ir_stat = try_to_enable_IR(); -- cgit v1.2.3-70-g09d2 From 659006bf3ae37a08706907ce1a36ddf57c9131d2 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:26 +0000 Subject: x86/x2apic: Split enable and setup function enable_x2apic() is a convoluted unreadable mess because it is used for both enablement in early boot and for setup in cpu_init(). Split the code into x2apic_enable() for enablement and x2apic_setup() for setup of (secondary cpus). Make use of the new state tracking to simplify the logic. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211703.129287153@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 4 +-- arch/x86/kernel/apic/apic.c | 63 ++++++++++++++++++++++++++------------------ arch/x86/kernel/cpu/common.c | 2 +- 3 files changed, 41 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 5d7488e9b66e..ac60c603f8dd 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -179,7 +179,7 @@ static inline u64 native_x2apic_icr_read(void) extern int x2apic_mode; extern int x2apic_phys; extern void __init check_x2apic(void); -extern void enable_x2apic(void); +extern void x2apic_setup(void); static inline int x2apic_enabled(void) { return cpu_has_x2apic && apic_is_x2apic_enabled(); @@ -188,7 +188,7 @@ static inline int x2apic_enabled(void) #define x2apic_supported() (cpu_has_x2apic) #else static inline void check_x2apic(void) { } -static inline void enable_x2apic(void) { } +static inline void x2apic_setup(void) { } static inline int x2apic_enabled(void) { return 0; } #define x2apic_mode (0) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 90b8ac5df250..0ee96b9fe4e6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1488,6 +1488,9 @@ static inline void __x2apic_disable(void) { u64 msr; + if (cpu_has_apic) + return; + rdmsrl(MSR_IA32_APICBASE, msr); if (!(msr & X2APIC_ENABLE)) return; @@ -1497,6 +1500,17 @@ static inline void __x2apic_disable(void) printk_once(KERN_INFO "x2apic disabled\n"); } +static inline void __x2apic_enable(void) +{ + u64 msr; + + rdmsrl(MSR_IA32_APICBASE, msr); + if (msr & X2APIC_ENABLE) + return; + wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); + printk_once(KERN_INFO "x2apic enabled\n"); +} + static int __init setup_nox2apic(char *str) { if (x2apic_enabled()) { @@ -1517,6 +1531,20 @@ static int __init setup_nox2apic(char *str) } early_param("nox2apic", setup_nox2apic); +/* Called from cpu_init() to enable x2apic on (secondary) cpus */ +void x2apic_setup(void) +{ + /* + * If x2apic is not in ON state, disable it if already enabled + * from BIOS. + */ + if (x2apic_state != X2APIC_ON) { + __x2apic_disable(); + return; + } + __x2apic_enable(); +} + static __init void x2apic_disable(void) { u64 msr; @@ -1541,30 +1569,19 @@ static __init void x2apic_disable(void) x2apic_state = X2APIC_DISABLED; } -void enable_x2apic(void) +static __init void x2apic_enable(void) { - u64 msr; - - if (x2apic_state == X2APIC_DISABLED) { - __x2apic_disable(); - x2apic_mode = 0; - return; - } - - if (!x2apic_mode) + if (x2apic_state != X2APIC_OFF) return; - rdmsrl(MSR_IA32_APICBASE, msr); - if (!(msr & X2APIC_ENABLE)) { - printk_once(KERN_INFO "Enabling x2apic\n"); - wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); - } + x2apic_mode = 1; x2apic_state = X2APIC_ON; + __x2apic_enable(); } static __init void try_to_enable_x2apic(int remap_mode) { - if (!x2apic_supported()) + if (x2apic_state == X2APIC_DISABLED) return; if (remap_mode != IRQ_REMAP_X2APIC_MODE) { @@ -1585,12 +1602,7 @@ static __init void try_to_enable_x2apic(int remap_mode) */ x2apic_phys = 1; } - - if (!x2apic_mode) { - x2apic_mode = 1; - enable_x2apic(); - pr_info("Enabled x2apic\n"); - } + x2apic_enable(); } void __init check_x2apic(void) @@ -1616,6 +1628,7 @@ static int __init validate_x2apic(void) early_initcall(validate_x2apic); static inline void try_to_enable_x2apic(int remap_mode) { } +static inline void __x2apic_enable(void) { } #endif /* !CONFIG_X86_X2APIC */ static int __init try_to_enable_IR(void) @@ -2357,9 +2370,9 @@ static void lapic_resume(void) mask_ioapic_entries(); legacy_pic->mask_all(); - if (x2apic_mode) - enable_x2apic(); - else { + if (x2apic_mode) { + __x2apic_enable(); + } else { /* * Make sure the APICBASE points to the right address * diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c6049650c093..cb5692551b98 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1332,7 +1332,7 @@ void cpu_init(void) barrier(); x86_configure_nx(); - enable_x2apic(); + x2apic_setup(); /* * set up and load the per-CPU TSS -- cgit v1.2.3-70-g09d2 From 6d2d49d2cd0199ce298d111ee7fd405af3344a70 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:27 +0000 Subject: x86/x2apic: Use state information for disable Use the state information to simplify the disable logic further. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.209387598@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0ee96b9fe4e6..0c554f5d03a6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1547,26 +1547,20 @@ void x2apic_setup(void) static __init void x2apic_disable(void) { - u64 msr; - - if (!cpu_has_x2apic) - return; - - rdmsrl(MSR_IA32_APICBASE, msr); - if (msr & X2APIC_ENABLE) { - u32 x2apic_id = read_apic_id(); + u32 x2apic_id; - if (x2apic_id >= 255) - panic("Cannot disable x2apic, id: %08x\n", x2apic_id); + if (x2apic_state != X2APIC_ON) + goto out; - __x2apic_disable(); - - x2apic_mode = 0; - - register_lapic_address(mp_lapic_addr); - } + x2apic_id = read_apic_id(); + if (x2apic_id >= 255) + panic("Cannot disable x2apic, id: %08x\n", x2apic_id); + __x2apic_disable(); + register_lapic_address(mp_lapic_addr); +out: x2apic_state = X2APIC_DISABLED; + x2apic_mode = 0; } static __init void x2apic_enable(void) -- cgit v1.2.3-70-g09d2 From f77aa308e5a6144a47311ad6905a1a72bc0014f9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:29 +0000 Subject: x86/smpboot: Move smpboot inlines to code No point for a separate header file. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211703.304126687@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/smpboot_hooks.h | 68 ------------------------------------ arch/x86/kernel/smpboot.c | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 69 deletions(-) delete mode 100644 arch/x86/include/asm/smpboot_hooks.h (limited to 'arch') diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h deleted file mode 100644 index 0da7409f0bec..000000000000 --- a/arch/x86/include/asm/smpboot_hooks.h +++ /dev/null @@ -1,68 +0,0 @@ -/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws - * which needs to alter them. */ - -static inline void smpboot_clear_io_apic_irqs(void) -{ -#ifdef CONFIG_X86_IO_APIC - io_apic_irqs = 0; -#endif -} - -static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) -{ - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - CMOS_WRITE(0xa, 0xf); - spin_unlock_irqrestore(&rtc_lock, flags); - local_flush_tlb(); - pr_debug("1.\n"); - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = - start_eip >> 4; - pr_debug("2.\n"); - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = - start_eip & 0xf; - pr_debug("3.\n"); -} - -static inline void smpboot_restore_warm_reset_vector(void) -{ - unsigned long flags; - - /* - * Install writable page 0 entry to set BIOS data area. - */ - local_flush_tlb(); - - /* - * Paranoid: Set warm reset code and vector here back - * to default values. - */ - spin_lock_irqsave(&rtc_lock, flags); - CMOS_WRITE(0, 0xf); - spin_unlock_irqrestore(&rtc_lock, flags); - - *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; -} - -static inline void __init smpboot_setup_io_apic(void) -{ -#ifdef CONFIG_X86_IO_APIC - /* - * Here we can be sure that there is an IO-APIC in the system. Let's - * go and set it up: - */ - if (!skip_ioapic_setup && nr_ioapics) - setup_IO_APIC(); - else { - nr_ioapics = 0; - } -#endif -} - -static inline void smpboot_clear_io_apic(void) -{ -#ifdef CONFIG_X86_IO_APIC - nr_ioapics = 0; -#endif -} diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6d7022c683e3..110ed1145e27 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -73,7 +73,6 @@ #include #include #include -#include #include #include #include @@ -104,6 +103,71 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); atomic_t init_deasserted; +static inline void smpboot_clear_io_apic_irqs(void) +{ +#ifdef CONFIG_X86_IO_APIC + io_apic_irqs = 0; +#endif +} + +static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) +{ + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + CMOS_WRITE(0xa, 0xf); + spin_unlock_irqrestore(&rtc_lock, flags); + local_flush_tlb(); + pr_debug("1.\n"); + *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = + start_eip >> 4; + pr_debug("2.\n"); + *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = + start_eip & 0xf; + pr_debug("3.\n"); +} + +static inline void smpboot_restore_warm_reset_vector(void) +{ + unsigned long flags; + + /* + * Install writable page 0 entry to set BIOS data area. + */ + local_flush_tlb(); + + /* + * Paranoid: Set warm reset code and vector here back + * to default values. + */ + spin_lock_irqsave(&rtc_lock, flags); + CMOS_WRITE(0, 0xf); + spin_unlock_irqrestore(&rtc_lock, flags); + + *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; +} + +static inline void __init smpboot_setup_io_apic(void) +{ +#ifdef CONFIG_X86_IO_APIC + /* + * Here we can be sure that there is an IO-APIC in the system. Let's + * go and set it up: + */ + if (!skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); + else + nr_ioapics = 0; +#endif +} + +static inline void smpboot_clear_io_apic(void) +{ +#ifdef CONFIG_X86_IO_APIC + nr_ioapics = 0; +#endif +} + /* * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. -- cgit v1.2.3-70-g09d2 From 8686608336e11276d72d020cb0b67bee70d9a5cd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:30 +0000 Subject: x86/ioapic: Provide stub functions for IOAPIC%3Dn To avoid lots of ifdeffery provide proper stubs for setup_IO_APIC(), enable_IO_APIC() and setup_ioapic_dest(). Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.397170414@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/io_apic.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index bf006cce9418..2f91685fe1cd 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -279,6 +279,11 @@ static inline void disable_ioapic_support(void) { } #define native_ioapic_set_affinity NULL #define native_setup_ioapic_entry NULL #define native_eoi_ioapic_pin NULL + +static inline void setup_IO_APIC(void) { } +static inline void enable_IO_APIC(void) { } +static inline void setup_ioapic_dest(void) { } + #endif #endif /* _ASM_X86_IO_APIC_H */ -- cgit v1.2.3-70-g09d2 From a46f5c89274245e42834dc976896444efd53ccdc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:32 +0000 Subject: x86/ioapic: Add proper checks to setp/enable_IO_APIC() No point to have the same checks at every call site. Add them to the functions, so they can be called unconditionally. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.490719938@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/io_apic.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e5e00f509f03..f4dc2462a1ac 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1507,7 +1507,10 @@ void __init enable_IO_APIC(void) int i8259_apic, i8259_pin; int apic, pin; - if (!nr_legacy_irqs()) + if (skip_ioapic_setup) + nr_ioapics = 0; + + if (!nr_legacy_irqs() || !nr_ioapics) return; for_each_ioapic_pin(apic, pin) { @@ -2373,9 +2376,9 @@ void __init setup_IO_APIC(void) { int ioapic; - /* - * calling enable_IO_APIC() is moved to setup_local_APIC for BP - */ + if (skip_ioapic_setup || !nr_ioapics) + return; + io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); -- cgit v1.2.3-70-g09d2 From 35e4c6d30e6f69745d77afd5f63203ad440bed12 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:34 +0000 Subject: x86/apic: Sanitize ioapic handling We have proper stubs for the IOAPIC=n case and the setup/enable function have the required checks inside now. Remove the ifdeffery and the copy&pasted conditionals. Signed-off-by: Thomas Gleixner C Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.569830549@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0c554f5d03a6..3b4bdd5da12e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1905,24 +1905,13 @@ int __init APIC_init_uniprocessor(void) physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); setup_local_APIC(); -#ifdef CONFIG_X86_IO_APIC - /* - * Now enable IO-APICs, actually call clear_IO_APIC - * We need clear_IO_APIC before enabling error vector - */ - if (!skip_ioapic_setup && nr_ioapics) - enable_IO_APIC(); -#endif + /* Enable IO-APICs before enabling error vector */ + enable_IO_APIC(); bsp_end_local_APIC_setup(); -#ifdef CONFIG_X86_IO_APIC - if (smp_found_config && !skip_ioapic_setup && nr_ioapics) + if (smp_found_config) setup_IO_APIC(); - else { - nr_ioapics = 0; - } -#endif x86_init.timers.setup_percpu_clockev(); return 0; -- cgit v1.2.3-70-g09d2 From ef4c59a4b64c62f977187cae444aee25bebb02fe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:35 +0000 Subject: x86/smpboot: Cleanup ioapic handling smpboot is very creative with the ways to disable ioapic. smpboot_clear_io_apic() smpboot_clear_io_apic_irqs() and disable_ioapic_support() serve a similar purpose. smpboot_clear_io_apic_irqs() is the most useless of all functions as it clears a variable which has not been setup yet. Aside of that it has the same ifdef mess and conditionals around the ioapic related code, which can now be removed. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.650280684@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/smpboot.c | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 110ed1145e27..ca7f7b696f07 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -103,13 +103,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); atomic_t init_deasserted; -static inline void smpboot_clear_io_apic_irqs(void) -{ -#ifdef CONFIG_X86_IO_APIC - io_apic_irqs = 0; -#endif -} - static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) { unsigned long flags; @@ -147,27 +140,6 @@ static inline void smpboot_restore_warm_reset_vector(void) *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; } -static inline void __init smpboot_setup_io_apic(void) -{ -#ifdef CONFIG_X86_IO_APIC - /* - * Here we can be sure that there is an IO-APIC in the system. Let's - * go and set it up: - */ - if (!skip_ioapic_setup && nr_ioapics) - setup_IO_APIC(); - else - nr_ioapics = 0; -#endif -} - -static inline void smpboot_clear_io_apic(void) -{ -#ifdef CONFIG_X86_IO_APIC - nr_ioapics = 0; -#endif -} - /* * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. @@ -1019,9 +991,10 @@ void arch_disable_smp_support(void) */ static __init void disable_smp(void) { + disable_ioapic_support(); + init_cpu_present(cpumask_of(0)); init_cpu_possible(cpumask_of(0)); - smpboot_clear_io_apic_irqs(); if (smp_found_config) physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); @@ -1105,7 +1078,6 @@ static int __init smp_sanity_check(unsigned max_cpus) boot_cpu_physical_apicid); pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); } - smpboot_clear_io_apic(); disable_ioapic_support(); return -1; } @@ -1117,7 +1089,7 @@ static int __init smp_sanity_check(unsigned max_cpus) */ if (!max_cpus) { pr_info("SMP mode deactivated\n"); - smpboot_clear_io_apic(); + disable_ioapic_support(); connect_bsp_APIC(); setup_local_APIC(); @@ -1191,18 +1163,15 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) else cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); - /* - * Enable IO APIC before setting up error vector - */ - if (!skip_ioapic_setup && nr_ioapics) - enable_IO_APIC(); + /* Enable IO APIC before setting up error vector */ + enable_IO_APIC(); bsp_end_local_APIC_setup(); - smpboot_setup_io_apic(); + setup_IO_APIC(); + /* * Set up local APIC timer on boot CPU. */ - pr_info("CPU%d: ", 0); print_cpu_info(&cpu_data(0)); x86_init.timers.setup_percpu_clockev(); @@ -1241,9 +1210,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus) nmi_selftest(); impress_friends(); -#ifdef CONFIG_X86_IO_APIC setup_ioapic_dest(); -#endif mtrr_aps_init(); } -- cgit v1.2.3-70-g09d2 From e714a91f92ca59f7e71e7332b8ec2aa2944f629e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:37 +0000 Subject: x86/apic: Move apic_init_uniprocessor code Move the code to a different place so we can make other functions inline. Preparatory patch for further cleanups. No change. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.731329006@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 125 ++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 63 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3b4bdd5da12e..c681e9ba9e47 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1852,71 +1852,8 @@ void __init register_lapic_address(unsigned long address) } } -/* - * This initializes the IO-APIC and APIC hardware if this is - * a UP kernel. - */ int apic_version[MAX_LOCAL_APIC]; -int __init APIC_init_uniprocessor(void) -{ - if (disable_apic) { - pr_info("Apic disabled\n"); - return -1; - } -#ifdef CONFIG_X86_64 - if (!cpu_has_apic) { - disable_apic = 1; - pr_info("Apic disabled by BIOS\n"); - return -1; - } -#else - if (!smp_found_config && !cpu_has_apic) - return -1; - - /* - * Complain if the BIOS pretends there is one. - */ - if (!cpu_has_apic && - APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { - pr_err("BIOS bug, local APIC 0x%x not detected!...\n", - boot_cpu_physical_apicid); - return -1; - } -#endif - - default_setup_apic_routing(); - - verify_local_APIC(); - connect_bsp_APIC(); - -#ifdef CONFIG_X86_64 - apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); -#else - /* - * Hack: In case of kdump, after a crash, kernel might be booting - * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid - * might be zero if read from MP tables. Get it from LAPIC. - */ -# ifdef CONFIG_CRASH_DUMP - boot_cpu_physical_apicid = read_apic_id(); -# endif -#endif - physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); - setup_local_APIC(); - - /* Enable IO-APICs before enabling error vector */ - enable_IO_APIC(); - - bsp_end_local_APIC_setup(); - - if (smp_found_config) - setup_IO_APIC(); - - x86_init.timers.setup_percpu_clockev(); - return 0; -} - /* * Local APIC interrupts */ @@ -2268,6 +2205,68 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) } } +/* + * This initializes the IO-APIC and APIC hardware if this is + * a UP kernel. + */ +int __init APIC_init_uniprocessor(void) +{ + if (disable_apic) { + pr_info("Apic disabled\n"); + return -1; + } +#ifdef CONFIG_X86_64 + if (!cpu_has_apic) { + disable_apic = 1; + pr_info("Apic disabled by BIOS\n"); + return -1; + } +#else + if (!smp_found_config && !cpu_has_apic) + return -1; + + /* + * Complain if the BIOS pretends there is one. + */ + if (!cpu_has_apic && + APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { + pr_err("BIOS bug, local APIC 0x%x not detected!...\n", + boot_cpu_physical_apicid); + return -1; + } +#endif + + default_setup_apic_routing(); + + verify_local_APIC(); + connect_bsp_APIC(); + +#ifdef CONFIG_X86_64 + apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); +#else + /* + * Hack: In case of kdump, after a crash, kernel might be booting + * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid + * might be zero if read from MP tables. Get it from LAPIC. + */ +# ifdef CONFIG_CRASH_DUMP + boot_cpu_physical_apicid = read_apic_id(); +# endif +#endif + physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); + setup_local_APIC(); + + if (smp_found_config) + enable_IO_APIC(); + + bsp_end_local_APIC_setup(); + + setup_IO_APIC(); + + x86_init.timers.setup_percpu_clockev(); + return 0; +} + /* * Power management */ -- cgit v1.2.3-70-g09d2 From 30b8b0066cafef274fc92462578ee346211ce7cb Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:39 +0000 Subject: init: Get rid of x86isms The UP local API support can be set up from an early initcall. No need for horrible hackery in the init code. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211703.827943883@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig | 4 ++++ arch/x86/kernel/apic/apic.c | 7 +++++++ include/linux/smp.h | 7 +++++++ init/main.c | 13 ------------- 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ba397bde7948..ffcc3ca5862a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -855,6 +855,10 @@ config SCHED_MC source "kernel/Kconfig.preempt" +config UP_LATE_INIT + def_bool y + depends on X86_UP_APIC + config X86_UP_APIC bool "Local APIC support on uniprocessors" depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !PCI_MSI diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index c681e9ba9e47..19f1bc714ee6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2267,6 +2267,13 @@ int __init APIC_init_uniprocessor(void) return 0; } +#ifdef CONFIG_UP_LATE_INIT +void __init up_late_init(void) +{ + APIC_init_uniprocessor(); +} +#endif + /* * Power management */ diff --git a/include/linux/smp.h b/include/linux/smp.h index 93dff5fff524..be91db2a7017 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -151,6 +151,13 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, static inline void kick_all_cpus_sync(void) { } static inline void wake_up_all_idle_cpus(void) { } +#ifdef CONFIG_UP_LATE_INIT +extern void __init up_late_init(void); +static inline void smp_init(void) { up_late_init(); } +#else +static inline void smp_init(void) { } +#endif + #endif /* !SMP */ /* diff --git a/init/main.c b/init/main.c index 61b993767db5..179ada15d08a 100644 --- a/init/main.c +++ b/init/main.c @@ -87,10 +87,6 @@ #include #include -#ifdef CONFIG_X86_LOCAL_APIC -#include -#endif - static int kernel_init(void *); extern void init_IRQ(void); @@ -351,15 +347,6 @@ __setup("rdinit=", rdinit_setup); #ifndef CONFIG_SMP static const unsigned int setup_max_cpus = NR_CPUS; -#ifdef CONFIG_X86_LOCAL_APIC -static void __init smp_init(void) -{ - APIC_init_uniprocessor(); -} -#else -#define smp_init() do { } while (0) -#endif - static inline void setup_nr_cpu_ids(void) { } static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif -- cgit v1.2.3-70-g09d2 From 05f7e46d2aac359b6bcfc06b302bdd03ca0bcada Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:40 +0000 Subject: x86/smpboot: Move apic init code to apic.c We better provide proper functions which implement the required code flow in the apic code rather than letting the smpboot code open code it. That allows to make more functions static and confines the APIC functionality to apic.c where it belongs. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.907616730@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 6 +++--- arch/x86/kernel/apic/apic.c | 51 ++++++++++++++++++++++++++++++++++++--------- arch/x86/kernel/smpboot.c | 27 +++--------------------- 3 files changed, 47 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index ac60c603f8dd..92f34042be85 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -201,7 +201,6 @@ extern int get_physical_broadcast(void); extern int lapic_get_maxlvt(void); extern void clear_local_APIC(void); -extern void connect_bsp_APIC(void); extern void disconnect_bsp_APIC(int virt_wire_setup); extern void disable_local_APIC(void); extern void lapic_shutdown(void); @@ -209,8 +208,6 @@ extern int verify_local_APIC(void); extern void sync_Arb_IDs(void); extern void init_bsp_APIC(void); extern void setup_local_APIC(void); -extern void end_local_APIC_setup(void); -extern void bsp_end_local_APIC_setup(void); extern void init_apic_mappings(void); void register_lapic_address(unsigned long address); extern void setup_boot_APIC_clock(void); @@ -218,6 +215,9 @@ extern void setup_secondary_APIC_clock(void); extern int APIC_init_uniprocessor(void); extern int apic_force_enable(unsigned long addr); +extern int apic_bsp_setup(void); +extern void apic_ap_setup(void); + /* * On 32bit this is mach-xxx local */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 19f1bc714ee6..0a4107013ada 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1445,7 +1445,7 @@ void setup_local_APIC(void) #endif } -void end_local_APIC_setup(void) +static void end_local_APIC_setup(void) { lapic_setup_esr(); @@ -1462,16 +1462,13 @@ void end_local_APIC_setup(void) apic_pm_activate(); } -void __init bsp_end_local_APIC_setup(void) +/* + * APIC setup function for application processors. Called from smpboot.c + */ +void apic_ap_setup(void) { + setup_local_APIC(); end_local_APIC_setup(); - - /* - * Now that local APIC setup is completed for BP, configure the fault - * handling for interrupt remapping. - */ - irq_remap_enable_fault_handling(); - } #ifdef CONFIG_X86_X2APIC @@ -1958,7 +1955,7 @@ __visible void smp_trace_error_interrupt(struct pt_regs *regs) /** * connect_bsp_APIC - attach the APIC to the interrupt system */ -void __init connect_bsp_APIC(void) +static void __init connect_bsp_APIC(void) { #ifdef CONFIG_X86_32 if (pic_mode) { @@ -2205,6 +2202,40 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) } } +static void __init bsp_end_local_APIC_setup(void) +{ + end_local_APIC_setup(); + /* + * Now that local APIC setup is completed for BP, configure the fault + * handling for interrupt remapping. + */ + irq_remap_enable_fault_handling(); +} + +/** + * apic_bsp_setup - Setup function for local apic and io-apic + * + * Returns: + * apic_id of BSP APIC + */ +int __init apic_bsp_setup(void) +{ + int id; + + connect_bsp_APIC(); + setup_local_APIC(); + + if (x2apic_mode) + id = apic_read(APIC_LDR); + else + id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); + + enable_IO_APIC(); + bsp_end_local_APIC_setup(); + setup_IO_APIC(); + return id; +} + /* * This initializes the IO-APIC and APIC hardware if this is * a UP kernel. diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index ca7f7b696f07..d53870928824 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -172,8 +172,7 @@ static void smp_callin(void) * CPU, first the APIC. (this is probably redundant on most * boards) */ - setup_local_APIC(); - end_local_APIC_setup(); + apic_ap_setup(); /* * Need to setup vector mappings before we enable interrupts. @@ -1078,7 +1077,6 @@ static int __init smp_sanity_check(unsigned max_cpus) boot_cpu_physical_apicid); pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); } - disable_ioapic_support(); return -1; } @@ -1090,10 +1088,7 @@ static int __init smp_sanity_check(unsigned max_cpus) if (!max_cpus) { pr_info("SMP mode deactivated\n"); disable_ioapic_support(); - - connect_bsp_APIC(); - setup_local_APIC(); - bsp_end_local_APIC_setup(); + apic_bsp_setup(); return -1; } @@ -1151,23 +1146,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) /* Or can we switch back to PIC here? */ } - connect_bsp_APIC(); - - /* - * Switch from PIC to APIC mode. - */ - setup_local_APIC(); - - if (x2apic_mode) - cpu0_logical_apicid = apic_read(APIC_LDR); - else - cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); - - /* Enable IO APIC before setting up error vector */ - enable_IO_APIC(); - - bsp_end_local_APIC_setup(); - setup_IO_APIC(); + cpu0_logical_apicid = apic_bsp_setup(); /* * Set up local APIC timer on boot CPU. -- cgit v1.2.3-70-g09d2 From 613c25efbdc763ee8b9d732368106d2456279356 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:42 +0000 Subject: x86/smpboot: Sanitize uniprocessor init The UP related setups for local apic are mangled into smp_sanity_check(). That results in duplicate calls to disable_smp() and makes the code hard to follow. Let smp_sanity_check() return dedicated values for the various exit reasons and handle them at the call site. Signed-off-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Link: http://lkml.kernel.org/r/20150115211703.987833932@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/smpboot.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index d53870928824..fe8783d500c2 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -990,6 +990,8 @@ void arch_disable_smp_support(void) */ static __init void disable_smp(void) { + pr_info("SMP disabled\n"); + disable_ioapic_support(); init_cpu_present(cpumask_of(0)); @@ -1003,6 +1005,13 @@ static __init void disable_smp(void) cpumask_set_cpu(0, cpu_core_mask(0)); } +enum { + SMP_OK, + SMP_NO_CONFIG, + SMP_NO_APIC, + SMP_FORCE_UP, +}; + /* * Various sanity checks. */ @@ -1050,10 +1059,7 @@ static int __init smp_sanity_check(unsigned max_cpus) if (!smp_found_config && !acpi_lapic) { preempt_enable(); pr_notice("SMP motherboard not detected\n"); - disable_smp(); - if (APIC_init_uniprocessor()) - pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); - return -1; + return SMP_NO_CONFIG; } /* @@ -1077,7 +1083,7 @@ static int __init smp_sanity_check(unsigned max_cpus) boot_cpu_physical_apicid); pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); } - return -1; + return SMP_NO_APIC; } verify_local_APIC(); @@ -1087,12 +1093,10 @@ static int __init smp_sanity_check(unsigned max_cpus) */ if (!max_cpus) { pr_info("SMP mode deactivated\n"); - disable_ioapic_support(); - apic_bsp_setup(); - return -1; + return SMP_FORCE_UP; } - return 0; + return SMP_OK; } static void __init smp_cpu_index_default(void) @@ -1132,10 +1136,21 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) } set_cpu_sibling_map(0); - if (smp_sanity_check(max_cpus) < 0) { - pr_info("SMP disabled\n"); + switch (smp_sanity_check(max_cpus)) { + case SMP_NO_CONFIG: disable_smp(); + if (APIC_init_uniprocessor()) + pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); + return; + case SMP_NO_APIC: + disable_smp(); + return; + case SMP_FORCE_UP: + disable_smp(); + apic_bsp_setup(); return; + case SMP_OK: + break; } default_setup_apic_routing(); -- cgit v1.2.3-70-g09d2 From 374aab339f10f0510cec0e79d752d31d84b08aa2 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:44 +0000 Subject: x86/apic: Reuse apic_bsp_setup() for UP APIC setup Extend apic_bsp_setup() so the same code flow can be used for APIC_init_uniprocessor(). Folded Jiangs fix to provide proper ordering of the UP setup. Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211704.084765674@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 2 +- arch/x86/kernel/apic/apic.c | 53 +++++++++++++++++++-------------------------- arch/x86/kernel/smpboot.c | 4 ++-- 3 files changed, 25 insertions(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 92f34042be85..92003f3c8a42 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -215,7 +215,7 @@ extern void setup_secondary_APIC_clock(void); extern int APIC_init_uniprocessor(void); extern int apic_force_enable(unsigned long addr); -extern int apic_bsp_setup(void); +extern int apic_bsp_setup(bool upmode); extern void apic_ap_setup(void); /* diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0a4107013ada..437c35bdddc8 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2202,27 +2202,37 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) } } -static void __init bsp_end_local_APIC_setup(void) +static void __init apic_bsp_up_setup(void) { - end_local_APIC_setup(); +#ifdef CONFIG_X86_64 + apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); +#else /* - * Now that local APIC setup is completed for BP, configure the fault - * handling for interrupt remapping. + * Hack: In case of kdump, after a crash, kernel might be booting + * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid + * might be zero if read from MP tables. Get it from LAPIC. */ - irq_remap_enable_fault_handling(); +# ifdef CONFIG_CRASH_DUMP + boot_cpu_physical_apicid = read_apic_id(); +# endif +#endif + physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); } /** * apic_bsp_setup - Setup function for local apic and io-apic + * @upmode: Force UP mode (for APIC_init_uniprocessor) * * Returns: * apic_id of BSP APIC */ -int __init apic_bsp_setup(void) +int __init apic_bsp_setup(bool upmode) { int id; connect_bsp_APIC(); + if (upmode) + apic_bsp_up_setup(); setup_local_APIC(); if (x2apic_mode) @@ -2231,7 +2241,8 @@ int __init apic_bsp_setup(void) id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); enable_IO_APIC(); - bsp_end_local_APIC_setup(); + end_local_APIC_setup(); + irq_remap_enable_fault_handling(); setup_IO_APIC(); return id; } @@ -2267,32 +2278,12 @@ int __init APIC_init_uniprocessor(void) } #endif - default_setup_apic_routing(); + if (!smp_found_config) + disable_ioapic_support(); + default_setup_apic_routing(); verify_local_APIC(); - connect_bsp_APIC(); - -#ifdef CONFIG_X86_64 - apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); -#else - /* - * Hack: In case of kdump, after a crash, kernel might be booting - * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid - * might be zero if read from MP tables. Get it from LAPIC. - */ -# ifdef CONFIG_CRASH_DUMP - boot_cpu_physical_apicid = read_apic_id(); -# endif -#endif - physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); - setup_local_APIC(); - - if (smp_found_config) - enable_IO_APIC(); - - bsp_end_local_APIC_setup(); - - setup_IO_APIC(); + apic_bsp_setup(true); x86_init.timers.setup_percpu_clockev(); return 0; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fe8783d500c2..0a46e5e4fa1f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1147,7 +1147,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) return; case SMP_FORCE_UP: disable_smp(); - apic_bsp_setup(); + apic_bsp_setup(false); return; case SMP_OK: break; @@ -1161,7 +1161,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) /* Or can we switch back to PIC here? */ } - cpu0_logical_apicid = apic_bsp_setup(); + cpu0_logical_apicid = apic_bsp_setup(false); /* * Set up local APIC timer on boot CPU. -- cgit v1.2.3-70-g09d2 From 9c4d9c73dd380ecfe1893600174f96d0eb068997 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Jan 2015 21:22:45 +0000 Subject: x86: Consolidate boot cpu timer setup Now that the APIC bringup is consolidated we can move the setup call for the percpu clock event device to apic_bsp_setup(). Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel Cc: Tony Luck Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20150115211704.162567839@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 4 ++-- arch/x86/kernel/smpboot.c | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 437c35bdddc8..b665d241efad 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2244,6 +2244,8 @@ int __init apic_bsp_setup(bool upmode) end_local_APIC_setup(); irq_remap_enable_fault_handling(); setup_IO_APIC(); + /* Setup local timer */ + x86_init.timers.setup_percpu_clockev(); return id; } @@ -2284,8 +2286,6 @@ int __init APIC_init_uniprocessor(void) default_setup_apic_routing(); verify_local_APIC(); apic_bsp_setup(true); - - x86_init.timers.setup_percpu_clockev(); return 0; } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0a46e5e4fa1f..febc6aabc72e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1163,12 +1163,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) cpu0_logical_apicid = apic_bsp_setup(false); - /* - * Set up local APIC timer on boot CPU. - */ pr_info("CPU%d: ", 0); print_cpu_info(&cpu_data(0)); - x86_init.timers.setup_percpu_clockev(); if (is_uv_system()) uv_system_init(); -- cgit v1.2.3-70-g09d2 From 2f82c9dc608a03913acc04e990b31fec22b2c0b7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 22 Jan 2015 15:13:36 +0100 Subject: x86/acpi: Make acpi_[un]register_gsi_ioapic() depend on CONFIG_X86_LOCAL_APIC Get rid of the defined but not used warnings Signed-off-by: Thomas Gleixner Cc: Jiang Liu --- arch/x86/kernel/acpi/boot.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index d1626364a28a..add9b3a4ba13 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -653,6 +653,7 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi, return gsi; } +#ifdef CONFIG_X86_LOCAL_APIC static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, int trigger, int polarity) { @@ -675,6 +676,7 @@ static void acpi_unregister_gsi_ioapic(u32 gsi) mutex_unlock(&acpi_ioapic_lock); #endif } +#endif int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; -- cgit v1.2.3-70-g09d2 From ba360f887a4130b06c55eb93bcb4ae373b262a1c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 24 Jan 2015 10:34:46 +0100 Subject: x86, init: Fix UP boot regression on x86_64 Commit 30b8b0066caf "init: Get rid of x86isms" broke the UP boot on x86_64. That happens because CONFIG_UP_LATE_INIT depends on CONFIG_X86_UP_APIC. X86_UP_APIC is a 32bit only config switch and therefor not set on 64bit UP builds. As a consequence the UP init of the local APIC and the IOAPIC is not called, which results in a boot failure. Make it depend on !SMP && X86_LOCAL_APIC instead. Fixes: 30b8b0066caf init: Get rid of x86isms Reported-by: Fengguang Wu Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ffcc3ca5862a..04b8810a5489 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -857,7 +857,7 @@ source "kernel/Kconfig.preempt" config UP_LATE_INIT def_bool y - depends on X86_UP_APIC + depends on !SMP && X86_LOCAL_APIC config X86_UP_APIC bool "Local APIC support on uniprocessors" -- cgit v1.2.3-70-g09d2