diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
| -rw-r--r-- | virt/kvm/kvm_main.c | 106 |
1 files changed, 79 insertions, 27 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f032806a212..b78b794c103 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * machines without emulation or binary translation. | 5 | * machines without emulation or binary translation. |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2006 Qumranet, Inc. | 7 | * Copyright (C) 2006 Qumranet, Inc. |
| 8 | * Copyright 2010 Red Hat, Inc. and/or its affilates. | ||
| 8 | * | 9 | * |
| 9 | * Authors: | 10 | * Authors: |
| 10 | * Avi Kivity <avi@qumranet.com> | 11 | * Avi Kivity <avi@qumranet.com> |
| @@ -92,6 +93,12 @@ static bool kvm_rebooting; | |||
| 92 | 93 | ||
| 93 | static bool largepages_enabled = true; | 94 | static bool largepages_enabled = true; |
| 94 | 95 | ||
| 96 | static struct page *hwpoison_page; | ||
| 97 | static pfn_t hwpoison_pfn; | ||
| 98 | |||
| 99 | static struct page *fault_page; | ||
| 100 | static pfn_t fault_pfn; | ||
| 101 | |||
| 95 | inline int kvm_is_mmio_pfn(pfn_t pfn) | 102 | inline int kvm_is_mmio_pfn(pfn_t pfn) |
| 96 | { | 103 | { |
| 97 | if (pfn_valid(pfn)) { | 104 | if (pfn_valid(pfn)) { |
| @@ -141,7 +148,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) | |||
| 141 | raw_spin_lock(&kvm->requests_lock); | 148 | raw_spin_lock(&kvm->requests_lock); |
| 142 | me = smp_processor_id(); | 149 | me = smp_processor_id(); |
| 143 | kvm_for_each_vcpu(i, vcpu, kvm) { | 150 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 144 | if (test_and_set_bit(req, &vcpu->requests)) | 151 | if (kvm_make_check_request(req, vcpu)) |
| 145 | continue; | 152 | continue; |
| 146 | cpu = vcpu->cpu; | 153 | cpu = vcpu->cpu; |
| 147 | if (cpus != NULL && cpu != -1 && cpu != me) | 154 | if (cpus != NULL && cpu != -1 && cpu != me) |
| @@ -566,6 +573,7 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
| 566 | 573 | ||
| 567 | new = old = *memslot; | 574 | new = old = *memslot; |
| 568 | 575 | ||
| 576 | new.id = mem->slot; | ||
| 569 | new.base_gfn = base_gfn; | 577 | new.base_gfn = base_gfn; |
| 570 | new.npages = npages; | 578 | new.npages = npages; |
| 571 | new.flags = mem->flags; | 579 | new.flags = mem->flags; |
| @@ -596,7 +604,7 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
| 596 | /* Allocate if a slot is being created */ | 604 | /* Allocate if a slot is being created */ |
| 597 | #ifndef CONFIG_S390 | 605 | #ifndef CONFIG_S390 |
| 598 | if (npages && !new.rmap) { | 606 | if (npages && !new.rmap) { |
| 599 | new.rmap = vmalloc(npages * sizeof(struct page *)); | 607 | new.rmap = vmalloc(npages * sizeof(*new.rmap)); |
| 600 | 608 | ||
| 601 | if (!new.rmap) | 609 | if (!new.rmap) |
| 602 | goto out_free; | 610 | goto out_free; |
| @@ -621,9 +629,9 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
| 621 | if (new.lpage_info[i]) | 629 | if (new.lpage_info[i]) |
| 622 | continue; | 630 | continue; |
| 623 | 631 | ||
| 624 | lpages = 1 + (base_gfn + npages - 1) / | 632 | lpages = 1 + ((base_gfn + npages - 1) |
| 625 | KVM_PAGES_PER_HPAGE(level); | 633 | >> KVM_HPAGE_GFN_SHIFT(level)); |
| 626 | lpages -= base_gfn / KVM_PAGES_PER_HPAGE(level); | 634 | lpages -= base_gfn >> KVM_HPAGE_GFN_SHIFT(level); |
| 627 | 635 | ||
| 628 | new.lpage_info[i] = vmalloc(lpages * sizeof(*new.lpage_info[i])); | 636 | new.lpage_info[i] = vmalloc(lpages * sizeof(*new.lpage_info[i])); |
| 629 | 637 | ||
| @@ -633,9 +641,9 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
| 633 | memset(new.lpage_info[i], 0, | 641 | memset(new.lpage_info[i], 0, |
| 634 | lpages * sizeof(*new.lpage_info[i])); | 642 | lpages * sizeof(*new.lpage_info[i])); |
| 635 | 643 | ||
| 636 | if (base_gfn % KVM_PAGES_PER_HPAGE(level)) | 644 | if (base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1)) |
| 637 | new.lpage_info[i][0].write_count = 1; | 645 | new.lpage_info[i][0].write_count = 1; |
| 638 | if ((base_gfn+npages) % KVM_PAGES_PER_HPAGE(level)) | 646 | if ((base_gfn+npages) & (KVM_PAGES_PER_HPAGE(level) - 1)) |
| 639 | new.lpage_info[i][lpages - 1].write_count = 1; | 647 | new.lpage_info[i][lpages - 1].write_count = 1; |
| 640 | ugfn = new.userspace_addr >> PAGE_SHIFT; | 648 | ugfn = new.userspace_addr >> PAGE_SHIFT; |
| 641 | /* | 649 | /* |
| @@ -810,16 +818,28 @@ EXPORT_SYMBOL_GPL(kvm_disable_largepages); | |||
| 810 | 818 | ||
| 811 | int is_error_page(struct page *page) | 819 | int is_error_page(struct page *page) |
| 812 | { | 820 | { |
| 813 | return page == bad_page; | 821 | return page == bad_page || page == hwpoison_page || page == fault_page; |
| 814 | } | 822 | } |
| 815 | EXPORT_SYMBOL_GPL(is_error_page); | 823 | EXPORT_SYMBOL_GPL(is_error_page); |
| 816 | 824 | ||
| 817 | int is_error_pfn(pfn_t pfn) | 825 | int is_error_pfn(pfn_t pfn) |
| 818 | { | 826 | { |
| 819 | return pfn == bad_pfn; | 827 | return pfn == bad_pfn || pfn == hwpoison_pfn || pfn == fault_pfn; |
| 820 | } | 828 | } |
| 821 | EXPORT_SYMBOL_GPL(is_error_pfn); | 829 | EXPORT_SYMBOL_GPL(is_error_pfn); |
| 822 | 830 | ||
| 831 | int is_hwpoison_pfn(pfn_t pfn) | ||
| 832 | { | ||
| 833 | return pfn == hwpoison_pfn; | ||
| 834 | } | ||
| 835 | EXPORT_SYMBOL_GPL(is_hwpoison_pfn); | ||
| 836 | |||
| 837 | int is_fault_pfn(pfn_t pfn) | ||
| 838 | { | ||
| 839 | return pfn == fault_pfn; | ||
| 840 | } | ||
| 841 | EXPORT_SYMBOL_GPL(is_fault_pfn); | ||
| 842 | |||
| 823 | static inline unsigned long bad_hva(void) | 843 | static inline unsigned long bad_hva(void) |
| 824 | { | 844 | { |
| 825 | return PAGE_OFFSET; | 845 | return PAGE_OFFSET; |
| @@ -831,7 +851,7 @@ int kvm_is_error_hva(unsigned long addr) | |||
| 831 | } | 851 | } |
| 832 | EXPORT_SYMBOL_GPL(kvm_is_error_hva); | 852 | EXPORT_SYMBOL_GPL(kvm_is_error_hva); |
| 833 | 853 | ||
| 834 | struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn) | 854 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) |
| 835 | { | 855 | { |
| 836 | int i; | 856 | int i; |
| 837 | struct kvm_memslots *slots = kvm_memslots(kvm); | 857 | struct kvm_memslots *slots = kvm_memslots(kvm); |
| @@ -845,20 +865,13 @@ struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn) | |||
| 845 | } | 865 | } |
| 846 | return NULL; | 866 | return NULL; |
| 847 | } | 867 | } |
| 848 | EXPORT_SYMBOL_GPL(gfn_to_memslot_unaliased); | 868 | EXPORT_SYMBOL_GPL(gfn_to_memslot); |
| 849 | |||
| 850 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) | ||
| 851 | { | ||
| 852 | gfn = unalias_gfn(kvm, gfn); | ||
| 853 | return gfn_to_memslot_unaliased(kvm, gfn); | ||
| 854 | } | ||
| 855 | 869 | ||
| 856 | int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) | 870 | int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) |
| 857 | { | 871 | { |
| 858 | int i; | 872 | int i; |
| 859 | struct kvm_memslots *slots = kvm_memslots(kvm); | 873 | struct kvm_memslots *slots = kvm_memslots(kvm); |
| 860 | 874 | ||
| 861 | gfn = unalias_gfn_instantiation(kvm, gfn); | ||
| 862 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { | 875 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { |
| 863 | struct kvm_memory_slot *memslot = &slots->memslots[i]; | 876 | struct kvm_memory_slot *memslot = &slots->memslots[i]; |
| 864 | 877 | ||
| @@ -903,7 +916,6 @@ int memslot_id(struct kvm *kvm, gfn_t gfn) | |||
| 903 | struct kvm_memslots *slots = kvm_memslots(kvm); | 916 | struct kvm_memslots *slots = kvm_memslots(kvm); |
| 904 | struct kvm_memory_slot *memslot = NULL; | 917 | struct kvm_memory_slot *memslot = NULL; |
| 905 | 918 | ||
| 906 | gfn = unalias_gfn(kvm, gfn); | ||
| 907 | for (i = 0; i < slots->nmemslots; ++i) { | 919 | for (i = 0; i < slots->nmemslots; ++i) { |
| 908 | memslot = &slots->memslots[i]; | 920 | memslot = &slots->memslots[i]; |
| 909 | 921 | ||
| @@ -924,8 +936,7 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | |||
| 924 | { | 936 | { |
| 925 | struct kvm_memory_slot *slot; | 937 | struct kvm_memory_slot *slot; |
| 926 | 938 | ||
| 927 | gfn = unalias_gfn_instantiation(kvm, gfn); | 939 | slot = gfn_to_memslot(kvm, gfn); |
| 928 | slot = gfn_to_memslot_unaliased(kvm, gfn); | ||
| 929 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | 940 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) |
| 930 | return bad_hva(); | 941 | return bad_hva(); |
| 931 | return gfn_to_hva_memslot(slot, gfn); | 942 | return gfn_to_hva_memslot(slot, gfn); |
| @@ -946,13 +957,19 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | |||
| 946 | struct vm_area_struct *vma; | 957 | struct vm_area_struct *vma; |
| 947 | 958 | ||
| 948 | down_read(¤t->mm->mmap_sem); | 959 | down_read(¤t->mm->mmap_sem); |
| 960 | if (is_hwpoison_address(addr)) { | ||
| 961 | up_read(¤t->mm->mmap_sem); | ||
| 962 | get_page(hwpoison_page); | ||
| 963 | return page_to_pfn(hwpoison_page); | ||
| 964 | } | ||
| 965 | |||
| 949 | vma = find_vma(current->mm, addr); | 966 | vma = find_vma(current->mm, addr); |
| 950 | 967 | ||
| 951 | if (vma == NULL || addr < vma->vm_start || | 968 | if (vma == NULL || addr < vma->vm_start || |
| 952 | !(vma->vm_flags & VM_PFNMAP)) { | 969 | !(vma->vm_flags & VM_PFNMAP)) { |
| 953 | up_read(¤t->mm->mmap_sem); | 970 | up_read(¤t->mm->mmap_sem); |
| 954 | get_page(bad_page); | 971 | get_page(fault_page); |
| 955 | return page_to_pfn(bad_page); | 972 | return page_to_pfn(fault_page); |
| 956 | } | 973 | } |
| 957 | 974 | ||
| 958 | pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | 975 | pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
| @@ -1187,8 +1204,7 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) | |||
| 1187 | { | 1204 | { |
| 1188 | struct kvm_memory_slot *memslot; | 1205 | struct kvm_memory_slot *memslot; |
| 1189 | 1206 | ||
| 1190 | gfn = unalias_gfn(kvm, gfn); | 1207 | memslot = gfn_to_memslot(kvm, gfn); |
| 1191 | memslot = gfn_to_memslot_unaliased(kvm, gfn); | ||
| 1192 | if (memslot && memslot->dirty_bitmap) { | 1208 | if (memslot && memslot->dirty_bitmap) { |
| 1193 | unsigned long rel_gfn = gfn - memslot->base_gfn; | 1209 | unsigned long rel_gfn = gfn - memslot->base_gfn; |
| 1194 | 1210 | ||
| @@ -1207,7 +1223,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) | |||
| 1207 | prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); | 1223 | prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); |
| 1208 | 1224 | ||
| 1209 | if (kvm_arch_vcpu_runnable(vcpu)) { | 1225 | if (kvm_arch_vcpu_runnable(vcpu)) { |
| 1210 | set_bit(KVM_REQ_UNHALT, &vcpu->requests); | 1226 | kvm_make_request(KVM_REQ_UNHALT, vcpu); |
| 1211 | break; | 1227 | break; |
| 1212 | } | 1228 | } |
| 1213 | if (kvm_cpu_has_pending_timer(vcpu)) | 1229 | if (kvm_cpu_has_pending_timer(vcpu)) |
| @@ -1378,6 +1394,18 @@ static long kvm_vcpu_ioctl(struct file *filp, | |||
| 1378 | 1394 | ||
| 1379 | if (vcpu->kvm->mm != current->mm) | 1395 | if (vcpu->kvm->mm != current->mm) |
| 1380 | return -EIO; | 1396 | return -EIO; |
| 1397 | |||
| 1398 | #if defined(CONFIG_S390) || defined(CONFIG_PPC) | ||
| 1399 | /* | ||
| 1400 | * Special cases: vcpu ioctls that are asynchronous to vcpu execution, | ||
| 1401 | * so vcpu_load() would break it. | ||
| 1402 | */ | ||
| 1403 | if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT) | ||
| 1404 | return kvm_arch_vcpu_ioctl(filp, ioctl, arg); | ||
| 1405 | #endif | ||
| 1406 | |||
| 1407 | |||
| 1408 | vcpu_load(vcpu); | ||
| 1381 | switch (ioctl) { | 1409 | switch (ioctl) { |
| 1382 | case KVM_RUN: | 1410 | case KVM_RUN: |
| 1383 | r = -EINVAL; | 1411 | r = -EINVAL; |
| @@ -1520,7 +1548,7 @@ out_free2: | |||
| 1520 | goto out; | 1548 | goto out; |
| 1521 | p = &sigset; | 1549 | p = &sigset; |
| 1522 | } | 1550 | } |
| 1523 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); | 1551 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, p); |
| 1524 | break; | 1552 | break; |
| 1525 | } | 1553 | } |
| 1526 | case KVM_GET_FPU: { | 1554 | case KVM_GET_FPU: { |
| @@ -1555,6 +1583,7 @@ out_free2: | |||
| 1555 | r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); | 1583 | r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); |
| 1556 | } | 1584 | } |
| 1557 | out: | 1585 | out: |
| 1586 | vcpu_put(vcpu); | ||
| 1558 | kfree(fpu); | 1587 | kfree(fpu); |
| 1559 | kfree(kvm_sregs); | 1588 | kfree(kvm_sregs); |
| 1560 | return r; | 1589 | return r; |
| @@ -2197,6 +2226,24 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, | |||
| 2197 | 2226 | ||
| 2198 | bad_pfn = page_to_pfn(bad_page); | 2227 | bad_pfn = page_to_pfn(bad_page); |
| 2199 | 2228 | ||
| 2229 | hwpoison_page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
| 2230 | |||
| 2231 | if (hwpoison_page == NULL) { | ||
| 2232 | r = -ENOMEM; | ||
| 2233 | goto out_free_0; | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | hwpoison_pfn = page_to_pfn(hwpoison_page); | ||
| 2237 | |||
| 2238 | fault_page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
| 2239 | |||
| 2240 | if (fault_page == NULL) { | ||
| 2241 | r = -ENOMEM; | ||
| 2242 | goto out_free_0; | ||
| 2243 | } | ||
| 2244 | |||
| 2245 | fault_pfn = page_to_pfn(fault_page); | ||
| 2246 | |||
| 2200 | if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) { | 2247 | if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) { |
| 2201 | r = -ENOMEM; | 2248 | r = -ENOMEM; |
| 2202 | goto out_free_0; | 2249 | goto out_free_0; |
| @@ -2269,6 +2316,10 @@ out_free_1: | |||
| 2269 | out_free_0a: | 2316 | out_free_0a: |
| 2270 | free_cpumask_var(cpus_hardware_enabled); | 2317 | free_cpumask_var(cpus_hardware_enabled); |
| 2271 | out_free_0: | 2318 | out_free_0: |
| 2319 | if (fault_page) | ||
| 2320 | __free_page(fault_page); | ||
| 2321 | if (hwpoison_page) | ||
| 2322 | __free_page(hwpoison_page); | ||
| 2272 | __free_page(bad_page); | 2323 | __free_page(bad_page); |
| 2273 | out: | 2324 | out: |
| 2274 | kvm_arch_exit(); | 2325 | kvm_arch_exit(); |
| @@ -2290,6 +2341,7 @@ void kvm_exit(void) | |||
| 2290 | kvm_arch_hardware_unsetup(); | 2341 | kvm_arch_hardware_unsetup(); |
| 2291 | kvm_arch_exit(); | 2342 | kvm_arch_exit(); |
| 2292 | free_cpumask_var(cpus_hardware_enabled); | 2343 | free_cpumask_var(cpus_hardware_enabled); |
| 2344 | __free_page(hwpoison_page); | ||
| 2293 | __free_page(bad_page); | 2345 | __free_page(bad_page); |
| 2294 | } | 2346 | } |
| 2295 | EXPORT_SYMBOL_GPL(kvm_exit); | 2347 | EXPORT_SYMBOL_GPL(kvm_exit); |
