aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/fixmap.h2
-rw-r--r--arch/x86/kernel/alternative.c24
2 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 63a79c77d220..81937a5dc77c 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -111,6 +111,8 @@ enum fixed_addresses {
111#ifdef CONFIG_PARAVIRT 111#ifdef CONFIG_PARAVIRT
112 FIX_PARAVIRT_BOOTMAP, 112 FIX_PARAVIRT_BOOTMAP,
113#endif 113#endif
114 FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */
115 FIX_TEXT_POKE1,
114 __end_of_permanent_fixed_addresses, 116 __end_of_permanent_fixed_addresses,
115#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT 117#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
116 FIX_OHCI1394_BASE, 118 FIX_OHCI1394_BASE,
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 092a7b8be68d..2d903b760ddb 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -13,7 +13,9 @@
13#include <asm/nmi.h> 13#include <asm/nmi.h>
14#include <asm/vsyscall.h> 14#include <asm/vsyscall.h>
15#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
16#include <asm/tlbflush.h>
16#include <asm/io.h> 17#include <asm/io.h>
18#include <asm/fixmap.h>
17 19
18#define MAX_PATCH_LEN (255-1) 20#define MAX_PATCH_LEN (255-1)
19 21
@@ -505,15 +507,16 @@ void *text_poke_early(void *addr, const void *opcode, size_t len)
505 * It means the size must be writable atomically and the address must be aligned 507 * It means the size must be writable atomically and the address must be aligned
506 * in a way that permits an atomic write. It also makes sure we fit on a single 508 * in a way that permits an atomic write. It also makes sure we fit on a single
507 * page. 509 * page.
510 *
511 * Note: Must be called under text_mutex.
508 */ 512 */
509void *__kprobes text_poke(void *addr, const void *opcode, size_t len) 513void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
510{ 514{
515 unsigned long flags;
511 char *vaddr; 516 char *vaddr;
512 int nr_pages = 2;
513 struct page *pages[2]; 517 struct page *pages[2];
514 int i; 518 int i;
515 519
516 might_sleep();
517 if (!core_kernel_text((unsigned long)addr)) { 520 if (!core_kernel_text((unsigned long)addr)) {
518 pages[0] = vmalloc_to_page(addr); 521 pages[0] = vmalloc_to_page(addr);
519 pages[1] = vmalloc_to_page(addr + PAGE_SIZE); 522 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 pages[1] = virt_to_page(addr + PAGE_SIZE); 526 pages[1] = virt_to_page(addr + PAGE_SIZE);
524 } 527 }
525 BUG_ON(!pages[0]); 528 BUG_ON(!pages[0]);
526 if (!pages[1]) 529 set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
527 nr_pages = 1; 530 if (pages[1])
528 vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); 531 set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
529 BUG_ON(!vaddr); 532 vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
530 local_irq_disable(); 533 local_irq_save(flags);
531 memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); 534 memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
532 local_irq_enable(); 535 local_irq_restore(flags);
533 vunmap(vaddr); 536 clear_fixmap(FIX_TEXT_POKE0);
537 if (pages[1])
538 clear_fixmap(FIX_TEXT_POKE1);
539 local_flush_tlb();
534 sync_core(); 540 sync_core();
535 /* Could also do a CLFLUSH here to speed up CPU recovery; but 541 /* Could also do a CLFLUSH here to speed up CPU recovery; but
536 that causes hangs on some VIA CPUs. */ 542 that causes hangs on some VIA CPUs. */