[RFC patch 2/9] selftests/resctrl: Refactor resctrl_val.c for vendor-specific mem bw measurement

Yifan Wu wuyifan50 at huawei.com
Tue Mar 3 20:03:27 PST 2026


Currently, the resctrl_val.c is tightly coupled with X86's uncore IMC
counter, which is inapplicable on other platforms like ARM.

This commit refactor resctrl_val.c by introducing a structure to support
vendor-specific PMU, event and scale. This allows the test to dynamically
select the PMU based on the detected CPU vendor, paving the way for
supporting multiple vendors and architectures.

Signed-off-by: Yifan Wu <wuyifan50 at huawei.com>
---
 tools/testing/selftests/resctrl/resctrl_val.c | 48 +++++++++++++++----
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c
index 85ac96c7cb8f..b0570c615aac 100644
--- a/tools/testing/selftests/resctrl/resctrl_val.c
+++ b/tools/testing/selftests/resctrl/resctrl_val.c
@@ -10,10 +10,7 @@
  */
 #include "resctrl.h"
 
-#define UNCORE_IMC		"uncore_imc"
-#define READ_FILE_NAME		"events/cas_count_read"
 #define DYN_PMU_PATH		"/sys/bus/event_source/devices"
-#define SCALE			0.00006103515625
 #define MAX_IMCS		20
 #define MAX_TOKENS		5
 
@@ -36,10 +33,30 @@ struct imc_counter_config {
 	int fd;
 };
 
+struct membw_read_config {
+	int vendor_id;
+	const char *name;
+	const char *event;
+	double scale;
+};
+
+static struct membw_read_config membw_read_configs[] = {
+	{
+		.vendor_id = ARCH_INTEL | ARCH_AMD | ARCH_HYGON,
+		.name = "uncore_imc",
+		.event = "events/cas_count_read",
+		.scale = 64.0 / MB,
+	},
+	{
+		.vendor_id = NULL
+	}
+};
+
 static char mbm_total_path[1024];
 static int imcs;
 static struct imc_counter_config imc_counters_config[MAX_IMCS];
 static const struct resctrl_test *current_test;
+static struct membw_read_config *current_config;
 
 static void read_mem_bw_initialize_perf_event_attr(int i)
 {
@@ -133,7 +150,7 @@ static int read_from_imc_dir(char *imc_dir, int count)
 	fclose(fp);
 
 	/* Get read config */
-	sprintf(imc_counter_cfg, "%s%s", imc_dir, READ_FILE_NAME);
+	sprintf(imc_counter_cfg, "%s%s", imc_dir, current_config->event);
 	fp = fopen(imc_counter_cfg, "r");
 	if (!fp) {
 		ksft_perror("Failed to open iMC config file");
@@ -176,18 +193,18 @@ static int num_of_imcs(void)
 	dp = opendir(DYN_PMU_PATH);
 	if (dp) {
 		while ((ep = readdir(dp))) {
-			temp = strstr(ep->d_name, UNCORE_IMC);
+			temp = strstr(ep->d_name, current_config->name);
 			if (!temp)
 				continue;
 
 			/*
 			 * imc counters are named as "uncore_imc_<n>", hence
 			 * increment the pointer to point to <n>. Note that
-			 * sizeof(UNCORE_IMC) would count for null character as
+			 * sizeof("uncore_imc") would count for null character as
 			 * well and hence the last underscore character in
 			 * uncore_imc'_' need not be counted.
 			 */
-			temp = temp + sizeof(UNCORE_IMC);
+			temp = temp + strlen(current_config->name) + 1;
 
 			/*
 			 * Some directories under "DYN_PMU_PATH" could have
@@ -328,7 +345,7 @@ static int get_read_mem_bw_imc(float *bw_imc)
 			of_mul_read = (float)r_time_enabled /
 					(float)r_time_running;
 
-		reads += r->return_value.value * of_mul_read * SCALE;
+		reads += r->return_value.value * of_mul_read * current_config->scale;
 	}
 
 	*bw_imc = reads;
@@ -469,6 +486,21 @@ static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc,
 	return 0;
 }
 
+int initialize_measure_read_mem_bw(const struct resctrl_val_param *param, int domain_id)
+{
+	unsigned int vendor = get_vendor();
+
+	for (current_config = membw_read_configs;
+		!(current_config->vendor_id & vendor);
+		current_config++)
+		continue;
+
+	if (!current_config->vendor_id)
+		return -1;
+
+	return 0;
+}
+
 /*
  * measure_read_mem_bw - Measures read memory bandwidth numbers while benchmark runs
  * @uparams:		User supplied parameters
-- 
2.33.0




More information about the linux-arm-kernel mailing list