@@ -45,15 +45,17 @@ use kvm_bindings::{
45
45
} ;
46
46
#[ cfg( feature = "tee" ) ]
47
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 ,
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 ,
50
51
} ;
51
- use kvm_ioctls:: * ;
52
+ use kvm_ioctls:: { Cap :: * , * } ;
52
53
use utils:: eventfd:: EventFd ;
53
54
use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
54
55
use utils:: sm:: StateMachine ;
55
56
use vm_memory:: {
56
57
Address , GuestAddress , GuestMemory , GuestMemoryError , GuestMemoryMmap , GuestMemoryRegion ,
58
+ GuestRegionMmap ,
57
59
} ;
58
60
59
61
#[ cfg( feature = "amd-sev" ) ]
@@ -68,6 +70,8 @@ pub enum Error {
68
70
#[ cfg( target_arch = "x86_64" ) ]
69
71
/// A call to cpuid instruction failed.
70
72
CpuId ( cpuid:: Error ) ,
73
+ /// Unable to create a KVM guest_memfd.
74
+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
71
75
#[ cfg( target_arch = "x86_64" ) ]
72
76
/// Error configuring the floating point related registers
73
77
FPUConfiguration ( arch:: x86_64:: regs:: Error ) ,
@@ -104,16 +108,12 @@ pub enum Error {
104
108
#[ cfg( target_arch = "x86_64" ) ]
105
109
/// Error configuring the general purpose registers
106
110
REGSConfiguration ( arch:: x86_64:: regs:: Error ) ,
111
+ /// Cannot set memory region attributes.
112
+ SetMemoryAttributes ( kvm_ioctls:: Error ) ,
107
113
/// Cannot set the memory regions.
108
114
SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
109
115
/// Error creating memory map for SHM region.
110
116
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 ) ,
117
117
#[ cfg( feature = "amd-sev" ) ]
118
118
/// Error initializing the Secure Virtualization Backend (SNP).
119
119
SnpSecVirtInit ( SnpError ) ,
@@ -239,6 +239,7 @@ impl Display for Error {
239
239
match self {
240
240
#[ cfg( target_arch = "x86_64" ) ]
241
241
CpuId ( e) => write ! ( f, "Cpuid error: {e:?}" ) ,
242
+ CreateGuestMemfd ( e) => write ! ( f, "Unable to create KVM guest_memfd: {e:?}" ) ,
242
243
GuestMemoryMmap ( e) => write ! ( f, "Guest memory error: {e:?}" ) ,
243
244
#[ cfg( target_arch = "x86_64" ) ]
244
245
GuestMSRs ( e) => write ! ( f, "Retrieving supported guest MSRs fails: {e:?}" ) ,
@@ -263,13 +264,10 @@ impl Display for Error {
263
264
f,
264
265
"Cannot set the local interruption due to bad configuration: {e:?}"
265
266
) ,
267
+ SetMemoryAttributes ( e) => write ! ( f, "Cannot set memory region attributes: {e}" ) ,
266
268
SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
267
269
ShmMmap ( e) => write ! ( f, "Error creating memory map for SHM region: {e}" ) ,
268
270
#[ 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" ) ]
273
271
SnpSecVirtInit ( e) => write ! (
274
272
f,
275
273
"Error initializing the Secure Virtualization Backend (SEV): {e:?}"
@@ -393,7 +391,6 @@ pub struct KvmContext {
393
391
394
392
impl KvmContext {
395
393
pub fn new ( ) -> Result < Self > {
396
- use kvm_ioctls:: Cap :: * ;
397
394
let kvm = Kvm :: new ( ) . expect ( "Error creating the Kvm object" ) ;
398
395
399
396
// Check that KVM has the correct version.
@@ -520,80 +517,14 @@ impl Vm {
520
517
pub fn memory_init (
521
518
& mut self ,
522
519
guest_mem : & GuestMemoryMmap ,
523
- #[ cfg( feature = "tee" ) ] guest_memfd : & mut Vec < RawFd > ,
524
520
kvm_max_memslots : usize ,
525
521
) -> Result < ( ) > {
526
522
if guest_mem. num_regions ( ) > kvm_max_memslots {
527
523
return Err ( Error :: NotEnoughMemorySlots ) ;
528
524
}
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) ;
533
525
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) ?;
597
528
}
598
529
599
530
#[ cfg( target_arch = "x86_64" ) ]
@@ -604,6 +535,76 @@ impl Vm {
604
535
Ok ( ( ) )
605
536
}
606
537
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
+
607
608
#[ cfg( feature = "amd-sev" ) ]
608
609
pub fn snp_secure_virt_prepare (
609
610
& self ,
0 commit comments