On 7/13/26 23:40, Dave Hansen wrote:
> On 7/13/26 14:17, David Hildenbrand (Arm) wrote:
>>> To me, the double READ_ONCE() is a non-issue.
>> To other arch maintainers, it is!
> 
> Ahh, so it seems like Christophe in ppc32 land was looking at this more
> like a regression that needed to get fixed.

Yes, exactly. :)

And I agree that it is something we should be optimizing.

> 
> Christophe, just out of curiosity, was this something that was causing
> you practical problems like measurable performance regressions, or was
> it really just insane code generation that seems unacceptably suboptimal?

I'd be curious about that as well. I mean, looking at the generated code
it's clear that it is suboptimal.


The solution space I see:


(1) Pass the result from e.g., pgdp_get() into p4d_get(), so it can just return 
    the value with folded p4ds.

That requires extreme amounts of churn in core-mm AFAIKS, so I don't see that 
as feasible.


(2) Rewrite folding code to make p4d_present() be a dummy instead of 
    pgd_present(), and make p4dp_get() return a dummy value.

... a lot of churn across architectures. I'm sure we'll learn soon why it was 
done 
ike the way it is today in the first place. Something interesting to look at,
certainly, but a bit of a stretch just to optimize reads.


(3) Make folded pgdp_get() use an ordinary read instead of a READ_ONCE / dummy.

I don't like that, because we couldn't catch easily if the value is then
actually used some old/new code.

If pgd_present() etc are supposed to ignore the value, I'd rather have a 
mechanism
that enforces that the values are actually ignore in pgd_offset() etc as well.


(4) What we do in this series, but instead of forbidding set_pgd(), make it 
only 
    complain when we are passing in a dummy value.

The expectation is that it would avoid touching most architecture code in patch
12 -> 27 and still prevent mistakes in the future.

@Yeoreum can you play with that and see what the end result would be?


The problem of how to handle ptdump effective_prot remains. Which is 
unfortunately an
x86 32-bit only problem ;) ... and effective_prot is essentially an x86-only 
thing.

There are various ways we could handle that, my preferred one would be

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index fb298e2191792..3d56e48fe4151 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -96,7 +96,7 @@ config X86
        select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
        select ARCH_HAS_PMEM_API                if X86_64
        select ARCH_HAS_PREEMPT_LAZY
-       select ARCH_HAS_PTDUMP
+       select ARCH_HAS_PTDUMP                  if X86_64
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_HW_PTE_YOUNG
        select ARCH_HAS_NONLEAF_PMD_YOUNG       if PGTABLE_LEVELS > 2


Another option would be to keep the behavior unchanged:


diff --git a/mm/ptdump.c b/mm/ptdump.c
index 5851096e6f656..ce2cf5e07ac0a 100644
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -39,6 +39,9 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr,
                return note_kasan_page_table(walk, addr);
 #endif
 
+       if (mm_p4d_folded(walk->mm))
+               return 0;
+
        if (st->effective_prot_pgd)
                st->effective_prot_pgd(st, val);
 
@@ -62,6 +65,13 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr,
                return note_kasan_page_table(walk, addr);
 #endif
 
+       if (mm_pud_folded(walk->mm))
+               return 0;
+
+       /* Simulate old behavior: all page table levels exist with folded 
values. */
+       if (mm_p4d_folded(walk->mm) && (st->effective_prot_pgd))
+               st->effective_prot_pgd(st, __pgd(p4d_val(val)));
+
        if (st->effective_prot_p4d)
                st->effective_prot_p4d(st, val);
 
@@ -85,6 +95,15 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr,
                return note_kasan_page_table(walk, addr);
 #endif
 
+       if (mm_pmd_folded(walk->mm))
+               return 0;
+
+       /* Simulate old behavior: all page table levels exist with folded 
values. */
+       if (mm_pud_folded(walk->mm) && st->effective_prot_pgd)
+               st->effective_prot_pgd(st, __pgd(pud_val(val)));
+       if (mm_p4d_folded(walk->mm) && st->effective_prot_p4d)
+               st->effective_prot_p4d(st, __p4d(pud_val(val)));
+
        if (st->effective_prot_pud)
                st->effective_prot_pud(st, val);
 
@@ -107,6 +126,14 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr,
                return note_kasan_page_table(walk, addr);
 #endif
 
+       /* Simulate old behavior: all page table levels exist with folded 
values. */
+       if (mm_pud_folded(walk->mm) && st->effective_prot_pgd)
+               st->effective_prot_pgd(st, __pgd(pmd_val(val)));
+       if (mm_p4d_folded(walk->mm) && st->effective_prot_p4d)
+               st->effective_prot_p4d(st, __p4d(pmd_val(val)));
+       if (mm_pmd_folded(walk->mm) && st->effective_prot_pud)
+               st->effective_prot_pud(st, __pud(pmd_val(val)));
+
        if (st->effective_prot_pmd)
                st->effective_prot_pmd(st, val);
        if (pmd_leaf(val)) {


Then there would be another option of making x86 simply remembering the first 
level it got called for.


-- 
Cheers,

David

Reply via email to