diff options
| author | Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> | 2018-08-22 13:16:04 -0400 |
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2018-08-22 22:16:01 -0400 |
| commit | bd0dbb73e01306a1060e56f81e5fe287be936477 (patch) | |
| tree | c9fca4a21b66504708a415be3f63b5a4d03573a6 | |
| parent | 810e9f86f36f59f1d6f6710220c49afe0c705f38 (diff) | |
powerpc/mm/books3s: Add new pte bit to mark pte temporarily invalid.
When splitting a huge pmd pte, we need to mark the pmd entry invalid. We
can do that by clearing _PAGE_PRESENT bit. But then that will be taken as a
swap pte. In order to differentiate between the two use a software pte bit
when invalidating.
For regular pte, due to bd5050e38aec ("powerpc/mm/radix: Change pte relax
sequence to handle nest MMU hang") we need to mark the pte entry invalid when
relaxing access permission. Instead of marking pte_none which can result in
different page table walk routines possibly skipping this pte entry, invalidate
it but still keep it marked present.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/pgtable.h | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 676118743a06..13a688fc8cd0 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h | |||
| @@ -44,6 +44,16 @@ | |||
| 44 | 44 | ||
| 45 | #define _PAGE_PTE 0x4000000000000000UL /* distinguishes PTEs from pointers */ | 45 | #define _PAGE_PTE 0x4000000000000000UL /* distinguishes PTEs from pointers */ |
| 46 | #define _PAGE_PRESENT 0x8000000000000000UL /* pte contains a translation */ | 46 | #define _PAGE_PRESENT 0x8000000000000000UL /* pte contains a translation */ |
| 47 | /* | ||
| 48 | * We need to mark a pmd pte invalid while splitting. We can do that by clearing | ||
| 49 | * the _PAGE_PRESENT bit. But then that will be taken as a swap pte. In order to | ||
| 50 | * differentiate between two use a SW field when invalidating. | ||
| 51 | * | ||
| 52 | * We do that temporary invalidate for regular pte entry in ptep_set_access_flags | ||
| 53 | * | ||
| 54 | * This is used only when _PAGE_PRESENT is cleared. | ||
| 55 | */ | ||
| 56 | #define _PAGE_INVALID _RPAGE_SW0 | ||
| 47 | 57 | ||
| 48 | /* | 58 | /* |
| 49 | * Top and bottom bits of RPN which can be used by hash | 59 | * Top and bottom bits of RPN which can be used by hash |
| @@ -568,7 +578,13 @@ static inline pte_t pte_clear_savedwrite(pte_t pte) | |||
| 568 | 578 | ||
| 569 | static inline int pte_present(pte_t pte) | 579 | static inline int pte_present(pte_t pte) |
| 570 | { | 580 | { |
| 571 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT)); | 581 | /* |
| 582 | * A pte is considerent present if _PAGE_PRESENT is set. | ||
| 583 | * We also need to consider the pte present which is marked | ||
| 584 | * invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID | ||
| 585 | * if we find _PAGE_PRESENT cleared. | ||
| 586 | */ | ||
| 587 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)); | ||
| 572 | } | 588 | } |
| 573 | 589 | ||
| 574 | #ifdef CONFIG_PPC_MEM_KEYS | 590 | #ifdef CONFIG_PPC_MEM_KEYS |
