diff options
| -rw-r--r-- | arch/x86/include/asm/fixmap.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/alternative.c | 24 |
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 | */ |
| 509 | void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | 513 | void *__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. */ |
