[PATCH 12/17] platform/x86/intel/ifs: Add new sysfs interfaces {status, details, cpus_ran}_list

From: Ehab Ababneh

Date: Mon Oct 26 2026 - 14:40:08 EST


From: Jithu Joseph <jithu.joseph@xxxxxxxxx>

Problem
=======
The current legacy interface for Intel In-Field Scan is designed to
simultaneously test all CPUs in a group [1], but it only reports the
status of the primary CPU in this group and doesn't indicate that
secondary CPUs have been tested. This results in the following issues:

- All CPUs in a group can hold different statuses, but the user can
only see the status of the primary CPU, as any errors observed by
secondary CPUs are ignored.

- The topology of a group of CPUs may vary across systems. For example,
in a Hyper-Threading (HT) system, the group consists of all CPUs in
a core, while in a Dual-Core Module (DCM) based system (e.g., Intel
Diamond Rapids CPU), two cores in a module form a group. The user may
be unaware of the group topology and test each CPU of the system
individually, leading to duplicate test runs.

Solution
========
The user continues to write a single value to run_test, and while the
legacy sysfs reports results for the tested CPU to ensure backward
compatibility, new sysfs interfaces {status, details, cpus_run}_list
provide results for multiple related CPUs tested as part of a group.
The user can check for the presence of new sysfs interfaces to
understand that multiple results are available, read them, and identify
which CPUs have been tested to avoid duplicate tests.

intel_ifs_0
+---- run_test <--- Same legacy file
+---- current_batch
+---- details
+---- details_list <--- Details for all CPUs in the group (new)
+---- dev
+---- image_version
+---- status
+---- status_list <--- Status for all CPUs in the group (new)
+---- cpus_ran_list <--- CPUs in the group tested along with CPU written to run_test (new)
\---- uevent

Example of reading the cpus_ran_list to see the CPUs tested:

echo 0 > run_test
cat cpus_ran_list
0,96

cat status_list
pass pass

cat details_list
0x8086 0x8087

[1] Indicated by bits [20:16] of MSR_INTEGRITY_CAPABILITIES when bit 21 is set.
E.g., in Hyper-Threading (HT) systems, a group includes all threads in a core;
in Dual-Core Module (DCM) system, a group includes all CPU cores in a module.

[ Qiuxu: wrote the commit message. ]

Signed-off-by: Jithu Joseph <jithu.joseph@xxxxxxxxx>
Signed-off-by: Ehab Ababneh <ehab.ababneh@xxxxxxxxx>
---
drivers/platform/x86/intel/ifs/sysfs.c | 56 ++++++++++++++++++++++++++
1 file changed, 56 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
index 287f96bb033e..82a603cd1fd3 100644
--- a/drivers/platform/x86/intel/ifs/sysfs.c
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -135,6 +135,59 @@ static ssize_t image_version_show(struct device *dev,

static DEVICE_ATTR_RO(image_version);

+static ssize_t status_list_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ifs_data *ifsd = ifs_get_data(dev);
+ struct ifs_test_output *pcpu_state;
+ int lcpu, len = 0;
+
+ if (cpumask_weight(&ifsd->grp_cpumask) == 0)
+ return sysfs_emit(buf, "%s\n", "none");
+
+ for_each_cpu(lcpu, &ifsd->grp_cpumask) {
+ pcpu_state = per_cpu_ptr(ifsd->result_ptr, lcpu);
+ len += sysfs_emit_at(buf, len, "%s%s", (len > 0) ? " " : "",
+ status_msg[pcpu_state->test_result]);
+ }
+ len += sysfs_emit_at(buf, len, "\n");
+
+ return len;
+}
+
+static DEVICE_ATTR_RO(status_list);
+
+static ssize_t details_list_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ifs_data *ifsd = ifs_get_data(dev);
+ struct ifs_test_output *pcpu_state;
+ int lcpu, len = 0;
+
+ if (cpumask_weight(&ifsd->grp_cpumask) == 0)
+ return sysfs_emit(buf, "%s\n", "none");
+
+ for_each_cpu(lcpu, &ifsd->grp_cpumask) {
+ pcpu_state = per_cpu_ptr(ifsd->result_ptr, lcpu);
+ len += sysfs_emit_at(buf, len, "%s%#llx", (len > 0) ? " " : "",
+ pcpu_state->test_details);
+ }
+ len += sysfs_emit_at(buf, len, "\n");
+
+ return len;
+}
+
+static DEVICE_ATTR_RO(details_list);
+
+static ssize_t cpus_ran_list_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ifs_data *ifsd = ifs_get_data(dev);
+
+ if (cpumask_weight(&ifsd->grp_cpumask) == 0)
+ return sysfs_emit(buf, "%s\n", "none");
+
+ return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&ifsd->grp_cpumask));
+}
+
+static DEVICE_ATTR_RO(cpus_ran_list);
/* global scan sysfs attributes */
struct attribute *plat_ifs_attrs[] = {
&dev_attr_details.attr,
@@ -142,6 +195,9 @@ struct attribute *plat_ifs_attrs[] = {
&dev_attr_run_test.attr,
&dev_attr_current_batch.attr,
&dev_attr_image_version.attr,
+ &dev_attr_status_list.attr,
+ &dev_attr_details_list.attr,
+ &dev_attr_cpus_ran_list.attr,
NULL
};

--
2.43.0