Skip to content

Commit 5475abb

Browse files
KAGA-KOKOPeter Zijlstra
authored andcommitted
x86/smpboot: Remove the CPU0 hotplug kludge
This was introduced with commit e1c467e ("x86, hotplug: Wake up CPU0 via NMI instead of INIT, SIPI, SIPI") to eventually support physical hotplug of CPU0: "We'll change this code in the future to wake up hard offlined CPU0 if real platform and request are available." 11 years later this has not happened and physical hotplug is not officially supported. Remove the cruft. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Michael Kelley <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Tested-by: Helge Deller <[email protected]> # parisc Tested-by: Guilherme G. Piccoli <[email protected]> # Steam Deck Link: https://lore.kernel.org/r/[email protected]
1 parent e59e74d commit 5475abb

File tree

4 files changed

+13
-161
lines changed

4 files changed

+13
-161
lines changed

arch/x86/include/asm/apic.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,6 @@ extern struct apic *__apicdrivers[], *__apicdrivers_end[];
377377
* APIC functionality to boot other CPUs - only used on SMP:
378378
*/
379379
#ifdef CONFIG_SMP
380-
extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip);
381380
extern int lapic_can_unplug_cpu(void);
382381
#endif
383382

arch/x86/include/asm/smp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ void native_play_dead(void);
130130
void play_dead_common(void);
131131
void wbinvd_on_cpu(int cpu);
132132
int wbinvd_on_all_cpus(void);
133-
void cond_wakeup_cpu0(void);
134133

135134
void native_smp_send_reschedule(int cpu);
136135
void native_send_call_func_ipi(const struct cpumask *mask);

arch/x86/kernel/smpboot.c

Lines changed: 13 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,6 @@ static void ap_calibrate_delay(void)
216216
cpu_data(smp_processor_id()).loops_per_jiffy = loops_per_jiffy;
217217
}
218218

219-
static int cpu0_logical_apicid;
220-
static int enable_start_cpu0;
221-
222219
/*
223220
* Activate a secondary processor.
224221
*/
@@ -241,8 +238,6 @@ static void notrace start_secondary(void *unused)
241238
x86_cpuinit.early_percpu_clock_init();
242239
smp_callin();
243240

244-
enable_start_cpu0 = 0;
245-
246241
/* otherwise gcc will move up smp_processor_id before the cpu_init */
247242
barrier();
248243
/* Check TSC synchronization with the control CPU: */
@@ -410,7 +405,7 @@ void smp_store_cpu_info(int id)
410405
c->cpu_index = id;
411406
/*
412407
* During boot time, CPU0 has this setup already. Save the info when
413-
* bringing up AP or offlined CPU0.
408+
* bringing up an AP.
414409
*/
415410
identify_secondary_cpu(c);
416411
c->initialized = true;
@@ -807,51 +802,14 @@ static void __init smp_quirk_init_udelay(void)
807802
}
808803

