| From b0467e9f5af4bd71d34272f46a6e83a39d13adce Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 29 Mar 2022 18:54:36 +0000 |
| Subject: parisc: Fix patch code locking and flushing |
| |
| From: John David Anglin <dave.anglin@bell.net> |
| |
| [ Upstream commit a9fe7fa7d874a536e0540469f314772c054a0323 ] |
| |
| This change fixes the following: |
| |
| 1) The flags variable is not initialized. Always use raw_spin_lock_irqsave |
| and raw_spin_unlock_irqrestore to serialize patching. |
| |
| 2) flush_kernel_vmap_range is primarily intended for DMA flushes. Since |
| __patch_text_multiple is often called with interrupts disabled, it is |
| better to directly call flush_kernel_dcache_range_asm and |
| flush_kernel_icache_range_asm. This avoids an extra call. |
| |
| 3) The final call to flush_icache_range is unnecessary. |
| |
| Signed-off-by: John David Anglin <dave.anglin@bell.net> |
| Signed-off-by: Helge Deller <deller@gmx.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/parisc/kernel/patch.c | 25 +++++++++++-------------- |
| 1 file changed, 11 insertions(+), 14 deletions(-) |
| |
| diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c |
| index 80a0ab372802..e59574f65e64 100644 |
| --- a/arch/parisc/kernel/patch.c |
| +++ b/arch/parisc/kernel/patch.c |
| @@ -40,10 +40,7 @@ static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags, |
| |
| *need_unmap = 1; |
| set_fixmap(fixmap, page_to_phys(page)); |
| - if (flags) |
| - raw_spin_lock_irqsave(&patch_lock, *flags); |
| - else |
| - __acquire(&patch_lock); |
| + raw_spin_lock_irqsave(&patch_lock, *flags); |
| |
| return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); |
| } |
| @@ -52,10 +49,7 @@ static void __kprobes patch_unmap(int fixmap, unsigned long *flags) |
| { |
| clear_fixmap(fixmap); |
| |
| - if (flags) |
| - raw_spin_unlock_irqrestore(&patch_lock, *flags); |
| - else |
| - __release(&patch_lock); |
| + raw_spin_unlock_irqrestore(&patch_lock, *flags); |
| } |
| |
| void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) |
| @@ -67,8 +61,9 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) |
| int mapped; |
| |
| /* Make sure we don't have any aliases in cache */ |
| - flush_kernel_vmap_range(addr, len); |
| - flush_icache_range(start, end); |
| + flush_kernel_dcache_range_asm(start, end); |
| + flush_kernel_icache_range_asm(start, end); |
| + flush_tlb_kernel_range(start, end); |
| |
| p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped); |
| |
| @@ -81,8 +76,10 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) |
| * We're crossing a page boundary, so |
| * need to remap |
| */ |
| - flush_kernel_vmap_range((void *)fixmap, |
| - (p-fixmap) * sizeof(*p)); |
| + flush_kernel_dcache_range_asm((unsigned long)fixmap, |
| + (unsigned long)p); |
| + flush_tlb_kernel_range((unsigned long)fixmap, |
| + (unsigned long)p); |
| if (mapped) |
| patch_unmap(FIX_TEXT_POKE0, &flags); |
| p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, |
| @@ -90,10 +87,10 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) |
| } |
| } |
| |
| - flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p)); |
| + flush_kernel_dcache_range_asm((unsigned long)fixmap, (unsigned long)p); |
| + flush_tlb_kernel_range((unsigned long)fixmap, (unsigned long)p); |
| if (mapped) |
| patch_unmap(FIX_TEXT_POKE0, &flags); |
| - flush_icache_range(start, end); |
| } |
| |
| void __kprobes __patch_text(void *addr, u32 insn) |
| -- |
| 2.35.1 |
| |