@@ -10,6 +10,7 @@ use libc::{c_int, c_void, siginfo_t};
1010use std:: cell:: Cell ;
1111use std:: fmt:: { Display , Formatter } ;
1212use std:: io;
13+ use std:: os:: fd:: RawFd ;
1314
1415#[ cfg( feature = "tee" ) ]
1516use std:: os:: unix:: io:: RawFd ;
@@ -45,7 +46,10 @@ use kvm_bindings::{
4546 Msrs , KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
4647 KVM_MAX_CPUID_ENTRIES , KVM_PIT_SPEAKER_DUMMY ,
4748} ;
48- use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
49+ use kvm_bindings:: {
50+ kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
51+ KVM_API_VERSION , KVM_MEM_GUEST_MEMFD ,
52+ } ;
4953use kvm_ioctls:: * ;
5054use utils:: eventfd:: EventFd ;
5155use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
@@ -112,6 +116,10 @@ pub enum Error {
112116 SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
113117 /// Error creating memory map for SHM region.
114118 ShmMmap ( io:: Error ) ,
119+ /// Cannot set the memory regions.
120+ SetUserMemoryRegion2 ( kvm_ioctls:: Error ) ,
121+ /// Cannot create guest memfd.
122+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
115123 #[ cfg( feature = "amd-sev" ) ]
116124 /// Error initializing the Secure Virtualization Backend (SEV).
117125 SevSecVirtInit ( SevError ) ,
@@ -272,6 +280,8 @@ impl Display for Error {
272280 ) ,
273281 SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
274282 ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
283+ SetUserMemoryRegion2 ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
284+ CreateGuestMemfd ( e) => write ! ( f, "Cannot create guest memfd: {e}" ) ,
275285 #[ cfg( feature = "tee" ) ]
276286 SevSecVirtInit ( e) => {
277287 write ! (
@@ -554,27 +564,62 @@ impl Vm {
554564 & mut self ,
555565 guest_mem : & GuestMemoryMmap ,
556566 kvm_max_memslots : usize ,
567+ require_guest_memfd : bool ,
557568 ) -> Result < ( ) > {
558569 if guest_mem. num_regions ( ) > kvm_max_memslots {
559570 return Err ( Error :: NotEnoughMemorySlots ) ;
560571 }
561572 for region in guest_mem. iter ( ) {
562573 // It's safe to unwrap because the guest address is valid.
563574 let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
564- debug ! ( "Guest memory starts at {:x?}" , host_addr) ;
565- let memory_region = kvm_userspace_memory_region {
566- slot : self . next_mem_slot ,
567- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
568- memory_size : region. len ( ) ,
569- userspace_addr : host_addr as u64 ,
570- flags : 0 ,
571- } ;
572- // Safe because we mapped the memory region, we made sure that the regions
573- // are not overlapping.
574- unsafe {
575- self . fd
576- . set_user_memory_region ( memory_region)
577- . map_err ( Error :: SetUserMemoryRegion ) ?;
575+ info ! ( "Guest memory starts at {:x?}" , host_addr) ;
576+
577+ if require_guest_memfd {
578+ let gmem = kvm_create_guest_memfd {
579+ size : region. len ( ) ,
580+ flags : 0 ,
581+ reserved : [ 0 ; 6 ] ,
582+ } ;
583+
584+ let id: RawFd = self
585+ . fd
586+ . create_guest_memfd ( gmem)
587+ . map_err ( Error :: CreateGuestMemfd ) ?;
588+
589+ let memory_region = kvm_userspace_memory_region2 {
590+ slot : self . next_mem_slot as u32 ,
591+ flags : KVM_MEM_GUEST_MEMFD ,
592+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
593+ memory_size : region. len ( ) ,
594+ userspace_addr : host_addr as u64 ,
595+ guest_memfd_offset : 0 ,
596+ guest_memfd : id as u32 ,
597+ pad1 : 0 ,
598+ pad2 : [ 0 ; 14 ] ,
599+ } ;
600+
601+ // Safe because we mapped the memory region, we made sure that the regions
602+ // are not overlapping.
603+ unsafe {
604+ self . fd
605+ . set_user_memory_region2 ( memory_region)
606+ . map_err ( Error :: SetUserMemoryRegion2 ) ?;
607+ } ;
608+ } else {
609+ let memory_region = kvm_userspace_memory_region {
610+ slot : self . next_mem_slot as u32 ,
611+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
612+ memory_size : region. len ( ) ,
613+ userspace_addr : host_addr as u64 ,
614+ flags : 0 ,
615+ } ;
616+ // Safe because we mapped the memory region, we made sure that the regions
617+ // are not overlapping.
618+ unsafe {
619+ self . fd
620+ . set_user_memory_region ( memory_region)
621+ . map_err ( Error :: SetUserMemoryRegion ) ?;
622+ } ;
578623 } ;
579624 self . next_mem_slot += 1 ;
580625 }
@@ -1510,7 +1555,7 @@ mod tests {
15101555 let kvm = KvmContext :: new ( ) . unwrap ( ) ;
15111556 let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , mem_size) ] ) . unwrap ( ) ;
15121557 let mut vm = Vm :: new ( kvm. fd ( ) ) . expect ( "Cannot create new vm" ) ;
1513- assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) ) . is_ok( ) ) ;
1558+ assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) , false ) . is_ok( ) ) ;
15141559
15151560 let exit_evt = EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK ) . unwrap ( ) ;
15161561
@@ -1565,7 +1610,7 @@ mod tests {
15651610
15661611 // Create valid memory region and test that the initialization is successful.
15671612 let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] ) . unwrap ( ) ;
1568- assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) ) . is_ok( ) ) ;
1613+ assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) , false ) . is_ok( ) ) ;
15691614
15701615 // Set the maximum number of memory slots to 1 in KvmContext to check the error
15711616 // path of memory_init. Create 2 non-overlapping memory slots.
@@ -1575,7 +1620,7 @@ mod tests {
15751620 ( GuestAddress ( 0x1001 ) , 0x2000 ) ,
15761621 ] )
15771622 . unwrap ( ) ;
1578- assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) ) . is_err( ) ) ;
1623+ assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) , false ) . is_err( ) ) ;
15791624 }
15801625
15811626 #[ cfg( target_arch = "x86_64" ) ]
@@ -1656,7 +1701,7 @@ mod tests {
16561701 let kvm = KvmContext :: new ( ) . unwrap ( ) ;
16571702 let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( ) ;
16581703 let mut vm = Vm :: new ( kvm. fd ( ) ) . expect ( "new vm failed" ) ;
1659- assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) ) . is_ok( ) ) ;
1704+ assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) , false ) . is_ok( ) ) ;
16601705
16611706 // Try it for when vcpu id is 0.
16621707 let mut vcpu = Vcpu :: new_aarch64 (
0 commit comments