Skip to contentSkip to conversation

mm/huge_memory: fix pgtable withdrawal for huge zero PMDs

PATCH In review Lance Yang 4 participants 13 messages Sep 13 – Sep 16

Subsystems (3)
lore
Share & tools
lore

Lance Yang

author reviewer
#0 lore raw

PATCH 1/1 mm/huge_memory: fix pgtable withdrawal for huge zero PMDs

From: Lance Yang <[email protected]>

has_deposited_pgtable() uses !vma_is_dax() to decide whether a huge zero PMD has a deposited PTE page table. That also accepts raw PFN mappings of huge_zero_pfn, although vmf_insert_pfn_pmd() does not deposit a page table on x86.

Zapping such a mapping would call pgtable_trans_huge_withdraw() without a corresponding deposit. With pmd_huge_pte(mm, pmd) == NULL, that causes a NULL pointer dereference.

Use vma_is_anonymous() for the huge zero PMD check. This matches how PTE page tables are allocated, deposited and moved.

- For anonymous page faults that install a huge zero PMD, do_huge_pmd_anonymous_page() allocates a PTE page table and set_huge_zero_folio() deposits it before installing the PMD.

- On fork, copy_huge_pmd() allocates and deposits a PTE page table when copying a huge zero PMD into an anonymous VMA.

- Raw PFN mappings use vmf_insert_pfn_pmd(), and DAX file holes use vmf_insert_folio_pmd() to map the huge zero folio. Both use insert_pmd(), which deposits a PTE page table only when arch_needs_pgtable_deposit() requires it.

- Moving an anonymous huge PMD preserves its deposited PTE page table. move_huge_pmd() transfers the deposit when necessary. For UFFD MOVE, both VMAs must be anonymous, and move_pages_huge_pmd() transfers the deposit as well.

Keep arch_needs_pgtable_deposit() first so architectures that require a deposited PTE page table still return true regardless of the VMA type.

Commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()") removed the vma_is_special_huge() check in zap_huge_pmd(). That check skipped the huge zero PMD deposit test for non-DAX VM_PFNMAP and VM_MIXEDMAP mappings. Removing it exposed these mappings to the incorrect !vma_is_dax() test.

Fixes d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()")
---
 mm/huge_memory.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
mm/huge_memory.c +3 -3
index 6895b38e4704..0ed997a97416 100644
@@ -2529,11 +2529,11 @@ static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval,
 		return true;
 
 	/*
-	 * Huge zero always deposited except for DAX which handles itself, see
-	 * set_huge_zero_folio().
+	 * Huge zero PMDs have a deposited page table only for anonymous VMAs,
+	 * see set_huge_zero_folio().
 	 */
 	if (is_huge_zero_pmd(pmdval))
