vmm: Add dirty pages tracked by vm_memory::bitmap to live migration

Live migration currently handles guest memory writes from the guest
through the KVM dirty page tracking and sends those dirty pages to the
destination. This patch augments the live migration support with dirty
page tracking of writes from the VMM to the guest memory(e.g. virtio
devices).

Fixes: #2458

Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
Bo Chen 2021-05-25 13:34:49 -07:00 committed by Rob Bradford
parent 2c4fa258a6
commit 7839e121f6

View File

@ -1477,9 +1477,29 @@ impl MemoryManager {
let page_size = 4096; // TODO: Does this need to vary?
let mut table = MemoryRangeTable::default();
for r in &self.guest_ram_mappings {
let dirty_bitmap = self.vm.get_dirty_log(r.slot, r.size).map_err(|e| {
let vm_dirty_bitmap = self.vm.get_dirty_log(r.slot, r.size).map_err(|e| {
MigratableError::MigrateSend(anyhow!("Error getting VM dirty log {}", e))
})?;
let vmm_dirty_bitmap = match self.guest_memory.memory().find_region(GuestAddress(r.gpa))
{
Some(region) => {
assert!(region.start_addr().raw_value() == r.gpa);
assert!(region.len() == r.size);
region.bitmap().get_and_reset()
}
None => {
return Err(MigratableError::MigrateSend(anyhow!(
"Error finding 'guest memory region' with address {:x}",
r.gpa
)))
}
};
let dirty_bitmap: Vec<u64> = vm_dirty_bitmap
.iter()
.zip(vmm_dirty_bitmap.iter())
.map(|(x, y)| x | y)
.collect();
let mut entry: Option<MemoryRange> = None;
for (i, block) in dirty_bitmap.iter().enumerate() {
@ -1525,6 +1545,11 @@ impl MemoryManager {
MigratableError::MigrateSend(anyhow!("Error getting VM dirty log {}", e))
})?;
}
for r in self.guest_memory.memory().iter() {
r.bitmap().reset();
}
Ok(())
}
}