diff options
-rw-r--r-- | include/linux/kvm_host.h | 6 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 11 |
2 files changed, 12 insertions, 5 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 169d07758ee5..55830638aeb1 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -105,6 +105,12 @@ struct kvm_vcpu { | |||
105 | struct kvm_vcpu_arch arch; | 105 | struct kvm_vcpu_arch arch; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | /* | ||
109 | * Some of the bitops functions do not support too long bitmaps. | ||
110 | * This number must be determined not to exceed such limits. | ||
111 | */ | ||
112 | #define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1) | ||
113 | |||
108 | struct kvm_memory_slot { | 114 | struct kvm_memory_slot { |
109 | gfn_t base_gfn; | 115 | gfn_t base_gfn; |
110 | unsigned long npages; | 116 | unsigned long npages; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 55a5d4804499..d6351a34b297 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -557,6 +557,10 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
557 | base_gfn = mem->guest_phys_addr >> PAGE_SHIFT; | 557 | base_gfn = mem->guest_phys_addr >> PAGE_SHIFT; |
558 | npages = mem->memory_size >> PAGE_SHIFT; | 558 | npages = mem->memory_size >> PAGE_SHIFT; |
559 | 559 | ||
560 | r = -EINVAL; | ||
561 | if (npages > KVM_MEM_MAX_NR_PAGES) | ||
562 | goto out; | ||
563 | |||
560 | if (!npages) | 564 | if (!npages) |
561 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; | 565 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; |
562 | 566 | ||
@@ -1187,13 +1191,10 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) | |||
1187 | memslot = gfn_to_memslot_unaliased(kvm, gfn); | 1191 | memslot = gfn_to_memslot_unaliased(kvm, gfn); |
1188 | if (memslot && memslot->dirty_bitmap) { | 1192 | if (memslot && memslot->dirty_bitmap) { |
1189 | unsigned long rel_gfn = gfn - memslot->base_gfn; | 1193 | unsigned long rel_gfn = gfn - memslot->base_gfn; |
1190 | unsigned long *p = memslot->dirty_bitmap + | ||
1191 | rel_gfn / BITS_PER_LONG; | ||
1192 | int offset = rel_gfn % BITS_PER_LONG; | ||
1193 | 1194 | ||
1194 | /* avoid RMW */ | 1195 | /* avoid RMW */ |
1195 | if (!generic_test_le_bit(offset, p)) | 1196 | if (!generic_test_le_bit(rel_gfn, memslot->dirty_bitmap)) |
1196 | generic___set_le_bit(offset, p); | 1197 | generic___set_le_bit(rel_gfn, memslot->dirty_bitmap); |
1197 | } | 1198 | } |
1198 | } | 1199 | } |
1199 | 1200 | ||