Skip to content

Commit 7f48405

Browse files
mpeKAGA-KOKO
authored andcommitted
cpu/SMT: Allow enabling partial SMT states via sysfs
Add support to the /sys/devices/system/cpu/smt/control interface for enabling a specified number of SMT threads per core, including partial SMT states where not all threads are brought online. The current interface accepts "on" and "off", to enable either 1 or all SMT threads per core. This commit allows writing an integer, between 1 and the number of SMT threads supported by the machine. Writing 1 is a synonym for "off", 2 or more enables SMT with the specified number of threads. When reading the file, if all threads are online "on" is returned, to avoid changing behaviour for existing users. If some other number of threads is online then the integer value is returned. Architectures like x86 only supporting 1 thread or all threads, should not define CONFIG_SMT_NUM_THREADS_DYNAMIC. Architecture supporting partial SMT states, like PowerPC, should define it. [ ldufour: Slightly reword the commit's description ] [ ldufour: Remove switch() in __store_smt_control() ] [ ldufour: Rix build issue in control_show() ] Reported-by: kernel test robot <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Signed-off-by: Laurent Dufour <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Zhang Rui <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3825346 commit 7f48405

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

Documentation/ABI/testing/sysfs-devices-system-cpu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ Description: Control Symmetric Multi Threading (SMT)
555555
================ =========================================
556556
"on" SMT is enabled
557557
"off" SMT is disabled
558+
"<N>" SMT is enabled with N threads per core.
558559
"forceoff" SMT is force disabled. Cannot be changed.
559560
"notsupported" SMT is not supported by the CPU
560561
"notimplemented" SMT runtime toggling is not

kernel/cpu.c

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,42 +2876,59 @@ static const struct attribute_group cpuhp_cpu_root_attr_group = {
28762876

28772877
#ifdef CONFIG_HOTPLUG_SMT
28782878

2879+
static bool cpu_smt_num_threads_valid(unsigned int threads)
2880+
{
2881+
if (IS_ENABLED(CONFIG_SMT_NUM_THREADS_DYNAMIC))
2882+
return threads >= 1 && threads <= cpu_smt_max_threads;
2883+
return threads == 1 || threads == cpu_smt_max_threads;
2884+
}
2885+
28792886
static ssize_t
28802887
__store_smt_control(struct device *dev, struct device_attribute *attr,
28812888
const char *buf, size_t count)
28822889
{
2883-
int ctrlval, ret;
2890+
int ctrlval, ret, num_threads, orig_threads;
2891+
bool force_off;
28842892

28852893
if (cpu_smt_control == CPU_SMT_FORCE_DISABLED)
28862894
return -EPERM;
28872895

28882896
if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
28892897
return -ENODEV;
28902898

2891-
if (sysfs_streq(buf, "on"))
2899+
if (sysfs_streq(buf, "on")) {
28922900
ctrlval = CPU_SMT_ENABLED;
2893-
else if (sysfs_streq(buf, "off"))
2901+
num_threads = cpu_smt_max_threads;
2902+
} else if (sysfs_streq(buf, "off")) {
28942903
ctrlval = CPU_SMT_DISABLED;
2895-
else if (sysfs_streq(buf, "forceoff"))
2904+
num_threads = 1;
2905+
} else if (sysfs_streq(buf, "forceoff")) {
28962906
ctrlval = CPU_SMT_FORCE_DISABLED;
2897-
else
2907+
num_threads = 1;
2908+
} else if (kstrtoint(buf, 10, &num_threads) == 0) {
2909+
if (num_threads == 1)
2910+
ctrlval = CPU_SMT_DISABLED;
2911+
else if (cpu_smt_num_threads_valid(num_threads))
2912+
ctrlval = CPU_SMT_ENABLED;
2913+
else
2914+
return -EINVAL;
2915+
} else {
28982916
return -EINVAL;
2917+
}
28992918

29002919
ret = lock_device_hotplug_sysfs();
29012920
if (ret)
29022921
return ret;
29032922

2904-
if (ctrlval != cpu_smt_control) {
2905-
switch (ctrlval) {
2906-
case CPU_SMT_ENABLED:
2907-
ret = cpuhp_smt_enable();
2908-
break;
2909-
case CPU_SMT_DISABLED:
2910-
case CPU_SMT_FORCE_DISABLED:
2911-
ret = cpuhp_smt_disable(ctrlval);
2912-
break;
2913-
}
2914-
}
2923+
orig_threads = cpu_smt_num_threads;
2924+
cpu_smt_num_threads = num_threads;
2925+
2926+
force_off = ctrlval != cpu_smt_control && ctrlval == CPU_SMT_FORCE_DISABLED;
2927+
2928+
if (num_threads > orig_threads)
2929+
ret = cpuhp_smt_enable();
2930+
else if (num_threads < orig_threads || force_off)
2931+
ret = cpuhp_smt_disable(ctrlval);
29152932

29162933
unlock_device_hotplug();
29172934
return ret ? ret : count;
@@ -2939,6 +2956,17 @@ static ssize_t control_show(struct device *dev,
29392956
{
29402957
const char *state = smt_states[cpu_smt_control];
29412958

2959+
#ifdef CONFIG_HOTPLUG_SMT
2960+
/*
2961+
* If SMT is enabled but not all threads are enabled then show the
2962+
* number of threads. If all threads are enabled show "on". Otherwise
2963+
* show the state name.
2964+
*/
2965+
if (cpu_smt_control == CPU_SMT_ENABLED &&
2966+
cpu_smt_num_threads != cpu_smt_max_threads)
2967+
return sysfs_emit(buf, "%d\n", cpu_smt_num_threads);
2968+
#endif
2969+
29422970
return snprintf(buf, PAGE_SIZE - 2, "%s\n", state);
29432971
}
29442972

0 commit comments

Comments
 (0)