@@ -42,21 +42,22 @@ use crate::resources::TeeConfig;
4242use crate :: vmm_config:: machine_config:: CpuFeaturesTemplate ;
4343#[ cfg( target_arch = "x86_64" ) ]
4444use cpuid:: { c3, filter_cpuid, t2, VmSpec } ;
45+ #[ cfg( not( feature = "tee" ) ) ]
46+ use kvm_bindings:: kvm_userspace_memory_region;
4547#[ cfg( target_arch = "x86_64" ) ]
4648use kvm_bindings:: {
4749 kvm_clock_data, kvm_debugregs, kvm_irqchip, kvm_lapic_state, kvm_mp_state, kvm_pit_state2,
4850 kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, kvm_xsave, CpuId , MsrList , Msrs ,
4951 KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
5052 KVM_MAX_CPUID_ENTRIES ,
5153} ;
52- use kvm_bindings:: {
53- kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
54- KVM_API_VERSION , KVM_MEM_GUEST_MEMFD , KVM_SYSTEM_EVENT_RESET , KVM_SYSTEM_EVENT_SHUTDOWN ,
55- } ;
54+ #[ cfg( all( feature = "tee" , target_arch = "x86_64" ) ) ]
55+ use kvm_bindings:: { kvm_create_guest_memfd, kvm_userspace_memory_region2, KVM_MEM_GUEST_MEMFD } ;
5656#[ cfg( feature = "tee" ) ]
5757use kvm_bindings:: { kvm_enable_cap, KVM_CAP_EXIT_HYPERCALL , KVM_MEMORY_EXIT_FLAG_PRIVATE } ;
58- #[ cfg( not ( target_arch = "riscv64 " ) ) ]
58+ #[ cfg( all ( feature = "tee" , target_arch = "x86_64 " ) ) ]
5959use kvm_bindings:: { kvm_memory_attributes, KVM_MEMORY_ATTRIBUTE_PRIVATE } ;
60+ use kvm_bindings:: { KVM_API_VERSION , KVM_SYSTEM_EVENT_RESET , KVM_SYSTEM_EVENT_SHUTDOWN } ;
6061use kvm_ioctls:: { Cap :: * , * } ;
6162use utils:: eventfd:: EventFd ;
6263use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
@@ -661,90 +662,121 @@ impl Vm {
661662 None
662663 }
663664
664- #[ allow( unused_mut) ]
665- fn memory_region_set (
665+ // GuestMemfd is generally intended for either of two purposes:
666+ // * sharing the memory with out-of-process components, and conversely,
667+ // * hiding the memory completely from the VMM process (Confidential Computing).
668+ //
669+ // We only use it for the second use case currently, so don't even try to use it
670+ // outside of TEE builds. Software-protected VMs are only available on x86_64 and
671+ // are marked with strongly-worded warnings about them being for development only,
672+ // as of late 2025. Also, on other architectures like aarch64, guest_memfd in
673+ // general is unstable for now, so don't try to use it without a reason.
674+
675+ #[ cfg( not( feature = "tee" ) ) ]
676+ fn create_guest_physical_memory_slot (
666677 & mut self ,
667- guest_mem : & GuestMemoryMmap ,
678+ host_addr : u64 ,
679+ start : u64 ,
668680 region : & GuestRegionMmap ,
669681 ) -> Result < ( ) > {
670- let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
671- let start = region. start_addr ( ) . raw_value ( ) ;
672- let end = start + region. len ( ) ;
682+ let memory_region = kvm_userspace_memory_region {
683+ slot : self . next_mem_slot ,
684+ guest_phys_addr : start,
685+ memory_size : region. len ( ) ,
686+ userspace_addr : host_addr,
687+ flags : 0 ,
688+ } ;
673689
674- // GuestMemfd is generally intended for either of two purposes:
675- // * sharing the memory with out-of-process components, and conversely,
676- // * hiding the memory completely from the VMM process (Confidential Computing).
677- //
678- // We only use it for the second use case currently, so don't even try to use it
679- // outside of TEE builds. Software-protected VMs are only available on x86_64 and
680- // are marked with strongly-worded warnings about them being for development only,
681- // as of late 2025. Also, on other architectures like aarch64, guest_memfd in
682- // general is unstable for now, so don't try to use it without a reason.
683-
684- if cfg ! ( not( feature = "tee" ) ) {
685- let memory_region = kvm_userspace_memory_region {
686- slot : self . next_mem_slot ,
687- guest_phys_addr : start,
688- memory_size : region. len ( ) ,
689- userspace_addr : host_addr as u64 ,
690- flags : 0 ,
691- } ;
690+ // Safe because we mapped the memory region and ensured regions do not overlap.
691+ unsafe {
692+ self . fd
693+ . set_user_memory_region ( memory_region)
694+ . map_err ( Error :: SetUserMemoryRegion ) ?;
695+ } ;
692696
693- // Safe because we mapped the memory region, we made sure that the regions
694- // are not overlapping.
695- unsafe {
696- self . fd
697- . set_user_memory_region ( memory_region)
698- . map_err ( Error :: SetUserMemoryRegion ) ?;
699- } ;
700- } else {
701- if !self . fd . check_extension ( GuestMemfd ) {
702- return Err ( Error :: KvmCap ( GuestMemfd ) ) ;
703- }
697+ Ok ( ( ) )
698+ }
704699
705- // Create a guest_memfd and set the region.
706- let guest_memfd = self
707- . fd
708- . create_guest_memfd ( kvm_create_guest_memfd {
709- size : region. size ( ) as u64 ,
710- flags : 0 ,
711- reserved : [ 0 ; 6 ] ,
712- } )
713- . map_err ( Error :: CreateGuestMemfd ) ?;
714-
715- let memory_region = kvm_userspace_memory_region2 {
716- slot : self . next_mem_slot ,
717- flags : KVM_MEM_GUEST_MEMFD ,
718- guest_phys_addr : start,
719- memory_size : region. len ( ) ,
720- userspace_addr : host_addr as u64 ,
721- guest_memfd_offset : 0 ,
722- guest_memfd : guest_memfd as u32 ,
723- pad1 : 0 ,
724- pad2 : [ 0 ; 14 ] ,
725- } ;
726-
727- // Safe because we mapped the memory region, we made sure that the regions
728- // are not overlapping.
729- unsafe {
730- self . fd
731- . set_user_memory_region2 ( memory_region)
732- . map_err ( Error :: SetUserMemoryRegion ) ?;
733- } ;
734-
735- let attr = kvm_memory_attributes {
736- address : start,
737- size : region. len ( ) ,
738- attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
700+ #[ cfg( all( feature = "tee" , target_arch = "x86_64" ) ) ]
701+ fn create_guest_physical_memory_slot (
702+ & mut self ,
703+ host_addr : u64 ,
704+ start : u64 ,
705+ region : & GuestRegionMmap ,
706+ ) -> Result < ( ) > {
707+ let end = start + region. len ( ) ;
708+
709+ if !self . fd . check_extension ( GuestMemfd ) {
710+ return Err ( Error :: KvmCap ( GuestMemfd ) ) ;
711+ }
712+
713+ // GuestMemfd is only used for confidential-memory setups in TEE builds.
714+ let guest_memfd = self
715+ . fd
716+ . create_guest_memfd ( kvm_create_guest_memfd {
717+ size : region. size ( ) as u64 ,
739718 flags : 0 ,
740- } ;
719+ reserved : [ 0 ; 6 ] ,
720+ } )
721+ . map_err ( Error :: CreateGuestMemfd ) ?;
722+
723+ let memory_region = kvm_userspace_memory_region2 {
724+ slot : self . next_mem_slot ,
725+ flags : KVM_MEM_GUEST_MEMFD ,
726+ guest_phys_addr : start,
727+ memory_size : region. len ( ) ,
728+ userspace_addr : host_addr,
729+ guest_memfd_offset : 0 ,
730+ guest_memfd : guest_memfd as u32 ,
731+ pad1 : 0 ,
732+ pad2 : [ 0 ; 14 ] ,
733+ } ;
741734
735+ // Safe because we mapped the memory region and ensured regions do not overlap.
736+ unsafe {
742737 self . fd
743- . set_memory_attributes ( attr)
744- . map_err ( Error :: SetMemoryAttributes ) ?;
738+ . set_user_memory_region2 ( memory_region)
739+ . map_err ( Error :: SetUserMemoryRegion ) ?;
740+ } ;
745741
746- self . guest_memfds . push ( ( Range { start, end } , guest_memfd) ) ;
747- }
742+ let attr = kvm_memory_attributes {
743+ address : start,
744+ size : region. len ( ) ,
745+ attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
746+ flags : 0 ,
747+ } ;
748+
749+ self . fd
750+ . set_memory_attributes ( attr)
751+ . map_err ( Error :: SetMemoryAttributes ) ?;
752+
753+ self . guest_memfds . push ( ( Range { start, end } , guest_memfd) ) ;
754+
755+ Ok ( ( ) )
756+ }
757+
758+ #[ cfg( all( feature = "tee" , not( target_arch = "x86_64" ) ) ) ]
759+ fn create_guest_physical_memory_slot (
760+ & mut self ,
761+ _host_addr : u64 ,
762+ _start : u64 ,
763+ _region : & GuestRegionMmap ,
764+ ) -> Result < ( ) > {
765+ // TEE support should be rejected during VM setup on non-x86_64 targets.
766+ // Do not silently fall back to the non-TEE path here, because that would
767+ // ignore an invalid TEE configuration and create a normal VM instead.
768+ Err ( Error :: InvalidTee )
769+ }
770+
771+ fn memory_region_set (
772+ & mut self ,
773+ guest_mem : & GuestMemoryMmap ,
774+ region : & GuestRegionMmap ,
775+ ) -> Result < ( ) > {
776+ let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) as u64 ;
777+ let start = region. start_addr ( ) . raw_value ( ) ;
778+
779+ self . create_guest_physical_memory_slot ( host_addr, start, region) ?;
748780
749781 self . next_mem_slot += 1 ;
750782
0 commit comments