Commit 08d5b29e authored by Pasha Tatashin's avatar Pasha Tatashin Committed by Linus Torvalds

mm: ptep_clear() page table helper

We have ptep_get_and_clear() and ptep_get_and_clear_full() helpers to
clear PTE from user page tables, but there is no variant for simple
clear of a present PTE from user page tables without using a low level
pte_clear() which can be either native or para-virtualised.

Add a new ptep_clear() that can be used in common code to clear PTEs
from page table.  We will need this call later in order to add a hook
for page table check.

Link: https://lkml.kernel.org/r/20211221154650.1047963-3-pasha.tatashin@soleen.comSigned-off-by: default avatarPasha Tatashin <pasha.tatashin@soleen.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: Greg Thelen <gthelen@google.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Slaby <jirislaby@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Kees Cook <keescook@chromium.org>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Muchun Song <songmuchun@bytedance.com>
Cc: Paul Turner <pjt@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sami Tolvanen <samitolvanen@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Wei Xu <weixugc@google.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1eba86c0
...@@ -66,9 +66,11 @@ PTE Page Table Helpers ...@@ -66,9 +66,11 @@ PTE Page Table Helpers
+---------------------------+--------------------------------------------------+ +---------------------------+--------------------------------------------------+
| pte_mknotpresent | Invalidates a mapped PTE | | pte_mknotpresent | Invalidates a mapped PTE |
+---------------------------+--------------------------------------------------+ +---------------------------+--------------------------------------------------+
| ptep_get_and_clear | Clears a PTE | | ptep_clear | Clears a PTE |
+---------------------------+--------------------------------------------------+ +---------------------------+--------------------------------------------------+
| ptep_get_and_clear_full | Clears a PTE | | ptep_get_and_clear | Clears and returns PTE |
+---------------------------+--------------------------------------------------+
| ptep_get_and_clear_full | Clears and returns PTE (batched PTE unmap) |
+---------------------------+--------------------------------------------------+ +---------------------------+--------------------------------------------------+
| ptep_test_and_clear_young | Clears young from a PTE | | ptep_test_and_clear_young | Clears young from a PTE |
+---------------------------+--------------------------------------------------+ +---------------------------+--------------------------------------------------+
......
...@@ -258,6 +258,14 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma, ...@@ -258,6 +258,14 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma,
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#endif #endif
#ifndef __HAVE_ARCH_PTEP_CLEAR
static inline void ptep_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
pte_clear(mm, addr, ptep);
}
#endif
#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, unsigned long address,
......
...@@ -652,7 +652,7 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args) ...@@ -652,7 +652,7 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
set_pte_at(args->mm, args->vaddr, args->ptep, pte); set_pte_at(args->mm, args->vaddr, args->ptep, pte);
flush_dcache_page(page); flush_dcache_page(page);
barrier(); barrier();
pte_clear(args->mm, args->vaddr, args->ptep); ptep_clear(args->mm, args->vaddr, args->ptep);
pte = ptep_get(args->ptep); pte = ptep_get(args->ptep);
WARN_ON(!pte_none(pte)); WARN_ON(!pte_none(pte));
} }
......
...@@ -756,11 +756,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, ...@@ -756,11 +756,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
* ptl mostly unnecessary. * ptl mostly unnecessary.
*/ */
spin_lock(ptl); spin_lock(ptl);
/* ptep_clear(vma->vm_mm, address, _pte);
* paravirt calls inside pte_clear here are
* superfluous.
*/
pte_clear(vma->vm_mm, address, _pte);
spin_unlock(ptl); spin_unlock(ptl);
} }
} else { } else {
...@@ -774,11 +770,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, ...@@ -774,11 +770,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
* inside page_remove_rmap(). * inside page_remove_rmap().
*/ */
spin_lock(ptl); spin_lock(ptl);
/* ptep_clear(vma->vm_mm, address, _pte);
* paravirt calls inside pte_clear here are
* superfluous.
*/
pte_clear(vma->vm_mm, address, _pte);
page_remove_rmap(src_page, false); page_remove_rmap(src_page, false);
spin_unlock(ptl); spin_unlock(ptl);
free_page_and_swap_cache(src_page); free_page_and_swap_cache(src_page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment