aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/alternative.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r--arch/x86/kernel/alternative.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index df4099dc1c68..65c7857a90dd 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -511,31 +511,30 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
511 unsigned long flags; 511 unsigned long flags;
512 char *vaddr; 512 char *vaddr;
513 int nr_pages = 2; 513 int nr_pages = 2;
514 struct page *pages[2];
515 int i;
514 516
515 BUG_ON(len > sizeof(long)); 517 if (!core_kernel_text((unsigned long)addr)) {
516 BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1)) 518 pages[0] = vmalloc_to_page(addr);
517 - ((long)addr & ~(sizeof(long) - 1))); 519 pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
518 if (kernel_text_address((unsigned long)addr)) {
519 struct page *pages[2] = { virt_to_page(addr),
520 virt_to_page(addr + PAGE_SIZE) };
521 if (!pages[1])
522 nr_pages = 1;
523 vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
524 BUG_ON(!vaddr);
525 local_irq_save(flags);
526 memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
527 local_irq_restore(flags);
528 vunmap(vaddr);
529 } else { 520 } else {
530 /* 521 pages[0] = virt_to_page(addr);
531 * modules are in vmalloc'ed memory, always writable. 522 WARN_ON(!PageReserved(pages[0]));
532 */ 523 pages[1] = virt_to_page(addr + PAGE_SIZE);
533 local_irq_save(flags);
534 memcpy(addr, opcode, len);
535 local_irq_restore(flags);
536 } 524 }
525 BUG_ON(!pages[0]);
526 if (!pages[1])
527 nr_pages = 1;
528 vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
529 BUG_ON(!vaddr);
530 local_irq_save(flags);
531 memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
532 local_irq_restore(flags);
533 vunmap(vaddr);
537 sync_core(); 534 sync_core();
538 /* Could also do a CLFLUSH here to speed up CPU recovery; but 535 /* Could also do a CLFLUSH here to speed up CPU recovery; but
539 that causes hangs on some VIA CPUs. */ 536 that causes hangs on some VIA CPUs. */
537 for (i = 0; i < len; i++)
538 BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
540 return addr; 539 return addr;
541} 540}