diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 880370caf9ed..0021c2862140 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -444,6 +444,15 @@ out_err_nodisable: | |||
444 | return ERR_PTR(r); | 444 | return ERR_PTR(r); |
445 | } | 445 | } |
446 | 446 | ||
447 | static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) | ||
448 | { | ||
449 | if (!memslot->dirty_bitmap) | ||
450 | return; | ||
451 | |||
452 | vfree(memslot->dirty_bitmap); | ||
453 | memslot->dirty_bitmap = NULL; | ||
454 | } | ||
455 | |||
447 | /* | 456 | /* |
448 | * Free any memory in @free but not in @dont. | 457 | * Free any memory in @free but not in @dont. |
449 | */ | 458 | */ |
@@ -456,7 +465,7 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free, | |||
456 | vfree(free->rmap); | 465 | vfree(free->rmap); |
457 | 466 | ||
458 | if (!dont || free->dirty_bitmap != dont->dirty_bitmap) | 467 | if (!dont || free->dirty_bitmap != dont->dirty_bitmap) |
459 | vfree(free->dirty_bitmap); | 468 | kvm_destroy_dirty_bitmap(free); |
460 | 469 | ||
461 | 470 | ||
462 | for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { | 471 | for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { |
@@ -467,7 +476,6 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free, | |||
467 | } | 476 | } |
468 | 477 | ||
469 | free->npages = 0; | 478 | free->npages = 0; |
470 | free->dirty_bitmap = NULL; | ||
471 | free->rmap = NULL; | 479 | free->rmap = NULL; |
472 | } | 480 | } |
473 | 481 | ||
@@ -529,6 +537,18 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) | |||
529 | return 0; | 537 | return 0; |
530 | } | 538 | } |
531 | 539 | ||
540 | static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) | ||
541 | { | ||
542 | unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot); | ||
543 | |||
544 | memslot->dirty_bitmap = vmalloc(dirty_bytes); | ||
545 | if (!memslot->dirty_bitmap) | ||
546 | return -ENOMEM; | ||
547 | |||
548 | memset(memslot->dirty_bitmap, 0, dirty_bytes); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
532 | /* | 552 | /* |
533 | * Allocate some memory and give it an address in the guest physical address | 553 | * Allocate some memory and give it an address in the guest physical address |
534 | * space. | 554 | * space. |
@@ -663,12 +683,8 @@ skip_lpage: | |||
663 | 683 | ||
664 | /* Allocate page dirty bitmap if needed */ | 684 | /* Allocate page dirty bitmap if needed */ |
665 | if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) { | 685 | if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) { |
666 | unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(&new); | 686 | if (kvm_create_dirty_bitmap(&new) < 0) |
667 | |||
668 | new.dirty_bitmap = vmalloc(dirty_bytes); | ||
669 | if (!new.dirty_bitmap) | ||
670 | goto out_free; | 687 | goto out_free; |
671 | memset(new.dirty_bitmap, 0, dirty_bytes); | ||
672 | /* destroy any largepage mappings for dirty tracking */ | 688 | /* destroy any largepage mappings for dirty tracking */ |
673 | if (old.npages) | 689 | if (old.npages) |
674 | flush_shadow = 1; | 690 | flush_shadow = 1; |