@@ -74,6 +74,13 @@ unsigned int max_physical_apicid;
74
74
*/
75
75
physid_mask_t phys_cpu_present_map ;
76
76
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
+ */
82
+ static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID ;
83
+
77
84
/*
78
85
* Map cpu index to physical APIC ID
79
86
*/
@@ -1968,7 +1975,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs)
1968
1975
*/
1969
1976
static inline void __smp_error_interrupt (struct pt_regs * regs )
1970
1977
{
1971
- u32 v0 , v1 ;
1978
+ u32 v ;
1972
1979
u32 i = 0 ;
1973
1980
static const char * const error_interrupt_reason [] = {
1974
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
1991
/* First tickle the hardware, only then report what went on. -- REW */
1985
- v0 = apic_read (APIC_ESR );
1986
1992
apic_write (APIC_ESR , 0 );
1987
- v1 = apic_read (APIC_ESR );
1993
+ v = apic_read (APIC_ESR );
1988
1994
ack_APIC_irq ();
1989
1995
atomic_inc (& irq_err_count );
1990
1996
1991
- apic_printk (APIC_DEBUG , KERN_DEBUG "APIC error on CPU%d: %02x(%02x) " ,
1992
- smp_processor_id (), v0 , v1 );
1997
+ apic_printk (APIC_DEBUG , KERN_DEBUG "APIC error on CPU%d: %02x" ,
1998
+ smp_processor_id (), v );
1993
1999
1994
- v1 = v1 & 0xff ;
1995
- while (v1 ) {
1996
- if (v1 & 0x1 )
2000
+ v &= 0xff ;
2001
+ while (v ) {
2002
+ if (v & 0x1 )
1997
2003
apic_printk (APIC_DEBUG , KERN_CONT " : %s" , error_interrupt_reason [i ]);
1998
2004
i ++ ;
1999
- v1 >>= 1 ;
2005
+ v >>= 1 ;
2000
2006
}
2001
2007
2002
2008
apic_printk (APIC_DEBUG , KERN_CONT "\n" );
@@ -2114,6 +2120,39 @@ int generic_processor_info(int apicid, int version)
2114
2120
bool boot_cpu_detected = physid_isset (boot_cpu_physical_apicid ,
2115
2121
phys_cpu_present_map );
2116
2122
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
+
2117
2156
/*
2118
2157
* If boot cpu has not been detected yet, then only allow upto
2119
2158
* nr_cpu_ids - 1 processors and keep one slot free for boot cpu
@@ -2592,3 +2631,12 @@ static int __init lapic_insert_resource(void)
2592
2631
* that is using request_resource
2593
2632
*/
2594
2633
late_initcall (lapic_insert_resource );
2634
+
2635
+ static 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
+ }
2642
+ early_param ("disable_cpu_apicid" , apic_set_disabled_cpu_apicid );
0 commit comments