[RFC PATCH 10/34] x86: mm: carve out the generic compile-time folded pgtable case in effective_prot()
Yeoreum Yun
yeoreum.yun at arm.com
Thu Jul 16 01:47:43 PDT 2026
On Wed, Jul 15, 2026 at 11:44:51AM +0200, David Hildenbrand (Arm) wrote:
> On 7/14/26 19:58, Yeoreum Yun wrote:
> > On Tue, Jul 14, 2026 at 07:29:38PM +0200, David Hildenbrand (Arm) wrote:
> >> On 7/14/26 18:51, Yeoreum Yun wrote:
> >>>
> >>> Furthermore, the effective_prot() need to require to identify whether
> >>> it's the first pgtable to prevent the inheriting from dummy value.
> >>> So I think it seems to make a ptdump_pt_level_first() like:
> >>>
> >>> diff --git a/mm/ptdump.c b/mm/ptdump.c
> >>> index 973020000096c..2ec5700e4be5e 100644
> >>> --- a/mm/ptdump.c
> >>> +++ b/mm/ptdump.c
> >>> @@ -190,6 +190,23 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
> >>> st->note_page_flush(st);
> >>> }
> >>>
> >>> +bool pdtump_pt_level_first(struct mm_struct *mm, int level)
> >>> +{
> >>> + if (!mm || level > CONFIG_PGTABLE_LEVELS)
> >>> + return false;
> >>
> >> Do we actually ever get !mm ?
> >
> > Yes. for the case of s390 use mm anyway for folded check.
> That's not what I meant, let me clarify.
>
> I think in ptdump_walk_pgd() it is guaranteed that mm != NULL, so I am wondering
> why you are handling mm == NULL.
Agree. I'll remove it.
BTW, this helper is incorrect because it returns true even for folded
upper-level page tables. For example, if p4d is folded,
level 0 would still be treated as the first level.
So, it would better to the following:
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 2afa7a23340e9..4e545988953a0 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -27,6 +27,7 @@
*/
struct pg_state {
struct ptdump_state ptdump;
+ int first_level;
int level;
pgprotval_t current_prot;
pgprotval_t effective_prot;
@@ -254,7 +255,7 @@ static void effective_prot(struct ptdump_state *pt_st, int level, u64 val)
pgprotval_t prot = val & PTE_FLAGS_MASK;
pgprotval_t effective;
- if (level > 0) {
+ if (level > st->first_level) {
pgprotval_t higher_prot = st->prot_levels[level - 1];
effective = (higher_prot & prot & (_PAGE_USER | _PAGE_RW)) |
@@ -455,6 +456,8 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m,
.seq = m
};
+ st.first_level = ptdump_pt_level_first(mm);
+
ptdump_walk_pgd(&st.ptdump, mm, pgd);
if (!checkwx)
diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h
index 240bd3bff18dd..26fa624eac44e 100644
--- a/include/linux/ptdump.h
+++ b/include/linux/ptdump.h
@@ -29,6 +29,7 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m,
struct mm_struct *mm, pgd_t *pgd,
bool checkwx, bool dmesg);
void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd);
+int ptdump_pt_level_first(struct mm_struct *mm);
bool ptdump_check_wx(void);
static inline void debug_checkwx(void)
diff --git a/mm/ptdump.c b/mm/ptdump.c
index 973020000096c..b1d06ac4c0555 100644
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -190,6 +190,17 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
st->note_page_flush(st);
}
+int ptdump_pt_level_first(struct mm_struct *mm)
+{
+ if (mm_pmd_folded(mm))
+ return 3;
+ if (mm_pud_folded(mm))
+ return 2;
+ if (mm_p4d_folded(mm))
+ return 1;
+ return 0;
+}
+
--
Sincerely,
Yeoreum Yun
More information about the kvm-riscv
mailing list