diff options
Diffstat (limited to 'drivers/kvm')
-rw-r--r-- | drivers/kvm/kvm.h | 2 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 38 |
2 files changed, 3 insertions, 37 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index ee9f8bdee755..351da40807c5 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -411,8 +411,6 @@ struct kvm { | |||
411 | int n_free_mmu_pages; | 411 | int n_free_mmu_pages; |
412 | struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; | 412 | struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; |
413 | struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; | 413 | struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; |
414 | int memory_config_version; | ||
415 | int busy; | ||
416 | unsigned long rmap_overflow; | 414 | unsigned long rmap_overflow; |
417 | struct list_head vm_list; | 415 | struct list_head vm_list; |
418 | struct file *filp; | 416 | struct file *filp; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 9dffbbea46a7..8da13a462e3c 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -679,7 +679,6 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, | |||
679 | unsigned long i; | 679 | unsigned long i; |
680 | struct kvm_memory_slot *memslot; | 680 | struct kvm_memory_slot *memslot; |
681 | struct kvm_memory_slot old, new; | 681 | struct kvm_memory_slot old, new; |
682 | int memory_config_version; | ||
683 | 682 | ||
684 | r = -EINVAL; | 683 | r = -EINVAL; |
685 | /* General sanity checks */ | 684 | /* General sanity checks */ |
@@ -699,10 +698,8 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, | |||
699 | if (!npages) | 698 | if (!npages) |
700 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; | 699 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; |
701 | 700 | ||
702 | raced: | ||
703 | mutex_lock(&kvm->lock); | 701 | mutex_lock(&kvm->lock); |
704 | 702 | ||
705 | memory_config_version = kvm->memory_config_version; | ||
706 | new = old = *memslot; | 703 | new = old = *memslot; |
707 | 704 | ||
708 | new.base_gfn = base_gfn; | 705 | new.base_gfn = base_gfn; |
@@ -725,11 +722,6 @@ raced: | |||
725 | (base_gfn >= s->base_gfn + s->npages))) | 722 | (base_gfn >= s->base_gfn + s->npages))) |
726 | goto out_unlock; | 723 | goto out_unlock; |
727 | } | 724 | } |
728 | /* | ||
729 | * Do memory allocations outside lock. memory_config_version will | ||
730 | * detect any races. | ||
731 | */ | ||
732 | mutex_unlock(&kvm->lock); | ||
733 | 725 | ||
734 | /* Deallocate if slot is being removed */ | 726 | /* Deallocate if slot is being removed */ |
735 | if (!npages) | 727 | if (!npages) |
@@ -746,14 +738,14 @@ raced: | |||
746 | new.phys_mem = vmalloc(npages * sizeof(struct page *)); | 738 | new.phys_mem = vmalloc(npages * sizeof(struct page *)); |
747 | 739 | ||
748 | if (!new.phys_mem) | 740 | if (!new.phys_mem) |
749 | goto out_free; | 741 | goto out_unlock; |
750 | 742 | ||
751 | memset(new.phys_mem, 0, npages * sizeof(struct page *)); | 743 | memset(new.phys_mem, 0, npages * sizeof(struct page *)); |
752 | for (i = 0; i < npages; ++i) { | 744 | for (i = 0; i < npages; ++i) { |
753 | new.phys_mem[i] = alloc_page(GFP_HIGHUSER | 745 | new.phys_mem[i] = alloc_page(GFP_HIGHUSER |
754 | | __GFP_ZERO); | 746 | | __GFP_ZERO); |
755 | if (!new.phys_mem[i]) | 747 | if (!new.phys_mem[i]) |
756 | goto out_free; | 748 | goto out_unlock; |
757 | set_page_private(new.phys_mem[i],0); | 749 | set_page_private(new.phys_mem[i],0); |
758 | } | 750 | } |
759 | } | 751 | } |
@@ -764,27 +756,14 @@ raced: | |||
764 | 756 | ||
765 | new.dirty_bitmap = vmalloc(dirty_bytes); | 757 | new.dirty_bitmap = vmalloc(dirty_bytes); |
766 | if (!new.dirty_bitmap) | 758 | if (!new.dirty_bitmap) |
767 | goto out_free; | 759 | goto out_unlock; |
768 | memset(new.dirty_bitmap, 0, dirty_bytes); | 760 | memset(new.dirty_bitmap, 0, dirty_bytes); |
769 | } | 761 | } |
770 | 762 | ||
771 | mutex_lock(&kvm->lock); | ||
772 | |||
773 | if (memory_config_version != kvm->memory_config_version) { | ||
774 | mutex_unlock(&kvm->lock); | ||
775 | kvm_free_physmem_slot(&new, &old); | ||
776 | goto raced; | ||
777 | } | ||
778 | |||
779 | r = -EAGAIN; | ||
780 | if (kvm->busy) | ||
781 | goto out_unlock; | ||
782 | |||
783 | if (mem->slot >= kvm->nmemslots) | 763 | if (mem->slot >= kvm->nmemslots) |
784 | kvm->nmemslots = mem->slot + 1; | 764 | kvm->nmemslots = mem->slot + 1; |
785 | 765 | ||
786 | *memslot = new; | 766 | *memslot = new; |
787 | ++kvm->memory_config_version; | ||
788 | 767 | ||
789 | kvm_mmu_slot_remove_write_access(kvm, mem->slot); | 768 | kvm_mmu_slot_remove_write_access(kvm, mem->slot); |
790 | kvm_flush_remote_tlbs(kvm); | 769 | kvm_flush_remote_tlbs(kvm); |
@@ -796,7 +775,6 @@ raced: | |||
796 | 775 | ||
797 | out_unlock: | 776 | out_unlock: |
798 | mutex_unlock(&kvm->lock); | 777 | mutex_unlock(&kvm->lock); |
799 | out_free: | ||
800 | kvm_free_physmem_slot(&new, &old); | 778 | kvm_free_physmem_slot(&new, &old); |
801 | out: | 779 | out: |
802 | return r; | 780 | return r; |
@@ -815,12 +793,6 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
815 | 793 | ||
816 | mutex_lock(&kvm->lock); | 794 | mutex_lock(&kvm->lock); |
817 | 795 | ||
818 | /* | ||
819 | * Prevent changes to guest memory configuration even while the lock | ||
820 | * is not taken. | ||
821 | */ | ||
822 | ++kvm->busy; | ||
823 | mutex_unlock(&kvm->lock); | ||
824 | r = -EINVAL; | 796 | r = -EINVAL; |
825 | if (log->slot >= KVM_MEMORY_SLOTS) | 797 | if (log->slot >= KVM_MEMORY_SLOTS) |
826 | goto out; | 798 | goto out; |
@@ -841,18 +813,14 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
841 | 813 | ||
842 | /* If nothing is dirty, don't bother messing with page tables. */ | 814 | /* If nothing is dirty, don't bother messing with page tables. */ |
843 | if (any) { | 815 | if (any) { |
844 | mutex_lock(&kvm->lock); | ||
845 | kvm_mmu_slot_remove_write_access(kvm, log->slot); | 816 | kvm_mmu_slot_remove_write_access(kvm, log->slot); |
846 | kvm_flush_remote_tlbs(kvm); | 817 | kvm_flush_remote_tlbs(kvm); |
847 | memset(memslot->dirty_bitmap, 0, n); | 818 | memset(memslot->dirty_bitmap, 0, n); |
848 | mutex_unlock(&kvm->lock); | ||
849 | } | 819 | } |
850 | 820 | ||
851 | r = 0; | 821 | r = 0; |
852 | 822 | ||
853 | out: | 823 | out: |
854 | mutex_lock(&kvm->lock); | ||
855 | --kvm->busy; | ||
856 | mutex_unlock(&kvm->lock); | 824 | mutex_unlock(&kvm->lock); |
857 | return r; | 825 | return r; |
858 | } | 826 | } |