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
This commit is contained in:
commit
1a7dbbcc8c
@ -774,6 +774,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
disable= [IPV6]
|
||||
See Documentation/networking/ipv6.txt.
|
||||
|
||||
disable_cpu_apicid= [X86,APIC,SMP]
|
||||
Format: <int>
|
||||
The number of initial APIC ID for the
|
||||
corresponding CPU to be disabled at boot,
|
||||
mostly used for the kdump 2nd kernel to
|
||||
disable BSP to wake up multiple CPUs without
|
||||
causing system reset or hang due to sending
|
||||
INIT from AP to BSP.
|
||||
|
||||
disable_ddw [PPC/PSERIES]
|
||||
Disable Dynamic DMA Window support. Use this if
|
||||
to workaround buggy firmware.
|
||||
|
@ -74,6 +74,13 @@ unsigned int max_physical_apicid;
|
||||
*/
|
||||
physid_mask_t phys_cpu_present_map;
|
||||
|
||||
/*
|
||||
* Processor to be disabled specified by kernel parameter
|
||||
* disable_cpu_apicid=<int>, mostly used for the kdump 2nd kernel to
|
||||
* avoid undefined behaviour caused by sending INIT from AP to BSP.
|
||||
*/
|
||||
static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID;
|
||||
|
||||
/*
|
||||
* Map cpu index to physical APIC ID
|
||||
*/
|
||||
@ -1968,7 +1975,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs)
|
||||
*/
|
||||
static inline void __smp_error_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
u32 v0, v1;
|
||||
u32 v;
|
||||
u32 i = 0;
|
||||
static const char * const error_interrupt_reason[] = {
|
||||
"Send CS error", /* APIC Error Bit 0 */
|
||||
@ -1982,21 +1989,20 @@ static inline void __smp_error_interrupt(struct pt_regs *regs)
|
||||
};
|
||||
|
||||
/* First tickle the hardware, only then report what went on. -- REW */
|
||||
v0 = apic_read(APIC_ESR);
|
||||
apic_write(APIC_ESR, 0);
|
||||
v1 = apic_read(APIC_ESR);
|
||||
v = apic_read(APIC_ESR);
|
||||
ack_APIC_irq();
|
||||
atomic_inc(&irq_err_count);
|
||||
|
||||
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)",
|
||||
smp_processor_id(), v0 , v1);
|
||||
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
|
||||
smp_processor_id(), v);
|
||||
|
||||
v1 = v1 & 0xff;
|
||||
while (v1) {
|
||||
if (v1 & 0x1)
|
||||
v &= 0xff;
|
||||
while (v) {
|
||||
if (v & 0x1)
|
||||
apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
|
||||
i++;
|
||||
v1 >>= 1;
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
apic_printk(APIC_DEBUG, KERN_CONT "\n");
|
||||
@ -2114,6 +2120,39 @@ int generic_processor_info(int apicid, int version)
|
||||
bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
|
||||
phys_cpu_present_map);
|
||||
|
||||
/*
|
||||
* boot_cpu_physical_apicid is designed to have the apicid
|
||||
* returned by read_apic_id(), i.e, the apicid of the
|
||||
* currently booting-up processor. However, on some platforms,
|
||||
* it is temporarily modified by the apicid reported as BSP
|
||||
* through MP table. Concretely:
|
||||
*
|
||||
* - arch/x86/kernel/mpparse.c: MP_processor_info()
|
||||
* - arch/x86/mm/amdtopology.c: amd_numa_init()
|
||||
* - arch/x86/platform/visws/visws_quirks.c: MP_processor_info()
|
||||
*
|
||||
* This function is executed with the modified
|
||||
* boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel
|
||||
* parameter doesn't work to disable APs on kdump 2nd kernel.
|
||||
*
|
||||
* Since fixing handling of boot_cpu_physical_apicid requires
|
||||
* another discussion and tests on each platform, we leave it
|
||||
* for now and here we use read_apic_id() directly in this
|
||||
* function, generic_processor_info().
|
||||
*/
|
||||
if (disabled_cpu_apicid != BAD_APICID &&
|
||||
disabled_cpu_apicid != read_apic_id() &&
|
||||
disabled_cpu_apicid == apicid) {
|
||||
int thiscpu = num_processors + disabled_cpus;
|
||||
|
||||
pr_warning("APIC: Disabling requested cpu."
|
||||
" Processor %d/0x%x ignored.\n",
|
||||
thiscpu, apicid);
|
||||
|
||||
disabled_cpus++;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* If boot cpu has not been detected yet, then only allow upto
|
||||
* nr_cpu_ids - 1 processors and keep one slot free for boot cpu
|
||||
@ -2592,3 +2631,12 @@ static int __init lapic_insert_resource(void)
|
||||
* that is using request_resource
|
||||
*/
|
||||
late_initcall(lapic_insert_resource);
|
||||
|
||||
static int __init apic_set_disabled_cpu_apicid(char *arg)
|
||||
{
|
||||
if (!arg || !get_option(&arg, &disabled_cpu_apicid))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid);
|
||||
|
Loading…
Reference in New Issue
Block a user