Re: [PATCH v3 0/9] mm: distinguish HW PTE pointers from SW PTE value pointers
From: Alexander Gordeev <agordeev@linux.ibm.com>
Date: 2026-09-28 07:10:13
Also in:
bpf, damon, dri-devel, intel-gfx, linux-arch, linux-fsdevel, linux-mm, linux-perf-users, lkml, xen-devel
On Tue, Sep 22, 2026 at 06:12:28PM +0100, Muhammad Usama Anjum wrote:
Hi, pte_t currently describes both a software PTE value and an element stored in a PTE table. Consequently, pte_t * can point either to a software PTE 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 *. Software 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 unless an architecture selects ARCH_HAS_HW_PTE_T, which enables a distinct generic wrapper named __hw_pte_t. Some architectures define pgtable_t in headers parsed before the generic hw_pte_t typedef is visible. The structure tag allows those headers to define pgtable_t as struct __hw_pte_t * without creating an include-order dependency. This is required when converting s390, m68k, powerpc and sparc. No architecture selects ARCH_HAS_HW_PTE_T in this series, so the representation and behavior of every architecture are preserved. ptep_get() keeps its existing READ_ONCE() semantics and converts the stored element through __pte_from_hw(). An architecture can later select the option 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 software PTE 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]. I've the patches here [3] for arm64 conversion which I used to find usages in generic code which I missed during development. [1] https://lore.kernel.org/all/6110202c-057b-4701-8c04-1a76ee7bb9ab@arm.com/ (local) [2] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com (local) [3] https://lore.kernel.org/all/20260914-pte0_arm-v1-0-bb53b663e396@arm.com (local) Testing: Testing was performed with and without the series on both x86_64 and arm64. KUnit and the MM kselftests produced matching before-and-after results problems or regressions. Fastpath performance testing was also completed on arm64. No regression was found. Thanks, Usama
...
Muhammad Usama Anjum (9):
mm: introduce hw_pte_t for PTE table storage
mm: rename pointers to software PTE values as ptentp
mm: use hw_pte_t for generic PTE table storage
mm: convert PTE table entries in ptep_get()
mm: convert PTE table entry to pte
mm: add hw_pte_val for HW PTE storage
mm/kasan: use hw_pte_t for the early shadow PTE table
drm/i915: use hw_pte_t for PTE range callbacks
xen: use hw_pte_t for PTE range callbacks
MAINTAINERS | 1 +
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 4 +--
drivers/gpu/drm/i915/i915_mm.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 | 33 ++++++++++----------
include/asm-generic/hugetlb.h | 15 ++++-----
include/asm-generic/pgalloc.h | 6 ++--
include/asm-generic/tlb.h | 5 +--
include/linux/hugetlb.h | 53 +++++++++++++++++--------------
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 | 23 ++++++++++++++
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/Kconfig | 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 | 50 ++++++++++++++++++------------
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 | 4 +--
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 | 22 ++++++-------
mm/swap_state.c | 3 +-
mm/swapfile.c | 5 +--
mm/userfaultfd.c | 32 ++++++++++---------
mm/util.c | 2 +-
mm/vmalloc.c | 11 ++++---
mm/vmscan.c | 6 ++--
66 files changed, 457 insertions(+), 375 deletions(-)
---
base-commit: ead700ca770c82167af32622cf8b68c9f87c3c7c
change-id: 20260914-pte0-6c88f5592d79I backported this series to the Linus master and tested on s390 with the lazy mmu series applied on top. In case it still counts: Tested-by: Alexander Gordeev <agordeev@linux.ibm.com>
Best regards, -- Usama
Thanks!