Dynamic Housekeeping Management allows runtime configuration of kernel overhead isolation boundaries. However, configuring CPUMASKs that separate SMT siblings (e.g., placing one hardware thread in the housekeeping mask and leaving the other isolated) can lead to severe performance degradation due to shared L1 caches and pipeline resources.
This patch introduces `cpuset.housekeeping.smt_aware`, a robust safety guard to prevent user-space from splitting SMT sibling pairs across isolation boundaries. When `cpuset.housekeeping.smt_aware` is enabled (1): - Any write to `cpuset.housekeeping.cpus` must include all SMT siblings for each CPU presented in the new mask (verified via `topology_sibling_cpumask`). - If an invalid mask is supplied, the write operation is aborted with `-EINVAL`. This ensures the kernel's housekeeping constraints are met while maintaining maximum hardware thread efficiency. Signed-off-by: Qiliang Yuan <[email protected]> --- kernel/cgroup/cpuset-internal.h | 1 + kernel/cgroup/cpuset.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h index 3ab437f54ecdf..162594eaf8467 100644 --- a/kernel/cgroup/cpuset-internal.h +++ b/kernel/cgroup/cpuset-internal.h @@ -61,6 +61,7 @@ typedef enum { FILE_EFFECTIVE_XCPULIST, FILE_ISOLATED_CPULIST, FILE_HOUSEKEEPING_CPULIST, + FILE_HOUSEKEEPING_SMT_AWARE, FILE_CPU_EXCLUSIVE, FILE_MEM_EXCLUSIVE, FILE_MEM_HARDWALL, diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 5df19dc9bfa89..4272bb298ec3d 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -37,6 +37,7 @@ #include <linux/wait.h> #include <linux/workqueue.h> #include <linux/task_work.h> +#include <linux/topology.h> DEFINE_STATIC_KEY_FALSE(cpusets_pre_enable_key); DEFINE_STATIC_KEY_FALSE(cpusets_enabled_key); @@ -156,6 +157,9 @@ static bool update_housekeeping; /* RWCS */ */ static cpumask_var_t isolated_hk_cpus; /* T */ +/* DHM: Enable SMT-aware boundary checks */ +static bool cpuset_housekeeping_smt_aware = false; + /* * A flag to force sched domain rebuild at the end of an operation. * It can be set in @@ -3218,6 +3222,16 @@ static ssize_t cpuset_write_housekeeping_cpus(struct kernfs_open_file *of, if (retval) goto out_free; + if (cpuset_housekeeping_smt_aware) { + int cpu; + for_each_cpu(cpu, new_mask) { + if (!cpumask_subset(topology_sibling_cpumask(cpu), new_mask)) { + retval = -EINVAL; + goto out_free; + } + } + } + retval = housekeeping_update_all_types(new_mask); out_free: @@ -3225,6 +3239,18 @@ static ssize_t cpuset_write_housekeeping_cpus(struct kernfs_open_file *of, return retval ?: nbytes; } +static ssize_t cpuset_write_housekeeping_smt_aware(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) +{ + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + cpuset_housekeeping_smt_aware = val; + return nbytes; +} + /* * Common handling for a write to a "cpus" or "mems" file. */ @@ -3317,6 +3343,9 @@ int cpuset_common_seq_show(struct seq_file *sf, void *v) case FILE_HOUSEKEEPING_CPULIST: seq_printf(sf, "%*pbl\n", cpumask_pr_args(housekeeping_cpumask(HK_TYPE_DOMAIN))); break; + case FILE_HOUSEKEEPING_SMT_AWARE: + seq_printf(sf, "%d\n", cpuset_housekeeping_smt_aware); + break; default: ret = -EINVAL; } @@ -3464,6 +3493,14 @@ static struct cftype dfl_files[] = { .flags = CFTYPE_ONLY_ON_ROOT, }, + { + .name = "housekeeping.smt_aware", + .seq_show = cpuset_common_seq_show, + .write = cpuset_write_housekeeping_smt_aware, + .private = FILE_HOUSEKEEPING_SMT_AWARE, + .flags = CFTYPE_ONLY_ON_ROOT, + }, + { } /* terminate */ }; -- 2.43.0

