kvm: return removed memory region

When a memory region is added to the guest, ownership is passed to the
Vm object.  However, it was not possible to get the memory region back
when removing it from the Vm.  Update the return type of
remove_memory_region so that the original boxed memory region can be
returned to the caller.

BUG=None
TEST=cargo test -p kvm

Change-Id: Ie39a57e0c037ed25a603865cb3dce1af1478e143
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2300840
Reviewed-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Tomasz Jeznach <tjeznach@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Zach Reizner <zachr@chromium.org>
This commit is contained in:
Daniel Verkamp 2020-06-29 14:13:37 -07:00 committed by Commit Bot
parent f4f8f86873
commit 05b13d0eff
3 changed files with 15 additions and 9 deletions

View file

@ -479,7 +479,7 @@ impl Vm for KvmVm {
})
}
fn remove_memory_region(&mut self, slot: MemSlot) -> Result<()> {
fn remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>> {
let mut regions = self.mem_regions.lock();
if !regions.contains_key(&slot) {
return Err(Error::new(ENOENT));
@ -489,8 +489,8 @@ impl Vm for KvmVm {
set_user_memory_region(&self.vm, slot, false, false, 0, 0, std::ptr::null_mut())?;
}
self.mem_slot_gaps.lock().push(MemSlotOrd(slot));
regions.remove(&slot);
Ok(())
// This remove will always succeed because of the contains_key check above.
Ok(regions.remove(&slot).unwrap())
}
fn create_device(&self, kind: DeviceKind) -> Result<SafeDescriptor> {
@ -1210,10 +1210,13 @@ mod tests {
let mut vm = KvmVm::new(&kvm, gm).unwrap();
let mem_size = 0x1000;
let mem = MemoryMapping::new(mem_size).unwrap();
let mem_ptr = mem.as_ptr();
let slot = vm
.add_memory_region(GuestAddress(0x1000), Box::new(mem), false, false)
.unwrap();
vm.remove_memory_region(slot).unwrap();
let removed_mem = vm.remove_memory_region(slot).unwrap();
assert_eq!(removed_mem.size(), mem_size);
assert_eq!(removed_mem.as_ptr(), mem_ptr);
}
#[test]

View file

@ -83,7 +83,7 @@ pub trait Vm: Send + Sized {
fn msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()>;
/// Removes and drops the `UserMemoryRegion` that was previously added at the given slot.
fn remove_memory_region(&mut self, slot: MemSlot) -> Result<()>;
fn remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>>;
/// Creates an emulated device.
fn create_device(&self, kind: DeviceKind) -> Result<SafeDescriptor>;

View file

@ -423,7 +423,7 @@ impl Vm {
/// Removes memory that was previously added at the given slot.
///
/// Ownership of the host memory mapping associated with the given slot is returned on success.
pub fn remove_memory_region(&mut self, slot: u32) -> Result<()> {
pub fn remove_memory_region(&mut self, slot: u32) -> Result<Box<dyn MappedRegion>> {
let mut regions = self.mem_regions.lock();
if !regions.contains_key(&slot) {
return Err(Error::new(ENOENT));
@ -433,8 +433,8 @@ impl Vm {
set_user_memory_region(&self.vm, slot, false, false, 0, 0, std::ptr::null_mut())?;
}
self.mem_slot_gaps.lock().push(MemSlot(slot));
regions.remove(&slot);
Ok(())
// This remove will always succeed because of the contains_key check above.
Ok(regions.remove(&slot).unwrap())
}
pub fn mysnc_memory_region(&mut self, slot: u32, offset: usize, size: usize) -> Result<()> {
@ -2107,10 +2107,13 @@ mod tests {
let mut vm = Vm::new(&kvm, gm).unwrap();
let mem_size = 0x1000;
let mem = MemoryMapping::new(mem_size).unwrap();
let mem_ptr = mem.as_ptr();
let slot = vm
.add_memory_region(GuestAddress(0x1000), Box::new(mem), false, false)
.unwrap();
vm.remove_memory_region(slot).unwrap();
let removed_mem = vm.remove_memory_region(slot).unwrap();
assert_eq!(removed_mem.size(), mem_size);
assert_eq!(removed_mem.as_ptr(), mem_ptr);
}
#[test]