Skip to content

Commit

Permalink
kernel/cpu: hack around deadlocks and cpus_online > 1 assertion
Browse files Browse the repository at this point in the history
This allows suspend and resume to work with arch_freeze_secondary_cpu
and arch_thaw_secondary_cpu as implemented by pseries in QEMU:

[   30.664951] PM: suspend entry (deep)
[   30.679085] Filesystems sync: 0.010 seconds
[   30.719020] Freezing user space processes
[   30.723635] Freezing user space processes completed (elapsed 0.004 seconds)
[   30.724256] OOM killer disabled.
[   30.724406] Freezing remaining freezable tasks
[   30.729172] Freezing remaining freezable tasks completed (elapsed 0.004 seconds)
[   30.787473] PM: suspend of devices complete after 53.129 msecs
[   30.787696] PM: start suspend of devices complete after 58.071 msecs
[   30.787881] PM: suspend devices took 0.060 seconds
[   30.799036] PM: late suspend of devices complete after 10.700 msecs
[   30.811568] PM: noirq suspend of devices complete after 8.846 msecs
[   30.814902] Disabling non-boot CPUs ...
[   30.817107] Checking wakeup interrupts
[   30.817264] Calling timekeeping_suspend+0x0/0x410
[   30.819336] Calling mpic_suspend+0x0/0x170
[   30.819508] Calling fw_suspend+0x0/0x30
[   30.819649] PM: suspend debug: Waiting for 5 second(s).
[   30.825653] premature return from H_JOIN on CPU 6, retrying
[   30.825684] premature return from H_JOIN on CPU 2, retrying
[   30.825700] premature return from H_JOIN on CPU 5, retrying
[   30.825710] premature return from H_JOIN on CPU 7, retrying
[   30.825723] premature return from H_JOIN on CPU 3, retrying
[   30.825744] premature return from H_JOIN on CPU 4, retrying
[   30.825752] premature return from H_JOIN on CPU 1, retrying
[   30.826057] premature return from H_JOIN on CPU 5, retrying
[   30.826081] premature return from H_JOIN on CPU 4, retrying
[   30.826084] premature return from H_JOIN on CPU 1, retrying
[   35.820159] Calling mpic_resume+0x0/0x160
[   35.820575] Calling irq_pm_syscore_resume+0x0/0x20
[   35.826136] Calling timekeeping_resume+0x0/0x2b0
[   35.827634] Timekeeping suspended for 5.287 seconds
[   35.829584] Enabling non-boot CPUs ...
[   35.830133] CPU1 is up
[   35.830324] CPU2 is up
[   35.830440] CPU3 is up
[   35.830544] CPU4 is up
[   35.830647] CPU5 is up
[   35.830752] CPU6 is up
[   35.830860] CPU7 is up
[   35.837837] PM: noirq resume of devices complete after 5.709 msecs
[   35.844871] PM: early resume of devices complete after 4.853 msecs
[   35.851745] PM: resume of devices complete after 6.692 msecs
[   35.855215] PM: resume devices took 0.010 seconds
[   35.858200] OOM killer enabled.
[   35.858312] Restarting tasks ... done.
[   35.864429] random: crng reseeded on system resumption
[   35.865776] PM: suspend exit

Also verified on a real P8 LPAR. Tracing suspend_resume events shows
the difference in time taken to bring up CPUs on resume:

