Commit 6b60a128 authored by Vivian Wang's avatar Vivian Wang Committed by Paul Walmsley
Browse files

riscv: patch: Avoid early phys_to_page()



Similarly to commit 8d09e2d5 ("arm64: patching: avoid early
page_to_phys()"), avoid using phys_to_page() for the kernel address case
in patch_map().

Since this is called from apply_boot_alternatives() in setup_arch(), and
commit 4267739c ("arch, mm: consolidate initialization of SPARSE
memory model") has moved sparse_init() to after setup_arch(),
phys_to_page() is not available there yet, and it panics on boot with
SPARSEMEM on RV32, which does not use SPARSEMEM_VMEMMAP.

Reported-by: default avatarThomas Weißschuh <thomas.weissschuh@linutronix.de>
Closes: https://lore.kernel.org/r/20260223144108-dcace0b9-02e8-4b67-a7ce-f263bed36f26@linutronix.de/


Fixes: 4267739c ("arch, mm: consolidate initialization of SPARSE memory model")
Suggested-by: default avatarMike Rapoport <rppt@kernel.org>
Signed-off-by: default avatarVivian Wang <wangruikang@iscas.ac.cn>
Acked-by: default avatarMike Rapoport (Microsoft) <rppt@kernel.org>
Tested-by: default avatarThomas Weißschuh <thomas.weissschuh@linutronix.de>
Link: https://patch.msgid.link/20260310-riscv-sparsemem-alternatives-fix-v1-1-659d5dd257e2@iscas.ac.cn


[pjw@kernel.org: fix the subject line to align with the patch description]
Signed-off-by: default avatarPaul Walmsley <pjw@kernel.org>
parent 834911eb
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -42,19 +42,20 @@ static inline bool is_kernel_exittext(uintptr_t addr)
static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
{
	uintptr_t uintaddr = (uintptr_t) addr;
	struct page *page;
	phys_addr_t phys;

	if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
		page = phys_to_page(__pa_symbol(addr));
	else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
		page = vmalloc_to_page(addr);
	else
		return addr;
	if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr)) {
		phys = __pa_symbol(addr);
	} else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) {
		struct page *page = vmalloc_to_page(addr);

		BUG_ON(!page);
		phys = page_to_phys(page) + offset_in_page(addr);
	} else {
		return addr;
	}

	return (void *)set_fixmap_offset(fixmap, page_to_phys(page) +
					 offset_in_page(addr));
	return (void *)set_fixmap_offset(fixmap, phys);
}

static void patch_unmap(int fixmap)