@@ -45,15 +45,17 @@ use kvm_bindings::{
4545} ;
4646#[ cfg( feature = "tee" ) ]
4747use kvm_bindings:: {
48- kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, KVM_API_VERSION ,
49- KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEM_GUEST_MEMFD ,
48+ kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region,
49+ kvm_userspace_memory_region2, KVM_API_VERSION , KVM_MEMORY_ATTRIBUTE_PRIVATE ,
50+ KVM_MEM_GUEST_MEMFD ,
5051} ;
51- use kvm_ioctls:: * ;
52+ use kvm_ioctls:: { Cap :: * , * } ;
5253use utils:: eventfd:: EventFd ;
5354use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
5455use utils:: sm:: StateMachine ;
5556use vm_memory:: {
5657 Address , GuestAddress , GuestMemory , GuestMemoryError , GuestMemoryMmap , GuestMemoryRegion ,
58+ GuestRegionMmap ,
5759} ;
5860
5961#[ cfg( feature = "amd-sev" ) ]
@@ -68,6 +70,8 @@ pub enum Error {
6870 #[ cfg( target_arch = "x86_64" ) ]
6971 /// A call to cpuid instruction failed.
7072 CpuId ( cpuid:: Error ) ,
73+ /// Unable to create a KVM guest_memfd.
74+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
7175 #[ cfg( target_arch = "x86_64" ) ]
7276 /// Error configuring the floating point related registers
7377 FPUConfiguration ( arch:: x86_64:: regs:: Error ) ,
@@ -104,16 +108,12 @@ pub enum Error {
104108 #[ cfg( target_arch = "x86_64" ) ]
105109 /// Error configuring the general purpose registers
106110 REGSConfiguration ( arch:: x86_64:: regs:: Error ) ,
111+ /// Cannot set memory region attributes.
112+ SetMemoryAttributes ( kvm_ioctls:: Error ) ,
107113 /// Cannot set the memory regions.
108114 SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
109115 /// Error creating memory map for SHM region.
110116 ShmMmap ( io:: Error ) ,
111- #[ cfg( feature = "tee" ) ]
112- /// Cannot set the memory regions.
113- SetUserMemoryRegion2 ( kvm_ioctls:: Error ) ,
114- #[ cfg( feature = "tee" ) ]
115- /// Cannot create guest memfd.
116- CreateGuestMemfd ( kvm_ioctls:: Error ) ,
117117 #[ cfg( feature = "amd-sev" ) ]
118118 /// Error initializing the Secure Virtualization Backend (SNP).
119119 SnpSecVirtInit ( SnpError ) ,
@@ -239,6 +239,7 @@ impl Display for Error {
239239 match self {
240240 #[ cfg( target_arch = "x86_64" ) ]
241241 CpuId ( e) => write ! ( f, "Cpuid error: {e:?}" ) ,
242+ CreateGuestMemfd ( e) => write ! ( f, "Unable to create KVM guest_memfd: {e:?}" ) ,
242243 GuestMemoryMmap ( e) => write ! ( f, "Guest memory error: {e:?}" ) ,
243244 #[ cfg( target_arch = "x86_64" ) ]
244245 GuestMSRs ( e) => write ! ( f, "Retrieving supported guest MSRs fails: {e:?}" ) ,
@@ -263,13 +264,10 @@ impl Display for Error {
263264 f,
264265 "Cannot set the local interruption due to bad configuration: {e:?}"
265266 ) ,
267+ SetMemoryAttributes ( e) => write ! ( f, "Cannot set memory region attributes: {e}" ) ,
266268 SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
267269 ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
268270 #[ cfg( feature = "tee" ) ]
269- SetUserMemoryRegion2 ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
270- #[ cfg( feature = "tee" ) ]
271- CreateGuestMemfd ( e) => write ! ( f, "Cannot create guest memfd: {e}" ) ,
272- #[ cfg( feature = "tee" ) ]
273271 SnpSecVirtInit ( e) => write ! (
274272 f,
275273 "Error initializing the Secure Virtualization Backend (SEV): {e:?}"
@@ -393,7 +391,6 @@ pub struct KvmContext {
393391
394392impl KvmContext {
395393 pub fn new ( ) -> Result < Self > {
396- use kvm_ioctls:: Cap :: * ;
397394 let kvm = Kvm :: new ( ) . expect ( "Error creating the Kvm object" ) ;
398395
399396 // Check that KVM has the correct version.
@@ -520,80 +517,14 @@ impl Vm {
520517 pub fn memory_init (
521518 & mut self ,
522519 guest_mem : & GuestMemoryMmap ,
523- #[ cfg( feature = "tee" ) ] guest_memfd : & mut Vec < RawFd > ,
524520 kvm_max_memslots : usize ,
525521 ) -> Result < ( ) > {
526522 if guest_mem. num_regions ( ) > kvm_max_memslots {
527523 return Err ( Error :: NotEnoughMemorySlots ) ;
528524 }
529- for region in guest_mem. iter ( ) {
530- // It's safe to unwrap because the guest address is valid.
531- let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
532- info ! ( "Guest memory starts at {:x?}" , host_addr) ;
533525
534- #[ cfg( feature = "tee" ) ]
535- {
536- let gmem = kvm_create_guest_memfd {
537- size : region. len ( ) ,
538- flags : 0 ,
539- reserved : [ 0 ; 6 ] ,
540- } ;
541-
542- let id: RawFd = self
543- . fd
544- . create_guest_memfd ( gmem)
545- . map_err ( Error :: CreateGuestMemfd ) ?;
546-
547- guest_memfd. push ( id) ;
548-
549- let memory_region = kvm_userspace_memory_region2 {
550- slot : self . next_mem_slot as u32 ,
551- flags : KVM_MEM_GUEST_MEMFD ,
552- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
553- memory_size : region. len ( ) ,
554- userspace_addr : host_addr as u64 ,
555- guest_memfd_offset : 0 ,
556- guest_memfd : id as u32 ,
557- pad1 : 0 ,
558- pad2 : [ 0 ; 14 ] ,
559- } ;
560-
561- // Safe because we mapped the memory region, we made sure that the regions
562- // are not overlapping.
563- unsafe {
564- self . fd
565- . set_user_memory_region2 ( memory_region)
566- . map_err ( Error :: SetUserMemoryRegion2 ) ?;
567- } ;
568-
569- // set private by default when using guestmemfd
570- // this imitates QEMU behavior
571- let attr = kvm_memory_attributes {
572- address : region. start_addr ( ) . raw_value ( ) ,
573- size : region. len ( ) ,
574- attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
575- flags : 0 ,
576- } ;
577- self . fd . set_memory_attributes ( attr) . unwrap ( ) ;
578- }
579- #[ cfg( not( feature = "tee" ) ) ]
580- {
581- let memory_region = kvm_userspace_memory_region {
582- slot : self . next_mem_slot as u32 ,
583- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
584- memory_size : region. len ( ) ,
585- userspace_addr : host_addr as u64 ,
586- flags : 0 ,
587- } ;
588- // Safe because we mapped the memory region, we made sure that the regions
589- // are not overlapping.
590- unsafe {
591- self . fd
592- . set_user_memory_region ( memory_region)
593- . map_err ( Error :: SetUserMemoryRegion ) ?;
594- } ;
595- } ;
596- self . next_mem_slot += 1 ;
526+ for region in guest_mem. iter ( ) {
527+ self . memory_region_set ( guest_mem, region) ?;
597528 }
598529
599530 #[ cfg( target_arch = "x86_64" ) ]
@@ -604,6 +535,76 @@ impl Vm {
604535 Ok ( ( ) )
605536 }
606537
538+ fn memory_region_set (
539+ & mut self ,
540+ guest_mem : & GuestMemoryMmap ,
541+ region : & GuestRegionMmap ,
542+ ) -> Result < ( ) > {
543+ let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
544+ if !self . fd . check_extension ( GuestMemfd ) {
545+ let memory_region = kvm_userspace_memory_region {
546+ slot : self . next_mem_slot ,
547+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
548+ memory_size : region. len ( ) ,
549+ userspace_addr : host_addr as u64 ,
550+ flags : 0 ,
551+ } ;
552+
553+ // Safe because we mapped the memory region, we made sure that the regions
554+ // are not overlapping.
555+ unsafe {
556+ self . fd
557+ . set_user_memory_region ( memory_region)
558+ . map_err ( Error :: SetUserMemoryRegion ) ?;
559+ } ;
560+ } else {
561+ // Create a guest_memfd and set the region.
562+ let guest_memfd = self
563+ . fd
564+ . create_guest_memfd ( kvm_create_guest_memfd {
565+ size : region. size ( ) as u64 ,
566+ flags : 0 ,
567+ reserved : [ 0 ; 6 ] ,
568+ } )
569+ . map_err ( Error :: CreateGuestMemfd ) ?;
570+
571+ let memory_region = kvm_userspace_memory_region2 {
572+ slot : self . next_mem_slot ,
573+ flags : KVM_MEM_GUEST_MEMFD ,
574+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
575+ memory_size : region. len ( ) ,
576+ userspace_addr : host_addr as u64 ,
577+ guest_memfd_offset : 0 ,
578+ guest_memfd : guest_memfd as u32 ,
579+ pad1 : 0 ,
580+ pad2 : [ 0 ; 14 ] ,
581+ } ;
582+
583+ // Safe because we mapped the memory region, we made sure that the regions
584+ // are not overlapping.
585+ unsafe {
586+ self . fd
587+ . set_user_memory_region2 ( memory_region)
588+ . map_err ( Error :: SetUserMemoryRegion ) ?;
589+ } ;
590+
591+ let attr = kvm_memory_attributes {
592+ address : region. start_addr ( ) . raw_value ( ) ,
593+ size : region. len ( ) ,
594+ attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
595+ flags : 0 ,
596+ } ;
597+
598+ self . fd
599+ . set_memory_attributes ( attr)
600+ . map_err ( Error :: SetMemoryAttributes ) ?;
601+ }
602+
603+ self . next_mem_slot += 1 ;
604+
605+ Ok ( ( ) )
606+ }
607+
607608 #[ cfg( feature = "amd-sev" ) ]
608609 pub fn snp_secure_virt_prepare (
609610 & self ,
0 commit comments