Skip to content

Commit 420370f

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
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: 043cb41 ("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>
1 parent ed5b7cf commit 420370f

4 files changed

Lines changed: 15 additions & 1 deletion

File tree

arch/riscv/include/asm/sections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern char _start_kernel[];
1313
extern char __init_data_begin[], __init_data_end[];
1414
extern char __init_text_begin[], __init_text_end[];
1515
extern char __alt_start[], __alt_end[];
16+
extern char __exittext_begin[], __exittext_end[];
1617

1718
static inline bool is_va_kernel_text(uintptr_t va)
1819
{

arch/riscv/kernel/patch.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/fixmap.h>
1515
#include <asm/ftrace.h>
1616
#include <asm/patch.h>
17+
#include <asm/sections.h>
1718

1819
struct patch_insn {
1920
void *addr;
@@ -25,6 +26,14 @@ struct patch_insn {
2526
int riscv_patch_in_stop_machine = false;
2627

2728
#ifdef CONFIG_MMU
29+
30+
static inline bool is_kernel_exittext(uintptr_t addr)
31+
{
32+
return system_state < SYSTEM_RUNNING &&
33+
addr >= (uintptr_t)__exittext_begin &&
34+
addr < (uintptr_t)__exittext_end;
35+
}
36+
2837
/*
2938
* The fix_to_virt(, idx) needs a const value (not a dynamic variable of
3039
* 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)
3544
uintptr_t uintaddr = (uintptr_t) addr;
3645
struct page *page;
3746

38-
if (core_kernel_text(uintaddr))
47+
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
3948
page = phys_to_page(__pa_symbol(addr));
4049
else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
4150
page = vmalloc_to_page(addr);

arch/riscv/kernel/vmlinux-xip.lds.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ SECTIONS
2929
HEAD_TEXT_SECTION
3030
INIT_TEXT_SECTION(PAGE_SIZE)
3131
/* we have to discard exit text and such at runtime, not link time */
32+
__exittext_begin = .;
3233
.exit.text :
3334
{
3435
EXIT_TEXT
3536
}
37+
__exittext_end = .;
3638

3739
.text : {
3840
_text = .;

arch/riscv/kernel/vmlinux.lds.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ SECTIONS
6969
__soc_builtin_dtb_table_end = .;
7070
}
7171
/* we have to discard exit text and such at runtime, not link time */
72+
__exittext_begin = .;
7273
.exit.text :
7374
{
7475
EXIT_TEXT
7576
}
77+
__exittext_end = .;
7678

7779
__init_text_end = .;
7880
. = ALIGN(SECTION_ALIGN);

0 commit comments

Comments
 (0)