Hi, pte_t currently describes both a logical PTE value and an element stored in a PTE table. Consequently, pte_t * can point either to a standalone value, often a stack copy, or to a PTE-table slot. The compiler cannot distinguish these cases. A value pointer can therefore be passed to an interface that expects table storage, while table storage can be read by direct dereference instead of the architecture accessor.
This series begins a staged conversion at the PTE level. It introduces hw_pte_t as the element type for PTE-table storage and converts generic MM to use hw_pte_t *. Logical PTE values remain pte_t. Interfaces that intentionally return a value through pte_t *, such as install_pte, remain value interfaces; the relevant parameters are named ptentp to make that distinction explicit. The generic definition aliases hw_pte_t to pte_t, so this series preserves the representation and behaviour of every architecture. ptep_get() keeps its existing READ_ONCE() semantics and converts the stored element through __pte_from_hw(). An architecture can later define a distinct hw_pte_t and convert its PTE interfaces to make the distinction compiler-enforced. Architecture PTE implementations and most architecture code are deliberately left for those later opt-in conversions. Here, hw_pte_t identifies PTE-table storage rather than table lifetime: complete PTE tables use hw_pte_t whether or not they are currently linked into a page-table hierarchy, while standalone copied values use pte_t. The distinction between complete but unlinked tables and hardware-reachable tables was raised during discussion and remains an important point for review. PMD, PUD, P4D and PGD storage are deliberately out of scope. They can be converted in later series after the PTE boundary is agreed, avoiding the PMD-specific cases that made an all-level conversion difficult to review. Most mechanical pointer conversions were generated with the Coccinelle script included below, then audited and fixed by hand. This series does not add a second ptep_get_once() accessor and does not remove or replace STRICT_MM_TYPECHECKS. The design discussion is available at [1]; while the original idea came from [2]. [1] https://lore.kernel.org/all/[email protected]/ [2] https://lore.kernel.org/all/[email protected] Thanks, Usama --- // SPDX-License-Identifier: GPL-2.0-only /// /// Rename raw PTE pointer types to hardware PTE pointer types. /// /// This is a mechanical type rename. It converts common declarations, /// function parameters, prototypes, return types and casts from "pte_t *" /// to "hw_pte_t *". Plain "pte_t" objects are intentionally left unchanged. /// Pointers named "ptentp" refer to temporary logical PTE values and are /// intentionally ignored in all modes. /// Re-run in context mode afterwards to audit remaining raw pte_t pointers /// and cases that need hand conversion, such as trace macros and mixed /// declarations. /// /// Confidence: Moderate // Options: --no-includes --include-headers virtual patch virtual report virtual context @local_decl depends on patch@ identifier x != ptentp; @@ - pte_t *x; + hw_pte_t *x; @local_decl_init depends on patch@ identifier x != ptentp; expression e; @@ - pte_t *x = e; + hw_pte_t *x = e; @param_proto depends on patch@ identifier f; identifier x != ptentp; type R; @@ R f(..., - pte_t *x + hw_pte_t *x ,...); @param_proto_unnamed depends on patch@ identifier f; type R; @@ R f(..., - pte_t * + hw_pte_t * ,...); @param_def depends on patch@ identifier f; identifier x != ptentp; type R; @@ R f(..., - pte_t *x + hw_pte_t *x ,...) { ... } @ret_proto depends on patch@ identifier f; parameter list ps; @@ - pte_t * + hw_pte_t * f(ps); @ret_def depends on patch@ identifier f; parameter list ps; @@ - pte_t * + hw_pte_t * f(ps) { ... } @struct_member depends on patch@ identifier S; identifier x != ptentp; @@ struct S { ... - pte_t *x; + hw_pte_t *x; ... }; @union_member depends on patch@ identifier x != ptentp; @@ union { ... - pte_t *x; + hw_pte_t *x; ... }; @union_member_in_struct depends on patch@ identifier S; identifier x != ptentp; @@ struct S { ... union { ... - pte_t *x; + hw_pte_t *x; ... }; ... }; @fnptr_struct_member depends on patch@ identifier S,f; identifier x != ptentp; type R; @@ struct S { ... R (*f)(..., - pte_t *x + hw_pte_t *x ,...); ... }; @fnptr_typedef_pte_fn_t depends on patch@ identifier x != ptentp; @@ typedef int (*pte_fn_t)(..., - pte_t *x + hw_pte_t *x ,...); @cast depends on patch@ expression e; @@ - (pte_t *)e + (hw_pte_t *)e @remaining_decl depends on context || report@ identifier x != ptentp; position p; @@ * pte_t *x@p; @remaining_decl_init depends on context || report@ identifier x != ptentp; expression e; position p; @@ * pte_t *x@p = e; @remaining_param_proto depends on context || report@ identifier f; identifier x != ptentp; type R; position p; @@ R f(..., * pte_t *x@p ,...); @remaining_param_proto_unnamed depends on context || report@ identifier f; type R; position p; @@ R f(..., * pte_t *@p ,...); @remaining_param_def depends on context || report@ identifier f; identifier x != ptentp; type R; position p; @@ R f(..., * pte_t *x@p ,...) { ... } @remaining_ret_proto depends on context || report@ identifier f; parameter list ps; position p; @@ * pte_t *f@p(ps); @remaining_ret_def depends on context || report@ identifier f; parameter list ps; position p; @@ * pte_t *f@p(ps) { ... } @remaining_struct_member depends on context || report@ identifier S; identifier x != ptentp; position p; @@ struct S { ... * pte_t *x@p; ... }; @remaining_union_member depends on context || report@ identifier x != ptentp; position p; @@ union { ... * pte_t *x@p; ... }; @remaining_union_member_in_struct depends on context || report@ identifier S; identifier x != ptentp; position p; @@ struct S { ... union { ... * pte_t *x@p; ... }; ... }; @remaining_fnptr_struct_member depends on context || report@ identifier S,f; identifier x != ptentp; type R; position p; @@ struct S { ... R (*f)(..., * pte_t *x@p ,...); ... }; @remaining_fnptr_typedef_pte_fn_t depends on context || report@ identifier x != ptentp; position p; @@ typedef int (*pte_fn_t)(..., * pte_t *x@p ,...); Muhammad Usama Anjum (11): mm: introduce hw_pte_t for PTE table storage mm: make hw_pte_t visible to generic PTE interfaces mm: name pointers to copied PTE values ptentp mm: use hw_pte_t for generic PTE table storage mm: convert PTE table entries in ptep_get() mm/kasan: use hw_pte_t for the early shadow PTE table mm/mremap: use ptep_get() for the destination PTE drm/i915: use hw_pte_t for PTE range callbacks misc/sgi-gru: use ptep_get() for page-table reads parisc: use hw_pte_t for the data-break callback xen: use hw_pte_t for PTE range callbacks MAINTAINERS | 1 + .../drm/i915/gem/selftests/i915_gem_mman.c | 4 +- drivers/gpu/drm/i915/i915_mm.c | 4 +- drivers/misc/sgi-gru/grufault.c | 4 +- drivers/parisc/sba_iommu.c | 4 +- drivers/xen/gntdev.c | 2 +- drivers/xen/privcmd.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 2 +- drivers/xen/xlate_mmu.c | 4 +- fs/hugetlbfs/inode.c | 3 +- fs/proc/task_mmu.c | 39 ++++----- include/asm-generic/hugetlb.h | 15 ++-- include/asm-generic/pgalloc.h | 6 +- include/asm-generic/tlb.h | 6 +- include/linux/hugetlb.h | 50 +++++++----- include/linux/kasan.h | 2 +- include/linux/mm.h | 26 +++--- include/linux/page_table_check.h | 10 ++- include/linux/pagewalk.h | 10 +-- include/linux/pgtable.h | 81 ++++++++++--------- include/linux/pgtable_types.h | 12 +++ include/linux/rmap.h | 2 +- include/linux/swapops.h | 6 +- include/linux/vmalloc.h | 4 +- include/trace/events/xen.h | 10 +-- kernel/bpf/arena.c | 9 ++- kernel/events/core.c | 3 +- mm/damon/ops-common.c | 2 +- mm/damon/ops-common.h | 2 +- mm/damon/vaddr.c | 20 ++--- mm/debug_vm_pgtable.c | 2 +- mm/filemap.c | 4 +- mm/gup.c | 9 ++- mm/highmem.c | 15 ++-- mm/hmm.c | 6 +- mm/huge_memory.c | 4 +- mm/hugetlb.c | 60 +++++++------- mm/hugetlb_vmemmap.c | 13 +-- mm/internal.h | 16 ++-- mm/kasan/init.c | 14 ++-- mm/kasan/shadow.c | 6 +- mm/khugepaged.c | 23 +++--- mm/ksm.c | 11 +-- mm/madvise.c | 18 +++-- mm/mapping_dirty_helpers.c | 4 +- mm/memory-failure.c | 6 +- mm/memory.c | 78 +++++++++--------- mm/mempolicy.c | 4 +- mm/migrate.c | 4 +- mm/migrate_device.c | 4 +- mm/mincore.c | 4 +- mm/mlock.c | 4 +- mm/mprotect.c | 19 ++--- mm/mremap.c | 6 +- mm/page_table_check.c | 4 +- mm/pagewalk.c | 9 ++- mm/percpu.c | 2 +- mm/pgtable-generic.c | 20 ++--- mm/ptdump.c | 4 +- mm/rmap.c | 6 +- mm/sparse-vmemmap.c | 24 +++--- mm/swap_state.c | 3 +- mm/swapfile.c | 5 +- mm/userfaultfd.c | 32 ++++---- mm/util.c | 2 +- mm/vmalloc.c | 13 +-- mm/vmscan.c | 6 +- 67 files changed, 435 insertions(+), 374 deletions(-) create mode 100644 include/linux/pgtable_types.h -- 2.47.3
