Re: [linus:master] [atomic] 80047d84ee: WARNING:at_include/linux/instrumented.h:#__split_huge_pmd_locked

From: Arnd Bergmann

Date: Tue Nov 03 2026 - 09:11:10 EST


On Tue, Nov 3, 2026, at 14:13, Arnd Bergmann wrote:
> On Tue, Nov 3, 2026, at 13:35, Sasha Levin wrote:
>>
>> 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:
>
> The question is how many of the other functions may be affected by the
> same bug. I see a variation of the same code in vmemmap_split_pmd(),
> and aligning the types is clearly the safer option here, especially
> given that most 32-bit architectures already align u64 all the time
> the same way that 64-bit ones do.

FWIW, I checked the other architectures that may be affected:

- 32-bit arm has transparent hugepages and a 64-bit pmd_t with lpae,
but that type has natural alignment, and pmd_populate is a
simple assignment.

- arc has transparent hugepages and a 32-bit pmd_t but a 64-bit
pte_t that is not naturally aligned. It probably should be
aligned, even though I don't see any actual bugs

- sh has a 64-bit pmd_t on sh4a CPUs that is not naturally
aligned and probably should be, but there are no transparent
hugepages.

All other 32-bit targets don't use transparent hugepages
or 64-bit pmd_t.

We probably only need to align p?d_t though, not p?dval_t.
How about the version below?

Arnd

diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index 9720fe6b2c24..af5303459d56 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -65,7 +65,7 @@ typedef struct {

typedef struct {
#ifdef CONFIG_ARC_HAS_PAE40
- unsigned long long pte;
+ unsigned long long pte __aligned(8);
#else
unsigned long pte;
#endif
diff --git a/arch/sh/include/asm/pgtable-3level.h b/arch/sh/include/asm/pgtable-3level.h
index d1ce73f3bd85..6d5e2e3248f2 100644
--- a/arch/sh/include/asm/pgtable-3level.h
+++ b/arch/sh/include/asm/pgtable-3level.h
@@ -33,7 +33,7 @@ typedef union {
unsigned long pmd_low;
unsigned long pmd_high;
};
- unsigned long long pmd;
+ unsigned long long pmd __aligned(8);
} pmd_t;
#define pmd_val(x) ((x).pmd)
#define __pmd(x) ((pmd_t) { .pmd = (x) } )
diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h
index 580b09bf6a45..061283293341 100644
--- a/arch/x86/include/asm/pgtable-3level_types.h
+++ b/arch/x86/include/asm/pgtable-3level_types.h
@@ -16,14 +16,14 @@ typedef union {
struct {
unsigned long pte_low, pte_high;
};
- pteval_t pte;
+ pteval_t pte __aligned(8);
} pte_t;

typedef union {
struct {
unsigned long pmd_low, pmd_high;
};
- pmdval_t pmd;
+ pmdval_t pmd __aligned(8);
} pmd_t;
#endif /* !__ASSEMBLER__ */

diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 2ec250ba467e..5c028b3f59c4 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -292,7 +292,7 @@ enum page_cache_mode {

typedef struct pgprot { pgprotval_t pgprot; } pgprot_t;

-typedef struct { pgdval_t pgd; } pgd_t;
+typedef struct { pgdval_t pgd __aligned(sizeof(pgdval_t)); } pgd_t;

static inline pgprot_t pgprot_nx(pgprot_t prot)
{