aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>2014-01-15 01:44:58 -0500
committerH. Peter Anvin <hpa@zytor.com>2014-01-15 12:19:20 -0500
commit151e0c7de616310f95393d9306903900fcd8b277 (patch)
tree8a89917fe18c1d34d9208249d71eb812ad040358
parent60283df7ac26a4fe2d56631ca2946e04725e7eaf (diff)
x86, apic, kexec: Add disable_cpu_apicid kernel parameter
Add disable_cpu_apicid kernel parameter. To use this kernel parameter, specify an initial APIC ID of the corresponding CPU you want to disable. This is 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. Kdump users first figure out initial APIC ID of the BSP, CPU0 in the 1st kernel, for example from /proc/cpuinfo and then set up this kernel parameter for the 2nd kernel using the obtained APIC ID. However, doing this procedure at each boot time manually is awkward, which should be automatically done by user-land service scripts, for example, kexec-tools on fedora/RHEL distributions. This design is more flexible than disabling BSP in kernel boot time automatically in that in kernel boot time we have no choice but referring to ACPI/MP table to obtain initial APIC ID for BSP, meaning that the method is not applicable to the systems without such BIOS tables. One assumption behind this design is that users get initial APIC ID of the BSP in still healthy state and so BSP is uniquely kept in CPU0. Thus, through the kernel parameter, only one initial APIC ID can be specified. In a comparison with disabled_cpu_apicid, we use read_apic_id(), not boot_cpu_physical_apicid, because on some platforms, the variable is modified to the apicid reported as BSP through MP table and this function is executed with the temporarily modified boot_cpu_physical_apicid. As a result, disabled_cpu_apicid kernel parameter doesn't work well for apicids of APs. Fixing the wrong handling of boot_cpu_physical_apicid requires some reviews and tests beyond some platforms and it could take some time. The fix here is a kind of workaround to focus on the main topic of this patch. Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com> Link: http://lkml.kernel.org/r/20140115064458.1545.38775.stgit@localhost6.localdomain6 Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--arch/x86/kernel/apic/apic.c49
2 files changed, 58 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b9e9bd854298..6fdbf8c968e6 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 4ec1dd64022a..e78ab8c8ac2e 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 */
82unsigned int disabled_cpu_apicid = 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);
@@ -2114,6 +2121,39 @@ int generic_processor_info(int apicid, int version)
2114 phys_cpu_present_map); 2121 phys_cpu_present_map);
2115 2122
2116 /* 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 temporarilly 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("ACPI: Disabling requested cpu."
2149 " Processor %d/0x%x ignored.\n",
2150 thiscpu, apicid);
2151
2152 disabled_cpus++;
2153 return -ENODEV;
2154 }
2155
2156 /*
2117 * 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
2118 * 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
2119 */ 2159 */
@@ -2591,3 +2631,12 @@ static int __init lapic_insert_resource(void)
2591 * that is using request_resource 2631 * that is using request_resource
2592 */ 2632 */
2593late_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);