diff options
| -rw-r--r-- | arch/x86/events/amd/core.c | 35 | ||||
| -rw-r--r-- | arch/x86/events/intel/core.c | 2 | ||||
| -rw-r--r-- | arch/x86/events/perf_event.h | 38 | ||||
| -rw-r--r-- | arch/x86/kernel/kprobes/core.c | 48 | ||||
| -rw-r--r-- | include/linux/kprobes.h | 1 | ||||
| -rw-r--r-- | kernel/events/core.c | 37 | ||||
| -rw-r--r-- | kernel/events/ring_buffer.c | 33 | ||||
| -rw-r--r-- | kernel/kprobes.c | 6 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 6 | ||||
| -rw-r--r-- | tools/include/uapi/sound/asound.h | 1 | ||||
| -rw-r--r-- | tools/lib/traceevent/event-parse.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-stat.c | 1 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 1 | ||||
| -rw-r--r-- | tools/perf/scripts/python/export-to-sqlite.py | 2 | ||||
| -rw-r--r-- | tools/perf/util/env.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 14 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 22 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 4 |
20 files changed, 195 insertions, 98 deletions
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index 0ecfac84ba91..d45f3fbd232e 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c | |||
| @@ -117,22 +117,39 @@ static __initconst const u64 amd_hw_cache_event_ids | |||
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | /* | 119 | /* |
| 120 | * AMD Performance Monitor K7 and later. | 120 | * AMD Performance Monitor K7 and later, up to and including Family 16h: |
| 121 | */ | 121 | */ |
| 122 | static const u64 amd_perfmon_event_map[PERF_COUNT_HW_MAX] = | 122 | static const u64 amd_perfmon_event_map[PERF_COUNT_HW_MAX] = |
| 123 | { | 123 | { |
| 124 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | 124 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, |
| 125 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | 125 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, |
| 126 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x077d, | 126 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x077d, |
| 127 | [PERF_COUNT_HW_CACHE_MISSES] = 0x077e, | 127 | [PERF_COUNT_HW_CACHE_MISSES] = 0x077e, |
| 128 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, | 128 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, |
| 129 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, | 129 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, |
| 130 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00d0, /* "Decoder empty" event */ | 130 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00d0, /* "Decoder empty" event */ |
| 131 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x00d1, /* "Dispatch stalls" event */ | 131 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x00d1, /* "Dispatch stalls" event */ |
| 132 | }; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * AMD Performance Monitor Family 17h and later: | ||
| 136 | */ | ||
| 137 | static const u64 amd_f17h_perfmon_event_map[PERF_COUNT_HW_MAX] = | ||
| 138 | { | ||
| 139 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | ||
| 140 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 141 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0xff60, | ||
| 142 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, | ||
| 143 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, | ||
| 144 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x0287, | ||
| 145 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x0187, | ||
| 132 | }; | 146 | }; |
| 133 | 147 | ||
| 134 | static u64 amd_pmu_event_map(int hw_event) | 148 | static u64 amd_pmu_event_map(int hw_event) |
| 135 | { | 149 | { |
| 150 | if (boot_cpu_data.x86 >= 0x17) | ||
| 151 | return amd_f17h_perfmon_event_map[hw_event]; | ||
| 152 | |||
| 136 | return amd_perfmon_event_map[hw_event]; | 153 | return amd_perfmon_event_map[hw_event]; |
| 137 | } | 154 | } |
| 138 | 155 | ||
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index f61dcbef20ff..f9451566cd9b 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c | |||
| @@ -3131,7 +3131,7 @@ static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event) | |||
| 3131 | flags &= ~PERF_SAMPLE_TIME; | 3131 | flags &= ~PERF_SAMPLE_TIME; |
| 3132 | if (!event->attr.exclude_kernel) | 3132 | if (!event->attr.exclude_kernel) |
| 3133 | flags &= ~PERF_SAMPLE_REGS_USER; | 3133 | flags &= ~PERF_SAMPLE_REGS_USER; |
| 3134 | if (event->attr.sample_regs_user & ~PEBS_REGS) | 3134 | if (event->attr.sample_regs_user & ~PEBS_GP_REGS) |
| 3135 | flags &= ~(PERF_SAMPLE_REGS_USER | PERF_SAMPLE_REGS_INTR); | 3135 | flags &= ~(PERF_SAMPLE_REGS_USER | PERF_SAMPLE_REGS_INTR); |
| 3136 | return flags; | 3136 | return flags; |
| 3137 | } | 3137 | } |
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index a75955741c50..1e98a42b560a 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h | |||
| @@ -96,25 +96,25 @@ struct amd_nb { | |||
| 96 | PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER | \ | 96 | PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER | \ |
| 97 | PERF_SAMPLE_PERIOD) | 97 | PERF_SAMPLE_PERIOD) |
| 98 | 98 | ||
| 99 | #define PEBS_REGS \ | 99 | #define PEBS_GP_REGS \ |
| 100 | (PERF_REG_X86_AX | \ | 100 | ((1ULL << PERF_REG_X86_AX) | \ |
| 101 | PERF_REG_X86_BX | \ | 101 | (1ULL << PERF_REG_X86_BX) | \ |
| 102 | PERF_REG_X86_CX | \ | 102 | (1ULL << PERF_REG_X86_CX) | \ |
| 103 | PERF_REG_X86_DX | \ | 103 | (1ULL << PERF_REG_X86_DX) | \ |
| 104 | PERF_REG_X86_DI | \ | 104 | (1ULL << PERF_REG_X86_DI) | \ |
| 105 | PERF_REG_X86_SI | \ | 105 | (1ULL << PERF_REG_X86_SI) | \ |
| 106 | PERF_REG_X86_SP | \ | 106 | (1ULL << PERF_REG_X86_SP) | \ |
| 107 | PERF_REG_X86_BP | \ | 107 | (1ULL << PERF_REG_X86_BP) | \ |
| 108 | PERF_REG_X86_IP | \ | 108 | (1ULL << PERF_REG_X86_IP) | \ |
| 109 | PERF_REG_X86_FLAGS | \ | 109 | (1ULL << PERF_REG_X86_FLAGS) | \ |
| 110 | PERF_REG_X86_R8 | \ | 110 | (1ULL << PERF_REG_X86_R8) | \ |
| 111 | PERF_REG_X86_R9 | \ | 111 | (1ULL << PERF_REG_X86_R9) | \ |
| 112 | PERF_REG_X86_R10 | \ | 112 | (1ULL << PERF_REG_X86_R10) | \ |
| 113 | PERF_REG_X86_R11 | \ | 113 | (1ULL << PERF_REG_X86_R11) | \ |
| 114 | PERF_REG_X86_R12 | \ | 114 | (1ULL << PERF_REG_X86_R12) | \ |
| 115 | PERF_REG_X86_R13 | \ | 115 | (1ULL << PERF_REG_X86_R13) | \ |
| 116 | PERF_REG_X86_R14 | \ | 116 | (1ULL << PERF_REG_X86_R14) | \ |
| 117 | PERF_REG_X86_R15) | 117 | (1ULL << PERF_REG_X86_R15)) |
| 118 | 118 | ||
| 119 | /* | 119 | /* |
| 120 | * Per register state. | 120 | * Per register state. |
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index a034cb808e7e..fed46ddb1eef 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
| @@ -569,6 +569,7 @@ void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 569 | unsigned long *sara = stack_addr(regs); | 569 | unsigned long *sara = stack_addr(regs); |
| 570 | 570 | ||
| 571 | ri->ret_addr = (kprobe_opcode_t *) *sara; | 571 | ri->ret_addr = (kprobe_opcode_t *) *sara; |
| 572 | ri->fp = sara; | ||
| 572 | 573 | ||
| 573 | /* Replace the return addr with trampoline addr */ | 574 | /* Replace the return addr with trampoline addr */ |
| 574 | *sara = (unsigned long) &kretprobe_trampoline; | 575 | *sara = (unsigned long) &kretprobe_trampoline; |
| @@ -748,26 +749,48 @@ asm( | |||
| 748 | NOKPROBE_SYMBOL(kretprobe_trampoline); | 749 | NOKPROBE_SYMBOL(kretprobe_trampoline); |
| 749 | STACK_FRAME_NON_STANDARD(kretprobe_trampoline); | 750 | STACK_FRAME_NON_STANDARD(kretprobe_trampoline); |
| 750 | 751 | ||
| 752 | static struct kprobe kretprobe_kprobe = { | ||
| 753 | .addr = (void *)kretprobe_trampoline, | ||
| 754 | }; | ||
| 755 | |||
| 751 | /* | 756 | /* |
| 752 | * Called from kretprobe_trampoline | 757 | * Called from kretprobe_trampoline |
| 753 | */ | 758 | */ |
| 754 | static __used void *trampoline_handler(struct pt_regs *regs) | 759 | static __used void *trampoline_handler(struct pt_regs *regs) |
| 755 | { | 760 | { |
| 761 | struct kprobe_ctlblk *kcb; | ||
| 756 | struct kretprobe_instance *ri = NULL; | 762 | struct kretprobe_instance *ri = NULL; |
| 757 | struct hlist_head *head, empty_rp; | 763 | struct hlist_head *head, empty_rp; |
| 758 | struct hlist_node *tmp; | 764 | struct hlist_node *tmp; |
| 759 | unsigned long flags, orig_ret_address = 0; | 765 | unsigned long flags, orig_ret_address = 0; |
| 760 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 766 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
| 761 | kprobe_opcode_t *correct_ret_addr = NULL; | 767 | kprobe_opcode_t *correct_ret_addr = NULL; |
| 768 | void *frame_pointer; | ||
| 769 | bool skipped = false; | ||
| 770 | |||
| 771 | preempt_disable(); | ||
| 772 | |||
| 773 | /* | ||
| 774 | * Set a dummy kprobe for avoiding kretprobe recursion. | ||
| 775 | * Since kretprobe never run in kprobe handler, kprobe must not | ||
| 776 | * be running at this point. | ||
| 777 | */ | ||
| 778 | kcb = get_kprobe_ctlblk(); | ||
| 779 | __this_cpu_write(current_kprobe, &kretprobe_kprobe); | ||
| 780 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 762 | 781 | ||
| 763 | INIT_HLIST_HEAD(&empty_rp); | 782 | INIT_HLIST_HEAD(&empty_rp); |
| 764 | kretprobe_hash_lock(current, &head, &flags); | 783 | kretprobe_hash_lock(current, &head, &flags); |
| 765 | /* fixup registers */ | 784 | /* fixup registers */ |
| 766 | #ifdef CONFIG_X86_64 | 785 | #ifdef CONFIG_X86_64 |
| 767 | regs->cs = __KERNEL_CS; | 786 | regs->cs = __KERNEL_CS; |
| 787 | /* On x86-64, we use pt_regs->sp for return address holder. */ | ||
| 788 | frame_pointer = ®s->sp; | ||
| 768 | #else | 789 | #else |
| 769 | regs->cs = __KERNEL_CS | get_kernel_rpl(); | 790 | regs->cs = __KERNEL_CS | get_kernel_rpl(); |
| 770 | regs->gs = 0; | 791 | regs->gs = 0; |
| 792 | /* On x86-32, we use pt_regs->flags for return address holder. */ | ||
| 793 | frame_pointer = ®s->flags; | ||
| 771 | #endif | 794 | #endif |
| 772 | regs->ip = trampoline_address; | 795 | regs->ip = trampoline_address; |
| 773 | regs->orig_ax = ~0UL; | 796 | regs->orig_ax = ~0UL; |
| @@ -789,8 +812,25 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 789 | if (ri->task != current) | 812 | if (ri->task != current) |
| 790 | /* another task is sharing our hash bucket */ | 813 | /* another task is sharing our hash bucket */ |
| 791 | continue; | 814 | continue; |
| 815 | /* | ||
| 816 | * Return probes must be pushed on this hash list correct | ||
| 817 | * order (same as return order) so that it can be poped | ||
| 818 | * correctly. However, if we find it is pushed it incorrect | ||
| 819 | * order, this means we find a function which should not be | ||
| 820 | * probed, because the wrong order entry is pushed on the | ||
| 821 | * path of processing other kretprobe itself. | ||
| 822 | */ | ||
| 823 | if (ri->fp != frame_pointer) { | ||
| 824 | if (!skipped) | ||
| 825 | pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n"); | ||
| 826 | skipped = true; | ||
| 827 | continue; | ||
| 828 | } | ||
| 792 | 829 | ||
| 793 | orig_ret_address = (unsigned long)ri->ret_addr; | 830 | orig_ret_address = (unsigned long)ri->ret_addr; |
| 831 | if (skipped) | ||
| 832 | pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n", | ||
| 833 | ri->rp->kp.addr); | ||
| 794 | 834 | ||
| 795 | if (orig_ret_address != trampoline_address) | 835 | if (orig_ret_address != trampoline_address) |
| 796 | /* | 836 | /* |
| @@ -808,14 +848,15 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 808 | if (ri->task != current) | 848 | if (ri->task != current) |
| 809 | /* another task is sharing our hash bucket */ | 849 | /* another task is sharing our hash bucket */ |
| 810 | continue; | 850 | continue; |
| 851 | if (ri->fp != frame_pointer) | ||
| 852 | continue; | ||
| 811 | 853 | ||
| 812 | orig_ret_address = (unsigned long)ri->ret_addr; | 854 | orig_ret_address = (unsigned long)ri->ret_addr; |
| 813 | if (ri->rp && ri->rp->handler) { | 855 | if (ri->rp && ri->rp->handler) { |
| 814 | __this_cpu_write(current_kprobe, &ri->rp->kp); | 856 | __this_cpu_write(current_kprobe, &ri->rp->kp); |
| 815 | get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 816 | ri->ret_addr = correct_ret_addr; | 857 | ri->ret_addr = correct_ret_addr; |
| 817 | ri->rp->handler(ri, regs); | 858 | ri->rp->handler(ri, regs); |
| 818 | __this_cpu_write(current_kprobe, NULL); | 859 | __this_cpu_write(current_kprobe, &kretprobe_kprobe); |
| 819 | } | 860 | } |
| 820 | 861 | ||
| 821 | recycle_rp_inst(ri, &empty_rp); | 862 | recycle_rp_inst(ri, &empty_rp); |
| @@ -831,6 +872,9 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 831 | 872 | ||
| 832 | kretprobe_hash_unlock(current, &flags); | 873 | kretprobe_hash_unlock(current, &flags); |
| 833 | 874 | ||
| 875 | __this_cpu_write(current_kprobe, NULL); | ||
| 876 | preempt_enable(); | ||
| 877 | |||
| 834 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { | 878 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { |
| 835 | hlist_del(&ri->hlist); | 879 | hlist_del(&ri->hlist); |
| 836 | kfree(ri); | 880 | kfree(ri); |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 201f0f2683f2..9a897256e481 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
| @@ -173,6 +173,7 @@ struct kretprobe_instance { | |||
| 173 | struct kretprobe *rp; | 173 | struct kretprobe *rp; |
| 174 | kprobe_opcode_t *ret_addr; | 174 | kprobe_opcode_t *ret_addr; |
| 175 | struct task_struct *task; | 175 | struct task_struct *task; |
| 176 | void *fp; | ||
| 176 | char data[0]; | 177 | char data[0]; |
| 177 | }; | 178 | }; |
| 178 | 179 | ||
diff --git a/kernel/events/core.c b/kernel/events/core.c index 534e01e7bc36..dc7dead2d2cc 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -9077,26 +9077,29 @@ static void perf_event_addr_filters_apply(struct perf_event *event) | |||
| 9077 | if (task == TASK_TOMBSTONE) | 9077 | if (task == TASK_TOMBSTONE) |
| 9078 | return; | 9078 | return; |
| 9079 | 9079 | ||
| 9080 | if (!ifh->nr_file_filters) | 9080 | if (ifh->nr_file_filters) { |
| 9081 | return; | 9081 | mm = get_task_mm(event->ctx->task); |
| 9082 | 9082 | if (!mm) | |
| 9083 | mm = get_task_mm(event->ctx->task); | 9083 | goto restart; |
| 9084 | if (!mm) | ||
| 9085 | goto restart; | ||
| 9086 | 9084 | ||
| 9087 | down_read(&mm->mmap_sem); | 9085 | down_read(&mm->mmap_sem); |
| 9086 | } | ||
| 9088 | 9087 | ||
| 9089 | raw_spin_lock_irqsave(&ifh->lock, flags); | 9088 | raw_spin_lock_irqsave(&ifh->lock, flags); |
| 9090 | list_for_each_entry(filter, &ifh->list, entry) { | 9089 | list_for_each_entry(filter, &ifh->list, entry) { |
| 9091 | event->addr_filter_ranges[count].start = 0; | 9090 | if (filter->path.dentry) { |
| 9092 | event->addr_filter_ranges[count].size = 0; | 9091 | /* |
| 9092 | * Adjust base offset if the filter is associated to a | ||
| 9093 | * binary that needs to be mapped: | ||
| 9094 | */ | ||
| 9095 | event->addr_filter_ranges[count].start = 0; | ||
| 9096 | event->addr_filter_ranges[count].size = 0; | ||
| 9093 | 9097 | ||
| 9094 | /* | ||
| 9095 | * Adjust base offset if the filter is associated to a binary | ||
| 9096 | * that needs to be mapped: | ||
| 9097 | */ | ||
| 9098 | if (filter->path.dentry) | ||
| 9099 | perf_addr_filter_apply(filter, mm, &event->addr_filter_ranges[count]); | 9098 | perf_addr_filter_apply(filter, mm, &event->addr_filter_ranges[count]); |
| 9099 | } else { | ||
| 9100 | event->addr_filter_ranges[count].start = filter->offset; | ||
| 9101 | event->addr_filter_ranges[count].size = filter->size; | ||
| 9102 | } | ||
| 9100 | 9103 | ||
| 9101 | count++; | 9104 | count++; |
| 9102 | } | 9105 | } |
| @@ -9104,9 +9107,11 @@ static void perf_event_addr_filters_apply(struct perf_event *event) | |||
| 9104 | event->addr_filters_gen++; | 9107 | event->addr_filters_gen++; |
| 9105 | raw_spin_unlock_irqrestore(&ifh->lock, flags); | 9108 | raw_spin_unlock_irqrestore(&ifh->lock, flags); |
| 9106 | 9109 | ||
| 9107 | up_read(&mm->mmap_sem); | 9110 | if (ifh->nr_file_filters) { |
| 9111 | up_read(&mm->mmap_sem); | ||
| 9108 | 9112 | ||
| 9109 | mmput(mm); | 9113 | mmput(mm); |
| 9114 | } | ||
| 9110 | 9115 | ||
| 9111 | restart: | 9116 | restart: |
| 9112 | perf_event_stop(event, 1); | 9117 | perf_event_stop(event, 1); |
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 2545ac08cc77..5eedb49a65ea 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
| @@ -455,24 +455,21 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size) | |||
| 455 | rb->aux_head += size; | 455 | rb->aux_head += size; |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | if (size || handle->aux_flags) { | 458 | /* |
| 459 | /* | 459 | * Only send RECORD_AUX if we have something useful to communicate |
| 460 | * Only send RECORD_AUX if we have something useful to communicate | 460 | * |
| 461 | * | 461 | * Note: the OVERWRITE records by themselves are not considered |
| 462 | * Note: the OVERWRITE records by themselves are not considered | 462 | * useful, as they don't communicate any *new* information, |
| 463 | * useful, as they don't communicate any *new* information, | 463 | * aside from the short-lived offset, that becomes history at |
| 464 | * aside from the short-lived offset, that becomes history at | 464 | * the next event sched-in and therefore isn't useful. |
| 465 | * the next event sched-in and therefore isn't useful. | 465 | * The userspace that needs to copy out AUX data in overwrite |
| 466 | * The userspace that needs to copy out AUX data in overwrite | 466 | * mode should know to use user_page::aux_head for the actual |
| 467 | * mode should know to use user_page::aux_head for the actual | 467 | * offset. So, from now on we don't output AUX records that |
| 468 | * offset. So, from now on we don't output AUX records that | 468 | * have *only* OVERWRITE flag set. |
| 469 | * have *only* OVERWRITE flag set. | 469 | */ |
| 470 | */ | 470 | if (size || (handle->aux_flags & ~(u64)PERF_AUX_FLAG_OVERWRITE)) |
| 471 | 471 | perf_event_aux_event(handle->event, aux_head, size, | |
| 472 | if (handle->aux_flags & ~(u64)PERF_AUX_FLAG_OVERWRITE) | 472 | handle->aux_flags); |
| 473 | perf_event_aux_event(handle->event, aux_head, size, | ||
| 474 | handle->aux_flags); | ||
| 475 | } | ||
| 476 | 473 | ||
| 477 | rb->user_page->aux_head = rb->aux_head; | 474 | rb->user_page->aux_head = rb->aux_head; |
| 478 | if (rb_need_aux_wakeup(rb)) | 475 | if (rb_need_aux_wakeup(rb)) |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index c83e54727131..b1ea30a5540e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -709,7 +709,6 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) | |||
| 709 | static int reuse_unused_kprobe(struct kprobe *ap) | 709 | static int reuse_unused_kprobe(struct kprobe *ap) |
| 710 | { | 710 | { |
| 711 | struct optimized_kprobe *op; | 711 | struct optimized_kprobe *op; |
| 712 | int ret; | ||
| 713 | 712 | ||
| 714 | /* | 713 | /* |
| 715 | * Unused kprobe MUST be on the way of delayed unoptimizing (means | 714 | * Unused kprobe MUST be on the way of delayed unoptimizing (means |
| @@ -720,9 +719,8 @@ static int reuse_unused_kprobe(struct kprobe *ap) | |||
| 720 | /* Enable the probe again */ | 719 | /* Enable the probe again */ |
| 721 | ap->flags &= ~KPROBE_FLAG_DISABLED; | 720 | ap->flags &= ~KPROBE_FLAG_DISABLED; |
| 722 | /* Optimize it again (remove from op->list) */ | 721 | /* Optimize it again (remove from op->list) */ |
| 723 | ret = kprobe_optready(ap); | 722 | if (!kprobe_optready(ap)) |
| 724 | if (ret) | 723 | return -EINVAL; |
| 725 | return ret; | ||
| 726 | 724 | ||
| 727 | optimize_kprobe(ap); | 725 | optimize_kprobe(ap); |
| 728 | return 0; | 726 | return 0; |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 26c8ca9bd06b..b920358dd8f7 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
| 34 | #include <linux/hash.h> | 34 | #include <linux/hash.h> |
| 35 | #include <linux/rcupdate.h> | 35 | #include <linux/rcupdate.h> |
| 36 | #include <linux/kprobes.h> | ||
| 36 | 37 | ||
| 37 | #include <trace/events/sched.h> | 38 | #include <trace/events/sched.h> |
| 38 | 39 | ||
| @@ -6246,7 +6247,7 @@ void ftrace_reset_array_ops(struct trace_array *tr) | |||
| 6246 | tr->ops->func = ftrace_stub; | 6247 | tr->ops->func = ftrace_stub; |
| 6247 | } | 6248 | } |
| 6248 | 6249 | ||
| 6249 | static inline void | 6250 | static nokprobe_inline void |
| 6250 | __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, | 6251 | __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, |
| 6251 | struct ftrace_ops *ignored, struct pt_regs *regs) | 6252 | struct ftrace_ops *ignored, struct pt_regs *regs) |
| 6252 | { | 6253 | { |
| @@ -6306,11 +6307,13 @@ static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, | |||
| 6306 | { | 6307 | { |
| 6307 | __ftrace_ops_list_func(ip, parent_ip, NULL, regs); | 6308 | __ftrace_ops_list_func(ip, parent_ip, NULL, regs); |
| 6308 | } | 6309 | } |
| 6310 | NOKPROBE_SYMBOL(ftrace_ops_list_func); | ||
| 6309 | #else | 6311 | #else |
| 6310 | static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip) | 6312 | static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip) |
| 6311 | { | 6313 | { |
| 6312 | __ftrace_ops_list_func(ip, parent_ip, NULL, NULL); | 6314 | __ftrace_ops_list_func(ip, parent_ip, NULL, NULL); |
| 6313 | } | 6315 | } |
| 6316 | NOKPROBE_SYMBOL(ftrace_ops_no_ops); | ||
| 6314 | #endif | 6317 | #endif |
| 6315 | 6318 | ||
| 6316 | /* | 6319 | /* |
| @@ -6337,6 +6340,7 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip, | |||
| 6337 | preempt_enable_notrace(); | 6340 | preempt_enable_notrace(); |
| 6338 | trace_clear_recursion(bit); | 6341 | trace_clear_recursion(bit); |
| 6339 | } | 6342 | } |
| 6343 | NOKPROBE_SYMBOL(ftrace_ops_assist_func); | ||
| 6340 | 6344 | ||
| 6341 | /** | 6345 | /** |
| 6342 | * ftrace_ops_get_func - get the function a trampoline should call | 6346 | * ftrace_ops_get_func - get the function a trampoline should call |
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h index 404d4b9ffe76..df1153cea0b7 100644 --- a/tools/include/uapi/sound/asound.h +++ b/tools/include/uapi/sound/asound.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | 32 | ||
| 33 | #ifndef __KERNEL__ | 33 | #ifndef __KERNEL__ |
| 34 | #include <stdlib.h> | 34 | #include <stdlib.h> |
| 35 | #include <time.h> | ||
| 35 | #endif | 36 | #endif |
| 36 | 37 | ||
| 37 | /* | 38 | /* |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 87494c7c619d..981c6ce2da2c 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
| @@ -2233,7 +2233,7 @@ eval_type_str(unsigned long long val, const char *type, int pointer) | |||
| 2233 | return val & 0xffffffff; | 2233 | return val & 0xffffffff; |
| 2234 | 2234 | ||
| 2235 | if (strcmp(type, "u64") == 0 || | 2235 | if (strcmp(type, "u64") == 0 || |
| 2236 | strcmp(type, "s64")) | 2236 | strcmp(type, "s64") == 0) |
| 2237 | return val; | 2237 | return val; |
| 2238 | 2238 | ||
| 2239 | if (strcmp(type, "s8") == 0) | 2239 | if (strcmp(type, "s8") == 0) |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 49ee3c2033ec..c3625ec374e0 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -1308,6 +1308,7 @@ static void init_features(struct perf_session *session) | |||
| 1308 | for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) | 1308 | for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) |
| 1309 | perf_header__set_feat(&session->header, feat); | 1309 | perf_header__set_feat(&session->header, feat); |
| 1310 | 1310 | ||
| 1311 | perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); | ||
| 1311 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); | 1312 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); |
| 1312 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); | 1313 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); |
| 1313 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); | 1314 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 1999d6533d12..fbbb0da43abb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -1377,6 +1377,7 @@ int cmd_top(int argc, const char **argv) | |||
| 1377 | * */ | 1377 | * */ |
| 1378 | .overwrite = 0, | 1378 | .overwrite = 0, |
| 1379 | .sample_time = true, | 1379 | .sample_time = true, |
| 1380 | .sample_time_set = true, | ||
| 1380 | }, | 1381 | }, |
| 1381 | .max_stack = sysctl__max_stack(), | 1382 | .max_stack = sysctl__max_stack(), |
| 1382 | .annotation_opts = annotation__default_options, | 1383 | .annotation_opts = annotation__default_options, |
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index 3b71902a5a21..bf271fbc3a88 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py | |||
| @@ -331,7 +331,7 @@ if perf_db_export_calls: | |||
| 331 | 'return_id,' | 331 | 'return_id,' |
| 332 | 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' | 332 | 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' |
| 333 | 'parent_call_path_id,' | 333 | 'parent_call_path_id,' |
| 334 | 'parent_id' | 334 | 'calls.parent_id' |
| 335 | ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') | 335 | ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') |
| 336 | 336 | ||
| 337 | do_query(query, 'CREATE VIEW samples_view AS ' | 337 | do_query(query, 'CREATE VIEW samples_view AS ' |
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index c6351b557bb0..9494f9dc61ec 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c | |||
| @@ -57,9 +57,11 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, | |||
| 57 | else if (prog_id > node->info_linear->info.id) | 57 | else if (prog_id > node->info_linear->info.id) |
| 58 | n = n->rb_right; | 58 | n = n->rb_right; |
| 59 | else | 59 | else |
| 60 | break; | 60 | goto out; |
| 61 | } | 61 | } |
| 62 | node = NULL; | ||
| 62 | 63 | ||
| 64 | out: | ||
| 63 | up_read(&env->bpf_progs.lock); | 65 | up_read(&env->bpf_progs.lock); |
| 64 | return node; | 66 | return node; |
| 65 | } | 67 | } |
| @@ -109,10 +111,12 @@ struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id) | |||
| 109 | else if (btf_id > node->id) | 111 | else if (btf_id > node->id) |
| 110 | n = n->rb_right; | 112 | n = n->rb_right; |
| 111 | else | 113 | else |
| 112 | break; | 114 | goto out; |
| 113 | } | 115 | } |
| 116 | node = NULL; | ||
| 114 | 117 | ||
| 115 | up_read(&env->bpf_progs.lock); | 118 | up_read(&env->bpf_progs.lock); |
| 119 | out: | ||
| 116 | return node; | 120 | return node; |
| 117 | } | 121 | } |
| 118 | 122 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6689378ee577..51ead577533f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -1868,12 +1868,12 @@ static void *perf_evlist__poll_thread(void *arg) | |||
| 1868 | { | 1868 | { |
| 1869 | struct perf_evlist *evlist = arg; | 1869 | struct perf_evlist *evlist = arg; |
| 1870 | bool draining = false; | 1870 | bool draining = false; |
| 1871 | int i; | 1871 | int i, done = 0; |
| 1872 | |||
| 1873 | while (!done) { | ||
| 1874 | bool got_data = false; | ||
| 1872 | 1875 | ||
| 1873 | while (draining || !(evlist->thread.done)) { | 1876 | if (evlist->thread.done) |
| 1874 | if (draining) | ||
| 1875 | draining = false; | ||
| 1876 | else if (evlist->thread.done) | ||
| 1877 | draining = true; | 1877 | draining = true; |
| 1878 | 1878 | ||
| 1879 | if (!draining) | 1879 | if (!draining) |
| @@ -1894,9 +1894,13 @@ static void *perf_evlist__poll_thread(void *arg) | |||
| 1894 | pr_warning("cannot locate proper evsel for the side band event\n"); | 1894 | pr_warning("cannot locate proper evsel for the side band event\n"); |
| 1895 | 1895 | ||
| 1896 | perf_mmap__consume(map); | 1896 | perf_mmap__consume(map); |
| 1897 | got_data = true; | ||
| 1897 | } | 1898 | } |
| 1898 | perf_mmap__read_done(map); | 1899 | perf_mmap__read_done(map); |
| 1899 | } | 1900 | } |
| 1901 | |||
| 1902 | if (draining && !got_data) | ||
| 1903 | break; | ||
| 1900 | } | 1904 | } |
| 1901 | return NULL; | 1905 | return NULL; |
| 1902 | } | 1906 | } |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 66d066f18b5b..966360844fff 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -2368,7 +2368,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
| 2368 | if (data->user_regs.abi) { | 2368 | if (data->user_regs.abi) { |
| 2369 | u64 mask = evsel->attr.sample_regs_user; | 2369 | u64 mask = evsel->attr.sample_regs_user; |
| 2370 | 2370 | ||
| 2371 | sz = hweight_long(mask) * sizeof(u64); | 2371 | sz = hweight64(mask) * sizeof(u64); |
| 2372 | OVERFLOW_CHECK(array, sz, max_size); | 2372 | OVERFLOW_CHECK(array, sz, max_size); |
| 2373 | data->user_regs.mask = mask; | 2373 | data->user_regs.mask = mask; |
| 2374 | data->user_regs.regs = (u64 *)array; | 2374 | data->user_regs.regs = (u64 *)array; |
| @@ -2424,7 +2424,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
| 2424 | if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { | 2424 | if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { |
| 2425 | u64 mask = evsel->attr.sample_regs_intr; | 2425 | u64 mask = evsel->attr.sample_regs_intr; |
| 2426 | 2426 | ||
| 2427 | sz = hweight_long(mask) * sizeof(u64); | 2427 | sz = hweight64(mask) * sizeof(u64); |
| 2428 | OVERFLOW_CHECK(array, sz, max_size); | 2428 | OVERFLOW_CHECK(array, sz, max_size); |
| 2429 | data->intr_regs.mask = mask; | 2429 | data->intr_regs.mask = mask; |
| 2430 | data->intr_regs.regs = (u64 *)array; | 2430 | data->intr_regs.regs = (u64 *)array; |
| @@ -2552,7 +2552,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, | |||
| 2552 | if (type & PERF_SAMPLE_REGS_USER) { | 2552 | if (type & PERF_SAMPLE_REGS_USER) { |
| 2553 | if (sample->user_regs.abi) { | 2553 | if (sample->user_regs.abi) { |
| 2554 | result += sizeof(u64); | 2554 | result += sizeof(u64); |
| 2555 | sz = hweight_long(sample->user_regs.mask) * sizeof(u64); | 2555 | sz = hweight64(sample->user_regs.mask) * sizeof(u64); |
| 2556 | result += sz; | 2556 | result += sz; |
| 2557 | } else { | 2557 | } else { |
| 2558 | result += sizeof(u64); | 2558 | result += sizeof(u64); |
| @@ -2580,7 +2580,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, | |||
| 2580 | if (type & PERF_SAMPLE_REGS_INTR) { | 2580 | if (type & PERF_SAMPLE_REGS_INTR) { |
| 2581 | if (sample->intr_regs.abi) { | 2581 | if (sample->intr_regs.abi) { |
| 2582 | result += sizeof(u64); | 2582 | result += sizeof(u64); |
| 2583 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | 2583 | sz = hweight64(sample->intr_regs.mask) * sizeof(u64); |
| 2584 | result += sz; | 2584 | result += sz; |
| 2585 | } else { | 2585 | } else { |
| 2586 | result += sizeof(u64); | 2586 | result += sizeof(u64); |
| @@ -2710,7 +2710,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
| 2710 | if (type & PERF_SAMPLE_REGS_USER) { | 2710 | if (type & PERF_SAMPLE_REGS_USER) { |
| 2711 | if (sample->user_regs.abi) { | 2711 | if (sample->user_regs.abi) { |
| 2712 | *array++ = sample->user_regs.abi; | 2712 | *array++ = sample->user_regs.abi; |
| 2713 | sz = hweight_long(sample->user_regs.mask) * sizeof(u64); | 2713 | sz = hweight64(sample->user_regs.mask) * sizeof(u64); |
| 2714 | memcpy(array, sample->user_regs.regs, sz); | 2714 | memcpy(array, sample->user_regs.regs, sz); |
| 2715 | array = (void *)array + sz; | 2715 | array = (void *)array + sz; |
| 2716 | } else { | 2716 | } else { |
| @@ -2746,7 +2746,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
| 2746 | if (type & PERF_SAMPLE_REGS_INTR) { | 2746 | if (type & PERF_SAMPLE_REGS_INTR) { |
| 2747 | if (sample->intr_regs.abi) { | 2747 | if (sample->intr_regs.abi) { |
| 2748 | *array++ = sample->intr_regs.abi; | 2748 | *array++ = sample->intr_regs.abi; |
| 2749 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | 2749 | sz = hweight64(sample->intr_regs.mask) * sizeof(u64); |
| 2750 | memcpy(array, sample->intr_regs.regs, sz); | 2750 | memcpy(array, sample->intr_regs.regs, sz); |
| 2751 | array = (void *)array + sz; | 2751 | array = (void *)array + sz; |
| 2752 | } else { | 2752 | } else { |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index b9e693825873..2d2af2ac2b1e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -2606,6 +2606,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused) | |||
| 2606 | perf_env__insert_bpf_prog_info(env, info_node); | 2606 | perf_env__insert_bpf_prog_info(env, info_node); |
| 2607 | } | 2607 | } |
| 2608 | 2608 | ||
| 2609 | up_write(&env->bpf_progs.lock); | ||
| 2609 | return 0; | 2610 | return 0; |
| 2610 | out: | 2611 | out: |
| 2611 | free(info_linear); | 2612 | free(info_linear); |
| @@ -2623,7 +2624,9 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _ | |||
| 2623 | static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused) | 2624 | static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused) |
| 2624 | { | 2625 | { |
| 2625 | struct perf_env *env = &ff->ph->env; | 2626 | struct perf_env *env = &ff->ph->env; |
| 2627 | struct btf_node *node = NULL; | ||
| 2626 | u32 count, i; | 2628 | u32 count, i; |
| 2629 | int err = -1; | ||
| 2627 | 2630 | ||
| 2628 | if (ff->ph->needs_swap) { | 2631 | if (ff->ph->needs_swap) { |
| 2629 | pr_warning("interpreting btf from systems with endianity is not yet supported\n"); | 2632 | pr_warning("interpreting btf from systems with endianity is not yet supported\n"); |
| @@ -2636,31 +2639,32 @@ static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused) | |||
| 2636 | down_write(&env->bpf_progs.lock); | 2639 | down_write(&env->bpf_progs.lock); |
| 2637 | 2640 | ||
| 2638 | for (i = 0; i < count; ++i) { | 2641 | for (i = 0; i < count; ++i) { |
| 2639 | struct btf_node *node; | ||
| 2640 | u32 id, data_size; | 2642 | u32 id, data_size; |
| 2641 | 2643 | ||
| 2642 | if (do_read_u32(ff, &id)) | 2644 | if (do_read_u32(ff, &id)) |
| 2643 | return -1; | 2645 | goto out; |
| 2644 | if (do_read_u32(ff, &data_size)) | 2646 | if (do_read_u32(ff, &data_size)) |
| 2645 | return -1; | 2647 | goto out; |
| 2646 | 2648 | ||
| 2647 | node = malloc(sizeof(struct btf_node) + data_size); | 2649 | node = malloc(sizeof(struct btf_node) + data_size); |
| 2648 | if (!node) | 2650 | if (!node) |
| 2649 | return -1; | 2651 | goto out; |
| 2650 | 2652 | ||
| 2651 | node->id = id; | 2653 | node->id = id; |
| 2652 | node->data_size = data_size; | 2654 | node->data_size = data_size; |
| 2653 | 2655 | ||
| 2654 | if (__do_read(ff, node->data, data_size)) { | 2656 | if (__do_read(ff, node->data, data_size)) |
| 2655 | free(node); | 2657 | goto out; |
| 2656 | return -1; | ||
| 2657 | } | ||
| 2658 | 2658 | ||
| 2659 | perf_env__insert_btf(env, node); | 2659 | perf_env__insert_btf(env, node); |
| 2660 | node = NULL; | ||
| 2660 | } | 2661 | } |
| 2661 | 2662 | ||
| 2663 | err = 0; | ||
| 2664 | out: | ||
| 2662 | up_write(&env->bpf_progs.lock); | 2665 | up_write(&env->bpf_progs.lock); |
| 2663 | return 0; | 2666 | free(node); |
| 2667 | return err; | ||
| 2664 | } | 2668 | } |
| 2665 | 2669 | ||
| 2666 | struct feature_ops { | 2670 | struct feature_ops { |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index e32628cd20a7..ee71efb9db62 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -261,6 +261,22 @@ bool __map__is_extra_kernel_map(const struct map *map) | |||
| 261 | return kmap && kmap->name[0]; | 261 | return kmap && kmap->name[0]; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | bool __map__is_bpf_prog(const struct map *map) | ||
| 265 | { | ||
| 266 | const char *name; | ||
| 267 | |||
| 268 | if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) | ||
| 269 | return true; | ||
| 270 | |||
| 271 | /* | ||
| 272 | * If PERF_RECORD_BPF_EVENT is not included, the dso will not have | ||
| 273 | * type of DSO_BINARY_TYPE__BPF_PROG_INFO. In such cases, we can | ||
| 274 | * guess the type based on name. | ||
| 275 | */ | ||
| 276 | name = map->dso->short_name; | ||
| 277 | return name && (strstr(name, "bpf_prog_") == name); | ||
| 278 | } | ||
| 279 | |||
| 264 | bool map__has_symbols(const struct map *map) | 280 | bool map__has_symbols(const struct map *map) |
| 265 | { | 281 | { |
| 266 | return dso__has_symbols(map->dso); | 282 | return dso__has_symbols(map->dso); |
| @@ -910,10 +926,8 @@ static void __maps__insert_name(struct maps *maps, struct map *map) | |||
| 910 | rc = strcmp(m->dso->short_name, map->dso->short_name); | 926 | rc = strcmp(m->dso->short_name, map->dso->short_name); |
| 911 | if (rc < 0) | 927 | if (rc < 0) |
| 912 | p = &(*p)->rb_left; | 928 | p = &(*p)->rb_left; |
| 913 | else if (rc > 0) | ||
| 914 | p = &(*p)->rb_right; | ||
| 915 | else | 929 | else |
| 916 | return; | 930 | p = &(*p)->rb_right; |
| 917 | } | 931 | } |
| 918 | rb_link_node(&map->rb_node_name, parent, p); | 932 | rb_link_node(&map->rb_node_name, parent, p); |
| 919 | rb_insert_color(&map->rb_node_name, &maps->names); | 933 | rb_insert_color(&map->rb_node_name, &maps->names); |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e20749f2c55..dc93787c74f0 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -159,10 +159,12 @@ int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, | |||
| 159 | 159 | ||
| 160 | bool __map__is_kernel(const struct map *map); | 160 | bool __map__is_kernel(const struct map *map); |
| 161 | bool __map__is_extra_kernel_map(const struct map *map); | 161 | bool __map__is_extra_kernel_map(const struct map *map); |
| 162 | bool __map__is_bpf_prog(const struct map *map); | ||
| 162 | 163 | ||
| 163 | static inline bool __map__is_kmodule(const struct map *map) | 164 | static inline bool __map__is_kmodule(const struct map *map) |
| 164 | { | 165 | { |
| 165 | return !__map__is_kernel(map) && !__map__is_extra_kernel_map(map); | 166 | return !__map__is_kernel(map) && !__map__is_extra_kernel_map(map) && |
| 167 | !__map__is_bpf_prog(map); | ||
| 166 | } | 168 | } |
| 167 | 169 | ||
| 168 | bool map__has_symbols(const struct map *map); | 170 | bool map__has_symbols(const struct map *map); |
