[PATCH v2 0/8] mm: distinguish PTE table storage from PTE values

Muhammad Usama Anjum posted 8 patches 3 weeks ago
There is a newer version of this series
MAINTAINERS                                   |  1 +
.../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                 | 19 +++++
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, 453 insertions(+), 375 deletions(-)
create mode 100644 include/linux/pgtable_types.h
[PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Muhammad Usama Anjum 3 weeks ago
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. These would be
sent separately.

[1] https://lore.kernel.org/all/6110202c-057b-4701-8c04-1a76ee7bb9ab@arm.com/
[2] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
[3] https://gitlab.arm.com/linux-arm/linux-us/-/commits/pte0_arm

Thanks,
Usama
---
Changes since v1:
- Name the generic wrapper structure __hw_pte_t so architectures can
  forward-declare it before the generic typedef is visible.
- Use software PTE value terminology consistently
- Fold the prerequisite header includes into the generic storage
  conversion
- Explain why the NOMMU stub converts the stored entry without
  ptep_get().
- Rebase onto mm-new and rerun the Coccinelle conversion.

Changes since RFC v1:
- Add ARCH_HAS_HW_PTE_T so architectures can opt in to a distinct
  PTE-table storage type.
- Define the distinct hw_pte_t wrapper and its conversion helpers in
  generic code instead of requiring each architecture to define them.
- Read hw_pte_t through READ_ONCE() before converting it to pte_t.
- Drop the previous mremap patch in favour of [a]. Apply [a] first if
  it is not already present.
- Drop the previous two dead-code conversion patches; the affected
  code was cleaned up separately in [b] and [c].

[a] https://lore.kernel.org/linux-mm/20260720141633.501799-1-agordeev@linux.ibm.com/
[b] https://lore.kernel.org/all/20260730111316.3672672-1-usama.anjum@arm.com
[c] https://lore.kernel.org/all/20260730094501.3002718-1-usama.anjum@arm.com

---
// 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 software 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 (8):
  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/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 +
 .../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                 | 19 +++++
 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, 453 insertions(+), 375 deletions(-)
 create mode 100644 include/linux/pgtable_types.h

-- 
2.47.3
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Alexander Gordeev 1 day, 6 hours ago
On Thu, Sep 03, 2026 at 11:29:52AM +0100, Muhammad Usama Anjum wrote:

Hi Muhammad,

> I've the patches here [3] for arm64 conversion which I used to find
> usages in generic code which I missed during development. These would be
> sent separately.
> 
> [1] https://lore.kernel.org/all/6110202c-057b-4701-8c04-1a76ee7bb9ab@arm.com/
> [2] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
> [3] https://gitlab.arm.com/linux-arm/linux-us/-/commits/pte0_arm

I checked [3] with s390 and also against our lazy mmu implementation and it
looks okay.

However, is there a particular reason this series is against mm-new?
Should it be against the master, it would be easier for me to try it in our CI.

> Thanks,
> Usama

Thanks!
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Muhammad Usama Anjum 1 day, 5 hours ago
On 23/09/2026 1:25 pm, Alexander Gordeev wrote:
> On Thu, Sep 03, 2026 at 11:29:52AM +0100, Muhammad Usama Anjum wrote:
> 
> Hi Muhammad,
> 
>> I've the patches here [3] for arm64 conversion which I used to find
>> usages in generic code which I missed during development. These would be
>> sent separately.
>>
>> [1] https://lore.kernel.org/all/6110202c-057b-4701-8c04-1a76ee7bb9ab@arm.com/
>> [2] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
>> [3] https://gitlab.arm.com/linux-arm/linux-us/-/commits/pte0_arm
> 
> I checked [3] with s390 and also against our lazy mmu implementation and it
> looks okay.
> 
> However, is there a particular reason this series is against mm-new?
> Should it be against the master, it would be easier for me to try it in our CI.

I think, mm-new is the branch in which this series would be picked up. This is
why its based on that. Are you referring to mm/master?

-- 
Thanks,
Usama
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Alexander Gordeev 1 day, 4 hours ago
On Wed, Sep 23, 2026 at 02:47:08PM +0100, Muhammad Usama Anjum wrote:
> > However, is there a particular reason this series is against mm-new?
> > Should it be against the master, it would be easier for me to try it in our CI.
> 
> I think, mm-new is the branch in which this series would be picked up. This is
> why its based on that. Are you referring to mm/master?

No, to the Linus master.
I will try to backport it and give it a try.

> -- 
> Thanks,
> Usama

Thanks!
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by David Hildenbrand (Arm) 1 week, 6 days ago
On 9/3/26 12:29, Muhammad Usama Anjum wrote:
> Hi,

Btw, I was wonder whether the subject would be better as

"mm: distinguish HW PTE pointers from SW PTE value pointers"

or sth. like that.

-- 
Cheers,

David
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Muhammad Usama Anjum 1 week, 3 days ago
On 11/09/2026 5:59 pm, David Hildenbrand (Arm) wrote:
> On 9/3/26 12:29, Muhammad Usama Anjum wrote:
>> Hi,
> 
> Btw, I was wonder whether the subject would be better as
> 
> "mm: distinguish HW PTE pointers from SW PTE value pointers"
> 
> or sth. like that.
> 

Seems good. I'll update.

-- 
Thanks,
Usama
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by David Hildenbrand (Arm) 1 week, 6 days ago
On 9/3/26 12:29, 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. These would be
> sent separately.

Unless there is more feedback on the overall approach, the next step for this is
to have at least one architecture support posted.

We should only merge this if at least one architecture (better two? :) arm64 and
s390x? ) would merge the architecture bits.

That is, we should get an ACK from the arch maintainer son the common code bits
and the arch bits.

-- 
Cheers,

David
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Alexander Gordeev 6 days, 6 hours ago
On Fri, Sep 11, 2026 at 06:55:18PM +0200, David Hildenbrand (Arm) wrote:

Hi David, Muhammad,

Sorry for the long delay.

> Unless there is more feedback on the overall approach, the next step for this is
> to have at least one architecture support posted.
> 
> We should only merge this if at least one architecture (better two? :) arm64 and
> s390x? ) would merge the architecture bits.

I am going to give it a try, hopefully next week.

> That is, we should get an ACK from the arch maintainer son the common code bits
> and the arch bits.
> 
> -- 
> Cheers,

Thanks!

> David
Re: [PATCH v2 0/8] mm: distinguish PTE table storage from PTE values
Posted by Muhammad Usama Anjum 1 week, 3 days ago
On 11/09/2026 5:55 pm, David Hildenbrand (Arm) wrote:
> On 9/3/26 12:29, 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. These would be
>> sent separately.
> 
> Unless there is more feedback on the overall approach, the next step for this is
> to have at least one architecture support posted.
> 
> We should only merge this if at least one architecture (better two? :) arm64 and
> s390x? ) would merge the architecture bits.
> 
> That is, we should get an ACK from the arch maintainer son the common code bits
> and the arch bits.
> 

Thank you for reviewing the series. I've posted the patches for arm64 just
now [1]. Let's wait for arm64 maintainers to ACK the patches.

[1] https://lore.kernel.org/all/20260914-pte0_arm-v1-0-bb53b663e396@arm.com 

-- 
Thanks,
Usama