diff options
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 137 |
1 files changed, 64 insertions, 73 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 89a49fb46a2..741373e8ca7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "mmu.h" | 20 | #include "mmu.h" |
21 | #include "x86.h" | ||
21 | #include "kvm_cache_regs.h" | 22 | #include "kvm_cache_regs.h" |
22 | 23 | ||
23 | #include <linux/kvm_host.h> | 24 | #include <linux/kvm_host.h> |
@@ -29,6 +30,7 @@ | |||
29 | #include <linux/swap.h> | 30 | #include <linux/swap.h> |
30 | #include <linux/hugetlb.h> | 31 | #include <linux/hugetlb.h> |
31 | #include <linux/compiler.h> | 32 | #include <linux/compiler.h> |
33 | #include <linux/srcu.h> | ||
32 | 34 | ||
33 | #include <asm/page.h> | 35 | #include <asm/page.h> |
34 | #include <asm/cmpxchg.h> | 36 | #include <asm/cmpxchg.h> |
@@ -136,16 +138,6 @@ module_param(oos_shadow, bool, 0644); | |||
136 | #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \ | 138 | #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \ |
137 | | PT64_NX_MASK) | 139 | | PT64_NX_MASK) |
138 | 140 | ||
139 | #define PFERR_PRESENT_MASK (1U << 0) | ||
140 | #define PFERR_WRITE_MASK (1U << 1) | ||
141 | #define PFERR_USER_MASK (1U << 2) | ||
142 | #define PFERR_RSVD_MASK (1U << 3) | ||
143 | #define PFERR_FETCH_MASK (1U << 4) | ||
144 | |||
145 | #define PT_PDPE_LEVEL 3 | ||
146 | #define PT_DIRECTORY_LEVEL 2 | ||
147 | #define PT_PAGE_TABLE_LEVEL 1 | ||
148 | |||
149 | #define RMAP_EXT 4 | 141 | #define RMAP_EXT 4 |
150 | 142 | ||
151 | #define ACC_EXEC_MASK 1 | 143 | #define ACC_EXEC_MASK 1 |
@@ -153,6 +145,9 @@ module_param(oos_shadow, bool, 0644); | |||
153 | #define ACC_USER_MASK PT_USER_MASK | 145 | #define ACC_USER_MASK PT_USER_MASK |
154 | #define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) | 146 | #define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) |
155 | 147 | ||
148 | #include <trace/events/kvm.h> | ||
149 | |||
150 | #undef TRACE_INCLUDE_FILE | ||
156 | #define CREATE_TRACE_POINTS | 151 | #define CREATE_TRACE_POINTS |
157 | #include "mmutrace.h" | 152 | #include "mmutrace.h" |
158 | 153 | ||
@@ -229,7 +224,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); | |||
229 | 224 | ||
230 | static int is_write_protection(struct kvm_vcpu *vcpu) | 225 | static int is_write_protection(struct kvm_vcpu *vcpu) |
231 | { | 226 | { |
232 | return vcpu->arch.cr0 & X86_CR0_WP; | 227 | return kvm_read_cr0_bits(vcpu, X86_CR0_WP); |
233 | } | 228 | } |
234 | 229 | ||
235 | static int is_cpuid_PSE36(void) | 230 | static int is_cpuid_PSE36(void) |
@@ -239,7 +234,7 @@ static int is_cpuid_PSE36(void) | |||
239 | 234 | ||
240 | static int is_nx(struct kvm_vcpu *vcpu) | 235 | static int is_nx(struct kvm_vcpu *vcpu) |
241 | { | 236 | { |
242 | return vcpu->arch.shadow_efer & EFER_NX; | 237 | return vcpu->arch.efer & EFER_NX; |
243 | } | 238 | } |
244 | 239 | ||
245 | static int is_shadow_present_pte(u64 pte) | 240 | static int is_shadow_present_pte(u64 pte) |
@@ -253,7 +248,7 @@ static int is_large_pte(u64 pte) | |||
253 | return pte & PT_PAGE_SIZE_MASK; | 248 | return pte & PT_PAGE_SIZE_MASK; |
254 | } | 249 | } |
255 | 250 | ||
256 | static int is_writeble_pte(unsigned long pte) | 251 | static int is_writable_pte(unsigned long pte) |
257 | { | 252 | { |
258 | return pte & PT_WRITABLE_MASK; | 253 | return pte & PT_WRITABLE_MASK; |
259 | } | 254 | } |
@@ -470,24 +465,10 @@ static int has_wrprotected_page(struct kvm *kvm, | |||
470 | 465 | ||
471 | static int host_mapping_level(struct kvm *kvm, gfn_t gfn) | 466 | static int host_mapping_level(struct kvm *kvm, gfn_t gfn) |
472 | { | 467 | { |
473 | unsigned long page_size = PAGE_SIZE; | 468 | unsigned long page_size; |
474 | struct vm_area_struct *vma; | ||
475 | unsigned long addr; | ||
476 | int i, ret = 0; | 469 | int i, ret = 0; |
477 | 470 | ||
478 | addr = gfn_to_hva(kvm, gfn); | 471 | page_size = kvm_host_page_size(kvm, gfn); |
479 | if (kvm_is_error_hva(addr)) | ||
480 | return PT_PAGE_TABLE_LEVEL; | ||
481 | |||
482 | down_read(¤t->mm->mmap_sem); | ||
483 | vma = find_vma(current->mm, addr); | ||
484 | if (!vma) | ||
485 | goto out; | ||
486 | |||
487 | page_size = vma_kernel_pagesize(vma); | ||
488 | |||
489 | out: | ||
490 | up_read(¤t->mm->mmap_sem); | ||
491 | 472 | ||
492 | for (i = PT_PAGE_TABLE_LEVEL; | 473 | for (i = PT_PAGE_TABLE_LEVEL; |
493 | i < (PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES); ++i) { | 474 | i < (PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES); ++i) { |
@@ -503,8 +484,7 @@ out: | |||
503 | static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) | 484 | static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) |
504 | { | 485 | { |
505 | struct kvm_memory_slot *slot; | 486 | struct kvm_memory_slot *slot; |
506 | int host_level; | 487 | int host_level, level, max_level; |
507 | int level = PT_PAGE_TABLE_LEVEL; | ||
508 | 488 | ||
509 | slot = gfn_to_memslot(vcpu->kvm, large_gfn); | 489 | slot = gfn_to_memslot(vcpu->kvm, large_gfn); |
510 | if (slot && slot->dirty_bitmap) | 490 | if (slot && slot->dirty_bitmap) |
@@ -515,7 +495,10 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) | |||
515 | if (host_level == PT_PAGE_TABLE_LEVEL) | 495 | if (host_level == PT_PAGE_TABLE_LEVEL) |
516 | return host_level; | 496 | return host_level; |
517 | 497 | ||
518 | for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) | 498 | max_level = kvm_x86_ops->get_lpage_level() < host_level ? |
499 | kvm_x86_ops->get_lpage_level() : host_level; | ||
500 | |||
501 | for (level = PT_DIRECTORY_LEVEL; level <= max_level; ++level) | ||
519 | if (has_wrprotected_page(vcpu->kvm, large_gfn, level)) | 502 | if (has_wrprotected_page(vcpu->kvm, large_gfn, level)) |
520 | break; | 503 | break; |
521 | 504 | ||
@@ -633,7 +616,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) | |||
633 | pfn = spte_to_pfn(*spte); | 616 | pfn = spte_to_pfn(*spte); |
634 | if (*spte & shadow_accessed_mask) | 617 | if (*spte & shadow_accessed_mask) |
635 | kvm_set_pfn_accessed(pfn); | 618 | kvm_set_pfn_accessed(pfn); |
636 | if (is_writeble_pte(*spte)) | 619 | if (is_writable_pte(*spte)) |
637 | kvm_set_pfn_dirty(pfn); | 620 | kvm_set_pfn_dirty(pfn); |
638 | rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], sp->role.level); | 621 | rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], sp->role.level); |
639 | if (!*rmapp) { | 622 | if (!*rmapp) { |
@@ -662,6 +645,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) | |||
662 | prev_desc = desc; | 645 | prev_desc = desc; |
663 | desc = desc->more; | 646 | desc = desc->more; |
664 | } | 647 | } |
648 | pr_err("rmap_remove: %p %llx many->many\n", spte, *spte); | ||
665 | BUG(); | 649 | BUG(); |
666 | } | 650 | } |
667 | } | 651 | } |
@@ -708,7 +692,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn) | |||
708 | BUG_ON(!spte); | 692 | BUG_ON(!spte); |
709 | BUG_ON(!(*spte & PT_PRESENT_MASK)); | 693 | BUG_ON(!(*spte & PT_PRESENT_MASK)); |
710 | rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte); | 694 | rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte); |
711 | if (is_writeble_pte(*spte)) { | 695 | if (is_writable_pte(*spte)) { |
712 | __set_spte(spte, *spte & ~PT_WRITABLE_MASK); | 696 | __set_spte(spte, *spte & ~PT_WRITABLE_MASK); |
713 | write_protected = 1; | 697 | write_protected = 1; |
714 | } | 698 | } |
@@ -732,7 +716,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn) | |||
732 | BUG_ON(!(*spte & PT_PRESENT_MASK)); | 716 | BUG_ON(!(*spte & PT_PRESENT_MASK)); |
733 | BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)); | 717 | BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)); |
734 | pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn); | 718 | pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn); |
735 | if (is_writeble_pte(*spte)) { | 719 | if (is_writable_pte(*spte)) { |
736 | rmap_remove(kvm, spte); | 720 | rmap_remove(kvm, spte); |
737 | --kvm->stat.lpages; | 721 | --kvm->stat.lpages; |
738 | __set_spte(spte, shadow_trap_nonpresent_pte); | 722 | __set_spte(spte, shadow_trap_nonpresent_pte); |
@@ -787,7 +771,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
787 | 771 | ||
788 | new_spte &= ~PT_WRITABLE_MASK; | 772 | new_spte &= ~PT_WRITABLE_MASK; |
789 | new_spte &= ~SPTE_HOST_WRITEABLE; | 773 | new_spte &= ~SPTE_HOST_WRITEABLE; |
790 | if (is_writeble_pte(*spte)) | 774 | if (is_writable_pte(*spte)) |
791 | kvm_set_pfn_dirty(spte_to_pfn(*spte)); | 775 | kvm_set_pfn_dirty(spte_to_pfn(*spte)); |
792 | __set_spte(spte, new_spte); | 776 | __set_spte(spte, new_spte); |
793 | spte = rmap_next(kvm, rmapp, spte); | 777 | spte = rmap_next(kvm, rmapp, spte); |
@@ -805,35 +789,32 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
805 | unsigned long data)) | 789 | unsigned long data)) |
806 | { | 790 | { |
807 | int i, j; | 791 | int i, j; |
792 | int ret; | ||
808 | int retval = 0; | 793 | int retval = 0; |
794 | struct kvm_memslots *slots; | ||
809 | 795 | ||
810 | /* | 796 | slots = rcu_dereference(kvm->memslots); |
811 | * If mmap_sem isn't taken, we can look the memslots with only | 797 | |
812 | * the mmu_lock by skipping over the slots with userspace_addr == 0. | 798 | for (i = 0; i < slots->nmemslots; i++) { |
813 | */ | 799 | struct kvm_memory_slot *memslot = &slots->memslots[i]; |
814 | for (i = 0; i < kvm->nmemslots; i++) { | ||
815 | struct kvm_memory_slot *memslot = &kvm->memslots[i]; | ||
816 | unsigned long start = memslot->userspace_addr; | 800 | unsigned long start = memslot->userspace_addr; |
817 | unsigned long end; | 801 | unsigned long end; |
818 | 802 | ||
819 | /* mmu_lock protects userspace_addr */ | ||
820 | if (!start) | ||
821 | continue; | ||
822 | |||
823 | end = start + (memslot->npages << PAGE_SHIFT); | 803 | end = start + (memslot->npages << PAGE_SHIFT); |
824 | if (hva >= start && hva < end) { | 804 | if (hva >= start && hva < end) { |
825 | gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT; | 805 | gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT; |
826 | 806 | ||
827 | retval |= handler(kvm, &memslot->rmap[gfn_offset], | 807 | ret = handler(kvm, &memslot->rmap[gfn_offset], data); |
828 | data); | ||
829 | 808 | ||
830 | for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) { | 809 | for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) { |
831 | int idx = gfn_offset; | 810 | int idx = gfn_offset; |
832 | idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j); | 811 | idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j); |
833 | retval |= handler(kvm, | 812 | ret |= handler(kvm, |
834 | &memslot->lpage_info[j][idx].rmap_pde, | 813 | &memslot->lpage_info[j][idx].rmap_pde, |
835 | data); | 814 | data); |
836 | } | 815 | } |
816 | trace_kvm_age_page(hva, memslot, ret); | ||
817 | retval |= ret; | ||
837 | } | 818 | } |
838 | } | 819 | } |
839 | 820 | ||
@@ -856,9 +837,15 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
856 | u64 *spte; | 837 | u64 *spte; |
857 | int young = 0; | 838 | int young = 0; |
858 | 839 | ||
859 | /* always return old for EPT */ | 840 | /* |
841 | * Emulate the accessed bit for EPT, by checking if this page has | ||
842 | * an EPT mapping, and clearing it if it does. On the next access, | ||
843 | * a new EPT mapping will be established. | ||
844 | * This has some overhead, but not as much as the cost of swapping | ||
845 | * out actively used pages or breaking up actively used hugepages. | ||
846 | */ | ||
860 | if (!shadow_accessed_mask) | 847 | if (!shadow_accessed_mask) |
861 | return 0; | 848 | return kvm_unmap_rmapp(kvm, rmapp, data); |
862 | 849 | ||
863 | spte = rmap_next(kvm, rmapp, NULL); | 850 | spte = rmap_next(kvm, rmapp, NULL); |
864 | while (spte) { | 851 | while (spte) { |
@@ -1615,7 +1602,7 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn) | |||
1615 | 1602 | ||
1616 | static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn) | 1603 | static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn) |
1617 | { | 1604 | { |
1618 | int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn)); | 1605 | int slot = memslot_id(kvm, gfn); |
1619 | struct kvm_mmu_page *sp = page_header(__pa(pte)); | 1606 | struct kvm_mmu_page *sp = page_header(__pa(pte)); |
1620 | 1607 | ||
1621 | __set_bit(slot, sp->slot_bitmap); | 1608 | __set_bit(slot, sp->slot_bitmap); |
@@ -1639,7 +1626,7 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva) | |||
1639 | { | 1626 | { |
1640 | struct page *page; | 1627 | struct page *page; |
1641 | 1628 | ||
1642 | gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); | 1629 | gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); |
1643 | 1630 | ||
1644 | if (gpa == UNMAPPED_GVA) | 1631 | if (gpa == UNMAPPED_GVA) |
1645 | return NULL; | 1632 | return NULL; |
@@ -1852,7 +1839,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
1852 | * is responsibility of mmu_get_page / kvm_sync_page. | 1839 | * is responsibility of mmu_get_page / kvm_sync_page. |
1853 | * Same reasoning can be applied to dirty page accounting. | 1840 | * Same reasoning can be applied to dirty page accounting. |
1854 | */ | 1841 | */ |
1855 | if (!can_unsync && is_writeble_pte(*sptep)) | 1842 | if (!can_unsync && is_writable_pte(*sptep)) |
1856 | goto set_pte; | 1843 | goto set_pte; |
1857 | 1844 | ||
1858 | if (mmu_need_write_protect(vcpu, gfn, can_unsync)) { | 1845 | if (mmu_need_write_protect(vcpu, gfn, can_unsync)) { |
@@ -1860,7 +1847,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
1860 | __func__, gfn); | 1847 | __func__, gfn); |
1861 | ret = 1; | 1848 | ret = 1; |
1862 | pte_access &= ~ACC_WRITE_MASK; | 1849 | pte_access &= ~ACC_WRITE_MASK; |
1863 | if (is_writeble_pte(spte)) | 1850 | if (is_writable_pte(spte)) |
1864 | spte &= ~PT_WRITABLE_MASK; | 1851 | spte &= ~PT_WRITABLE_MASK; |
1865 | } | 1852 | } |
1866 | } | 1853 | } |
@@ -1881,7 +1868,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
1881 | bool reset_host_protection) | 1868 | bool reset_host_protection) |
1882 | { | 1869 | { |
1883 | int was_rmapped = 0; | 1870 | int was_rmapped = 0; |
1884 | int was_writeble = is_writeble_pte(*sptep); | 1871 | int was_writable = is_writable_pte(*sptep); |
1885 | int rmap_count; | 1872 | int rmap_count; |
1886 | 1873 | ||
1887 | pgprintk("%s: spte %llx access %x write_fault %d" | 1874 | pgprintk("%s: spte %llx access %x write_fault %d" |
@@ -1932,7 +1919,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
1932 | if (rmap_count > RMAP_RECYCLE_THRESHOLD) | 1919 | if (rmap_count > RMAP_RECYCLE_THRESHOLD) |
1933 | rmap_recycle(vcpu, sptep, gfn); | 1920 | rmap_recycle(vcpu, sptep, gfn); |
1934 | } else { | 1921 | } else { |
1935 | if (was_writeble) | 1922 | if (was_writable) |
1936 | kvm_release_pfn_dirty(pfn); | 1923 | kvm_release_pfn_dirty(pfn); |
1937 | else | 1924 | else |
1938 | kvm_release_pfn_clean(pfn); | 1925 | kvm_release_pfn_clean(pfn); |
@@ -2162,8 +2149,11 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) | |||
2162 | spin_unlock(&vcpu->kvm->mmu_lock); | 2149 | spin_unlock(&vcpu->kvm->mmu_lock); |
2163 | } | 2150 | } |
2164 | 2151 | ||
2165 | static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) | 2152 | static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr, |
2153 | u32 access, u32 *error) | ||
2166 | { | 2154 | { |
2155 | if (error) | ||
2156 | *error = 0; | ||
2167 | return vaddr; | 2157 | return vaddr; |
2168 | } | 2158 | } |
2169 | 2159 | ||
@@ -2747,7 +2737,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) | |||
2747 | if (tdp_enabled) | 2737 | if (tdp_enabled) |
2748 | return 0; | 2738 | return 0; |
2749 | 2739 | ||
2750 | gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); | 2740 | gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); |
2751 | 2741 | ||
2752 | spin_lock(&vcpu->kvm->mmu_lock); | 2742 | spin_lock(&vcpu->kvm->mmu_lock); |
2753 | r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT); | 2743 | r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT); |
@@ -2847,16 +2837,13 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu) | |||
2847 | */ | 2837 | */ |
2848 | page = alloc_page(GFP_KERNEL | __GFP_DMA32); | 2838 | page = alloc_page(GFP_KERNEL | __GFP_DMA32); |
2849 | if (!page) | 2839 | if (!page) |
2850 | goto error_1; | 2840 | return -ENOMEM; |
2841 | |||
2851 | vcpu->arch.mmu.pae_root = page_address(page); | 2842 | vcpu->arch.mmu.pae_root = page_address(page); |
2852 | for (i = 0; i < 4; ++i) | 2843 | for (i = 0; i < 4; ++i) |
2853 | vcpu->arch.mmu.pae_root[i] = INVALID_PAGE; | 2844 | vcpu->arch.mmu.pae_root[i] = INVALID_PAGE; |
2854 | 2845 | ||
2855 | return 0; | 2846 | return 0; |
2856 | |||
2857 | error_1: | ||
2858 | free_mmu_pages(vcpu); | ||
2859 | return -ENOMEM; | ||
2860 | } | 2847 | } |
2861 | 2848 | ||
2862 | int kvm_mmu_create(struct kvm_vcpu *vcpu) | 2849 | int kvm_mmu_create(struct kvm_vcpu *vcpu) |
@@ -2936,10 +2923,9 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
2936 | spin_lock(&kvm_lock); | 2923 | spin_lock(&kvm_lock); |
2937 | 2924 | ||
2938 | list_for_each_entry(kvm, &vm_list, vm_list) { | 2925 | list_for_each_entry(kvm, &vm_list, vm_list) { |
2939 | int npages; | 2926 | int npages, idx; |
2940 | 2927 | ||
2941 | if (!down_read_trylock(&kvm->slots_lock)) | 2928 | idx = srcu_read_lock(&kvm->srcu); |
2942 | continue; | ||
2943 | spin_lock(&kvm->mmu_lock); | 2929 | spin_lock(&kvm->mmu_lock); |
2944 | npages = kvm->arch.n_alloc_mmu_pages - | 2930 | npages = kvm->arch.n_alloc_mmu_pages - |
2945 | kvm->arch.n_free_mmu_pages; | 2931 | kvm->arch.n_free_mmu_pages; |
@@ -2952,7 +2938,7 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
2952 | nr_to_scan--; | 2938 | nr_to_scan--; |
2953 | 2939 | ||
2954 | spin_unlock(&kvm->mmu_lock); | 2940 | spin_unlock(&kvm->mmu_lock); |
2955 | up_read(&kvm->slots_lock); | 2941 | srcu_read_unlock(&kvm->srcu, idx); |
2956 | } | 2942 | } |
2957 | if (kvm_freed) | 2943 | if (kvm_freed) |
2958 | list_move_tail(&kvm_freed->vm_list, &vm_list); | 2944 | list_move_tail(&kvm_freed->vm_list, &vm_list); |
@@ -3019,9 +3005,11 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm) | |||
3019 | int i; | 3005 | int i; |
3020 | unsigned int nr_mmu_pages; | 3006 | unsigned int nr_mmu_pages; |
3021 | unsigned int nr_pages = 0; | 3007 | unsigned int nr_pages = 0; |
3008 | struct kvm_memslots *slots; | ||
3022 | 3009 | ||
3023 | for (i = 0; i < kvm->nmemslots; i++) | 3010 | slots = rcu_dereference(kvm->memslots); |
3024 | nr_pages += kvm->memslots[i].npages; | 3011 | for (i = 0; i < slots->nmemslots; i++) |
3012 | nr_pages += slots->memslots[i].npages; | ||
3025 | 3013 | ||
3026 | nr_mmu_pages = nr_pages * KVM_PERMILLE_MMU_PAGES / 1000; | 3014 | nr_mmu_pages = nr_pages * KVM_PERMILLE_MMU_PAGES / 1000; |
3027 | nr_mmu_pages = max(nr_mmu_pages, | 3015 | nr_mmu_pages = max(nr_mmu_pages, |
@@ -3246,7 +3234,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte, | |||
3246 | if (is_shadow_present_pte(ent) && !is_last_spte(ent, level)) | 3234 | if (is_shadow_present_pte(ent) && !is_last_spte(ent, level)) |
3247 | audit_mappings_page(vcpu, ent, va, level - 1); | 3235 | audit_mappings_page(vcpu, ent, va, level - 1); |
3248 | else { | 3236 | else { |
3249 | gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va); | 3237 | gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL); |
3250 | gfn_t gfn = gpa >> PAGE_SHIFT; | 3238 | gfn_t gfn = gpa >> PAGE_SHIFT; |
3251 | pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn); | 3239 | pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn); |
3252 | hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT; | 3240 | hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT; |
@@ -3291,10 +3279,12 @@ static void audit_mappings(struct kvm_vcpu *vcpu) | |||
3291 | static int count_rmaps(struct kvm_vcpu *vcpu) | 3279 | static int count_rmaps(struct kvm_vcpu *vcpu) |
3292 | { | 3280 | { |
3293 | int nmaps = 0; | 3281 | int nmaps = 0; |
3294 | int i, j, k; | 3282 | int i, j, k, idx; |
3295 | 3283 | ||
3284 | idx = srcu_read_lock(&kvm->srcu); | ||
3285 | slots = rcu_dereference(kvm->memslots); | ||
3296 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { | 3286 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { |
3297 | struct kvm_memory_slot *m = &vcpu->kvm->memslots[i]; | 3287 | struct kvm_memory_slot *m = &slots->memslots[i]; |
3298 | struct kvm_rmap_desc *d; | 3288 | struct kvm_rmap_desc *d; |
3299 | 3289 | ||
3300 | for (j = 0; j < m->npages; ++j) { | 3290 | for (j = 0; j < m->npages; ++j) { |
@@ -3317,6 +3307,7 @@ static int count_rmaps(struct kvm_vcpu *vcpu) | |||
3317 | } | 3307 | } |
3318 | } | 3308 | } |
3319 | } | 3309 | } |
3310 | srcu_read_unlock(&kvm->srcu, idx); | ||
3320 | return nmaps; | 3311 | return nmaps; |
3321 | } | 3312 | } |
3322 | 3313 | ||