Re: [linus:master] [atomic] 80047d84ee: WARNING:at_include/linux/instrumented.h:#__split_huge_pmd_locked
From: Peter Zijlstra
Date: Tue Nov 03 2026 - 08:01:57 EST
On Tue, Nov 03, 2026 at 07:35:08AM -0500, Sasha Levin wrote:
> On Tue, Nov 03, 2026 at 01:26:47PM +0100, Peter Zijlstra wrote:
> > The below 'fixes' it, but the question is of course, WTF are we using an
> > on-stack pmd value for set_pmd().
>
> The split fills in the new PTE table before installing it, and uses a
> temporary pmd on the stack so pte_offset_map() can find the table:
>
> pgtable = pgtable_trans_huge_withdraw(mm, pmd);
> pmd_populate(mm, &_pmd, pgtable);
> pte = pte_offset_map(&_pmd, haddr);
>
> __split_huge_zero_page_pmd() does the same thing.
>
> I tried the typedef change. It works, but gcc ends up realigning the
> stack in a lot of pte/pmd code (126 more functions with Arnd's version
> in a small config, 204 with yours), including handle_mm_fault(). Just
> aligning the two locals seems simpler:
Does that matter though?
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index bd44d58e86845..b8faa6df9bb14 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -3132,7 +3132,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
> {
> struct mm_struct *mm = vma->vm_mm;
> pgtable_t pgtable;
> - pmd_t _pmd, old_pmd;
> + pmd_t _pmd __aligned(sizeof(pmd_t)), old_pmd;
> unsigned long addr;
> pte_t *pte;
> int i;
> @@ -3180,7 +3180,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
> struct folio *folio;
> struct page *page;
> pgtable_t pgtable;
> - pmd_t old_pmd, _pmd;
> + pmd_t old_pmd, _pmd __aligned(sizeof(pmd_t));
> bool soft_dirty, uffd_wp = false, young = false, write = false;
> bool anon_exclusive = false, dirty = false;
> unsigned long addr;
This will work; but it feels more fragile.