Expose cpuN/nohz_tick_allowed on CPUs in the boot-time nohz_full set. The boolean defaults to 1: allow non-idle tick suppression, subject to existing dependencies. Writing 0 prevents suppression through POLICY. Readback reports permission, not the current tick state.
Each write affects only that CPU. Registered offline CPUs remain configurable, and policy persists across offline/online transitions. Retry writes when CPU hotplug is in progress so CPU device removal can drain active sysfs callbacks without a lock dependency cycle. Co-developed-by: He Rongguang <[email protected]> Signed-off-by: He Rongguang <[email protected]> Signed-off-by: Peng Wang <[email protected]> --- .../ABI/testing/sysfs-devices-system-cpu | 27 ++++++++++ drivers/base/cpu.c | 53 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 82d10d556cc89..4f6ac6b41e2b6 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -767,6 +767,33 @@ Description: Preferred MTE tag checking mode See also: Documentation/arch/arm64/memory-tagging-extension.rst +What: /sys/devices/system/cpu/cpuX/nohz_tick_allowed +Date: October 2026 +Contact: Linux kernel mailing list <[email protected]> +Description: + (RW) Boolean allowing this CPU to stop its non-idle scheduler + tick. Present only for registered CPUs in the boot-time + nohz_full set, with CONFIG_NO_HZ_FULL. + + The default is 1 (allowed), subject to existing tick + dependencies. Writing 0 prevents non-idle tick suppression; + writing 1 allows it without forcing the tick to stop. Each + write affects one CPU. Readback reports permission, not the + current tick state. + + Revoking permission requests an asynchronous restart of a + stopped non-idle tick on an online CPU. The write does not wait + for restart. Idle tick suppression is unchanged; the policy + applies when the CPU leaves idle. + + Registered offline CPUs may be configured. Policy is retained + per logical CPU across offline/online and CPU device removal + and re-addition. CPUs without a registered cpuN device cannot + be configured through this interface. + + This does not change nohz_full membership, context tracking, + RCU offloading or housekeeping configuration. + What: /sys/devices/system/cpu/nohz_full Date: Apr 2015 Contact: Linux kernel mailing list <[email protected]> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 69e52fed42415..6fad1b0227dac 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/cpu.h> #include <linux/topology.h> #include <linux/device.h> @@ -189,7 +190,56 @@ static const struct attribute_group crash_note_cpu_attr_group = { }; #endif +#ifdef CONFIG_NO_HZ_FULL +static ssize_t nohz_tick_allowed_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%u\n", tick_nohz_full_get_allowed(dev->id)); +} + +static ssize_t nohz_tick_allowed_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + bool allowed; + int ret; + + ret = kstrtobool(buf, &allowed); + if (ret) + return ret; + + ret = tick_nohz_full_set_allowed(dev->id, allowed); + if (ret == -EBUSY) { + /* Retry after releasing the sysfs active reference. */ + fsleep(5000); + return restart_syscall(); + } + + return ret ? ret : count; +} +static DEVICE_ATTR_RW(nohz_tick_allowed); + +static umode_t nohz_tick_is_visible(struct kobject *kobj, + struct attribute *attr, int unused) +{ + return tick_nohz_full_cpu(kobj_to_dev(kobj)->id) ? attr->mode : 0; +} + +static struct attribute *nohz_tick_cpu_attrs[] = { + &dev_attr_nohz_tick_allowed.attr, + NULL +}; + +static const struct attribute_group nohz_tick_cpu_attr_group = { + .attrs = nohz_tick_cpu_attrs, + .is_visible = nohz_tick_is_visible, +}; +#endif + static const struct attribute_group *common_cpu_attr_groups[] = { +#ifdef CONFIG_NO_HZ_FULL + &nohz_tick_cpu_attr_group, +#endif #ifdef CONFIG_CRASH_DUMP &crash_note_cpu_attr_group, #endif @@ -197,6 +247,9 @@ static const struct attribute_group *common_cpu_attr_groups[] = { }; static const struct attribute_group *hotplugable_cpu_attr_groups[] = { +#ifdef CONFIG_NO_HZ_FULL + &nohz_tick_cpu_attr_group, +#endif #ifdef CONFIG_CRASH_DUMP &crash_note_cpu_attr_group, #endif -- 2.47.0
