|
32 | 32 | #include <linux/debugfs.h> |
33 | 33 | #include <linux/sysctl.h> |
34 | 34 | #include <linux/kdebug.h> |
| 35 | +#include <linux/kthread.h> |
35 | 36 | #include <linux/memory.h> |
36 | 37 | #include <linux/ftrace.h> |
37 | 38 | #include <linux/cpu.h> |
|
40 | 41 | #include <linux/perf_event.h> |
41 | 42 | #include <linux/execmem.h> |
42 | 43 | #include <linux/cleanup.h> |
| 44 | +#include <linux/wait.h> |
43 | 45 |
|
44 | 46 | #include <asm/sections.h> |
45 | 47 | #include <asm/cacheflush.h> |
@@ -514,8 +516,18 @@ static LIST_HEAD(optimizing_list); |
514 | 516 | static LIST_HEAD(unoptimizing_list); |
515 | 517 | static LIST_HEAD(freeing_list); |
516 | 518 |
|
517 | | -static void kprobe_optimizer(struct work_struct *work); |
518 | | -static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer); |
| 519 | +static void optimize_kprobe(struct kprobe *p); |
| 520 | +static struct task_struct *kprobe_optimizer_task; |
| 521 | +static wait_queue_head_t kprobe_optimizer_wait; |
| 522 | +static atomic_t optimizer_state; |
| 523 | +enum { |
| 524 | + OPTIMIZER_ST_IDLE = 0, |
| 525 | + OPTIMIZER_ST_KICKED = 1, |
| 526 | + OPTIMIZER_ST_FLUSHING = 2, |
| 527 | +}; |
| 528 | + |
| 529 | +static DECLARE_COMPLETION(optimizer_completion); |
| 530 | + |
519 | 531 | #define OPTIMIZE_DELAY 5 |
520 | 532 |
|
521 | 533 | /* |
@@ -593,18 +605,25 @@ static void do_free_cleaned_kprobes(void) |
593 | 605 | */ |
594 | 606 | continue; |
595 | 607 | } |
| 608 | + |
| 609 | + /* |
| 610 | + * The aggregator was holding back another probe while it sat on the |
| 611 | + * unoptimizing/freeing lists. Now that the aggregator has been fully |
| 612 | + * reverted we can safely retry the optimization of that sibling. |
| 613 | + */ |
| 614 | + |
| 615 | + struct kprobe *_p = get_optimized_kprobe(op->kp.addr); |
| 616 | + if (unlikely(_p)) |
| 617 | + optimize_kprobe(_p); |
| 618 | + |
596 | 619 | free_aggr_kprobe(&op->kp); |
597 | 620 | } |
598 | 621 | } |
599 | 622 |
|
600 | | -/* Start optimizer after OPTIMIZE_DELAY passed */ |
601 | | -static void kick_kprobe_optimizer(void) |
602 | | -{ |
603 | | - schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY); |
604 | | -} |
| 623 | +static void kick_kprobe_optimizer(void); |
605 | 624 |
|
606 | 625 | /* Kprobe jump optimizer */ |
607 | | -static void kprobe_optimizer(struct work_struct *work) |
| 626 | +static void kprobe_optimizer(void) |
608 | 627 | { |
609 | 628 | guard(mutex)(&kprobe_mutex); |
610 | 629 |
|
@@ -635,23 +654,71 @@ static void kprobe_optimizer(struct work_struct *work) |
635 | 654 | do_free_cleaned_kprobes(); |
636 | 655 | } |
637 | 656 |
|
638 | | - /* Step 5: Kick optimizer again if needed */ |
| 657 | + /* Step 5: Kick optimizer again if needed. But if there is a flush requested, */ |
| 658 | + if (completion_done(&optimizer_completion)) |
| 659 | + complete(&optimizer_completion); |
| 660 | + |
639 | 661 | if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) |
640 | | - kick_kprobe_optimizer(); |
| 662 | + kick_kprobe_optimizer(); /*normal kick*/ |
| 663 | +} |
| 664 | + |
| 665 | +static int kprobe_optimizer_thread(void *data) |
| 666 | +{ |
| 667 | + while (!kthread_should_stop()) { |
| 668 | + /* To avoid hung_task, wait in interruptible state. */ |
| 669 | + wait_event_interruptible(kprobe_optimizer_wait, |
| 670 | + atomic_read(&optimizer_state) != OPTIMIZER_ST_IDLE || |
| 671 | + kthread_should_stop()); |
| 672 | + |
| 673 | + if (kthread_should_stop()) |
| 674 | + break; |
| 675 | + |
| 676 | + /* |
| 677 | + * If it was a normal kick, wait for OPTIMIZE_DELAY. |
| 678 | + * This wait can be interrupted by a flush request. |
| 679 | + */ |
| 680 | + if (atomic_read(&optimizer_state) == 1) |
| 681 | + wait_event_interruptible_timeout( |
| 682 | + kprobe_optimizer_wait, |
| 683 | + atomic_read(&optimizer_state) == OPTIMIZER_ST_FLUSHING || |
| 684 | + kthread_should_stop(), |
| 685 | + OPTIMIZE_DELAY); |
| 686 | + |
| 687 | + if (kthread_should_stop()) |
| 688 | + break; |
| 689 | + |
| 690 | + atomic_set(&optimizer_state, OPTIMIZER_ST_IDLE); |
| 691 | + |
| 692 | + kprobe_optimizer(); |
| 693 | + } |
| 694 | + return 0; |
| 695 | +} |
| 696 | + |
| 697 | +/* Start optimizer after OPTIMIZE_DELAY passed */ |
| 698 | +static void kick_kprobe_optimizer(void) |
| 699 | +{ |
| 700 | + lockdep_assert_held(&kprobe_mutex); |
| 701 | + if (atomic_cmpxchg(&optimizer_state, |
| 702 | + OPTIMIZER_ST_IDLE, OPTIMIZER_ST_KICKED) == OPTIMIZER_ST_IDLE) |
| 703 | + wake_up(&kprobe_optimizer_wait); |
641 | 704 | } |
642 | 705 |
|
643 | 706 | static void wait_for_kprobe_optimizer_locked(void) |
644 | 707 | { |
645 | 708 | lockdep_assert_held(&kprobe_mutex); |
646 | 709 |
|
647 | 710 | while (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) { |
648 | | - mutex_unlock(&kprobe_mutex); |
649 | | - |
650 | | - /* This will also make 'optimizing_work' execute immmediately */ |
651 | | - flush_delayed_work(&optimizing_work); |
652 | | - /* 'optimizing_work' might not have been queued yet, relax */ |
653 | | - cpu_relax(); |
| 711 | + init_completion(&optimizer_completion); |
| 712 | + /* |
| 713 | + * Set state to OPTIMIZER_ST_FLUSHING and wake up the thread if it's |
| 714 | + * idle. If it's already kicked, it will see the state change. |
| 715 | + */ |
| 716 | + if (atomic_xchg_acquire(&optimizer_state, |
| 717 | + OPTIMIZER_ST_FLUSHING) != OPTIMIZER_ST_FLUSHING) |
| 718 | + wake_up(&kprobe_optimizer_wait); |
654 | 719 |
|
| 720 | + mutex_unlock(&kprobe_mutex); |
| 721 | + wait_for_completion(&optimizer_completion); |
655 | 722 | mutex_lock(&kprobe_mutex); |
656 | 723 | } |
657 | 724 | } |
@@ -1002,16 +1069,23 @@ static void __disarm_kprobe(struct kprobe *p, bool reopt) |
1002 | 1069 | if (unlikely(_p) && reopt) |
1003 | 1070 | optimize_kprobe(_p); |
1004 | 1071 | } |
1005 | | - /* |
1006 | | - * TODO: Since unoptimization and real disarming will be done by |
1007 | | - * the worker thread, we can not check whether another probe are |
1008 | | - * unoptimized because of this probe here. It should be re-optimized |
1009 | | - * by the worker thread. |
1010 | | - */ |
1011 | 1072 | } |
1012 | 1073 |
|
| 1074 | +static void __init init_optprobe(void) |
| 1075 | +{ |
| 1076 | +#ifdef __ARCH_WANT_KPROBES_INSN_SLOT |
| 1077 | + /* Init 'kprobe_optinsn_slots' for allocation */ |
| 1078 | + kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE; |
| 1079 | +#endif |
| 1080 | + |
| 1081 | + init_waitqueue_head(&kprobe_optimizer_wait); |
| 1082 | + atomic_set(&optimizer_state, OPTIMIZER_ST_IDLE); |
| 1083 | + kprobe_optimizer_task = kthread_run(kprobe_optimizer_thread, NULL, |
| 1084 | + "kprobe-optimizer"); |
| 1085 | +} |
1013 | 1086 | #else /* !CONFIG_OPTPROBES */ |
1014 | 1087 |
|
| 1088 | +#define init_optprobe() do {} while (0) |
1015 | 1089 | #define optimize_kprobe(p) do {} while (0) |
1016 | 1090 | #define unoptimize_kprobe(p, f) do {} while (0) |
1017 | 1091 | #define kill_optimized_kprobe(p) do {} while (0) |
@@ -2694,10 +2768,8 @@ static int __init init_kprobes(void) |
2694 | 2768 | /* By default, kprobes are armed */ |
2695 | 2769 | kprobes_all_disarmed = false; |
2696 | 2770 |
|
2697 | | -#if defined(CONFIG_OPTPROBES) && defined(__ARCH_WANT_KPROBES_INSN_SLOT) |
2698 | | - /* Init 'kprobe_optinsn_slots' for allocation */ |
2699 | | - kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE; |
2700 | | -#endif |
| 2771 | + /* Initialize the optimization infrastructure */ |
| 2772 | + init_optprobe(); |
2701 | 2773 |
|
2702 | 2774 | err = arch_init_kprobes(); |
2703 | 2775 | if (!err) |
|
0 commit comments