@@ -33,6 +33,7 @@ use crate::devices::acpi::vmgenid::VmGenIdError;
3333use crate :: devices:: virtio:: balloon:: Balloon ;
3434use crate :: devices:: virtio:: block:: device:: Block ;
3535use crate :: devices:: virtio:: net:: Net ;
36+ use crate :: devices:: virtio:: pmem:: device:: Pmem ;
3637use crate :: devices:: virtio:: rng:: Entropy ;
3738use crate :: devices:: virtio:: vsock:: { Vsock , VsockUnixBackend } ;
3839#[ cfg( feature = "gdb" ) ]
@@ -68,6 +69,8 @@ pub enum StartMicrovmError {
6869 CreateGuestConfig ( #[ from] GuestConfigError ) ,
6970 /// Cannot create network device: {0}
7071 CreateNetDevice ( crate :: devices:: virtio:: net:: NetError ) ,
72+ /// Cannot create pmem device: {0}
73+ CreatePmemDevice ( #[ from] crate :: devices:: virtio:: pmem:: device:: PmemError ) ,
7174 /// Cannot create RateLimiter: {0}
7275 CreateRateLimiter ( io:: Error ) ,
7376 /// Error creating legacy device: {0}
@@ -219,6 +222,13 @@ pub fn build_microvm_for_boot(
219222 vm_resources. net_builder . iter ( ) ,
220223 event_manager,
221224 ) ?;
225+ attach_pmem_devices (
226+ & mut device_manager,
227+ & vm,
228+ & mut boot_cmdline,
229+ vm_resources. pmem . devices . iter ( ) ,
230+ event_manager,
231+ ) ?;
222232
223233 if let Some ( unix_vsock) = vm_resources. vsock . get ( ) {
224234 attach_unixsock_vsock_device (
@@ -609,6 +619,34 @@ fn attach_net_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Net>>> + Debug>(
609619 Ok ( ( ) )
610620}
611621
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+
612650fn attach_unixsock_vsock_device (
613651 device_manager : & mut DeviceManager ,
614652 vm : & Arc < Vm > ,
@@ -655,6 +693,7 @@ pub(crate) mod tests {
655693 use crate :: vmm_config:: drive:: { BlockBuilder , BlockDeviceConfig } ;
656694 use crate :: vmm_config:: entropy:: { EntropyDeviceBuilder , EntropyDeviceConfig } ;
657695 use crate :: vmm_config:: net:: { NetBuilder , NetworkInterfaceConfig } ;
696+ use crate :: vmm_config:: pmem:: { PmemBuilder , PmemConfig } ;
658697 use crate :: vmm_config:: vsock:: tests:: default_config;
659698 use crate :: vmm_config:: vsock:: { VsockBuilder , VsockDeviceConfig } ;
660699 use crate :: vstate:: vm:: tests:: setup_vm_with_memory;
@@ -875,6 +914,34 @@ pub(crate) mod tests {
875914 ) ;
876915 }
877916
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+
878945 #[ cfg( target_arch = "x86_64" ) ]
879946 pub ( crate ) fn insert_vmgenid_device ( vmm : & mut Vmm ) {
880947 vmm. device_manager
@@ -1122,6 +1189,28 @@ pub(crate) mod tests {
11221189 }
11231190 }
11241191
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+
11251214 #[ test]
11261215 fn test_attach_boot_timer_device ( ) {
11271216 let mut vmm = default_vmm ( ) ;
0 commit comments