[PATCH v1 2/2] platform/x86/intel-uncore-freq: Expose instance ID in the sysfs
From: Maciej Wieczor-Retman
Date: Fri Mar 27 2026 - 11:44:25 EST
From: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
To allow userspace matching between the kernel driver and direct TPMI
register accesses, expose the data required to identify a TPMI uncore
frequency control register set.
Specifically expose the instance ID that's unique in the scope of one
TPMI device. The value was previously available through the domain_id
file exported through sysfs. However on newer systems with multiple
clusters attached to a single instance, domain_id is taking on a unique
value, that's not local to the single TPMI device anymore.
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
---
.../uncore-frequency/uncore-frequency-common.c | 10 ++++++++++
.../uncore-frequency/uncore-frequency-common.h | 6 +++++-
.../uncore-frequency/uncore-frequency-tpmi.c | 17 ++++++++++++++++-
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
index 71c47aa77d3c..52a62cad35de 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
@@ -29,6 +29,13 @@ static ssize_t show_domain_id(struct kobject *kobj, struct kobj_attribute *attr,
return sysfs_emit(buf, "%u\n", data->domain_id);
}
+static ssize_t show_instance_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct uncore_data *data = container_of(attr, struct uncore_data, instance_id_kobj_attr);
+
+ return sprintf(buf, "%u\n", data->instance_id);
+}
+
static ssize_t show_fabric_cluster_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_kobj_attr);
@@ -200,6 +207,9 @@ static int create_attr_group(struct uncore_data *data, char *name)
if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
init_attribute_root_ro(domain_id);
data->uncore_attrs[index++] = &data->domain_id_kobj_attr.attr;
+ init_attribute_root_ro(instance_id);
+ data->uncore_attrs[index++] = &data->instance_id_kobj_attr.attr;
+
init_attribute_root_ro(fabric_cluster_id);
data->uncore_attrs[index++] = &data->fabric_cluster_id_kobj_attr.attr;
init_attribute_root_ro(package_id);
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
index 915506de4ebf..5e00030fedc5 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
@@ -36,6 +36,7 @@
* @domain_id: Power domain id for this instance
* @cluster_id: cluster id in a domain
* @seqname_id: Unique id to append to directory name
+ * @instance_id: Feature instances for a single PCI device
* @name: Sysfs entry name for this instance
* @agent_type_mask: Bit mask of all hardware agents for this domain
* @uncore_attr_group: Attribute group storage
@@ -56,6 +57,7 @@
* @elc_floor_freq_khz_kobj_attr: Storage for kobject attribute elc_floor_freq_khz
* @agent_types_kobj_attr: Storage for kobject attribute agent_type
* @die_id_kobj_attr: Attribute storage for die_id information
+ * @instance_id_kobj_attr: Attribute storage for feat_instance value
* @uncore_attrs: Attribute storage for group creation
*
* This structure is used to encapsulate all data related to uncore sysfs
@@ -72,6 +74,7 @@ struct uncore_data {
int domain_id;
int cluster_id;
int seqname_id;
+ int instance_id;
char name[32];
u16 agent_type_mask;
@@ -90,7 +93,8 @@ struct uncore_data {
struct kobj_attribute elc_floor_freq_khz_kobj_attr;
struct kobj_attribute agent_types_kobj_attr;
struct kobj_attribute die_id_kobj_attr;
- struct attribute *uncore_attrs[15];
+ struct kobj_attribute instance_id_kobj_attr;
+ struct attribute *uncore_attrs[16];
};
#define UNCORE_DOMAIN_ID_INVALID -1
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
index 1237d9570886..e74e7d2e26b6 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -385,7 +385,21 @@ static u8 io_die_index_next;
/* Lock to protect io_die_start, io_die_index_next */
static DEFINE_MUTEX(domain_lock);
-static void set_domain_id(int id, int num_resources,
+static void set_instance_id(int id, struct tpmi_uncore_cluster_info *cluster_info)
+{
+ /*
+ * In its base form the domain_id is a per-TPMI device value that lists
+ * feature instances for that specific TPMI device (instances as named by
+ * the intel_vsec system). On newer platforms the cdie system comes into
+ * effect which makes domain_id a unique identifier and there is no more
+ * correlation between the TPMI device and the domain_id number. The old
+ * version is still relevant so TPMI device scoped information can be
+ * matched with the data from the TPMI driver.
+ */
+ cluster_info->uncore_data.instance_id = id;
+}
+
+static void set_domain_id(int id, int num_resources,
struct oobmsm_plat_info *plat_info,
struct tpmi_uncore_cluster_info *cluster_info)
{
@@ -686,6 +700,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
set_cdie_id(i, cluster_info, plat_info);
set_domain_id(i, num_resources, plat_info, cluster_info);
+ set_instance_id(i, cluster_info);
cluster_info->uncore_root = tpmi_uncore;
--
2.53.0