@@ -33,6 +33,7 @@ use crate::devices::acpi::vmgenid::VmGenIdError;
33
33
use crate :: devices:: virtio:: balloon:: Balloon ;
34
34
use crate :: devices:: virtio:: block:: device:: Block ;
35
35
use crate :: devices:: virtio:: net:: Net ;
36
+ use crate :: devices:: virtio:: pmem:: device:: Pmem ;
36
37
use crate :: devices:: virtio:: rng:: Entropy ;
37
38
use crate :: devices:: virtio:: vsock:: { Vsock , VsockUnixBackend } ;
38
39
#[ cfg( feature = "gdb" ) ]
@@ -68,6 +69,8 @@ pub enum StartMicrovmError {
68
69
CreateGuestConfig ( #[ from] GuestConfigError ) ,
69
70
/// Cannot create network device: {0}
70
71
CreateNetDevice ( crate :: devices:: virtio:: net:: NetError ) ,
72
+ /// Cannot create pmem device: {0}
73
+ CreatePmemDevice ( #[ from] crate :: devices:: virtio:: pmem:: device:: PmemError ) ,
71
74
/// Cannot create RateLimiter: {0}
72
75
CreateRateLimiter ( io:: Error ) ,
73
76
/// Error creating legacy device: {0}
@@ -219,6 +222,13 @@ pub fn build_microvm_for_boot(
219
222
vm_resources. net_builder . iter ( ) ,
220
223
event_manager,
221
224
) ?;
225
+ attach_pmem_devices (
226
+ & mut device_manager,
227
+ & vm,
228
+ & mut boot_cmdline,
229
+ vm_resources. pmem . devices . iter ( ) ,
230
+ event_manager,
231
+ ) ?;
222
232
223
233
if let Some ( unix_vsock) = vm_resources. vsock . get ( ) {
224
234
attach_unixsock_vsock_device (
@@ -609,6 +619,34 @@ fn attach_net_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Net>>> + Debug>(
609
619
Ok ( ( ) )
610
620
}
611
621
622
+ fn attach_pmem_devices < ' a , I : Iterator < Item = & ' a Arc < Mutex < Pmem > > > + Debug > (
623
+ device_manager : & mut DeviceManager ,
624
+ vm : & Arc < Vm > ,
625
+ cmdline : & mut LoaderKernelCmdline ,
626
+ pmem_devices : I ,
627
+ event_manager : & mut EventManager ,
628
+ ) -> Result < ( ) , StartMicrovmError > {
629
+ for ( i, device) in pmem_devices. enumerate ( ) {
630
+ let id = {
631
+ let mut locked_dev = device. lock ( ) . expect ( "Poisoned lock" ) ;
632
+ if locked_dev. config . root_device {
633
+ cmdline. insert_str ( format ! ( "root=/dev/pmem{i}" ) ) ?;
634
+ match locked_dev. config . read_only {
635
+ true => cmdline. insert_str ( "ro" ) ?,
636
+ false => cmdline. insert_str ( "rw" ) ?,
637
+ }
638
+ }
639
+ locked_dev. alloc_region ( vm. as_ref ( ) ) ;
640
+ locked_dev. set_mem_region ( vm. as_ref ( ) ) ?;
641
+ locked_dev. config . id . to_string ( )
642
+ } ;
643
+
644
+ event_manager. add_subscriber ( device. clone ( ) ) ;
645
+ device_manager. attach_virtio_device ( vm, id, device. clone ( ) , cmdline, false ) ?;
646
+ }
647
+ Ok ( ( ) )
648
+ }
649
+
612
650
fn attach_unixsock_vsock_device (
613
651
device_manager : & mut DeviceManager ,
614
652
vm : & Arc < Vm > ,
@@ -655,6 +693,7 @@ pub(crate) mod tests {
655
693
use crate :: vmm_config:: drive:: { BlockBuilder , BlockDeviceConfig } ;
656
694
use crate :: vmm_config:: entropy:: { EntropyDeviceBuilder , EntropyDeviceConfig } ;
657
695
use crate :: vmm_config:: net:: { NetBuilder , NetworkInterfaceConfig } ;
696
+ use crate :: vmm_config:: pmem:: { PmemBuilder , PmemConfig } ;
658
697
use crate :: vmm_config:: vsock:: tests:: default_config;
659
698
use crate :: vmm_config:: vsock:: { VsockBuilder , VsockDeviceConfig } ;
660
699
use crate :: vstate:: vm:: tests:: setup_vm_with_memory;
@@ -875,6 +914,34 @@ pub(crate) mod tests {
875
914
) ;
876
915
}
877
916
917
+ pub ( crate ) fn insert_pmem_devices (
918
+ vmm : & mut Vmm ,
919
+ cmdline : & mut Cmdline ,
920
+ event_manager : & mut EventManager ,
921
+ configs : Vec < PmemConfig > ,
922
+ ) -> Vec < TempFile > {
923
+ let mut builder = PmemBuilder :: default ( ) ;
924
+ let mut files = Vec :: new ( ) ;
925
+ for mut config in configs {
926
+ let tmp_file = TempFile :: new ( ) . unwrap ( ) ;
927
+ tmp_file. as_file ( ) . set_len ( 0x20_0000 ) . unwrap ( ) ;
928
+ let tmp_file_path = tmp_file. as_path ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
929
+ files. push ( tmp_file) ;
930
+ config. path_on_host = tmp_file_path;
931
+ builder. build ( config, false ) . unwrap ( ) ;
932
+ }
933
+
934
+ attach_pmem_devices (
935
+ & mut vmm. device_manager ,
936
+ & vmm. vm ,
937
+ cmdline,
938
+ builder. devices . iter ( ) ,
939
+ event_manager,
940
+ )
941
+ . unwrap ( ) ;
942
+ files
943
+ }
944
+
878
945
#[ cfg( target_arch = "x86_64" ) ]
879
946
pub ( crate ) fn insert_vmgenid_device ( vmm : & mut Vmm ) {
880
947
vmm. device_manager
@@ -1122,6 +1189,28 @@ pub(crate) mod tests {
1122
1189
}
1123
1190
}
1124
1191
1192
+ #[ test]
1193
+ fn test_attach_pmem_devices ( ) {
1194
+ let mut event_manager = EventManager :: new ( ) . expect ( "Unable to create EventManager" ) ;
1195
+
1196
+ let id = String :: from ( "root" ) ;
1197
+ let configs = vec ! [ PmemConfig {
1198
+ id: id. clone( ) ,
1199
+ path_on_host: "" . into( ) ,
1200
+ root_device: true ,
1201
+ read_only: true ,
1202
+ } ] ;
1203
+ let mut vmm = default_vmm ( ) ;
1204
+ let mut cmdline = default_kernel_cmdline ( ) ;
1205
+ _ = insert_pmem_devices ( & mut vmm, & mut cmdline, & mut event_manager, configs) ;
1206
+ assert ! ( cmdline_contains( & cmdline, "root=/dev/pmem0 ro" ) ) ;
1207
+ assert ! (
1208
+ vmm. device_manager
1209
+ . get_virtio_device( virtio_ids:: VIRTIO_ID_PMEM , id. as_str( ) )
1210
+ . is_some( )
1211
+ ) ;
1212
+ }
1213
+
1125
1214
#[ test]
1126
1215
fn test_attach_boot_timer_device ( ) {
1127
1216
let mut vmm = default_vmm ( ) ;
0 commit comments