Re: [PATCH 3/6] arm64: convert between HW PTEs and SW PTE values
From: Muhammad Usama Anjum
Date: Mon Sep 21 2026 - 06:33:17 EST
On 21/09/2026 9:26 am, Ryan Roberts wrote:
> On 14/09/2026 14:51, Muhammad Usama Anjum wrote:
>> __ptep_get() returns a SW PTE value, and __set_pte_nosync() accepts one.
>> When HW PTEs use a distinct hw_pte_t, directly reading or writing *ptep
>> as a SW PTE value no longer satisfies those interfaces.
>>
>> Use __pte_from_hw after READ_ONCE() to obtain a SW PTE value and add
>> __hw_pte before WRITE_ONCE() to form an HW PTE.
>>
>> Define __hw_pte for both the wrapper and alias configurations so the
>> same accessor code works in either case.
>>
>> Signed-off-by: Muhammad Usama Anjum <usama.anjum@xxxxxxx>
>> ---
>> arch/arm64/include/asm/pgtable.h | 4 ++--
>> include/linux/pgtable_types.h | 2 ++
>> 2 files changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index 4768ec59de555..67c4a6179e154 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -360,7 +360,7 @@ static inline pte_t pte_clear_uffd(pte_t pte)
>>
>> static inline void __set_pte_nosync(hw_pte_t *ptep, pte_t pte)
>> {
>> - WRITE_ONCE(*ptep, pte);
>> + WRITE_ONCE(*ptep, __hw_pte(pte));
>
> Would this work as an alternative? It removes the need for the new __hw_pte()
> helper. In future, converting a pte_t to a hw_pte_t won't be trivial so having a
> generic helper for it doesn't feel like a good fit.
>
> WRITE_ONCE(hw_pte_val(*ptep), pte_val(pte));
Yeah, this would work. It removes the need for the generic conversion
helpers which is even better.
>
> In general, I wonder if we should avoid defining both the __hw_pte() and
> __pte_from_hw() generic helpers. Conversion between sw and hw representations
> will become arch-specific in future and for arm64 that conversion will need
> extra information so it's can't just specialize these interfaces as they are.
Agreed.
>
>> }
>>
>> static inline void __set_pte_complete(pte_t pte)
>> @@ -381,7 +381,7 @@ static inline void __set_pte(hw_pte_t *ptep, pte_t pte)
>>
>> static inline pte_t __ptep_get(hw_pte_t *ptep)
>> {
>> - return READ_ONCE(*ptep);
>> + return __pte_from_hw(READ_ONCE(*ptep));
>
>
> ...Corresponds with:
>
> return __pte(READ_ONCE(hw_pte_val(*ptep)));
I'll update.
>
> Thanks,
> Ryan
>
>> }
>>
>> extern void __sync_icache_dcache(pte_t pteval);
>> diff --git a/include/linux/pgtable_types.h b/include/linux/pgtable_types.h
>> index ee4eace5c3e1c..b5862a16aa497 100644
>> --- a/include/linux/pgtable_types.h
>> +++ b/include/linux/pgtable_types.h
>> @@ -9,11 +9,13 @@
>> #ifdef CONFIG_ARCH_HAS_HW_PTE_T
>> typedef struct __hw_pte_t { pte_t __pte; } hw_pte_t;
>> #define __pte_from_hw(pte) ((pte).__pte)
>> +#define __hw_pte(pte) ((hw_pte_t) { (pte) })
>>
>> #define hw_pte_val(x) pte_val((x).__pte)
>> #else
>> #define hw_pte_t pte_t
>> #define __pte_from_hw(pte) (pte)
>> +#define __hw_pte(pte) (pte)
>>
>> #define hw_pte_val(x) pte_val(x)
>> #endif
>>
>
--
Thanks,
Usama