22// SPDX-License-Identifier: Apache-2.0
33
44use std:: io:: { Seek , SeekFrom } ;
5+ use std:: sync:: { Arc , Mutex } ;
56use std:: thread;
67use std:: time:: Duration ;
78
@@ -15,7 +16,9 @@ use vmm::rpc_interface::{
1516use vmm:: seccomp:: get_empty_filters;
1617use vmm:: snapshot:: Snapshot ;
1718use vmm:: test_utils:: mock_resources:: { MockVmResources , NOISY_KERNEL_IMAGE } ;
18- use vmm:: test_utils:: { create_vmm, default_vmm, default_vmm_no_boot} ;
19+ use vmm:: test_utils:: {
20+ create_vmm, default_vmm, default_vmm_no_boot, default_vmm_pci, default_vmm_pci_no_boot,
21+ } ;
1922use vmm:: vmm_config:: balloon:: BalloonDeviceConfig ;
2023use vmm:: vmm_config:: boot_source:: BootSourceConfig ;
2124use vmm:: vmm_config:: drive:: BlockDeviceConfig ;
@@ -26,9 +29,23 @@ use vmm::vmm_config::snapshot::{
2629 CreateSnapshotParams , LoadSnapshotParams , MemBackendConfig , MemBackendType , SnapshotType ,
2730} ;
2831use vmm:: vmm_config:: vsock:: VsockDeviceConfig ;
29- use vmm:: { DumpCpuConfigError , EventManager , FcExitCode } ;
32+ use vmm:: { DumpCpuConfigError , EventManager , FcExitCode , Vmm } ;
3033use vmm_sys_util:: tempfile:: TempFile ;
3134
35+ fn check_booted_microvm ( vmm : Arc < Mutex < Vmm > > , mut evmgr : EventManager ) {
36+ // On x86_64, the vmm should exit once its workload completes and signals the exit event.
37+ // On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
38+ #[ cfg( target_arch = "x86_64" ) ]
39+ evmgr. run_with_timeout ( 500 ) . unwrap ( ) ;
40+ #[ cfg( target_arch = "aarch64" ) ]
41+ vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
42+
43+ assert_eq ! (
44+ vmm. lock( ) . unwrap( ) . shutdown_exit_code( ) ,
45+ Some ( FcExitCode :: Ok )
46+ ) ;
47+ }
48+
3249#[ test]
3350fn test_build_and_boot_microvm ( ) {
3451 // Error case: no boot source configured.
@@ -47,33 +64,24 @@ fn test_build_and_boot_microvm() {
4764 }
4865
4966 // Success case.
50- let ( vmm, mut _evmgr) = default_vmm ( None ) ;
67+ let ( vmm, evmgr) = default_vmm ( None ) ;
68+ check_booted_microvm ( vmm, evmgr) ;
5169
52- // On x86_64, the vmm should exit once its workload completes and signals the exit event.
53- // On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
54- #[ cfg( target_arch = "x86_64" ) ]
55- _evmgr. run_with_timeout ( 500 ) . unwrap ( ) ;
56- #[ cfg( target_arch = "aarch64" ) ]
57- vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
58-
59- assert_eq ! (
60- vmm. lock( ) . unwrap( ) . shutdown_exit_code( ) ,
61- Some ( FcExitCode :: Ok )
62- ) ;
70+ // microVM with PCI
71+ let ( vmm, evmgr) = default_vmm_pci ( None ) ;
72+ check_booted_microvm ( vmm, evmgr) ;
6373}
6474
65- #[ test]
66- fn test_build_microvm ( ) {
75+ fn check_build_microvm ( vmm : Arc < Mutex < Vmm > > , mut evmgr : EventManager ) {
6776 // The built microVM should be in the `VmState::Paused` state here.
68- let ( vmm, mut _evtmgr) = default_vmm_no_boot ( None ) ;
6977 assert_eq ! ( vmm. lock( ) . unwrap( ) . instance_info( ) . state, VmState :: Paused ) ;
7078
7179 // The microVM should be able to resume and exit successfully.
7280 // On x86_64, the vmm should exit once its workload completes and signals the exit event.
7381 // On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
7482 vmm. lock ( ) . unwrap ( ) . resume_vm ( ) . unwrap ( ) ;
7583 #[ cfg( target_arch = "x86_64" ) ]
76- _evtmgr . run_with_timeout ( 500 ) . unwrap ( ) ;
84+ evmgr . run_with_timeout ( 500 ) . unwrap ( ) ;
7785 #[ cfg( target_arch = "aarch64" ) ]
7886 vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
7987 assert_eq ! (
@@ -83,10 +91,14 @@ fn test_build_microvm() {
8391}
8492
8593#[ test]
86- fn test_pause_resume_microvm ( ) {
87- // Tests that pausing and resuming a microVM work as expected.
88- let ( vmm, _) = default_vmm ( None ) ;
94+ fn test_build_microvm ( ) {
95+ let ( vmm, evtmgr) = default_vmm_no_boot ( None ) ;
96+ check_build_microvm ( vmm, evtmgr) ;
97+ let ( vmm, evtmgr) = default_vmm_pci_no_boot ( None ) ;
98+ check_build_microvm ( vmm, evtmgr) ;
99+ }
89100
101+ fn pause_resume_microvm ( vmm : Arc < Mutex < Vmm > > ) {
90102 let mut api_controller = RuntimeApiController :: new ( VmResources :: default ( ) , vmm. clone ( ) ) ;
91103
92104 // There's a race between this thread and the vcpu thread, but this thread
@@ -100,6 +112,17 @@ fn test_pause_resume_microvm() {
100112 vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
101113}
102114
115+ #[ test]
116+ fn test_pause_resume_microvm ( ) {
117+ // Tests that pausing and resuming a microVM work as expected.
118+ let ( vmm, _) = default_vmm ( None ) ;
119+
120+ pause_resume_microvm ( vmm) ;
121+
122+ let ( vmm, _) = default_vmm_pci ( None ) ;
123+ pause_resume_microvm ( vmm) ;
124+ }
125+
103126#[ test]
104127fn test_dirty_bitmap_error ( ) {
105128 // Error case: dirty tracking disabled.
@@ -185,11 +208,11 @@ fn test_disallow_dump_cpu_config_without_pausing() {
185208 vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
186209}
187210
188- fn verify_create_snapshot ( is_diff : bool ) -> ( TempFile , TempFile ) {
211+ fn verify_create_snapshot ( is_diff : bool , pci_enabled : bool ) -> ( TempFile , TempFile ) {
189212 let snapshot_file = TempFile :: new ( ) . unwrap ( ) ;
190213 let memory_file = TempFile :: new ( ) . unwrap ( ) ;
191214
192- let ( vmm, _) = create_vmm ( Some ( NOISY_KERNEL_IMAGE ) , is_diff, true ) ;
215+ let ( vmm, _) = create_vmm ( Some ( NOISY_KERNEL_IMAGE ) , is_diff, true , pci_enabled ) ;
193216 let resources = VmResources {
194217 machine_config : MachineConfig {
195218 mem_size_mib : 1 ,
@@ -296,29 +319,27 @@ fn verify_load_snapshot(snapshot_file: TempFile, memory_file: TempFile) {
296319
297320#[ test]
298321fn test_create_and_load_snapshot ( ) {
299- // Create diff snapshot.
300- let ( snapshot_file, memory_file) = verify_create_snapshot ( true ) ;
301- // Create a new microVm from snapshot. This only tests code-level logic; it verifies
302- // that a microVM can be built with no errors from given snapshot.
303- // It does _not_ verify that the guest is actually restored properly. We're using
304- // python integration tests for that.
305- verify_load_snapshot ( snapshot_file, memory_file) ;
306-
307- // Create full snapshot.
308- let ( snapshot_file, memory_file) = verify_create_snapshot ( false ) ;
309- // Create a new microVm from snapshot. This only tests code-level logic; it verifies
310- // that a microVM can be built with no errors from given snapshot.
311- // It does _not_ verify that the guest is actually restored properly. We're using
312- // python integration tests for that.
313- verify_load_snapshot ( snapshot_file, memory_file) ;
322+ for ( diff_snap, pci_enabled) in [ ( false , false ) , ( false , true ) , ( true , false ) , ( true , true ) ] {
323+ // Create snapshot.
324+ let ( snapshot_file, memory_file) = verify_create_snapshot ( diff_snap, pci_enabled) ;
325+ // Create a new microVm from snapshot. This only tests code-level logic; it verifies
326+ // that a microVM can be built with no errors from given snapshot.
327+ // It does _not_ verify that the guest is actually restored properly. We're using
328+ // python integration tests for that.
329+ verify_load_snapshot ( snapshot_file, memory_file) ;
330+ }
314331}
315332
316333#[ test]
317334fn test_snapshot_load_sanity_checks ( ) {
318- use vmm:: persist:: SnapShotStateSanityCheckError ;
319-
320- let mut microvm_state = get_microvm_state_from_snapshot ( ) ;
335+ let microvm_state = get_microvm_state_from_snapshot ( false ) ;
336+ check_snapshot ( microvm_state) ;
337+ let microvm_state = get_microvm_state_from_snapshot ( true ) ;
338+ check_snapshot ( microvm_state) ;
339+ }
321340
341+ fn check_snapshot ( mut microvm_state : MicrovmState ) {
342+ use vmm:: persist:: SnapShotStateSanityCheckError ;
322343 snapshot_state_sanity_check ( & microvm_state) . unwrap ( ) ;
323344
324345 // Remove memory regions.
@@ -331,9 +352,9 @@ fn test_snapshot_load_sanity_checks() {
331352 ) ;
332353}
333354
334- fn get_microvm_state_from_snapshot ( ) -> MicrovmState {
355+ fn get_microvm_state_from_snapshot ( pci_enabled : bool ) -> MicrovmState {
335356 // Create a diff snapshot
336- let ( snapshot_file, _) = verify_create_snapshot ( true ) ;
357+ let ( snapshot_file, _) = verify_create_snapshot ( true , pci_enabled ) ;
337358
338359 // Deserialize the microVM state.
339360 let snapshot_file_metadata = snapshot_file. as_file ( ) . metadata ( ) . unwrap ( ) ;
@@ -344,7 +365,7 @@ fn get_microvm_state_from_snapshot() -> MicrovmState {
344365}
345366
346367fn verify_load_snap_disallowed_after_boot_resources ( res : VmmAction , res_name : & str ) {
347- let ( snapshot_file, memory_file) = verify_create_snapshot ( false ) ;
368+ let ( snapshot_file, memory_file) = verify_create_snapshot ( false , false ) ;
348369
349370 let mut event_manager = EventManager :: new ( ) . unwrap ( ) ;
350371 let empty_seccomp_filters = get_empty_filters ( ) ;
0 commit comments