Skip to content

Commit 0b03ab7

Browse files
committed
tests: fix MMIO gaps in memory monitor tool
The memory monitor was only assuming a single MMIO gap on x86_64 when calculating the memory regions that corresponded to guest memory. Now we need to account for two MMIO gaps in x86 and one in ARM. Signed-off-by: Babis Chalios <[email protected]>
1 parent 1574ef7 commit 0b03ab7

File tree

1 file changed

+62
-15
lines changed

1 file changed

+62
-15
lines changed

tests/host_tools/memory.py

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import time
77
from threading import Thread
8+
from framework.properties import global_props
89

910
import psutil
1011

@@ -28,10 +29,20 @@ class MemoryMonitor(Thread):
2829
VMM memory usage.
2930
"""
3031

31-
# If guest memory is >3328MB, it is split in a 2nd region
32-
X86_MEMORY_GAP_START = 3328 * 2**20
33-
34-
def __init__(self, vm, threshold=5 * 2**20, period_s=0.05):
32+
# If guest memory is >3GiB, it is split in a 2nd region
33+
# Gap starts at 3GiBs and is 1GiB long
34+
X86_32BIT_MEMORY_GAP_START = 3 * 2**30
35+
X86_32BIT_MEMORY_GAP_SIZE = 1 * 2**30
36+
# If guest memory is >255GiB, it is split in a 3rd region
37+
# Gap starts at 256 GiB and is 256GiB long
38+
X86_64BIT_MEMORY_GAP_START = 256 * 2**30
39+
# On ARM64 we just have a single gap, but memory starts at an offset
40+
# Gap starts at 256 GiB and is GiB long
41+
# Memory starts at 2GiB
42+
ARM64_64BIT_MEMORY_GAP_START = 256 * 2**30
43+
ARM64_MEMORY_START = 2 * 2**30
44+
45+
def __init__(self, vm, threshold=5 * 2**20, period_s=0.01):
3546
"""Initialize monitor attributes."""
3647
Thread.__init__(self)
3748
self._vm = vm
@@ -71,8 +82,13 @@ def run(self):
7182
return
7283
mem_total = 0
7384
for mmap in mmaps:
85+
if mmap.size >= 512 * 2**20:
86+
print(f"Checking mmap region: {mmap}. VM memory: {guest_mem_bytes}")
87+
7488
if self.is_guest_mem(mmap.size, guest_mem_bytes):
89+
print(f"Region {mmap} is guest memory")
7590
continue
91+
7692
mem_total += mmap.rss
7793
self._current_rss = mem_total
7894
if mem_total > self.threshold:
@@ -81,24 +97,55 @@ def run(self):
8197

8298
time.sleep(self._period_s)
8399

84-
def is_guest_mem(self, size, guest_mem_bytes):
100+
def is_guest_mem_x86(self, size, guest_mem_bytes):
85101
"""
86-
If the address is recognised as a guest memory region,
87-
return True, otherwise return False.
102+
Checks if a region is a guest memory region based on
103+
x86_64 physical memory layout
88104
"""
105+
return size in (
106+
# memory fits before the first gap
107+
guest_mem_bytes,
108+
# guest memory spans at least two regions & memory fits before the second gap
109+
self.X86_32BIT_MEMORY_GAP_START,
110+
# guest memory spans exactly two regions
111+
guest_mem_bytes - self.X86_32BIT_MEMORY_GAP_START,
112+
# guest memory fills the space between the two gaps
113+
self.X86_64BIT_MEMORY_GAP_START
114+
- self.X86_32BIT_MEMORY_GAP_START
115+
- self.X86_32BIT_MEMORY_GAP_SIZE,
116+
# guest memory spans 3 regions, this is what remains past the second gap
117+
guest_mem_bytes
118+
- self.X86_64BIT_MEMORY_GAP_START
119+
+ self.X86_32BIT_MEMORY_GAP_SIZE,
120+
)
89121

90-
# If x86_64 guest memory exceeds 3328M, it will be split
91-
# in 2 regions: 3328M and the rest. We have 3 cases here
92-
# to recognise a guest memory region:
93-
# - its size matches the guest memory exactly
94-
# - its size is 3328M
95-
# - its size is guest memory minus 3328M.
122+
def is_guest_mem_arch64(self, size, guest_mem_bytes):
123+
"""
124+
Checks if a region is a guest memory region based on
125+
ARM64 physical memory layout
126+
"""
96127
return size in (
128+
# guest memory fits before the gap
97129
guest_mem_bytes,
98-
self.X86_MEMORY_GAP_START,
99-
guest_mem_bytes - self.X86_MEMORY_GAP_START,
130+
# guest memory fills the space before the gap
131+
self.ARM64_64BIT_MEMORY_GAP_START - self.ARM64_MEMORY_START,
132+
# guest memory spans 2 regions, this is what remains past the gap
133+
guest_mem_bytes
134+
- self.ARM64_64BIT_MEMORY_GAP_START
135+
+ self.ARM64_MEMORY_START,
100136
)
101137

138+
def is_guest_mem(self, size, guest_mem_bytes):
139+
"""
140+
If the address is recognised as a guest memory region,
141+
return True, otherwise return False.
142+
"""
143+
144+
if global_props.cpu_architecture == "x86_64":
145+
return self.is_guest_mem_x86(size, guest_mem_bytes)
146+
147+
return self.is_guest_mem_arch64(size, guest_mem_bytes)
148+
102149
def check_samples(self):
103150
"""Check that there are no samples over the threshold."""
104151
if self._exceeded is not None:

0 commit comments

Comments
 (0)