Re: [PATCH v3 01/13] arm64: Move the zero page to rodata

Catalin Marinas
2026-04-08T13:43:35Z

Hi Ard,

On Fri, Mar 20, 2026 at 03:59:36PM +0100, Ard Biesheuvel wrote:
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 2964aad0362e..2d021a576e50 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -229,6 +229,7 @@ SECTIONS
> #endif
>
> reserved_pg_dir = .;
> + empty_zero_page = .;
> . += PAGE_SIZE;
>
> swapper_pg_dir = .;
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index a6a00accf4f9..795743913ce5 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -66,9 +66,8 @@ long __section(".mmuoff.data.write") __early_cpu_boot_status;
>
> /*
> * Empty_zero_page is a special page that is used for zero-initialized data
> - * and COW.
> + * and COW. Defined in the linker script.
> */
> -unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
> EXPORT_SYMBOL(empty_zero_page);

I looked at Sashiko's reports
(https://sashiko.dev/#/patchset/20260320145934.2349881-15-ardb+git@google.com)
and it has a point here that with MTE, map_mem() doesn't map the
empty_zero_page as Tagged in the for_each_mem_range() loop. The
subsequent cpu_enable_mte() will fail to initialise the tags. I think
this problem disappears with patch 11 where all the linear map is now
Tagged.

We either ignore it or we temporarily map the kernel as Tagged until the
linear alias is removed later:

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 795743913ce5..5290f7537074 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1175,7 +1175,7 @@ static void __init map_mem(pgd_t *pgdp)
* so we should avoid them here.
*/
__map_memblock(pgdp, kernel_start, kernel_end,
- PAGE_KERNEL, NO_CONT_MAPPINGS);
+ pgprot_tagged(PAGE_KERNEL), NO_CONT_MAPPINGS);
memblock_clear_nomap(kernel_start, kernel_end - kernel_start);
arm64_kfence_map_pool(early_kfence_pool, pgdp);
}

--
Catalin