[PATCH 3/7] rteval: Include core sharing warnings in XML report

John Kacur
2026-04-21T18:26:42Z

Add core sharing validation warnings to the CPUtopology section of the
XML report, making isolation issues part of the permanent test record.

This complements the console warnings added in the previous commit by
ensuring that core sharing conflicts are documented in the XML output,
allowing users to analyze test runs later even if they missed the
console warnings during execution.

Implementation:
- CPUtopology.add_core_sharing_warnings(): New method to add warnings
to the CPUtopology XML node after CPU lists are finalized
- rteval-cmd: Call add_core_sharing_warnings() after RtEval object is
created and CPU lists are available
- XML structure: CoreSharingWarnings appears at the end of CPUtopology
node, after all CPU entries and summary properties

Note: The warnings must be added after SystemInfo initialization because
CPU lists are finalized in rteval-cmd after the config is processed,
which happens after SystemInfo is created. We call the method explicitly
once the CPU lists are known.

Example XML output:
<CPUtopology num_cpu_cores="16" ...>
<cpu name="cpu0" ... isolated="1"/>
<cpu name="cpu8" ... isolated="1"/>
...
<CoreSharingWarnings>
<warning>Warning: Housekeeping CPU 0 (isol) shares core with measurement CPU 8 (isol)</warning>
</CoreSharingWarnings>
</CPUtopology>

The warnings use the same format as console output, clearly indicating
which CPUs are isolated with "(isol)" markers.

Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: John Kacur <jkacur@redhat.com>
---
rteval-cmd | 13 +++++++++----
rteval/sysinfo/__init__.py | 3 +++
rteval/sysinfo/cputopology.py | 33 +++++++++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/rteval-cmd b/rteval-cmd
index f0efb0117726..b3f9fac2c2cf 100755
--- a/rteval-cmd
+++ b/rteval-cmd
@@ -447,10 +447,11 @@ if __name__ == '__main__':
logger.log(Log.DEBUG, f"workdir: {rtevcfg.workdir}")

# Validate core sharing between housekeeping, measurement, and load CPUs
- if housekeeping_cpus or msrcfg_cpus or ldcfg_cpus:
- core_warnings = validate_core_sharing(housekeeping_cpus, msrcfg_cpus, ldcfg_cpus)
- for warning in core_warnings:
- logger.log(Log.WARN, warning)
+ 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)
+ for warning in core_warnings:
+ logger.log(Log.WARN, warning)

# if --summarize was specified then just parse the XML, print it and exit
if cmd_opts.rteval___summarize:
@@ -487,6 +488,10 @@ if __name__ == '__main__':
cpupower_controller.enable_idle_state()

rteval = RtEval(config, loadmods, measuremods, logger)
+
+ # Add core sharing warnings to the XML report now that CPU lists are finalized
+ rteval._sysinfo.add_core_sharing_warnings(housekeeping_cpus, msrcfg_cpus, ldcfg_cpus)
+
rteval.Prepare(rtevcfg.onlyload)

if rtevcfg.onlyload:
diff --git a/rteval/sysinfo/__init__.py b/rteval/sysinfo/__init__.py
index 4b7b03cda626..56a0c57b2cbc 100644
--- a/rteval/sysinfo/__init__.py
+++ b/rteval/sysinfo/__init__.py
@@ -35,6 +35,9 @@ class SystemInfo(KernelInfo, SystemServices, dmi.DMIinfo, CPUtopology,
self.ProcessWarnings()

# Parse CPU info
+ # Note: CPU lists are not available at this point (they're finalized in rteval-cmd),
+ # so we can't add core sharing warnings to the XML report yet.
+ # Console warnings are still generated in rteval-cmd.
CPUtopology._parse(self)

diff --git a/rteval/sysinfo/cputopology.py b/rteval/sysinfo/cputopology.py
index db30635a0488..a21c19179f28 100644
--- a/rteval/sysinfo/cputopology.py
+++ b/rteval/sysinfo/cputopology.py
@@ -94,6 +94,39 @@ class CPUtopology:
return self.__cputop_n

+ def add_core_sharing_warnings(self, housekeeping_cpus, measurement_cpus, load_cpus):
+ """
+ Add core sharing warnings to the CPUtopology XML node.
+ Should be called after CPU lists are finalized.
+
+ :param housekeeping_cpus: List of housekeeping CPU integers
+ :param measurement_cpus: List of measurement CPU integers
+ :param load_cpus: List of load CPU integers
+ """
+ if self.__cputop_n is None:
+ return
+
+ # Remove any existing CoreSharingWarnings section
+ existing = self.__cputop_n.xpathEval('CoreSharingWarnings')
+ if existing:
+ for node in existing:
+ node.unlinkNode()
+ node.freeNode()
+
+ # Generate new warnings
+ from rteval.systopology import validate_core_sharing
+ warnings = validate_core_sharing(
+ housekeeping_cpus or [],
+ measurement_cpus or [],
+ load_cpus or []
+ )
+
+ # Add warnings to XML if any were found
+ if warnings:
+ warnings_n = self.__cputop_n.newChild(None, 'CoreSharingWarnings', None)
+ for warning in warnings:
+ warnings_n.newChild(None, 'warning', warning)
+
def MakeReport(self):
return self.__cputop_n

--
2.53.0