-		return !vma_is_dax(vma);
+		return vma_is_anonymous(vma);
 
 	/*
 	 * Otherwise, only anonymous folios are deposited, see
Signature · 1 line
2.39.3 (Apple Git-146)
maintainer
#1 lore raw
Quoted 10 lines · On Sun, 13 Sep 2026 13:19:42 +0800 Lance Yang <[email protected]> wrote:

From: Lance Yang <[email protected]>

has_deposited_pgtable() uses !vma_is_dax() to decide whether a huge zero PMD has a deposited PTE page table. That also accepts raw PFN mappings of huge_zero_pfn, although vmf_insert_pfn_pmd() does not deposit a page table on x86.

Zapping such a mapping would call pgtable_trans_huge_withdraw() without a corresponding deposit. With pmd_huge_pte(mm, pmd) == NULL, that causes a NULL pointer dereference.

That's the sort of thing we'd prefer to avoid.

Quoted 23 lines

Use vma_is_anonymous() for the huge zero PMD check. This matches how PTE page tables are allocated, deposited and moved.

- For anonymous page faults that install a huge zero PMD, do_huge_pmd_anonymous_page() allocates a PTE page table and set_huge_zero_folio() deposits it before installing the PMD.

- On fork, copy_huge_pmd() allocates and deposits a PTE page table when copying a huge zero PMD into an anonymous VMA.

- Raw PFN mappings use vmf_insert_pfn_pmd(), and DAX file holes use vmf_insert_folio_pmd() to map the huge zero folio. Both use insert_pmd(), which deposits a PTE page table only when arch_needs_pgtable_deposit() requires it.

- Moving an anonymous huge PMD preserves its deposited PTE page table. move_huge_pmd() transfers the deposit when necessary. For UFFD MOVE, both VMAs must be anonymous, and move_pages_huge_pmd() transfers the deposit as well.

Keep arch_needs_pgtable_deposit() first so architectures that require a deposited PTE page table still return true regardless of the VMA type.

Quoted 8 lines

Commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()") removed the vma_is_special_huge() check in zap_huge_pmd(). That check skipped the huge zero PMD deposit test for non-DAX VM_PFNMAP and VM_MIXEDMAP mappings. Removing it exposed these mappings to the incorrect !vma_is_dax() test.

Fixes d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()")

How real is this? Is there a reported-by:? Do you have a reproducer? Is it a theoretical, LLM-found-this thing which can't really happen?

Quoted 7 lines
mm/huge_memory.c +0 -1
@@ -2529,11 +2529,11 @@ static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval,
 		return true;
 
 	/*
-	 * Huge zero always deposited except for DAX which handles itself, see

mm/huge_memory.c static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval, · line 2539

Quoted 10 lines
mm/huge_memory.c +3 -2
-	 * set_huge_zero_folio().
+	 * Huge zero PMDs have a deposited page table only for anonymous VMAs,
+	 * see set_huge_zero_folio().
 	 */
 	if (is_huge_zero_pmd(pmdval))
-		return !vma_is_dax(vma);
+		return vma_is_anonymous(vma);
 
 	/*
 	 * Otherwise, only anonymous folios are deposited, see

Thanks, I'll add it for test-n-review.

author reviewer
#2 lore raw
Quoted 44 lines · Andrew Morton
Quoted 10 lines · On Sun, 13 Sep 2026 13:19:42 +0800 Lance Yang <[email protected]> wrote:

From: Lance Yang <[email protected]>

has_deposited_pgtable() uses !vma_is_dax() to decide whether a huge zero PMD has a deposited PTE page table. That also accepts raw PFN mappings of huge_zero_pfn, although vmf_insert_pfn_pmd() does not deposit a page table on x86.

Zapping such a mapping would call pgtable_trans_huge_withdraw() without a corresponding deposit. With pmd_huge_pte(mm, pmd) == NULL, that causes a NULL pointer dereference.

That's the sort of thing we'd prefer to avoid.

Quoted 29 lines

Use vma_is_anonymous() for the huge zero PMD check. This matches how PTE page tables are allocated, deposited and moved.

- For anonymous page faults that install a huge zero PMD, do_huge_pmd_anonymous_page() allocates a PTE page table and set_huge_zero_folio() deposits it before installing the PMD.

- On fork, copy_huge_pmd() allocates and deposits a PTE page table when copying a huge zero PMD into an anonymous VMA.

- Raw PFN mappings use vmf_insert_pfn_pmd(), and DAX file holes use vmf_insert_folio_pmd() to map the huge zero folio. Both use insert_pmd(), which deposits a PTE page table only when arch_needs_pgtable_deposit() requires it.

- Moving an anonymous huge PMD preserves its deposited PTE page table. move_huge_pmd() transfers the deposit when necessary. For UFFD MOVE, both VMAs must be anonymous, and move_pages_huge_pmd() transfers the deposit as well.

Keep arch_needs_pgtable_deposit() first so architectures that require a deposited PTE page table still return true regardless of the VMA type.

Commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()") removed the vma_is_special_huge() check in zap_huge_pmd(). That check skipped the huge zero PMD deposit test for non-DAX VM_PFNMAP and VM_MIXEDMAP mappings. Removing it exposed these mappings to the incorrect !vma_is_dax() test.

Quoted 4 lines
Quoted 2 lines
Fixes d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()")

How real is this? Is there a reported-by:? Do you have a reproducer?

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Quoted 1 line

Is it a theoretical, LLM-found-this thing which can't really happen?

I found this while reviewing the split series with LLM assistance.

mshv_vtl_low derives the PFN from the mmap offset, and its checks do not exclude huge_zero_pfn. I haven't tested this on a Hyper-V, though.

[1] https://lore.kernel.org/linux-mm/[email protected]/

Quoted 15 lines
Quoted 15 lines
mm/huge_memory.c +3 -3
@@ -2529,11 +2529,11 @@ static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval,
 		return true;
 
 	/*
-	 * Huge zero always deposited except for DAX which handles itself, see
-	 * set_huge_zero_folio().
+	 * Huge zero PMDs have a deposited page table only for anonymous VMAs,
+	 * see set_huge_zero_folio().
 	 */
 	if (is_huge_zero_pmd(pmdval))
