Thread (20 messages) 20 messages, 3 authors, 7h ago

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-6c88f5592d79
I 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!
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help