summaryrefslogtreecommitdiff
path: root/arch/riscv/kernel/patch.c
diff options
context:
space:
mode:
authorAlexandre Ghiti <alexghiti@rivosinc.com>2023-12-14 10:19:26 +0100
committerPalmer Dabbelt <palmer@rivosinc.com>2024-01-09 10:58:59 -0800
commit420370f3ae3d3b883813fd3051a38805160b2b9f (patch)
tree637445e78c14c045aa880edaf6c8994b7e8540e8 /arch/riscv/kernel/patch.c
parented5b7cfd7839f9280a63365c1133482b42d0981f (diff)
downloadlinux-420370f3ae3d3b883813fd3051a38805160b2b9f.tar.gz
linux-420370f3ae3d3b883813fd3051a38805160b2b9f.tar.bz2
linux-420370f3ae3d3b883813fd3051a38805160b2b9f.zip
riscv: Check if the code to patch lies in the exit section
Otherwise we fall through to vmalloc_to_page() which panics since the address does not lie in the vmalloc region. Fixes: 043cb41a85de ("riscv: introduce interfaces to patch kernel code") Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> Reviewed-by: Charlie Jenkins <charlie@rivosinc.com> Link: https://lore.kernel.org/r/20231214091926.203439-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/kernel/patch.c')
-rw-r--r--arch/riscv/kernel/patch.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 13ee7bf589a1..37e87fdcf6a0 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -14,6 +14,7 @@
#include <asm/fixmap.h>
#include <asm/ftrace.h>
#include <asm/patch.h>
+#include <asm/sections.h>
struct patch_insn {
void *addr;
@@ -25,6 +26,14 @@ struct patch_insn {
int riscv_patch_in_stop_machine = false;
#ifdef CONFIG_MMU
+
+static inline bool is_kernel_exittext(uintptr_t addr)
+{
+ return system_state < SYSTEM_RUNNING &&
+ addr >= (uintptr_t)__exittext_begin &&
+ addr < (uintptr_t)__exittext_end;
+}
+
/*
* The fix_to_virt(, idx) needs a const value (not a dynamic variable of
* reg-a0) or BUILD_BUG_ON failed with "idx >= __end_of_fixed_addresses".
@@ -35,7 +44,7 @@ static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
uintptr_t uintaddr = (uintptr_t) addr;
struct page *page;
- if (core_kernel_text(uintaddr))
+ 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);