-		return !vma_is_dax(vma);
+		return vma_is_anonymous(vma);
 
Quoted 4 lines

mm/huge_memory.c static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval, · line 2539

Quoted 2 lines
mm/huge_memory.c +0 -0
 	/*
 	 * Otherwise, only anonymous folios are deposited, see

Thanks, I'll add it for test-n-review.

Thanks!

#3 lore raw
Quoted 49 lines · Lance Yang
Quoted 47 lines · Andrew Morton
Quoted 10 lines · On Sun, 13 Sep 2026 13:19:42 +0800 Lance Yang <[email protected]> wrote:

From: Lance Yang <[email protected]>

has_deposited_pgtable() uses !vma_is_dax() to decide whether a huge zero PMD has a deposited PTE page table. That also accepts raw PFN mappings of huge_zero_pfn, although vmf_insert_pfn_pmd() does not deposit a page table on x86.

Zapping such a mapping would call pgtable_trans_huge_withdraw() without a corresponding deposit. With pmd_huge_pte(mm, pmd) == NULL, that causes a NULL pointer dereference.

That's the sort of thing we'd prefer to avoid.

Quoted 31 lines

Use vma_is_anonymous() for the huge zero PMD check. This matches how PTE page tables are allocated, deposited and moved.

- For anonymous page faults that install a huge zero PMD, do_huge_pmd_anonymous_page() allocates a PTE page table and set_huge_zero_folio() deposits it before installing the PMD.

- On fork, copy_huge_pmd() allocates and deposits a PTE page table when copying a huge zero PMD into an anonymous VMA.

- Raw PFN mappings use vmf_insert_pfn_pmd(), and DAX file holes use vmf_insert_folio_pmd() to map the huge zero folio. Both use insert_pmd(), which deposits a PTE page table only when arch_needs_pgtable_deposit() requires it.

- Moving an anonymous huge PMD preserves its deposited PTE page table. move_huge_pmd() transfers the deposit when necessary. For UFFD MOVE, both VMAs must be anonymous, and move_pages_huge_pmd() transfers the deposit as well.

Keep arch_needs_pgtable_deposit() first so architectures that require a deposited PTE page table still return true regardless of the VMA type.

Commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()") removed the vma_is_special_huge() check in zap_huge_pmd(). That check skipped the huge zero PMD deposit test for non-DAX VM_PFNMAP and VM_MIXEDMAP mappings. Removing it exposed these mappings to the incorrect !vma_is_dax() test.

Fixes d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()")
Quoted 6 lines
Quoted 1 line

How real is this? Is there a reported-by:? Do you have a reproducer?

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Ah. So there's no real bug upstream, right?

And I am not sure it is how we want to address this. I don't think we should allow randomly map huge zero page (and non-huge too). It can be a security risk if it ever gets exposed writable.

See CVE-2015-3288 and 6b7339f4c31a ("mm: avoid setting up anonymous pages into file mapping").

Signature · 1 line
  Kiryl Shutsemau / Kirill A. Shutemov
#4 lore raw
Quoted 8 lines · Kiryl Shutsemau
Quoted 7 lines · Lance Yang
Quoted 5 lines · Andrew Morton

That's the sort of thing we'd prefer to avoid.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

How real is this? Is there a reported-by:? Do you have a reproducer?

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Ah. So there's no real bug upstream, right?

Matches my understanding.

Quoted 4 lines

And I am not sure it is how we want to address this. I don't think we should allow randomly map huge zero page (and non-huge too). It can be a security risk if it ever gets exposed writable.

Due to some DAX stuff (and others) we have the shared zeropage in VM_MIXEDMAP. And we have some elaborate checks in vm_mixed_zeropage_allowed() to test for that.

We should do a similar validation, and ideally just forbid it if not used yet.

Signature · 3 lines
Cheers,

David
maintainer
#5 lore raw
Quoted 11 lines · On Mon, 14 Sep 2026 16:29:00 +0200 "David Hildenbrand (Arm)"…
Quoted 10 lines · Kiryl Shutsemau
Quoted 9 lines · Lance Yang
Quoted 6 lines · Andrew Morton

That's the sort of thing we'd prefer to avoid.

How real is this? Is there a reported-by:? Do you have a reproducer?

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Ah. So there's no real bug upstream, right?

Matches my understanding.

Thanks. I'll remove cc:stable, move this into mm-unstable as a next-merge-window thing.

author reviewer
#6 lore raw
Quoted 18 lines · Andrew Morton
Quoted 16 lines · On Mon, 14 Sep 2026 16:29:00 +0200 "David Hildenbrand (Arm)"…
Quoted 15 lines · Kiryl Shutsemau
Quoted 13 lines · Lance Yang
Quoted 6 lines · Andrew Morton

That's the sort of thing we'd prefer to avoid.

How real is this? Is there a reported-by:? Do you have a reproducer?

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

Ah. So there's no real bug upstream, right?

Matches my understanding.

Thanks. I'll remove cc:stable, move this into mm-unstable as a next-merge-window thing.

Sounds good to me, thanks, Andrew!

Kiryl, David, would you prefer the validation for raw-PFN mappings of the huge zero page as a separate follow-up, or should that validation replace this patch? wdyt

Cheers, Lance

#7 lore raw
Quoted 25 lines · Lance Yang
Quoted 22 lines · Andrew Morton
Quoted 19 lines · On Mon, 14 Sep 2026 16:29:00 +0200 "David Hildenbrand (Arm)"…
Quoted 8 lines · Kiryl Shutsemau
Quoted 7 lines · Lance Yang
Quoted 5 lines · Andrew Morton

That's the sort of thing we'd prefer to avoid.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

How real is this? Is there a reported-by:? Do you have a reproducer?

Yes, I reproduced it on x86 with a small test module. It sets VM_MIXEDMAP | VM_HUGEPAGE and calls vmf_insert_pfn_pmd() with huge_zero_pfn, without touching the page tables directly. A full-PMD munmap() crashes before the split series[1] as well.

Ah. So there's no real bug upstream, right?

Matches my understanding.

Quoted 8 lines
Quoted 2 lines

Thanks. I'll remove cc:stable, move this into mm-unstable as a next-merge-window thing.

Sounds good to me, thanks, Andrew!

Kiryl, David, would you prefer the validation for raw-PFN mappings of the huge zero page as a separate follow-up, or should that validation replace this patch? wdyt

I think this patch can be useful for graceful recovery if we somehow ended up with a zero page in a mapping where we shouldn't have one.

A separate patch with validation would be great.

Signature · 1 line
  Kiryl Shutsemau / Kirill A. Shutemov
#8 lore raw
Quoted 11 lines · Kiryl Shutsemau
Quoted 10 lines · Lance Yang
Quoted 4 lines · Andrew Morton

Thanks. I'll remove cc:stable, move this into mm-unstable as a next-merge-window thing.

Sounds good to me, thanks, Andrew!

Quoted 9 lines
Quoted 3 lines

Kiryl, David, would you prefer the validation for raw-PFN mappings of the huge zero page as a separate follow-up, or should that validation replace this patch? wdyt

I think this patch can be useful for graceful recovery if we somehow ended up with a zero page in a mapping where we shouldn't have one.

A separate patch with validation would be great.

Ack

Signature · 3 lines
Cheers,

David
#9 lore raw
In reply to Lance Yang
Quoted 56 lines · Lance Yang

From: Lance Yang <[email protected]>

has_deposited_pgtable() uses !vma_is_dax() to decide whether a huge zero PMD has a deposited PTE page table. That also accepts raw PFN mappings of huge_zero_pfn, although vmf_insert_pfn_pmd() does not deposit a page table on x86.

Zapping such a mapping would call pgtable_trans_huge_withdraw() without a corresponding deposit. With pmd_huge_pte(mm, pmd) == NULL, that causes a NULL pointer dereference.

Use vma_is_anonymous() for the huge zero PMD check. This matches how PTE page tables are allocated, deposited and moved.

- For anonymous page faults that install a huge zero PMD, do_huge_pmd_anonymous_page() allocates a PTE page table and set_huge_zero_folio() deposits it before installing the PMD.

- On fork, copy_huge_pmd() allocates and deposits a PTE page table when copying a huge zero PMD into an anonymous VMA.

- Raw PFN mappings use vmf_insert_pfn_pmd(), and DAX file holes use vmf_insert_folio_pmd() to map the huge zero folio. Both use insert_pmd(), which deposits a PTE page table only when arch_needs_pgtable_deposit() requires it.

- Moving an anonymous huge PMD preserves its deposited PTE page table. move_huge_pmd() transfers the deposit when necessary. For UFFD MOVE, both VMAs must be anonymous, and move_pages_huge_pmd() transfers the deposit as well.

Keep arch_needs_pgtable_deposit() first so architectures that require a deposited PTE page table still return true regardless of the VMA type.

Commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()") removed the vma_is_special_huge() check in zap_huge_pmd(). That check skipped the huge zero PMD deposit test for non-DAX VM_PFNMAP and VM_MIXEDMAP mappings. Removing it exposed these mappings to the incorrect !vma_is_dax() test.

Fixes d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()")
---
 mm/huge_memory.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
mm/huge_memory.c +0 -1
index 6895b38e4704..0ed997a97416 100644
@@ -2529,11 +2529,11 @@ static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval,
 		return true;
 
 	/*
-	 * Huge zero always deposited except for DAX which handles itself, see

mm/huge_memory.c static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval, · line 2539

Quoted 10 lines
mm/huge_memory.c +3 -2
-	 * set_huge_zero_folio().
+	 * Huge zero PMDs have a deposited page table only for anonymous VMAs,
+	 * see set_huge_zero_folio().
 	 */
 	if (is_huge_zero_pmd(pmdval))
