@@ -45,6 +45,12 @@ use kvm_bindings::{
45
45
Msrs , KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
46
46
KVM_MAX_CPUID_ENTRIES , KVM_PIT_SPEAKER_DUMMY ,
47
47
} ;
48
+ #[ cfg( feature = "tee" ) ]
49
+ use kvm_bindings:: {
50
+ kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, KVM_API_VERSION ,
51
+ KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEM_GUEST_MEMFD ,
52
+ } ;
53
+ #[ cfg( not( feature = "tee" ) ) ]
48
54
use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
49
55
use kvm_ioctls:: * ;
50
56
use utils:: eventfd:: EventFd ;
@@ -112,6 +118,12 @@ pub enum Error {
112
118
SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
113
119
/// Error creating memory map for SHM region.
114
120
ShmMmap ( io:: Error ) ,
121
+ #[ cfg( feature = "tee" ) ]
122
+ /// Cannot set the memory regions.
123
+ SetUserMemoryRegion2 ( kvm_ioctls:: Error ) ,
124
+ #[ cfg( feature = "tee" ) ]
125
+ /// Cannot create guest memfd.
126
+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
115
127
#[ cfg( feature = "amd-sev" ) ]
116
128
/// Error initializing the Secure Virtualization Backend (SEV).
117
129
SevSecVirtInit ( SevError ) ,
@@ -273,6 +285,10 @@ impl Display for Error {
273
285
SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
274
286
ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
275
287
#[ cfg( feature = "tee" ) ]
288
+ SetUserMemoryRegion2 ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
289
+ #[ cfg( feature = "tee" ) ]
290
+ CreateGuestMemfd ( e) => write ! ( f, "Cannot create guest memfd: {e}" ) ,
291
+ #[ cfg( feature = "tee" ) ]
276
292
SevSecVirtInit ( e) => {
277
293
write ! (
278
294
f,
@@ -553,6 +569,7 @@ impl Vm {
553
569
pub fn memory_init (
554
570
& mut self ,
555
571
guest_mem : & GuestMemoryMmap ,
572
+ #[ cfg( feature = "tee" ) ] guest_memfd : & mut Vec < RawFd > ,
556
573
kvm_max_memslots : usize ,
557
574
) -> Result < ( ) > {
558
575
if guest_mem. num_regions ( ) > kvm_max_memslots {
@@ -561,20 +578,69 @@ impl Vm {
561
578
for region in guest_mem. iter ( ) {
562
579
// It's safe to unwrap because the guest address is valid.
563
580
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 ) ?;
581
+ info ! ( "Guest memory starts at {:x?}" , host_addr) ;
582
+
583
+ #[ cfg( feature = "tee" ) ]
584
+ {
585
+ let gmem = kvm_create_guest_memfd {
586
+ size : region. len ( ) ,
587
+ flags : 0 ,
588
+ reserved : [ 0 ; 6 ] ,
589
+ } ;
590
+
591
+ let id: RawFd = self
592
+ . fd
593
+ . create_guest_memfd ( gmem)
594
+ . map_err ( Error :: CreateGuestMemfd ) ?;
595
+
596
+ guest_memfd. push ( id) ;
597
+
598
+ let memory_region = kvm_userspace_memory_region2 {
599
+ slot : self . next_mem_slot as u32 ,
600
+ flags : KVM_MEM_GUEST_MEMFD ,
601
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
602
+ memory_size : region. len ( ) ,
603
+ userspace_addr : host_addr as u64 ,
604
+ guest_memfd_offset : 0 ,
605
+ guest_memfd : id as u32 ,
606
+ pad1 : 0 ,
607
+ pad2 : [ 0 ; 14 ] ,
608
+ } ;
609
+
610
+ // Safe because we mapped the memory region, we made sure that the regions
611
+ // are not overlapping.
612
+ unsafe {
613
+ self . fd
614
+ . set_user_memory_region2 ( memory_region)
615
+ . map_err ( Error :: SetUserMemoryRegion2 ) ?;
616
+ } ;
617
+
618
+ // set private by default when using guestmemfd
619
+ // this imitates QEMU behavior
620
+ let attr = kvm_memory_attributes {
621
+ address : region. start_addr ( ) . raw_value ( ) ,
622
+ size : region. len ( ) ,
623
+ attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
624
+ flags : 0 ,
625
+ } ;
626
+ self . fd . set_memory_attributes ( attr) . unwrap ( ) ;
627
+ }
628
+ #[ cfg( not( feature = "tee" ) ) ]
629
+ {
630
+ let memory_region = kvm_userspace_memory_region {
631
+ slot : self . next_mem_slot as u32 ,
632
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
633
+ memory_size : region. len ( ) ,
634
+ userspace_addr : host_addr as u64 ,
635
+ flags : 0 ,
636
+ } ;
637
+ // Safe because we mapped the memory region, we made sure that the regions
638
+ // are not overlapping.
639
+ unsafe {
640
+ self . fd
641
+ . set_user_memory_region ( memory_region)
642
+ . map_err ( Error :: SetUserMemoryRegion ) ?;
643
+ } ;
578
644
} ;
579
645
self . next_mem_slot += 1 ;
580
646
}
0 commit comments