@@ -54,12 +54,21 @@ impl From<NoDatamatch> for u64 {
5454 }
5555}
5656
57+ /// Information about dirty log ring configuration.
58+ #[ derive( Debug ) ]
59+ struct DirtyLogRingInfo {
60+ /// Size of dirty ring in bytes.
61+ bytes : usize ,
62+ /// Whether to use acquire/release semantics.
63+ acq_rel : bool ,
64+ }
65+
5766/// Wrapper over KVM VM ioctls.
5867#[ derive( Debug ) ]
5968pub struct VmFd {
6069 vm : File ,
6170 run_size : usize ,
62- dirty_ring_bytes : usize ,
71+ dirty_log_ring_info : Option < DirtyLogRingInfo > ,
6372}
6473
6574impl VmFd {
@@ -1215,12 +1224,14 @@ impl VmFd {
12151224
12161225 let kvm_run_ptr = KvmRunWrapper :: mmap_from_fd ( & vcpu, self . run_size ) ?;
12171226
1218- let dirty_log_ring = {
1219- if self . dirty_ring_bytes > 0 {
1220- Some ( KvmDirtyLogRing :: mmap_from_fd ( & vcpu, self . dirty_ring_bytes ) ?)
1221- } else {
1222- None
1223- }
1227+ let dirty_log_ring = if let Some ( info) = & self . dirty_log_ring_info {
1228+ Some ( KvmDirtyLogRing :: mmap_from_fd (
1229+ & vcpu,
1230+ info. bytes ,
1231+ info. acq_rel ,
1232+ ) ?)
1233+ } else {
1234+ None
12241235 } ;
12251236
12261237 Ok ( new_vcpu ( vcpu, kvm_run_ptr, dirty_log_ring) )
@@ -1259,12 +1270,14 @@ impl VmFd {
12591270 // SAFETY: we trust the kernel and verified parameters
12601271 let vcpu = unsafe { File :: from_raw_fd ( fd) } ;
12611272 let kvm_run_ptr = KvmRunWrapper :: mmap_from_fd ( & vcpu, self . run_size ) ?;
1262- let dirty_log_ring = {
1263- if self . dirty_ring_bytes > 0 {
1264- Some ( KvmDirtyLogRing :: mmap_from_fd ( & vcpu, self . dirty_ring_bytes ) ?)
1265- } else {
1266- None
1267- }
1273+ let dirty_log_ring = if let Some ( info) = & self . dirty_log_ring_info {
1274+ Some ( KvmDirtyLogRing :: mmap_from_fd (
1275+ & vcpu,
1276+ info. bytes ,
1277+ info. acq_rel ,
1278+ ) ?)
1279+ } else {
1280+ None
12681281 } ;
12691282 Ok ( new_vcpu ( vcpu, kvm_run_ptr, dirty_log_ring) )
12701283 }
@@ -1931,15 +1944,15 @@ impl VmFd {
19311944 }
19321945
19331946 /// Enables KVM's dirty log ring for new vCPUs created on this VM. Checks required capabilities and returns
1934- /// `true` if the ring needs to be used together with a backup bitmap `KVM_GET_DIRTY_LOG`. Takes optional
1935- /// dirty ring size as bytes, if not supplied, will use maximum supported dirty ring size. Enabling the dirty
1936- /// log ring is only allowed before any vCPU was created on the VmFd.
1947+ /// a boolean `use_bitmap` as a result. `use_bitmap` is `true` if the ring needs to be used
1948+ /// together with a backup bitmap `KVM_GET_DIRTY_LOG`. Takes optional dirty ring size as bytes, if not supplied, will
1949+ /// use maximum supported dirty ring size. Enabling the dirty log ring is only allowed before any vCPU was
1950+ /// created on the VmFd.
19371951 /// # Arguments
19381952 ///
19391953 /// * `bytes` - Size of the dirty log ring in bytes. Needs to be multiple of `std::mem::size_of::<kvm_dirty_gfn>()`
19401954 /// and power of two.
1941- #[ cfg( target_arch = "x86_64" ) ]
1942- pub fn enable_dirty_log_ring ( & self , bytes : Option < i32 > ) -> Result < bool > {
1955+ pub fn enable_dirty_log_ring ( & mut self , bytes : Option < i32 > ) -> Result < bool > {
19431956 // Check if requested size is larger than 0
19441957 if let Some ( sz) = bytes {
19451958 if sz <= 0
@@ -1950,7 +1963,7 @@ impl VmFd {
19501963 }
19511964 }
19521965
1953- let ( dirty_ring_cap, max_bytes, bitmap ) = {
1966+ let ( dirty_ring_cap, max_bytes, use_bitmap ) = {
19541967 // Check if KVM_CAP_DIRTY_LOG_RING_ACQ_REL is available, enable if possible
19551968 let acq_rel_sz = self . check_extension_raw ( KVM_CAP_DIRTY_LOG_RING_ACQ_REL . into ( ) ) ;
19561969 if acq_rel_sz > 0 {
@@ -1987,11 +2000,12 @@ impl VmFd {
19872000 args : [ cap_ring_size as u64 , 0 , 0 , 0 ] ,
19882001 ..Default :: default ( )
19892002 } ;
2003+ let use_acq_rel = dirty_ring_cap == KVM_CAP_DIRTY_LOG_RING_ACQ_REL ;
19902004
19912005 // Enable the ring cap first
19922006 self . enable_cap ( & ar_ring_cap) ?;
19932007
1994- if bitmap {
2008+ if use_bitmap {
19952009 let with_bitmap_cap = kvm_enable_cap {
19962010 cap : KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP ,
19972011 ..Default :: default ( )
@@ -2001,7 +2015,12 @@ impl VmFd {
20012015 self . enable_cap ( & with_bitmap_cap) ?;
20022016 }
20032017
2004- Ok ( bitmap)
2018+ self . dirty_log_ring_info = Some ( DirtyLogRingInfo {
2019+ bytes : cap_ring_size as usize ,
2020+ acq_rel : use_acq_rel,
2021+ } ) ;
2022+
2023+ Ok ( use_bitmap)
20052024 }
20062025
20072026 /// Resets all vCPU's dirty log rings. This notifies the kernel that pages have been harvested
@@ -2013,7 +2032,7 @@ impl VmFd {
20132032 /// # extern crate kvm_ioctls;
20142033 /// # use kvm_ioctls::{Cap, Kvm};
20152034 /// let kvm = Kvm::new().unwrap();
2016- /// let vm = kvm.create_vm().unwrap();
2035+ /// let mut vm = kvm.create_vm().unwrap();
20172036 /// vm.enable_dirty_log_ring(None).unwrap();
20182037 /// if kvm.check_extension(Cap::DirtyLogRing) {
20192038 /// vm.reset_dirty_rings().unwrap();
@@ -2131,7 +2150,7 @@ pub fn new_vmfd(vm: File, run_size: usize) -> VmFd {
21312150 VmFd {
21322151 vm,
21332152 run_size,
2134- dirty_ring_bytes : 0 ,
2153+ dirty_log_ring_info : None ,
21352154 }
21362155}
21372156
@@ -2722,7 +2741,7 @@ mod tests {
27222741 let faulty_vm_fd = VmFd {
27232742 vm : unsafe { File :: from_raw_fd ( -2 ) } ,
27242743 run_size : 0 ,
2725- dirty_ring_bytes : 0 ,
2744+ dirty_log_ring_info : None ,
27262745 } ;
27272746
27282747 let invalid_mem_region = kvm_userspace_memory_region {
0 commit comments