aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/paging_tmpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/paging_tmpl.h')
-rw-r--r--arch/x86/kvm/paging_tmpl.h86
1 files changed, 40 insertions, 46 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 92994100638b..15610285ebb6 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -497,6 +497,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
497 shadow_walk_next(&it)) { 497 shadow_walk_next(&it)) {
498 gfn_t table_gfn; 498 gfn_t table_gfn;
499 499
500 clear_sp_write_flooding_count(it.sptep);
500 drop_large_spte(vcpu, it.sptep); 501 drop_large_spte(vcpu, it.sptep);
501 502
502 sp = NULL; 503 sp = NULL;
@@ -522,6 +523,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
522 shadow_walk_next(&it)) { 523 shadow_walk_next(&it)) {
523 gfn_t direct_gfn; 524 gfn_t direct_gfn;
524 525
526 clear_sp_write_flooding_count(it.sptep);
525 validate_direct_spte(vcpu, it.sptep, direct_access); 527 validate_direct_spte(vcpu, it.sptep, direct_access);
526 528
527 drop_large_spte(vcpu, it.sptep); 529 drop_large_spte(vcpu, it.sptep);
@@ -536,6 +538,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
536 link_shadow_page(it.sptep, sp); 538 link_shadow_page(it.sptep, sp);
537 } 539 }
538 540
541 clear_sp_write_flooding_count(it.sptep);
539 mmu_set_spte(vcpu, it.sptep, access, gw->pte_access, 542 mmu_set_spte(vcpu, it.sptep, access, gw->pte_access,
540 user_fault, write_fault, emulate, it.level, 543 user_fault, write_fault, emulate, it.level,
541 gw->gfn, pfn, prefault, map_writable); 544 gw->gfn, pfn, prefault, map_writable);
@@ -599,11 +602,9 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
599 */ 602 */
600 if (!r) { 603 if (!r) {
601 pgprintk("%s: guest page fault\n", __func__); 604 pgprintk("%s: guest page fault\n", __func__);
602 if (!prefault) { 605 if (!prefault)
603 inject_page_fault(vcpu, &walker.fault); 606 inject_page_fault(vcpu, &walker.fault);
604 /* reset fork detector */ 607
605 vcpu->arch.last_pt_write_count = 0;
606 }
607 return 0; 608 return 0;
608 } 609 }
609 610
@@ -631,7 +632,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
631 if (mmu_notifier_retry(vcpu, mmu_seq)) 632 if (mmu_notifier_retry(vcpu, mmu_seq))
632 goto out_unlock; 633 goto out_unlock;
633 634
634 trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT); 635 kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
635 kvm_mmu_free_some_pages(vcpu); 636 kvm_mmu_free_some_pages(vcpu);
636 if (!force_pt_level) 637 if (!force_pt_level)
637 transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level); 638 transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
@@ -641,11 +642,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
641 pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__, 642 pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__,
642 sptep, *sptep, emulate); 643 sptep, *sptep, emulate);
643 644
644 if (!emulate)
645 vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
646
647 ++vcpu->stat.pf_fixed; 645 ++vcpu->stat.pf_fixed;
648 trace_kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); 646 kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
649 spin_unlock(&vcpu->kvm->mmu_lock); 647 spin_unlock(&vcpu->kvm->mmu_lock);
650 648
651 return emulate; 649 return emulate;
@@ -656,65 +654,66 @@ out_unlock:
656 return 0; 654 return 0;
657} 655}
658 656
657static gpa_t FNAME(get_level1_sp_gpa)(struct kvm_mmu_page *sp)
658{
659 int offset = 0;
660
661 WARN_ON(sp->role.level != 1);
662
663 if (PTTYPE == 32)
664 offset = sp->role.quadrant << PT64_LEVEL_BITS;
665
666 return gfn_to_gpa(sp->gfn) + offset * sizeof(pt_element_t);
667}
668
659static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) 669static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
660{ 670{
661 struct kvm_shadow_walk_iterator iterator; 671 struct kvm_shadow_walk_iterator iterator;
662 struct kvm_mmu_page *sp; 672 struct kvm_mmu_page *sp;
663 gpa_t pte_gpa = -1;
664 int level; 673 int level;
665 u64 *sptep; 674 u64 *sptep;
666 int need_flush = 0;
667 675
668 vcpu_clear_mmio_info(vcpu, gva); 676 vcpu_clear_mmio_info(vcpu, gva);
669 677
670 spin_lock(&vcpu->kvm->mmu_lock); 678 /*
679 * No need to check return value here, rmap_can_add() can
680 * help us to skip pte prefetch later.
681 */
682 mmu_topup_memory_caches(vcpu);
671 683
684 spin_lock(&vcpu->kvm->mmu_lock);
672 for_each_shadow_entry(vcpu, gva, iterator) { 685 for_each_shadow_entry(vcpu, gva, iterator) {
673 level = iterator.level; 686 level = iterator.level;
674 sptep = iterator.sptep; 687 sptep = iterator.sptep;
675 688
676 sp = page_header(__pa(sptep)); 689 sp = page_header(__pa(sptep));
677 if (is_last_spte(*sptep, level)) { 690 if (is_last_spte(*sptep, level)) {
678 int offset, shift; 691 pt_element_t gpte;
692 gpa_t pte_gpa;
679 693
680 if (!sp->unsync) 694 if (!sp->unsync)
681 break; 695 break;
682 696
683 shift = PAGE_SHIFT - 697 pte_gpa = FNAME(get_level1_sp_gpa)(sp);
684 (PT_LEVEL_BITS - PT64_LEVEL_BITS) * level;
685 offset = sp->role.quadrant << shift;
686
687 pte_gpa = (sp->gfn << PAGE_SHIFT) + offset;
688 pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); 698 pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
689 699
690 if (is_shadow_present_pte(*sptep)) { 700 if (mmu_page_zap_pte(vcpu->kvm, sp, sptep))
691 if (is_large_pte(*sptep)) 701 kvm_flush_remote_tlbs(vcpu->kvm);
692 --vcpu->kvm->stat.lpages;
693 drop_spte(vcpu->kvm, sptep);
694 need_flush = 1;
695 } else if (is_mmio_spte(*sptep))
696 mmu_spte_clear_no_track(sptep);
697 702
698 break; 703 if (!rmap_can_add(vcpu))
704 break;
705
706 if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte,
707 sizeof(pt_element_t)))
708 break;
709
710 FNAME(update_pte)(vcpu, sp, sptep, &gpte);
699 } 711 }
700 712
701 if (!is_shadow_present_pte(*sptep) || !sp->unsync_children) 713 if (!is_shadow_present_pte(*sptep) || !sp->unsync_children)
702 break; 714 break;
703 } 715 }
704
705 if (need_flush)
706 kvm_flush_remote_tlbs(vcpu->kvm);
707
708 atomic_inc(&vcpu->kvm->arch.invlpg_counter);
709
710 spin_unlock(&vcpu->kvm->mmu_lock); 716 spin_unlock(&vcpu->kvm->mmu_lock);
711
712 if (pte_gpa == -1)
713 return;
714
715 if (mmu_topup_memory_caches(vcpu))
716 return;
717 kvm_mmu_pte_write(vcpu, pte_gpa, NULL, sizeof(pt_element_t), 0);
718} 717}
719 718
720static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access, 719static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
@@ -769,19 +768,14 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
769 */ 768 */
770static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) 769static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
771{ 770{
772 int i, offset, nr_present; 771 int i, nr_present = 0;
773 bool host_writable; 772 bool host_writable;
774 gpa_t first_pte_gpa; 773 gpa_t first_pte_gpa;
775 774
776 offset = nr_present = 0;
777
778 /* direct kvm_mmu_page can not be unsync. */ 775 /* direct kvm_mmu_page can not be unsync. */
779 BUG_ON(sp->role.direct); 776 BUG_ON(sp->role.direct);
780 777
781 if (PTTYPE == 32) 778 first_pte_gpa = FNAME(get_level1_sp_gpa)(sp);
782 offset = sp->role.quadrant << PT64_LEVEL_BITS;
783
784 first_pte_gpa = gfn_to_gpa(sp->gfn) + offset * sizeof(pt_element_t);
785 779
786 for (i = 0; i < PT64_ENT_PER_PAGE; i++) { 780 for (i = 0; i < PT64_ENT_PER_PAGE; i++) {
787 unsigned pte_access; 781 unsigned pte_access;