aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kvm_host.h6
-rw-r--r--virt/kvm/kvm_main.c11
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
108struct kvm_memory_slot { 114struct 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