On Thu, Jan 09, 2025, Paolo Bonzini wrote: > @@ -483,7 +383,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, > * can't run hence pfn won't change. > */ > local_irq_save(flags); > - ptep = find_linux_pte(pgdir, hva, NULL, NULL); > + ptep = find_linux_pte(pgdir, hva, NULL, &psize); > if (ptep) { > pte_t pte = READ_ONCE(*ptep); LOL, this code is such a mess. If no ptep is found, IRQs are left disabled. The bug has existed since commit 691e95fd7396 ("powerpc/mm/thp: Make page table walk safe against thp split/collapse"), i.e. we didn't accidentally delete a local_irq_restore() at some point. @@ -468,14 +469,23 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, pgdir = vcpu_e500->vcpu.arch.pgdir; + /* + * We are just looking at the wimg bits, so we don't + * care much about the trans splitting bit. + * We are holding kvm->mmu_lock so a notifier invalidate + * can't run hence pfn won't change. + */ + local_irq_save(flags); ptep = find_linux_pte_or_hugepte(pgdir, hva, NULL); if (ptep) { pte_t pte = READ_ONCE(*ptep); - if (pte_present(pte)) + if (pte_present(pte)) { wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK; - else { + local_irq_restore(flags); + } else { + local_irq_restore(flags); pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n", __func__, (long)gfn, pfn); ret = -EINVAL;