Skip to content

Commit d10a904

Browse files
KAGA-KOKOhansendc
authored andcommitted
x86/apic: Consolidate boot_cpu_physical_apicid initialization sites
boot_cpu_physical_apicid is written in random places and in the last consequence filled with the APIC ID read from the local APIC. That causes it to have inconsistent state when the MPTABLE is broken. As a consequence tons of moronic checks are sprinkled all over the place. Consolidate the code and read it exactly once when either X2APIC mode is detected early or when the APIC mapping is established. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Michael Kelley <[email protected]> Tested-by: Sohil Mehta <[email protected]> Tested-by: Juergen Gross <[email protected]> # Xen PV (dom0 and unpriv. guest)
1 parent 1d90c9f commit d10a904

File tree

3 files changed

+34
-74
lines changed

3 files changed

+34
-74
lines changed

arch/x86/include/asm/apic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ static inline int x2apic_enabled(void)
247247
#else /* !CONFIG_X86_X2APIC */
248248
static inline void x2apic_setup(void) { }
249249
static inline int x2apic_enabled(void) { return 0; }
250-
250+
static inline u32 native_apic_msr_read(u32 reg) { BUG(); }
251251
#define x2apic_mode (0)
252252
#define x2apic_supported() (0)
253253
#endif /* !CONFIG_X86_X2APIC */

arch/x86/kernel/apic/apic.c

Lines changed: 32 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,8 +1318,7 @@ static int __init __apic_intr_mode_select(void)
13181318
if (!boot_cpu_has(X86_FEATURE_APIC) &&
13191319
APIC_INTEGRATED(boot_cpu_apic_version)) {
13201320
apic_is_disabled = true;
1321-
pr_err(FW_BUG "Local APIC %d not detected, force emulation\n",
1322-
boot_cpu_physical_apicid);
1321+
pr_err(FW_BUG "Local APIC not detected, force emulation\n");
13231322
return APIC_PIC;
13241323
}
13251324
#endif
@@ -1340,12 +1339,6 @@ static int __init __apic_intr_mode_select(void)
13401339
pr_info("APIC: SMP mode deactivated\n");
13411340
return APIC_SYMMETRIC_IO_NO_ROUTING;
13421341
}
1343-
1344-
if (read_apic_id() != boot_cpu_physical_apicid) {
1345-
panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
1346-
read_apic_id(), boot_cpu_physical_apicid);
1347-
/* Or can we switch back to PIC here? */
1348-
}
13491342
#endif
13501343

13511344
return APIC_SYMMETRIC_IO;
@@ -1741,6 +1734,23 @@ void apic_ap_setup(void)
17411734
end_local_APIC_setup();
17421735
}
17431736

1737+
static __init void apic_read_boot_cpu_id(bool x2apic)
1738+
{
1739+
/*
1740+
* This can be invoked from check_x2apic() before the APIC has been
1741+
* selected. But that code knows for sure that the BIOS enabled
1742+
* X2APIC.
1743+
*/
1744+
if (x2apic) {
1745+
boot_cpu_physical_apicid = native_apic_msr_read(APIC_ID);
1746+
boot_cpu_apic_version = GET_APIC_VERSION(native_apic_msr_read(APIC_LVR));
1747+
} else {
1748+
boot_cpu_physical_apicid = read_apic_id();
1749+
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
1750+
}
1751+
}
1752+
1753+
17441754
#ifdef CONFIG_X86_X2APIC
17451755
int x2apic_mode;
17461756
EXPORT_SYMBOL_GPL(x2apic_mode);
@@ -1921,6 +1931,7 @@ void __init check_x2apic(void)
19211931
x2apic_state = X2APIC_ON_LOCKED;
19221932
else
19231933
x2apic_state = X2APIC_ON;
1934+
apic_read_boot_cpu_id(true);
19241935
} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
19251936
x2apic_state = X2APIC_DISABLED;
19261937
}
@@ -2109,15 +2120,11 @@ static int __init detect_init_APIC(void)
21092120
*/
21102121
void __init init_apic_mappings(void)
21112122
{
2112-
unsigned int new_apicid;
2113-
21142123
if (apic_validate_deadline_timer())
21152124
pr_info("TSC deadline timer available\n");
21162125

2117-
if (x2apic_mode) {
2118-
boot_cpu_physical_apicid = read_apic_id();
2126+
if (x2apic_mode)
21192127
return;
2120-
}
21212128

21222129
/* If no local APIC can be found return early */
21232130
if (!smp_found_config && detect_init_APIC()) {
@@ -2134,39 +2141,19 @@ void __init init_apic_mappings(void)
21342141
if (!acpi_lapic && !smp_found_config)
21352142
register_lapic_address(apic_phys);
21362143
}
2137-
2138-
/*
2139-
* Fetch the APIC ID of the BSP in case we have a
2140-
* default configuration (or the MP table is broken).
2141-
*/
2142-
new_apicid = read_apic_id();
2143-
if (boot_cpu_physical_apicid != new_apicid) {
2144-
boot_cpu_physical_apicid = new_apicid;
2145-
/*
2146-
* yeah -- we lie about apic_version
2147-
* in case if apic was disabled via boot option
2148-
* but it's not a problem for SMP compiled kernel
2149-
* since apic_intr_mode_select is prepared for such
2150-
* a case and disable smp mode
2151-
*/
2152-
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
2153-
}
21542144
}
21552145