809804
/*
810-
* Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
811-
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
812-
* won't ... remember to clear down the APIC, etc later.
805+
* Wake up AP by INIT, INIT, STARTUP sequence.
813806
*/
814-
int
815-
wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip)
816-
{
817-
u32 dm = apic->dest_mode_logical ? APIC_DEST_LOGICAL : APIC_DEST_PHYSICAL;
818-
unsigned long send_status, accept_status = 0;
819-
int maxlvt;
820-
821-
/* Target chip */
822-
/* Boot on the stack */
823-
/* Kick the second */
824-
apic_icr_write(APIC_DM_NMI | dm, apicid);
825-
826-
pr_debug("Waiting for send to finish...\n");
827-
send_status = safe_apic_wait_icr_idle();
828-
829-
/*
830-
* Give the other CPU some time to accept the IPI.
831-
*/
832-
udelay(200);
833-
if (APIC_INTEGRATED(boot_cpu_apic_version)) {
834-
maxlvt = lapic_get_maxlvt();
835-
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
836-
apic_write(APIC_ESR, 0);
837-
accept_status = (apic_read(APIC_ESR) & 0xEF);
838-
}
839-
pr_debug("NMI sent\n");
840-
841-
if (send_status)
842-
pr_err("APIC never delivered???\n");
843-
if (accept_status)
844-
pr_err("APIC delivery error (%lx)\n", accept_status);
845-
846-
return (send_status | accept_status);
847-
}
848-
849-
static int
850-
wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
807+
static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
851808
{
852809
unsigned long send_status = 0, accept_status = 0;
853810
int maxlvt, num_starts, j;
854811

812+
preempt_disable();
855813
maxlvt = lapic_get_maxlvt();
856814

857815
/*
@@ -957,6 +915,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
957915
if (accept_status)
958916
pr_err("APIC delivery error (%lx)\n", accept_status);
959917

918+
preempt_enable();
960919
return (send_status | accept_status);
961920
}
962921

@@ -997,67 +956,6 @@ static void announce_cpu(int cpu, int apicid)
997956
node, cpu, apicid);
998957
}
999958

1000-
static int wakeup_cpu0_nmi(unsigned int cmd, struct pt_regs *regs)
1001-
{
1002-
int cpu;
1003-
1004-
cpu = smp_processor_id();
1005-
if (cpu == 0 && !cpu_online(cpu) && enable_start_cpu0)
1006-
return NMI_HANDLED;
1007-
1008-
return NMI_DONE;
1009-
}
1010-
1011-
/*
1012-
* Wake up AP by INIT, INIT, STARTUP sequence.
1013-
*
1014-
* Instead of waiting for STARTUP after INITs, BSP will execute the BIOS
1015-
* boot-strap code which is not a desired behavior for waking up BSP. To
1016-
* void the boot-strap code, wake up CPU0 by NMI instead.
1017-
*
1018-
* This works to wake up soft offlined CPU0 only. If CPU0 is hard offlined
1019-
* (i.e. physically hot removed and then hot added), NMI won't wake it up.
1020-
* We'll change this code in the future to wake up hard offlined CPU0 if
1021-
* real platform and request are available.
1022-
*/
1023-
static int
1024-
wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid,
1025-
int *cpu0_nmi_registered)
1026-
{
1027-
int id;
1028-
int boot_error;
1029-
1030-
preempt_disable();
1031-
1032-
/*
1033-
* Wake up AP by INIT, INIT, STARTUP sequence.
1034-
*/
1035-
if (cpu) {
1036-
boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip);
1037-
goto out;
1038-
}
1039-
1040-
/*
1041-
* Wake up BSP by nmi.
1042-
*
1043-
* Register a NMI handler to help wake up CPU0.
1044-
*/
1045-
boot_error = register_nmi_handler(NMI_LOCAL,
1046-
wakeup_cpu0_nmi, 0, "wake_cpu0");
1047-
1048-
if (!boot_error) {
1049-
enable_start_cpu0 = 1;
1050-
*cpu0_nmi_registered = 1;
1051-
id = apic->dest_mode_logical ? cpu0_logical_apicid : apicid;
1052-
boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip);
1053-
}
1054-
1055-
out:
1056-
preempt_enable();
1057-
1058-
return boot_error;
1059-
}
1060-
1061959
int common_cpu_up(unsigned int cpu, struct task_struct *idle)
1062960
{
1063961
int ret;
@@ -1086,8 +984,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
1086984
* Returns zero if CPU booted OK, else error code from
1087985
* ->wakeup_secondary_cpu.
1088986
*/
1089-
static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
1090-
int *cpu0_nmi_registered)
987+
static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
1091988
{
1092989
/* start_ip had better be page-aligned! */
1093990
unsigned long start_ip = real_mode_header->trampoline_start;
@@ -1120,7 +1017,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
11201017
* This grunge runs the startup process for
11211018
* the targeted processor.
11221019
*/
1123-
11241020
if (x86_platform.legacy.warm_reset) {
11251021

11261022
pr_debug("Setting warm reset code and vector.\n");
@@ -1149,15 +1045,14 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
11491045
* - Use a method from the APIC driver if one defined, with wakeup
11501046
* straight to 64-bit mode preferred over wakeup to RM.
11511047
* Otherwise,
1152-
* - Use an INIT boot APIC message for APs or NMI for BSP.
1048+
* - Use an INIT boot APIC message
11531049
*/
11541050
if (apic->wakeup_secondary_cpu_64)
11551051
boot_error = apic->wakeup_secondary_cpu_64(apicid, start_ip);
11561052
else if (apic->wakeup_secondary_cpu)
11571053
boot_error = apic->wakeup_secondary_cpu(apicid, start_ip);
11581054
else
1159-
boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
1160-
cpu0_nmi_registered);
1055+
boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip);
11611056

