]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
riscv: Disable preemption when using patch_map()
authorAlexandre Ghiti <alexghiti@rivosinc.com>
Tue, 26 Mar 2024 20:30:17 +0000 (21:30 +0100)
committerPalmer Dabbelt <palmer@rivosinc.com>
Thu, 4 Apr 2024 19:33:38 +0000 (12:33 -0700)
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: Andrea Parri <andrea@rivosinc.com>
Closes: https://lore.kernel.org/all/ZcS+GAaM25LXsBOl@andrea/
Reported-by: Andy Chiu <andy.chiu@sifive.com>
Closes: https://lore.kernel.org/linux-riscv/CABgGipUMz3Sffu-CkmeUB1dKVwVQ73+7=sgC45-m0AE9RCjOZg@mail.gmail.com/
Fixes: cad539baa48f ("riscv: implement a memset like function for text")
Fixes: 0ff7c3b33127 ("riscv: Use text_mutex instead of patch_lock")
Co-developed-by: Andy Chiu <andy.chiu@sifive.com>
Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Acked-by: Puranjay Mohan <puranjay12@gmail.com>
Link: https://lore.kernel.org/r/20240326203017.310422-3-alexghiti@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/kernel/patch.c

index 37e87fdcf6a00057663ffd636c50e85e865be3c4..30e12b310cab7397f91d622f8d4c20117e5e8c5f 100644 (file)
@@ -80,6 +80,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
         */
        lockdep_assert_held(&text_mutex);
 
+       preempt_disable();
+
        if (across_pages)
                patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
 
@@ -92,6 +94,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
        if (across_pages)
                patch_unmap(FIX_TEXT_POKE1);
 
+       preempt_enable();
+
        return 0;
 }
 NOKPROBE_SYMBOL(__patch_insn_set);
@@ -122,6 +126,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)
        if (!riscv_patch_in_stop_machine)
                lockdep_assert_held(&text_mutex);
 
+       preempt_disable();
+
        if (across_pages)
                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)
        if (across_pages)
                patch_unmap(FIX_TEXT_POKE1);
 
+       preempt_enable();
+
        return ret;
 }
 NOKPROBE_SYMBOL(__patch_insn_write);