Before:
  bash-2387  [009]   234.063755: (+2)     suspend_resume:       CPU_ON[88] begin
  bash-2387  [009]   234.071351: (+7596)  suspend_resume:       CPU_ON[88] end
  bash-2387  [009]   234.071353: (+2)     suspend_resume:       CPU_ON[89] begin
  bash-2387  [009]   234.078726: (+7373)  suspend_resume:       CPU_ON[89] end
  bash-2387  [009]   234.078727: (+1)     suspend_resume:       CPU_ON[90] begin
  bash-2387  [009]   234.086230: (+7503)  suspend_resume:       CPU_ON[90] end
  bash-2387  [009]   234.086232: (+2)     suspend_resume:       CPU_ON[91] begin
  bash-2387  [009]   234.093798: (+7566)  suspend_resume:       CPU_ON[91] end
  bash-2387  [009]   234.093800: (+2)     suspend_resume:       CPU_ON[92] begin
  bash-2387  [009]   234.101398: (+7598)  suspend_resume:       CPU_ON[92] end
  bash-2387  [009]   234.101400: (+2)     suspend_resume:       CPU_ON[93] begin
  bash-2387  [009]   234.108746: (+7346)  suspend_resume:       CPU_ON[93] end
  bash-2387  [009]   234.108748: (+2)     suspend_resume:       CPU_ON[94] begin
  bash-2387  [009]   234.116060: (+7312)  suspend_resume:       CPU_ON[94] end
  bash-2387  [009]   234.116062: (+2)     suspend_resume:       CPU_ON[95] begin
  bash-2387  [009]   234.123455: (+7393)  suspend_resume:       CPU_ON[95] end

After:
  bash-2163  [000]  1710.118645: (+5)     suspend_resume:       CPU_ON[88] begin
  bash-2163  [000]  1710.118650: (+5)     suspend_resume:       CPU_ON[88] end
  bash-2163  [000]  1710.118654: (+4)     suspend_resume:       CPU_ON[89] begin
  bash-2163  [000]  1710.118657: (+3)     suspend_resume:       CPU_ON[89] end
  bash-2163  [000]  1710.118662: (+5)     suspend_resume:       CPU_ON[90] begin
  bash-2163  [000]  1710.118666: (+4)     suspend_resume:       CPU_ON[90] end
  bash-2163  [000]  1710.118670: (+4)     suspend_resume:       CPU_ON[91] begin
  bash-2163  [000]  1710.118674: (+4)     suspend_resume:       CPU_ON[91] end
  bash-2163  [000]  1710.118678: (+4)     suspend_resume:       CPU_ON[92] begin
  bash-2163  [000]  1710.118683: (+5)     suspend_resume:       CPU_ON[92] end
  bash-2163  [000]  1710.118687: (+4)     suspend_resume:       CPU_ON[93] begin
  bash-2163  [000]  1710.118691: (+4)     suspend_resume:       CPU_ON[93] end
  bash-2163  [000]  1710.118696: (+5)     suspend_resume:       CPU_ON[94] begin
  bash-2163  [000]  1710.118699: (+3)     suspend_resume:       CPU_ON[94] end
  bash-2163  [000]  1710.118704: (+5)     suspend_resume:       CPU_ON[95] begin
  bash-2163  [000]  1710.118707: (+3)     suspend_resume:       CPU_ON[95] end

Signed-off-by: Nathan Lynch <[email protected]>
  • Loading branch information
nathanlynch committed Oct 12, 2023
1 parent 40bdd0d commit 995b79f
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,12 @@ int freeze_secondary_cpus(int primary)
primary = cpumask_first(cpu_online_mask);
}

/*
* We're potentially going to IPI and synchronize with the
* other CPUs, ensure we're running on the primary.
*/
set_cpus_allowed_ptr(current, cpumask_of(primary));

/*
* We take down all of the non-boot CPUs in one shot to avoid races
* with the userspace trying to use the CPU hotplug at the same time
Expand Down Expand Up @@ -1957,9 +1963,7 @@ int freeze_secondary_cpus(int primary)
}
}

if (!error)
BUG_ON(num_online_cpus() > 1);
else
if (error)
pr_err("Non-boot CPUs are not disabled\n");

/*
Expand Down Expand Up @@ -2018,6 +2022,9 @@ void thaw_secondary_cpus(void)

cpumask_clear(frozen_cpus);
out:
// FIXME this should be properly saved and restored in
// cooperation w/freeze_secondary_cpus()
set_cpus_allowed_ptr(current, cpu_online_mask);
cpu_maps_update_done();
}

Expand Down

0 comments on commit 995b79f

Please sign in to comment.