11621057
if (!boot_error) {
11631058
/*
@@ -1206,9 +1101,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
12061101
int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
12071102
{
12081103
int apicid = apic->cpu_present_to_apicid(cpu);
1209-
int cpu0_nmi_registered = 0;
12101104
unsigned long flags;
1211-
int err, ret = 0;
1105+
int err;
12121106

12131107
lockdep_assert_irqs_enabled();
12141108

@@ -1247,11 +1141,10 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
12471141
if (err)
12481142
return err;
12491143

1250-
err = do_boot_cpu(apicid, cpu, tidle, &cpu0_nmi_registered);
1144+
err = do_boot_cpu(apicid, cpu, tidle);
12511145
if (err) {
12521146
pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
1253-
ret = -EIO;
1254-
goto unreg_nmi;
1147+
return err;
12551148
}
12561149

12571150
/*
@@ -1267,15 +1160,7 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
12671160
touch_nmi_watchdog();
12681161
}
12691162

1270-
unreg_nmi:
1271-
/*
1272-
* Clean up the nmi handler. Do this after the callin and callout sync
1273-
* to avoid impact of possible long unregister time.
1274-
*/
1275-
if (cpu0_nmi_registered)
1276-
unregister_nmi_handler(NMI_LOCAL, "wake_cpu0");
1277-
1278-
return ret;
1163+
return 0;
12791164
}
12801165

12811166
/**
@@ -1373,14 +1258,6 @@ static void __init smp_cpu_index_default(void)
13731258
}
13741259
}
13751260

1376-
static void __init smp_get_logical_apicid(void)
1377-
{
1378-
if (x2apic_mode)
1379-
cpu0_logical_apicid = apic_read(APIC_LDR);
1380-
else
1381-
cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
1382-
}
1383-
13841261
void __init smp_prepare_cpus_common(void)
13851262
{
13861263
unsigned int i;
@@ -1443,8 +1320,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
14431320
/* Setup local timer */
14441321
x86_init.timers.setup_percpu_clockev();
14451322

1446-
smp_get_logical_apicid();
1447-
14481323
pr_info("CPU0: ");
14491324
print_cpu_info(&cpu_data(0));
14501325

@@ -1752,18 +1627,6 @@ void play_dead_common(void)
17521627
local_irq_disable();
17531628
}
17541629

1755-
/**
1756-
* cond_wakeup_cpu0 - Wake up CPU0 if needed.
1757-
*
1758-
* If NMI wants to wake up CPU0, start CPU0.
1759-
*/
1760-
void cond_wakeup_cpu0(void)
1761-
{
1762-
if (smp_processor_id() == 0 && enable_start_cpu0)
1763-
start_cpu0();
1764-
}
1765-
EXPORT_SYMBOL_GPL(cond_wakeup_cpu0);
1766-
17671630
/*
17681631
* We need to flush the caches before going to sleep, lest we have
17691632
* dirty data in our caches when we come back up.
@@ -1831,8 +1694,6 @@ static inline void mwait_play_dead(void)
18311694
__monitor(mwait_ptr, 0, 0);
18321695
mb();
18331696
__mwait(eax, 0);
1834-
1835-
cond_wakeup_cpu0();
18361697
}
18371698
}
18381699

@@ -1841,11 +1702,8 @@ void __noreturn hlt_play_dead(void)
18411702
if (__this_cpu_read(cpu_info.x86) >= 4)
18421703
wbinvd();
18431704

1844-
while (1) {
1705+
while (1)
18451706
native_halt();
1846-
1847-
cond_wakeup_cpu0();
1848-
}
18491707
}
18501708

18511709
void native_play_dead(void)

drivers/acpi/processor_idle.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,10 +597,6 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
597597
io_idle(cx->address);
598598
} else
599599
return -ENODEV;
600-
601-
#if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU)
602-
cond_wakeup_cpu0();
603-
#endif
604600
}
605601

606602
/* Never reached */

0 commit comments

Comments
 (0)