Skip to content

Commit ec4abf1

Browse files
kvaneeshmpe
authored andcommitted
powerpc/mm/hash64: use _PAGE_PTE when checking for pte_present
This makes the pte_present check stricter by checking for additional _PAGE_PTE bit. A level 1 pte pointer (THP pte) can be switched to a pointer to level 0 pte page table page by following two operations. 1) THP split. 2) madvise(MADV_DONTNEED) in parallel to page fault. A lockless page table walk need to make sure we can handle such changes gracefully. Signed-off-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c46241a commit ec4abf1

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

arch/powerpc/include/asm/book3s/64/pgtable.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,12 @@ static inline pte_t pte_clear_savedwrite(pte_t pte)
553553
}
554554
#endif /* CONFIG_NUMA_BALANCING */
555555

556+
static inline bool pte_hw_valid(pte_t pte)
557+
{
558+
return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE)) ==
559+
cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE);
560+
}
561+
556562
static inline int pte_present(pte_t pte)
557563
{
558564
/*
@@ -561,12 +567,11 @@ static inline int pte_present(pte_t pte)
561567
* invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID
562568
* if we find _PAGE_PRESENT cleared.
563569
*/
564-
return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
565-
}
566570

567-
static inline bool pte_hw_valid(pte_t pte)
568-
{
569-
return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT));
571+
if (pte_hw_valid(pte))
572+
return true;
573+
return (pte_raw(pte) & cpu_to_be64(_PAGE_INVALID | _PAGE_PTE)) ==
574+
cpu_to_be64(_PAGE_INVALID | _PAGE_PTE);
570575
}
571576

572577
#ifdef CONFIG_PPC_MEM_KEYS

arch/powerpc/mm/book3s64/hash_utils.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,8 +1350,15 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
13501350
goto bail;
13511351
}
13521352

1353-
/* Add _PAGE_PRESENT to the required access perm */
1354-
access |= _PAGE_PRESENT;
1353+
/*
1354+
* Add _PAGE_PRESENT to the required access perm. If there are parallel
1355+
* updates to the pte that can possibly clear _PAGE_PTE, catch that too.
1356+
*
1357+
* We can safely use the return pte address in rest of the function
1358+
* because we do set H_PAGE_BUSY which prevents further updates to pte
1359+
* from generic code.
1360+
*/
1361+
access |= _PAGE_PRESENT | _PAGE_PTE;
13551362

13561363
/*
13571364
* Pre-check access permissions (will be re-checked atomically

0 commit comments

Comments
 (0)