Skip to content

Commit eb32522

Browse files
[AI Generated] BugFix: Handle missing cache topology in lscpu output for verify_l3_cache
1 parent 96869b7 commit eb32522

2 files changed

Lines changed: 54 additions & 15 deletions

File tree

lisa/microsoft/testsuites/core/cpu.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ def verify_l3_cache(
121121
# For all other cases, check L3 cache mapping with socket awareness
122122
cpu_info = lscpu.get_cpu_info()
123123

124+
# On some VMs (e.g. confidential VMs), cache topology is not exposed
125+
# by the hypervisor, so lscpu reports "-" for all cache values.
126+
# In this case, we cannot verify L3 cache mapping.
127+
if any(cpu.l3_cache == -1 for cpu in cpu_info):
128+
raise SkippedException(
129+
"Cache topology is not exposed on this VM. "
130+
"lscpu reports no cache information (likely a confidential VM "
131+
"or a VM size that does not expose cache topology to the guest)."
132+
)
133+
124134
# Build a mapping of socket -> NUMA nodes and socket -> L3 caches
125135
socket_to_numa_nodes: dict[int, set[int]] = {}
126136
socket_to_l3_caches: dict[int, set[int]] = {}
@@ -299,6 +309,11 @@ def _create_stimer_interrupts(self, node: Node, cpu_count: int) -> None:
299309

300310
def _verify_node_mapping(self, node: Node, numa_node_size: int) -> None:
301311
cpu_info = node.tools[Lscpu].get_cpu_info()
312+
if any(cpu.l3_cache == -1 for cpu in cpu_info):
313+
raise SkippedException(
314+
"Cache topology is not exposed on this VM. "
315+
"lscpu reports no cache information."
316+
)
302317
cpu_info.sort(key=lambda cpu: cpu.cpu)
303318
for i, cpu in enumerate(cpu_info):
304319
numa_node_id = i // numa_node_size

lisa/tools/lscpu.py

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ class Lscpu(Tool):
9191
r"(?P<l1_data_cache>\d+):(?P<l1_instruction_cache>\d+):"
9292
r"(?P<l2_cache>\d+):(?P<l3_cache>\d+)$"
9393
)
94+
# On some VMs (e.g. confidential VMs), cache topology is not exposed
95+
# and lscpu outputs "-" instead of cache IDs:
96+
# 0 0 0 -
97+
_core_numa_no_cache = re.compile(
98+
r"\s*(?P<cpu>\d+)\s+(?P<numa_node>\d+)\s+(?P<socket>\d+)\s+-$"
99+
)
94100
# Model name: Intel(R) Xeon(R) Platinum 8168 CPU @ 2.70GHz
95101
# Model name: AMD EPYC 7763 64-Core Processor
96102
# Model name: AMD EPYC 7763 64-Core Processor
@@ -267,6 +273,10 @@ def get_cpu_info(self) -> List[CPUInfo]:
267273
# CPU NODE SOCKET L1d:L1i:L2:L3
268274
# 0 0 0 0:0:0:0
269275
# 1 0 0 0:0:0:0
276+
#
277+
# On some VMs (e.g. confidential VMs), cache topology is not exposed:
278+
# CPU NODE SOCKET CACHE
279+
# 0 0 0 -
270280
result = self.run(
271281
"--extended=cpu,node,socket,cache", expected_exit_code=0
272282
).stdout
@@ -278,22 +288,36 @@ def get_cpu_info(self) -> List[CPUInfo]:
278288
output: List[CPUInfo] = []
279289
for item in mappings:
280290
match_result = self._core_numa_mappings.fullmatch(item)
281-
assert (
282-
match_result
283-
), f"lscpu NUMA node mapping is not in expected format: {item}"
284-
output.append(
285-
CPUInfo(
286-
cpu=int(match_result.group("cpu")),
287-
numa_node=int(match_result.group("numa_node")),
288-
socket=int(match_result.group("socket")),
289-
l1_data_cache=int(match_result.group("l1_data_cache")),
290-
l1_instruction_cache=int(
291-
match_result.group("l1_instruction_cache")
292-
),
293-
l2_cache=int(match_result.group("l2_cache")),
294-
l3_cache=int(match_result.group("l3_cache")),
291+
if match_result:
292+
output.append(
293+
CPUInfo(
294+
cpu=int(match_result.group("cpu")),
295+
numa_node=int(match_result.group("numa_node")),
296+
socket=int(match_result.group("socket")),
297+
l1_data_cache=int(match_result.group("l1_data_cache")),
298+
l1_instruction_cache=int(
299+
match_result.group("l1_instruction_cache")
300+
),
301+
l2_cache=int(match_result.group("l2_cache")),
302+
l3_cache=int(match_result.group("l3_cache")),
303+
)
295304
)
296-
)
305+
continue
306+
no_cache_match = self._core_numa_no_cache.fullmatch(item)
307+
if no_cache_match:
308+
output.append(
309+
CPUInfo(
310+
cpu=int(no_cache_match.group("cpu")),
311+
numa_node=int(no_cache_match.group("numa_node")),
312+
socket=int(no_cache_match.group("socket")),
313+
l1_data_cache=-1,
314+
l1_instruction_cache=-1,
315+
l2_cache=-1,
316+
l3_cache=-1,
317+
)
318+
)
319+
continue
320+
assert False, f"lscpu NUMA node mapping is not in expected format: {item}"
297321
return output
298322

299323
def get_numa_node_count(self) -> int:

0 commit comments

Comments
 (0)