[PATCH 2/2] riscv: mm: check the valid bit in kernel_page_present()

From: Mike Rapoport (Microsoft)

Date: Thu Nov 12 2026 - 09:20:42 EST


set_direct_map_invalid_noflush() clears _PAGE_PRESENT, but the kernel
mappings keep _PAGE_PROT_NONE set: it used to be _PAGE_READ and now it is
the same bit as _PAGE_GLOBAL. pte_present() and pmd_present() still
return true for the invalidated entry. kernel_page_present() then reports
that an unmapped page is mapped, and hibernation copies it without
remapping it first.

Test _PAGE_PRESENT directly for PMD and PTE leaves.

Fixes: 32a0de886eb3 ("arch, mm: make kernel_page_present() always available")
Signed-off-by: Mike Rapoport (Microsoft) <rppt@xxxxxxxxxx>
---
arch/riscv/mm/pageattr.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index b138113755359..62fbcf7cf36b6 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -453,8 +453,9 @@ bool kernel_page_present(struct page *page)
if (!pmd_present(pmdp_get(pmd)))
return false;
if (pmd_leaf(pmdp_get(pmd)))
- return true;
+ return pmd_val(pmdp_get(pmd)) & _PAGE_PRESENT;

+ /* pte_present() is true for PAGE_KERNEL with _PAGE_PRESENT cleared */
pte = pte_offset_kernel(pmd, addr);
- return pte_present(ptep_get(pte));
+ return pte_val(ptep_get(pte)) & _PAGE_PRESENT;
}

--
2.53.0