2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
4
use std:: io:: { Seek , SeekFrom } ;
5
+ use std:: sync:: { Arc , Mutex } ;
5
6
use std:: thread;
6
7
use std:: time:: Duration ;
7
8
@@ -15,7 +16,9 @@ use vmm::rpc_interface::{
15
16
use vmm:: seccomp:: get_empty_filters;
16
17
use vmm:: snapshot:: Snapshot ;
17
18
use 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
+ } ;
19
22
use vmm:: vmm_config:: balloon:: BalloonDeviceConfig ;
20
23
use vmm:: vmm_config:: boot_source:: BootSourceConfig ;
21
24
use vmm:: vmm_config:: drive:: BlockDeviceConfig ;
@@ -26,9 +29,23 @@ use vmm::vmm_config::snapshot::{
26
29
CreateSnapshotParams , LoadSnapshotParams , MemBackendConfig , MemBackendType , SnapshotType ,
27
30
} ;
28
31
use vmm:: vmm_config:: vsock:: VsockDeviceConfig ;
29
- use vmm:: { DumpCpuConfigError , EventManager , FcExitCode } ;
32
+ use vmm:: { DumpCpuConfigError , EventManager , FcExitCode , Vmm } ;
30
33
use vmm_sys_util:: tempfile:: TempFile ;
31
34
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
+
32
49
#[ test]
33
50
fn test_build_and_boot_microvm ( ) {
34
51
// Error case: no boot source configured.
@@ -47,33 +64,24 @@ fn test_build_and_boot_microvm() {
47
64
}
48
65
49
66
// Success case.
50
- let ( vmm, mut _evmgr) = default_vmm ( None ) ;
67
+ let ( vmm, evmgr) = default_vmm ( None ) ;
68
+ check_booted_microvm ( vmm, evmgr) ;
51
69
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) ;
63
73
}
64
74
65
- #[ test]
66
- fn test_build_microvm ( ) {
75
+ fn check_build_microvm ( vmm : Arc < Mutex < Vmm > > , mut evmgr : EventManager ) {
67
76
// The built microVM should be in the `VmState::Paused` state here.
68
- let ( vmm, mut _evtmgr) = default_vmm_no_boot ( None ) ;
69
77
assert_eq ! ( vmm. lock( ) . unwrap( ) . instance_info( ) . state, VmState :: Paused ) ;
70
78
71
79
// The microVM should be able to resume and exit successfully.
72
80
// On x86_64, the vmm should exit once its workload completes and signals the exit event.
73
81
// On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
74
82
vmm. lock ( ) . unwrap ( ) . resume_vm ( ) . unwrap ( ) ;
75
83
#[ cfg( target_arch = "x86_64" ) ]
76
- _evtmgr . run_with_timeout ( 500 ) . unwrap ( ) ;
84
+ evmgr . run_with_timeout ( 500 ) . unwrap ( ) ;
77
85
#[ cfg( target_arch = "aarch64" ) ]
78
86
vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
79
87
assert_eq ! (
@@ -83,10 +91,14 @@ fn test_build_microvm() {
83
91
}
84
92
85
93
#[ 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
+ }
89
100
101
+ fn pause_resume_microvm ( vmm : Arc < Mutex < Vmm > > ) {
90
102
let mut api_controller = RuntimeApiController :: new ( VmResources :: default ( ) , vmm. clone ( ) ) ;
91
103
92
104
// There's a race between this thread and the vcpu thread, but this thread
@@ -100,6 +112,17 @@ fn test_pause_resume_microvm() {
100
112
vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
101
113
}
102
114
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
+
103
126
#[ test]
104
127
fn test_dirty_bitmap_error ( ) {
105
128
// Error case: dirty tracking disabled.
@@ -185,11 +208,11 @@ fn test_disallow_dump_cpu_config_without_pausing() {
185
208
vmm. lock ( ) . unwrap ( ) . stop ( FcExitCode :: Ok ) ;
186
209
}
187
210
188
- fn verify_create_snapshot ( is_diff : bool ) -> ( TempFile , TempFile ) {
211
+ fn verify_create_snapshot ( is_diff : bool , pci_enabled : bool ) -> ( TempFile , TempFile ) {
189
212
let snapshot_file = TempFile :: new ( ) . unwrap ( ) ;
190
213
let memory_file = TempFile :: new ( ) . unwrap ( ) ;
191
214
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 ) ;
193
216
let resources = VmResources {
194
217
machine_config : MachineConfig {
195
218
mem_size_mib : 1 ,
@@ -296,29 +319,27 @@ fn verify_load_snapshot(snapshot_file: TempFile, memory_file: TempFile) {
296
319
297
320
#[ test]
298
321
fn 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
+ }
314
331
}
315
332
316
333
#[ test]
317
334
fn 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
+ }
321
340
341
+ fn check_snapshot ( mut microvm_state : MicrovmState ) {
342
+ use vmm:: persist:: SnapShotStateSanityCheckError ;
322
343
snapshot_state_sanity_check ( & microvm_state) . unwrap ( ) ;
323
344
324
345
// Remove memory regions.
@@ -331,9 +352,9 @@ fn test_snapshot_load_sanity_checks() {
331
352
) ;
332
353
}
333
354
334
- fn get_microvm_state_from_snapshot ( ) -> MicrovmState {
355
+ fn get_microvm_state_from_snapshot ( pci_enabled : bool ) -> MicrovmState {
335
356
// Create a diff snapshot
336
- let ( snapshot_file, _) = verify_create_snapshot ( true ) ;
357
+ let ( snapshot_file, _) = verify_create_snapshot ( true , pci_enabled ) ;
337
358
338
359
// Deserialize the microVM state.
339
360
let snapshot_file_metadata = snapshot_file. as_file ( ) . metadata ( ) . unwrap ( ) ;
@@ -344,7 +365,7 @@ fn get_microvm_state_from_snapshot() -> MicrovmState {
344
365
}
345
366
346
367
fn 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 ) ;
348
369
349
370
let mut event_manager = EventManager :: new ( ) . unwrap ( ) ;
350
371
let empty_seccomp_filters = get_empty_filters ( ) ;
0 commit comments