[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20250616082453.3725-3-ilpo.jarvinen@linux.intel.com>
Date: Mon, 16 Jun 2025 11:24:53 +0300
From: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
To: linux-kselftest@...r.kernel.org,
Reinette Chatre <reinette.chatre@...el.com>,
Shuah Khan <shuah@...nel.org>,
Tony Luck <tony.luck@...el.com>,
Dave Martin <Dave.Martin@....com>,
James Morse <james.morse@....com>,
Shaopeng Tan <tan.shaopeng@...fujitsu.com>,
linux-kernel@...r.kernel.org
Cc: Fenghua Yu <fenghua.yu@...el.com>,
Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
Subject: [RFC PATCH v1 2/2] kselftest/resctrl: Add L3 CAT CBM functional test for Intel RDT
Resctrl CAT selftests have been limited to mainly testing performance.
In order to validate the kernel side behavior better, add a functional
test that checks the MSR contents (if MSRs are accessible). As the
low-level mapping is architecture specific, this test is currently
limited to testing resctrl only on Intel CPUs.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
---
tools/testing/selftests/resctrl/cat_test.c | 126 ++++++++++++++++++
tools/testing/selftests/resctrl/msr.c | 55 ++++++++
tools/testing/selftests/resctrl/resctrl.h | 4 +
.../testing/selftests/resctrl/resctrl_tests.c | 1 +
4 files changed, 186 insertions(+)
create mode 100644 tools/testing/selftests/resctrl/msr.c
diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c
index 78cb9ac90bb1..fbe1d2f7657f 100644
--- a/tools/testing/selftests/resctrl/cat_test.c
+++ b/tools/testing/selftests/resctrl/cat_test.c
@@ -9,8 +9,15 @@
* Fenghua Yu <fenghua.yu@...el.com>
*/
#include "resctrl.h"
+
+#include <string.h>
#include <unistd.h>
+#define MSR_IA32_PQR_ASSOC 0xc8f
+#define MSR_IA32_PQR_ASSOC_COS 0xffffffff00000000ULL
+
+#define MSR_IA32_L3_CBM_BASE 0xc90
+
#define RESULT_FILE_NAME "result_cat"
#define NUM_OF_RUNS 5
@@ -452,6 +459,116 @@ static int cat_ctrlgrp_tasks_test(const struct resctrl_test *test,
return ret;
}
+static int cat_ctrlgrp_check_msr(const struct user_params *uparams,
+ unsigned long mask)
+{
+ __u64 msr_val;
+ __u32 clos;
+ int ret;
+
+ ret = read_msr(uparams->cpu, MSR_IA32_PQR_ASSOC, &msr_val);
+ if (ret)
+ return -1;
+
+ clos = (msr_val & MSR_IA32_PQR_ASSOC_COS) >> (ffsl(MSR_IA32_PQR_ASSOC_COS) - 1);
+
+ ret = read_msr(uparams->cpu, MSR_IA32_L3_CBM_BASE + clos, &msr_val);
+ if (ret)
+ return -1;
+
+ if (msr_val != mask) {
+ ksft_print_msg("Incorrect CBM mask %llx, should be %lx\n",
+ msr_val, mask);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int cat_ctrlgrp_msr_test(const struct resctrl_test *test,
+ const struct user_params *uparams)
+{
+ unsigned long mask1 = 0x3, mask2 = 0x6, mask3 = 0x0c;
+ cpu_set_t old_affinity;
+ char schemata[64];
+ pid_t bm_pid;
+ int ret;
+
+ bm_pid = getpid();
+
+ if (!msr_access_supported(uparams->cpu)) {
+ ksft_test_result_skip("Cannot access MSRs\n");
+ return 0;
+ }
+
+ ret = resctrl_grp_has_task(NULL, bm_pid);
+ if (ret < 0)
+ return ret;
+ if (!ret) {
+ ksft_print_msg("PID not found in the root group\n");
+ return 1;
+ }
+
+ /* Taskset benchmark to specified CPU */
+ ksft_print_msg("Placing task to ctrlgrp 'c1'\n");
+ ret = taskset_benchmark(bm_pid, uparams->cpu, &old_affinity);
+ if (ret)
+ return ret;
+ ret = write_bm_pid_to_resctrl(bm_pid, "c1", NULL);
+ if (ret)
+ goto reset_affinity;
+ snprintf(schemata, sizeof(schemata), "%lx", mask1);
+ ret = write_schemata("c1", schemata, uparams->cpu, test->resource);
+ if (ret)
+ goto reset_affinity;
+ ret = cat_ctrlgrp_check_msr(uparams, mask1);
+ if (ret)
+ goto reset_affinity;
+
+ ksft_print_msg("Placing task to ctrlgrp 'c2'\n");
+ ret = write_bm_pid_to_resctrl(bm_pid, "c2", NULL);
+ if (ret)
+ goto reset_affinity;
+ snprintf(schemata, sizeof(schemata), "%lx", mask2);
+ ret = write_schemata("c2", schemata, uparams->cpu, test->resource);
+ if (ret)
+ goto reset_affinity;
+ ret = cat_ctrlgrp_check_msr(uparams, mask2);
+ if (ret)
+ goto reset_affinity;
+
+ ksft_print_msg("Adjusting CBM for unrelated ctrlgrp 'c1'\n");
+ snprintf(schemata, sizeof(schemata), "%lx", mask3);
+ ret = write_schemata("c1", schemata, uparams->cpu, test->resource);
+ if (ret)
+ goto reset_affinity;
+ ret = cat_ctrlgrp_check_msr(uparams, mask2);
+ if (ret)
+ goto reset_affinity;
+
+ ksft_print_msg("Adjusting CBM for ctrlgrp 'c2'\n");
+ snprintf(schemata, sizeof(schemata), "%lx", mask1);
+ ret = write_schemata("c2", schemata, uparams->cpu, test->resource);
+ if (ret)
+ goto reset_affinity;
+ ret = cat_ctrlgrp_check_msr(uparams, mask1);
+ if (ret)
+ goto reset_affinity;
+
+ ksft_print_msg("Placing task to ctrlgrp 'c1'\n");
+ ret = write_bm_pid_to_resctrl(bm_pid, "c1", NULL);
+ if (ret)
+ goto reset_affinity;
+ ret = cat_ctrlgrp_check_msr(uparams, mask3);
+ if (ret)
+ goto reset_affinity;
+
+reset_affinity:
+ taskset_restore(bm_pid, &old_affinity);
+
+ return ret;
+}
+
struct resctrl_test l3_cat_test = {
.name = "L3_CAT",
.group = "CAT",
@@ -484,3 +601,12 @@ struct resctrl_test cat_grp_tasks_test = {
.feature_check = test_resource_feature_check,
.run_test = cat_ctrlgrp_tasks_test,
};
+
+struct resctrl_test cat_grp_mask_test = {
+ .name = "CAT_GROUP_MASK",
+ .group = "CAT",
+ .resource = "L3",
+ .vendor_specific = ARCH_INTEL,
+ .feature_check = test_resource_feature_check,
+ .run_test = cat_ctrlgrp_msr_test,
+};
diff --git a/tools/testing/selftests/resctrl/msr.c b/tools/testing/selftests/resctrl/msr.c
new file mode 100644
index 000000000000..1e8674036c7d
--- /dev/null
+++ b/tools/testing/selftests/resctrl/msr.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <linux/types.h>
+
+#include "resctrl.h"
+
+#define MSR_PATH "/dev/cpu/%d/msr"
+
+static int open_msr_file(int cpu)
+{
+ char msr_path[PATH_MAX];
+
+ snprintf(msr_path, sizeof(msr_path), MSR_PATH, cpu);
+
+ return open(msr_path, O_RDONLY);
+}
+
+int read_msr(int cpu, __u32 msr, __u64 *val)
+{
+ ssize_t res;
+ int fd;
+
+ fd = open_msr_file(cpu);
+ if (fd < 0) {
+ ksft_print_msg("Failed to open msr file for CPU %d\n", cpu);
+ return -1;
+ }
+
+ res = pread(fd, val, sizeof(*val), msr);
+ close(fd);
+ if (res < sizeof(*val)) {
+ ksft_print_msg("Reading MSR failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+bool msr_access_supported(int cpu)
+{
+ int fd;
+
+ fd = open_msr_file(cpu);
+ if (fd < 0)
+ return false;
+
+ close(fd);
+ return true;
+}
diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h
index d25f83d0a54d..909a101f0e4c 100644
--- a/tools/testing/selftests/resctrl/resctrl.h
+++ b/tools/testing/selftests/resctrl/resctrl.h
@@ -243,8 +243,12 @@ extern struct resctrl_test mbm_test;
extern struct resctrl_test mba_test;
extern struct resctrl_test cmt_test;
extern struct resctrl_test cat_grp_tasks_test;
+extern struct resctrl_test cat_grp_mask_test;
extern struct resctrl_test l3_cat_test;
extern struct resctrl_test l3_noncont_cat_test;
extern struct resctrl_test l2_noncont_cat_test;
+bool msr_access_supported(int cpu);
+int read_msr(int cpu, __u32 msr, __u64 *val);
+
#endif /* RESCTRL_H */
diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c b/tools/testing/selftests/resctrl/resctrl_tests.c
index 71b7cd846dc1..08ae48165c7a 100644
--- a/tools/testing/selftests/resctrl/resctrl_tests.c
+++ b/tools/testing/selftests/resctrl/resctrl_tests.c
@@ -19,6 +19,7 @@ static struct resctrl_test *resctrl_tests[] = {
&mba_test,
&cmt_test,
&cat_grp_tasks_test,
+ &cat_grp_mask_test,
&l3_cat_test,
&l3_noncont_cat_test,
&l2_noncont_cat_test,
--
2.39.5
Powered by blists - more mailing lists