162306a36Sopenharmony_ci=========================
262306a36Sopenharmony_ciCPU hotplug in the Kernel
362306a36Sopenharmony_ci=========================
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci:Date: September, 2021
662306a36Sopenharmony_ci:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
762306a36Sopenharmony_ci         Rusty Russell <rusty@rustcorp.com.au>,
862306a36Sopenharmony_ci         Srivatsa Vaddagiri <vatsa@in.ibm.com>,
962306a36Sopenharmony_ci         Ashok Raj <ashok.raj@intel.com>,
1062306a36Sopenharmony_ci         Joel Schopp <jschopp@austin.ibm.com>,
1162306a36Sopenharmony_ci	 Thomas Gleixner <tglx@linutronix.de>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ciIntroduction
1462306a36Sopenharmony_ci============
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciModern advances in system architectures have introduced advanced error
1762306a36Sopenharmony_cireporting and correction capabilities in processors. There are couple OEMS that
1862306a36Sopenharmony_cisupport NUMA hardware which are hot pluggable as well, where physical node
1962306a36Sopenharmony_ciinsertion and removal require support for CPU hotplug.
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciSuch advances require CPUs available to a kernel to be removed either for
2262306a36Sopenharmony_ciprovisioning reasons, or for RAS purposes to keep an offending CPU off
2362306a36Sopenharmony_cisystem execution path. Hence the need for CPU hotplug support in the
2462306a36Sopenharmony_ciLinux kernel.
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciA more novel use of CPU-hotplug support is its use today in suspend resume
2762306a36Sopenharmony_cisupport for SMP. Dual-core and HT support makes even a laptop run SMP kernels
2862306a36Sopenharmony_ciwhich didn't support these methods.
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciCommand Line Switches
3262306a36Sopenharmony_ci=====================
3362306a36Sopenharmony_ci``maxcpus=n``
3462306a36Sopenharmony_ci  Restrict boot time CPUs to *n*. Say if you have four CPUs, using
3562306a36Sopenharmony_ci  ``maxcpus=2`` will only boot two. You can choose to bring the
3662306a36Sopenharmony_ci  other CPUs later online.
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci``nr_cpus=n``
3962306a36Sopenharmony_ci  Restrict the total amount of CPUs the kernel will support. If the number
4062306a36Sopenharmony_ci  supplied here is lower than the number of physically available CPUs, then
4162306a36Sopenharmony_ci  those CPUs can not be brought online later.
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci``additional_cpus=n``
4462306a36Sopenharmony_ci  Use this to limit hotpluggable CPUs. This option sets
4562306a36Sopenharmony_ci  ``cpu_possible_mask = cpu_present_mask + additional_cpus``
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci  This option is limited to the IA64 architecture.
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci``possible_cpus=n``
5062306a36Sopenharmony_ci  This option sets ``possible_cpus`` bits in ``cpu_possible_mask``.
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci  This option is limited to the X86 and S390 architecture.
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci``cpu0_hotplug``
5562306a36Sopenharmony_ci  Allow to shutdown CPU0.
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci  This option is limited to the X86 architecture.
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciCPU maps
6062306a36Sopenharmony_ci========
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci``cpu_possible_mask``
6362306a36Sopenharmony_ci  Bitmap of possible CPUs that can ever be available in the
6462306a36Sopenharmony_ci  system. This is used to allocate some boot time memory for per_cpu variables
6562306a36Sopenharmony_ci  that aren't designed to grow/shrink as CPUs are made available or removed.
6662306a36Sopenharmony_ci  Once set during boot time discovery phase, the map is static, i.e no bits
6762306a36Sopenharmony_ci  are added or removed anytime. Trimming it accurately for your system needs
6862306a36Sopenharmony_ci  upfront can save some boot time memory.
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci``cpu_online_mask``
7162306a36Sopenharmony_ci  Bitmap of all CPUs currently online. Its set in ``__cpu_up()``
7262306a36Sopenharmony_ci  after a CPU is available for kernel scheduling and ready to receive
7362306a36Sopenharmony_ci  interrupts from devices. Its cleared when a CPU is brought down using
7462306a36Sopenharmony_ci  ``__cpu_disable()``, before which all OS services including interrupts are
7562306a36Sopenharmony_ci  migrated to another target CPU.
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci``cpu_present_mask``
7862306a36Sopenharmony_ci  Bitmap of CPUs currently present in the system. Not all
7962306a36Sopenharmony_ci  of them may be online. When physical hotplug is processed by the relevant
8062306a36Sopenharmony_ci  subsystem (e.g ACPI) can change and new bit either be added or removed
8162306a36Sopenharmony_ci  from the map depending on the event is hot-add/hot-remove. There are currently
8262306a36Sopenharmony_ci  no locking rules as of now. Typical usage is to init topology during boot,
8362306a36Sopenharmony_ci  at which time hotplug is disabled.
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciYou really don't need to manipulate any of the system CPU maps. They should
8662306a36Sopenharmony_cibe read-only for most use. When setting up per-cpu resources almost always use
8762306a36Sopenharmony_ci``cpu_possible_mask`` or ``for_each_possible_cpu()`` to iterate. To macro
8862306a36Sopenharmony_ci``for_each_cpu()`` can be used to iterate over a custom CPU mask.
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciNever use anything other than ``cpumask_t`` to represent bitmap of CPUs.
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciUsing CPU hotplug
9462306a36Sopenharmony_ci=================
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciThe kernel option *CONFIG_HOTPLUG_CPU* needs to be enabled. It is currently
9762306a36Sopenharmony_ciavailable on multiple architectures including ARM, MIPS, PowerPC and X86. The
9862306a36Sopenharmony_ciconfiguration is done via the sysfs interface::
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci $ ls -lh /sys/devices/system/cpu
10162306a36Sopenharmony_ci total 0
10262306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu0
10362306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu1
10462306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu2
10562306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu3
10662306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu4
10762306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu5
10862306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu6
10962306a36Sopenharmony_ci drwxr-xr-x  9 root root    0 Dec 21 16:33 cpu7
11062306a36Sopenharmony_ci drwxr-xr-x  2 root root    0 Dec 21 16:33 hotplug
11162306a36Sopenharmony_ci -r--r--r--  1 root root 4.0K Dec 21 16:33 offline
11262306a36Sopenharmony_ci -r--r--r--  1 root root 4.0K Dec 21 16:33 online
11362306a36Sopenharmony_ci -r--r--r--  1 root root 4.0K Dec 21 16:33 possible
11462306a36Sopenharmony_ci -r--r--r--  1 root root 4.0K Dec 21 16:33 present
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciThe files *offline*, *online*, *possible*, *present* represent the CPU masks.
11762306a36Sopenharmony_ciEach CPU folder contains an *online* file which controls the logical on (1) and
11862306a36Sopenharmony_cioff (0) state. To logically shutdown CPU4::
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci $ echo 0 > /sys/devices/system/cpu/cpu4/online
12162306a36Sopenharmony_ci  smpboot: CPU 4 is now offline
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciOnce the CPU is shutdown, it will be removed from */proc/interrupts*,
12462306a36Sopenharmony_ci*/proc/cpuinfo* and should also not be shown visible by the *top* command. To
12562306a36Sopenharmony_cibring CPU4 back online::
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci $ echo 1 > /sys/devices/system/cpu/cpu4/online
12862306a36Sopenharmony_ci smpboot: Booting Node 0 Processor 4 APIC 0x1
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciThe CPU is usable again. This should work on all CPUs, but CPU0 is often special
13162306a36Sopenharmony_ciand excluded from CPU hotplug.
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ciThe CPU hotplug coordination
13462306a36Sopenharmony_ci============================
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciThe offline case
13762306a36Sopenharmony_ci----------------
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ciOnce a CPU has been logically shutdown the teardown callbacks of registered
14062306a36Sopenharmony_cihotplug states will be invoked, starting with ``CPUHP_ONLINE`` and terminating
14162306a36Sopenharmony_ciat state ``CPUHP_OFFLINE``. This includes:
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci* If tasks are frozen due to a suspend operation then *cpuhp_tasks_frozen*
14462306a36Sopenharmony_ci  will be set to true.
14562306a36Sopenharmony_ci* All processes are migrated away from this outgoing CPU to new CPUs.
14662306a36Sopenharmony_ci  The new CPU is chosen from each process' current cpuset, which may be
14762306a36Sopenharmony_ci  a subset of all online CPUs.
14862306a36Sopenharmony_ci* All interrupts targeted to this CPU are migrated to a new CPU
14962306a36Sopenharmony_ci* timers are also migrated to a new CPU
15062306a36Sopenharmony_ci* Once all services are migrated, kernel calls an arch specific routine
15162306a36Sopenharmony_ci  ``__cpu_disable()`` to perform arch specific cleanup.
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ciThe CPU hotplug API
15562306a36Sopenharmony_ci===================
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciCPU hotplug state machine
15862306a36Sopenharmony_ci-------------------------
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ciCPU hotplug uses a trivial state machine with a linear state space from
16162306a36Sopenharmony_ciCPUHP_OFFLINE to CPUHP_ONLINE. Each state has a startup and a teardown
16262306a36Sopenharmony_cicallback.
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ciWhen a CPU is onlined, the startup callbacks are invoked sequentially until
16562306a36Sopenharmony_cithe state CPUHP_ONLINE is reached. They can also be invoked when the
16662306a36Sopenharmony_cicallbacks of a state are set up or an instance is added to a multi-instance
16762306a36Sopenharmony_cistate.
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ciWhen a CPU is offlined the teardown callbacks are invoked in the reverse
17062306a36Sopenharmony_ciorder sequentially until the state CPUHP_OFFLINE is reached. They can also
17162306a36Sopenharmony_cibe invoked when the callbacks of a state are removed or an instance is
17262306a36Sopenharmony_ciremoved from a multi-instance state.
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ciIf a usage site requires only a callback in one direction of the hotplug
17562306a36Sopenharmony_cioperations (CPU online or CPU offline) then the other not-required callback
17662306a36Sopenharmony_cican be set to NULL when the state is set up.
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ciThe state space is divided into three sections:
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci* The PREPARE section
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci  The PREPARE section covers the state space from CPUHP_OFFLINE to
18362306a36Sopenharmony_ci  CPUHP_BRINGUP_CPU.
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci  The startup callbacks in this section are invoked before the CPU is
18662306a36Sopenharmony_ci  started during a CPU online operation. The teardown callbacks are invoked
18762306a36Sopenharmony_ci  after the CPU has become dysfunctional during a CPU offline operation.
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci  The callbacks are invoked on a control CPU as they can't obviously run on
19062306a36Sopenharmony_ci  the hotplugged CPU which is either not yet started or has become
19162306a36Sopenharmony_ci  dysfunctional already.
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci  The startup callbacks are used to setup resources which are required to
19462306a36Sopenharmony_ci  bring a CPU successfully online. The teardown callbacks are used to free
19562306a36Sopenharmony_ci  resources or to move pending work to an online CPU after the hotplugged
19662306a36Sopenharmony_ci  CPU became dysfunctional.
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci  The startup callbacks are allowed to fail. If a callback fails, the CPU
19962306a36Sopenharmony_ci  online operation is aborted and the CPU is brought down to the previous
20062306a36Sopenharmony_ci  state (usually CPUHP_OFFLINE) again.
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci  The teardown callbacks in this section are not allowed to fail.
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci* The STARTING section
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci  The STARTING section covers the state space between CPUHP_BRINGUP_CPU + 1
20762306a36Sopenharmony_ci  and CPUHP_AP_ONLINE.
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci  The startup callbacks in this section are invoked on the hotplugged CPU
21062306a36Sopenharmony_ci  with interrupts disabled during a CPU online operation in the early CPU
21162306a36Sopenharmony_ci  setup code. The teardown callbacks are invoked with interrupts disabled
21262306a36Sopenharmony_ci  on the hotplugged CPU during a CPU offline operation shortly before the
21362306a36Sopenharmony_ci  CPU is completely shut down.
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci  The callbacks in this section are not allowed to fail.
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci  The callbacks are used for low level hardware initialization/shutdown and
21862306a36Sopenharmony_ci  for core subsystems.
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci* The ONLINE section
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci  The ONLINE section covers the state space between CPUHP_AP_ONLINE + 1 and
22362306a36Sopenharmony_ci  CPUHP_ONLINE.
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci  The startup callbacks in this section are invoked on the hotplugged CPU
22662306a36Sopenharmony_ci  during a CPU online operation. The teardown callbacks are invoked on the
22762306a36Sopenharmony_ci  hotplugged CPU during a CPU offline operation.
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci  The callbacks are invoked in the context of the per CPU hotplug thread,
23062306a36Sopenharmony_ci  which is pinned on the hotplugged CPU. The callbacks are invoked with
23162306a36Sopenharmony_ci  interrupts and preemption enabled.
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci  The callbacks are allowed to fail. When a callback fails the hotplug
23462306a36Sopenharmony_ci  operation is aborted and the CPU is brought back to the previous state.
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ciCPU online/offline operations
23762306a36Sopenharmony_ci-----------------------------
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciA successful online operation looks like this::
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci  [CPUHP_OFFLINE]
24262306a36Sopenharmony_ci  [CPUHP_OFFLINE + 1]->startup()       -> success
24362306a36Sopenharmony_ci  [CPUHP_OFFLINE + 2]->startup()       -> success
24462306a36Sopenharmony_ci  [CPUHP_OFFLINE + 3]                  -> skipped because startup == NULL
24562306a36Sopenharmony_ci  ...
24662306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU]->startup()       -> success
24762306a36Sopenharmony_ci  === End of PREPARE section
24862306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU + 1]->startup()   -> success
24962306a36Sopenharmony_ci  ...
25062306a36Sopenharmony_ci  [CPUHP_AP_ONLINE]->startup()         -> success
25162306a36Sopenharmony_ci  === End of STARTUP section
25262306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + 1]->startup()     -> success
25362306a36Sopenharmony_ci  ...
25462306a36Sopenharmony_ci  [CPUHP_ONLINE - 1]->startup()        -> success
25562306a36Sopenharmony_ci  [CPUHP_ONLINE]
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ciA successful offline operation looks like this::
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci  [CPUHP_ONLINE]
26062306a36Sopenharmony_ci  [CPUHP_ONLINE - 1]->teardown()       -> success
26162306a36Sopenharmony_ci  ...
26262306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + 1]->teardown()    -> success
26362306a36Sopenharmony_ci  === Start of STARTUP section
26462306a36Sopenharmony_ci  [CPUHP_AP_ONLINE]->teardown()        -> success
26562306a36Sopenharmony_ci  ...
26662306a36Sopenharmony_ci  [CPUHP_BRINGUP_ONLINE - 1]->teardown()
26762306a36Sopenharmony_ci  ...
26862306a36Sopenharmony_ci  === Start of PREPARE section
26962306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU]->teardown()
27062306a36Sopenharmony_ci  [CPUHP_OFFLINE + 3]->teardown()
27162306a36Sopenharmony_ci  [CPUHP_OFFLINE + 2]                  -> skipped because teardown == NULL
27262306a36Sopenharmony_ci  [CPUHP_OFFLINE + 1]->teardown()
27362306a36Sopenharmony_ci  [CPUHP_OFFLINE]
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ciA failed online operation looks like this::
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci  [CPUHP_OFFLINE]
27862306a36Sopenharmony_ci  [CPUHP_OFFLINE + 1]->startup()       -> success
27962306a36Sopenharmony_ci  [CPUHP_OFFLINE + 2]->startup()       -> success
28062306a36Sopenharmony_ci  [CPUHP_OFFLINE + 3]                  -> skipped because startup == NULL
28162306a36Sopenharmony_ci  ...
28262306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU]->startup()       -> success
28362306a36Sopenharmony_ci  === End of PREPARE section
28462306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU + 1]->startup()   -> success
28562306a36Sopenharmony_ci  ...
28662306a36Sopenharmony_ci  [CPUHP_AP_ONLINE]->startup()         -> success
28762306a36Sopenharmony_ci  === End of STARTUP section
28862306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + 1]->startup()     -> success
28962306a36Sopenharmony_ci  ---
29062306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + N]->startup()     -> fail
29162306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + (N - 1)]->teardown()
29262306a36Sopenharmony_ci  ...
29362306a36Sopenharmony_ci  [CPUHP_AP_ONLINE + 1]->teardown()
29462306a36Sopenharmony_ci  === Start of STARTUP section
29562306a36Sopenharmony_ci  [CPUHP_AP_ONLINE]->teardown()
29662306a36Sopenharmony_ci  ...
29762306a36Sopenharmony_ci  [CPUHP_BRINGUP_ONLINE - 1]->teardown()
29862306a36Sopenharmony_ci  ...
29962306a36Sopenharmony_ci  === Start of PREPARE section
30062306a36Sopenharmony_ci  [CPUHP_BRINGUP_CPU]->teardown()
30162306a36Sopenharmony_ci  [CPUHP_OFFLINE + 3]->teardown()
30262306a36Sopenharmony_ci  [CPUHP_OFFLINE + 2]                  -> skipped because teardown == NULL
30362306a36Sopenharmony_ci  [CPUHP_OFFLINE + 1]->teardown()
30462306a36Sopenharmony_ci  [CPUHP_OFFLINE]
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ciA failed offline operation looks like this::
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci  [CPUHP_ONLINE]
30962306a36Sopenharmony_ci  [CPUHP_ONLINE - 1]->teardown()       -> success
31062306a36Sopenharmony_ci  ...
31162306a36Sopenharmony_ci  [CPUHP_ONLINE - N]->teardown()       -> fail
31262306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]->startup()
31362306a36Sopenharmony_ci  ...
31462306a36Sopenharmony_ci  [CPUHP_ONLINE - 1]->startup()
31562306a36Sopenharmony_ci  [CPUHP_ONLINE]
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ciRecursive failures cannot be handled sensibly. Look at the following
31862306a36Sopenharmony_ciexample of a recursive fail due to a failed offline operation: ::
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci  [CPUHP_ONLINE]
32162306a36Sopenharmony_ci  [CPUHP_ONLINE - 1]->teardown()       -> success
32262306a36Sopenharmony_ci  ...
32362306a36Sopenharmony_ci  [CPUHP_ONLINE - N]->teardown()       -> fail
32462306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]->startup()  -> success
32562306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 2)]->startup()  -> fail
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ciThe CPU hotplug state machine stops right here and does not try to go back
32862306a36Sopenharmony_cidown again because that would likely result in an endless loop::
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]->teardown() -> success
33162306a36Sopenharmony_ci  [CPUHP_ONLINE - N]->teardown()       -> fail
33262306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]->startup()  -> success
33362306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 2)]->startup()  -> fail
33462306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]->teardown() -> success
33562306a36Sopenharmony_ci  [CPUHP_ONLINE - N]->teardown()       -> fail
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ciLather, rinse and repeat. In this case the CPU left in state::
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci  [CPUHP_ONLINE - (N - 1)]
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ciwhich at least lets the system make progress and gives the user a chance to
34262306a36Sopenharmony_cidebug or even resolve the situation.
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ciAllocating a state
34562306a36Sopenharmony_ci------------------
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ciThere are two ways to allocate a CPU hotplug state:
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci* Static allocation
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci  Static allocation has to be used when the subsystem or driver has
35262306a36Sopenharmony_ci  ordering requirements versus other CPU hotplug states. E.g. the PERF core
35362306a36Sopenharmony_ci  startup callback has to be invoked before the PERF driver startup
35462306a36Sopenharmony_ci  callbacks during a CPU online operation. During a CPU offline operation
35562306a36Sopenharmony_ci  the driver teardown callbacks have to be invoked before the core teardown
35662306a36Sopenharmony_ci  callback. The statically allocated states are described by constants in
35762306a36Sopenharmony_ci  the cpuhp_state enum which can be found in include/linux/cpuhotplug.h.
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci  Insert the state into the enum at the proper place so the ordering
36062306a36Sopenharmony_ci  requirements are fulfilled. The state constant has to be used for state
36162306a36Sopenharmony_ci  setup and removal.
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci  Static allocation is also required when the state callbacks are not set
36462306a36Sopenharmony_ci  up at runtime and are part of the initializer of the CPU hotplug state
36562306a36Sopenharmony_ci  array in kernel/cpu.c.
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci* Dynamic allocation
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci  When there are no ordering requirements for the state callbacks then
37062306a36Sopenharmony_ci  dynamic allocation is the preferred method. The state number is allocated
37162306a36Sopenharmony_ci  by the setup function and returned to the caller on success.
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci  Only the PREPARE and ONLINE sections provide a dynamic allocation
37462306a36Sopenharmony_ci  range. The STARTING section does not as most of the callbacks in that
37562306a36Sopenharmony_ci  section have explicit ordering requirements.
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ciSetup of a CPU hotplug state
37862306a36Sopenharmony_ci----------------------------
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ciThe core code provides the following functions to setup a state:
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci* cpuhp_setup_state(state, name, startup, teardown)
38362306a36Sopenharmony_ci* cpuhp_setup_state_nocalls(state, name, startup, teardown)
38462306a36Sopenharmony_ci* cpuhp_setup_state_cpuslocked(state, name, startup, teardown)
38562306a36Sopenharmony_ci* cpuhp_setup_state_nocalls_cpuslocked(state, name, startup, teardown)
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ciFor cases where a driver or a subsystem has multiple instances and the same
38862306a36Sopenharmony_ciCPU hotplug state callbacks need to be invoked for each instance, the CPU
38962306a36Sopenharmony_cihotplug core provides multi-instance support. The advantage over driver
39062306a36Sopenharmony_cispecific instance lists is that the instance related functions are fully
39162306a36Sopenharmony_ciserialized against CPU hotplug operations and provide the automatic
39262306a36Sopenharmony_ciinvocations of the state callbacks on add and removal. To set up such a
39362306a36Sopenharmony_cimulti-instance state the following function is available:
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci* cpuhp_setup_state_multi(state, name, startup, teardown)
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ciThe @state argument is either a statically allocated state or one of the
39862306a36Sopenharmony_ciconstants for dynamically allocated states - CPUHP_BP_PREPARE_DYN,
39962306a36Sopenharmony_ciCPUHP_AP_ONLINE_DYN - depending on the state section (PREPARE, ONLINE) for
40062306a36Sopenharmony_ciwhich a dynamic state should be allocated.
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ciThe @name argument is used for sysfs output and for instrumentation. The
40362306a36Sopenharmony_cinaming convention is "subsys:mode" or "subsys/driver:mode",
40462306a36Sopenharmony_cie.g. "perf:mode" or "perf/x86:mode". The common mode names are:
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci======== =======================================================
40762306a36Sopenharmony_ciprepare  For states in the PREPARE section
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cidead     For states in the PREPARE section which do not provide
41062306a36Sopenharmony_ci         a startup callback
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistarting For states in the STARTING section
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cidying    For states in the STARTING section which do not provide
41562306a36Sopenharmony_ci         a startup callback
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cionline   For states in the ONLINE section
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_cioffline  For states in the ONLINE section which do not provide
42062306a36Sopenharmony_ci         a startup callback
42162306a36Sopenharmony_ci======== =======================================================
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ciAs the @name argument is only used for sysfs and instrumentation other mode
42462306a36Sopenharmony_cidescriptors can be used as well if they describe the nature of the state
42562306a36Sopenharmony_cibetter than the common ones.
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ciExamples for @name arguments: "perf/online", "perf/x86:prepare",
42862306a36Sopenharmony_ci"RCU/tree:dying", "sched/waitempty"
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ciThe @startup argument is a function pointer to the callback which should be
43162306a36Sopenharmony_ciinvoked during a CPU online operation. If the usage site does not require a
43262306a36Sopenharmony_cistartup callback set the pointer to NULL.
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ciThe @teardown argument is a function pointer to the callback which should
43562306a36Sopenharmony_cibe invoked during a CPU offline operation. If the usage site does not
43662306a36Sopenharmony_cirequire a teardown callback set the pointer to NULL.
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ciThe functions differ in the way how the installed callbacks are treated:
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci  * cpuhp_setup_state_nocalls(), cpuhp_setup_state_nocalls_cpuslocked()
44162306a36Sopenharmony_ci    and cpuhp_setup_state_multi() only install the callbacks
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci  * cpuhp_setup_state() and cpuhp_setup_state_cpuslocked() install the
44462306a36Sopenharmony_ci    callbacks and invoke the @startup callback (if not NULL) for all online
44562306a36Sopenharmony_ci    CPUs which have currently a state greater than the newly installed
44662306a36Sopenharmony_ci    state. Depending on the state section the callback is either invoked on
44762306a36Sopenharmony_ci    the current CPU (PREPARE section) or on each online CPU (ONLINE
44862306a36Sopenharmony_ci    section) in the context of the CPU's hotplug thread.
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci    If a callback fails for CPU N then the teardown callback for CPU
45162306a36Sopenharmony_ci    0 .. N-1 is invoked to rollback the operation. The state setup fails,
45262306a36Sopenharmony_ci    the callbacks for the state are not installed and in case of dynamic
45362306a36Sopenharmony_ci    allocation the allocated state is freed.
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ciThe state setup and the callback invocations are serialized against CPU
45662306a36Sopenharmony_cihotplug operations. If the setup function has to be called from a CPU
45762306a36Sopenharmony_cihotplug read locked region, then the _cpuslocked() variants have to be
45862306a36Sopenharmony_ciused. These functions cannot be used from within CPU hotplug callbacks.
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ciThe function return values:
46162306a36Sopenharmony_ci  ======== ===================================================================
46262306a36Sopenharmony_ci  0        Statically allocated state was successfully set up
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci  >0       Dynamically allocated state was successfully set up.
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci           The returned number is the state number which was allocated. If
46762306a36Sopenharmony_ci           the state callbacks have to be removed later, e.g. module
46862306a36Sopenharmony_ci           removal, then this number has to be saved by the caller and used
46962306a36Sopenharmony_ci           as @state argument for the state remove function. For
47062306a36Sopenharmony_ci           multi-instance states the dynamically allocated state number is
47162306a36Sopenharmony_ci           also required as @state argument for the instance add/remove
47262306a36Sopenharmony_ci           operations.
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci  <0	   Operation failed
47562306a36Sopenharmony_ci  ======== ===================================================================
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ciRemoval of a CPU hotplug state
47862306a36Sopenharmony_ci------------------------------
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ciTo remove a previously set up state, the following functions are provided:
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci* cpuhp_remove_state(state)
48362306a36Sopenharmony_ci* cpuhp_remove_state_nocalls(state)
48462306a36Sopenharmony_ci* cpuhp_remove_state_nocalls_cpuslocked(state)
48562306a36Sopenharmony_ci* cpuhp_remove_multi_state(state)
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ciThe @state argument is either a statically allocated state or the state
48862306a36Sopenharmony_cinumber which was allocated in the dynamic range by cpuhp_setup_state*(). If
48962306a36Sopenharmony_cithe state is in the dynamic range, then the state number is freed and
49062306a36Sopenharmony_ciavailable for dynamic allocation again.
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ciThe functions differ in the way how the installed callbacks are treated:
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci  * cpuhp_remove_state_nocalls(), cpuhp_remove_state_nocalls_cpuslocked()
49562306a36Sopenharmony_ci    and cpuhp_remove_multi_state() only remove the callbacks.
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci  * cpuhp_remove_state() removes the callbacks and invokes the teardown
49862306a36Sopenharmony_ci    callback (if not NULL) for all online CPUs which have currently a state
49962306a36Sopenharmony_ci    greater than the removed state. Depending on the state section the
50062306a36Sopenharmony_ci    callback is either invoked on the current CPU (PREPARE section) or on
50162306a36Sopenharmony_ci    each online CPU (ONLINE section) in the context of the CPU's hotplug
50262306a36Sopenharmony_ci    thread.
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci    In order to complete the removal, the teardown callback should not fail.
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ciThe state removal and the callback invocations are serialized against CPU
50762306a36Sopenharmony_cihotplug operations. If the remove function has to be called from a CPU
50862306a36Sopenharmony_cihotplug read locked region, then the _cpuslocked() variants have to be
50962306a36Sopenharmony_ciused. These functions cannot be used from within CPU hotplug callbacks.
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ciIf a multi-instance state is removed then the caller has to remove all
51262306a36Sopenharmony_ciinstances first.
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ciMulti-Instance state instance management
51562306a36Sopenharmony_ci----------------------------------------
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ciOnce the multi-instance state is set up, instances can be added to the
51862306a36Sopenharmony_cistate:
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci  * cpuhp_state_add_instance(state, node)
52162306a36Sopenharmony_ci  * cpuhp_state_add_instance_nocalls(state, node)
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ciThe @state argument is either a statically allocated state or the state
52462306a36Sopenharmony_cinumber which was allocated in the dynamic range by cpuhp_setup_state_multi().
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ciThe @node argument is a pointer to an hlist_node which is embedded in the
52762306a36Sopenharmony_ciinstance's data structure. The pointer is handed to the multi-instance
52862306a36Sopenharmony_cistate callbacks and can be used by the callback to retrieve the instance
52962306a36Sopenharmony_civia container_of().
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ciThe functions differ in the way how the installed callbacks are treated:
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci  * cpuhp_state_add_instance_nocalls() and only adds the instance to the
53462306a36Sopenharmony_ci    multi-instance state's node list.
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci  * cpuhp_state_add_instance() adds the instance and invokes the startup
53762306a36Sopenharmony_ci    callback (if not NULL) associated with @state for all online CPUs which
53862306a36Sopenharmony_ci    have currently a state greater than @state. The callback is only
53962306a36Sopenharmony_ci    invoked for the to be added instance. Depending on the state section
54062306a36Sopenharmony_ci    the callback is either invoked on the current CPU (PREPARE section) or
54162306a36Sopenharmony_ci    on each online CPU (ONLINE section) in the context of the CPU's hotplug
54262306a36Sopenharmony_ci    thread.
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci    If a callback fails for CPU N then the teardown callback for CPU
54562306a36Sopenharmony_ci    0 .. N-1 is invoked to rollback the operation, the function fails and
54662306a36Sopenharmony_ci    the instance is not added to the node list of the multi-instance state.
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ciTo remove an instance from the state's node list these functions are
54962306a36Sopenharmony_ciavailable:
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci  * cpuhp_state_remove_instance(state, node)
55262306a36Sopenharmony_ci  * cpuhp_state_remove_instance_nocalls(state, node)
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ciThe arguments are the same as for the cpuhp_state_add_instance*()
55562306a36Sopenharmony_civariants above.
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ciThe functions differ in the way how the installed callbacks are treated:
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci  * cpuhp_state_remove_instance_nocalls() only removes the instance from the
56062306a36Sopenharmony_ci    state's node list.
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci  * cpuhp_state_remove_instance() removes the instance and invokes the
56362306a36Sopenharmony_ci    teardown callback (if not NULL) associated with @state for all online
56462306a36Sopenharmony_ci    CPUs which have currently a state greater than @state.  The callback is
56562306a36Sopenharmony_ci    only invoked for the to be removed instance.  Depending on the state
56662306a36Sopenharmony_ci    section the callback is either invoked on the current CPU (PREPARE
56762306a36Sopenharmony_ci    section) or on each online CPU (ONLINE section) in the context of the
56862306a36Sopenharmony_ci    CPU's hotplug thread.
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci    In order to complete the removal, the teardown callback should not fail.
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ciThe node list add/remove operations and the callback invocations are
57362306a36Sopenharmony_ciserialized against CPU hotplug operations. These functions cannot be used
57462306a36Sopenharmony_cifrom within CPU hotplug callbacks and CPU hotplug read locked regions.
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ciExamples
57762306a36Sopenharmony_ci--------
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ciSetup and teardown a statically allocated state in the STARTING section for
58062306a36Sopenharmony_cinotifications on online and offline operations::
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci   ret = cpuhp_setup_state(CPUHP_SUBSYS_STARTING, "subsys:starting", subsys_cpu_starting, subsys_cpu_dying);
58362306a36Sopenharmony_ci   if (ret < 0)
58462306a36Sopenharmony_ci        return ret;
58562306a36Sopenharmony_ci   ....
58662306a36Sopenharmony_ci   cpuhp_remove_state(CPUHP_SUBSYS_STARTING);
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ciSetup and teardown a dynamically allocated state in the ONLINE section
58962306a36Sopenharmony_cifor notifications on offline operations::
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci   state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "subsys:offline", NULL, subsys_cpu_offline);
59262306a36Sopenharmony_ci   if (state < 0)
59362306a36Sopenharmony_ci       return state;
59462306a36Sopenharmony_ci   ....
59562306a36Sopenharmony_ci   cpuhp_remove_state(state);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ciSetup and teardown a dynamically allocated state in the ONLINE section
59862306a36Sopenharmony_cifor notifications on online operations without invoking the callbacks::
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci   state = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "subsys:online", subsys_cpu_online, NULL);
60162306a36Sopenharmony_ci   if (state < 0)
60262306a36Sopenharmony_ci       return state;
60362306a36Sopenharmony_ci   ....
60462306a36Sopenharmony_ci   cpuhp_remove_state_nocalls(state);
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ciSetup, use and teardown a dynamically allocated multi-instance state in the
60762306a36Sopenharmony_ciONLINE section for notifications on online and offline operation::
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci   state = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "subsys:online", subsys_cpu_online, subsys_cpu_offline);
61062306a36Sopenharmony_ci   if (state < 0)
61162306a36Sopenharmony_ci       return state;
61262306a36Sopenharmony_ci   ....
61362306a36Sopenharmony_ci   ret = cpuhp_state_add_instance(state, &inst1->node);
61462306a36Sopenharmony_ci   if (ret)
61562306a36Sopenharmony_ci        return ret;
61662306a36Sopenharmony_ci   ....
61762306a36Sopenharmony_ci   ret = cpuhp_state_add_instance(state, &inst2->node);
61862306a36Sopenharmony_ci   if (ret)
61962306a36Sopenharmony_ci        return ret;
62062306a36Sopenharmony_ci   ....
62162306a36Sopenharmony_ci   cpuhp_remove_instance(state, &inst1->node);
62262306a36Sopenharmony_ci   ....
62362306a36Sopenharmony_ci   cpuhp_remove_instance(state, &inst2->node);
62462306a36Sopenharmony_ci   ....
62562306a36Sopenharmony_ci   remove_multi_state(state);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ciTesting of hotplug states
62962306a36Sopenharmony_ci=========================
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ciOne way to verify whether a custom state is working as expected or not is to
63262306a36Sopenharmony_cishutdown a CPU and then put it online again. It is also possible to put the CPU
63362306a36Sopenharmony_cito certain state (for instance *CPUHP_AP_ONLINE*) and then go back to
63462306a36Sopenharmony_ci*CPUHP_ONLINE*. This would simulate an error one state after *CPUHP_AP_ONLINE*
63562306a36Sopenharmony_ciwhich would lead to rollback to the online state.
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ciAll registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states`` ::
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci $ tail /sys/devices/system/cpu/hotplug/states
64062306a36Sopenharmony_ci 138: mm/vmscan:online
64162306a36Sopenharmony_ci 139: mm/vmstat:online
64262306a36Sopenharmony_ci 140: lib/percpu_cnt:online
64362306a36Sopenharmony_ci 141: acpi/cpu-drv:online
64462306a36Sopenharmony_ci 142: base/cacheinfo:online
64562306a36Sopenharmony_ci 143: virtio/net:online
64662306a36Sopenharmony_ci 144: x86/mce:online
64762306a36Sopenharmony_ci 145: printk:online
64862306a36Sopenharmony_ci 168: sched:active
64962306a36Sopenharmony_ci 169: online
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ciTo rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue::
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci  $ cat /sys/devices/system/cpu/cpu4/hotplug/state
65462306a36Sopenharmony_ci  169
65562306a36Sopenharmony_ci  $ echo 140 > /sys/devices/system/cpu/cpu4/hotplug/target
65662306a36Sopenharmony_ci  $ cat /sys/devices/system/cpu/cpu4/hotplug/state
65762306a36Sopenharmony_ci  140
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ciIt is important to note that the teardown callback of state 140 have been
66062306a36Sopenharmony_ciinvoked. And now get back online::
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci  $ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
66362306a36Sopenharmony_ci  $ cat /sys/devices/system/cpu/cpu4/hotplug/state
66462306a36Sopenharmony_ci  169
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ciWith trace events enabled, the individual steps are visible, too::
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci  #  TASK-PID   CPU#    TIMESTAMP  FUNCTION
66962306a36Sopenharmony_ci  #     | |       |        |         |
67062306a36Sopenharmony_ci      bash-394  [001]  22.976: cpuhp_enter: cpu: 0004 target: 140 step: 169 (cpuhp_kick_ap_work)
67162306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.977: cpuhp_enter: cpu: 0004 target: 140 step: 168 (sched_cpu_deactivate)
67262306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.990: cpuhp_exit:  cpu: 0004  state: 168 step: 168 ret: 0
67362306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.991: cpuhp_enter: cpu: 0004 target: 140 step: 144 (mce_cpu_pre_down)
67462306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.992: cpuhp_exit:  cpu: 0004  state: 144 step: 144 ret: 0
67562306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.993: cpuhp_multi_enter: cpu: 0004 target: 140 step: 143 (virtnet_cpu_down_prep)
67662306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.994: cpuhp_exit:  cpu: 0004  state: 143 step: 143 ret: 0
67762306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.995: cpuhp_enter: cpu: 0004 target: 140 step: 142 (cacheinfo_cpu_pre_down)
67862306a36Sopenharmony_ci   cpuhp/4-31   [004]  22.996: cpuhp_exit:  cpu: 0004  state: 142 step: 142 ret: 0
67962306a36Sopenharmony_ci      bash-394  [001]  22.997: cpuhp_exit:  cpu: 0004  state: 140 step: 169 ret: 0
68062306a36Sopenharmony_ci      bash-394  [005]  95.540: cpuhp_enter: cpu: 0004 target: 169 step: 140 (cpuhp_kick_ap_work)
68162306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.541: cpuhp_enter: cpu: 0004 target: 169 step: 141 (acpi_soft_cpu_online)
68262306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.542: cpuhp_exit:  cpu: 0004  state: 141 step: 141 ret: 0
68362306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.543: cpuhp_enter: cpu: 0004 target: 169 step: 142 (cacheinfo_cpu_online)
68462306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.544: cpuhp_exit:  cpu: 0004  state: 142 step: 142 ret: 0
68562306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.545: cpuhp_multi_enter: cpu: 0004 target: 169 step: 143 (virtnet_cpu_online)
68662306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.546: cpuhp_exit:  cpu: 0004  state: 143 step: 143 ret: 0
68762306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.547: cpuhp_enter: cpu: 0004 target: 169 step: 144 (mce_cpu_online)
68862306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.548: cpuhp_exit:  cpu: 0004  state: 144 step: 144 ret: 0
68962306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.549: cpuhp_enter: cpu: 0004 target: 169 step: 145 (console_cpu_notify)
69062306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.550: cpuhp_exit:  cpu: 0004  state: 145 step: 145 ret: 0
69162306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.551: cpuhp_enter: cpu: 0004 target: 169 step: 168 (sched_cpu_activate)
69262306a36Sopenharmony_ci   cpuhp/4-31   [004]  95.552: cpuhp_exit:  cpu: 0004  state: 168 step: 168 ret: 0
69362306a36Sopenharmony_ci      bash-394  [005]  95.553: cpuhp_exit:  cpu: 0004  state: 169 step: 140 ret: 0
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ciAs it an be seen, CPU4 went down until timestamp 22.996 and then back up until
69662306a36Sopenharmony_ci95.552. All invoked callbacks including their return codes are visible in the
69762306a36Sopenharmony_citrace.
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ciArchitecture's requirements
70062306a36Sopenharmony_ci===========================
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ciThe following functions and configurations are required:
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci``CONFIG_HOTPLUG_CPU``
70562306a36Sopenharmony_ci  This entry needs to be enabled in Kconfig
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci``__cpu_up()``
70862306a36Sopenharmony_ci  Arch interface to bring up a CPU
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci``__cpu_disable()``
71162306a36Sopenharmony_ci  Arch interface to shutdown a CPU, no more interrupts can be handled by the
71262306a36Sopenharmony_ci  kernel after the routine returns. This includes the shutdown of the timer.
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci``__cpu_die()``
71562306a36Sopenharmony_ci  This actually supposed to ensure death of the CPU. Actually look at some
71662306a36Sopenharmony_ci  example code in other arch that implement CPU hotplug. The processor is taken
71762306a36Sopenharmony_ci  down from the ``idle()`` loop for that specific architecture. ``__cpu_die()``
71862306a36Sopenharmony_ci  typically waits for some per_cpu state to be set, to ensure the processor dead
71962306a36Sopenharmony_ci  routine is called to be sure positively.
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ciUser Space Notification
72262306a36Sopenharmony_ci=======================
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ciAfter CPU successfully onlined or offline udev events are sent. A udev rule like::
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci  SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ciwill receive all events. A script like::
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci  #!/bin/sh
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci  if [ "${ACTION}" = "offline" ]
73362306a36Sopenharmony_ci  then
73462306a36Sopenharmony_ci      echo "CPU ${DEVPATH##*/} offline"
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci  elif [ "${ACTION}" = "online" ]
73762306a36Sopenharmony_ci  then
73862306a36Sopenharmony_ci      echo "CPU ${DEVPATH##*/} online"
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci  fi
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_cican process the event further.
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ciWhen changes to the CPUs in the system occur, the sysfs file
74562306a36Sopenharmony_ci/sys/devices/system/cpu/crash_hotplug contains '1' if the kernel
74662306a36Sopenharmony_ciupdates the kdump capture kernel list of CPUs itself (via elfcorehdr),
74762306a36Sopenharmony_cior '0' if userspace must update the kdump capture kernel list of CPUs.
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ciThe availability depends on the CONFIG_HOTPLUG_CPU kernel configuration
75062306a36Sopenharmony_cioption.
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ciTo skip userspace processing of CPU hot un/plug events for kdump
75362306a36Sopenharmony_ci(i.e. the unload-then-reload to obtain a current list of CPUs), this sysfs
75462306a36Sopenharmony_cifile can be used in a udev rule as follows:
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci SUBSYSTEM=="cpu", ATTRS{crash_hotplug}=="1", GOTO="kdump_reload_end"
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ciFor a CPU hot un/plug event, if the architecture supports kernel updates
75962306a36Sopenharmony_ciof the elfcorehdr (which contains the list of CPUs), then the rule skips
76062306a36Sopenharmony_cithe unload-then-reload of the kdump capture kernel.
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ciKernel Inline Documentations Reference
76362306a36Sopenharmony_ci======================================
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci.. kernel-doc:: include/linux/cpuhotplug.h
766