[RFC PATCH 2/3] arm64/mm: make huge zero folio read-only in linear map
From: Xueyuan chen <hidden>
Date: 2026-05-27 03:56:46
Also in:
linux-mm, lkml
Subsystem:
arm64 port (aarch64 architecture), the rest · Maintainers:
Catalin Marinas, Will Deacon, Linus Torvalds
From: Xueyuan Chen <redacted> Implement arch_make_huge_zero_folio_readonly() for arm64. Once allocated, try to make the folio read-only in the linear map so unexpected writes fault instead of corrupting shared zero contents. Respect can_set_direct_map() before touching the linear map, and treat the pageattr update as best effort: it can still fail while splitting a leaf mapping or applying new permissions. If that happens, generic THP keeps using the writable persistent huge zero folio. Co-developed-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Xueyuan Chen <redacted> --- arch/arm64/Kconfig | 1 + arch/arm64/mm/pageattr.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fe60738e5943..3cd705dd5251 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig@@ -44,6 +44,7 @@ config ARM64 select ARCH_HAS_PREEMPT_LAZY select ARCH_HAS_PTDUMP select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_READONLY_HUGE_ZERO_FOLIO select ARCH_HAS_HW_PTE_YOUNG select ARCH_HAS_SETUP_DMA_OPS select ARCH_HAS_SET_DIRECT_MAP
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index ce035e1b4eaf..51ce31e74a18 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c@@ -3,7 +3,9 @@ * Copyright (c) 2014, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> +#include <linux/init.h> #include <linux/mm.h> +#include <linux/huge_mm.h> #include <linux/module.h> #include <linux/mem_encrypt.h> #include <linux/sched.h>
@@ -147,6 +149,20 @@ static int __change_memory_common(unsigned long start, unsigned long size, return ret; } +#ifdef CONFIG_READONLY_HUGE_ZERO_FOLIO +bool __init arch_make_huge_zero_folio_readonly(struct folio *folio) +{ + unsigned long addr = (unsigned long)folio_address(folio); + + if (!can_set_direct_map()) + return false; + + return !__change_memory_common(addr, PMD_SIZE, + __pgprot(PTE_RDONLY), + __pgprot(PTE_WRITE)); +} +#endif + static int change_memory_common(unsigned long addr, int numpages, pgprot_t set_mask, pgprot_t clear_mask) {
--
2.47.3