From: Jisheng Zhang <jszhang@kernel.org>
To: Nickolai Zeldovich <nickolai@csail.mit.edu>
Cc: Paul Walmsley <pjw@kernel.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>,
Muchun Song <muchun.song@linux.dev>,
linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1] riscv: mm: Define PAGE_KERNEL_RO
Date: Tue, 20 Oct 2026 09:20:05 +0800 [thread overview]
Message-ID: <atbBxX-kCkB5pgsk@xhacker> (raw)
In-Reply-To: <20261018023649.798595-1-nickolai@csail.mit.edu>
On Sat, Oct 17, 2026 at 10:36:49PM -0400, Nickolai Zeldovich wrote:
> Kernel mappings that generic code creates read-only are writable on
> riscv. With HugeTLB vmemmap optimization (selected by riscv and on by
> default with CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON), the tail
> vmemmap pages of every optimized huge page are remapped to one shared
> page with PAGE_KERNEL_RO so that a stray write to a tail struct page
> faults. On riscv that remap keeps _PAGE_WRITE, so such a write silently
> changes the struct pages of every optimized huge page instead.
> early_memremap_ro() (EFI system and configuration tables), the
> firmware loader's vmap() of the loaded image, and acpi_os_ioremap() for
> EFI runtime code and NOMAP regions, which asks for a read-only mapping
> precisely to avoid a writable mapping of executable code, are affected
> the same way.
>
> riscv defines PAGE_KERNEL_READ but not PAGE_KERNEL_RO, so
> include/linux/pgtable.h falls back to "#define PAGE_KERNEL_RO
> PAGE_KERNEL". Define PAGE_KERNEL_RO as PAGE_KERNEL_READ. FIXMAP_PAGE_RO
> then follows from asm-generic/fixmap.h: early_memremap_ro() now passes
> 0xe3 instead of 0xe7 to __early_ioremap().
>
> Tested on QEMU virt (riscv64, defconfig with
> CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON and CONFIG_PTDUMP_DEBUGFS,
> booted with hugepages=8): before, every vmemmap entry in
> /sys/kernel/debug/kernel_page_tables has W set; after, the 28K of tail
> vmemmap of each huge page is mapped R without W.
>
> Fixes: a3c7d6b642e4 ("riscv: mm: hugetlb: Enable ARCH_WANT_HUGETLB_PAGE_OPTIMIZE_VMEMMAP")
> Assisted-by: LLM
> Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu>
Reviewed-by: Jisheng Zhang <jszhang@kernel.org>
> ---
>
> Notes:
> Reproducer (riscv64 defconfig + CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON=y
> CONFIG_PTDUMP_DEBUGFS=y, QEMU virt): a static /init that prints the vmemmap
> part of the kernel page table dump.
>
> #include <stdio.h>
> #include <string.h>
> #include <sys/mount.h>
> #include <sys/reboot.h>
>
> int main(void)
> {
> char line[256];
> int in = 0;
> FILE *f;
>
> mount("sysfs", "/sys", "sysfs", 0, NULL);
> mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL);
> f = fopen("/sys/kernel/debug/kernel_page_tables", "r");
> while (f && fgets(line, sizeof(line), f)) {
> if (strstr(line, "---[ "))
> in = strstr(line, "vmemmap start") != NULL;
> if (in)
> fputs(line, stdout);
> }
> fflush(stdout);
> reboot(RB_POWER_OFF);
> return 0;
> }
>
> riscv64-linux-gnu-gcc -static -O2 -o init init.c
> qemu-system-riscv64 -M virt -cpu max -smp 2 -m 1G -nographic -kernel Image \
> -initrd initramfs.cpio -append "console=ttyS0 hugepages=8"
>
> Before (all vmemmap entries writable):
> 0xff1c000002000000-0xff1c000002200000 0xbec00000 2M PTE D A G . . W R V
> 0xff1c000002200000-0xff1c000002800000 0xbea00000 6M PMD D A G . . W R V
>
> After (each huge page: 4K head W, 28K tail read-only, shared page 0x81fd0000):
> 0xff1c0000020a1000-0xff1c0000020a8000 0x81fd0000 28K PTE D A G . . . R V
> 0xff1c0000020a8000-0xff1c0000020a9000 0x81fd6000 4K PTE D A G . . W R V
> 0xff1c0000020a9000-0xff1c0000020b0000 0x81fd0000 28K PTE D A G . . . R V
>
> arch/riscv/include/asm/pgtable.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 40b1ed4f3ea8..13447181ceb7 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -189,6 +189,7 @@ extern struct pt_alloc_ops pt_ops __meminitdata;
>
> #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
> #define PAGE_KERNEL_READ __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
> +#define PAGE_KERNEL_RO PAGE_KERNEL_READ
> #define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL | _PAGE_EXEC)
> #define PAGE_KERNEL_READ_EXEC __pgprot((_PAGE_KERNEL & ~_PAGE_WRITE) \
> | _PAGE_EXEC)
>
> base-commit: 58161ead29e50d70a317ea26b472e0c7508e69da
> --
> 2.53.0
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
prev parent reply other threads:[~2026-10-20 1:40 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-18 2:36 [PATCH v1] riscv: mm: Define PAGE_KERNEL_RO Nickolai Zeldovich
2026-10-18 2:47 ` Muchun Song
2026-10-20 1:20 ` Jisheng Zhang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=atbBxX-kCkB5pgsk@xhacker \
--to=jszhang@kernel.org \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=muchun.song@linux.dev \
--cc=nickolai@csail.mit.edu \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.