]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/resctrl: Reduce interference from L2 occupancy during cache occupancy test
authorReinette Chatre <reinette.chatre@intel.com>
Sat, 4 Apr 2026 01:56:01 +0000 (18:56 -0700)
committerShuah Khan <skhan@linuxfoundation.org>
Tue, 5 May 2026 00:40:02 +0000 (18:40 -0600)
The CMT test creates a new control group that is also capable of monitoring
and assigns the workload to it. The workload allocates a buffer that by
default fills a portion of the L3 and keeps reading from the buffer,
measuring the L3 occupancy at intervals. The test passes if the workload's
L3 occupancy is within 15% of the buffer size.

The CMT test does not take into account that some of the workload's data
may land in L2/L1. Matching L3 occupancy to the size of the buffer while
a portion of the buffer can be allocated into L2 is not accurate.

Take the L2 cache into account to improve test accuracy:
 - Reduce the workload's L2 cache allocation to the minimum on systems that
   support L2 cache allocation. Do so with a new utility in preparation for
   all L3 cache allocation tests needing the same capability.
 - Increase the buffer size to accommodate data that may be allocated into
   the L2 cache. Use a buffer size double the L3 portion to keep using the
   L3 portion size as goal for L3 occupancy while taking into account that
   some of the data may be in L2.

Running the CMT test on a sample system while introducing significant
cache misses using "stress-ng --matrix-3d 0 --matrix-3d-zyx" shows
significant improvement in L3 cache occupancy:

Before:

    # Starting CMT test ...
    # Mounting resctrl to "/sys/fs/resctrl"
    # Cache size :335544320
    # Writing benchmark parameters to resctrl FS
    # Write schema "L3:0=fffe0" to resctrl FS
    # Write schema "L3:0=1f" to resctrl FS
    # Benchmark PID: 7089
    # Checking for pass/fail
    # Pass: Check cache miss rate within 15%
    # Percent diff=12
    # Number of bits: 5
    # Average LLC val: 73269248
    # Cache span (bytes): 83886080
    ok 1 CMT: test

After:
    # Starting CMT test ...
    # Mounting resctrl to "/sys/fs/resctrl"
    # Cache size :335544320
    # Writing benchmark parameters to resctrl FS
    # Write schema "L3:0=fffe0" to resctrl FS
    # Write schema "L3:0=1f" to resctrl FS
    # Write schema "L2:1=0x1" to resctrl FS
    # Benchmark PID: 7171
    # Checking for pass/fail
    # Pass: Check cache miss rate within 15%
    # Percent diff=0
    # Number of bits: 5
    # Average LLC val: 83755008
    # Cache span (bytes): 83886080
    ok 1 CMT: test

Link: https://lore.kernel.org/r/00445fa64c251b86b86023f87220ee1ad8561460.1775266384.git.reinette.chatre@intel.com
Reported-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Chen Yu <yu.c.chen@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/lkml/aO+7MeSMV29VdbQs@e133380.arm.com/
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
tools/testing/selftests/resctrl/cache.c
tools/testing/selftests/resctrl/cmt_test.c
tools/testing/selftests/resctrl/resctrl.h

index 1ff1104e657531cf2ec42ba519ac56d98751553a..bef71b6feacc608fe4cdfb56f32357758a337b11 100644 (file)
@@ -173,6 +173,19 @@ int measure_llc_resctrl(const char *filename, pid_t bm_pid)
        return print_results_cache(filename, bm_pid, llc_occu_resc);
 }
 
+/*
+ * Reduce L2 allocation to minimum when testing L3 cache allocation.
+ */
+int minimize_l2_occupancy(const struct resctrl_test *test,
+                         const struct user_params *uparams,
+                         const struct resctrl_val_param *param)
+{
+       if (!strcmp(test->resource, "L3") && resctrl_resource_exists("L2"))
+               return write_schemata(param->ctrlgrp, "0x1", uparams->cpu, "L2");
+
+       return 0;
+}
+
 /*
  * show_cache_info - Show generic cache test information
  * @no_of_bits:                Number of bits
index 7bc6cf49c1c5b6da9dfb2df3bce9242d74513567..ccb6fe881a94837882fd6ec0e4a1b9559394f12e 100644 (file)
@@ -23,7 +23,9 @@
  * Initialize capacity bitmasks (CBMs) of:
  * - control group being tested per test parameters,
  * - default resource group as inverse of control group being tested to prevent
- *   other tasks from interfering with test.
+ *   other tasks from interfering with test,
+ * - L2 resource of control group being tested to minimize allocations into
+ *   L2 if possible to better predict L3 occupancy.
  */
 static int cmt_init(const struct resctrl_test *test,
                    const struct user_params *uparams,
@@ -46,7 +48,11 @@ static int cmt_init(const struct resctrl_test *test,
                return ret;
 
        snprintf(schemata, sizeof(schemata), "%lx", param->mask);
-       return write_schemata(param->ctrlgrp, schemata, uparams->cpu, test->resource);
+       ret = write_schemata(param->ctrlgrp, schemata, uparams->cpu, test->resource);
+       if (ret)
+               return ret;
+
+       return minimize_l2_occupancy(test, uparams, param);
 }
 
 static int cmt_setup(const struct resctrl_test *test,
@@ -175,11 +181,11 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param
        span = cache_portion_size(cache_total_size, param.mask, long_mask);
 
        if (uparams->fill_buf) {
-               fill_buf.buf_size = span;
+               fill_buf.buf_size = span * 2;
                fill_buf.memflush = uparams->fill_buf->memflush;
                param.fill_buf = &fill_buf;
        } else if (!uparams->benchmark_cmd[0]) {
-               fill_buf.buf_size = span;
+               fill_buf.buf_size = span * 2;
                fill_buf.memflush = true;
                param.fill_buf = &fill_buf;
        }
index c72045c74ac4f91c91903518f99fc727d963b7aa..7f2ab28be8571ac54f93552d08660746275053e3 100644 (file)
@@ -216,6 +216,9 @@ int perf_event_reset_enable(int pe_fd);
 int perf_event_measure(int pe_fd, struct perf_event_read *pe_read,
                       const char *filename, pid_t bm_pid);
 int measure_llc_resctrl(const char *filename, pid_t bm_pid);
+int minimize_l2_occupancy(const struct resctrl_test *test,
+                         const struct user_params *uparams,
+                         const struct resctrl_val_param *param);
 void show_cache_info(int no_of_bits, __u64 avg_llc_val, size_t cache_span, bool lines);
 
 /*