[PATCH 6/7] rteval: Add --warn-non-isolated-core-sharing option for measurement vs load warnings

John Kacur <[email protected]> Tue, 21 Apr 2026 14:26:17 -0400
Newsgroups org.kernel.vger.linux-rt-users
Message-ID <[email protected]>
Add a new command-line flag --warn-non-isolated-core-sharing that enables
warnings when measurement and load CPUs share physical cores even when
neither CPU is isolated.

By default, rteval only warns about core sharing when at least one of the
sharing CPUs is isolated (via isolcpus). This is the most critical case
because isolated CPUs are explicitly intended for dedicated workloads, and
sharing cores defeats the isolation.

However, even when CPUs are not isolated, running measurement and load
threads on sibling CPUs sharing a physical core can still impact
measurement accuracy due to shared execution resources (L1/L2 caches,
execution units, TLB, etc.). This new flag allows users to detect this
situation when they want stricter validation.

The flag only affects measurement vs load checking. Housekeeping vs
measurement and housekeeping vs load continue to warn only when at least
one CPU is isolated, as housekeeping tasks are expected to run on
non-isolated CPUs.

Example usage:
  rteval --measurement-cpulist 4 --loads-cpulist 12 \
         --warn-non-isolated-core-sharing

  Warning: Measurement CPU 4 shares core with load CPU 12

Implementation:
- rteval-cmd: Add --warn-non-isolated-core-sharing argument
- systopology.py: Add warn_non_isolated parameter to validate_core_sharing()
- check_pair(): Add check_type parameter to distinguish measurement_vs_load
  from other combinations and apply different warning logic

Assisted-by: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: John Kacur <[email protected]>
---
 rteval-cmd            |  6 +++++-
 rteval/systopology.py | 23 ++++++++++++++++-------
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/rteval-cmd b/rteval-cmd
index b3f9fac2c2cf..3180e1a7857a 100755
--- a/rteval-cmd
+++ b/rteval-cmd
@@ -116,6 +116,9 @@ def parse_options(cfg, parser, cmdargs):
     parser.add_argument("--housekeeping", dest="rteval___housekeeping",
                       type=str, default="", metavar="CPULIST",
                       help="isolated CPUs reserved for system tasks (not used by rteval)")
+    parser.add_argument("--warn-non-isolated-core-sharing", dest="rteval___warn_non_isolated_core_sharing",
+                      action="store_true", default=False,
+                      help="warn about measurement and load CPUs sharing cores even when neither is isolated")
     parser.add_argument("-s", "--sysreport", dest="rteval___sysreport",
                       action="store_true", default=rtevcfg.sysreport,
                       help=f'run sysreport to collect system data (default: {rtevcfg.sysreport})')
@@ -449,7 +452,8 @@ if __name__ == '__main__':
         # Validate core sharing between housekeeping, measurement, and load CPUs
         msrcfg_cpus = CpuList(msrcfg.cpulist).cpus if msrcfg.cpulist else []
         ldcfg_cpus = CpuList(ldcfg.cpulist).cpus if ldcfg.cpulist else []
-        core_warnings = validate_core_sharing(housekeeping_cpus, msrcfg_cpus, ldcfg_cpus)
+        core_warnings = validate_core_sharing(housekeeping_cpus, msrcfg_cpus, ldcfg_cpus,
+                                              cmd_opts.rteval___warn_non_isolated_core_sharing)
         for warning in core_warnings:
             logger.log(Log.WARN, warning)
 
diff --git a/rteval/systopology.py b/rteval/systopology.py
index 0ee81d5c5e36..0e4eb5fe7b89 100644
--- a/rteval/systopology.py
+++ b/rteval/systopology.py
@@ -294,7 +294,7 @@ def parse_cpulist_from_config(cpulist, run_on_isolcpus=False):
     return result
 
 
-def validate_core_sharing(housekeeping_cpus, measurement_cpus, load_cpus):
+def validate_core_sharing(housekeeping_cpus, measurement_cpus, load_cpus, warn_non_isolated=False):
     """
     Check for CPUs sharing physical cores across different workload types.
     Warns if isolated CPUs share cores between housekeeping, measurement, and load groups.
@@ -302,6 +302,7 @@ def validate_core_sharing(housekeeping_cpus, measurement_cpus, load_cpus):
     :param housekeeping_cpus: List of housekeeping CPU integers
     :param measurement_cpus: List of measurement CPU integers
     :param load_cpus: List of load CPU integers
+    :param warn_non_isolated: If True, also warn about measurement vs load sharing even when neither is isolated
     :return: List of warning messages (empty if no issues)
     """
     from rteval.sysinfo.coresiblings import CoreSiblings
@@ -318,14 +319,22 @@ def validate_core_sharing(housekeeping_cpus, measurement_cpus, load_cpus):
         # If we can't read topology, skip validation
         return warnings
 
-    def check_pair(cpu1, cpu2, type1, type2):
+    def check_pair(cpu1, cpu2, type1, type2, check_type):
         """Check if two CPUs share a core and generate warning if at least one is isolated"""
         if cs.share_core(cpu1, cpu2):
             cpu1_isol = cpu1 in isolated_cpus
             cpu2_isol = cpu2 in isolated_cpus
 
-            # Only warn if at least one CPU is isolated
-            if cpu1_isol or cpu2_isol:
+            # Determine if we should warn based on check_type
+            should_warn = False
+            if check_type == "measurement_vs_load" and warn_non_isolated:
+                # For measurement vs load with flag set: warn if neither is isolated
+                should_warn = not cpu1_isol and not cpu2_isol
+            else:
+                # For all other cases: only warn if at least one CPU is isolated
+                should_warn = cpu1_isol or cpu2_isol
+
+            if should_warn:
                 cpu1_str = f"{type1} CPU {cpu1}{' (isol)' if cpu1_isol else ''}"
                 cpu2_str = f"{type2} CPU {cpu2}{' (isol)' if cpu2_isol else ''}"
                 warnings.append(f"Warning: {cpu1_str} shares core with {cpu2_str}")
@@ -334,17 +343,17 @@ def validate_core_sharing(housekeeping_cpus, measurement_cpus, load_cpus):
     # 1. Housekeeping vs Measurement
     for hk_cpu in housekeeping_cpus:
         for msr_cpu in measurement_cpus:
-            check_pair(hk_cpu, msr_cpu, "Housekeeping", "measurement")
+            check_pair(hk_cpu, msr_cpu, "Housekeeping", "measurement", "housekeeping_vs_measurement")
 
     # 2. Housekeeping vs Load
     for hk_cpu in housekeeping_cpus:
         for ld_cpu in load_cpus:
-            check_pair(hk_cpu, ld_cpu, "Housekeeping", "load")
+            check_pair(hk_cpu, ld_cpu, "Housekeeping", "load", "housekeeping_vs_load")
 
     # 3. Measurement vs Load
     for msr_cpu in measurement_cpus:
         for ld_cpu in load_cpus:
-            check_pair(msr_cpu, ld_cpu, "Measurement", "load")
+            check_pair(msr_cpu, ld_cpu, "Measurement", "load", "measurement_vs_load")
 
     return warnings
 
-- 
2.53.0