Skip to content

Commit 2760f5a

Browse files
Peter Zijlstrajwrdegoede
authored andcommitted
stop_machine: Add stop_core_cpuslocked() for per-core operations
Hardware core level testing features require near simultaneous execution of WRMSR instructions on all threads of a core to initiate a test. Provide a customized cut down version of stop_machine_cpuslocked() that just operates on the threads of a single core. Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20220506225410.1652287-4-tony.luck@intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent db1af12 commit 2760f5a

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

include/linux/stop_machine.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
124124
*/
125125
int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
126126

127+
/**
128+
* stop_core_cpuslocked: - stop all threads on just one core
129+
* @cpu: any cpu in the targeted core
130+
* @fn: the function to run
131+
* @data: the data ptr for @fn()
132+
*
133+
* Same as above, but instead of every CPU, only the logical CPUs of a
134+
* single core are affected.
135+
*
136+
* Context: Must be called from within a cpus_read_lock() protected region.
137+
*
138+
* Return: 0 if all executions of @fn returned 0, any non zero return
139+
* value if any returned non zero.
140+
*/
141+
int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
142+
127143
int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
128144
const struct cpumask *cpus);
129145
#else /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */

kernel/stop_machine.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,27 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
633633
}
634634
EXPORT_SYMBOL_GPL(stop_machine);
635635

636+
#ifdef CONFIG_SCHED_SMT
637+
int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
638+
{
639+
const struct cpumask *smt_mask = cpu_smt_mask(cpu);
640+
641+
struct multi_stop_data msdata = {
642+
.fn = fn,
643+
.data = data,
644+
.num_threads = cpumask_weight(smt_mask),
645+
.active_cpus = smt_mask,
646+
};
647+
648+
lockdep_assert_cpus_held();
649+
650+
/* Set the initial state and stop all online cpus. */
651+
set_state(&msdata, MULTI_STOP_PREPARE);
652+
return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
653+
}
654+
EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
655+
#endif
656+
636657
/**
637658
* stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
638659
* @fn: the function to run

0 commit comments

Comments
 (0)