* mm: opaque hardware page-table entry handles
@ 2026-06-24 14:09 Usama Anjum
2026-06-24 15:52 ` Zi Yan
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Usama Anjum @ 2026-06-24 14:09 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland
Cc: usama.anjum, linux-mm, linux-arm-kernel, linux-kernel
Hi all,
This is a direction-check with the wider community before spending time on the
development. This picks up the idea that was raised and broadly agreed in the
earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
The problem
-----------
Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
representation. Sprinkling getters wouldn't solve the problem entirely. The
problem is one level up: the *pointer type* itself is overloaded. At each level
there are really three distinct things:
1. a page-table entry value (pte_t, pmd_t, ...)
2. a pointer to an entry value, e.g. a pXX_t on the stack
3. a pointer to a live entry in the hardware page table
Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
distinguishes a pointer into a live table from a pointer to a stack copy.
A pointer to an on-stack entry value and a pointer to a live hardware entry have
the same type, so the compiler cannot distinguish them. Passing the stack
pointer to an arch helper that expects a hardware-entry pointer compiles fine,
but is wrong - a bug class the type system makes invisible. It also blocks
evolution: an arch helper may need to read beyond the addressed entry (e.g.
adjacent or contiguous entries), which only makes sense for a real page-table
pointer, not a stack copy.
The idea
--------
Give (3) its own opaque type that cannot be dereferenced:
/* opaque handle to a HW page-table entry; not dereferenceable */
typedef struct {
pte_t *ptr;
} hw_ptep;
With this:
- a stack value can no longer masquerade as a hardware table entry,
- a hardware handle can no longer be raw-dereferenced,
- cases that genuinely operate on a value can be refactored to pass the value
and let the caller, which knows whether it holds a handle or a stack copy,
read it once.
The overload becomes a compile-time type error instead of a silent runtime bug,
and converting the tree forces every such site to be made explicit. This gives
us a framework where the architecture can completely virtualize the pgtable if
it likes; and the compiler can enforce that higher level code can't accidentally
work around it.
It is opt-in by architectures and incremental. The generic definition is
just an alias, so arches that do not care build unchanged:
typedef pte_t *hw_ptep;
An arch flips to the strong struct type when it is ready, and only then does
it get the stronger checking. This lets the conversion land gradually.
Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
features that need tighter control over how page tables are accessed and
manipulated.
Getter flavours
---------------
While converting, it is useful to have two accessor flavours at each level:
- pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
- pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
duplicated by the compiler
Keeping them distinct simplifies the conversion and avoids re-introducing the
class of lockless-read bugs seen on 32-bit.
Example conversion
------------------
Most of the conversion is mechanical.
-static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte, unsigned int nr)
+static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
+ hw_ptep ptep, pte_t pte, unsigned int nr)
{
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);
pte = pte_next_pfn(pte);
}
}
The bulk of work is this kind of rote substitution. The genuine work is the
handful of sites that turn out to be operating on a stack copy rather than a
live entry - those are exactly the ones the new type forces us to surface and
fix.
Estimated churn:
----------------
Half way through the prototyping converting only PTE and PMD levels:
77 files changed, +1801 / -1425
~57 files reference the new types
So the line count will grow once PUD/P4D/PGD and the remaining call sites are
converted; expect meaningfully more churn than the numbers above.
Introduce the type as an alias, convert one helper family per patch, and flip
an arch to the strong type last - with non-opted arches building unchanged at
every step.
Open questions
--------------
- Is the type-safety + future-feature enablement worth the churn?
- Naming: hw_ptep/hw_pmdp vs something else?
- Should all five levels be converted before merging anything, or is a staged
PTE-and-PMD then landing others acceptable?
- Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
level?
[1] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-24 14:09 mm: opaque hardware page-table entry handles Usama Anjum
@ 2026-06-24 15:52 ` Zi Yan
2026-06-24 22:39 ` Muhammad Usama Anjum
2026-06-24 19:25 ` Pedro Falcato
2026-07-01 20:56 ` David Hildenbrand (Arm)
2 siblings, 1 reply; 18+ messages in thread
From: Zi Yan @ 2026-06-24 15:52 UTC (permalink / raw)
To: Usama Anjum, Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland
Cc: linux-mm, linux-arm-kernel, linux-kernel
On Wed Jun 24, 2026 at 10:09 AM EDT, Usama Anjum wrote:
> Hi all,
>
> This is a direction-check with the wider community before spending time on the
> development. This picks up the idea that was raised and broadly agreed in the
> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>
> The problem
> -----------
> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
> representation. Sprinkling getters wouldn't solve the problem entirely. The
> problem is one level up: the *pointer type* itself is overloaded. At each level
> there are really three distinct things:
>
> 1. a page-table entry value (pte_t, pmd_t, ...)
> 2. a pointer to an entry value, e.g. a pXX_t on the stack
> 3. a pointer to a live entry in the hardware page table
This sounds good to me, but can you clarify the situation below?
A live entry means the entry can be accessed by hardware when the code
is manipulating it? What type should we use if we are pre-populating
PTEs in a PMD page before we establish the PMD page as a HW page table?
In __split_huge_pmd_locked(), we do that. A PMD page is first withdrawn
and filled with after-split PTEs, pmd_populate() and pte_offset_map()
are used for this not-yet-HW page table. Later, pmd_populate() is used
to make this page table visible to HW. Should we have two versions of
pmd_populate() and pte_offset_map()? Since the first pmd_populate()
would accept pmd_t*, but the second one would accept hw_pmdp, if we are
pedantic. Of course, we can be flexible here to use pmd_populate()
accpeting hw_pmdp for both, since the PMD page table we are modifying
is going to be visible to HW soon. But I think we should have clear
definitions for where these types are used and document them well.
You probably can ask LLMs to check these ambiguous/vague uses throughout
the code base.
>
> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
> distinguishes a pointer into a live table from a pointer to a stack copy.
>
> A pointer to an on-stack entry value and a pointer to a live hardware entry have
> the same type, so the compiler cannot distinguish them. Passing the stack
> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
> but is wrong - a bug class the type system makes invisible. It also blocks
> evolution: an arch helper may need to read beyond the addressed entry (e.g.
> adjacent or contiguous entries), which only makes sense for a real page-table
> pointer, not a stack copy.
>
> The idea
> --------
> Give (3) its own opaque type that cannot be dereferenced:
>
> /* opaque handle to a HW page-table entry; not dereferenceable */
> typedef struct {
> pte_t *ptr;
> } hw_ptep;
>
> With this:
>
> - a stack value can no longer masquerade as a hardware table entry,
> - a hardware handle can no longer be raw-dereferenced,
> - cases that genuinely operate on a value can be refactored to pass the value
> and let the caller, which knows whether it holds a handle or a stack copy,
> read it once.
>
> The overload becomes a compile-time type error instead of a silent runtime bug,
> and converting the tree forces every such site to be made explicit. This gives
> us a framework where the architecture can completely virtualize the pgtable if
> it likes; and the compiler can enforce that higher level code can't accidentally
> work around it.
>
> It is opt-in by architectures and incremental. The generic definition is
> just an alias, so arches that do not care build unchanged:
>
> typedef pte_t *hw_ptep;
>
> An arch flips to the strong struct type when it is ready, and only then does
> it get the stronger checking. This lets the conversion land gradually.
>
> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
> features that need tighter control over how page tables are accessed and
> manipulated.
>
> Getter flavours
> ---------------
> While converting, it is useful to have two accessor flavours at each level:
>
> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
> duplicated by the compiler
>
> Keeping them distinct simplifies the conversion and avoids re-introducing the
> class of lockless-read bugs seen on 32-bit.
>
> Example conversion
> ------------------
> Most of the conversion is mechanical.
>
> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> - pte_t *ptep, pte_t pte, unsigned int nr)
> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> + hw_ptep ptep, pte_t pte, unsigned int nr)
> {
> 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);
> pte = pte_next_pfn(pte);
> }
> }
>
> The bulk of work is this kind of rote substitution. The genuine work is the
> handful of sites that turn out to be operating on a stack copy rather than a
> live entry - those are exactly the ones the new type forces us to surface and
> fix.
>
> Estimated churn:
> ----------------
> Half way through the prototyping converting only PTE and PMD levels:
> 77 files changed, +1801 / -1425
> ~57 files reference the new types
>
> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
> converted; expect meaningfully more churn than the numbers above.
>
> Introduce the type as an alias, convert one helper family per patch, and flip
> an arch to the strong type last - with non-opted arches building unchanged at
> every step.
>
> Open questions
> --------------
> - Is the type-safety + future-feature enablement worth the churn?
> - Naming: hw_ptep/hw_pmdp vs something else?
> - Should all five levels be converted before merging anything, or is a staged
> PTE-and-PMD then landing others acceptable?
> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
> level?
>
> [1] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
>
> Thanks,
> Usama
--
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-24 14:09 mm: opaque hardware page-table entry handles Usama Anjum
2026-06-24 15:52 ` Zi Yan
@ 2026-06-24 19:25 ` Pedro Falcato
2026-06-25 10:50 ` Muhammad Usama Anjum
2026-07-01 20:56 ` David Hildenbrand (Arm)
2 siblings, 1 reply; 18+ messages in thread
From: Pedro Falcato @ 2026-06-24 19:25 UTC (permalink / raw)
To: Usama Anjum
Cc: Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-mm,
linux-arm-kernel, linux-kernel
On Wed, Jun 24, 2026 at 03:09:08PM +0100, Usama Anjum wrote:
> Hi all,
>
> This is a direction-check with the wider community before spending time on the
> development. This picks up the idea that was raised and broadly agreed in the
> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>
> The problem
> -----------
> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
> representation. Sprinkling getters wouldn't solve the problem entirely. The
> problem is one level up: the *pointer type* itself is overloaded. At each level
> there are really three distinct things:
>
> 1. a page-table entry value (pte_t, pmd_t, ...)
> 2. a pointer to an entry value, e.g. a pXX_t on the stack
> 3. a pointer to a live entry in the hardware page table
>
> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
> distinguishes a pointer into a live table from a pointer to a stack copy.
>
> A pointer to an on-stack entry value and a pointer to a live hardware entry have
> the same type, so the compiler cannot distinguish them. Passing the stack
> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
> but is wrong - a bug class the type system makes invisible. It also blocks
> evolution: an arch helper may need to read beyond the addressed entry (e.g.
> adjacent or contiguous entries), which only makes sense for a real page-table
> pointer, not a stack copy.
>
> The idea
> --------
> Give (3) its own opaque type that cannot be dereferenced:
>
> /* opaque handle to a HW page-table entry; not dereferenceable */
> typedef struct {
> pte_t *ptr;
> } hw_ptep;
I don't love typedefs that hide pointers.
>
> With this:
>
> - a stack value can no longer masquerade as a hardware table entry,
> - a hardware handle can no longer be raw-dereferenced,
> - cases that genuinely operate on a value can be refactored to pass the value
> and let the caller, which knows whether it holds a handle or a stack copy,
> read it once.
Just a small passing comment: how about doing it differently? like
typedef struct {
pte_t *ptep;
} sw_ptep_t;
or something like that. Were I to guess, referring to a pte_t on the stack
is much rarer than all the pte_t references to actual page tables. But maybe
reality doesn't match up with my guess :)
>
> The overload becomes a compile-time type error instead of a silent runtime bug,
> and converting the tree forces every such site to be made explicit. This gives
> us a framework where the architecture can completely virtualize the pgtable if
> it likes; and the compiler can enforce that higher level code can't accidentally
> work around it.
>
> It is opt-in by architectures and incremental. The generic definition is
> just an alias, so arches that do not care build unchanged:
>
> typedef pte_t *hw_ptep;
>
> An arch flips to the strong struct type when it is ready, and only then does
> it get the stronger checking. This lets the conversion land gradually.
>
> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
> features that need tighter control over how page tables are accessed and
> manipulated.
>
> Getter flavours
> ---------------
> While converting, it is useful to have two accessor flavours at each level:
>
> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
> duplicated by the compiler
>
> Keeping them distinct simplifies the conversion and avoids re-introducing the
> class of lockless-read bugs seen on 32-bit.
>
> Example conversion
> ------------------
> Most of the conversion is mechanical.
>
> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> - pte_t *ptep, pte_t pte, unsigned int nr)
> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> + hw_ptep ptep, pte_t pte, unsigned int nr)
> {
> 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);
> pte = pte_next_pfn(pte);
> }
> }
>
> The bulk of work is this kind of rote substitution. The genuine work is the
> handful of sites that turn out to be operating on a stack copy rather than a
> live entry - those are exactly the ones the new type forces us to surface and
> fix.
>
> Estimated churn:
> ----------------
> Half way through the prototyping converting only PTE and PMD levels:
> 77 files changed, +1801 / -1425
> ~57 files reference the new types
Right, the churn would be very unfortunate.
>
> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
> converted; expect meaningfully more churn than the numbers above.
>
> Introduce the type as an alias, convert one helper family per patch, and flip
> an arch to the strong type last - with non-opted arches building unchanged at
> every step.
>
> Open questions
> --------------
> - Is the type-safety + future-feature enablement worth the churn?
> - Naming: hw_ptep/hw_pmdp vs something else?
> - Should all five levels be converted before merging anything, or is a staged
> PTE-and-PMD then landing others acceptable?
> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
> level?
>
> [1] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
>
> Thanks,
> Usama
>
--
Pedro
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-24 15:52 ` Zi Yan
@ 2026-06-24 22:39 ` Muhammad Usama Anjum
0 siblings, 0 replies; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-06-24 22:39 UTC (permalink / raw)
To: Zi Yan, Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland
Cc: usama.anjum, linux-mm, linux-arm-kernel, linux-kernel
On 24/06/2026 4:52 pm, Zi Yan wrote:
> On Wed Jun 24, 2026 at 10:09 AM EDT, Usama Anjum wrote:
>> Hi all,
>>
>> This is a direction-check with the wider community before spending time on the
>> development. This picks up the idea that was raised and broadly agreed in the
>> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>>
>> The problem
>> -----------
>> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
>> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
>> representation. Sprinkling getters wouldn't solve the problem entirely. The
>> problem is one level up: the *pointer type* itself is overloaded. At each level
>> there are really three distinct things:
>>
>> 1. a page-table entry value (pte_t, pmd_t, ...)
>> 2. a pointer to an entry value, e.g. a pXX_t on the stack
>> 3. a pointer to a live entry in the hardware page table
>
> This sounds good to me, but can you clarify the situation below?
>
> A live entry means the entry can be accessed by hardware when the code
> is manipulating it?
I think live is wrong world to chose here. Its a mistake on my end. (3) means
the pointer points into real page-table memory and that table is complete,
whether or not it's linked in yet. A withdrawn-but-not-yet-installed table is
still a hardware table and can be represented by hw_pXXp type.
> What type should we use if we are pre-populating
> PTEs in a PMD page before we establish the PMD page as a HW page table?
> In __split_huge_pmd_locked(), we do that. A PMD page is first withdrawn
> and filled with after-split PTEs, pmd_populate() and pte_offset_map()
> are used for this not-yet-HW page table. Later, pmd_populate() is used> to make this page table visible to HW. Should we have two versions of
> pmd_populate() and pte_offset_map()? Since the first pmd_populate()
> would accept pmd_t*, but the second one would accept hw_pmdp, if we are
> pedantic. Of course, we can be flexible here to use pmd_populate()
> accpeting hw_pmdp for both, since the PMD page table we are modifying
> is going to be visible to HW soon. But I think we should have clear
> definitions for where these types are used and document them well.
This is exactly the example that causes the confusion. Following the definition
above, the pmd is on the stack while the PTEs are being prepared, and the PTE
table is complete — so the pmd pointer should be pmd_t * and the PTE table
hw_ptep. I'd keep the two APIs distinct rather than overloading hw_pmdp for
both: that's what enforces the rule that no stack pointer reaches a
table-writing API, and what lets the *_stack path drop the synchronization.
(One thing I still need to chase: there are cases where we convert between pmd
and pte. I need to understand how often that happens — if it's common, a
hw_ptep could get converted into a pmd and bring the confusion back, and if we
have to account for that, definition (3) may need to change.)
>
> You probably can ask LLMs to check these ambiguous/vague uses throughout
> the code base.
>
>>
>> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
>> distinguishes a pointer into a live table from a pointer to a stack copy.
>>
>> A pointer to an on-stack entry value and a pointer to a live hardware entry have
>> the same type, so the compiler cannot distinguish them. Passing the stack
>> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
>> but is wrong - a bug class the type system makes invisible. It also blocks
>> evolution: an arch helper may need to read beyond the addressed entry (e.g.
>> adjacent or contiguous entries), which only makes sense for a real page-table
>> pointer, not a stack copy.
>>
>> The idea
>> --------
>> Give (3) its own opaque type that cannot be dereferenced:
>>
>> /* opaque handle to a HW page-table entry; not dereferenceable */
>> typedef struct {
>> pte_t *ptr;
>> } hw_ptep;
>>
>> With this:
>>
>> - a stack value can no longer masquerade as a hardware table entry,
>> - a hardware handle can no longer be raw-dereferenced,
>> - cases that genuinely operate on a value can be refactored to pass the value
>> and let the caller, which knows whether it holds a handle or a stack copy,
>> read it once.
>>
>> The overload becomes a compile-time type error instead of a silent runtime bug,
>> and converting the tree forces every such site to be made explicit. This gives
>> us a framework where the architecture can completely virtualize the pgtable if
>> it likes; and the compiler can enforce that higher level code can't accidentally
>> work around it.
>>
>> It is opt-in by architectures and incremental. The generic definition is
>> just an alias, so arches that do not care build unchanged:
>>
>> typedef pte_t *hw_ptep;
>>
>> An arch flips to the strong struct type when it is ready, and only then does
>> it get the stronger checking. This lets the conversion land gradually.
>>
>> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
>> features that need tighter control over how page tables are accessed and
>> manipulated.
>>
>> Getter flavours
>> ---------------
>> While converting, it is useful to have two accessor flavours at each level:
>>
>> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
>> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
>> duplicated by the compiler
>>
>> Keeping them distinct simplifies the conversion and avoids re-introducing the
>> class of lockless-read bugs seen on 32-bit.
>>
>> Example conversion
>> ------------------
>> Most of the conversion is mechanical.
>>
>> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> - pte_t *ptep, pte_t pte, unsigned int nr)
>> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> + hw_ptep ptep, pte_t pte, unsigned int nr)
>> {
>> 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);
>> pte = pte_next_pfn(pte);
>> }
>> }
>>
>> The bulk of work is this kind of rote substitution. The genuine work is the
>> handful of sites that turn out to be operating on a stack copy rather than a
>> live entry - those are exactly the ones the new type forces us to surface and
>> fix.
>>
>> Estimated churn:
>> ----------------
>> Half way through the prototyping converting only PTE and PMD levels:
>> 77 files changed, +1801 / -1425
>> ~57 files reference the new types
>>
>> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
>> converted; expect meaningfully more churn than the numbers above.
>>
>> Introduce the type as an alias, convert one helper family per patch, and flip
>> an arch to the strong type last - with non-opted arches building unchanged at
>> every step.
>>
>> Open questions
>> --------------
>> - Is the type-safety + future-feature enablement worth the churn?
>> - Naming: hw_ptep/hw_pmdp vs something else?
>> - Should all five levels be converted before merging anything, or is a staged
>> PTE-and-PMD then landing others acceptable?
>> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
>> level?
>>
>> [1] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
>>
>> Thanks,
>> Usama
>
>
>
>
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-24 19:25 ` Pedro Falcato
@ 2026-06-25 10:50 ` Muhammad Usama Anjum
2026-06-25 11:08 ` Pedro Falcato
0 siblings, 1 reply; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-06-25 10:50 UTC (permalink / raw)
To: Pedro Falcato
Cc: usama.anjum, Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-mm,
linux-arm-kernel, linux-kernel
On 24/06/2026 8:25 pm, Pedro Falcato wrote:
> On Wed, Jun 24, 2026 at 03:09:08PM +0100, Usama Anjum wrote:
>> Hi all,
>>
>> This is a direction-check with the wider community before spending time on the
>> development. This picks up the idea that was raised and broadly agreed in the
>> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>>
>> The problem
>> -----------
>> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
>> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
>> representation. Sprinkling getters wouldn't solve the problem entirely. The
>> problem is one level up: the *pointer type* itself is overloaded. At each level
>> there are really three distinct things:
>>
>> 1. a page-table entry value (pte_t, pmd_t, ...)
>> 2. a pointer to an entry value, e.g. a pXX_t on the stack
>> 3. a pointer to a live entry in the hardware page table
>>
>> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
>> distinguishes a pointer into a live table from a pointer to a stack copy.
>>
>> A pointer to an on-stack entry value and a pointer to a live hardware entry have
>> the same type, so the compiler cannot distinguish them. Passing the stack
>> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
>> but is wrong - a bug class the type system makes invisible. It also blocks
>> evolution: an arch helper may need to read beyond the addressed entry (e.g.
>> adjacent or contiguous entries), which only makes sense for a real page-table
>> pointer, not a stack copy.
>>
>> The idea
>> --------
>> Give (3) its own opaque type that cannot be dereferenced:
>>
>> /* opaque handle to a HW page-table entry; not dereferenceable */
>> typedef struct {
>> pte_t *ptr;
>> } hw_ptep;
>
> I don't love typedefs that hide pointers.
Nobody likes them. This is the only way so that by mistake stack pointers
don't get reintroduced. Its also hard to catch such cases during review.
>
>>
>> With this:
>>
>> - a stack value can no longer masquerade as a hardware table entry,
>> - a hardware handle can no longer be raw-dereferenced,
>> - cases that genuinely operate on a value can be refactored to pass the value
>> and let the caller, which knows whether it holds a handle or a stack copy,
>> read it once.
>
> Just a small passing comment: how about doing it differently? like
>
> typedef struct {
> pte_t *ptep;
> } sw_ptep_t;
>
> or something like that. Were I to guess, referring to a pte_t on the stack
> is much rarer than all the pte_t references to actual page tables. But maybe
> reality doesn't match up with my guess :)
We want to fix the current usages and future usages as well. sw_ptep_t can work
for current usages, but it'll not force the new code to be written using correct
notations. Apart from different types, another benefit of hw_pXXp would be that
it'll become an opaque object which only architecture can manipulate. Hence
architecture can decide howeverever it wants to manage them in certain cases.
>
>>
>> The overload becomes a compile-time type error instead of a silent runtime bug,
>> and converting the tree forces every such site to be made explicit. This gives
>> us a framework where the architecture can completely virtualize the pgtable if
>> it likes; and the compiler can enforce that higher level code can't accidentally
>> work around it.
>>
>> It is opt-in by architectures and incremental. The generic definition is
>> just an alias, so arches that do not care build unchanged:
>>
>> typedef pte_t *hw_ptep;
>>
>> An arch flips to the strong struct type when it is ready, and only then does
>> it get the stronger checking. This lets the conversion land gradually.
>>
>> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
>> features that need tighter control over how page tables are accessed and
>> manipulated.
>>
>> Getter flavours
>> ---------------
>> While converting, it is useful to have two accessor flavours at each level:
>>
>> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
>> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
>> duplicated by the compiler
>>
>> Keeping them distinct simplifies the conversion and avoids re-introducing the
>> class of lockless-read bugs seen on 32-bit.
>>
>> Example conversion
>> ------------------
>> Most of the conversion is mechanical.
>>
>> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> - pte_t *ptep, pte_t pte, unsigned int nr)
>> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> + hw_ptep ptep, pte_t pte, unsigned int nr)
>> {
>> 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);
>> pte = pte_next_pfn(pte);
>> }
>> }
>>
>> The bulk of work is this kind of rote substitution. The genuine work is the
>> handful of sites that turn out to be operating on a stack copy rather than a
>> live entry - those are exactly the ones the new type forces us to surface and
>> fix.
>>
>> Estimated churn:
>> ----------------
>> Half way through the prototyping converting only PTE and PMD levels:
>> 77 files changed, +1801 / -1425
>> ~57 files reference the new types
>
> Right, the churn would be very unfortunate.
>
>>
>> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
>> converted; expect meaningfully more churn than the numbers above.
>>
>> Introduce the type as an alias, convert one helper family per patch, and flip
>> an arch to the strong type last - with non-opted arches building unchanged at
>> every step.
>>
>> Open questions
>> --------------
>> - Is the type-safety + future-feature enablement worth the churn?
>> - Naming: hw_ptep/hw_pmdp vs something else?
>> - Should all five levels be converted before merging anything, or is a staged
>> PTE-and-PMD then landing others acceptable?
>> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
>> level?
>>
>> [1] https://lore.kernel.org/all/a063f6c5-2785-4a9f-8079-25edb3e54cef@arm.com
>>
>> Thanks,
>> Usama
>>
>
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-25 10:50 ` Muhammad Usama Anjum
@ 2026-06-25 11:08 ` Pedro Falcato
2026-06-25 12:15 ` Muhammad Usama Anjum
0 siblings, 1 reply; 18+ messages in thread
From: Pedro Falcato @ 2026-06-25 11:08 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-mm,
linux-arm-kernel, linux-kernel
On Thu, Jun 25, 2026 at 11:50:28AM +0100, Muhammad Usama Anjum wrote:
> On 24/06/2026 8:25 pm, Pedro Falcato wrote:
> > On Wed, Jun 24, 2026 at 03:09:08PM +0100, Usama Anjum wrote:
> >> Hi all,
> >>
> >> This is a direction-check with the wider community before spending time on the
> >> development. This picks up the idea that was raised and broadly agreed in the
> >> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
> >>
> >> The problem
> >> -----------
> >> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
> >> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
> >> representation. Sprinkling getters wouldn't solve the problem entirely. The
> >> problem is one level up: the *pointer type* itself is overloaded. At each level
> >> there are really three distinct things:
> >>
> >> 1. a page-table entry value (pte_t, pmd_t, ...)
> >> 2. a pointer to an entry value, e.g. a pXX_t on the stack
> >> 3. a pointer to a live entry in the hardware page table
> >>
> >> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
> >> distinguishes a pointer into a live table from a pointer to a stack copy.
> >>
> >> A pointer to an on-stack entry value and a pointer to a live hardware entry have
> >> the same type, so the compiler cannot distinguish them. Passing the stack
> >> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
> >> but is wrong - a bug class the type system makes invisible. It also blocks
> >> evolution: an arch helper may need to read beyond the addressed entry (e.g.
> >> adjacent or contiguous entries), which only makes sense for a real page-table
> >> pointer, not a stack copy.
> >>
> >> The idea
> >> --------
> >> Give (3) its own opaque type that cannot be dereferenced:
> >>
> >> /* opaque handle to a HW page-table entry; not dereferenceable */
> >> typedef struct {
> >> pte_t *ptr;
> >> } hw_ptep;
> >
> > I don't love typedefs that hide pointers.
> Nobody likes them. This is the only way so that by mistake stack pointers
> don't get reintroduced. Its also hard to catch such cases during review.
That's not true, you could have:
typedef struct { pteval_t pte; } sw_pte_t;
and
/* only usable by arch code and whoever wants to interpret these
* types */
static inline sw_to_ptep(sw_pte_t *swptep)
{
return (pte_t *) swptep;
}
and so on... Also, see Documentation/process/coding-style.rst 5) typedefs, it
explicitly warns against pointer typedefs.
>
> >
> >>
> >> With this:
> >>
> >> - a stack value can no longer masquerade as a hardware table entry,
> >> - a hardware handle can no longer be raw-dereferenced,
> >> - cases that genuinely operate on a value can be refactored to pass the value
> >> and let the caller, which knows whether it holds a handle or a stack copy,
> >> read it once.
> >
> > Just a small passing comment: how about doing it differently? like
> >
> > typedef struct {
> > pte_t *ptep;
> > } sw_ptep_t;
> >
> > or something like that. Were I to guess, referring to a pte_t on the stack
> > is much rarer than all the pte_t references to actual page tables. But maybe
> > reality doesn't match up with my guess :)
> We want to fix the current usages and future usages as well. sw_ptep_t can work
> for current usages, but it'll not force the new code to be written using correct
> notations.
I don't understand what you mean. pte_t is a perfectly correct notation,
it's just currently maybe too ambiguously overloaded.
> Apart from different types, another benefit of hw_pXXp would be that
> it'll become an opaque object which only architecture can manipulate. Hence
> architecture can decide howeverever it wants to manage them in certain cases.
That's already the case. pte_t is fully opaque apart from the little fact
that you can declare one on your stack. Introducing a different sw_pte_t
would further reinforce that. And if you want ways to find raw derefs on
pointers, we can simply slap on __attribute__((noderef)) (available in
sparse and clang) on those types after sw_pte_t is introduced and pte_t
is unambiguously a "hardware" PTE.
I dunno, I'm not convinced that changing around ~450 files is worth it, and
_if_ we want to do something like this I would strongly prefer the way that
is less churny.
--
Pedro
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-25 11:08 ` Pedro Falcato
@ 2026-06-25 12:15 ` Muhammad Usama Anjum
0 siblings, 0 replies; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-06-25 12:15 UTC (permalink / raw)
To: Pedro Falcato
Cc: usama.anjum, Andrew Morton, Lorenzo Stoakes, David Hildenbrand,
Liam R. Howlett, Mike Rapoport, Ryan Roberts, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-mm,
linux-arm-kernel, linux-kernel
On 25/06/2026 12:08 pm, Pedro Falcato wrote:
> On Thu, Jun 25, 2026 at 11:50:28AM +0100, Muhammad Usama Anjum wrote:
>> On 24/06/2026 8:25 pm, Pedro Falcato wrote:
>>> On Wed, Jun 24, 2026 at 03:09:08PM +0100, Usama Anjum wrote:
>>>> Hi all,
>>>>
>>>> This is a direction-check with the wider community before spending time on the
>>>> development. This picks up the idea that was raised and broadly agreed in the
>>>> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>>>>
>>>> The problem
>>>> -----------
>>>> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
>>>> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
>>>> representation. Sprinkling getters wouldn't solve the problem entirely. The
>>>> problem is one level up: the *pointer type* itself is overloaded. At each level
>>>> there are really three distinct things:
>>>>
>>>> 1. a page-table entry value (pte_t, pmd_t, ...)
>>>> 2. a pointer to an entry value, e.g. a pXX_t on the stack
>>>> 3. a pointer to a live entry in the hardware page table
>>>>
>>>> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
>>>> distinguishes a pointer into a live table from a pointer to a stack copy.
>>>>
>>>> A pointer to an on-stack entry value and a pointer to a live hardware entry have
>>>> the same type, so the compiler cannot distinguish them. Passing the stack
>>>> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
>>>> but is wrong - a bug class the type system makes invisible. It also blocks
>>>> evolution: an arch helper may need to read beyond the addressed entry (e.g.
>>>> adjacent or contiguous entries), which only makes sense for a real page-table
>>>> pointer, not a stack copy.
>>>>
>>>> The idea
>>>> --------
>>>> Give (3) its own opaque type that cannot be dereferenced:
>>>>
>>>> /* opaque handle to a HW page-table entry; not dereferenceable */
>>>> typedef struct {
>>>> pte_t *ptr;
>>>> } hw_ptep;
>>>
>>> I don't love typedefs that hide pointers.
>> Nobody likes them. This is the only way so that by mistake stack pointers
>> don't get reintroduced. Its also hard to catch such cases during review.
>
> That's not true, you could have:
>
> typedef struct { pteval_t pte; } sw_pte_t;
>
> and
>
> /* only usable by arch code and whoever wants to interpret these
> * types */
> static inline sw_to_ptep(sw_pte_t *swptep)
> {
> return (pte_t *) swptep;
> }
>
> and so on... Also, see Documentation/process/coding-style.rst 5) typedefs, it
> explicitly warns against pointer typedefs.
I hear your concern, but I think the sw_pte_t inversion solves the small problem
and gives up the big one. Let me make the case for keeping the opaque hardware type.
The narrow goal is "no stack pointer reaches a table-writing API". Both schemes catch
that. But the actual reasons for this idea is broader one:
* making core independent of how a real page table entry is represented and accessed.
It only works if hardware type is the abstract one.
* As you may have noted with pmdp_get(): on some arches the read is not a pure load
(folding, lockless ordering, kmap of a highmem table page). pte_t * lets callers
bypass all of that with *ptep. The handle makes the accessor the only door, so the
barriers/folds can't be skipped by accident.
>>
>>>
>>>>
>>>> With this:
>>>>
>>>> - a stack value can no longer masquerade as a hardware table entry,
>>>> - a hardware handle can no longer be raw-dereferenced,
>>>> - cases that genuinely operate on a value can be refactored to pass the value
>>>> and let the caller, which knows whether it holds a handle or a stack copy,
>>>> read it once.
>>>
>>> Just a small passing comment: how about doing it differently? like
>>>
>>> typedef struct {
>>> pte_t *ptep;
>>> } sw_ptep_t;
>>>
>>> or something like that. Were I to guess, referring to a pte_t on the stack
>>> is much rarer than all the pte_t references to actual page tables. But maybe
>>> reality doesn't match up with my guess :)
>> We want to fix the current usages and future usages as well. sw_ptep_t can work
>> for current usages, but it'll not force the new code to be written using correct
>> notations.
>
> I don't understand what you mean. pte_t is a perfectly correct notation,
> it's just currently maybe too ambiguously overloaded.
Yes, this overload is what need fixing.
>
>> Apart from different types, another benefit of hw_pXXp would be that
>> it'll become an opaque object which only architecture can manipulate. Hence
>> architecture can decide howeverever it wants to manage them in certain cases.
>
> That's already the case. pte_t is fully opaque apart from the little fact
> that you can declare one on your stack. Introducing a different sw_pte_t
> would further reinforce that. And if you want ways to find raw derefs on
> pointers, we can simply slap on __attribute__((noderef)) (available in
> sparse and clang) on those types after sw_pte_t is introduced and pte_t
> is unambiguously a "hardware" PTE.
The pte_t iterator loops in core code prove that it isn't opaque enough.
The pointer arithmetic (ptep++) is done at several places in the core.
The sw_pte_t + deref protection only catches misues under sparse. While the
hw_ptep type is enforced by every compiler for every build.
>
> I dunno, I'm not convinced that changing around ~450 files is worth it, and
> _if_ we want to do something like this I would strongly prefer the way that
> is less churny.
Probably you grepped these types to come up with 450 files? But we aren't going
to update all files. Only the generic code would be converted with one or two
architectures. Its architecture opt-in. It'll be transparent to non-converted
architectures. So if arch/ is excluded, the number of files would become a
quarter?
This type change is going to localize the future churn. It is one time cost;
after that, every future representation change lives behind the accessors.
If pte_t * stays the live type, each such change is another N files audit.
The struct buys us one choke point to evolve.
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-06-24 14:09 mm: opaque hardware page-table entry handles Usama Anjum
2026-06-24 15:52 ` Zi Yan
2026-06-24 19:25 ` Pedro Falcato
@ 2026-07-01 20:56 ` David Hildenbrand (Arm)
2026-07-06 12:52 ` Muhammad Usama Anjum
2 siblings, 1 reply; 18+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-01 20:56 UTC (permalink / raw)
To: Usama Anjum, Andrew Morton, Lorenzo Stoakes, Liam R. Howlett,
Mike Rapoport, Ryan Roberts, Anshuman Khandual, Catalin Marinas,
Will Deacon, Samuel Holland
Cc: linux-mm, linux-arm-kernel, linux-kernel
On 6/24/26 16:09, Usama Anjum wrote:
> Hi all,
Hi!
>
> This is a direction-check with the wider community before spending time on the
> development. This picks up the idea that was raised and broadly agreed in the
> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>
> The problem
> -----------
> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
> representation. Sprinkling getters wouldn't solve the problem entirely. The
> problem is one level up: the *pointer type* itself is overloaded. At each level
> there are really three distinct things:
>
> 1. a page-table entry value (pte_t, pmd_t, ...)
> 2. a pointer to an entry value, e.g. a pXX_t on the stack
> 3. a pointer to a live entry in the hardware page table
>
> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
> distinguishes a pointer into a live table from a pointer to a stack copy.
Yes, I just stumbled over that myself while working on Levi on some folded page
table optimizations for pdgp_get() and friends.
The stack usage is nasty. Calling ptep_get() on stack values makes no sense.
Reading actual page table values without ptep_get() is suboptimal. Punching
stack pointers into functions that don't expect the, is shaky.
>
> A pointer to an on-stack entry value and a pointer to a live hardware entry have
> the same type, so the compiler cannot distinguish them. Passing the stack
> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
> but is wrong - a bug class the type system makes invisible. It also blocks
> evolution: an arch helper may need to read beyond the addressed entry (e.g.
> adjacent or contiguous entries), which only makes sense for a real page-table
> pointer, not a stack copy.
>
> The idea
> --------
> Give (3) its own opaque type that cannot be dereferenced:
>
> /* opaque handle to a HW page-table entry; not dereferenceable */
> typedef struct {
> pte_t *ptr;
> } hw_ptep;
I guess the proper way of doing it would really be for hw_ptes to have a
distinct type, to completely decouple both concepts.
That's where the fun begins :(
We'd need hw_ptep++ to jump to the next entry in the page table. Assuming we're
on 32bit and have 64bit entries, would that work with the hw_ptep? hw_pte_next()
is rather nasty.
So, similar to what Pedro says
typedef struct {
pte_t __pte;
} hw_pte_t;
And then simply use
hw_pte_t *hptep;
>
> With this:
>
> - a stack value can no longer masquerade as a hardware table entry,
Right. What we don't care about is if someone deliberately would instantiate a
hw_pte_t above on the stack. We can catch that more easily.
> - a hardware handle can no longer be raw-dereferenced,
That's the important part, yes.
> - cases that genuinely operate on a value can be refactored to pass the value
> and let the caller, which knows whether it holds a handle or a stack copy,
> read it once.
The question is if these cases really just support one type of pointer (I assume
so).
>
> The overload becomes a compile-time type error instead of a silent runtime bug,
> and converting the tree forces every such site to be made explicit. This gives
> us a framework where the architecture can completely virtualize the pgtable if
> it likes; and the compiler can enforce that higher level code can't accidentally
> work around it.
>
> It is opt-in by architectures and incremental. The generic definition is
> just an alias, so arches that do not care build unchanged:
>
> typedef pte_t *hw_ptep;
Like Pedro says, pointer typedefs are really nasty.
>
> An arch flips to the strong struct type when it is ready, and only then does
> it get the stronger checking. This lets the conversion land gradually.
>
> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
> features that need tighter control over how page tables are accessed and
> manipulated.
>
> Getter flavours
> ---------------
> While converting, it is useful to have two accessor flavours at each level:
>
> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
That's just what we have. Defaults to READ_ONCE().
> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
> duplicated by the compiler
Why do we need this and what would we use it for?
>
> Keeping them distinct simplifies the conversion and avoids re-introducing the
> class of lockless-read bugs seen on 32-bit.
>
> Example conversion
> ------------------
> Most of the conversion is mechanical.
>
> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> - pte_t *ptep, pte_t pte, unsigned int nr)
> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> + hw_ptep ptep, pte_t pte, unsigned int nr)
hw_pte_t *ptep, pte_t pte, unsigned int nr)
or (with sw ptep)
pte_t *ptep, pte_t pte, unsigned int nr)
> {
> 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);
> }
> }
>
> The bulk of work is this kind of rote substitution. The genuine work is the
> handful of sites that turn out to be operating on a stack copy rather than a
> live entry - those are exactly the ones the new type forces us to surface and
> fix.
>
> Estimated churn:
> ----------------
> Half way through the prototyping converting only PTE and PMD levels:
> 77 files changed, +1801 / -1425
> ~57 files reference the new types
>
> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
> converted; expect meaningfully more churn than the numbers above.
>
> Introduce the type as an alias, convert one helper family per patch, and flip
> an arch to the strong type last - with non-opted arches building unchanged at
> every step.
>
> Open questions
> --------------
> - Is the type-safety + future-feature enablement worth the churn?
We have to minimize the churn. But yes, we really have to find a way to stop
ptep_get() and friends getting used on stack variables, or *ptep getting used
without ptep_get().
We have object_is_on_stack(), but that doesn't really allow for compile-time
checks ... and I don't know how safe it is in general.
> - Naming: hw_ptep/hw_pmdp vs something else?
Really avoid ptep typedefs.
> - Should all five levels be converted before merging anything, or is a staged
> PTE-and-PMD then landing others acceptable?
> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
> level?
I'm still not sure about the _once() really, and if we need that right now. We
survived without is so far, why do we need it now?
--
Cheers,
David
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-01 20:56 ` David Hildenbrand (Arm)
@ 2026-07-06 12:52 ` Muhammad Usama Anjum
2026-07-07 13:17 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-07-06 12:52 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: usama.anjum, linux-mm, linux-arm-kernel, linux-kernel,
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
Ryan Roberts, Anshuman Khandual, Catalin Marinas, Will Deacon,
Samuel Holland
Hi David,
Thank you for the review.
On 01/07/2026 9:56 pm, David Hildenbrand (Arm) wrote:
> On 6/24/26 16:09, Usama Anjum wrote:
>> Hi all,
>
> Hi!
>
>>
>> This is a direction-check with the wider community before spending time on the
>> development. This picks up the idea that was raised and broadly agreed in the
>> earlier thread (Ryan Roberts, Lorenzo Stoakes, David Hildenbrand) [1].
>>
>> The problem
>> -----------
>> Core MM code reaches page-table entries by raw pointer dereference (pte_t *,
>> pmd_t *, *pud, ...) in places, implicitly assuming a single, uniform
>> representation. Sprinkling getters wouldn't solve the problem entirely. The
>> problem is one level up: the *pointer type* itself is overloaded. At each level
>> there are really three distinct things:
>>
>> 1. a page-table entry value (pte_t, pmd_t, ...)
>> 2. a pointer to an entry value, e.g. a pXX_t on the stack
>> 3. a pointer to a live entry in the hardware page table
>>
>> Today (2) and (3) share the same type - pte_t *, pmd_t *, and so on. Nothing
>> distinguishes a pointer into a live table from a pointer to a stack copy.
>
> Yes, I just stumbled over that myself while working on Levi on some folded page
> table optimizations for pdgp_get() and friends.
>
> The stack usage is nasty. Calling ptep_get() on stack values makes no sense.
> Reading actual page table values without ptep_get() is suboptimal. Punching
> stack pointers into functions that don't expect the, is shaky.
>
>>
>> A pointer to an on-stack entry value and a pointer to a live hardware entry have
>> the same type, so the compiler cannot distinguish them. Passing the stack
>> pointer to an arch helper that expects a hardware-entry pointer compiles fine,
>> but is wrong - a bug class the type system makes invisible. It also blocks
>> evolution: an arch helper may need to read beyond the addressed entry (e.g.
>> adjacent or contiguous entries), which only makes sense for a real page-table
>> pointer, not a stack copy.
>>
>> The idea
>> --------
>> Give (3) its own opaque type that cannot be dereferenced:
>>
>> /* opaque handle to a HW page-table entry; not dereferenceable */
>> typedef struct {
>> pte_t *ptr;
>> } hw_ptep;
>
> I guess the proper way of doing it would really be for hw_ptes to have a
> distinct type, to completely decouple both concepts.
>
> That's where the fun begins :(
>
> We'd need hw_ptep++ to jump to the next entry in the page table. Assuming we're
> on 32bit and have 64bit entries, would that work with the hw_ptep? hw_pte_next()
> is rather nasty.
>
> So, similar to what Pedro says
>
> typedef struct {
> pte_t __pte;
> } hw_pte_t;
>
> And then simply use
>
> hw_pte_t *hptep;
Make sense. So you have suggested to just hide put pte_t inside a structure
instead of complex structure of pointer. I've tried to implement and it reduces
churn enormously.
>
>
>>
>> With this:
>>
>> - a stack value can no longer masquerade as a hardware table entry,
>
> Right. What we don't care about is if someone deliberately would instantiate a
> hw_pte_t above on the stack. We can catch that more easily.
>
>> - a hardware handle can no longer be raw-dereferenced,
>
> That's the important part, yes.
>
>> - cases that genuinely operate on a value can be refactored to pass the value
>> and let the caller, which knows whether it holds a handle or a stack copy,
>> read it once.
>
> The question is if these cases really just support one type of pointer (I assume
> so).
>
>>
>> The overload becomes a compile-time type error instead of a silent runtime bug,
>> and converting the tree forces every such site to be made explicit. This gives
>> us a framework where the architecture can completely virtualize the pgtable if
>> it likes; and the compiler can enforce that higher level code can't accidentally
>> work around it.
>>
>> It is opt-in by architectures and incremental. The generic definition is
>> just an alias, so arches that do not care build unchanged:
>>
>> typedef pte_t *hw_ptep;
>
> Like Pedro says, pointer typedefs are really nasty.
>
>>
>> An arch flips to the strong struct type when it is ready, and only then does
>> it get the stronger checking. This lets the conversion land gradually.
>>
>> Beyond fixing the latent bug class, this abstraction is an enabler for upcoming
>> features that need tighter control over how page tables are accessed and
>> manipulated.
>>
>> Getter flavours
>> ---------------
>> While converting, it is useful to have two accessor flavours at each level:
>>
>> - pXXp_get(hw_ptep) plain C dereference (compiler may optimize)
>
> That's just what we have. Defaults to READ_ONCE().
>
>> - pXXp_get_once(hw_ptep) single-copy-atomic, not torn, elided or
>> duplicated by the compiler
>
> Why do we need this and what would we use it for?
The idea was that there should be two different functions to read value. Let's
leave this out of the first initial series. It is complicating the original
proposal.
>
>>
>> Keeping them distinct simplifies the conversion and avoids re-introducing the
>> class of lockless-read bugs seen on 32-bit.
>>
>> Example conversion
>> ------------------
>> Most of the conversion is mechanical.
>>
>> -static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> - pte_t *ptep, pte_t pte, unsigned int nr)
>> +static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
>> + hw_ptep ptep, pte_t pte, unsigned int nr)
>
> hw_pte_t *ptep, pte_t pte, unsigned int nr)
Makes sense.
>
> or (with sw ptep)
>
> pte_t *ptep, pte_t pte, unsigned int nr)
>
>> {
>> 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.
Makes sense. There aren't very strong reasons to convert it at this time.
>
>> pte = pte_next_pfn(pte);
>> }
>> }
>>
>> The bulk of work is this kind of rote substitution. The genuine work is the
>> handful of sites that turn out to be operating on a stack copy rather than a
>> live entry - those are exactly the ones the new type forces us to surface and
>> fix.
>>
>> Estimated churn:
>> ----------------
>> Half way through the prototyping converting only PTE and PMD levels:
>> 77 files changed, +1801 / -1425
>> ~57 files reference the new types
>>
>> So the line count will grow once PUD/P4D/PGD and the remaining call sites are
>> converted; expect meaningfully more churn than the numbers above.
>>
>> Introduce the type as an alias, convert one helper family per patch, and flip
>> an arch to the strong type last - with non-opted arches building unchanged at
>> every step.
>>
>> Open questions
>> --------------
>> - Is the type-safety + future-feature enablement worth the churn?
>
> We have to minimize the churn. But yes, we really have to find a way to stop
> ptep_get() and friends getting used on stack variables, or *ptep getting used
> without ptep_get().
>
> We have object_is_on_stack(), but that doesn't really allow for compile-time
> checks ... and I don't know how safe it is in general.
>
>> - Naming: hw_ptep/hw_pmdp vs something else?
>
> Really avoid ptep typedefs.
>
>> - Should all five levels be converted before merging anything, or is a staged
>> PTE-and-PMD then landing others acceptable?
>> - Do we want the two getter flavours (pXXp_get / pXXp_get_once) at every
>> level?
>
> I'm still not sure about the _once() really, and if we need that right now. We
> survived without is so far, why do we need it now?
The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
discuss it later sometime again later.
>
>
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-06 12:52 ` Muhammad Usama Anjum
@ 2026-07-07 13:17 ` David Hildenbrand (Arm)
2026-07-15 16:15 ` Muhammad Usama Anjum
0 siblings, 1 reply; 18+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-07 13:17 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: linux-mm, linux-arm-kernel, linux-kernel, Andrew Morton,
Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport, Ryan Roberts,
Anshuman Khandual, Catalin Marinas, Will Deacon, Samuel Holland
[...]
>>
>> typedef struct {
>> pte_t __pte;
>> } hw_pte_t;
>>
>> And then simply use
>>
>> hw_pte_t *hptep;
> Make sense. So you have suggested to just hide put pte_t inside a structure
> instead of complex structure of pointer. I've tried to implement and it reduces
> churn enormously.
Right. And for most architectures we can probable leave both types be the same
under the hood.
So we'd only have to convert common code first, and can then e.g., look into
making architectures that care about the difference (e.g., arm64) actually have
it be two separate types.
Just an idea to further reduce the churn and limit it only to core code (because
I saw some very ugly stuff in some arch code that would make such a conversion
harder).
[...]
>> Why do we need this and what would we use it for?
> The idea was that there should be two different functions to read value. Let's
> leave this out of the first initial series. It is complicating the original
> proposal.
Right, let's leave that out for now. I'm currently working with Levi on an
approach that tries to avoid the overhead due to READ_ONCE with folded page
tables. [1]
We're still struggling with some bits, but looks like we can make it fly and
have it be fairly robust.
With that, maybe there is no reason left to have separate pXXp_get() vs.
pXXp_get_once(). TBD :)
[1] https://lore.kernel.org/all/08ecabe9-0664-4aea-82fb-f9cb1739f762@kernel.org/
[...]
>>
>> I'm still not sure about the _once() really, and if we need that right now. We
>> survived without is so far, why do we need it now?
> The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
> dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
> discuss it later sometime again later.
Sounds good.
--
Cheers,
David
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-07 13:17 ` David Hildenbrand (Arm)
@ 2026-07-15 16:15 ` Muhammad Usama Anjum
2026-07-21 12:40 ` Alexander Gordeev
0 siblings, 1 reply; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-07-15 16:15 UTC (permalink / raw)
To: David Hildenbrand (Arm), Zi Yan, Pedro Falcato, Ryan Roberts,
Lorenzo Stoakes
Cc: usama.anjum, linux-mm, linux-arm-kernel, linux-kernel,
Andrew Morton, Liam R. Howlett, Mike Rapoport, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland
Hi,
[Moved some already involved people to To. So they can help with the plan
details mentioned below.]
On 07/07/2026 2:17 pm, David Hildenbrand (Arm) wrote:
> [...]
>
>>>
>>> typedef struct {
>>> pte_t __pte;
>>> } hw_pte_t;
>>>
>>> And then simply use
>>>
>>> hw_pte_t *hptep;
>> Make sense. So you have suggested to just hide put pte_t inside a structure
>> instead of complex structure of pointer. I've tried to implement and it reduces
>> churn enormously.
>
> Right. And for most architectures we can probable leave both types be the same
> under the hood.
>
> So we'd only have to convert common code first, and can then e.g., look into
> making architectures that care about the difference (e.g., arm64) actually have
> it be two separate types.
It makes a lot of sense.
Let's even divide the series into more parts as there are several places where
conversion is controversial. (Xi Yan had mentioned one example earlier in this
thread.) Most of those controversial conversions are pmd related. I propose
that we convert pte_t first, then pmd_t and others. It'll keep the number of
patches manageable and easier to review.
I think wider agreement for this approach will be very helpful before I post the
actual code.
>
> Just an idea to further reduce the churn and limit it only to core code (because
> I saw some very ugly stuff in some arch code that would make such a conversion
> harder).
>
> [...]
>
>>> Why do we need this and what would we use it for?
>> The idea was that there should be two different functions to read value. Let's
>> leave this out of the first initial series. It is complicating the original
>> proposal.
>
> Right, let's leave that out for now. I'm currently working with Levi on an
> approach that tries to avoid the overhead due to READ_ONCE with folded page
> tables. [1]
So you are referring to page folding improvements. I also stumbled upon those
while doing a dirty implementation.
>
> We're still struggling with some bits, but looks like we can make it fly and
> have it be fairly robust.
>
> With that, maybe there is no reason left to have separate pXXp_get() vs.
> pXXp_get_once(). TBD :)
Yeah, I was reviewing that series earlier today. I've not looked deeply, but it
seems there are still a lot of cases where (mostly) pmd is getting dereferenced
directly. To complete the conversion, direct dereferences need to be converted
into an API. I've been thinking if there should be a dereference macro or we
must always use pmdp_get() even though it ensures ordering. It may add excessive
ordering in some functions if pmdp_get() is getting called multiple times. But
storing its output in a tmp variable would solve this.
Do you agree with converting all direct dereferences into pXXp_get()?
>
> [1] https://lore.kernel.org/all/08ecabe9-0664-4aea-82fb-f9cb1739f762@kernel.org/
>
> [...]
>
>>>
>>> I'm still not sure about the _once() really, and if we need that right now. We
>>> survived without is so far, why do we need it now?
>> The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
>> dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
>> discuss it later sometime again later.
>
> Sounds good.
I've tried to do conversions already. Converting by call hierarchy wise is very
difficult and error prune.
Converting component by component (such as page walk, huge page) is also difficult
as code is tangled. Some helper which is getting used in one component is also used
in another component.
I see the following way forward:
* Add the new type
* Identify which functions need explicitly pointer to a stack variable. These
must not be converted. These variables must be renamed to a common name. For
pte_t pointers on stack some functions already use ptentp, which is unique name
if we look at generic code. So ptentp would be used for all such variables.
* One commit per controversial change would be done at this point. We need new
separate function for stack types. Also we can do more renaming to a name which
will not be converted.
* Run Coccinelle script directory-by-directory which would ignore converting any
ptentp (and similarly for other types). Coccinelle doesn't converts in some case
(pte_t *a. *b) which can be done by hand at this point.
* Update any remaining functions
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-15 16:15 ` Muhammad Usama Anjum
@ 2026-07-21 12:40 ` Alexander Gordeev
2026-07-23 8:21 ` Muhammad Usama Anjum
0 siblings, 1 reply; 18+ messages in thread
From: Alexander Gordeev @ 2026-07-21 12:40 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: David Hildenbrand (Arm), Zi Yan, Pedro Falcato, Ryan Roberts,
Lorenzo Stoakes, linux-mm, linux-arm-kernel, linux-kernel,
Andrew Morton, Liam R. Howlett, Mike Rapoport, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-s390
On Wed, Jul 15, 2026 at 05:15:36PM +0100, Muhammad Usama Anjum wrote:
> Hi,
>
> [Moved some already involved people to To. So they can help with the plan
> details mentioned below.]
>
> On 07/07/2026 2:17 pm, David Hildenbrand (Arm) wrote:
> > [...]
> >
> >>>
> >>> typedef struct {
> >>> pte_t __pte;
> >>> } hw_pte_t;
> >>>
> >>> And then simply use
> >>>
> >>> hw_pte_t *hptep;
> >> Make sense. So you have suggested to just hide put pte_t inside a structure
> >> instead of complex structure of pointer. I've tried to implement and it reduces
> >> churn enormously.
> >
> > Right. And for most architectures we can probable leave both types be the same
> > under the hood.
> >
> > So we'd only have to convert common code first, and can then e.g., look into
> > making architectures that care about the difference (e.g., arm64) actually have
> > it be two separate types.
> It makes a lot of sense.
>
> Let's even divide the series into more parts as there are several places where
> conversion is controversial. (Xi Yan had mentioned one example earlier in this
> thread.) Most of those controversial conversions are pmd related. I propose
> that we convert pte_t first, then pmd_t and others. It'll keep the number of
> patches manageable and easier to review.
>
> I think wider agreement for this approach will be very helpful before I post the
> actual code.
>
> >
> > Just an idea to further reduce the churn and limit it only to core code (because
> > I saw some very ugly stuff in some arch code that would make such a conversion
> > harder).
> >
> > [...]
> >
> >>> Why do we need this and what would we use it for?
> >> The idea was that there should be two different functions to read value. Let's
> >> leave this out of the first initial series. It is complicating the original
> >> proposal.
> >
> > Right, let's leave that out for now. I'm currently working with Levi on an
> > approach that tries to avoid the overhead due to READ_ONCE with folded page
> > tables. [1]
> So you are referring to page folding improvements. I also stumbled upon those
> while doing a dirty implementation.
>
> >
> > We're still struggling with some bits, but looks like we can make it fly and
> > have it be fairly robust.
> >
> > With that, maybe there is no reason left to have separate pXXp_get() vs.
> > pXXp_get_once(). TBD :)
> Yeah, I was reviewing that series earlier today. I've not looked deeply, but it
> seems there are still a lot of cases where (mostly) pmd is getting dereferenced
> directly. To complete the conversion, direct dereferences need to be converted
> into an API. I've been thinking if there should be a dereference macro or we
> must always use pmdp_get() even though it ensures ordering. It may add excessive
> ordering in some functions if pmdp_get() is getting called multiple times. But
> storing its output in a tmp variable would solve this.
>
> Do you agree with converting all direct dereferences into pXXp_get()?
For the clarity (e.g. on the PTE level) is it goint to be converted to?
pte_t ptep_get(hw_pte_t *ptep);
pte_t set_pte(hw_pte_t *ptep, pte_t pte);
While variables on stack are still may be dereferenced directly via pte_t*?
What about unlinked/temporary page tables in memory?
> > [1] https://lore.kernel.org/all/08ecabe9-0664-4aea-82fb-f9cb1739f762@kernel.org/
> >
> > [...]
> >
> >>>
> >>> I'm still not sure about the _once() really, and if we need that right now. We
> >>> survived without is so far, why do we need it now?
> >> The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
> >> dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
> >> discuss it later sometime again later.
> >
> > Sounds good.
>
> I've tried to do conversions already. Converting by call hierarchy wise is very
> difficult and error prune.
>
> Converting component by component (such as page walk, huge page) is also difficult
> as code is tangled. Some helper which is getting used in one component is also used
> in another component.
>
> I see the following way forward:
> * Add the new type
> * Identify which functions need explicitly pointer to a stack variable. These
> must not be converted. These variables must be renamed to a common name. For
> pte_t pointers on stack some functions already use ptentp, which is unique name
> if we look at generic code. So ptentp would be used for all such variables.
> * One commit per controversial change would be done at this point. We need new
> separate function for stack types. Also we can do more renaming to a name which
> will not be converted.
> * Run Coccinelle script directory-by-directory which would ignore converting any
> ptentp (and similarly for other types). Coccinelle doesn't converts in some case
> (pte_t *a. *b) which can be done by hand at this point.
> * Update any remaining functions
What is the approach to STRICT_MM_TYPECHECKS?
We would like to keep it, and I guess some other architectures too.
> --
> Thanks,
> Usama
Thanks!
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-21 12:40 ` Alexander Gordeev
@ 2026-07-23 8:21 ` Muhammad Usama Anjum
2026-07-23 16:38 ` David Hildenbrand (Arm)
2026-07-24 6:47 ` Alexander Gordeev
0 siblings, 2 replies; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-07-23 8:21 UTC (permalink / raw)
To: Alexander Gordeev
Cc: usama.anjum, David Hildenbrand (Arm), Zi Yan, Pedro Falcato,
Ryan Roberts, Lorenzo Stoakes, linux-mm, linux-arm-kernel,
linux-kernel, Andrew Morton, Liam R. Howlett, Mike Rapoport,
Anshuman Khandual, Catalin Marinas, Will Deacon, Samuel Holland,
linux-s390
Hi Alexander,
Thank you for reviewing.
On 21/07/2026 1:40 pm, Alexander Gordeev wrote:
> On Wed, Jul 15, 2026 at 05:15:36PM +0100, Muhammad Usama Anjum wrote:
>> Hi,
>>
>> [Moved some already involved people to To. So they can help with the plan
>> details mentioned below.]
>>
>> On 07/07/2026 2:17 pm, David Hildenbrand (Arm) wrote:
>>> [...]
>>>
>>>>>
>>>>> typedef struct {
>>>>> pte_t __pte;
>>>>> } hw_pte_t;
>>>>>
>>>>> And then simply use
>>>>>
>>>>> hw_pte_t *hptep;
>>>> Make sense. So you have suggested to just hide put pte_t inside a structure
>>>> instead of complex structure of pointer. I've tried to implement and it reduces
>>>> churn enormously.
>>>
>>> Right. And for most architectures we can probable leave both types be the same
>>> under the hood.
>>>
>>> So we'd only have to convert common code first, and can then e.g., look into
>>> making architectures that care about the difference (e.g., arm64) actually have
>>> it be two separate types.
>> It makes a lot of sense.
>>
>> Let's even divide the series into more parts as there are several places where
>> conversion is controversial. (Xi Yan had mentioned one example earlier in this
>> thread.) Most of those controversial conversions are pmd related. I propose
>> that we convert pte_t first, then pmd_t and others. It'll keep the number of
>> patches manageable and easier to review.
>>
>> I think wider agreement for this approach will be very helpful before I post the
>> actual code.
>>
>>>
>>> Just an idea to further reduce the churn and limit it only to core code (because
>>> I saw some very ugly stuff in some arch code that would make such a conversion
>>> harder).
>>>
>>> [...]
>>>
>>>>> Why do we need this and what would we use it for?
>>>> The idea was that there should be two different functions to read value. Let's
>>>> leave this out of the first initial series. It is complicating the original
>>>> proposal.
>>>
>>> Right, let's leave that out for now. I'm currently working with Levi on an
>>> approach that tries to avoid the overhead due to READ_ONCE with folded page
>>> tables. [1]
>> So you are referring to page folding improvements. I also stumbled upon those
>> while doing a dirty implementation.
>>
>>>
>>> We're still struggling with some bits, but looks like we can make it fly and
>>> have it be fairly robust.
>>>
>>> With that, maybe there is no reason left to have separate pXXp_get() vs.
>>> pXXp_get_once(). TBD :)
>> Yeah, I was reviewing that series earlier today. I've not looked deeply, but it
>> seems there are still a lot of cases where (mostly) pmd is getting dereferenced
>> directly. To complete the conversion, direct dereferences need to be converted
>> into an API. I've been thinking if there should be a dereference macro or we
>> must always use pmdp_get() even though it ensures ordering. It may add excessive
>> ordering in some functions if pmdp_get() is getting called multiple times. But
>> storing its output in a tmp variable would solve this.
>>
>> Do you agree with converting all direct dereferences into pXXp_get()?
>
> For the clarity (e.g. on the PTE level) is it goint to be converted to?
>
> pte_t ptep_get(hw_pte_t *ptep);
Yes, that's correct.
> pte_t set_pte(hw_pte_t *ptep, pte_t pte);
Yeah, probably it has void type:
void set_pte(hw_pte_t *ptep, pte_t pte);
>
> While variables on stack are still may be dereferenced directly via pte_t*?
Yes. The conversion would force us to never directly dereference a hardware type.
>
> What about unlinked/temporary page tables in memory?
I've thought about it multiple times and it is best to represent using hw_p*_t
type. Even though they aren't installed or live, but it makes more sense to use
hardware type as they may get installed soon.
The difference between representing stack type with pte_t and unlinked/temporary
page table with hw_pte_t is that unlinked/temporary page tables are complete tables
and not just some copied value.
>
>>> [1] https://lore.kernel.org/all/08ecabe9-0664-4aea-82fb-f9cb1739f762@kernel.org/
>>>
>>> [...]
>>>
>>>>>
>>>>> I'm still not sure about the _once() really, and if we need that right now. We
>>>>> survived without is so far, why do we need it now?
>>>> The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
>>>> dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
>>>> discuss it later sometime again later.
>>>
>
>>> Sounds good.
>>
>> I've tried to do conversions already. Converting by call hierarchy wise is very
>> difficult and error prune.
>>
>> Converting component by component (such as page walk, huge page) is also difficult
>> as code is tangled. Some helper which is getting used in one component is also used
>> in another component.
>>
>> I see the following way forward:
>> * Add the new type
>> * Identify which functions need explicitly pointer to a stack variable. These
>> must not be converted. These variables must be renamed to a common name. For
>> pte_t pointers on stack some functions already use ptentp, which is unique name
>> if we look at generic code. So ptentp would be used for all such variables.
>> * One commit per controversial change would be done at this point. We need new
>> separate function for stack types. Also we can do more renaming to a name which
>> will not be converted.
>> * Run Coccinelle script directory-by-directory which would ignore converting any
>> ptentp (and similarly for other types). Coccinelle doesn't converts in some case
>> (pte_t *a. *b) which can be done by hand at this point.
>> * Update any remaining functions
>
> What is the approach to STRICT_MM_TYPECHECKS?
I've tested after converting couple of arches, it doesn't
break STRICT_MM_TYPECHECKS. I intend to keep STRICT_MM_TYPECHECKS working.
But once the architectures which uses STRICT_MM_TYPECHECKS are converted,
we don't need STRICT_MM_TYPECHECKS anymore as those checks would be enforced
by the conversion itself. Thinking out loud:
Normally:
typedef pteval_t pte_t;
In case of STRICT_MM_TYPECHECKS:
typedef struct { pteval_t pte; } pte_t;
After introducing type conversions:
Normally:
typedef pteval_t pte_t;
typedef struct {pte_t __pte;} hw_pte_t;
In case of STRICT_MM_TYPECHECKS:
typedef struct { pteval_t pte; } pte_t;
typedef struct { pte_t __pte;} hw_pte_t;
So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
around. Please correct me if I'm wrong.
This brings another thing in my mind that in ideal world we would just
turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
and separate stack and hardware types.
>
> We would like to keep it, and I guess some other architectures too.
David had summarized it well. We'll convert generic code to use hw_p*_t
types which would be typedef to p*_t for those architectures which don't
care about. But if an architecture wants to interpret these types
differently or want to make sure the type is enforced and not directly
dereferenced, they need to convert the arch code a well. But it can be
done slowly.
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-23 8:21 ` Muhammad Usama Anjum
@ 2026-07-23 16:38 ` David Hildenbrand (Arm)
2026-07-23 17:01 ` Muhammad Usama Anjum
2026-07-24 6:47 ` Alexander Gordeev
1 sibling, 1 reply; 18+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-23 16:38 UTC (permalink / raw)
To: Muhammad Usama Anjum, Alexander Gordeev
Cc: Zi Yan, Pedro Falcato, Ryan Roberts, Lorenzo Stoakes, linux-mm,
linux-arm-kernel, linux-kernel, Andrew Morton, Liam R. Howlett,
Mike Rapoport, Anshuman Khandual, Catalin Marinas, Will Deacon,
Samuel Holland, linux-s390
> So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
> around. Please correct me if I'm wrong.
>
> This brings another thing in my mind that in ideal world we would just
> turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
> with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
> meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
> and separate stack and hardware types.
I think STRICT_MM_TYPECHECKS is also to avoid catching when passing a pte_t into
a function that consumes a pmd_t, and vice versa.
STRICT_MM_TYPECHECKS makes the compiler generate worse code today, which is why
we don't enable it always.
>
>>
>> We would like to keep it, and I guess some other architectures too.
> David had summarized it well. We'll convert generic code to use hw_p*_t
> types which would be typedef to p*_t for those architectures which don't
> care about. But if an architecture wants to interpret these types
> differently or want to make sure the type is enforced and not directly
> dereferenced, they need to convert the arch code a well. But it can be
> done slowly.
I think what Alexander meant is: they want to keep STRICT_MM_TYPECHECKS (or
something that achieves something similar :) ). So as long as that keeps on
working, all good :)
--
Cheers,
David
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-23 16:38 ` David Hildenbrand (Arm)
@ 2026-07-23 17:01 ` Muhammad Usama Anjum
2026-07-24 9:30 ` Pedro Falcato
0 siblings, 1 reply; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-07-23 17:01 UTC (permalink / raw)
To: David Hildenbrand (Arm), Alexander Gordeev
Cc: usama.anjum, Zi Yan, Pedro Falcato, Ryan Roberts, Lorenzo Stoakes,
linux-mm, linux-arm-kernel, linux-kernel, Andrew Morton,
Liam R. Howlett, Mike Rapoport, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-s390
On 23/07/2026 5:38 pm, David Hildenbrand (Arm) wrote:
>
>> So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
>> around. Please correct me if I'm wrong.
>>
>> This brings another thing in my mind that in ideal world we would just
>> turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
>> with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
>> meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
>> and separate stack and hardware types.
>
> I think STRICT_MM_TYPECHECKS is also to avoid catching when passing a pte_t into
> a function that consumes a pmd_t, and vice versa.
>
> STRICT_MM_TYPECHECKS makes the compiler generate worse code today, which is why
> we don't enable it always.
>
>>
>>>
>>> We would like to keep it, and I guess some other architectures too.
>> David had summarized it well. We'll convert generic code to use hw_p*_t
>> types which would be typedef to p*_t for those architectures which don't
>> care about. But if an architecture wants to interpret these types
>> differently or want to make sure the type is enforced and not directly
>> dereferenced, they need to convert the arch code a well. But it can be
>> done slowly.
>
> I think what Alexander meant is: they want to keep STRICT_MM_TYPECHECKS (or
> something that achieves something similar :) ). So as long as that keeps on
> working, all good :)
Thank you for clarifying.
It has been a month since I started this discussion. We don't have any
disagreement on it. Should I proceed to post first part patch series considering
most people must already have viewed these emails and are on-board with it?
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-23 8:21 ` Muhammad Usama Anjum
2026-07-23 16:38 ` David Hildenbrand (Arm)
@ 2026-07-24 6:47 ` Alexander Gordeev
1 sibling, 0 replies; 18+ messages in thread
From: Alexander Gordeev @ 2026-07-24 6:47 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: David Hildenbrand (Arm), Zi Yan, Pedro Falcato, Ryan Roberts,
Lorenzo Stoakes, linux-mm, linux-arm-kernel, linux-kernel,
Andrew Morton, Liam R. Howlett, Mike Rapoport, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-s390
On Thu, Jul 23, 2026 at 09:21:32AM +0100, Muhammad Usama Anjum wrote:
> Hi Alexander,
>
> Thank you for reviewing.
>
> On 21/07/2026 1:40 pm, Alexander Gordeev wrote:
> > On Wed, Jul 15, 2026 at 05:15:36PM +0100, Muhammad Usama Anjum wrote:
> >> Hi,
> >>
> >> [Moved some already involved people to To. So they can help with the plan
> >> details mentioned below.]
> >>
> >> On 07/07/2026 2:17 pm, David Hildenbrand (Arm) wrote:
> >>> [...]
> >>>
> >>>>>
> >>>>> typedef struct {
> >>>>> pte_t __pte;
> >>>>> } hw_pte_t;
> >>>>>
> >>>>> And then simply use
> >>>>>
> >>>>> hw_pte_t *hptep;
> >>>> Make sense. So you have suggested to just hide put pte_t inside a structure
> >>>> instead of complex structure of pointer. I've tried to implement and it reduces
> >>>> churn enormously.
> >>>
> >>> Right. And for most architectures we can probable leave both types be the same
> >>> under the hood.
> >>>
> >>> So we'd only have to convert common code first, and can then e.g., look into
> >>> making architectures that care about the difference (e.g., arm64) actually have
> >>> it be two separate types.
> >> It makes a lot of sense.
> >>
> >> Let's even divide the series into more parts as there are several places where
> >> conversion is controversial. (Xi Yan had mentioned one example earlier in this
> >> thread.) Most of those controversial conversions are pmd related. I propose
> >> that we convert pte_t first, then pmd_t and others. It'll keep the number of
> >> patches manageable and easier to review.
> >>
> >> I think wider agreement for this approach will be very helpful before I post the
> >> actual code.
> >>
> >>>
> >>> Just an idea to further reduce the churn and limit it only to core code (because
> >>> I saw some very ugly stuff in some arch code that would make such a conversion
> >>> harder).
> >>>
> >>> [...]
> >>>
> >>>>> Why do we need this and what would we use it for?
> >>>> The idea was that there should be two different functions to read value. Let's
> >>>> leave this out of the first initial series. It is complicating the original
> >>>> proposal.
> >>>
> >>> Right, let's leave that out for now. I'm currently working with Levi on an
> >>> approach that tries to avoid the overhead due to READ_ONCE with folded page
> >>> tables. [1]
> >> So you are referring to page folding improvements. I also stumbled upon those
> >> while doing a dirty implementation.
> >>
> >>>
> >>> We're still struggling with some bits, but looks like we can make it fly and
> >>> have it be fairly robust.
> >>>
> >>> With that, maybe there is no reason left to have separate pXXp_get() vs.
> >>> pXXp_get_once(). TBD :)
> >> Yeah, I was reviewing that series earlier today. I've not looked deeply, but it
> >> seems there are still a lot of cases where (mostly) pmd is getting dereferenced
> >> directly. To complete the conversion, direct dereferences need to be converted
> >> into an API. I've been thinking if there should be a dereference macro or we
> >> must always use pmdp_get() even though it ensures ordering. It may add excessive
> >> ordering in some functions if pmdp_get() is getting called multiple times. But
> >> storing its output in a tmp variable would solve this.
> >>
> >> Do you agree with converting all direct dereferences into pXXp_get()?
> >
> > For the clarity (e.g. on the PTE level) is it goint to be converted to?
> >
> > pte_t ptep_get(hw_pte_t *ptep);
> Yes, that's correct.
>
> > pte_t set_pte(hw_pte_t *ptep, pte_t pte);
> Yeah, probably it has void type:
> void set_pte(hw_pte_t *ptep, pte_t pte);
>
> >
> > While variables on stack are still may be dereferenced directly via pte_t*?
> Yes. The conversion would force us to never directly dereference a hardware type.
>
> >
> > What about unlinked/temporary page tables in memory?
> I've thought about it multiple times and it is best to represent using hw_p*_t
> type. Even though they aren't installed or live, but it makes more sense to use
> hardware type as they may get installed soon.
My concern is in the long run the dedicated hw_pte_t APIs may want to do something
special with a hw_pXX_t pointers: accounting, HW resources allocation, tracking,
link a shadow, whatever. Some of those might be wrong when applied against a
temporary copy, even though that copy constitutes a formatted page table in memory.
E.g. right now [1] has the following ptep_get() implementation:
#define ptep_get ptep_get
static inline pte_t ptep_get(pte_t *ptep)
{
pte_t res;
if (!is_lazy_mmu_active() || !__lazy_mmu_ptep_get(ptep, &res))
res = __ptep_get(ptep);
return res;
}
Right now it would not hurt to get called against an unlinked hw_pte_t,
but it is certainly suboptimal.
> The difference between representing stack type with pte_t and unlinked/temporary
> page table with hw_pte_t is that unlinked/temporary page tables are complete tables
> and not just some copied value.
Well, in the past we had linked lists of page tables, which could well
be handled using direct dereferences even after this rework (assuming we
did not removed those lists).
Sorry for bringing up the classification question from your original
message again:
- "a pointer to a live entry in the hardware page table, or
- "the pointer points into real page-table memory and that table is complete,
whether or not it's linked in yet"
...but the semantics of the former still looks to me stronger than one of
the latter. I am afraid this question is going to pop up time and again.
1. https://lore.kernel.org/linux-s390/71acca838bd3c5bb690ccb4a36313a889a48f383.1784121418.git.agordeev@linux.ibm.com/
> >>> [1] https://lore.kernel.org/all/08ecabe9-0664-4aea-82fb-f9cb1739f762@kernel.org/
> >>>
> >>> [...]
> >>>
> >>>>>
> >>>>> I'm still not sure about the _once() really, and if we need that right now. We
> >>>>> survived without is so far, why do we need it now?
> >>>> The idea is to convert all current pXXp_get() to pXXp_get_once() and convert raw
> >>>> dereference to pXXp_get(). Let's keep this idea separate for the other work. Let's
> >>>> discuss it later sometime again later.
> >>>
> >
> >>> Sounds good.
> >>
> >> I've tried to do conversions already. Converting by call hierarchy wise is very
> >> difficult and error prune.
> >>
> >> Converting component by component (such as page walk, huge page) is also difficult
> >> as code is tangled. Some helper which is getting used in one component is also used
> >> in another component.
> >>
> >> I see the following way forward:
> >> * Add the new type
> >> * Identify which functions need explicitly pointer to a stack variable. These
> >> must not be converted. These variables must be renamed to a common name. For
> >> pte_t pointers on stack some functions already use ptentp, which is unique name
> >> if we look at generic code. So ptentp would be used for all such variables.
> >> * One commit per controversial change would be done at this point. We need new
> >> separate function for stack types. Also we can do more renaming to a name which
> >> will not be converted.
> >> * Run Coccinelle script directory-by-directory which would ignore converting any
> >> ptentp (and similarly for other types). Coccinelle doesn't converts in some case
> >> (pte_t *a. *b) which can be done by hand at this point.
> >> * Update any remaining functions
> >
> > What is the approach to STRICT_MM_TYPECHECKS?
> I've tested after converting couple of arches, it doesn't
> break STRICT_MM_TYPECHECKS. I intend to keep STRICT_MM_TYPECHECKS working.
> But once the architectures which uses STRICT_MM_TYPECHECKS are converted,
> we don't need STRICT_MM_TYPECHECKS anymore as those checks would be enforced
> by the conversion itself. Thinking out loud:
>
> Normally:
> typedef pteval_t pte_t;
>
> In case of STRICT_MM_TYPECHECKS:
> typedef struct { pteval_t pte; } pte_t;
>
> After introducing type conversions:
> Normally:
> typedef pteval_t pte_t;
> typedef struct {pte_t __pte;} hw_pte_t;
>
> In case of STRICT_MM_TYPECHECKS:
> typedef struct { pteval_t pte; } pte_t;
> typedef struct { pte_t __pte;} hw_pte_t;
>
> So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
> around. Please correct me if I'm wrong.
s390 ABI has an unfortunate quirk so that a struct return value
is passed via memory (as opposed to via registers). To avoid that
we turn on STRICT_MM_TYPECHECKS for debug kernels only like this:
#ifdef STRICT_MM_TYPECHECKS
typedef struct { unsigned long pte; } pte_t;
#else /* STRICT_MM_TYPECHECKS */
typedef unsigned long pte_t;
#endif /* STRICT_MM_TYPECHECKS */
So if possible we would like to keep STRICT_MM_TYPECHECKS for performance
reasons.
> This brings another thing in my mind that in ideal world we would just
> turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
> with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
> meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
> and separate stack and hardware types.
>
> > We would like to keep it, and I guess some other architectures too.
> David had summarized it well. We'll convert generic code to use hw_p*_t
> types which would be typedef to p*_t for those architectures which don't
> care about. But if an architecture wants to interpret these types
> differently or want to make sure the type is enforced and not directly
> dereferenced, they need to convert the arch code a well. But it can be
> done slowly.
I am bit lost here, but I think STRICT_MM_TYPECHECKS per se could be
reworked to address the s390 quirk above indeed.
Looking forward to see the patches ;)
> --
> Thanks,
> Usama
Thanks!
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-23 17:01 ` Muhammad Usama Anjum
@ 2026-07-24 9:30 ` Pedro Falcato
2026-07-24 10:34 ` Muhammad Usama Anjum
0 siblings, 1 reply; 18+ messages in thread
From: Pedro Falcato @ 2026-07-24 9:30 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: David Hildenbrand (Arm), Alexander Gordeev, Zi Yan, Ryan Roberts,
Lorenzo Stoakes, linux-mm, linux-arm-kernel, linux-kernel,
Andrew Morton, Liam R. Howlett, Mike Rapoport, Anshuman Khandual,
Catalin Marinas, Will Deacon, Samuel Holland, linux-s390
On Thu, Jul 23, 2026 at 06:01:49PM +0100, Muhammad Usama Anjum wrote:
> On 23/07/2026 5:38 pm, David Hildenbrand (Arm) wrote:
> >
> >> So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
> >> around. Please correct me if I'm wrong.
> >>
> >> This brings another thing in my mind that in ideal world we would just
> >> turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
> >> with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
> >> meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
> >> and separate stack and hardware types.
> >
> > I think STRICT_MM_TYPECHECKS is also to avoid catching when passing a pte_t into
> > a function that consumes a pmd_t, and vice versa.
> >
> > STRICT_MM_TYPECHECKS makes the compiler generate worse code today, which is why
> > we don't enable it always.
> >
> >>
> >>>
> >>> We would like to keep it, and I guess some other architectures too.
> >> David had summarized it well. We'll convert generic code to use hw_p*_t
> >> types which would be typedef to p*_t for those architectures which don't
> >> care about. But if an architecture wants to interpret these types
> >> differently or want to make sure the type is enforced and not directly
> >> dereferenced, they need to convert the arch code a well. But it can be
> >> done slowly.
> >
> > I think what Alexander meant is: they want to keep STRICT_MM_TYPECHECKS (or
> > something that achieves something similar :) ). So as long as that keeps on
> > working, all good :)
> Thank you for clarifying.
>
> It has been a month since I started this discussion. We don't have any
> disagreement on it. Should I proceed to post first part patch series considering
> most people must already have viewed these emails and are on-board with it?
Besides the vague disagreement I have (about whether this is worth it or
not), I have an actual objection: I've been doing some constifying of pte_t*
for various reasons lately, and something that just just came up is how
hw_ptep will _not_ work with const, unless you do something like
const_hw_ptep, in which case welcome to Win32 programming or something :|
(I'm assuming the idea still is typedef struct { pte_t *pte; } hw_ptep;)
Have you tried sparse instead?
--
Pedro
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: mm: opaque hardware page-table entry handles
2026-07-24 9:30 ` Pedro Falcato
@ 2026-07-24 10:34 ` Muhammad Usama Anjum
0 siblings, 0 replies; 18+ messages in thread
From: Muhammad Usama Anjum @ 2026-07-24 10:34 UTC (permalink / raw)
To: Pedro Falcato
Cc: usama.anjum, David Hildenbrand (Arm), Alexander Gordeev, Zi Yan,
Ryan Roberts, Lorenzo Stoakes, linux-mm, linux-arm-kernel,
linux-kernel, Andrew Morton, Liam R. Howlett, Mike Rapoport,
Anshuman Khandual, Catalin Marinas, Will Deacon, Samuel Holland,
linux-s390
On 24/07/2026 10:30 am, Pedro Falcato wrote:
> On Thu, Jul 23, 2026 at 06:01:49PM +0100, Muhammad Usama Anjum wrote:
>> On 23/07/2026 5:38 pm, David Hildenbrand (Arm) wrote:
>>>
>>>> So after the conversion, it doesn't makes sense to keep STRICT_MM_TYPECHECKS
>>>> around. Please correct me if I'm wrong.
>>>>
>>>> This brings another thing in my mind that in ideal world we would just
>>>> turn STRICT_MM_TYPECHECKS on for all arches all the time. But the problem
>>>> with it is that STRICT_MM_TYPECHECKS defines pte_t which will stay double
>>>> meaning still. So we want sort of STRICT_MM_TYPECHECKS with different name
>>>> and separate stack and hardware types.
>>>
>>> I think STRICT_MM_TYPECHECKS is also to avoid catching when passing a pte_t into
>>> a function that consumes a pmd_t, and vice versa.
>>>
>>> STRICT_MM_TYPECHECKS makes the compiler generate worse code today, which is why
>>> we don't enable it always.
>>>
>>>>
>>>>>
>>>>> We would like to keep it, and I guess some other architectures too.
>>>> David had summarized it well. We'll convert generic code to use hw_p*_t
>>>> types which would be typedef to p*_t for those architectures which don't
>>>> care about. But if an architecture wants to interpret these types
>>>> differently or want to make sure the type is enforced and not directly
>>>> dereferenced, they need to convert the arch code a well. But it can be
>>>> done slowly.
>>>
>>> I think what Alexander meant is: they want to keep STRICT_MM_TYPECHECKS (or
>>> something that achieves something similar :) ). So as long as that keeps on
>>> working, all good :)
>> Thank you for clarifying.
>>
>> It has been a month since I started this discussion. We don't have any
>> disagreement on it. Should I proceed to post first part patch series considering
>> most people must already have viewed these emails and are on-board with it?
>
> Besides the vague disagreement I have (about whether this is worth it or
> not), I have an actual objection: I've been doing some constifying of pte_t*
> for various reasons lately, and something that just just came up is how
> hw_ptep will _not_ work with const, unless you do something like
> const_hw_ptep, in which case welcome to Win32 programming or something :|
>
> (I'm assuming the idea still is typedef struct { pte_t *pte; } hw_ptep;)
We have moved on from this as it was very disruptive. Now we envision the
following:
typedef struct {pte_t __pte;} hw_pte_t;
With this, const wouldn't be a problem.
>
> Have you tried sparse instead?
We want to ensure safety during compile time. Without going into more detail,
more features would be build on top of this type conversion.
--
Thanks,
Usama
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-07-24 10:36 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 14:09 mm: opaque hardware page-table entry handles Usama Anjum
2026-06-24 15:52 ` Zi Yan
2026-06-24 22:39 ` Muhammad Usama Anjum
2026-06-24 19:25 ` Pedro Falcato
2026-06-25 10:50 ` Muhammad Usama Anjum
2026-06-25 11:08 ` Pedro Falcato
2026-06-25 12:15 ` Muhammad Usama Anjum
2026-07-01 20:56 ` David Hildenbrand (Arm)
2026-07-06 12:52 ` Muhammad Usama Anjum
2026-07-07 13:17 ` David Hildenbrand (Arm)
2026-07-15 16:15 ` Muhammad Usama Anjum
2026-07-21 12:40 ` Alexander Gordeev
2026-07-23 8:21 ` Muhammad Usama Anjum
2026-07-23 16:38 ` David Hildenbrand (Arm)
2026-07-23 17:01 ` Muhammad Usama Anjum
2026-07-24 9:30 ` Pedro Falcato
2026-07-24 10:34 ` Muhammad Usama Anjum
2026-07-24 6:47 ` Alexander Gordeev
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.