@@ -40,6 +40,12 @@ use kvm_bindings::{
40
40
KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
41
41
KVM_MAX_CPUID_ENTRIES ,
42
42
} ;
43
+ #[ cfg( feature = "tee" ) ]
44
+ use kvm_bindings:: {
45
+ kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, KVM_API_VERSION ,
46
+ KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEM_GUEST_MEMFD ,
47
+ } ;
48
+ #[ cfg( not( feature = "tee" ) ) ]
43
49
use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
44
50
use kvm_ioctls:: * ;
45
51
use utils:: eventfd:: EventFd ;
@@ -101,6 +107,12 @@ pub enum Error {
101
107
SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
102
108
/// Error creating memory map for SHM region.
103
109
ShmMmap ( io:: Error ) ,
110
+ #[ cfg( feature = "tee" ) ]
111
+ /// Cannot set the memory regions.
112
+ SetUserMemoryRegion2 ( kvm_ioctls:: Error ) ,
113
+ #[ cfg( feature = "tee" ) ]
114
+ /// Cannot create guest memfd.
115
+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
104
116
#[ cfg( feature = "amd-sev" ) ]
105
117
/// Error initializing the Secure Virtualization Backend (SNP).
106
118
SnpSecVirtInit ( SnpError ) ,
@@ -253,6 +265,10 @@ impl Display for Error {
253
265
SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
254
266
ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
255
267
#[ cfg( feature = "tee" ) ]
268
+ SetUserMemoryRegion2 ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
269
+ #[ cfg( feature = "tee" ) ]
270
+ CreateGuestMemfd ( e) => write ! ( f, "Cannot create guest memfd: {e}" ) ,
271
+ #[ cfg( feature = "tee" ) ]
256
272
SnpSecVirtInit ( e) => write ! (
257
273
f,
258
274
"Error initializing the Secure Virtualization Backend (SEV): {e:?}"
@@ -503,6 +519,7 @@ impl Vm {
503
519
pub fn memory_init (
504
520
& mut self ,
505
521
guest_mem : & GuestMemoryMmap ,
522
+ #[ cfg( feature = "tee" ) ] guest_memfd : & mut Vec < RawFd > ,
506
523
kvm_max_memslots : usize ,
507
524
) -> Result < ( ) > {
508
525
if guest_mem. num_regions ( ) > kvm_max_memslots {
@@ -511,20 +528,69 @@ impl Vm {
511
528
for region in guest_mem. iter ( ) {
512
529
// It's safe to unwrap because the guest address is valid.
513
530
let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
514
- debug ! ( "Guest memory starts at {:x?}" , host_addr) ;
515
- let memory_region = kvm_userspace_memory_region {
516
- slot : self . next_mem_slot ,
517
- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
518
- memory_size : region. len ( ) ,
519
- userspace_addr : host_addr as u64 ,
520
- flags : 0 ,
521
- } ;
522
- // Safe because we mapped the memory region, we made sure that the regions
523
- // are not overlapping.
524
- unsafe {
525
- self . fd
526
- . set_user_memory_region ( memory_region)
527
- . map_err ( Error :: SetUserMemoryRegion ) ?;
531
+ info ! ( "Guest memory starts at {:x?}" , host_addr) ;
532
+
533
+ #[ cfg( feature = "tee" ) ]
534
+ {
535
+ let gmem = kvm_create_guest_memfd {
536
+ size : region. len ( ) ,
537
+ flags : 0 ,
538
+ reserved : [ 0 ; 6 ] ,
539
+ } ;
540
+
541
+ let id: RawFd = self
542
+ . fd
543
+ . create_guest_memfd ( gmem)
544
+ . map_err ( Error :: CreateGuestMemfd ) ?;
545
+
546
+ guest_memfd. push ( id) ;
547
+
548
+ let memory_region = kvm_userspace_memory_region2 {
549
+ slot : self . next_mem_slot as u32 ,
550
+ flags : KVM_MEM_GUEST_MEMFD ,
551
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
552
+ memory_size : region. len ( ) ,
553
+ userspace_addr : host_addr as u64 ,
554
+ guest_memfd_offset : 0 ,
555
+ guest_memfd : id as u32 ,
556
+ pad1 : 0 ,
557
+ pad2 : [ 0 ; 14 ] ,
558
+ } ;
559
+
560
+ // Safe because we mapped the memory region, we made sure that the regions
561
+ // are not overlapping.
562
+ unsafe {
563
+ self . fd
564
+ . set_user_memory_region2 ( memory_region)
565
+ . map_err ( Error :: SetUserMemoryRegion2 ) ?;
566
+ } ;
567
+
568
+ // set private by default when using guestmemfd
569
+ // this imitates QEMU behavior
570
+ let attr = kvm_memory_attributes {
571
+ address : region. start_addr ( ) . raw_value ( ) ,
572
+ size : region. len ( ) ,
573
+ attributes : KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 ,
574
+ flags : 0 ,
575
+ } ;
576
+ self . fd . set_memory_attributes ( attr) . unwrap ( ) ;
577
+ }
578
+ #[ cfg( not( feature = "tee" ) ) ]
579
+ {
580
+ let memory_region = kvm_userspace_memory_region {
581
+ slot : self . next_mem_slot as u32 ,
582
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
583
+ memory_size : region. len ( ) ,
584
+ userspace_addr : host_addr as u64 ,
585
+ flags : 0 ,
586
+ } ;
587
+ // Safe because we mapped the memory region, we made sure that the regions
588
+ // are not overlapping.
589
+ unsafe {
590
+ self . fd
591
+ . set_user_memory_region ( memory_region)
592
+ . map_err ( Error :: SetUserMemoryRegion ) ?;
593
+ } ;
528
594
} ;
529
595
self . next_mem_slot += 1 ;
530
596
}
0 commit comments