Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5fad1e9 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Paul Mackerras
Browse files

KVM: PPC: Book3S HV: Use a helper to unmap ptes in the radix fault path

parent b7557451
Loading
Loading
Loading
Loading
+23 −23
Original line number Diff line number Diff line
@@ -228,6 +228,25 @@ static void kvmppc_pmd_free(pmd_t *pmdp)
	kmem_cache_free(kvm_pmd_cache, pmdp);
}

static void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte,
			     unsigned long gpa, unsigned int shift)

{
	unsigned long page_size = 1ul << shift;
	unsigned long old;

	old = kvmppc_radix_update_pte(kvm, pte, ~0UL, 0, gpa, shift);
	kvmppc_radix_tlbie_page(kvm, gpa, shift);
	if (old & _PAGE_DIRTY) {
		unsigned long gfn = gpa >> PAGE_SHIFT;
		struct kvm_memory_slot *memslot;

		memslot = gfn_to_memslot(kvm, gfn);
		if (memslot && memslot->dirty_bitmap)
			kvmppc_update_dirty_map(memslot, gfn, page_size);
	}
}

static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
			     unsigned int level, unsigned long mmu_seq)
{
@@ -235,7 +254,6 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
	pud_t *pud, *new_pud = NULL;
	pmd_t *pmd, *new_pmd = NULL;
	pte_t *ptep, *new_ptep = NULL;
	unsigned long old;
	int ret;

	/* Traverse the guest's 2nd-level tree, allocate new levels needed */
@@ -287,17 +305,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
			goto out_unlock;
		}
		/* Valid 1GB page here already, remove it */
		old = kvmppc_radix_update_pte(kvm, (pte_t *)pud,
					      ~0UL, 0, hgpa, PUD_SHIFT);
		kvmppc_radix_tlbie_page(kvm, hgpa, PUD_SHIFT);
		if (old & _PAGE_DIRTY) {
			unsigned long gfn = hgpa >> PAGE_SHIFT;
			struct kvm_memory_slot *memslot;
			memslot = gfn_to_memslot(kvm, gfn);
			if (memslot && memslot->dirty_bitmap)
				kvmppc_update_dirty_map(memslot,
							gfn, PUD_SIZE);
		}
		kvmppc_unmap_pte(kvm, (pte_t *)pud, hgpa, PUD_SHIFT);
	}
	if (level == 2) {
		if (!pud_none(*pud)) {
@@ -338,17 +346,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
			goto out_unlock;
		}
		/* Valid 2MB page here already, remove it */
		old = kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd),
					      ~0UL, 0, lgpa, PMD_SHIFT);
		kvmppc_radix_tlbie_page(kvm, lgpa, PMD_SHIFT);
		if (old & _PAGE_DIRTY) {
			unsigned long gfn = lgpa >> PAGE_SHIFT;
			struct kvm_memory_slot *memslot;
			memslot = gfn_to_memslot(kvm, gfn);
			if (memslot && memslot->dirty_bitmap)
				kvmppc_update_dirty_map(memslot,
							gfn, PMD_SIZE);
		}
		kvmppc_unmap_pte(kvm, pmdp_ptep(pmd), lgpa, PMD_SHIFT);
	}
	if (level == 1) {
		if (!pmd_none(*pmd)) {
@@ -373,6 +371,8 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
	}
	ptep = pte_offset_kernel(pmd, gpa);
	if (pte_present(*ptep)) {
		unsigned long old;

		/* Check if someone else set the same thing */
		if (pte_raw(*ptep) == pte_raw(pte)) {
			ret = 0;