History

mm/huge_memory: preserve pmd_swp_uffd_wp on device-private PMD downgrade

change_non_present_huge_pmd() rewrites a writable device-private PMD swap entry into a readable one without carrying pmd_swp_uffd_wp() across. The PTE-level change_softleaf_pte() does this correctly; mirror that here, matching what copy_huge_pmd() does for the fork path. Without the carry, a plain mprotect() over a UFFD_WP-marked device-private THP strips the bit and the trap is bypassed on swap-in.

Kiryl Shutsemau (Meta) committed 5 months ago

Commit f7e2c211 parent e92d92b1 file · +2 −0Browse files

Unified · Split

mm/huge_memory.c+2−0
@@ -2565,6 +2565,8 @@ static void change_non_present_huge_pmd(struct mm_struct *mm, · 2564 unmodified lines
25652565 } else if (softleaf_is_device_private_write(entry)) {
25662566 entry = make_readable_device_private_entry(swp_offset(entry));
25672567 newpmd = swp_entry_to_pmd(entry);
2568+ if (pmd_swp_uffd_wp(*pmd))
2569+ newpmd = pmd_swp_mkuffd_wp(newpmd);
25682570 } else {
25692571 newpmd = *pmd;
25702572 }