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
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/6110202c-057b-4701-8c04-1a76ee7bb9ab@arm.com/
[2] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
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
On 7/27/26 18:46, Muhammad Usama Anjum wrote: > 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. Do you have a pointer at the arm64 part, so people can get a feeling for how an actual hw_pte_t implementation can look like. -- Cheers, David
On 28/07/2026 8:26 pm, David Hildenbrand (Arm) wrote: > On 7/27/26 18:46, Muhammad Usama Anjum wrote: >> 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. > > Do you have a pointer at the arm64 part, so people can get a feeling for how an > actual hw_pte_t implementation can look like. I've the patches here [1] for arm64 conversion which I used to find usages in generic code which I missed during development. [1] https://github.com/musamaanjum/linux/commits/pte0_arm/ I could have posted these patches alongside the generic conversion. But I thought it would be best to convert generic side first. Please feel free to let me know if next series should have arm64 side conversion as well. -- Thanks, Usama
On Tue, Jul 28, 2026 at 09:26:06PM +0200, David Hildenbrand (Arm) wrote:
> > 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.
...
> Do you have a pointer at the arm64 part, so people can get a feeling for how an
> actual hw_pte_t implementation can look like.
May be we need the generic hw_pte_t implementation as { pte_t pte; }
right away?
Also, can you envision a case when sizeof(pte_t) != sizeof(hw_pte_t)?
If not, the compile-time check is worth adding.
> --
> Cheers,
>
> David
Thanks!
On 7/29/26 12:13, Alexander Gordeev wrote:
> On Tue, Jul 28, 2026 at 09:26:06PM +0200, David Hildenbrand (Arm) wrote:
>>> 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.
> ...
>> Do you have a pointer at the arm64 part, so people can get a feeling for how an
>> actual hw_pte_t implementation can look like.
>
> May be we need the generic hw_pte_t implementation as { pte_t pte; }
> right away?
Indeed, that makes sense. We just need a way for the architecture to opt-in that
it did the conversion.
>
> Also, can you envision a case when sizeof(pte_t) != sizeof(hw_pte_t)?
> If not, the compile-time check is worth adding.
That wouldn't work as is. We'd have to intercept ptep++ and instead have a
helper to advance the ptep pointer.
One idea for that would be to let the compiler catch that by marking hw_pte_t an
undefined struct (unknown size), such that the compiler would indicate any usage
of ptep++ properly.
That can be done when it would actually required, so as a first step having a
generic hw_pte_t would just work.
--
Cheers,
David
On Wed, Jul 29, 2026 at 01:05:35PM +0200, David Hildenbrand (Arm) wrote:
> On 7/29/26 12:13, Alexander Gordeev wrote:
> > On Tue, Jul 28, 2026 at 09:26:06PM +0200, David Hildenbrand (Arm) wrote:
> >>> 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.
> > ...
> >> Do you have a pointer at the arm64 part, so people can get a feeling for how an
> >> actual hw_pte_t implementation can look like.
> >
> > May be we need the generic hw_pte_t implementation as { pte_t pte; }
> > right away?
>
> Indeed, that makes sense. We just need a way for the architecture to opt-in that
> it did the conversion.
>
> >
> > Also, can you envision a case when sizeof(pte_t) != sizeof(hw_pte_t)?
> > If not, the compile-time check is worth adding.
>
> That wouldn't work as is. We'd have to intercept ptep++ and instead have a
> helper to advance the ptep pointer.
I think I am missing the point. That is my takeaway from your previous mail:
https://lore.kernel.org/lkml/31d36023-d728-4eee-90f8-158c7066f565@kernel.org/
<quote>
> {
> page_table_check_ptes_set(mm, addr, ptep, pte, nr);
> for (;;) {
> set_pte(ptep, pte);
> if (--nr == 0)
> break;
> - ptep++;
> + ptep = hw_pte_next(ptep);
We should really just let ptep++ work as before.
> pte = pte_next_pfn(pte);
> }
> }
</quote>
So are we going after hw_pte_next(ptep) or ptep++?
> One idea for that would be to let the compiler catch that by marking hw_pte_t an
> undefined struct (unknown size), such that the compiler would indicate any usage
> of ptep++ properly.
What is the purpose of that? I mean when pte_t vs hw_pte_t uses are sorted
out what is the benefit of preventing hw_ptep++?
> That can be done when it would actually required, so as a first step having a
> generic hw_pte_t would just work.
>
> --
> Cheers,
>
> David
Thanks!
On 7/29/26 13:44, Alexander Gordeev wrote:
> On Wed, Jul 29, 2026 at 01:05:35PM +0200, David Hildenbrand (Arm) wrote:
>> On 7/29/26 12:13, Alexander Gordeev wrote:
>>> ...
>>>
>>> May be we need the generic hw_pte_t implementation as { pte_t pte; }
>>> right away?
>>
>> Indeed, that makes sense. We just need a way for the architecture to opt-in that
>> it did the conversion.
>>
>>>
>>> Also, can you envision a case when sizeof(pte_t) != sizeof(hw_pte_t)?
>>> If not, the compile-time check is worth adding.
>>
>> That wouldn't work as is. We'd have to intercept ptep++ and instead have a
>> helper to advance the ptep pointer.
>
> I think I am missing the point. That is my takeaway from your previous mail:
> https://lore.kernel.org/lkml/31d36023-d728-4eee-90f8-158c7066f565@kernel.org/
>
> <quote>
>> {
>> page_table_check_ptes_set(mm, addr, ptep, pte, nr);
>> for (;;) {
>> set_pte(ptep, pte);
>> if (--nr == 0)
>> break;
>> - ptep++;
>> + ptep = hw_pte_next(ptep);
>
> We should really just let ptep++ work as before.
>
>> pte = pte_next_pfn(pte);
>> }
>> }
> </quote>
>
> So are we going after hw_pte_next(ptep) or ptep++?
As I said "That wouldn't work as is. We'd have ".
So in this series here we are clearly going for ptep++ and sizeof(pte_t) ==
sizeof(hw_pte_t).
Because otherwise it wouldn't work.
>
>> One idea for that would be to let the compiler catch that by marking hw_pte_t an
>> undefined struct (unknown size), such that the compiler would indicate any usage
>> of ptep++ properly.
>
> What is the purpose of that? I mean when pte_t vs hw_pte_t uses are sorted
> out what is the benefit of preventing hw_ptep++?
One thing I could pull out of my magic hat is that you might be able to decide
at runtime the size of your underlying page table entries.
E.g., have 128bit pteval, but allow running on HW with either 64bit ptes or
128bit ptes.
I'm sure there are more challenges to that, but that's an easy thing to imagine.
But again, the focus of this patch set here is ptep++ to just keep working.
--
Cheers,
David
On 29/07/2026 12:05 pm, David Hildenbrand (Arm) wrote:
> On 7/29/26 12:13, Alexander Gordeev wrote:
>> On Tue, Jul 28, 2026 at 09:26:06PM +0200, David Hildenbrand (Arm) wrote:
>>>> 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.
>> ...
>>> Do you have a pointer at the arm64 part, so people can get a feeling for how an
>>> actual hw_pte_t implementation can look like.
>>
>> May be we need the generic hw_pte_t implementation as { pte_t pte; }
>> right away?
>
> Indeed, that makes sense. We just need a way for the architecture to opt-in that
> it did the conversion.
Yeah and architecture cannot opt-in until its converted. So we should leave
it to architecture to define hw_pte_t.
>
>>
>> Also, can you envision a case when sizeof(pte_t) != sizeof(hw_pte_t)?
>> If not, the compile-time check is worth adding.
>
> That wouldn't work as is. We'd have to intercept ptep++ and instead have a
> helper to advance the ptep pointer.
>
> One idea for that would be to let the compiler catch that by marking hw_pte_t an
> undefined struct (unknown size), such that the compiler would indicate any usage
> of ptep++ properly.
>
> That can be done when it would actually required, so as a first step having a
> generic hw_pte_t would just work.
>
--
Thanks,
Usama
On 7/29/26 13:33, Muhammad Usama Anjum wrote:
> On 29/07/2026 12:05 pm, David Hildenbrand (Arm) wrote:
>> On 7/29/26 12:13, Alexander Gordeev wrote:
>>> ...
>>>
>>> May be we need the generic hw_pte_t implementation as { pte_t pte; }
>>> right away?
>>
>> Indeed, that makes sense. We just need a way for the architecture to opt-in that
>> it did the conversion.
> Yeah and architecture cannot opt-in until its converted. So we should leave
> it to architecture to define hw_pte_t.
In the context of this series, we should have something like an
CONFIG_ARCH_HAS_XXX and select the definition based on that.
So we'd have a generic variant.
--
Cheers,
David
On 29/07/2026 12:52 pm, David Hildenbrand (Arm) wrote:
> On 7/29/26 13:33, Muhammad Usama Anjum wrote:
>> On 29/07/2026 12:05 pm, David Hildenbrand (Arm) wrote:
>>> On 7/29/26 12:13, Alexander Gordeev wrote:
>>>> ...
>>>>
>>>> May be we need the generic hw_pte_t implementation as { pte_t pte; }
>>>> right away?
>>>
>>> Indeed, that makes sense. We just need a way for the architecture to opt-in that
>>> it did the conversion.
>> Yeah and architecture cannot opt-in until its converted. So we should leave
>> it to architecture to define hw_pte_t.
>
> In the context of this series, we should have something like an
> CONFIG_ARCH_HAS_XXX and select the definition based on that.
>
> So we'd have a generic variant.
I'll add CONFIG_ARCH_HAS_XXX config in generic version.
I don't understand why generic code would define hw_pte_t if arch optionally
opts-in.
Are you saying pte_t may have different definition in different arches. But
the hw_pte_t would always be structure of pte_t. Hence definition
typedef struct { pte_t __pte; }; hw_pte_t;
can be moved to the generic code?
Moving definition to generic side is fine at this point in time. But if
a arch wants to hw_pte_t opaque and don't want the generic code to perform
arithmatic (ptep++), it'll not work.
--
Thanks,
Usama
On 7/29/26 14:21, Muhammad Usama Anjum wrote:
> On 29/07/2026 12:52 pm, David Hildenbrand (Arm) wrote:
>> On 7/29/26 13:33, Muhammad Usama Anjum wrote:
>>> Yeah and architecture cannot opt-in until its converted. So we should leave
>>> it to architecture to define hw_pte_t.
>>
>> In the context of this series, we should have something like an
>> CONFIG_ARCH_HAS_XXX and select the definition based on that.
>>
>> So we'd have a generic variant.
> I'll add CONFIG_ARCH_HAS_XXX config in generic version.
>
> I don't understand why generic code would define hw_pte_t if arch optionally
> opts-in.
>
> Are you saying pte_t may have different definition in different arches. But
> the hw_pte_t would always be structure of pte_t. Hence definition
>
> typedef struct { pte_t __pte; }; hw_pte_t;
>
> can be moved to the generic code?
>
> Moving definition to generic side is fine at this point in time. But if
> a arch wants to hw_pte_t opaque and don't want the generic code to perform
> arithmatic (ptep++), it'll not work.
Yes, but we can tackle this once some arch actually needs that. For now, it
makes this patch set easier to digest.
--
Cheers,
David
© 2016 - 2026 Red Hat, Inc.