-		return !vma_is_dax(vma);
+		return vma_is_anonymous(vma);
 
 	/*
 	 * Otherwise, only anonymous folios are deposited, see

Ok, it's really only DAX and anonymous VMAs that use the huge zero folio. Other (module) code would have a hard time using it, as mm_get_huge_zero_folio() is not exported to modules.

DAX uses dax_pmd_load_hole()->vmf_insert_folio_pmd()->insert_pmd() where we deposit a page table only if arch_needs_pgtable_deposit().

So I think the rule is simply:

arch_needs_pgtable_deposit() -> always deposited
vma_is_anonymous() -> always deposited

?

The trick is that we don't have anon THPs in non-anon VMAs.

So could this be simplified further or am I missing something?

Signature · 3 lines
Cheers,

David
author reviewer
#10 lore raw

On Tue, Sep 15, 2026 at 05:13:17PM +0200, David Hildenbrand (Arm) wrote:
[...]

Quoted 9 lines

Ok, it's really only DAX and anonymous VMAs that use the huge zero folio. Other (module) code would have a hard time using it, as mm_get_huge_zero_folio() is not exported to modules.

DAX uses dax_pmd_load_hole()->vmf_insert_folio_pmd()->insert_pmd() where we deposit a page table only if arch_needs_pgtable_deposit().

Quoted 6 lines

So I think the rule is simply:

arch_needs_pgtable_deposit() -> always deposited
vma_is_anonymous() -> always deposited

?

YES!

Quoted 4 lines

The trick is that we don't have anon THPs in non-anon VMAs.

So could this be simplified further or am I missing something?

Ah, cool! I hadn't thought of that :) You're right, anon THPs cannot live in non-anon VMAs, so pmdval and folio aren't needed here. Will simplify it as suggested :) and add a comment explaining the rule.

static bool has_deposited_pgtable(struct vm_area_struct *vma)

{
	return arch_needs_pgtable_deposit() || vma_is_anonymous(vma);
}

Cheers, Lance

#11 lore raw
Quoted 26 lines · Lance Yang

On Tue, Sep 15, 2026 at 05:13:17PM +0200, David Hildenbrand (Arm) wrote:
[...]

Quoted 9 lines

Ok, it's really only DAX and anonymous VMAs that use the huge zero folio. Other (module) code would have a hard time using it, as mm_get_huge_zero_folio() is not exported to modules.

DAX uses dax_pmd_load_hole()->vmf_insert_folio_pmd()->insert_pmd() where we deposit a page table only if arch_needs_pgtable_deposit().

Quoted 6 lines

So I think the rule is simply:

arch_needs_pgtable_deposit() -> always deposited
vma_is_anonymous() -> always deposited

?

YES!

Quoted 4 lines

The trick is that we don't have anon THPs in non-anon VMAs.

So could this be simplified further or am I missing something?

Quoted 8 lines

Ah, cool! I hadn't thought of that :) You're right, anon THPs cannot live in non-anon VMAs, so pmdval and folio aren't needed here. Will simplify it as suggested :) and add a comment explaining the rule.

static bool has_deposited_pgtable(struct vm_area_struct *vma)

{
	return arch_needs_pgtable_deposit() || vma_is_anonymous(vma);
}

Yes, that's what I had in mind. (while at it, maybe call it "vma_has_*)

Signature · 3 lines
Cheers,

David
author reviewer
#12 lore raw
Quoted 31 lines · David Hildenbrand (Arm)
Quoted 30 lines · Lance Yang

On Tue, Sep 15, 2026 at 05:13:17PM +0200, David Hildenbrand (Arm) wrote:
[...]

Quoted 9 lines

Ok, it's really only DAX and anonymous VMAs that use the huge zero folio. Other (module) code would have a hard time using it, as mm_get_huge_zero_folio() is not exported to modules.

DAX uses dax_pmd_load_hole()->vmf_insert_folio_pmd()->insert_pmd() where we deposit a page table only if arch_needs_pgtable_deposit().

Quoted 6 lines

So I think the rule is simply:

arch_needs_pgtable_deposit() -> always deposited
vma_is_anonymous() -> always deposited

?

YES!

Quoted 4 lines

The trick is that we don't have anon THPs in non-anon VMAs.

So could this be simplified further or am I missing something?

Ah, cool! I hadn't thought of that :) You're right, anon THPs cannot live in non-anon VMAs, so pmdval and folio aren't needed here. Will simplify it as suggested :) and add a comment explaining the rule.

Quoted 6 lines
Quoted 4 lines

static bool has_deposited_pgtable(struct vm_area_struct *vma)

{
	return arch_needs_pgtable_deposit() || vma_is_anonymous(vma);
}

Yes, that's what I had in mind. (while at it, maybe call it "vma_has_*)

Good point, will do. Thanks!