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 f032806a212f..b78b794c1039 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); |