21562146
void __init register_lapic_address(unsigned long address)
21572147
{
21582148
mp_lapic_addr = address;
21592149

2160-
if (!x2apic_mode) {
2161-
set_fixmap_nocache(FIX_APIC_BASE, address);
2162-
apic_mmio_base = APIC_BASE;
2163-
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
2164-
APIC_BASE, address);
2165-
}
2166-
if (boot_cpu_physical_apicid == -1U) {
2167-
boot_cpu_physical_apicid = read_apic_id();
2168-
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
2169-
}
2150+
if (x2apic_mode)
2151+
return;
2152+
2153+
set_fixmap_nocache(FIX_APIC_BASE, address);
2154+
apic_mmio_base = APIC_BASE;
2155+
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", APIC_BASE, address);
2156+
apic_read_boot_cpu_id(false);
21702157
}
21712158

21722159
/*
@@ -2446,31 +2433,15 @@ int generic_processor_info(int apicid, int version)
24462433
phys_cpu_present_map);
24472434

24482435
/*
2449-
* boot_cpu_physical_apicid is designed to have the apicid
2450-
* returned by read_apic_id(), i.e, the apicid of the
2451-
* currently booting-up processor. However, on some platforms,
2452-
* it is temporarily modified by the apicid reported as BSP
2453-
* through MP table. Concretely:
2454-
*
2455-
* - arch/x86/kernel/mpparse.c: MP_processor_info()
2456-
* - arch/x86/mm/amdtopology.c: amd_numa_init()
2457-
*
2458-
* This function is executed with the modified
2459-
* boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel
2460-
* parameter doesn't work to disable APs on kdump 2nd kernel.
2461-
*
2462-
* Since fixing handling of boot_cpu_physical_apicid requires
2463-
* another discussion and tests on each platform, we leave it
2464-
* for now and here we use read_apic_id() directly in this
2465-
* function, generic_processor_info().
2436+
* boot_cpu_physical_apicid is guaranteed to contain the boot CPU
2437+
* APIC ID read from the local APIC when this function is invoked.
24662438
*/
2467-
if (disabled_cpu_apicid != BAD_APICID &&
2468-
disabled_cpu_apicid != read_apic_id() &&
2439+
if (disabled_cpu_apicid != boot_cpu_physical_apicid &&
24692440
disabled_cpu_apicid == apicid) {
24702441
int thiscpu = num_processors + disabled_cpus;
24712442

2472-
pr_warn("APIC: Disabling requested cpu."
2473-
" Processor %d/0x%x ignored.\n", thiscpu, apicid);
2443+
pr_warn("APIC: Disabling requested cpu. Processor %d/0x%x ignored.\n",
2444+
thiscpu, apicid);
24742445

24752446
disabled_cpus++;
24762447
return -ENODEV;
@@ -2626,15 +2597,6 @@ static void __init apic_bsp_up_setup(void)
26262597
{
26272598
#ifdef CONFIG_X86_64
26282599
apic_write(APIC_ID, apic->set_apic_id(boot_cpu_physical_apicid));
2629-
#else
2630-
/*
2631-
* Hack: In case of kdump, after a crash, kernel might be booting
2632-
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
2633-
* might be zero if read from MP tables. Get it from LAPIC.
2634-
*/
2635-
# ifdef CONFIG_CRASH_DUMP
2636-
boot_cpu_physical_apicid = read_apic_id();
2637-
# endif
26382600
#endif
26392601
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
26402602
}

arch/x86/kernel/mpparse.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,8 @@ static void __init MP_processor_info(struct mpc_cpu *m)
5858

5959
apicid = m->apicid;
6060

61-
if (m->cpuflag & CPU_BOOTPROCESSOR) {
61+
if (m->cpuflag & CPU_BOOTPROCESSOR)
6262
bootup_cpu = " (Bootup-CPU)";
63-
boot_cpu_physical_apicid = m->apicid;
64-
}
6563

6664
pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
6765
generic_processor_info(apicid, m->apicver);

0 commit comments

Comments
 (0)