@@ -9,6 +9,7 @@ use std::collections::HashMap;
9
9
use std:: fs:: OpenOptions ;
10
10
use std:: io:: Write ;
11
11
use std:: path:: Path ;
12
+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
12
13
use std:: sync:: { Arc , Mutex , MutexGuard } ;
13
14
14
15
use anyhow:: anyhow;
@@ -55,6 +56,7 @@ pub struct VmCommon {
55
56
max_memslots : u32 ,
56
57
/// The guest memory of this Vm.
57
58
pub guest_memory : GuestMemoryMmap ,
59
+ next_kvm_slot : AtomicU32 ,
58
60
/// Interrupts used by Vm's devices
59
61
pub interrupts : Mutex < HashMap < u32 , RoutingEntry > > ,
60
62
/// Allocator for VM resources
@@ -134,6 +136,7 @@ impl Vm {
134
136
fd,
135
137
max_memslots : kvm. max_nr_memslots ( ) ,
136
138
guest_memory : GuestMemoryMmap :: default ( ) ,
139
+ next_kvm_slot : AtomicU32 :: new ( 0 ) ,
137
140
interrupts : Mutex :: new ( HashMap :: with_capacity ( GSI_MSI_END as usize + 1 ) ) ,
138
141
resource_allocator : Mutex :: new ( ResourceAllocator :: new ( ) ) ,
139
142
mmio_bus : Arc :: new ( Bus :: new ( ) ) ,
@@ -160,6 +163,17 @@ impl Vm {
160
163
Ok ( ( vcpus, exit_evt) )
161
164
}
162
165
166
+ /// Obtain the next free kvm slot id
167
+ pub fn next_kvm_slot ( & self ) -> Option < u32 > {
168
+ let next = self . common . next_kvm_slot . load ( Ordering :: Relaxed ) ;
169
+ if next == self . common . max_memslots {
170
+ None
171
+ } else {
172
+ self . common . next_kvm_slot . store ( next + 1 , Ordering :: Relaxed ) ;
173
+ Some ( next)
174
+ }
175
+ }
176
+
163
177
/// Register a list of new memory regions to this [`Vm`].
164
178
pub fn register_memory_regions (
165
179
& mut self ,
@@ -175,13 +189,8 @@ impl Vm {
175
189
/// Register a new memory region to this [`Vm`].
176
190
pub fn register_memory_region ( & mut self , region : GuestRegionMmap ) -> Result < ( ) , VmError > {
177
191
let next_slot = self
178
- . guest_memory ( )
179
- . num_regions ( )
180
- . try_into ( )
181
- . expect ( "Number of existing memory regions exceeds u32::MAX" ) ;
182
- if self . common . max_memslots <= next_slot {
183
- return Err ( VmError :: NotEnoughMemorySlots ( self . common . max_memslots ) ) ;
184
- }
192
+ . next_kvm_slot ( )
193
+ . ok_or ( VmError :: NotEnoughMemorySlots ( self . common . max_memslots ) ) ?;
185
194
186
195
let flags = if region. bitmap ( ) . is_some ( ) {
187
196
KVM_MEM_LOG_DIRTY_PAGES
0 commit comments