aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 14:50:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 14:50:01 -0500
commit1a7dbbcc8cc6b34f3a4ae92026759fc057ffcba2 (patch)
tree1efa6cab2815c889ba8fbc928eab47f76c721e49
parent6c6461435611e1d4843516f2d55e8316c009112e (diff)
parent5b4d1dbc24bb6fd7179ada0f47be34e27e64decb (diff)
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/apic changes from Ingo Molnar: "Two main changes: - improve local APIC Error Status Register reporting robustness - add the 'disable_cpu_apicid=x' boot parameter for kexec booting" * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, apic: Make disabled_cpu_apicid static read_mostly, fix typos x86, apic, kexec: Add disable_cpu_apicid kernel parameter x86/apic: Read Error Status Register correctly
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--arch/x86/kernel/apic/apic.c66
2 files changed, 66 insertions, 9 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0940078edebb..3b8e262c3657 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -774,6 +774,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
774 disable= [IPV6] 774 disable= [IPV6]
775 See Documentation/networking/ipv6.txt. 775 See Documentation/networking/ipv6.txt.
776 776
777 disable_cpu_apicid= [X86,APIC,SMP]
778 Format: <int>
779 The number of initial APIC ID for the
780 corresponding CPU to be disabled at boot,
781 mostly used for the kdump 2nd kernel to
782 disable BSP to wake up multiple CPUs without
783 causing system reset or hang due to sending
784 INIT from AP to BSP.
785
777 disable_ddw [PPC/PSERIES] 786 disable_ddw [PPC/PSERIES]
778 Disable Dynamic DMA Window support. Use this if 787 Disable Dynamic DMA Window support. Use this if
779 to workaround buggy firmware. 788 to workaround buggy firmware.
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index d278736bf774..7f26c9a70a9e 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -75,6 +75,13 @@ unsigned int max_physical_apicid;
75physid_mask_t phys_cpu_present_map; 75physid_mask_t phys_cpu_present_map;
76 76
77/* 77/*
78 * Processor to be disabled specified by kernel parameter
79 * disable_cpu_apicid=<int>, mostly used for the kdump 2nd kernel to
80 * avoid undefined behaviour caused by sending INIT from AP to BSP.
81 */
82static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID;
83
84/*
78 * Map cpu index to physical APIC ID 85 * Map cpu index to physical APIC ID
79 */ 86 */
80DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); 87DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID);
@@ -1968,7 +1975,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs)
1968 */ 1975 */
1969static inline void __smp_error_interrupt(struct pt_regs *regs) 1976static inline void __smp_error_interrupt(struct pt_regs *regs)
1970{ 1977{
1971 u32 v0, v1; 1978 u32 v;
1972 u32 i = 0; 1979 u32 i = 0;
1973 static const char * const error_interrupt_reason[] = { 1980 static const char * const error_interrupt_reason[] = {
1974 "Send CS error", /* APIC Error Bit 0 */ 1981 "Send CS error", /* APIC Error Bit 0 */
@@ -1982,21 +1989,20 @@ static inline void __smp_error_interrupt(struct pt_regs *regs)
1982 }; 1989 };
1983 1990
1984 /* First tickle the hardware, only then report what went on. -- REW */ 1991 /* First tickle the hardware, only then report what went on. -- REW */
1985 v0 = apic_read(APIC_ESR);
1986 apic_write(APIC_ESR, 0); 1992 apic_write(APIC_ESR, 0);
1987 v1 = apic_read(APIC_ESR); 1993 v = apic_read(APIC_ESR);
1988 ack_APIC_irq(); 1994 ack_APIC_irq();
1989 atomic_inc(&irq_err_count); 1995 atomic_inc(&irq_err_count);
1990 1996
1991 apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)", 1997 apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
1992 smp_processor_id(), v0 , v1); 1998 smp_processor_id(), v);
1993 1999
1994 v1 = v1 & 0xff; 2000 v &= 0xff;
1995 while (v1) { 2001 while (v) {
1996 if (v1 & 0x1) 2002 if (v & 0x1)
1997 apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); 2003 apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
1998 i++; 2004 i++;
1999 v1 >>= 1; 2005 v >>= 1;
2000 } 2006 }
2001 2007
2002 apic_printk(APIC_DEBUG, KERN_CONT "\n"); 2008 apic_printk(APIC_DEBUG, KERN_CONT "\n");
@@ -2115,6 +2121,39 @@ int generic_processor_info(int apicid, int version)
2115 phys_cpu_present_map); 2121 phys_cpu_present_map);
2116 2122
2117 /* 2123 /*
2124 * boot_cpu_physical_apicid is designed to have the apicid
2125 * returned by read_apic_id(), i.e, the apicid of the
2126 * currently booting-up processor. However, on some platforms,
2127 * it is temporarily modified by the apicid reported as BSP
2128 * through MP table. Concretely:
2129 *
2130 * - arch/x86/kernel/mpparse.c: MP_processor_info()
2131 * - arch/x86/mm/amdtopology.c: amd_numa_init()
2132 * - arch/x86/platform/visws/visws_quirks.c: MP_processor_info()
2133 *
2134 * This function is executed with the modified
2135 * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel
2136 * parameter doesn't work to disable APs on kdump 2nd kernel.
2137 *
2138 * Since fixing handling of boot_cpu_physical_apicid requires
2139 * another discussion and tests on each platform, we leave it
2140 * for now and here we use read_apic_id() directly in this
2141 * function, generic_processor_info().
2142 */
2143 if (disabled_cpu_apicid != BAD_APICID &&
2144 disabled_cpu_apicid != read_apic_id() &&
2145 disabled_cpu_apicid == apicid) {
2146 int thiscpu = num_processors + disabled_cpus;
2147
2148 pr_warning("APIC: Disabling requested cpu."
2149 " Processor %d/0x%x ignored.\n",
2150 thiscpu, apicid);
2151
2152 disabled_cpus++;
2153 return -ENODEV;
2154 }
2155
2156 /*
2118 * If boot cpu has not been detected yet, then only allow upto 2157 * If boot cpu has not been detected yet, then only allow upto
2119 * nr_cpu_ids - 1 processors and keep one slot free for boot cpu 2158 * nr_cpu_ids - 1 processors and keep one slot free for boot cpu
2120 */ 2159 */
@@ -2592,3 +2631,12 @@ static int __init lapic_insert_resource(void)
2592 * that is using request_resource 2631 * that is using request_resource
2593 */ 2632 */
2594late_initcall(lapic_insert_resource); 2633late_initcall(lapic_insert_resource);
2634
2635static int __init apic_set_disabled_cpu_apicid(char *arg)
2636{
2637 if (!arg || !get_option(&arg, &disabled_cpu_apicid))
2638 return -EINVAL;
2639
2640 return 0;
2641}
2642early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid);