diff options
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 150 |
1 files changed, 63 insertions, 87 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index f02b8edc3d44..22fae7593ee7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -111,9 +111,6 @@ module_param(oos_shadow, bool, 0644); | |||
111 | #define PT64_LEVEL_SHIFT(level) \ | 111 | #define PT64_LEVEL_SHIFT(level) \ |
112 | (PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS) | 112 | (PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS) |
113 | 113 | ||
114 | #define PT64_LEVEL_MASK(level) \ | ||
115 | (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level)) | ||
116 | |||
117 | #define PT64_INDEX(address, level)\ | 114 | #define PT64_INDEX(address, level)\ |
118 | (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1)) | 115 | (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1)) |
119 | 116 | ||
@@ -123,8 +120,6 @@ module_param(oos_shadow, bool, 0644); | |||
123 | #define PT32_LEVEL_SHIFT(level) \ | 120 | #define PT32_LEVEL_SHIFT(level) \ |
124 | (PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS) | 121 | (PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS) |
125 | 122 | ||
126 | #define PT32_LEVEL_MASK(level) \ | ||
127 | (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level)) | ||
128 | #define PT32_LVL_OFFSET_MASK(level) \ | 123 | #define PT32_LVL_OFFSET_MASK(level) \ |
129 | (PT32_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \ | 124 | (PT32_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \ |
130 | * PT32_LEVEL_BITS))) - 1)) | 125 | * PT32_LEVEL_BITS))) - 1)) |
@@ -379,15 +374,15 @@ static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc, | |||
379 | static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache, | 374 | static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache, |
380 | int min) | 375 | int min) |
381 | { | 376 | { |
382 | struct page *page; | 377 | void *page; |
383 | 378 | ||
384 | if (cache->nobjs >= min) | 379 | if (cache->nobjs >= min) |
385 | return 0; | 380 | return 0; |
386 | while (cache->nobjs < ARRAY_SIZE(cache->objects)) { | 381 | while (cache->nobjs < ARRAY_SIZE(cache->objects)) { |
387 | page = alloc_page(GFP_KERNEL); | 382 | page = (void *)__get_free_page(GFP_KERNEL); |
388 | if (!page) | 383 | if (!page) |
389 | return -ENOMEM; | 384 | return -ENOMEM; |
390 | cache->objects[cache->nobjs++] = page_address(page); | 385 | cache->objects[cache->nobjs++] = page; |
391 | } | 386 | } |
392 | return 0; | 387 | return 0; |
393 | } | 388 | } |
@@ -554,13 +549,23 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn) | |||
554 | return ret; | 549 | return ret; |
555 | } | 550 | } |
556 | 551 | ||
557 | static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn) | 552 | static struct kvm_memory_slot * |
553 | gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn, | ||
554 | bool no_dirty_log) | ||
558 | { | 555 | { |
559 | struct kvm_memory_slot *slot; | 556 | struct kvm_memory_slot *slot; |
560 | slot = gfn_to_memslot(vcpu->kvm, large_gfn); | 557 | |
561 | if (slot && slot->dirty_bitmap) | 558 | slot = gfn_to_memslot(vcpu->kvm, gfn); |
562 | return true; | 559 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID || |
563 | return false; | 560 | (no_dirty_log && slot->dirty_bitmap)) |
561 | slot = NULL; | ||
562 | |||
563 | return slot; | ||
564 | } | ||
565 | |||
566 | static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn) | ||
567 | { | ||
568 | return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true); | ||
564 | } | 569 | } |
565 | 570 | ||
566 | static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) | 571 | static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) |
@@ -1032,9 +1037,9 @@ static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
1032 | ASSERT(is_empty_shadow_page(sp->spt)); | 1037 | ASSERT(is_empty_shadow_page(sp->spt)); |
1033 | hlist_del(&sp->hash_link); | 1038 | hlist_del(&sp->hash_link); |
1034 | list_del(&sp->link); | 1039 | list_del(&sp->link); |
1035 | __free_page(virt_to_page(sp->spt)); | 1040 | free_page((unsigned long)sp->spt); |
1036 | if (!sp->role.direct) | 1041 | if (!sp->role.direct) |
1037 | __free_page(virt_to_page(sp->gfns)); | 1042 | free_page((unsigned long)sp->gfns); |
1038 | kmem_cache_free(mmu_page_header_cache, sp); | 1043 | kmem_cache_free(mmu_page_header_cache, sp); |
1039 | kvm_mod_used_mmu_pages(kvm, -1); | 1044 | kvm_mod_used_mmu_pages(kvm, -1); |
1040 | } | 1045 | } |
@@ -1199,6 +1204,13 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva) | |||
1199 | { | 1204 | { |
1200 | } | 1205 | } |
1201 | 1206 | ||
1207 | static void nonpaging_update_pte(struct kvm_vcpu *vcpu, | ||
1208 | struct kvm_mmu_page *sp, u64 *spte, | ||
1209 | const void *pte, unsigned long mmu_seq) | ||
1210 | { | ||
1211 | WARN_ON(1); | ||
1212 | } | ||
1213 | |||
1202 | #define KVM_PAGE_ARRAY_NR 16 | 1214 | #define KVM_PAGE_ARRAY_NR 16 |
1203 | 1215 | ||
1204 | struct kvm_mmu_pages { | 1216 | struct kvm_mmu_pages { |
@@ -2150,26 +2162,13 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) | |||
2150 | { | 2162 | { |
2151 | } | 2163 | } |
2152 | 2164 | ||
2153 | static struct kvm_memory_slot * | ||
2154 | pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) | ||
2155 | { | ||
2156 | struct kvm_memory_slot *slot; | ||
2157 | |||
2158 | slot = gfn_to_memslot(vcpu->kvm, gfn); | ||
2159 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID || | ||
2160 | (no_dirty_log && slot->dirty_bitmap)) | ||
2161 | slot = NULL; | ||
2162 | |||
2163 | return slot; | ||
2164 | } | ||
2165 | |||
2166 | static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, | 2165 | static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, |
2167 | bool no_dirty_log) | 2166 | bool no_dirty_log) |
2168 | { | 2167 | { |
2169 | struct kvm_memory_slot *slot; | 2168 | struct kvm_memory_slot *slot; |
2170 | unsigned long hva; | 2169 | unsigned long hva; |
2171 | 2170 | ||
2172 | slot = pte_prefetch_gfn_to_memslot(vcpu, gfn, no_dirty_log); | 2171 | slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log); |
2173 | if (!slot) { | 2172 | if (!slot) { |
2174 | get_page(bad_page); | 2173 | get_page(bad_page); |
2175 | return page_to_pfn(bad_page); | 2174 | return page_to_pfn(bad_page); |
@@ -2190,7 +2189,7 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu, | |||
2190 | gfn_t gfn; | 2189 | gfn_t gfn; |
2191 | 2190 | ||
2192 | gfn = kvm_mmu_page_get_gfn(sp, start - sp->spt); | 2191 | gfn = kvm_mmu_page_get_gfn(sp, start - sp->spt); |
2193 | if (!pte_prefetch_gfn_to_memslot(vcpu, gfn, access & ACC_WRITE_MASK)) | 2192 | if (!gfn_to_memslot_dirty_bitmap(vcpu, gfn, access & ACC_WRITE_MASK)) |
2194 | return -1; | 2193 | return -1; |
2195 | 2194 | ||
2196 | ret = gfn_to_page_many_atomic(vcpu->kvm, gfn, pages, end - start); | 2195 | ret = gfn_to_page_many_atomic(vcpu->kvm, gfn, pages, end - start); |
@@ -2804,6 +2803,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu, | |||
2804 | context->prefetch_page = nonpaging_prefetch_page; | 2803 | context->prefetch_page = nonpaging_prefetch_page; |
2805 | context->sync_page = nonpaging_sync_page; | 2804 | context->sync_page = nonpaging_sync_page; |
2806 | context->invlpg = nonpaging_invlpg; | 2805 | context->invlpg = nonpaging_invlpg; |
2806 | context->update_pte = nonpaging_update_pte; | ||
2807 | context->root_level = 0; | 2807 | context->root_level = 0; |
2808 | context->shadow_root_level = PT32E_ROOT_LEVEL; | 2808 | context->shadow_root_level = PT32E_ROOT_LEVEL; |
2809 | context->root_hpa = INVALID_PAGE; | 2809 | context->root_hpa = INVALID_PAGE; |
@@ -2933,6 +2933,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu, | |||
2933 | context->prefetch_page = paging64_prefetch_page; | 2933 | context->prefetch_page = paging64_prefetch_page; |
2934 | context->sync_page = paging64_sync_page; | 2934 | context->sync_page = paging64_sync_page; |
2935 | context->invlpg = paging64_invlpg; | 2935 | context->invlpg = paging64_invlpg; |
2936 | context->update_pte = paging64_update_pte; | ||
2936 | context->free = paging_free; | 2937 | context->free = paging_free; |
2937 | context->root_level = level; | 2938 | context->root_level = level; |
2938 | context->shadow_root_level = level; | 2939 | context->shadow_root_level = level; |
@@ -2961,6 +2962,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu, | |||
2961 | context->prefetch_page = paging32_prefetch_page; | 2962 | context->prefetch_page = paging32_prefetch_page; |
2962 | context->sync_page = paging32_sync_page; | 2963 | context->sync_page = paging32_sync_page; |
2963 | context->invlpg = paging32_invlpg; | 2964 | context->invlpg = paging32_invlpg; |
2965 | context->update_pte = paging32_update_pte; | ||
2964 | context->root_level = PT32_ROOT_LEVEL; | 2966 | context->root_level = PT32_ROOT_LEVEL; |
2965 | context->shadow_root_level = PT32E_ROOT_LEVEL; | 2967 | context->shadow_root_level = PT32E_ROOT_LEVEL; |
2966 | context->root_hpa = INVALID_PAGE; | 2968 | context->root_hpa = INVALID_PAGE; |
@@ -2985,6 +2987,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) | |||
2985 | context->prefetch_page = nonpaging_prefetch_page; | 2987 | context->prefetch_page = nonpaging_prefetch_page; |
2986 | context->sync_page = nonpaging_sync_page; | 2988 | context->sync_page = nonpaging_sync_page; |
2987 | context->invlpg = nonpaging_invlpg; | 2989 | context->invlpg = nonpaging_invlpg; |
2990 | context->update_pte = nonpaging_update_pte; | ||
2988 | context->shadow_root_level = kvm_x86_ops->get_tdp_level(); | 2991 | context->shadow_root_level = kvm_x86_ops->get_tdp_level(); |
2989 | context->root_hpa = INVALID_PAGE; | 2992 | context->root_hpa = INVALID_PAGE; |
2990 | context->direct_map = true; | 2993 | context->direct_map = true; |
@@ -3089,8 +3092,6 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu) | |||
3089 | 3092 | ||
3090 | static int init_kvm_mmu(struct kvm_vcpu *vcpu) | 3093 | static int init_kvm_mmu(struct kvm_vcpu *vcpu) |
3091 | { | 3094 | { |
3092 | vcpu->arch.update_pte.pfn = bad_pfn; | ||
3093 | |||
3094 | if (mmu_is_nested(vcpu)) | 3095 | if (mmu_is_nested(vcpu)) |
3095 | return init_kvm_nested_mmu(vcpu); | 3096 | return init_kvm_nested_mmu(vcpu); |
3096 | else if (tdp_enabled) | 3097 | else if (tdp_enabled) |
@@ -3164,7 +3165,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu, | |||
3164 | static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, | 3165 | static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, |
3165 | struct kvm_mmu_page *sp, | 3166 | struct kvm_mmu_page *sp, |
3166 | u64 *spte, | 3167 | u64 *spte, |
3167 | const void *new) | 3168 | const void *new, unsigned long mmu_seq) |
3168 | { | 3169 | { |
3169 | if (sp->role.level != PT_PAGE_TABLE_LEVEL) { | 3170 | if (sp->role.level != PT_PAGE_TABLE_LEVEL) { |
3170 | ++vcpu->kvm->stat.mmu_pde_zapped; | 3171 | ++vcpu->kvm->stat.mmu_pde_zapped; |
@@ -3172,10 +3173,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, | |||
3172 | } | 3173 | } |
3173 | 3174 | ||
3174 | ++vcpu->kvm->stat.mmu_pte_updated; | 3175 | ++vcpu->kvm->stat.mmu_pte_updated; |
3175 | if (!sp->role.cr4_pae) | 3176 | vcpu->arch.mmu.update_pte(vcpu, sp, spte, new, mmu_seq); |
3176 | paging32_update_pte(vcpu, sp, spte, new); | ||
3177 | else | ||
3178 | paging64_update_pte(vcpu, sp, spte, new); | ||
3179 | } | 3177 | } |
3180 | 3178 | ||
3181 | static bool need_remote_flush(u64 old, u64 new) | 3179 | static bool need_remote_flush(u64 old, u64 new) |
@@ -3210,28 +3208,6 @@ static bool last_updated_pte_accessed(struct kvm_vcpu *vcpu) | |||
3210 | return !!(spte && (*spte & shadow_accessed_mask)); | 3208 | return !!(spte && (*spte & shadow_accessed_mask)); |
3211 | } | 3209 | } |
3212 | 3210 | ||
3213 | static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
3214 | u64 gpte) | ||
3215 | { | ||
3216 | gfn_t gfn; | ||
3217 | pfn_t pfn; | ||
3218 | |||
3219 | if (!is_present_gpte(gpte)) | ||
3220 | return; | ||
3221 | gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; | ||
3222 | |||
3223 | vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq; | ||
3224 | smp_rmb(); | ||
3225 | pfn = gfn_to_pfn(vcpu->kvm, gfn); | ||
3226 | |||
3227 | if (is_error_pfn(pfn)) { | ||
3228 | kvm_release_pfn_clean(pfn); | ||
3229 | return; | ||
3230 | } | ||
3231 | vcpu->arch.update_pte.gfn = gfn; | ||
3232 | vcpu->arch.update_pte.pfn = pfn; | ||
3233 | } | ||
3234 | |||
3235 | static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn) | 3211 | static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn) |
3236 | { | 3212 | { |
3237 | u64 *spte = vcpu->arch.last_pte_updated; | 3213 | u64 *spte = vcpu->arch.last_pte_updated; |
@@ -3253,21 +3229,14 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3253 | struct kvm_mmu_page *sp; | 3229 | struct kvm_mmu_page *sp; |
3254 | struct hlist_node *node; | 3230 | struct hlist_node *node; |
3255 | LIST_HEAD(invalid_list); | 3231 | LIST_HEAD(invalid_list); |
3256 | u64 entry, gentry; | 3232 | unsigned long mmu_seq; |
3257 | u64 *spte; | 3233 | u64 entry, gentry, *spte; |
3258 | unsigned offset = offset_in_page(gpa); | 3234 | unsigned pte_size, page_offset, misaligned, quadrant, offset; |
3259 | unsigned pte_size; | 3235 | int level, npte, invlpg_counter, r, flooded = 0; |
3260 | unsigned page_offset; | ||
3261 | unsigned misaligned; | ||
3262 | unsigned quadrant; | ||
3263 | int level; | ||
3264 | int flooded = 0; | ||
3265 | int npte; | ||
3266 | int r; | ||
3267 | int invlpg_counter; | ||
3268 | bool remote_flush, local_flush, zap_page; | 3236 | bool remote_flush, local_flush, zap_page; |
3269 | 3237 | ||
3270 | zap_page = remote_flush = local_flush = false; | 3238 | zap_page = remote_flush = local_flush = false; |
3239 | offset = offset_in_page(gpa); | ||
3271 | 3240 | ||
3272 | pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); | 3241 | pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); |
3273 | 3242 | ||
@@ -3275,9 +3244,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3275 | 3244 | ||
3276 | /* | 3245 | /* |
3277 | * Assume that the pte write on a page table of the same type | 3246 | * Assume that the pte write on a page table of the same type |
3278 | * as the current vcpu paging mode. This is nearly always true | 3247 | * as the current vcpu paging mode since we update the sptes only |
3279 | * (might be false while changing modes). Note it is verified later | 3248 | * when they have the same mode. |
3280 | * by update_pte(). | ||
3281 | */ | 3249 | */ |
3282 | if ((is_pae(vcpu) && bytes == 4) || !new) { | 3250 | if ((is_pae(vcpu) && bytes == 4) || !new) { |
3283 | /* Handle a 32-bit guest writing two halves of a 64-bit gpte */ | 3251 | /* Handle a 32-bit guest writing two halves of a 64-bit gpte */ |
@@ -3303,15 +3271,17 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3303 | break; | 3271 | break; |
3304 | } | 3272 | } |
3305 | 3273 | ||
3306 | mmu_guess_page_from_pte_write(vcpu, gpa, gentry); | 3274 | mmu_seq = vcpu->kvm->mmu_notifier_seq; |
3275 | smp_rmb(); | ||
3276 | |||
3307 | spin_lock(&vcpu->kvm->mmu_lock); | 3277 | spin_lock(&vcpu->kvm->mmu_lock); |
3308 | if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter) | 3278 | if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter) |
3309 | gentry = 0; | 3279 | gentry = 0; |
3310 | kvm_mmu_access_page(vcpu, gfn); | ||
3311 | kvm_mmu_free_some_pages(vcpu); | 3280 | kvm_mmu_free_some_pages(vcpu); |
3312 | ++vcpu->kvm->stat.mmu_pte_write; | 3281 | ++vcpu->kvm->stat.mmu_pte_write; |
3313 | trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE); | 3282 | trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE); |
3314 | if (guest_initiated) { | 3283 | if (guest_initiated) { |
3284 | kvm_mmu_access_page(vcpu, gfn); | ||
3315 | if (gfn == vcpu->arch.last_pt_write_gfn | 3285 | if (gfn == vcpu->arch.last_pt_write_gfn |
3316 | && !last_updated_pte_accessed(vcpu)) { | 3286 | && !last_updated_pte_accessed(vcpu)) { |
3317 | ++vcpu->arch.last_pt_write_count; | 3287 | ++vcpu->arch.last_pt_write_count; |
@@ -3375,7 +3345,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3375 | if (gentry && | 3345 | if (gentry && |
3376 | !((sp->role.word ^ vcpu->arch.mmu.base_role.word) | 3346 | !((sp->role.word ^ vcpu->arch.mmu.base_role.word) |
3377 | & mask.word)) | 3347 | & mask.word)) |
3378 | mmu_pte_write_new_pte(vcpu, sp, spte, &gentry); | 3348 | mmu_pte_write_new_pte(vcpu, sp, spte, &gentry, |
3349 | mmu_seq); | ||
3379 | if (!remote_flush && need_remote_flush(entry, *spte)) | 3350 | if (!remote_flush && need_remote_flush(entry, *spte)) |
3380 | remote_flush = true; | 3351 | remote_flush = true; |
3381 | ++spte; | 3352 | ++spte; |
@@ -3385,10 +3356,6 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3385 | kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list); | 3356 | kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list); |
3386 | trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE); | 3357 | trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE); |
3387 | spin_unlock(&vcpu->kvm->mmu_lock); | 3358 | spin_unlock(&vcpu->kvm->mmu_lock); |
3388 | if (!is_error_pfn(vcpu->arch.update_pte.pfn)) { | ||
3389 | kvm_release_pfn_clean(vcpu->arch.update_pte.pfn); | ||
3390 | vcpu->arch.update_pte.pfn = bad_pfn; | ||
3391 | } | ||
3392 | } | 3359 | } |
3393 | 3360 | ||
3394 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) | 3361 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) |
@@ -3538,14 +3505,23 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) | |||
3538 | if (!test_bit(slot, sp->slot_bitmap)) | 3505 | if (!test_bit(slot, sp->slot_bitmap)) |
3539 | continue; | 3506 | continue; |
3540 | 3507 | ||
3541 | if (sp->role.level != PT_PAGE_TABLE_LEVEL) | ||
3542 | continue; | ||
3543 | |||
3544 | pt = sp->spt; | 3508 | pt = sp->spt; |
3545 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) | 3509 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { |
3510 | if (!is_shadow_present_pte(pt[i]) || | ||
3511 | !is_last_spte(pt[i], sp->role.level)) | ||
3512 | continue; | ||
3513 | |||
3514 | if (is_large_pte(pt[i])) { | ||
3515 | drop_spte(kvm, &pt[i], | ||
3516 | shadow_trap_nonpresent_pte); | ||
3517 | --kvm->stat.lpages; | ||
3518 | continue; | ||
3519 | } | ||
3520 | |||
3546 | /* avoid RMW */ | 3521 | /* avoid RMW */ |
3547 | if (is_writable_pte(pt[i])) | 3522 | if (is_writable_pte(pt[i])) |
3548 | update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK); | 3523 | update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK); |
3524 | } | ||
3549 | } | 3525 | } |
3550 | kvm_flush_remote_tlbs(kvm); | 3526 | kvm_flush_remote_tlbs(kvm); |
3551 | } | 3527 | } |
@@ -3583,7 +3559,7 @@ static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | |||
3583 | if (nr_to_scan == 0) | 3559 | if (nr_to_scan == 0) |
3584 | goto out; | 3560 | goto out; |
3585 | 3561 | ||
3586 | spin_lock(&kvm_lock); | 3562 | raw_spin_lock(&kvm_lock); |
3587 | 3563 | ||
3588 | list_for_each_entry(kvm, &vm_list, vm_list) { | 3564 | list_for_each_entry(kvm, &vm_list, vm_list) { |
3589 | int idx, freed_pages; | 3565 | int idx, freed_pages; |
@@ -3606,7 +3582,7 @@ static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | |||
3606 | if (kvm_freed) | 3582 | if (kvm_freed) |
3607 | list_move_tail(&kvm_freed->vm_list, &vm_list); | 3583 | list_move_tail(&kvm_freed->vm_list, &vm_list); |
3608 | 3584 | ||
3609 | spin_unlock(&kvm_lock); | 3585 | raw_spin_unlock(&kvm_lock); |
3610 | 3586 | ||
3611 | out: | 3587 | out: |
3612 | return percpu_counter_read_positive(&kvm_total_used_mmu_pages); | 3588 | return percpu_counter_read_positive(&kvm_total_used_mmu_pages); |