aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2011-03-09 02:43:51 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2011-03-17 12:08:35 -0400
commit0f53b5b1c0baae4f949ac0721a55b7a2158dda01 (patch)
tree822b7230ed0d9731492733d33ad2221cb644bdf2 /arch/x86/kvm/mmu.c
parent5d163b1c9d6e5562dcdfd6cd471f237f1502bb35 (diff)
KVM: MMU: cleanup pte write path
This patch does: - call vcpu->arch.mmu.update_pte directly - use gfn_to_pfn_atomic in update_pte path The suggestion is from Avi. Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c69
1 files changed, 23 insertions, 46 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 83171fdd38a7..22fae7593ee7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1204,6 +1204,13 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
1204{ 1204{
1205} 1205}
1206 1206
1207static 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
1207#define KVM_PAGE_ARRAY_NR 16 1214#define KVM_PAGE_ARRAY_NR 16
1208 1215
1209struct kvm_mmu_pages { 1216struct kvm_mmu_pages {
@@ -2796,6 +2803,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu,
2796 context->prefetch_page = nonpaging_prefetch_page; 2803 context->prefetch_page = nonpaging_prefetch_page;
2797 context->sync_page = nonpaging_sync_page; 2804 context->sync_page = nonpaging_sync_page;
2798 context->invlpg = nonpaging_invlpg; 2805 context->invlpg = nonpaging_invlpg;
2806 context->update_pte = nonpaging_update_pte;
2799 context->root_level = 0; 2807 context->root_level = 0;
2800 context->shadow_root_level = PT32E_ROOT_LEVEL; 2808 context->shadow_root_level = PT32E_ROOT_LEVEL;
2801 context->root_hpa = INVALID_PAGE; 2809 context->root_hpa = INVALID_PAGE;
@@ -2925,6 +2933,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
2925 context->prefetch_page = paging64_prefetch_page; 2933 context->prefetch_page = paging64_prefetch_page;
2926 context->sync_page = paging64_sync_page; 2934 context->sync_page = paging64_sync_page;
2927 context->invlpg = paging64_invlpg; 2935 context->invlpg = paging64_invlpg;
2936 context->update_pte = paging64_update_pte;
2928 context->free = paging_free; 2937 context->free = paging_free;
2929 context->root_level = level; 2938 context->root_level = level;
2930 context->shadow_root_level = level; 2939 context->shadow_root_level = level;
@@ -2953,6 +2962,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
2953 context->prefetch_page = paging32_prefetch_page; 2962 context->prefetch_page = paging32_prefetch_page;
2954 context->sync_page = paging32_sync_page; 2963 context->sync_page = paging32_sync_page;
2955 context->invlpg = paging32_invlpg; 2964 context->invlpg = paging32_invlpg;
2965 context->update_pte = paging32_update_pte;
2956 context->root_level = PT32_ROOT_LEVEL; 2966 context->root_level = PT32_ROOT_LEVEL;
2957 context->shadow_root_level = PT32E_ROOT_LEVEL; 2967 context->shadow_root_level = PT32E_ROOT_LEVEL;
2958 context->root_hpa = INVALID_PAGE; 2968 context->root_hpa = INVALID_PAGE;
@@ -2977,6 +2987,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
2977 context->prefetch_page = nonpaging_prefetch_page; 2987 context->prefetch_page = nonpaging_prefetch_page;
2978 context->sync_page = nonpaging_sync_page; 2988 context->sync_page = nonpaging_sync_page;
2979 context->invlpg = nonpaging_invlpg; 2989 context->invlpg = nonpaging_invlpg;
2990 context->update_pte = nonpaging_update_pte;
2980 context->shadow_root_level = kvm_x86_ops->get_tdp_level(); 2991 context->shadow_root_level = kvm_x86_ops->get_tdp_level();
2981 context->root_hpa = INVALID_PAGE; 2992 context->root_hpa = INVALID_PAGE;
2982 context->direct_map = true; 2993 context->direct_map = true;
@@ -3081,8 +3092,6 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
3081 3092
3082static int init_kvm_mmu(struct kvm_vcpu *vcpu) 3093static int init_kvm_mmu(struct kvm_vcpu *vcpu)
3083{ 3094{
3084 vcpu->arch.update_pte.pfn = bad_pfn;
3085
3086 if (mmu_is_nested(vcpu)) 3095 if (mmu_is_nested(vcpu))
3087 return init_kvm_nested_mmu(vcpu); 3096 return init_kvm_nested_mmu(vcpu);
3088 else if (tdp_enabled) 3097 else if (tdp_enabled)
@@ -3156,7 +3165,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
3156static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, 3165static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
3157 struct kvm_mmu_page *sp, 3166 struct kvm_mmu_page *sp,
3158 u64 *spte, 3167 u64 *spte,
3159 const void *new) 3168 const void *new, unsigned long mmu_seq)
3160{ 3169{
3161 if (sp->role.level != PT_PAGE_TABLE_LEVEL) { 3170 if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
3162 ++vcpu->kvm->stat.mmu_pde_zapped; 3171 ++vcpu->kvm->stat.mmu_pde_zapped;
@@ -3164,10 +3173,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
3164 } 3173 }
3165 3174
3166 ++vcpu->kvm->stat.mmu_pte_updated; 3175 ++vcpu->kvm->stat.mmu_pte_updated;
3167 if (!sp->role.cr4_pae) 3176 vcpu->arch.mmu.update_pte(vcpu, sp, spte, new, mmu_seq);
3168 paging32_update_pte(vcpu, sp, spte, new);
3169 else
3170 paging64_update_pte(vcpu, sp, spte, new);
3171} 3177}
3172 3178
3173static bool need_remote_flush(u64 old, u64 new) 3179static bool need_remote_flush(u64 old, u64 new)
@@ -3202,27 +3208,6 @@ static bool last_updated_pte_accessed(struct kvm_vcpu *vcpu)
3202 return !!(spte && (*spte & shadow_accessed_mask)); 3208 return !!(spte && (*spte & shadow_accessed_mask));
3203} 3209}
3204 3210
3205static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3206 u64 gpte)
3207{
3208 gfn_t gfn;
3209 pfn_t pfn;
3210
3211 if (!is_present_gpte(gpte))
3212 return;
3213 gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
3214
3215 vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq;
3216 smp_rmb();
3217 pfn = gfn_to_pfn(vcpu->kvm, gfn);
3218
3219 if (is_error_pfn(pfn)) {
3220 kvm_release_pfn_clean(pfn);
3221 return;
3222 }
3223 vcpu->arch.update_pte.pfn = pfn;
3224}
3225
3226static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn) 3211static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn)
3227{ 3212{
3228 u64 *spte = vcpu->arch.last_pte_updated; 3213 u64 *spte = vcpu->arch.last_pte_updated;
@@ -3244,21 +3229,14 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3244 struct kvm_mmu_page *sp; 3229 struct kvm_mmu_page *sp;
3245 struct hlist_node *node; 3230 struct hlist_node *node;
3246 LIST_HEAD(invalid_list); 3231 LIST_HEAD(invalid_list);
3247 u64 entry, gentry; 3232 unsigned long mmu_seq;
3248 u64 *spte; 3233 u64 entry, gentry, *spte;
3249 unsigned offset = offset_in_page(gpa); 3234 unsigned pte_size, page_offset, misaligned, quadrant, offset;
3250 unsigned pte_size; 3235 int level, npte, invlpg_counter, r, flooded = 0;
3251 unsigned page_offset;
3252 unsigned misaligned;
3253 unsigned quadrant;
3254 int level;
3255 int flooded = 0;
3256 int npte;
3257 int r;
3258 int invlpg_counter;
3259 bool remote_flush, local_flush, zap_page; 3236 bool remote_flush, local_flush, zap_page;
3260 3237
3261 zap_page = remote_flush = local_flush = false; 3238 zap_page = remote_flush = local_flush = false;
3239 offset = offset_in_page(gpa);
3262 3240
3263 pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); 3241 pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
3264 3242
@@ -3293,7 +3271,9 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3293 break; 3271 break;
3294 } 3272 }
3295 3273
3296 mmu_guess_page_from_pte_write(vcpu, gpa, gentry); 3274 mmu_seq = vcpu->kvm->mmu_notifier_seq;
3275 smp_rmb();
3276
3297 spin_lock(&vcpu->kvm->mmu_lock); 3277 spin_lock(&vcpu->kvm->mmu_lock);
3298 if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter) 3278 if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter)
3299 gentry = 0; 3279 gentry = 0;
@@ -3365,7 +3345,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3365 if (gentry && 3345 if (gentry &&
3366 !((sp->role.word ^ vcpu->arch.mmu.base_role.word) 3346 !((sp->role.word ^ vcpu->arch.mmu.base_role.word)
3367 & mask.word)) 3347 & mask.word))
3368 mmu_pte_write_new_pte(vcpu, sp, spte, &gentry); 3348 mmu_pte_write_new_pte(vcpu, sp, spte, &gentry,
3349 mmu_seq);
3369 if (!remote_flush && need_remote_flush(entry, *spte)) 3350 if (!remote_flush && need_remote_flush(entry, *spte))
3370 remote_flush = true; 3351 remote_flush = true;
3371 ++spte; 3352 ++spte;
@@ -3375,10 +3356,6 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3375 kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list); 3356 kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
3376 trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE); 3357 trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE);
3377 spin_unlock(&vcpu->kvm->mmu_lock); 3358 spin_unlock(&vcpu->kvm->mmu_lock);
3378 if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
3379 kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
3380 vcpu->arch.update_pte.pfn = bad_pfn;
3381 }
3382} 3359}
3383 3360
3384int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) 3361int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)