* [PATCH 1/3] ptdesc: Convert __page_flags to pt_flags
2025-09-08 17:10 [PATCH 0/3] Some ptdesc cleanups Matthew Wilcox (Oracle)
@ 2025-09-08 17:11 ` Matthew Wilcox (Oracle)
2025-09-08 18:57 ` David Hildenbrand
2025-09-08 17:11 ` [PATCH 2/3] ptdesc: Remove references to folios from __pagetable_ctor() and pagetable_dtor() Matthew Wilcox (Oracle)
2025-09-08 17:11 ` [PATCH 3/3] ptdesc: Remove ptdesc_to_virt() Matthew Wilcox (Oracle)
2 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-09-08 17:11 UTC (permalink / raw)
To: Andrew Morton; +Cc: Matthew Wilcox (Oracle), linux-mm, Vishal Moola
Use the new memdesc_flags_t type to show that these are the same
bits as page/folio/slab and thesefore have the zone/node/section
information in them. Remove a use of ptdesc_folio() by converting
pagetable_is_reserved() to use test_bit() directly.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
include/linux/mm.h | 7 ++++++-
include/linux/mm_types.h | 6 +++---
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 02fddbc38647..46eb2a7c4fb7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2902,6 +2902,11 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
}
#endif /* CONFIG_MMU */
+enum pt_flags {
+ PT_reserved = PG_reserved,
+ /* High bits are used for zone/node/section */
+};
+
static inline struct ptdesc *virt_to_ptdesc(const void *x)
{
return page_ptdesc(virt_to_page(x));
@@ -2919,7 +2924,7 @@ static inline void *ptdesc_address(const struct ptdesc *pt)
static inline bool pagetable_is_reserved(struct ptdesc *pt)
{
- return folio_test_reserved(ptdesc_folio(pt));
+ return test_bit(PT_reserved, &pt->pt_flags.f);
}
/**
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index f7047483dd60..d3566bed5817 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -522,7 +522,7 @@ FOLIO_MATCH(compound_head, _head_3);
/**
* struct ptdesc - Memory descriptor for page tables.
- * @__page_flags: Same as page flags. Powerpc only.
+ * @pt_flags: enum pt_flags plus zone/node/section.
* @pt_rcu_head: For freeing page table pages.
* @pt_list: List of used page tables. Used for s390 gmap shadow pages
* (which are not linked into the user page tables) and x86
@@ -544,7 +544,7 @@ FOLIO_MATCH(compound_head, _head_3);
* understanding of the issues.
*/
struct ptdesc {
- unsigned long __page_flags;
+ memdesc_flags_t pt_flags;
union {
struct rcu_head pt_rcu_head;
@@ -582,7 +582,7 @@ struct ptdesc {
#define TABLE_MATCH(pg, pt) \
static_assert(offsetof(struct page, pg) == offsetof(struct ptdesc, pt))
-TABLE_MATCH(flags, __page_flags);
+TABLE_MATCH(flags, pt_flags);
TABLE_MATCH(compound_head, pt_list);
TABLE_MATCH(compound_head, _pt_pad_1);
TABLE_MATCH(mapping, __page_mapping);
--
2.47.2
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 1/3] ptdesc: Convert __page_flags to pt_flags
2025-09-08 17:11 ` [PATCH 1/3] ptdesc: Convert __page_flags to pt_flags Matthew Wilcox (Oracle)
@ 2025-09-08 18:57 ` David Hildenbrand
0 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2025-09-08 18:57 UTC (permalink / raw)
To: Matthew Wilcox (Oracle), Andrew Morton; +Cc: linux-mm, Vishal Moola
On 08.09.25 19:11, Matthew Wilcox (Oracle) wrote:
> Use the new memdesc_flags_t type to show that these are the same
> bits as page/folio/slab and thesefore have the zone/node/section
> information in them. Remove a use of ptdesc_folio() by converting
> pagetable_is_reserved() to use test_bit() directly.
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
Acked-by: David Hildenbrand <david@redhat.com>
--
Cheers
David / dhildenb
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] ptdesc: Remove references to folios from __pagetable_ctor() and pagetable_dtor()
2025-09-08 17:10 [PATCH 0/3] Some ptdesc cleanups Matthew Wilcox (Oracle)
2025-09-08 17:11 ` [PATCH 1/3] ptdesc: Convert __page_flags to pt_flags Matthew Wilcox (Oracle)
@ 2025-09-08 17:11 ` Matthew Wilcox (Oracle)
2025-09-08 18:59 ` David Hildenbrand
2025-09-08 17:11 ` [PATCH 3/3] ptdesc: Remove ptdesc_to_virt() Matthew Wilcox (Oracle)
2 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-09-08 17:11 UTC (permalink / raw)
To: Andrew Morton; +Cc: Matthew Wilcox (Oracle), linux-mm, Vishal Moola
In preparation for splitting struct ptdesc from struct page and struct
folio, remove mentions of struct folio from these functions. Introduce
ptdesc_nr_pages() to avoid using lruvec_stat_add/sub_folio()
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
include/linux/mm.h | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 46eb2a7c4fb7..3a339bd7a2f9 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2065,9 +2065,9 @@ static inline long folio_nr_pages(const struct folio *folio)
* page. compound_nr() can be called on a tail page, and is defined to
* return 1 in that case.
*/
-static inline long compound_nr(struct page *page)
+static inline long compound_nr(const struct page *page)
{
- struct folio *folio = (struct folio *)page;
+ const struct folio *folio = (struct folio *)page;
if (!test_bit(PG_head, &folio->flags.f))
return 1;
@@ -3034,21 +3034,26 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
static inline void ptlock_free(struct ptdesc *ptdesc) {}
#endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
+static inline unsigned long ptdesc_nr_pages(const struct ptdesc *ptdesc)
+{
+ return compound_nr(ptdesc_page(ptdesc));
+}
+
static inline void __pagetable_ctor(struct ptdesc *ptdesc)
{
- struct folio *folio = ptdesc_folio(ptdesc);
+ pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags));
- __folio_set_pgtable(folio);
- lruvec_stat_add_folio(folio, NR_PAGETABLE);
+ __SetPageTable(ptdesc_page(ptdesc));
+ mod_node_page_state(pgdat, NR_PAGETABLE, ptdesc_nr_pages(ptdesc));
}
static inline void pagetable_dtor(struct ptdesc *ptdesc)
{
- struct folio *folio = ptdesc_folio(ptdesc);
+ pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags));
ptlock_free(ptdesc);
- __folio_clear_pgtable(folio);
- lruvec_stat_sub_folio(folio, NR_PAGETABLE);
+ __ClearPageTable(ptdesc_page(ptdesc));
+ mod_node_page_state(pgdat, NR_PAGETABLE, -ptdesc_nr_pages(ptdesc));
}
static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
--
2.47.2
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 3/3] ptdesc: Remove ptdesc_to_virt()
2025-09-08 17:10 [PATCH 0/3] Some ptdesc cleanups Matthew Wilcox (Oracle)
2025-09-08 17:11 ` [PATCH 1/3] ptdesc: Convert __page_flags to pt_flags Matthew Wilcox (Oracle)
2025-09-08 17:11 ` [PATCH 2/3] ptdesc: Remove references to folios from __pagetable_ctor() and pagetable_dtor() Matthew Wilcox (Oracle)
@ 2025-09-08 17:11 ` Matthew Wilcox (Oracle)
2025-09-08 19:00 ` David Hildenbrand
2 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-09-08 17:11 UTC (permalink / raw)
To: Andrew Morton; +Cc: Matthew Wilcox (Oracle), linux-mm, Vishal Moola
This has the same effect as ptdesc_address() so convert the callers to
use that and delete the function. Add kernel-doc for ptdesc_address().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
arch/arm/mm/mmu.c | 2 +-
arch/s390/mm/pgalloc.c | 6 +++---
include/linux/mm.h | 11 ++++++-----
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index edb7f56b7c91..8bac96e205ac 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -737,7 +737,7 @@ static void *__init late_alloc(unsigned long sz)
if (!ptdesc || !pagetable_pte_ctor(NULL, ptdesc))
BUG();
- return ptdesc_to_virt(ptdesc);
+ return ptdesc_address(ptdesc);
}
static pte_t * __init arm_pte_alloc(pmd_t *pmd, unsigned long addr,
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index d2f6f1f6d2fc..f56ee9aeac83 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -21,7 +21,7 @@ unsigned long *crst_table_alloc(struct mm_struct *mm)
if (!ptdesc)
return NULL;
- table = ptdesc_to_virt(ptdesc);
+ table = ptdesc_address(ptdesc);
__arch_set_page_dat(table, 1UL << CRST_ALLOC_ORDER);
return table;
}
@@ -119,7 +119,7 @@ struct ptdesc *page_table_alloc_pgste(struct mm_struct *mm)
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
if (ptdesc) {
- table = (u64 *)ptdesc_to_virt(ptdesc);
+ table = (u64 *)ptdesc_address(ptdesc);
__arch_set_page_dat(table, 1);
memset64(table, _PAGE_INVALID, PTRS_PER_PTE);
memset64(table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
@@ -146,7 +146,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
pagetable_free(ptdesc);
return NULL;
}
- table = ptdesc_to_virt(ptdesc);
+ table = ptdesc_address(ptdesc);
__arch_set_page_dat(table, 1);
memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE);
memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 3a339bd7a2f9..2c3b99f60297 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2912,11 +2912,12 @@ static inline struct ptdesc *virt_to_ptdesc(const void *x)
return page_ptdesc(virt_to_page(x));
}
-static inline void *ptdesc_to_virt(const struct ptdesc *pt)
-{
- return page_to_virt(ptdesc_page(pt));
-}
-
+/**
+ * ptdesc_address - Virtual address of page table.
+ * @pt: Page table descriptor.
+ *
+ * Return: The first byte of the page table described by @pt.
+ */
static inline void *ptdesc_address(const struct ptdesc *pt)
{
return folio_address(ptdesc_folio(pt));
--
2.47.2
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 3/3] ptdesc: Remove ptdesc_to_virt()
2025-09-08 17:11 ` [PATCH 3/3] ptdesc: Remove ptdesc_to_virt() Matthew Wilcox (Oracle)
@ 2025-09-08 19:00 ` David Hildenbrand
0 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2025-09-08 19:00 UTC (permalink / raw)
To: Matthew Wilcox (Oracle), Andrew Morton; +Cc: linux-mm, Vishal Moola
> -
> +/**
> + * ptdesc_address - Virtual address of page table.
> + * @pt: Page table descriptor.
> + *
> + * Return: The first byte of the page table described by @pt.
> + */
> static inline void *ptdesc_address(const struct ptdesc *pt)
> {
> return folio_address(ptdesc_folio(pt));
I assume you'll tackle the ptdesc_folio() stuff separately.
Acked-by: David Hildenbrand <david@redhat.com>
--
Cheers
David / dhildenb
^ permalink raw reply [flat|nested] 7+ messages in thread