Commit 4495d6a74575b4ee7e9aabdc66e67b6c9e19a698
Committed by
Anthony Liguori
1 parent
e69917e2
kvm: Introduce kvm_set_migration_log
Introduce a global dirty logging flag that enforces logging for all slots. This can be used by the live migration code to enable/disable global logging withouth destroying the per-slot setting. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
2 changed files
with
40 additions
and
7 deletions
kvm-all.c
| @@ -58,6 +58,7 @@ struct KVMState | @@ -58,6 +58,7 @@ struct KVMState | ||
| 58 | int vmfd; | 58 | int vmfd; |
| 59 | int coalesced_mmio; | 59 | int coalesced_mmio; |
| 60 | int broken_set_mem_region; | 60 | int broken_set_mem_region; |
| 61 | + int migration_log; | ||
| 61 | #ifdef KVM_CAP_SET_GUEST_DEBUG | 62 | #ifdef KVM_CAP_SET_GUEST_DEBUG |
| 62 | struct kvm_sw_breakpoint_head kvm_sw_breakpoints; | 63 | struct kvm_sw_breakpoint_head kvm_sw_breakpoints; |
| 63 | #endif | 64 | #endif |
| @@ -135,7 +136,9 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) | @@ -135,7 +136,9 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) | ||
| 135 | mem.memory_size = slot->memory_size; | 136 | mem.memory_size = slot->memory_size; |
| 136 | mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset); | 137 | mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset); |
| 137 | mem.flags = slot->flags; | 138 | mem.flags = slot->flags; |
| 138 | - | 139 | + if (s->migration_log) { |
| 140 | + mem.flags |= KVM_MEM_LOG_DIRTY_PAGES; | ||
| 141 | + } | ||
| 139 | return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); | 142 | return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); |
| 140 | } | 143 | } |
| 141 | 144 | ||
| @@ -196,11 +199,12 @@ int kvm_sync_vcpus(void) | @@ -196,11 +199,12 @@ int kvm_sync_vcpus(void) | ||
| 196 | * dirty pages logging control | 199 | * dirty pages logging control |
| 197 | */ | 200 | */ |
| 198 | static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, | 201 | static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, |
| 199 | - ram_addr_t size, unsigned flags, | ||
| 200 | - unsigned mask) | 202 | + ram_addr_t size, int flags, int mask) |
| 201 | { | 203 | { |
| 202 | KVMState *s = kvm_state; | 204 | KVMState *s = kvm_state; |
| 203 | KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size); | 205 | KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size); |
| 206 | + int old_flags; | ||
| 207 | + | ||
| 204 | if (mem == NULL) { | 208 | if (mem == NULL) { |
| 205 | fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" | 209 | fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" |
| 206 | TARGET_FMT_plx "\n", __func__, phys_addr, | 210 | TARGET_FMT_plx "\n", __func__, phys_addr, |
| @@ -208,13 +212,19 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, | @@ -208,13 +212,19 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, | ||
| 208 | return -EINVAL; | 212 | return -EINVAL; |
| 209 | } | 213 | } |
| 210 | 214 | ||
| 211 | - flags = (mem->flags & ~mask) | flags; | ||
| 212 | - /* Nothing changed, no need to issue ioctl */ | ||
| 213 | - if (flags == mem->flags) | ||
| 214 | - return 0; | 215 | + old_flags = mem->flags; |
| 215 | 216 | ||
| 217 | + flags = (mem->flags & ~mask) | flags; | ||
| 216 | mem->flags = flags; | 218 | mem->flags = flags; |
| 217 | 219 | ||
| 220 | + /* If nothing changed effectively, no need to issue ioctl */ | ||
| 221 | + if (s->migration_log) { | ||
| 222 | + flags |= KVM_MEM_LOG_DIRTY_PAGES; | ||
| 223 | + } | ||
| 224 | + if (flags == old_flags) { | ||
| 225 | + return 0; | ||
| 226 | + } | ||
| 227 | + | ||
| 218 | return kvm_set_user_memory_region(s, mem); | 228 | return kvm_set_user_memory_region(s, mem); |
| 219 | } | 229 | } |
| 220 | 230 | ||
| @@ -232,6 +242,28 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size) | @@ -232,6 +242,28 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size) | ||
| 232 | KVM_MEM_LOG_DIRTY_PAGES); | 242 | KVM_MEM_LOG_DIRTY_PAGES); |
| 233 | } | 243 | } |
| 234 | 244 | ||
| 245 | +int kvm_set_migration_log(int enable) | ||
| 246 | +{ | ||
| 247 | + KVMState *s = kvm_state; | ||
| 248 | + KVMSlot *mem; | ||
| 249 | + int i, err; | ||
| 250 | + | ||
| 251 | + s->migration_log = enable; | ||
| 252 | + | ||
| 253 | + for (i = 0; i < ARRAY_SIZE(s->slots); i++) { | ||
| 254 | + mem = &s->slots[i]; | ||
| 255 | + | ||
| 256 | + if (!!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES) == enable) { | ||
| 257 | + continue; | ||
| 258 | + } | ||
| 259 | + err = kvm_set_user_memory_region(s, mem); | ||
| 260 | + if (err) { | ||
| 261 | + return err; | ||
| 262 | + } | ||
| 263 | + } | ||
| 264 | + return 0; | ||
| 265 | +} | ||
| 266 | + | ||
| 235 | /** | 267 | /** |
| 236 | * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space | 268 | * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space |
| 237 | * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty(). | 269 | * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty(). |
kvm.h
| @@ -45,6 +45,7 @@ void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | @@ -45,6 +45,7 @@ void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, | ||
| 45 | 45 | ||
| 46 | int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); | 46 | int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size); |
| 47 | int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); | 47 | int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); |
| 48 | +int kvm_set_migration_log(int enable); | ||
| 48 | 49 | ||
| 49 | int kvm_has_sync_mmu(void); | 50 | int kvm_has_sync_mmu(void); |
| 50 | 51 |