OSDN Git Service

KVM: arm64: Convert page-aging and access faults to generic page-table API
authorWill Deacon <will@kernel.org>
Fri, 11 Sep 2020 13:25:19 +0000 (14:25 +0100)
committerMarc Zyngier <maz@kernel.org>
Fri, 11 Sep 2020 14:51:14 +0000 (15:51 +0100)
Convert the page-aging functions and access fault handler to use the
generic page-table code instead of walking the page-table directly.

Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Quentin Perret <qperret@google.com>
Link: https://lore.kernel.org/r/20200911132529.19844-12-will@kernel.org
arch/arm64/kvm/mmu.c

index f03d3d0..36407dc 100644 (file)
@@ -1706,46 +1706,23 @@ out_unlock:
        return ret;
 }
 
-/*
- * Resolve the access fault by making the page young again.
- * Note that because the faulting entry is guaranteed not to be
- * cached in the TLB, we don't need to invalidate anything.
- * Only the HW Access Flag updates are supported for Stage 2 (no DBM),
- * so there is no need for atomic (pte|pmd)_mkyoung operations.
- */
+/* Resolve the access fault by making the page young again. */
 static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 {
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       kvm_pfn_t pfn;
-       bool pfn_valid = false;
+       pte_t pte;
+       kvm_pte_t kpte;
+       struct kvm_s2_mmu *mmu;
 
        trace_kvm_access_fault(fault_ipa);
 
        spin_lock(&vcpu->kvm->mmu_lock);
-
-       if (!stage2_get_leaf_entry(vcpu->arch.hw_mmu, fault_ipa, &pud, &pmd, &pte))
-               goto out;
-
-       if (pud) {              /* HugeTLB */
-               *pud = kvm_s2pud_mkyoung(*pud);
-               pfn = kvm_pud_pfn(*pud);
-               pfn_valid = true;
-       } else  if (pmd) {      /* THP, HugeTLB */
-               *pmd = pmd_mkyoung(*pmd);
-               pfn = pmd_pfn(*pmd);
-               pfn_valid = true;
-       } else {
-               *pte = pte_mkyoung(*pte);       /* Just a page... */
-               pfn = pte_pfn(*pte);
-               pfn_valid = true;
-       }
-
-out:
+       mmu = vcpu->arch.hw_mmu;
+       kpte = kvm_pgtable_stage2_mkyoung(mmu->pgt, fault_ipa);
        spin_unlock(&vcpu->kvm->mmu_lock);
-       if (pfn_valid)
-               kvm_set_pfn_accessed(pfn);
+
+       pte = __pte(kpte);
+       if (pte_valid(pte))
+               kvm_set_pfn_accessed(pte_pfn(pte));
 }
 
 /**
@@ -1962,38 +1939,19 @@ int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
 
 static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data)
 {
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
+       pte_t pte;
+       kvm_pte_t kpte;
 
        WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-       if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
-               return 0;
-
-       if (pud)
-               return stage2_pudp_test_and_clear_young(pud);
-       else if (pmd)
-               return stage2_pmdp_test_and_clear_young(pmd);
-       else
-               return stage2_ptep_test_and_clear_young(pte);
+       kpte = kvm_pgtable_stage2_mkold(kvm->arch.mmu.pgt, gpa);
+       pte = __pte(kpte);
+       return pte_valid(pte) && pte_young(pte);
 }
 
 static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data)
 {
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-
        WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-       if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
-               return 0;
-
-       if (pud)
-               return kvm_s2pud_young(*pud);
-       else if (pmd)
-               return pmd_young(*pmd);
-       else
-               return pte_young(*pte);
+       return kvm_pgtable_stage2_is_young(kvm->arch.mmu.pgt, gpa);
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)