Expose /sys/devices/system/cpu/preserved (global cpumask of preserved
cores) and /sys/devices/system/cpu/cpuX/preserve (per-CPU preservation
attribute and file descriptor target for LUO sessions), and document
both attributes in Documentation/ABI/testing/sysfs-devices-system-cpu.

Signed-off-by: Pasha Tatashin <[email protected]>
---
 .../ABI/testing/sysfs-devices-system-cpu      | 20 ++++++++
 kernel/liveupdate/cpu_preserve.c              | 49 +++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu 
b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 82d10d556cc8..88ab03efd433 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -806,3 +806,23 @@ Date:              Nov 2022
 Contact:       Linux kernel mailing list <[email protected]>
 Description:
                (RO) the list of CPUs that can be brought online.
+
+What:          /sys/devices/system/cpu/preserved
+Date:          March 2026
+Contact:       Pasha Tatashin <[email protected]>
+Description:
+               (RO) cpumask list of physical CPUs currently isolated and
+               preserved across a host kernel live update. Note the naming
+               distinction from the per-CPU 
/sys/devices/system/cpu/cpuX/preserve
+               attribute.
+
+What:          /sys/devices/system/cpu/cpuX/preserve
+Date:          March 2026
+Contact:       Pasha Tatashin <[email protected]>
+Description:
+               (RO) returns 1 if cpuX is currently preserved across a host
+               kernel live update, 0 otherwise. Although read-only, this sysfs
+               node exists to be opened and passed by file descriptor to a Live
+               Update Orchestrator (LUO) session via 
LIVEUPDATE_SESSION_PRESERVE_FD
+               to request preservation of cpuX across kexec.
+
diff --git a/kernel/liveupdate/cpu_preserve.c b/kernel/liveupdate/cpu_preserve.c
index c5fd3a07ccb5..cc27d1624d29 100644
--- a/kernel/liveupdate/cpu_preserve.c
+++ b/kernel/liveupdate/cpu_preserve.c
@@ -606,3 +606,52 @@ static int __init cpu_preserve_early_init(void)
        return 0;
 }
 early_initcall(cpu_preserve_early_init);
+static ssize_t preserved_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%*pbl\n",
+                         cpumask_pr_args(cpu_get_preserved_mask()));
+}
+static DEVICE_ATTR_RO(preserved);
+
+static ssize_t preserve_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%d\n", cpu_is_preserved(dev->id));
+}
+static DEVICE_ATTR_RO(preserve);
+
+static int __init cpu_preserve_sysfs_init(void)
+{
+       struct device *dev_root = bus_get_dev_root(&cpu_subsys);
+       int cpu, ret;
+
+       if (dev_root) {
+               ret = sysfs_create_file(&dev_root->kobj, 
&dev_attr_preserved.attr);
+               put_device(dev_root);
+               if (ret)
+                       pr_warn("Failed to create cpu preserved sysfs 
attribute: %d\n", ret);
+       }
+
+       for_each_possible_cpu(cpu) {
+               struct device *dev = get_cpu_device(cpu);
+
+               if (!dev && cpu_is_preserved(cpu)) {
+                       set_cpu_present(cpu, true);
+                       arch_register_cpu(cpu);
+                       dev = get_cpu_device(cpu);
+               }
+
+               if (dev) {
+                       ret = sysfs_create_file(&dev->kobj, 
&dev_attr_preserve.attr);
+                       if (ret)
+                               pr_warn("Failed to create cpu%d preserve sysfs 
attribute: %d\n",
+                                       cpu, ret);
+               }
+
+               if (cpu_is_preserved(cpu))
+                       set_cpu_present(cpu, false);
+       }
+       return 0;
+}
+late_initcall(cpu_preserve_sysfs_init);
-- 
2.55.0.1082.g2b9226bbc0-goog


Reply via email to