Loading Documentation/cpu-hotplug.txt +45 −0 Original line number Original line 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? 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. 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 If you need to perform some action for each cpu already in the system, then do this: for_each_online_cpu(i) { for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, 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, Q: If i would like to develop cpu hotplug support for a new architecture, what do i need at a minimum? what do i need at a minimum? A: The following are what is required for CPU hotplug infrastructure to work 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 Original line 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_brps = get_num_brps(); core_num_wrps = get_num_wrps(); core_num_wrps = get_num_wrps(); cpu_notifier_register_begin(); /* /* * We need to tread carefully here because DBGSWENABLE may be * We need to tread carefully here because DBGSWENABLE may be * driven low on this core and there isn't an architected way to * 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)) { if (!cpumask_empty(&debug_err_mask)) { core_num_brps = 0; core_num_brps = 0; core_num_wrps = 0; core_num_wrps = 0; cpu_notifier_register_done(); return 0; return 0; } } Loading @@ -1129,7 +1132,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "breakpoint debug exception"); TRAP_HWBKPT, "breakpoint debug exception"); /* Register hotplug and PM notifiers. */ /* Register hotplug and PM notifiers. */ register_cpu_notifier(&dbg_reset_nb); __register_cpu_notifier(&dbg_reset_nb); cpu_notifier_register_done(); pm_init(); pm_init(); return 0; return 0; } } Loading arch/arm64/kernel/debug-monitors.c +5 −1 Original line number Original line 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) static int __cpuinit debug_monitors_init(void) { { cpu_notifier_register_begin(); /* Clear the OS lock. */ /* Clear the OS lock. */ smp_call_function(clear_os_lock, NULL, 1); smp_call_function(clear_os_lock, NULL, 1); clear_os_lock(NULL); clear_os_lock(NULL); /* Register hotplug handler. */ /* Register hotplug handler. */ register_cpu_notifier(&os_lock_nb); __register_cpu_notifier(&os_lock_nb); cpu_notifier_register_done(); return 0; return 0; } } postcore_initcall(debug_monitors_init); postcore_initcall(debug_monitors_init); Loading arch/arm64/kernel/hw_breakpoint.c +6 −1 Original line number Original line 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", pr_info("found %d breakpoint and %d watchpoint registers.\n", core_num_brps, core_num_wrps); core_num_brps, core_num_wrps); cpu_notifier_register_begin(); /* /* * Reset the breakpoint resources. We assume that a halting * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. * 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"); TRAP_HWBKPT, "hw-watchpoint handler"); /* Register hotplug notifier. */ /* 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 */ /* Register cpu_suspend hw breakpoint restore hook */ cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); Loading drivers/base/topology.c +8 −4 Original line number Original line 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) static int __cpuinit topology_sysfs_init(void) { { int cpu; int cpu; int rc; int rc = 0; cpu_notifier_register_begin(); for_each_online_cpu(cpu) { for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); rc = topology_add_dev(cpu); if (rc) 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); device_initcall(topology_sysfs_init); Loading
Documentation/cpu-hotplug.txt +45 −0 Original line number Original line 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? 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. 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 If you need to perform some action for each cpu already in the system, then do this: for_each_online_cpu(i) { for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, 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, Q: If i would like to develop cpu hotplug support for a new architecture, what do i need at a minimum? what do i need at a minimum? A: The following are what is required for CPU hotplug infrastructure to work 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 Original line 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_brps = get_num_brps(); core_num_wrps = get_num_wrps(); core_num_wrps = get_num_wrps(); cpu_notifier_register_begin(); /* /* * We need to tread carefully here because DBGSWENABLE may be * We need to tread carefully here because DBGSWENABLE may be * driven low on this core and there isn't an architected way to * 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)) { if (!cpumask_empty(&debug_err_mask)) { core_num_brps = 0; core_num_brps = 0; core_num_wrps = 0; core_num_wrps = 0; cpu_notifier_register_done(); return 0; return 0; } } Loading @@ -1129,7 +1132,10 @@ static int __init arch_hw_breakpoint_init(void) TRAP_HWBKPT, "breakpoint debug exception"); TRAP_HWBKPT, "breakpoint debug exception"); /* Register hotplug and PM notifiers. */ /* Register hotplug and PM notifiers. */ register_cpu_notifier(&dbg_reset_nb); __register_cpu_notifier(&dbg_reset_nb); cpu_notifier_register_done(); pm_init(); pm_init(); return 0; return 0; } } Loading
arch/arm64/kernel/debug-monitors.c +5 −1 Original line number Original line 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) static int __cpuinit debug_monitors_init(void) { { cpu_notifier_register_begin(); /* Clear the OS lock. */ /* Clear the OS lock. */ smp_call_function(clear_os_lock, NULL, 1); smp_call_function(clear_os_lock, NULL, 1); clear_os_lock(NULL); clear_os_lock(NULL); /* Register hotplug handler. */ /* Register hotplug handler. */ register_cpu_notifier(&os_lock_nb); __register_cpu_notifier(&os_lock_nb); cpu_notifier_register_done(); return 0; return 0; } } postcore_initcall(debug_monitors_init); postcore_initcall(debug_monitors_init); Loading
arch/arm64/kernel/hw_breakpoint.c +6 −1 Original line number Original line 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", pr_info("found %d breakpoint and %d watchpoint registers.\n", core_num_brps, core_num_wrps); core_num_brps, core_num_wrps); cpu_notifier_register_begin(); /* /* * Reset the breakpoint resources. We assume that a halting * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. * 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"); TRAP_HWBKPT, "hw-watchpoint handler"); /* Register hotplug notifier. */ /* 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 */ /* Register cpu_suspend hw breakpoint restore hook */ cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); Loading
drivers/base/topology.c +8 −4 Original line number Original line 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) static int __cpuinit topology_sysfs_init(void) { { int cpu; int cpu; int rc; int rc = 0; cpu_notifier_register_begin(); for_each_online_cpu(cpu) { for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); rc = topology_add_dev(cpu); if (rc) 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); device_initcall(topology_sysfs_init);