diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-05 13:50:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-05 13:50:22 -0500 |
commit | 660f6a360be399f4ebdd6572a3d24afe54e9bb1c (patch) | |
tree | 9c16463c495a656e34577d59c97b58997b61d242 /arch/x86/kernel/alternative.c | |
parent | 586fac13f8685bf9dfb32e1ee98bfb14f0dd0061 (diff) | |
parent | e5a11016643d1ab7172193591506d33a844734cc (diff) |
Merge branch 'perf-probes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-probes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: Issue at least one memory barrier in stop_machine_text_poke()
perf probe: Correct probe syntax on command line help
perf probe: Add lazy line matching support
perf probe: Show more lines after last line
perf probe: Check function address range strictly in line finder
perf probe: Use libdw callback routines
perf probe: Use elfutils-libdw for analyzing debuginfo
perf probe: Rename probe finder functions
perf probe: Fix bugs in line range finder
perf probe: Update perf probe document
perf probe: Do not show --line option without dwarf support
kprobes: Add documents of jump optimization
kprobes/x86: Support kprobes jump optimization on x86
x86: Add text_poke_smp for SMP cross modifying code
kprobes/x86: Cleanup save/restore registers
kprobes/x86: Boost probes when reentering
kprobes: Jump optimization sysctl interface
kprobes: Introduce kprobes jump optimization
kprobes: Introduce generic insn_slot framework
kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r-- | arch/x86/kernel/alternative.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index e6ea0342c8f8..3a4bf35c179b 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/mm.h> | 7 | #include <linux/mm.h> |
8 | #include <linux/vmalloc.h> | 8 | #include <linux/vmalloc.h> |
9 | #include <linux/memory.h> | 9 | #include <linux/memory.h> |
10 | #include <linux/stop_machine.h> | ||
10 | #include <asm/alternative.h> | 11 | #include <asm/alternative.h> |
11 | #include <asm/sections.h> | 12 | #include <asm/sections.h> |
12 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
@@ -572,3 +573,62 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | |||
572 | local_irq_restore(flags); | 573 | local_irq_restore(flags); |
573 | return addr; | 574 | return addr; |
574 | } | 575 | } |
576 | |||
577 | /* | ||
578 | * Cross-modifying kernel text with stop_machine(). | ||
579 | * This code originally comes from immediate value. | ||
580 | */ | ||
581 | static atomic_t stop_machine_first; | ||
582 | static int wrote_text; | ||
583 | |||
584 | struct text_poke_params { | ||
585 | void *addr; | ||
586 | const void *opcode; | ||
587 | size_t len; | ||
588 | }; | ||
589 | |||
590 | static int __kprobes stop_machine_text_poke(void *data) | ||
591 | { | ||
592 | struct text_poke_params *tpp = data; | ||
593 | |||
594 | if (atomic_dec_and_test(&stop_machine_first)) { | ||
595 | text_poke(tpp->addr, tpp->opcode, tpp->len); | ||
596 | smp_wmb(); /* Make sure other cpus see that this has run */ | ||
597 | wrote_text = 1; | ||
598 | } else { | ||
599 | while (!wrote_text) | ||
600 | cpu_relax(); | ||
601 | smp_mb(); /* Load wrote_text before following execution */ | ||
602 | } | ||
603 | |||
604 | flush_icache_range((unsigned long)tpp->addr, | ||
605 | (unsigned long)tpp->addr + tpp->len); | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | /** | ||
610 | * text_poke_smp - Update instructions on a live kernel on SMP | ||
611 | * @addr: address to modify | ||
612 | * @opcode: source of the copy | ||
613 | * @len: length to copy | ||
614 | * | ||
615 | * Modify multi-byte instruction by using stop_machine() on SMP. This allows | ||
616 | * user to poke/set multi-byte text on SMP. Only non-NMI/MCE code modifying | ||
617 | * should be allowed, since stop_machine() does _not_ protect code against | ||
618 | * NMI and MCE. | ||
619 | * | ||
620 | * Note: Must be called under get_online_cpus() and text_mutex. | ||
621 | */ | ||
622 | void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len) | ||
623 | { | ||
624 | struct text_poke_params tpp; | ||
625 | |||
626 | tpp.addr = addr; | ||
627 | tpp.opcode = opcode; | ||
628 | tpp.len = len; | ||
629 | atomic_set(&stop_machine_first, 1); | ||
630 | wrote_text = 0; | ||
631 | stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); | ||
632 | return addr; | ||
633 | } | ||
634 | |||