Skip to content
Permalink
Browse files
kvm: mmu: Wrap mmu_lock lock / unlock in a function
Wrap locking and unlocking the mmu_lock in a function. This will
facilitate future logging and stat collection for the lock and more
immediately support a refactoring to move the lock into the struct
kvm_arch(s) so that x86 can change the spinlock to a rwlock without
affecting the performance of other archs.

No functional change intended.

Signed-off-by: Peter Feiner <pfeiner@google.com>

Signed-off-by: Ben Gardon <bgardon@google.com>
  • Loading branch information
Ben Gardon authored and intel-lab-lkp committed Jan 12, 2021
1 parent e537d29 commit 07d5ac23775a490560374edfec570f64687a6f09
Show file tree
Hide file tree
Showing 19 changed files with 172 additions and 159 deletions.
@@ -164,13 +164,13 @@ static void stage2_flush_vm(struct kvm *kvm)
int idx;

idx = srcu_read_lock(&kvm->srcu);
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);

slots = kvm_memslots(kvm);
kvm_for_each_memslot(memslot, slots)
stage2_flush_memslot(kvm, memslot);

spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
srcu_read_unlock(&kvm->srcu, idx);
}

@@ -456,13 +456,13 @@ void stage2_unmap_vm(struct kvm *kvm)

idx = srcu_read_lock(&kvm->srcu);
mmap_read_lock(current->mm);
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);

slots = kvm_memslots(kvm);
kvm_for_each_memslot(memslot, slots)
stage2_unmap_memslot(kvm, memslot);

spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
mmap_read_unlock(current->mm);
srcu_read_unlock(&kvm->srcu, idx);
}
@@ -472,14 +472,14 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
struct kvm *kvm = mmu->kvm;
struct kvm_pgtable *pgt = NULL;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
pgt = mmu->pgt;
if (pgt) {
mmu->pgd_phys = 0;
mmu->pgt = NULL;
free_percpu(mmu->last_vcpu_ran);
}
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);

if (pgt) {
kvm_pgtable_stage2_destroy(pgt);
@@ -516,10 +516,10 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
if (ret)
break;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
ret = kvm_pgtable_stage2_map(pgt, addr, PAGE_SIZE, pa, prot,
&cache);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
if (ret)
break;

@@ -567,9 +567,9 @@ void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot)
start = memslot->base_gfn << PAGE_SHIFT;
end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
stage2_wp_range(&kvm->arch.mmu, start, end);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
kvm_flush_remote_tlbs(kvm);
}

@@ -867,7 +867,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (exec_fault && device)
return -ENOEXEC;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
pgt = vcpu->arch.hw_mmu->pgt;
if (mmu_notifier_retry(kvm, mmu_seq))
goto out_unlock;
@@ -912,7 +912,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
}

out_unlock:
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
kvm_set_pfn_accessed(pfn);
kvm_release_pfn_clean(pfn);
return ret;
@@ -927,10 +927,10 @@ static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)

trace_kvm_access_fault(fault_ipa);

spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_lock(vcpu->kvm);
mmu = vcpu->arch.hw_mmu;
kpte = kvm_pgtable_stage2_mkyoung(mmu->pgt, fault_ipa);
spin_unlock(&vcpu->kvm->mmu_lock);
kvm_mmu_unlock(vcpu->kvm);

pte = __pte(kpte);
if (pte_valid(pte))
@@ -1365,12 +1365,12 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
if (change == KVM_MR_FLAGS_ONLY)
goto out;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
if (ret)
unmap_stage2_range(&kvm->arch.mmu, mem->guest_phys_addr, mem->memory_size);
else if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
stage2_flush_memslot(kvm, memslot);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
out:
mmap_read_unlock(current->mm);
return ret;
@@ -1395,9 +1395,9 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
gpa_t gpa = slot->base_gfn << PAGE_SHIFT;
phys_addr_t size = slot->npages << PAGE_SHIFT;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
unmap_stage2_range(&kvm->arch.mmu, gpa, size);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}

/*
@@ -217,13 +217,13 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
* need to ensure that it can no longer be accessed by any guest VCPUs.
*/

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
/* Flush slot from GPA */
kvm_mips_flush_gpa_pt(kvm, slot->base_gfn,
slot->base_gfn + slot->npages - 1);
/* Let implementation do the rest */
kvm_mips_callbacks->flush_shadow_memslot(kvm, slot);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}

int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -258,14 +258,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
if (change == KVM_MR_FLAGS_ONLY &&
(!(old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
new->flags & KVM_MEM_LOG_DIRTY_PAGES)) {
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
/* Write protect GPA page table entries */
needs_flush = kvm_mips_mkclean_gpa_pt(kvm, new->base_gfn,
new->base_gfn + new->npages - 1);
/* Let implementation do the rest */
if (needs_flush)
kvm_mips_callbacks->flush_shadow_memslot(kvm, new);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}
}

@@ -593,7 +593,7 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
bool pfn_valid = false;
int ret = 0;

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);

/* Fast path - just check GPA page table for an existing entry */
ptep = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
@@ -628,7 +628,7 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
*out_buddy = *ptep_buddy(ptep);

out:
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
if (pfn_valid)
kvm_set_pfn_accessed(pfn);
return ret;
@@ -710,15 +710,15 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa,
goto out;
}

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
/* Check if an invalidation has taken place since we got pfn */
if (mmu_notifier_retry(kvm, mmu_seq)) {
/*
* This can happen when mappings are changed asynchronously, but
* also synchronously if a COW is triggered by
* gfn_to_pfn_prot().
*/
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
kvm_release_pfn_clean(pfn);
goto retry;
}
@@ -748,7 +748,7 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa,
if (out_buddy)
*out_buddy = *ptep_buddy(ptep);

spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
kvm_release_pfn_clean(pfn);
kvm_set_pfn_accessed(pfn);
out:
@@ -1041,12 +1041,12 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
/* And its GVA buddy's GPA page table entry if it also exists */
pte_gpa[!idx] = pfn_pte(0, __pgprot(0));
if (tlb_lo[!idx] & ENTRYLO_V) {
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
ptep_buddy = kvm_mips_pte_for_gpa(kvm, NULL,
mips3_tlbpfn_to_paddr(tlb_lo[!idx]));
if (ptep_buddy)
pte_gpa[!idx] = *ptep_buddy;
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}

/* Get the GVA page table entry pair */
@@ -148,7 +148,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,

cpte = kvmppc_mmu_hpte_cache_next(vcpu);

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
if (!cpte || mmu_notifier_retry(kvm, mmu_seq)) {
r = -EAGAIN;
goto out_unlock;
@@ -200,7 +200,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
}

out_unlock:
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
kvm_release_pfn_clean(pfn);
if (cpte)
kvmppc_mmu_hpte_cache_free(cpte);
@@ -605,12 +605,12 @@ int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu,
* Read the PTE from the process' radix tree and use that
* so we get the shift and attribute bits.
*/
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
ptep = find_kvm_host_pte(kvm, mmu_seq, hva, &shift);
pte = __pte(0);
if (ptep)
pte = READ_ONCE(*ptep);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
/*
* If the PTE disappeared temporarily due to a THP
* collapse, just return and let the guest try again.
@@ -739,14 +739,14 @@ void kvmppc_rmap_reset(struct kvm *kvm)
slots = kvm_memslots(kvm);
kvm_for_each_memslot(memslot, slots) {
/* Mutual exclusion with kvm_unmap_hva_range etc. */
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
/*
* This assumes it is acceptable to lose reference and
* change bits across a reset.
*/
memset(memslot->arch.rmap, 0,
memslot->npages * sizeof(*memslot->arch.rmap));
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}
srcu_read_unlock(&kvm->srcu, srcu_idx);
}
@@ -1405,14 +1405,14 @@ static void resize_hpt_pivot(struct kvm_resize_hpt *resize)

resize_hpt_debug(resize, "resize_hpt_pivot()\n");

spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
asm volatile("ptesync" : : : "memory");

hpt_tmp = kvm->arch.hpt;
kvmppc_set_hpt(kvm, &resize->hpt);
resize->hpt = hpt_tmp;

spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);

synchronize_srcu_expedited(&kvm->srcu);

@@ -613,7 +613,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
new_ptep = kvmppc_pte_alloc();

/* Check if we might have been invalidated; let the guest retry if so */
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
ret = -EAGAIN;
if (mmu_notifier_retry(kvm, mmu_seq))
goto out_unlock;
@@ -749,7 +749,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
ret = 0;

out_unlock:
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
if (new_pud)
pud_free(kvm->mm, new_pud);
if (new_pmd)
@@ -837,12 +837,12 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
* Read the PTE from the process' radix tree and use that
* so we get the shift and attribute bits.
*/
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
ptep = find_kvm_host_pte(kvm, mmu_seq, hva, &shift);
pte = __pte(0);
if (ptep)
pte = READ_ONCE(*ptep);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
/*
* If the PTE disappeared temporarily due to a THP
* collapse, just return and let the guest try again.
@@ -972,11 +972,11 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,

/* Failed to set the reference/change bits */
if (dsisr & DSISR_SET_RC) {
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
if (kvmppc_hv_handle_set_rc(kvm, false, writing,
gpa, kvm->arch.lpid))
dsisr &= ~DSISR_SET_RC;
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);

if (!(dsisr & (DSISR_BAD_FAULT_64S | DSISR_NOHPTE |
DSISR_PROTFAULT | DSISR_SET_RC)))
@@ -1082,7 +1082,7 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,

pte = READ_ONCE(*ptep);
if (pte_present(pte) && pte_dirty(pte)) {
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
/*
* Recheck the pte again
*/
@@ -1094,7 +1094,7 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,
* walk.
*/
if (!pte_present(*ptep) || !pte_dirty(*ptep)) {
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
return 0;
}
}
@@ -1109,7 +1109,7 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,
kvmhv_update_nest_rmap_rc_list(kvm, rmapp, _PAGE_DIRTY, 0,
old & PTE_RPN_MASK,
1UL << shift);
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}
return ret;
}
@@ -1154,7 +1154,7 @@ void kvmppc_radix_flush_memslot(struct kvm *kvm,
return;

gpa = memslot->base_gfn << PAGE_SHIFT;
spin_lock(&kvm->mmu_lock);
kvm_mmu_lock(kvm);
for (n = memslot->npages; n; --n) {
ptep = find_kvm_secondary_pte(kvm, gpa, &shift);
if (ptep && pte_present(*ptep))
@@ -1167,7 +1167,7 @@ void kvmppc_radix_flush_memslot(struct kvm *kvm,
* fault that read the memslot earlier from writing a PTE.
*/
kvm->mmu_notifier_seq++;
spin_unlock(&kvm->mmu_lock);
kvm_mmu_unlock(kvm);
}

static void add_rmmu_ap_encoding(struct kvm_ppc_rmmu_info *info,

0 comments on commit 07d5ac2

Please sign in to comment.