提交 78ff7fae 编写于 作者: M Masami Hiramatsu 提交者: Ingo Molnar

x86: implement atomic text_poke() via fixmap

Use fixmaps instead of vmap/vunmap in text_poke() for avoiding
page allocation and delayed unmapping.

At the result of above change, text_poke() becomes atomic and can be called
from stop_machine() etc.
Signed-off-by: NMasami Hiramatsu <mhiramat@redhat.com>
Acked-by: NMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
LKML-Reference: <49B14352.2040705@redhat.com>
Signed-off-by: NIngo Molnar <mingo@elte.hu>
上级 3945dab4
...@@ -111,6 +111,8 @@ enum fixed_addresses { ...@@ -111,6 +111,8 @@ enum fixed_addresses {
#ifdef CONFIG_PARAVIRT #ifdef CONFIG_PARAVIRT
FIX_PARAVIRT_BOOTMAP, FIX_PARAVIRT_BOOTMAP,
#endif #endif
FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */
FIX_TEXT_POKE1,
__end_of_permanent_fixed_addresses, __end_of_permanent_fixed_addresses,
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
FIX_OHCI1394_BASE, FIX_OHCI1394_BASE,
......
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/vsyscall.h> #include <asm/vsyscall.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/fixmap.h>
#define MAX_PATCH_LEN (255-1) #define MAX_PATCH_LEN (255-1)
...@@ -505,15 +507,16 @@ void *text_poke_early(void *addr, const void *opcode, size_t len) ...@@ -505,15 +507,16 @@ void *text_poke_early(void *addr, const void *opcode, size_t len)
* It means the size must be writable atomically and the address must be aligned * It means the size must be writable atomically and the address must be aligned
* in a way that permits an atomic write. It also makes sure we fit on a single * in a way that permits an atomic write. It also makes sure we fit on a single
* page. * page.
*
* Note: Must be called under text_mutex.
*/ */
void *__kprobes text_poke(void *addr, const void *opcode, size_t len) void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
{ {
unsigned long flags;
char *vaddr; char *vaddr;
int nr_pages = 2;
struct page *pages[2]; struct page *pages[2];
int i; int i;
might_sleep();
if (!core_kernel_text((unsigned long)addr)) { if (!core_kernel_text((unsigned long)addr)) {
pages[0] = vmalloc_to_page(addr); pages[0] = vmalloc_to_page(addr);
pages[1] = vmalloc_to_page(addr + PAGE_SIZE); pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
...@@ -523,14 +526,17 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) ...@@ -523,14 +526,17 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
pages[1] = virt_to_page(addr + PAGE_SIZE); pages[1] = virt_to_page(addr + PAGE_SIZE);
} }
BUG_ON(!pages[0]); BUG_ON(!pages[0]);
if (!pages[1]) set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
nr_pages = 1; if (pages[1])
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
BUG_ON(!vaddr); vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
local_irq_disable(); local_irq_save(flags);
memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
local_irq_enable(); local_irq_restore(flags);
vunmap(vaddr); clear_fixmap(FIX_TEXT_POKE0);
if (pages[1])
clear_fixmap(FIX_TEXT_POKE1);
local_flush_tlb();
sync_core(); sync_core();
/* Could also do a CLFLUSH here to speed up CPU recovery; but /* Could also do a CLFLUSH here to speed up CPU recovery; but
that causes hangs on some VIA CPUs. */ that causes hangs on some VIA CPUs. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册