diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2019-06-07 13:56:35 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2019-06-07 16:26:44 +1000 |
commit | 33258a1db165cf43a9e6382587ad06e9b7f8187c (patch) | |
tree | 8a9ae7c9d3e450dea6edb557c3043d421214df7b /arch/powerpc/mm/book3s64/pgtable.c | |
parent | 6c284228eb356a1ec62a704b4d2329711831eaed (diff) | |
download | linux-stable-33258a1db165cf43a9e6382587ad06e9b7f8187c.tar.gz linux-stable-33258a1db165cf43a9e6382587ad06e9b7f8187c.tar.bz2 linux-stable-33258a1db165cf43a9e6382587ad06e9b7f8187c.zip |
powerpc/64s: Fix THP PMD collapse serialisation
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian
conversion in pte helpers") changed the actual bitwise tests in
pte_access_permitted by using pte_write() and pte_present() helpers
rather than raw bitwise testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present() change now returns true for PTEs which are
!_PAGE_PRESENT and _PAGE_INVALID, which is the combination used by
pmdp_invalidate() to synchronize access from lock-free lookups.
pte_access_permitted() is used by pmd_access_permitted(), so allowing
GUP lock free access to proceed with such PTEs breaks this
synchronisation.
This bug has been observed on a host using the hash page table MMU,
with random crashes and corruption in guests, usually together with
bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted(), and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from
falling back to the slow path when encountering savedwrite PTEs, which
matches what x86 (that does not implement savedwrite) does.
Fixes: 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion in pte helpers")
Cc: stable@vger.kernel.org # v4.20+
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm/book3s64/pgtable.c')
-rw-r--r-- | arch/powerpc/mm/book3s64/pgtable.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c index 16bda049187a..ff98b663c83e 100644 --- a/arch/powerpc/mm/book3s64/pgtable.c +++ b/arch/powerpc/mm/book3s64/pgtable.c @@ -116,6 +116,9 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, /* * This ensures that generic code that rely on IRQ disabling * to prevent a parallel THP split work as expected. + * + * Marking the entry with _PAGE_INVALID && ~_PAGE_PRESENT requires + * a special case check in pmd_access_permitted. */ serialize_against_pte_lookup(vma->vm_mm); return __pmd(old_pmd); |