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 |