88
99import psutil
1010
11+ from framework .properties import global_props
12+
1113
1214class MemoryUsageExceededError (Exception ):
1315 """A custom exception containing details on excessive memory usage."""
@@ -28,10 +30,20 @@ class MemoryMonitor(Thread):
2830 VMM memory usage.
2931 """
3032
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 ):
33+ # If guest memory is >3GiB, it is split in a 2nd region
34+ # Gap starts at 3GiBs and is 1GiB long
35+ X86_32BIT_MEMORY_GAP_START = 3 * 2 ** 30
36+ X86_32BIT_MEMORY_GAP_SIZE = 1 * 2 ** 30
37+ # If guest memory is >255GiB, it is split in a 3rd region
38+ # Gap starts at 256 GiB and is 256GiB long
39+ X86_64BIT_MEMORY_GAP_START = 256 * 2 ** 30
40+ # On ARM64 we just have a single gap, but memory starts at an offset
41+ # Gap starts at 256 GiB and is GiB long
42+ # Memory starts at 2GiB
43+ ARM64_64BIT_MEMORY_GAP_START = 256 * 2 ** 30
44+ ARM64_MEMORY_START = 2 * 2 ** 30
45+
46+ def __init__ (self , vm , threshold = 5 * 2 ** 20 , period_s = 0.01 ):
3547 """Initialize monitor attributes."""
3648 Thread .__init__ (self )
3749 self ._vm = vm
@@ -71,8 +83,13 @@ def run(self):
7183 return
7284 mem_total = 0
7385 for mmap in mmaps :
86+ if mmap .size >= 512 * 2 ** 20 :
87+ print (f"Checking mmap region: { mmap } . VM memory: { guest_mem_bytes } " )
88+
7489 if self .is_guest_mem (mmap .size , guest_mem_bytes ):
90+ print (f"Region { mmap } is guest memory" )
7591 continue
92+
7693 mem_total += mmap .rss
7794 self ._current_rss = mem_total
7895 if mem_total > self .threshold :
@@ -81,24 +98,55 @@ def run(self):
8198
8299 time .sleep (self ._period_s )
83100
84- def is_guest_mem (self , size , guest_mem_bytes ):
101+ def is_guest_mem_x86 (self , size , guest_mem_bytes ):
85102 """
86- If the address is recognised as a guest memory region,
87- return True, otherwise return False.
103+ Checks if a region is a guest memory region based on
104+ x86_64 physical memory layout
88105 """
106+ return size in (
107+ # memory fits before the first gap
108+ guest_mem_bytes ,
109+ # guest memory spans at least two regions & memory fits before the second gap
110+ self .X86_32BIT_MEMORY_GAP_START ,
111+ # guest memory spans exactly two regions
112+ guest_mem_bytes - self .X86_32BIT_MEMORY_GAP_START ,
113+ # guest memory fills the space between the two gaps
114+ self .X86_64BIT_MEMORY_GAP_START
115+ - self .X86_32BIT_MEMORY_GAP_START
116+ - self .X86_32BIT_MEMORY_GAP_SIZE ,
117+ # guest memory spans 3 regions, this is what remains past the second gap
118+ guest_mem_bytes
119+ - self .X86_64BIT_MEMORY_GAP_START
120+ + self .X86_32BIT_MEMORY_GAP_SIZE ,
121+ )
89122
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.
123+ def is_guest_mem_arch64 (self , size , guest_mem_bytes ):
124+ """
125+ Checks if a region is a guest memory region based on
126+ ARM64 physical memory layout
127+ """
96128 return size in (
129+ # guest memory fits before the gap
97130 guest_mem_bytes ,
98- self .X86_MEMORY_GAP_START ,
99- guest_mem_bytes - self .X86_MEMORY_GAP_START ,
131+ # guest memory fills the space before the gap
132+ self .ARM64_64BIT_MEMORY_GAP_START - self .ARM64_MEMORY_START ,
133+ # guest memory spans 2 regions, this is what remains past the gap
134+ guest_mem_bytes
135+ - self .ARM64_64BIT_MEMORY_GAP_START
136+ + self .ARM64_MEMORY_START ,
100137 )
101138
139+ def is_guest_mem (self , size , guest_mem_bytes ):
140+ """
141+ If the address is recognised as a guest memory region,
142+ return True, otherwise return False.
143+ """
144+
145+ if global_props .cpu_architecture == "x86_64" :
146+ return self .is_guest_mem_x86 (size , guest_mem_bytes )
147+
148+ return self .is_guest_mem_arch64 (size , guest_mem_bytes )
149+
102150 def check_samples (self ):
103151 """Check that there are no samples over the threshold."""
104152 if self ._exceeded is not None :
0 commit comments