Re: [PATCH RFC v3 2/4] mm/pgtable: Make pfn_pte() filter out huge page attributes

Yin Tirui
2026-04-20T11:43:42Z

Hi Will,

On 4/20/2026 4:48 PM, Will Deacon wrote:
> On Sat, Feb 28, 2026 at 03:09:04PM +0800, Yin Tirui wrote:
>> A fundamental principle of page table type safety is that `pte_t` represents
>> the lowest level page table entry and should never carry huge page attributes.
>>
>> Currently, passing a pgprot with huge page bits (e.g., extracted via
>> pmd_pgprot()) into pfn_pte() creates a malformed PTE that retains the huge
>> attribute, leading to the necessity of the ugly `pte_clrhuge()` anti-pattern.
>>
>> Enforce type safety by making `pfn_pte()` inherently filter out huge page
>> attributes:
>> - On x86: Strip the `_PAGE_PSE` bit.
>> - On ARM64: Mask out the block descriptor bits in `PTE_TYPE_MASK` and
>> enforce the `PTE_TYPE_PAGE` format.
>> - On RISC-V: No changes required, as RISC-V leaf PMDs and PTEs share the
>> exact same hardware format and do not use a distinct huge bit.
>>
>> Signed-off-by: Yin Tirui <yintirui@huawei.com>
>> ---
>> arch/arm64/include/asm/pgtable.h | 4 +++-
>> arch/x86/include/asm/pgtable.h | 4 ++++
>> 2 files changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index b3e58735c49b..f2a7a40106d2 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -141,7 +141,9 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
>>
>> #define pte_pfn(pte) (__pte_to_phys(pte) >> PAGE_SHIFT)
>> #define pfn_pte(pfn,prot) \
>> - __pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
>> + __pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | \
>> + ((pgprot_val(prot) & ~(PTE_TYPE_MASK & ~PTE_VALID)) | \
>> + (PTE_TYPE_PAGE & ~PTE_VALID)))
> Why are you touching arch/arm64? We don't implement pte_clrhuge() afaict.
> What does this actually fix?

Originally, this patch aimed to ensure that pfn_pte() always returns a
PTE without any

huge page attributes by embedding the logic of pte_clrhuge() directly
into pfn_pte().

However, we found this approach doesn't work well on x86, so we've
abandoned this design.

Following Matthew Wilcox's suggestion, the current approach is instead
to have pmd_pgprot()

return a 4K–formatted pgprot_t (i.e., without huge page attributes), and
then explicitly add the

huge page attributes when constructing a PMD via pfn_pmd().

I've already implemented this in my recent commit:

https://github.com/torvalds/linux/commit/5b8ce6d33822dd7776432e03a08fe6d2dedac079

>
> Will

--
Yin Tirui