KVM: PPC: Book3S HV: Use a helper to unmap ptes in the radix fault path
Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
b755745147
commit
a5fad1e959
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user