Loading Documentation/cpu-hotplug.txt +45 −0 Original line number Diff line number Diff line Loading @@ -312,12 +312,57 @@ things will happen if a notifier in path sent a BAD notify code. Q: I don't see my action being called for all CPUs already up and running? A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined. If you need to perform some action for each cpu already in the system, then do this: for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } However, if you want to register a hotplug callback, as well as perform some initialization for CPUs that are already online, then do this: Version 1: (Correct) --------- cpu_notifier_register_begin(); for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } /* Note the use of the double underscored version of the API */ __register_cpu_notifier(&foobar_cpu_notifier); cpu_notifier_register_done(); Note that the following code is *NOT* the right way to achieve this, because it is prone to an ABBA deadlock between the cpu_add_remove_lock and the cpu_hotplug.lock. Version 2: (Wrong!) --------- get_online_cpus(); for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } register_cpu_notifier(&foobar_cpu_notifier); put_online_cpus(); So always use the first version shown above when you want to register callbacks as well as initialize the already online CPUs. Q: If i would like to develop cpu hotplug support for a new architecture, what do i need at a minimum? A: The following are what is required for CPU hotplug infrastructure to work Loading arch/arm/kernel/hw_breakpoint.c +7 −1 Original line number Diff line number Diff line Loading @@ -1094,6 +1094,8 @@ static int __init arch_hw_breakpoint_init(void) core_num_brps = get_num_brps(); core_num_wrps = get_num_wrps(); cpu_notifier_register_begin(); /* * We need to tread carefully here because DBGSWENABLE may be * driven low on this core and there isn't an architected way to Loading @@ -1110,6 +1112,7 @@ static int __init arch_hw_breakpoint_init(void) if (!cpumask_empty(&debug_err_mask)) { core_num_brps = 0; core_num_wrps = 0; cpu_notifier_register_done(); return 0; } Loading @@ -1129,7 +1132,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "breakpoint debug exception"); /* Register hotplug and PM notifiers. */ register_cpu_notifier(&dbg_reset_nb); __register_cpu_notifier(&dbg_reset_nb); cpu_notifier_register_done(); pm_init(); return 0; } Loading arch/arm64/kernel/debug-monitors.c +5 −1 Original line number Diff line number Diff line Loading @@ -155,12 +155,16 @@ static struct notifier_block __cpuinitdata os_lock_nb = { static int __cpuinit debug_monitors_init(void) { cpu_notifier_register_begin(); /* Clear the OS lock. */ smp_call_function(clear_os_lock, NULL, 1); clear_os_lock(NULL); /* Register hotplug handler. */ register_cpu_notifier(&os_lock_nb); __register_cpu_notifier(&os_lock_nb); cpu_notifier_register_done(); return 0; } postcore_initcall(debug_monitors_init); Loading arch/arm64/kernel/hw_breakpoint.c +6 −1 Original line number Diff line number Diff line Loading @@ -913,6 +913,8 @@ static int __init arch_hw_breakpoint_init(void) pr_info("found %d breakpoint and %d watchpoint registers.\n", core_num_brps, core_num_wrps); cpu_notifier_register_begin(); /* * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. Loading @@ -927,7 +929,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "hw-watchpoint handler"); /* Register hotplug notifier. */ register_cpu_notifier(&hw_breakpoint_reset_nb); __register_cpu_notifier(&hw_breakpoint_reset_nb); cpu_notifier_register_done(); /* Register cpu_suspend hw breakpoint restore hook */ cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); Loading drivers/base/topology.c +8 −4 Original line number Diff line number Diff line Loading @@ -181,16 +181,20 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, static int __cpuinit topology_sysfs_init(void) { int cpu; int rc; int rc = 0; cpu_notifier_register_begin(); for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); if (rc) return rc; goto out; } hotcpu_notifier(topology_cpu_callback, 0); __hotcpu_notifier(topology_cpu_callback, 0); return 0; out: cpu_notifier_register_done(); return rc; } device_initcall(topology_sysfs_init); Loading
Documentation/cpu-hotplug.txt +45 −0 Original line number Diff line number Diff line Loading @@ -312,12 +312,57 @@ things will happen if a notifier in path sent a BAD notify code. Q: I don't see my action being called for all CPUs already up and running? A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined. If you need to perform some action for each cpu already in the system, then do this: for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } However, if you want to register a hotplug callback, as well as perform some initialization for CPUs that are already online, then do this: Version 1: (Correct) --------- cpu_notifier_register_begin(); for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } /* Note the use of the double underscored version of the API */ __register_cpu_notifier(&foobar_cpu_notifier); cpu_notifier_register_done(); Note that the following code is *NOT* the right way to achieve this, because it is prone to an ABBA deadlock between the cpu_add_remove_lock and the cpu_hotplug.lock. Version 2: (Wrong!) --------- get_online_cpus(); for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); } register_cpu_notifier(&foobar_cpu_notifier); put_online_cpus(); So always use the first version shown above when you want to register callbacks as well as initialize the already online CPUs. Q: If i would like to develop cpu hotplug support for a new architecture, what do i need at a minimum? A: The following are what is required for CPU hotplug infrastructure to work Loading
arch/arm/kernel/hw_breakpoint.c +7 −1 Original line number Diff line number Diff line Loading @@ -1094,6 +1094,8 @@ static int __init arch_hw_breakpoint_init(void) core_num_brps = get_num_brps(); core_num_wrps = get_num_wrps(); cpu_notifier_register_begin(); /* * We need to tread carefully here because DBGSWENABLE may be * driven low on this core and there isn't an architected way to Loading @@ -1110,6 +1112,7 @@ static int __init arch_hw_breakpoint_init(void) if (!cpumask_empty(&debug_err_mask)) { core_num_brps = 0; core_num_wrps = 0; cpu_notifier_register_done(); return 0; } Loading @@ -1129,7 +1132,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "breakpoint debug exception"); /* Register hotplug and PM notifiers. */ register_cpu_notifier(&dbg_reset_nb); __register_cpu_notifier(&dbg_reset_nb); cpu_notifier_register_done(); pm_init(); return 0; } Loading
arch/arm64/kernel/debug-monitors.c +5 −1 Original line number Diff line number Diff line Loading @@ -155,12 +155,16 @@ static struct notifier_block __cpuinitdata os_lock_nb = { static int __cpuinit debug_monitors_init(void) { cpu_notifier_register_begin(); /* Clear the OS lock. */ smp_call_function(clear_os_lock, NULL, 1); clear_os_lock(NULL); /* Register hotplug handler. */ register_cpu_notifier(&os_lock_nb); __register_cpu_notifier(&os_lock_nb); cpu_notifier_register_done(); return 0; } postcore_initcall(debug_monitors_init); Loading
arch/arm64/kernel/hw_breakpoint.c +6 −1 Original line number Diff line number Diff line Loading @@ -913,6 +913,8 @@ static int __init arch_hw_breakpoint_init(void) pr_info("found %d breakpoint and %d watchpoint registers.\n", core_num_brps, core_num_wrps); cpu_notifier_register_begin(); /* * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. Loading @@ -927,7 +929,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "hw-watchpoint handler"); /* Register hotplug notifier. */ register_cpu_notifier(&hw_breakpoint_reset_nb); __register_cpu_notifier(&hw_breakpoint_reset_nb); cpu_notifier_register_done(); /* Register cpu_suspend hw breakpoint restore hook */ cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); Loading
drivers/base/topology.c +8 −4 Original line number Diff line number Diff line Loading @@ -181,16 +181,20 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, static int __cpuinit topology_sysfs_init(void) { int cpu; int rc; int rc = 0; cpu_notifier_register_begin(); for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); if (rc) return rc; goto out; } hotcpu_notifier(topology_cpu_callback, 0); __hotcpu_notifier(topology_cpu_callback, 0); return 0; out: cpu_notifier_register_done(); return rc; } device_initcall(topology_sysfs_init);