@@ -43,6 +43,11 @@ use kvm_bindings::{
43
43
use kvm_bindings:: {
44
44
kvm_userspace_memory_region, KVM_API_VERSION , KVM_SYSTEM_EVENT_RESET , KVM_SYSTEM_EVENT_SHUTDOWN ,
45
45
} ;
46
+ #[ cfg( feature = "tee" ) ]
47
+ use 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 ,
50
+ } ;
46
51
use kvm_ioctls:: * ;
47
52
use utils:: eventfd:: EventFd ;
48
53
use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
@@ -103,6 +108,12 @@ pub enum Error {
103
108
SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
104
109
/// Error creating memory map for SHM region.
105
110
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 ) ,
106
117
#[ cfg( feature = "amd-sev" ) ]
107
118
/// Error initializing the Secure Virtualization Backend (SNP).
108
119
SnpSecVirtInit ( SnpError ) ,
@@ -255,6 +266,10 @@ impl Display for Error {
255
266
SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
256
267
ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
257
268
#[ 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" ) ]
258
273
SnpSecVirtInit ( e) => write ! (
259
274
f,
260
275
"Error initializing the Secure Virtualization Backend (SEV): {e:?}"
@@ -505,6 +520,7 @@ impl Vm {
505
520
pub fn memory_init (
506
521
& mut self ,
507
522
guest_mem : & GuestMemoryMmap ,
523
+ #[ cfg( feature = "tee" ) ] guest_memfd : & mut Vec < RawFd > ,
508
524
kvm_max_memslots : usize ,
509
525
) -> Result < ( ) > {
510
526
if guest_mem. num_regions ( ) > kvm_max_memslots {
@@ -513,20 +529,69 @@ impl Vm {
513
529
for region in guest_mem. iter ( ) {
514
530
// It's safe to unwrap because the guest address is valid.
515
531
let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
516
- debug ! ( "Guest memory starts at {:x?}" , host_addr) ;
517
- let memory_region = kvm_userspace_memory_region {
518
- slot : self . next_mem_slot ,
519
- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
520
- memory_size : region. len ( ) ,
521
- userspace_addr : host_addr as u64 ,
522
- flags : 0 ,
523
- } ;
524
- // Safe because we mapped the memory region, we made sure that the regions
525
- // are not overlapping.
526
- unsafe {
527
- self . fd
528
- . set_user_memory_region ( memory_region)
529
- . map_err ( Error :: SetUserMemoryRegion ) ?;
532
+ info ! ( "Guest memory starts at {:x?}" , host_addr) ;
533
+
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
+ } ;
530
595
} ;
531
596
self . next_mem_slot += 1 ;
532
597
}
0 commit comments