diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/mmu.c | 53 | ||||
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 30 |
2 files changed, 39 insertions, 44 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 6fc5c389f5a1..af9dafa54f85 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -3181,40 +3181,39 @@ static void direct_pte_prefetch(struct kvm_vcpu *vcpu, u64 *sptep) | |||
3181 | __direct_pte_prefetch(vcpu, sp, sptep); | 3181 | __direct_pte_prefetch(vcpu, sp, sptep); |
3182 | } | 3182 | } |
3183 | 3183 | ||
3184 | static int __direct_map(struct kvm_vcpu *vcpu, int write, int map_writable, | 3184 | static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, int write, |
3185 | int level, gfn_t gfn, kvm_pfn_t pfn, bool prefault) | 3185 | int map_writable, int level, kvm_pfn_t pfn, |
3186 | bool prefault) | ||
3186 | { | 3187 | { |
3187 | struct kvm_shadow_walk_iterator iterator; | 3188 | struct kvm_shadow_walk_iterator it; |
3188 | struct kvm_mmu_page *sp; | 3189 | struct kvm_mmu_page *sp; |
3189 | int emulate = 0; | 3190 | int ret; |
3190 | gfn_t pseudo_gfn; | 3191 | gfn_t gfn = gpa >> PAGE_SHIFT; |
3192 | gfn_t base_gfn = gfn; | ||
3191 | 3193 | ||
3192 | if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) | 3194 | if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) |
3193 | return 0; | 3195 | return RET_PF_RETRY; |
3194 | 3196 | ||
3195 | for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) { | 3197 | for_each_shadow_entry(vcpu, gpa, it) { |
3196 | if (iterator.level == level) { | 3198 | base_gfn = gfn & ~(KVM_PAGES_PER_HPAGE(it.level) - 1); |
3197 | emulate = mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, | 3199 | if (it.level == level) |
3198 | write, level, gfn, pfn, prefault, | ||
3199 | map_writable); | ||
3200 | direct_pte_prefetch(vcpu, iterator.sptep); | ||
3201 | ++vcpu->stat.pf_fixed; | ||
3202 | break; | 3200 | break; |
3203 | } | ||
3204 | 3201 | ||
3205 | drop_large_spte(vcpu, iterator.sptep); | 3202 | drop_large_spte(vcpu, it.sptep); |
3206 | if (!is_shadow_present_pte(*iterator.sptep)) { | 3203 | if (!is_shadow_present_pte(*it.sptep)) { |
3207 | u64 base_addr = iterator.addr; | 3204 | sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr, |
3205 | it.level - 1, true, ACC_ALL); | ||
3208 | 3206 | ||
3209 | base_addr &= PT64_LVL_ADDR_MASK(iterator.level); | 3207 | link_shadow_page(vcpu, it.sptep, sp); |
3210 | pseudo_gfn = base_addr >> PAGE_SHIFT; | ||
3211 | sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr, | ||
3212 | iterator.level - 1, 1, ACC_ALL); | ||
3213 | |||
3214 | link_shadow_page(vcpu, iterator.sptep, sp); | ||
3215 | } | 3208 | } |
3216 | } | 3209 | } |
3217 | return emulate; | 3210 | |
3211 | ret = mmu_set_spte(vcpu, it.sptep, ACC_ALL, | ||
3212 | write, level, base_gfn, pfn, prefault, | ||
3213 | map_writable); | ||
3214 | direct_pte_prefetch(vcpu, it.sptep); | ||
3215 | ++vcpu->stat.pf_fixed; | ||
3216 | return ret; | ||
3218 | } | 3217 | } |
3219 | 3218 | ||
3220 | static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *tsk) | 3219 | static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *tsk) |
@@ -3538,8 +3537,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code, | |||
3538 | goto out_unlock; | 3537 | goto out_unlock; |
3539 | if (likely(!force_pt_level)) | 3538 | if (likely(!force_pt_level)) |
3540 | transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level); | 3539 | transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level); |
3541 | r = __direct_map(vcpu, write, map_writable, level, gfn, pfn, prefault); | 3540 | r = __direct_map(vcpu, v, write, map_writable, level, pfn, prefault); |
3542 | |||
3543 | out_unlock: | 3541 | out_unlock: |
3544 | spin_unlock(&vcpu->kvm->mmu_lock); | 3542 | spin_unlock(&vcpu->kvm->mmu_lock); |
3545 | kvm_release_pfn_clean(pfn); | 3543 | kvm_release_pfn_clean(pfn); |
@@ -4165,8 +4163,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, | |||
4165 | goto out_unlock; | 4163 | goto out_unlock; |
4166 | if (likely(!force_pt_level)) | 4164 | if (likely(!force_pt_level)) |
4167 | transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level); | 4165 | transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level); |
4168 | r = __direct_map(vcpu, write, map_writable, level, gfn, pfn, prefault); | 4166 | r = __direct_map(vcpu, gpa, write, map_writable, level, pfn, prefault); |
4169 | |||
4170 | out_unlock: | 4167 | out_unlock: |
4171 | spin_unlock(&vcpu->kvm->mmu_lock); | 4168 | spin_unlock(&vcpu->kvm->mmu_lock); |
4172 | kvm_release_pfn_clean(pfn); | 4169 | kvm_release_pfn_clean(pfn); |
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 2db96401178e..bfd89966832b 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -623,6 +623,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
623 | struct kvm_shadow_walk_iterator it; | 623 | struct kvm_shadow_walk_iterator it; |
624 | unsigned direct_access, access = gw->pt_access; | 624 | unsigned direct_access, access = gw->pt_access; |
625 | int top_level, ret; | 625 | int top_level, ret; |
626 | gfn_t base_gfn; | ||
626 | 627 | ||
627 | direct_access = gw->pte_access; | 628 | direct_access = gw->pte_access; |
628 | 629 | ||
@@ -667,31 +668,29 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
667 | link_shadow_page(vcpu, it.sptep, sp); | 668 | link_shadow_page(vcpu, it.sptep, sp); |
668 | } | 669 | } |
669 | 670 | ||
670 | for (; | 671 | base_gfn = gw->gfn; |
671 | shadow_walk_okay(&it) && it.level > hlevel; | ||
672 | shadow_walk_next(&it)) { | ||
673 | gfn_t direct_gfn; | ||
674 | 672 | ||
673 | for (; shadow_walk_okay(&it); shadow_walk_next(&it)) { | ||
675 | clear_sp_write_flooding_count(it.sptep); | 674 | clear_sp_write_flooding_count(it.sptep); |
675 | base_gfn = gw->gfn & ~(KVM_PAGES_PER_HPAGE(it.level) - 1); | ||
676 | if (it.level == hlevel) | ||
677 | break; | ||
678 | |||
676 | validate_direct_spte(vcpu, it.sptep, direct_access); | 679 | validate_direct_spte(vcpu, it.sptep, direct_access); |
677 | 680 | ||
678 | drop_large_spte(vcpu, it.sptep); | 681 | drop_large_spte(vcpu, it.sptep); |
679 | 682 | ||
680 | if (is_shadow_present_pte(*it.sptep)) | 683 | if (!is_shadow_present_pte(*it.sptep)) { |
681 | continue; | 684 | sp = kvm_mmu_get_page(vcpu, base_gfn, addr, |
682 | 685 | it.level - 1, true, direct_access); | |
683 | direct_gfn = gw->gfn & ~(KVM_PAGES_PER_HPAGE(it.level) - 1); | 686 | link_shadow_page(vcpu, it.sptep, sp); |
684 | 687 | } | |
685 | sp = kvm_mmu_get_page(vcpu, direct_gfn, addr, it.level-1, | ||
686 | true, direct_access); | ||
687 | link_shadow_page(vcpu, it.sptep, sp); | ||
688 | } | 688 | } |
689 | 689 | ||
690 | clear_sp_write_flooding_count(it.sptep); | ||
691 | ret = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault, | 690 | ret = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault, |
692 | it.level, gw->gfn, pfn, prefault, map_writable); | 691 | it.level, base_gfn, pfn, prefault, map_writable); |
693 | FNAME(pte_prefetch)(vcpu, gw, it.sptep); | 692 | FNAME(pte_prefetch)(vcpu, gw, it.sptep); |
694 | 693 | ++vcpu->stat.pf_fixed; | |
695 | return ret; | 694 | return ret; |
696 | 695 | ||
697 | out_gpte_changed: | 696 | out_gpte_changed: |
@@ -854,7 +853,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, | |||
854 | transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level); | 853 | transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level); |
855 | r = FNAME(fetch)(vcpu, addr, &walker, write_fault, | 854 | r = FNAME(fetch)(vcpu, addr, &walker, write_fault, |
856 | level, pfn, map_writable, prefault); | 855 | level, pfn, map_writable, prefault); |
857 | ++vcpu->stat.pf_fixed; | ||
858 | kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); | 856 | kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); |
859 | 857 | ||
860 | out_unlock: | 858 | out_unlock: |