diff options
| author | Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> | 2012-02-07 23:00:13 -0500 |
|---|---|---|
| committer | Avi Kivity <avi@redhat.com> | 2012-03-08 07:10:20 -0500 |
| commit | a64f273a08d16bc66ccc5546bd28b1bba554ec81 (patch) | |
| tree | af305dee1d5c6c2fed1e6c913a18c4f43e16940a /virt | |
| parent | fb03cb6f44236f4bef62a0dda8e025ff5ca51417 (diff) | |
KVM: Split lpage_info creation out from __kvm_set_memory_region()
This makes it easy to make lpage_info architecture specific.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt')
| -rw-r--r-- | virt/kvm/kvm_main.c | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 415fe816fc15..7adaa2063415 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -685,6 +685,56 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new) | |||
| 685 | slots->generation++; | 685 | slots->generation++; |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | #ifndef CONFIG_S390 | ||
| 689 | static int create_lpage_info(struct kvm_memory_slot *slot, unsigned long npages) | ||
| 690 | { | ||
| 691 | int i; | ||
| 692 | |||
| 693 | for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { | ||
| 694 | unsigned long ugfn; | ||
| 695 | int lpages; | ||
| 696 | int level = i + 2; | ||
| 697 | |||
| 698 | if (slot->lpage_info[i]) | ||
| 699 | continue; | ||
| 700 | |||
| 701 | lpages = gfn_to_index(slot->base_gfn + npages - 1, | ||
| 702 | slot->base_gfn, level) + 1; | ||
| 703 | |||
| 704 | slot->lpage_info[i] = vzalloc(lpages * sizeof(*slot->lpage_info[i])); | ||
| 705 | if (!slot->lpage_info[i]) | ||
| 706 | goto out_free; | ||
| 707 | |||
| 708 | if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1)) | ||
| 709 | slot->lpage_info[i][0].write_count = 1; | ||
| 710 | if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1)) | ||
| 711 | slot->lpage_info[i][lpages - 1].write_count = 1; | ||
| 712 | ugfn = slot->userspace_addr >> PAGE_SHIFT; | ||
| 713 | /* | ||
| 714 | * If the gfn and userspace address are not aligned wrt each | ||
| 715 | * other, or if explicitly asked to, disable large page | ||
| 716 | * support for this slot | ||
| 717 | */ | ||
| 718 | if ((slot->base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) || | ||
| 719 | !largepages_enabled) { | ||
| 720 | unsigned long j; | ||
| 721 | |||
| 722 | for (j = 0; j < lpages; ++j) | ||
| 723 | slot->lpage_info[i][j].write_count = 1; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | |||
| 727 | return 0; | ||
| 728 | |||
| 729 | out_free: | ||
| 730 | for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { | ||
| 731 | vfree(slot->lpage_info[i]); | ||
| 732 | slot->lpage_info[i] = NULL; | ||
| 733 | } | ||
| 734 | return -ENOMEM; | ||
| 735 | } | ||
| 736 | #endif /* not defined CONFIG_S390 */ | ||
| 737 | |||
| 688 | /* | 738 | /* |
| 689 | * Allocate some memory and give it an address in the guest physical address | 739 | * Allocate some memory and give it an address in the guest physical address |
| 690 | * space. | 740 | * space. |
| @@ -778,37 +828,8 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
| 778 | if (!npages) | 828 | if (!npages) |
| 779 | goto skip_lpage; | 829 | goto skip_lpage; |
| 780 | 830 | ||
| 781 | for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { | 831 | if (create_lpage_info(&new, npages)) |
| 782 | unsigned long ugfn; | 832 | goto out_free; |
| 783 | unsigned long j; | ||
| 784 | int lpages; | ||
| 785 | int level = i + 2; | ||
| 786 | |||
| 787 | if (new.lpage_info[i]) | ||
| 788 | continue; | ||
| 789 | |||
| 790 | lpages = gfn_to_index(base_gfn + npages - 1, base_gfn, level) + 1; | ||
| 791 | |||
| 792 | new.lpage_info[i] = vzalloc(lpages * sizeof(*new.lpage_info[i])); | ||
| 793 | |||
| 794 | if (!new.lpage_info[i]) | ||
| 795 | goto out_free; | ||
| 796 | |||
| 797 | if (base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1)) | ||
| 798 | new.lpage_info[i][0].write_count = 1; | ||
| 799 | if ((base_gfn+npages) & (KVM_PAGES_PER_HPAGE(level) - 1)) | ||
| 800 | new.lpage_info[i][lpages - 1].write_count = 1; | ||
| 801 | ugfn = new.userspace_addr >> PAGE_SHIFT; | ||
| 802 | /* | ||
| 803 | * If the gfn and userspace address are not aligned wrt each | ||
| 804 | * other, or if explicitly asked to, disable large page | ||
| 805 | * support for this slot | ||
| 806 | */ | ||
| 807 | if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) || | ||
| 808 | !largepages_enabled) | ||
| 809 | for (j = 0; j < lpages; ++j) | ||
| 810 | new.lpage_info[i][j].write_count = 1; | ||
| 811 | } | ||
| 812 | 833 | ||
| 813 | skip_lpage: | 834 | skip_lpage: |
| 814 | 835 | ||
