diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index bd3c08a7c6c2..e299763ef744 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -440,13 +440,60 @@ static int kvm_init_mmu_notifier(struct kvm *kvm) | |||
440 | 440 | ||
441 | #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */ | 441 | #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */ |
442 | 442 | ||
443 | static void kvm_init_memslots_id(struct kvm *kvm) | 443 | static struct kvm_memslots *kvm_alloc_memslots(void) |
444 | { | 444 | { |
445 | int i; | 445 | int i; |
446 | struct kvm_memslots *slots = kvm->memslots; | 446 | struct kvm_memslots *slots; |
447 | 447 | ||
448 | slots = kvm_kvzalloc(sizeof(struct kvm_memslots)); | ||
449 | if (!slots) | ||
450 | return NULL; | ||
451 | |||
452 | /* | ||
453 | * Init kvm generation close to the maximum to easily test the | ||
454 | * code of handling generation number wrap-around. | ||
455 | */ | ||
456 | slots->generation = -150; | ||
448 | for (i = 0; i < KVM_MEM_SLOTS_NUM; i++) | 457 | for (i = 0; i < KVM_MEM_SLOTS_NUM; i++) |
449 | slots->id_to_index[i] = slots->memslots[i].id = i; | 458 | slots->id_to_index[i] = slots->memslots[i].id = i; |
459 | |||
460 | return slots; | ||
461 | } | ||
462 | |||
463 | static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) | ||
464 | { | ||
465 | if (!memslot->dirty_bitmap) | ||
466 | return; | ||
467 | |||
468 | kvfree(memslot->dirty_bitmap); | ||
469 | memslot->dirty_bitmap = NULL; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Free any memory in @free but not in @dont. | ||
474 | */ | ||
475 | static void kvm_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, | ||
476 | struct kvm_memory_slot *dont) | ||
477 | { | ||
478 | if (!dont || free->dirty_bitmap != dont->dirty_bitmap) | ||
479 | kvm_destroy_dirty_bitmap(free); | ||
480 | |||
481 | kvm_arch_free_memslot(kvm, free, dont); | ||
482 | |||
483 | free->npages = 0; | ||
484 | } | ||
485 | |||
486 | static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots) | ||
487 | { | ||
488 | struct kvm_memory_slot *memslot; | ||
489 | |||
490 | if (!slots) | ||
491 | return; | ||
492 | |||
493 | kvm_for_each_memslot(memslot, slots) | ||
494 | kvm_free_memslot(kvm, memslot, NULL); | ||
495 | |||
496 | kvfree(slots); | ||
450 | } | 497 | } |
451 | 498 | ||
452 | static struct kvm *kvm_create_vm(unsigned long type) | 499 | static struct kvm *kvm_create_vm(unsigned long type) |
@@ -472,17 +519,10 @@ static struct kvm *kvm_create_vm(unsigned long type) | |||
472 | BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX); | 519 | BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX); |
473 | 520 | ||
474 | r = -ENOMEM; | 521 | r = -ENOMEM; |
475 | kvm->memslots = kvm_kvzalloc(sizeof(struct kvm_memslots)); | 522 | kvm->memslots = kvm_alloc_memslots(); |
476 | if (!kvm->memslots) | 523 | if (!kvm->memslots) |
477 | goto out_err_no_srcu; | 524 | goto out_err_no_srcu; |
478 | 525 | ||
479 | /* | ||
480 | * Init kvm generation close to the maximum to easily test the | ||
481 | * code of handling generation number wrap-around. | ||
482 | */ | ||
483 | kvm->memslots->generation = -150; | ||
484 | |||
485 | kvm_init_memslots_id(kvm); | ||
486 | if (init_srcu_struct(&kvm->srcu)) | 526 | if (init_srcu_struct(&kvm->srcu)) |
487 | goto out_err_no_srcu; | 527 | goto out_err_no_srcu; |
488 | if (init_srcu_struct(&kvm->irq_srcu)) | 528 | if (init_srcu_struct(&kvm->irq_srcu)) |
@@ -523,7 +563,7 @@ out_err_no_srcu: | |||
523 | out_err_no_disable: | 563 | out_err_no_disable: |
524 | for (i = 0; i < KVM_NR_BUSES; i++) | 564 | for (i = 0; i < KVM_NR_BUSES; i++) |
525 | kfree(kvm->buses[i]); | 565 | kfree(kvm->buses[i]); |
526 | kvfree(kvm->memslots); | 566 | kvm_free_memslots(kvm, kvm->memslots); |
527 | kvm_arch_free_vm(kvm); | 567 | kvm_arch_free_vm(kvm); |
528 | return ERR_PTR(r); | 568 | return ERR_PTR(r); |
529 | } | 569 | } |
@@ -540,40 +580,6 @@ void *kvm_kvzalloc(unsigned long size) | |||
540 | return kzalloc(size, GFP_KERNEL); | 580 | return kzalloc(size, GFP_KERNEL); |
541 | } | 581 | } |
542 | 582 | ||
543 | static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) | ||
544 | { | ||
545 | if (!memslot->dirty_bitmap) | ||
546 | return; | ||
547 | |||
548 | kvfree(memslot->dirty_bitmap); | ||
549 | memslot->dirty_bitmap = NULL; | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Free any memory in @free but not in @dont. | ||
554 | */ | ||
555 | static void kvm_free_physmem_slot(struct kvm *kvm, struct kvm_memory_slot *free, | ||
556 | struct kvm_memory_slot *dont) | ||
557 | { | ||
558 | if (!dont || free->dirty_bitmap != dont->dirty_bitmap) | ||
559 | kvm_destroy_dirty_bitmap(free); | ||
560 | |||
561 | kvm_arch_free_memslot(kvm, free, dont); | ||
562 | |||
563 | free->npages = 0; | ||
564 | } | ||
565 | |||
566 | static void kvm_free_physmem(struct kvm *kvm) | ||
567 | { | ||
568 | struct kvm_memslots *slots = kvm->memslots; | ||
569 | struct kvm_memory_slot *memslot; | ||
570 | |||
571 | kvm_for_each_memslot(memslot, slots) | ||
572 | kvm_free_physmem_slot(kvm, memslot, NULL); | ||
573 | |||
574 | kvfree(kvm->memslots); | ||
575 | } | ||
576 | |||
577 | static void kvm_destroy_devices(struct kvm *kvm) | 583 | static void kvm_destroy_devices(struct kvm *kvm) |
578 | { | 584 | { |
579 | struct list_head *node, *tmp; | 585 | struct list_head *node, *tmp; |
@@ -607,7 +613,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
607 | #endif | 613 | #endif |
608 | kvm_arch_destroy_vm(kvm); | 614 | kvm_arch_destroy_vm(kvm); |
609 | kvm_destroy_devices(kvm); | 615 | kvm_destroy_devices(kvm); |
610 | kvm_free_physmem(kvm); | 616 | kvm_free_memslots(kvm, kvm->memslots); |
611 | cleanup_srcu_struct(&kvm->irq_srcu); | 617 | cleanup_srcu_struct(&kvm->irq_srcu); |
612 | cleanup_srcu_struct(&kvm->srcu); | 618 | cleanup_srcu_struct(&kvm->srcu); |
613 | kvm_arch_free_vm(kvm); | 619 | kvm_arch_free_vm(kvm); |
@@ -898,7 +904,7 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
898 | if (r) | 904 | if (r) |
899 | goto out_slots; | 905 | goto out_slots; |
900 | 906 | ||
901 | /* actual memory is freed via old in kvm_free_physmem_slot below */ | 907 | /* actual memory is freed via old in kvm_free_memslot below */ |
902 | if (change == KVM_MR_DELETE) { | 908 | if (change == KVM_MR_DELETE) { |
903 | new.dirty_bitmap = NULL; | 909 | new.dirty_bitmap = NULL; |
904 | memset(&new.arch, 0, sizeof(new.arch)); | 910 | memset(&new.arch, 0, sizeof(new.arch)); |
@@ -909,7 +915,7 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
909 | 915 | ||
910 | kvm_arch_commit_memory_region(kvm, mem, &old, change); | 916 | kvm_arch_commit_memory_region(kvm, mem, &old, change); |
911 | 917 | ||
912 | kvm_free_physmem_slot(kvm, &old, &new); | 918 | kvm_free_memslot(kvm, &old, &new); |
913 | kvfree(old_memslots); | 919 | kvfree(old_memslots); |
914 | 920 | ||
915 | /* | 921 | /* |
@@ -931,7 +937,7 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
931 | out_slots: | 937 | out_slots: |
932 | kvfree(slots); | 938 | kvfree(slots); |
933 | out_free: | 939 | out_free: |
934 | kvm_free_physmem_slot(kvm, &new, &old); | 940 | kvm_free_memslot(kvm, &new, &old); |
935 | out: | 941 | out: |
936 | return r; | 942 | return r; |
937 | } | 943 | } |