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