Commit a370c241 authored by Alexandre Ghiti's avatar Alexandre Ghiti Committed by Palmer Dabbelt

riscv: Disable preemption when using patch_map()

patch_map() uses fixmap mappings to circumvent the non-writability of
the kernel text mapping.

The __set_fixmap() function only flushes the current cpu tlb, it does
not emit an IPI so we must make sure that while we use a fixmap mapping,
the current task is not migrated on another cpu which could miss the
newly introduced fixmap mapping.

So in order to avoid any task migration, disable the preemption.
Reported-by: default avatarAndrea Parri <andrea@rivosinc.com>
Closes: https://lore.kernel.org/all/ZcS+GAaM25LXsBOl@andrea/Reported-by: default avatarAndy Chiu <andy.chiu@sifive.com>
Closes: https://lore.kernel.org/linux-riscv/CABgGipUMz3Sffu-CkmeUB1dKVwVQ73+7=sgC45-m0AE9RCjOZg@mail.gmail.com/
Fixes: cad539ba ("riscv: implement a memset like function for text")
Fixes: 0ff7c3b3 ("riscv: Use text_mutex instead of patch_lock")
Co-developed-by: default avatarAndy Chiu <andy.chiu@sifive.com>
Signed-off-by: default avatarAndy Chiu <andy.chiu@sifive.com>
Signed-off-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
Acked-by: default avatarPuranjay Mohan <puranjay12@gmail.com>
Link: https://lore.kernel.org/r/20240326203017.310422-3-alexghiti@rivosinc.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 8a48ea87
...@@ -80,6 +80,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len) ...@@ -80,6 +80,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
*/ */
lockdep_assert_held(&text_mutex); lockdep_assert_held(&text_mutex);
preempt_disable();
if (across_pages) if (across_pages)
patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1); patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
...@@ -92,6 +94,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len) ...@@ -92,6 +94,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
if (across_pages) if (across_pages)
patch_unmap(FIX_TEXT_POKE1); patch_unmap(FIX_TEXT_POKE1);
preempt_enable();
return 0; return 0;
} }
NOKPROBE_SYMBOL(__patch_insn_set); NOKPROBE_SYMBOL(__patch_insn_set);
...@@ -122,6 +126,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len) ...@@ -122,6 +126,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)
if (!riscv_patch_in_stop_machine) if (!riscv_patch_in_stop_machine)
lockdep_assert_held(&text_mutex); lockdep_assert_held(&text_mutex);
preempt_disable();
if (across_pages) if (across_pages)
patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1); patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
...@@ -134,6 +140,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len) ...@@ -134,6 +140,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)
if (across_pages) if (across_pages)
patch_unmap(FIX_TEXT_POKE1); patch_unmap(FIX_TEXT_POKE1);
preempt_enable();
return ret; return ret;
} }
NOKPROBE_SYMBOL(__patch_insn_write); NOKPROBE_SYMBOL(__patch_insn_write);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment