66from framework import utils
77from framework .microvm import HugePagesConfig
88from framework .properties import global_props
9+ from integration_tests .functional .test_uffd import SOCKET_PATH , spawn_pf_handler
910
1011
11- def check_hugetlbfs_in_use (pid ):
12- """Asserts that the process with the given pid is using hugetlbfs pages somewhere"""
12+ def check_hugetlbfs_in_use (pid : int , allocation_name : str ):
13+ """Asserts that the process with the given ` pid` is using hugetlbfs pages somewhere.
1314
14- # Format of a smaps entry:
15+ `allocation_name` should be the name of the smaps entry for which we want to verify that huge pages are used.
16+ For memfd-backed guest memory, this would be "memfd:guest_mem", for anonymous memory this would be "/anon_hugepage"
17+ """
18+
19+ # Format of a sample smaps entry:
1520 # 7fc2bc400000-7fc2cc400000 rw-s 00000000 00:10 25488401 /memfd:guest_mem (deleted)
1621 # Size: 262144 kB
1722 # KernelPageSize: 2048 kB
@@ -37,7 +42,7 @@ def check_hugetlbfs_in_use(pid):
3742 # THPeligible: 0
3843 # ProtectionKey: 0
3944 # the "memfd:guest_mem" is the identifier of our guest memory. It is memfd backed, with the memfd being called "guest_mem" in memory.rs
40- cmd = f"cat /proc/{ pid } /smaps | grep memfd:guest_mem -A 23 | grep KernelPageSize"
45+ cmd = f"cat /proc/{ pid } /smaps | grep { allocation_name } -A 23 | grep KernelPageSize"
4146 _ , stdout , _ = utils .run_cmd (cmd )
4247
4348 kernel_page_size_kib = int (stdout .split ()[1 ])
@@ -59,4 +64,51 @@ def test_hugetlbfs_boot(uvm_plain):
5964 rc , _ , _ = uvm_plain .ssh .run ("true" )
6065 assert not rc
6166
62- check_hugetlbfs_in_use (uvm_plain .firecracker_pid )
67+ check_hugetlbfs_in_use (uvm_plain .firecracker_pid , "memfd:guest_mem" )
68+
69+
70+ @pytest .mark .skipif (
71+ global_props .host_linux_version == "4.14" ,
72+ reason = "MFD_HUGETLB | MFD_ALLOW_SEALING only supported on kernels >= 4.16" ,
73+ )
74+ def test_hugetlbfs_snapshot (
75+ microvm_factory , guest_kernel_linux_5_10 , rootfs_ubuntu_22 , uffd_handler_paths
76+ ):
77+ """
78+ Test hugetlbfs snapshot restore via uffd
79+ """
80+
81+ ### Create Snapshot ###
82+ vm = microvm_factory .build (guest_kernel_linux_5_10 , rootfs_ubuntu_22 )
83+ vm .memory_monitor = None
84+ vm .spawn ()
85+ vm .basic_config (huge_pages = HugePagesConfig .HUGETLBFS_2MB , mem_size_mib = 128 )
86+ vm .add_net_iface ()
87+ vm .start ()
88+
89+ # Wait for microvm to boot
90+ rc , _ , _ = vm .ssh .run ("true" )
91+ assert not rc
92+
93+ check_hugetlbfs_in_use (vm .firecracker_pid , "memfd:guest_mem" )
94+
95+ snapshot = vm .snapshot_full ()
96+
97+ vm .kill ()
98+
99+ ### Restore Snapshot ###
100+ vm = microvm_factory .build ()
101+ vm .spawn ()
102+
103+ # Spawn page fault handler process.
104+ _pf_handler = spawn_pf_handler (
105+ vm , uffd_handler_paths ["valid_2m_handler" ], snapshot .mem
106+ )
107+
108+ vm .restore_from_snapshot (snapshot , resume = True , uffd_path = SOCKET_PATH )
109+
110+ # Verify if guest can run commands.
111+ rc , _ , _ = vm .ssh .run ("true" )
112+ assert not rc
113+
114+ check_hugetlbfs_in_use (vm .firecracker_pid , "/anon_hugepage" )
0 commit comments