@@ -10,6 +10,7 @@ use libc::{c_int, c_void, siginfo_t};
10
10
use std:: cell:: Cell ;
11
11
use std:: fmt:: { Display , Formatter } ;
12
12
use std:: io;
13
+ use std:: os:: fd:: RawFd ;
13
14
14
15
#[ cfg( feature = "tee" ) ]
15
16
use std:: os:: unix:: io:: RawFd ;
@@ -46,7 +47,10 @@ use kvm_bindings::{
46
47
Msrs , KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
47
48
KVM_MAX_CPUID_ENTRIES , KVM_PIT_SPEAKER_DUMMY ,
48
49
} ;
49
- use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
50
+ use kvm_bindings:: {
51
+ kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
52
+ KVM_API_VERSION , KVM_MEM_GUEST_MEMFD ,
53
+ } ;
50
54
use kvm_ioctls:: * ;
51
55
use utils:: eventfd:: EventFd ;
52
56
use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
@@ -111,6 +115,10 @@ pub enum Error {
111
115
SetupGIC ( arch:: aarch64:: gic:: Error ) ,
112
116
/// Cannot set the memory regions.
113
117
SetUserMemoryRegion ( kvm_ioctls:: Error ) ,
118
+ /// Cannot set the memory regions.
119
+ SetUserMemoryRegion2 ( kvm_ioctls:: Error ) ,
120
+ // Cannot create guest memfd.
121
+ CreateGuestMemfd ( kvm_ioctls:: Error ) ,
114
122
#[ cfg( feature = "amd-sev" ) ]
115
123
/// Error initializing the Secure Virtualization Backend (SEV).
116
124
SevSecVirtInit ( SevError ) ,
@@ -270,6 +278,8 @@ impl Display for Error {
270
278
"Cannot set the local interruption due to bad configuration: {e:?}"
271
279
) ,
272
280
SetUserMemoryRegion ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
281
+ SetUserMemoryRegion2 ( e) => write ! ( f, "Cannot set the memory regions: {e}" ) ,
282
+ CreateGuestMemfd ( e) => write ! ( f, "Cannot create guest memfd: {e}" ) ,
273
283
#[ cfg( feature = "tee" ) ]
274
284
SevSecVirtInit ( e) => {
275
285
write ! (
@@ -549,6 +559,7 @@ impl Vm {
549
559
& mut self ,
550
560
guest_mem : & GuestMemoryMmap ,
551
561
kvm_max_memslots : usize ,
562
+ require_guest_memfd : bool ,
552
563
) -> Result < ( ) > {
553
564
if guest_mem. num_regions ( ) > kvm_max_memslots {
554
565
return Err ( Error :: NotEnoughMemorySlots ) ;
@@ -557,19 +568,53 @@ impl Vm {
557
568
// It's safe to unwrap because the guest address is valid.
558
569
let host_addr = guest_mem. get_host_address ( region. start_addr ( ) ) . unwrap ( ) ;
559
570
info ! ( "Guest memory starts at {:x?}" , host_addr) ;
560
- let memory_region = kvm_userspace_memory_region {
561
- slot : index as u32 ,
562
- guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
563
- memory_size : region. len ( ) ,
564
- userspace_addr : host_addr as u64 ,
565
- flags : 0 ,
566
- } ;
567
- // Safe because we mapped the memory region, we made sure that the regions
568
- // are not overlapping.
569
- unsafe {
570
- self . fd
571
- . set_user_memory_region ( memory_region)
572
- . map_err ( Error :: SetUserMemoryRegion ) ?;
571
+
572
+ if require_guest_memfd {
573
+ let gmem = kvm_create_guest_memfd {
574
+ size : region. len ( ) ,
575
+ flags : 0 ,
576
+ reserved : [ 0 ; 6 ] ,
577
+ } ;
578
+
579
+ let id: RawFd = self
580
+ . fd
581
+ . create_guest_memfd ( gmem)
582
+ . map_err ( Error :: CreateGuestMemfd ) ?;
583
+
584
+ let memory_region = kvm_userspace_memory_region2 {
585
+ slot : index as u32 ,
586
+ flags : KVM_MEM_GUEST_MEMFD ,
587
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
588
+ memory_size : region. len ( ) ,
589
+ userspace_addr : host_addr as u64 ,
590
+ guest_memfd_offset : 0 ,
591
+ guest_memfd : id as u32 ,
592
+ pad1 : 0 ,
593
+ pad2 : [ 0 ; 14 ] ,
594
+ } ;
595
+
596
+ // Safe because we mapped the memory region, we made sure that the regions
597
+ // are not overlapping.
598
+ unsafe {
599
+ self . fd
600
+ . set_user_memory_region2 ( memory_region)
601
+ . map_err ( Error :: SetUserMemoryRegion2 ) ?;
602
+ } ;
603
+ } else {
604
+ let memory_region = kvm_userspace_memory_region {
605
+ slot : index as u32 ,
606
+ guest_phys_addr : region. start_addr ( ) . raw_value ( ) ,
607
+ memory_size : region. len ( ) ,
608
+ userspace_addr : host_addr as u64 ,
609
+ flags : 0 ,
610
+ } ;
611
+ // Safe because we mapped the memory region, we made sure that the regions
612
+ // are not overlapping.
613
+ unsafe {
614
+ self . fd
615
+ . set_user_memory_region ( memory_region)
616
+ . map_err ( Error :: SetUserMemoryRegion ) ?;
617
+ } ;
573
618
} ;
574
619
}
575
620
@@ -1505,7 +1550,7 @@ mod tests {
1505
1550
let kvm = KvmContext :: new ( ) . unwrap ( ) ;
1506
1551
let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , mem_size) ] ) . unwrap ( ) ;
1507
1552
let mut vm = Vm :: new ( kvm. fd ( ) ) . expect ( "Cannot create new vm" ) ;
1508
- assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) ) . is_ok( ) ) ;
1553
+ assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) , false ) . is_ok( ) ) ;
1509
1554
1510
1555
let exit_evt = EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK ) . unwrap ( ) ;
1511
1556
@@ -1560,7 +1605,7 @@ mod tests {
1560
1605
1561
1606
// Create valid memory region and test that the initialization is successful.
1562
1607
let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] ) . unwrap ( ) ;
1563
- assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) ) . is_ok( ) ) ;
1608
+ assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) , false ) . is_ok( ) ) ;
1564
1609
1565
1610
// Set the maximum number of memory slots to 1 in KvmContext to check the error
1566
1611
// path of memory_init. Create 2 non-overlapping memory slots.
@@ -1570,7 +1615,7 @@ mod tests {
1570
1615
( GuestAddress ( 0x1001 ) , 0x2000 ) ,
1571
1616
] )
1572
1617
. unwrap ( ) ;
1573
- assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) ) . is_err( ) ) ;
1618
+ assert ! ( vm. memory_init( & gm, kvm_context. max_memslots( ) , false ) . is_err( ) ) ;
1574
1619
}
1575
1620
1576
1621
#[ cfg( target_arch = "x86_64" ) ]
@@ -1651,7 +1696,7 @@ mod tests {
1651
1696
let kvm = KvmContext :: new ( ) . unwrap ( ) ;
1652
1697
let gm = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( ) ;
1653
1698
let mut vm = Vm :: new ( kvm. fd ( ) ) . expect ( "new vm failed" ) ;
1654
- assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) ) . is_ok( ) ) ;
1699
+ assert ! ( vm. memory_init( & gm, kvm. max_memslots( ) , false ) . is_ok( ) ) ;
1655
1700
1656
1701
// Try it for when vcpu id is 0.
1657
1702
let mut vcpu = Vcpu :: new_aarch64 (
0 commit comments