1*4882a593Smuzhiyun========================= 2*4882a593SmuzhiyunCPU hotplug in the Kernel 3*4882a593Smuzhiyun========================= 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun:Date: December, 2016 6*4882a593Smuzhiyun:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>, 7*4882a593Smuzhiyun Rusty Russell <rusty@rustcorp.com.au>, 8*4882a593Smuzhiyun Srivatsa Vaddagiri <vatsa@in.ibm.com>, 9*4882a593Smuzhiyun Ashok Raj <ashok.raj@intel.com>, 10*4882a593Smuzhiyun Joel Schopp <jschopp@austin.ibm.com> 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunIntroduction 13*4882a593Smuzhiyun============ 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunModern advances in system architectures have introduced advanced error 16*4882a593Smuzhiyunreporting and correction capabilities in processors. There are couple OEMS that 17*4882a593Smuzhiyunsupport NUMA hardware which are hot pluggable as well, where physical node 18*4882a593Smuzhiyuninsertion and removal require support for CPU hotplug. 19*4882a593Smuzhiyun 20*4882a593SmuzhiyunSuch advances require CPUs available to a kernel to be removed either for 21*4882a593Smuzhiyunprovisioning reasons, or for RAS purposes to keep an offending CPU off 22*4882a593Smuzhiyunsystem execution path. Hence the need for CPU hotplug support in the 23*4882a593SmuzhiyunLinux kernel. 24*4882a593Smuzhiyun 25*4882a593SmuzhiyunA more novel use of CPU-hotplug support is its use today in suspend resume 26*4882a593Smuzhiyunsupport for SMP. Dual-core and HT support makes even a laptop run SMP kernels 27*4882a593Smuzhiyunwhich didn't support these methods. 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunCommand Line Switches 31*4882a593Smuzhiyun===================== 32*4882a593Smuzhiyun``maxcpus=n`` 33*4882a593Smuzhiyun Restrict boot time CPUs to *n*. Say if you have four CPUs, using 34*4882a593Smuzhiyun ``maxcpus=2`` will only boot two. You can choose to bring the 35*4882a593Smuzhiyun other CPUs later online. 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun``nr_cpus=n`` 38*4882a593Smuzhiyun Restrict the total amount of CPUs the kernel will support. If the number 39*4882a593Smuzhiyun supplied here is lower than the number of physically available CPUs, then 40*4882a593Smuzhiyun those CPUs can not be brought online later. 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun``additional_cpus=n`` 43*4882a593Smuzhiyun Use this to limit hotpluggable CPUs. This option sets 44*4882a593Smuzhiyun ``cpu_possible_mask = cpu_present_mask + additional_cpus`` 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun This option is limited to the IA64 architecture. 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun``possible_cpus=n`` 49*4882a593Smuzhiyun This option sets ``possible_cpus`` bits in ``cpu_possible_mask``. 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun This option is limited to the X86 and S390 architecture. 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun``cpu0_hotplug`` 54*4882a593Smuzhiyun Allow to shutdown CPU0. 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun This option is limited to the X86 architecture. 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunCPU maps 59*4882a593Smuzhiyun======== 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun``cpu_possible_mask`` 62*4882a593Smuzhiyun Bitmap of possible CPUs that can ever be available in the 63*4882a593Smuzhiyun system. This is used to allocate some boot time memory for per_cpu variables 64*4882a593Smuzhiyun that aren't designed to grow/shrink as CPUs are made available or removed. 65*4882a593Smuzhiyun Once set during boot time discovery phase, the map is static, i.e no bits 66*4882a593Smuzhiyun are added or removed anytime. Trimming it accurately for your system needs 67*4882a593Smuzhiyun upfront can save some boot time memory. 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun``cpu_online_mask`` 70*4882a593Smuzhiyun Bitmap of all CPUs currently online. Its set in ``__cpu_up()`` 71*4882a593Smuzhiyun after a CPU is available for kernel scheduling and ready to receive 72*4882a593Smuzhiyun interrupts from devices. Its cleared when a CPU is brought down using 73*4882a593Smuzhiyun ``__cpu_disable()``, before which all OS services including interrupts are 74*4882a593Smuzhiyun migrated to another target CPU. 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun``cpu_present_mask`` 77*4882a593Smuzhiyun Bitmap of CPUs currently present in the system. Not all 78*4882a593Smuzhiyun of them may be online. When physical hotplug is processed by the relevant 79*4882a593Smuzhiyun subsystem (e.g ACPI) can change and new bit either be added or removed 80*4882a593Smuzhiyun from the map depending on the event is hot-add/hot-remove. There are currently 81*4882a593Smuzhiyun no locking rules as of now. Typical usage is to init topology during boot, 82*4882a593Smuzhiyun at which time hotplug is disabled. 83*4882a593Smuzhiyun 84*4882a593SmuzhiyunYou really don't need to manipulate any of the system CPU maps. They should 85*4882a593Smuzhiyunbe read-only for most use. When setting up per-cpu resources almost always use 86*4882a593Smuzhiyun``cpu_possible_mask`` or ``for_each_possible_cpu()`` to iterate. To macro 87*4882a593Smuzhiyun``for_each_cpu()`` can be used to iterate over a custom CPU mask. 88*4882a593Smuzhiyun 89*4882a593SmuzhiyunNever use anything other than ``cpumask_t`` to represent bitmap of CPUs. 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun 92*4882a593SmuzhiyunUsing CPU hotplug 93*4882a593Smuzhiyun================= 94*4882a593SmuzhiyunThe kernel option *CONFIG_HOTPLUG_CPU* needs to be enabled. It is currently 95*4882a593Smuzhiyunavailable on multiple architectures including ARM, MIPS, PowerPC and X86. The 96*4882a593Smuzhiyunconfiguration is done via the sysfs interface: :: 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun $ ls -lh /sys/devices/system/cpu 99*4882a593Smuzhiyun total 0 100*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu0 101*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu1 102*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu2 103*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu3 104*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu4 105*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu5 106*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu6 107*4882a593Smuzhiyun drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu7 108*4882a593Smuzhiyun drwxr-xr-x 2 root root 0 Dec 21 16:33 hotplug 109*4882a593Smuzhiyun -r--r--r-- 1 root root 4.0K Dec 21 16:33 offline 110*4882a593Smuzhiyun -r--r--r-- 1 root root 4.0K Dec 21 16:33 online 111*4882a593Smuzhiyun -r--r--r-- 1 root root 4.0K Dec 21 16:33 possible 112*4882a593Smuzhiyun -r--r--r-- 1 root root 4.0K Dec 21 16:33 present 113*4882a593Smuzhiyun 114*4882a593SmuzhiyunThe files *offline*, *online*, *possible*, *present* represent the CPU masks. 115*4882a593SmuzhiyunEach CPU folder contains an *online* file which controls the logical on (1) and 116*4882a593Smuzhiyunoff (0) state. To logically shutdown CPU4: :: 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun $ echo 0 > /sys/devices/system/cpu/cpu4/online 119*4882a593Smuzhiyun smpboot: CPU 4 is now offline 120*4882a593Smuzhiyun 121*4882a593SmuzhiyunOnce the CPU is shutdown, it will be removed from */proc/interrupts*, 122*4882a593Smuzhiyun*/proc/cpuinfo* and should also not be shown visible by the *top* command. To 123*4882a593Smuzhiyunbring CPU4 back online: :: 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun $ echo 1 > /sys/devices/system/cpu/cpu4/online 126*4882a593Smuzhiyun smpboot: Booting Node 0 Processor 4 APIC 0x1 127*4882a593Smuzhiyun 128*4882a593SmuzhiyunThe CPU is usable again. This should work on all CPUs. CPU0 is often special 129*4882a593Smuzhiyunand excluded from CPU hotplug. On X86 the kernel option 130*4882a593Smuzhiyun*CONFIG_BOOTPARAM_HOTPLUG_CPU0* has to be enabled in order to be able to 131*4882a593Smuzhiyunshutdown CPU0. Alternatively the kernel command option *cpu0_hotplug* can be 132*4882a593Smuzhiyunused. Some known dependencies of CPU0: 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun* Resume from hibernate/suspend. Hibernate/suspend will fail if CPU0 is offline. 135*4882a593Smuzhiyun* PIC interrupts. CPU0 can't be removed if a PIC interrupt is detected. 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunPlease let Fenghua Yu <fenghua.yu@intel.com> know if you find any dependencies 138*4882a593Smuzhiyunon CPU0. 139*4882a593Smuzhiyun 140*4882a593SmuzhiyunThe CPU hotplug coordination 141*4882a593Smuzhiyun============================ 142*4882a593Smuzhiyun 143*4882a593SmuzhiyunThe offline case 144*4882a593Smuzhiyun---------------- 145*4882a593SmuzhiyunOnce a CPU has been logically shutdown the teardown callbacks of registered 146*4882a593Smuzhiyunhotplug states will be invoked, starting with ``CPUHP_ONLINE`` and terminating 147*4882a593Smuzhiyunat state ``CPUHP_OFFLINE``. This includes: 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun* If tasks are frozen due to a suspend operation then *cpuhp_tasks_frozen* 150*4882a593Smuzhiyun will be set to true. 151*4882a593Smuzhiyun* All processes are migrated away from this outgoing CPU to new CPUs. 152*4882a593Smuzhiyun The new CPU is chosen from each process' current cpuset, which may be 153*4882a593Smuzhiyun a subset of all online CPUs. 154*4882a593Smuzhiyun* All interrupts targeted to this CPU are migrated to a new CPU 155*4882a593Smuzhiyun* timers are also migrated to a new CPU 156*4882a593Smuzhiyun* Once all services are migrated, kernel calls an arch specific routine 157*4882a593Smuzhiyun ``__cpu_disable()`` to perform arch specific cleanup. 158*4882a593Smuzhiyun 159*4882a593SmuzhiyunUsing the hotplug API 160*4882a593Smuzhiyun--------------------- 161*4882a593SmuzhiyunIt is possible to receive notifications once a CPU is offline or onlined. This 162*4882a593Smuzhiyunmight be important to certain drivers which need to perform some kind of setup 163*4882a593Smuzhiyunor clean up functions based on the number of available CPUs: :: 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun #include <linux/cpuhotplug.h> 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "X/Y:online", 168*4882a593Smuzhiyun Y_online, Y_prepare_down); 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun*X* is the subsystem and *Y* the particular driver. The *Y_online* callback 171*4882a593Smuzhiyunwill be invoked during registration on all online CPUs. If an error 172*4882a593Smuzhiyunoccurs during the online callback the *Y_prepare_down* callback will be 173*4882a593Smuzhiyuninvoked on all CPUs on which the online callback was previously invoked. 174*4882a593SmuzhiyunAfter registration completed, the *Y_online* callback will be invoked 175*4882a593Smuzhiyunonce a CPU is brought online and *Y_prepare_down* will be invoked when a 176*4882a593SmuzhiyunCPU is shutdown. All resources which were previously allocated in 177*4882a593Smuzhiyun*Y_online* should be released in *Y_prepare_down*. 178*4882a593SmuzhiyunThe return value *ret* is negative if an error occurred during the 179*4882a593Smuzhiyunregistration process. Otherwise a positive value is returned which 180*4882a593Smuzhiyuncontains the allocated hotplug for dynamically allocated states 181*4882a593Smuzhiyun(*CPUHP_AP_ONLINE_DYN*). It will return zero for predefined states. 182*4882a593Smuzhiyun 183*4882a593SmuzhiyunThe callback can be remove by invoking ``cpuhp_remove_state()``. In case of a 184*4882a593Smuzhiyundynamically allocated state (*CPUHP_AP_ONLINE_DYN*) use the returned state. 185*4882a593SmuzhiyunDuring the removal of a hotplug state the teardown callback will be invoked. 186*4882a593Smuzhiyun 187*4882a593SmuzhiyunMultiple instances 188*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~ 189*4882a593SmuzhiyunIf a driver has multiple instances and each instance needs to perform the 190*4882a593Smuzhiyuncallback independently then it is likely that a ''multi-state'' should be used. 191*4882a593SmuzhiyunFirst a multi-state state needs to be registered: :: 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online, 194*4882a593Smuzhiyun Y_online, Y_prepare_down); 195*4882a593Smuzhiyun Y_hp_online = ret; 196*4882a593Smuzhiyun 197*4882a593SmuzhiyunThe ``cpuhp_setup_state_multi()`` behaves similar to ``cpuhp_setup_state()`` 198*4882a593Smuzhiyunexcept it prepares the callbacks for a multi state and does not invoke 199*4882a593Smuzhiyunthe callbacks. This is a one time setup. 200*4882a593SmuzhiyunOnce a new instance is allocated, you need to register this new instance: :: 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun ret = cpuhp_state_add_instance(Y_hp_online, &d->node); 203*4882a593Smuzhiyun 204*4882a593SmuzhiyunThis function will add this instance to your previously allocated 205*4882a593Smuzhiyun*Y_hp_online* state and invoke the previously registered callback 206*4882a593Smuzhiyun(*Y_online*) on all online CPUs. The *node* element is a ``struct 207*4882a593Smuzhiyunhlist_node`` member of your per-instance data structure. 208*4882a593Smuzhiyun 209*4882a593SmuzhiyunOn removal of the instance: :: 210*4882a593Smuzhiyun cpuhp_state_remove_instance(Y_hp_online, &d->node) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyunshould be invoked which will invoke the teardown callback on all online 213*4882a593SmuzhiyunCPUs. 214*4882a593Smuzhiyun 215*4882a593SmuzhiyunManual setup 216*4882a593Smuzhiyun~~~~~~~~~~~~ 217*4882a593SmuzhiyunUsually it is handy to invoke setup and teardown callbacks on registration or 218*4882a593Smuzhiyunremoval of a state because usually the operation needs to performed once a CPU 219*4882a593Smuzhiyungoes online (offline) and during initial setup (shutdown) of the driver. However 220*4882a593Smuzhiyuneach registration and removal function is also available with a ``_nocalls`` 221*4882a593Smuzhiyunsuffix which does not invoke the provided callbacks if the invocation of the 222*4882a593Smuzhiyuncallbacks is not desired. During the manual setup (or teardown) the functions 223*4882a593Smuzhiyun``get_online_cpus()`` and ``put_online_cpus()`` should be used to inhibit CPU 224*4882a593Smuzhiyunhotplug operations. 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun 227*4882a593SmuzhiyunThe ordering of the events 228*4882a593Smuzhiyun-------------------------- 229*4882a593SmuzhiyunThe hotplug states are defined in ``include/linux/cpuhotplug.h``: 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun* The states *CPUHP_OFFLINE* … *CPUHP_AP_OFFLINE* are invoked before the 232*4882a593Smuzhiyun CPU is up. 233*4882a593Smuzhiyun* The states *CPUHP_AP_OFFLINE* … *CPUHP_AP_ONLINE* are invoked 234*4882a593Smuzhiyun just the after the CPU has been brought up. The interrupts are off and 235*4882a593Smuzhiyun the scheduler is not yet active on this CPU. Starting with *CPUHP_AP_OFFLINE* 236*4882a593Smuzhiyun the callbacks are invoked on the target CPU. 237*4882a593Smuzhiyun* The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are 238*4882a593Smuzhiyun reserved for the dynamic allocation. 239*4882a593Smuzhiyun* The states are invoked in the reverse order on CPU shutdown starting with 240*4882a593Smuzhiyun *CPUHP_ONLINE* and stopping at *CPUHP_OFFLINE*. Here the callbacks are 241*4882a593Smuzhiyun invoked on the CPU that will be shutdown until *CPUHP_AP_OFFLINE*. 242*4882a593Smuzhiyun 243*4882a593SmuzhiyunA dynamically allocated state via *CPUHP_AP_ONLINE_DYN* is often enough. 244*4882a593SmuzhiyunHowever if an earlier invocation during the bring up or shutdown is required 245*4882a593Smuzhiyunthen an explicit state should be acquired. An explicit state might also be 246*4882a593Smuzhiyunrequired if the hotplug event requires specific ordering in respect to 247*4882a593Smuzhiyunanother hotplug event. 248*4882a593Smuzhiyun 249*4882a593SmuzhiyunTesting of hotplug states 250*4882a593Smuzhiyun========================= 251*4882a593SmuzhiyunOne way to verify whether a custom state is working as expected or not is to 252*4882a593Smuzhiyunshutdown a CPU and then put it online again. It is also possible to put the CPU 253*4882a593Smuzhiyunto certain state (for instance *CPUHP_AP_ONLINE*) and then go back to 254*4882a593Smuzhiyun*CPUHP_ONLINE*. This would simulate an error one state after *CPUHP_AP_ONLINE* 255*4882a593Smuzhiyunwhich would lead to rollback to the online state. 256*4882a593Smuzhiyun 257*4882a593SmuzhiyunAll registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states``: :: 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun $ tail /sys/devices/system/cpu/hotplug/states 260*4882a593Smuzhiyun 138: mm/vmscan:online 261*4882a593Smuzhiyun 139: mm/vmstat:online 262*4882a593Smuzhiyun 140: lib/percpu_cnt:online 263*4882a593Smuzhiyun 141: acpi/cpu-drv:online 264*4882a593Smuzhiyun 142: base/cacheinfo:online 265*4882a593Smuzhiyun 143: virtio/net:online 266*4882a593Smuzhiyun 144: x86/mce:online 267*4882a593Smuzhiyun 145: printk:online 268*4882a593Smuzhiyun 168: sched:active 269*4882a593Smuzhiyun 169: online 270*4882a593Smuzhiyun 271*4882a593SmuzhiyunTo rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: :: 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun $ cat /sys/devices/system/cpu/cpu4/hotplug/state 274*4882a593Smuzhiyun 169 275*4882a593Smuzhiyun $ echo 140 > /sys/devices/system/cpu/cpu4/hotplug/target 276*4882a593Smuzhiyun $ cat /sys/devices/system/cpu/cpu4/hotplug/state 277*4882a593Smuzhiyun 140 278*4882a593Smuzhiyun 279*4882a593SmuzhiyunIt is important to note that the teardown callbac of state 140 have been 280*4882a593Smuzhiyuninvoked. And now get back online: :: 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun $ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target 283*4882a593Smuzhiyun $ cat /sys/devices/system/cpu/cpu4/hotplug/state 284*4882a593Smuzhiyun 169 285*4882a593Smuzhiyun 286*4882a593SmuzhiyunWith trace events enabled, the individual steps are visible, too: :: 287*4882a593Smuzhiyun 288*4882a593Smuzhiyun # TASK-PID CPU# TIMESTAMP FUNCTION 289*4882a593Smuzhiyun # | | | | | 290*4882a593Smuzhiyun bash-394 [001] 22.976: cpuhp_enter: cpu: 0004 target: 140 step: 169 (cpuhp_kick_ap_work) 291*4882a593Smuzhiyun cpuhp/4-31 [004] 22.977: cpuhp_enter: cpu: 0004 target: 140 step: 168 (sched_cpu_deactivate) 292*4882a593Smuzhiyun cpuhp/4-31 [004] 22.990: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0 293*4882a593Smuzhiyun cpuhp/4-31 [004] 22.991: cpuhp_enter: cpu: 0004 target: 140 step: 144 (mce_cpu_pre_down) 294*4882a593Smuzhiyun cpuhp/4-31 [004] 22.992: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0 295*4882a593Smuzhiyun cpuhp/4-31 [004] 22.993: cpuhp_multi_enter: cpu: 0004 target: 140 step: 143 (virtnet_cpu_down_prep) 296*4882a593Smuzhiyun cpuhp/4-31 [004] 22.994: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0 297*4882a593Smuzhiyun cpuhp/4-31 [004] 22.995: cpuhp_enter: cpu: 0004 target: 140 step: 142 (cacheinfo_cpu_pre_down) 298*4882a593Smuzhiyun cpuhp/4-31 [004] 22.996: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0 299*4882a593Smuzhiyun bash-394 [001] 22.997: cpuhp_exit: cpu: 0004 state: 140 step: 169 ret: 0 300*4882a593Smuzhiyun bash-394 [005] 95.540: cpuhp_enter: cpu: 0004 target: 169 step: 140 (cpuhp_kick_ap_work) 301*4882a593Smuzhiyun cpuhp/4-31 [004] 95.541: cpuhp_enter: cpu: 0004 target: 169 step: 141 (acpi_soft_cpu_online) 302*4882a593Smuzhiyun cpuhp/4-31 [004] 95.542: cpuhp_exit: cpu: 0004 state: 141 step: 141 ret: 0 303*4882a593Smuzhiyun cpuhp/4-31 [004] 95.543: cpuhp_enter: cpu: 0004 target: 169 step: 142 (cacheinfo_cpu_online) 304*4882a593Smuzhiyun cpuhp/4-31 [004] 95.544: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0 305*4882a593Smuzhiyun cpuhp/4-31 [004] 95.545: cpuhp_multi_enter: cpu: 0004 target: 169 step: 143 (virtnet_cpu_online) 306*4882a593Smuzhiyun cpuhp/4-31 [004] 95.546: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0 307*4882a593Smuzhiyun cpuhp/4-31 [004] 95.547: cpuhp_enter: cpu: 0004 target: 169 step: 144 (mce_cpu_online) 308*4882a593Smuzhiyun cpuhp/4-31 [004] 95.548: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0 309*4882a593Smuzhiyun cpuhp/4-31 [004] 95.549: cpuhp_enter: cpu: 0004 target: 169 step: 145 (console_cpu_notify) 310*4882a593Smuzhiyun cpuhp/4-31 [004] 95.550: cpuhp_exit: cpu: 0004 state: 145 step: 145 ret: 0 311*4882a593Smuzhiyun cpuhp/4-31 [004] 95.551: cpuhp_enter: cpu: 0004 target: 169 step: 168 (sched_cpu_activate) 312*4882a593Smuzhiyun cpuhp/4-31 [004] 95.552: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0 313*4882a593Smuzhiyun bash-394 [005] 95.553: cpuhp_exit: cpu: 0004 state: 169 step: 140 ret: 0 314*4882a593Smuzhiyun 315*4882a593SmuzhiyunAs it an be seen, CPU4 went down until timestamp 22.996 and then back up until 316*4882a593Smuzhiyun95.552. All invoked callbacks including their return codes are visible in the 317*4882a593Smuzhiyuntrace. 318*4882a593Smuzhiyun 319*4882a593SmuzhiyunArchitecture's requirements 320*4882a593Smuzhiyun=========================== 321*4882a593SmuzhiyunThe following functions and configurations are required: 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun``CONFIG_HOTPLUG_CPU`` 324*4882a593Smuzhiyun This entry needs to be enabled in Kconfig 325*4882a593Smuzhiyun 326*4882a593Smuzhiyun``__cpu_up()`` 327*4882a593Smuzhiyun Arch interface to bring up a CPU 328*4882a593Smuzhiyun 329*4882a593Smuzhiyun``__cpu_disable()`` 330*4882a593Smuzhiyun Arch interface to shutdown a CPU, no more interrupts can be handled by the 331*4882a593Smuzhiyun kernel after the routine returns. This includes the shutdown of the timer. 332*4882a593Smuzhiyun 333*4882a593Smuzhiyun``__cpu_die()`` 334*4882a593Smuzhiyun This actually supposed to ensure death of the CPU. Actually look at some 335*4882a593Smuzhiyun example code in other arch that implement CPU hotplug. The processor is taken 336*4882a593Smuzhiyun down from the ``idle()`` loop for that specific architecture. ``__cpu_die()`` 337*4882a593Smuzhiyun typically waits for some per_cpu state to be set, to ensure the processor dead 338*4882a593Smuzhiyun routine is called to be sure positively. 339*4882a593Smuzhiyun 340*4882a593SmuzhiyunUser Space Notification 341*4882a593Smuzhiyun======================= 342*4882a593SmuzhiyunAfter CPU successfully onlined or offline udev events are sent. A udev rule like: :: 343*4882a593Smuzhiyun 344*4882a593Smuzhiyun SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh" 345*4882a593Smuzhiyun 346*4882a593Smuzhiyunwill receive all events. A script like: :: 347*4882a593Smuzhiyun 348*4882a593Smuzhiyun #!/bin/sh 349*4882a593Smuzhiyun 350*4882a593Smuzhiyun if [ "${ACTION}" = "offline" ] 351*4882a593Smuzhiyun then 352*4882a593Smuzhiyun echo "CPU ${DEVPATH##*/} offline" 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun elif [ "${ACTION}" = "online" ] 355*4882a593Smuzhiyun then 356*4882a593Smuzhiyun echo "CPU ${DEVPATH##*/} online" 357*4882a593Smuzhiyun 358*4882a593Smuzhiyun fi 359*4882a593Smuzhiyun 360*4882a593Smuzhiyuncan process the event further. 361*4882a593Smuzhiyun 362*4882a593SmuzhiyunKernel Inline Documentations Reference 363*4882a593Smuzhiyun====================================== 364*4882a593Smuzhiyun 365*4882a593Smuzhiyun.. kernel-doc:: include/linux/cpuhotplug.h 366