perf fixes
Subsystems (2)
Linus,
Please pull the latest perf-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf-urgent-for-linus
# HEAD: 71e7bc2bab77e64882c031c2af943c3256c1adb0 perf/core: Check return value of the perf_event_read() IPI
Mostly tooling fixes, but also start/stop filter related fixes, a perf event read() fix, a fix uncovered by fuzzing, and an uprobes leak fix.
Thanks,
Ingo
------------------>
Adrian Hunter (2):
perf intel-pt: Fix ip compression
perf intel-pt: Fix occasional decoding errors when tracing system-wide
Anton Blanchard (1):
perf symbols: Fix annotation of objects with debuginfo files
Arnaldo Carvalho de Melo (3):
perf jitdump: Add the right header to get the major()/minor() definitions perf probe: Release resources on error when handling exit paths
tools: Sync kvm related header files for arm64 and s390
Colin Ian King (1):
perf probe: Check for dup and fdopen failures
David Carrillo-Cisneros (1):
perf/core: Check return value of the perf_event_read() IPI
He Kuang (2):
perf script: Show proper message when failed list scripts perf script: Don't disable use_callchain if input is pipe
Jiri Olsa (1):
perf tools mem: Fix -t store option for record command
Mathieu Poirier (3):
perf/core: Fix file name handling for start/stop filters perf/core: Update filters only on executable mmap perf/core: Enable mapping of the stop filters
Oleg Nesterov (1):
uprobes: Fix the memcg accounting
Peter Zijlstra (1):
perf/core: Fix event_function_local()
Ravi Bangoria (1):
perf ppc64le: Fix build failure when libelf is not present
kernel/events/core.c | 95 ++++++++++++++++------ kernel/events/uprobes.c | 5 +- tools/arch/arm64/include/uapi/asm/kvm.h | 2 + tools/arch/s390/include/uapi/asm/kvm.h | 41 ++++++++++ tools/arch/s390/include/uapi/asm/sie.h | 1 + tools/perf/arch/powerpc/util/sym-handling.c | 2 + tools/perf/arch/x86/util/intel-pt.c | 6 +- tools/perf/builtin-mem.c | 3 + tools/perf/builtin-script.c | 13 ++- .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 44 +++++----- .../util/intel-pt-decoder/intel-pt-pkt-decoder.c | 24 ++++-- tools/perf/util/jitdump.c | 1 + tools/perf/util/probe-file.c | 36 ++++++-- tools/perf/util/symbol-elf.c | 3 +- 14 files changed, 207 insertions(+), 69 deletions(-)
kernel/events/core.c +68 -27
@@ -242,18 +242,6 @@ static int event_function(void *info)return ret; } -static void event_function_local (struct perf_event *event,event_f func,void *data) -{ -struct event_function_struct efs = { - .event = event, - .func = func, - .data = data, - }; - -int ret =event_function (&efs); -WARN_ON_ONCE (ret); -} -static void event_function_call (struct perf_event *event,event_f func,void *data) {struct perf_event_context *ctx = event->ctx;
@@ -303,6 +291,54 @@ static void event_function_call(struct perf_event *event, event_f func, void *daraw_spin_unlock_irq (&ctx->lock); } +/* +* Similar to event_function_call() + event_function(), but hard assumes IRQs +* are already disabled and we're on the right CPU. +*/ +static void event_function_local (struct perf_event *event,event_f func,void *data) +{ +struct perf_event_context *ctx = event->ctx; +struct perf_cpu_context *cpuctx =__get_cpu_context (ctx); +struct task_struct *task =READ_ONCE (ctx->task); +struct perf_event_context *task_ctx =NULL ; + +WARN_ON_ONCE (!irqs_disabled ()); + +if (task) { +if (task ==TASK_TOMBSTONE ) +return ; + + task_ctx = ctx; + } + +perf_ctx_lock (cpuctx, task_ctx); + + task = ctx->task; +if (task ==TASK_TOMBSTONE ) + goto unlock; + +if (task) { +/* +* We must be either inactive or active and the right task, +* otherwise we're screwed, since we cannot IPI to somewhere +* else. +*/ +if (ctx->is_active) { +if (WARN_ON_ONCE (task != current)) + goto unlock; + +if (WARN_ON_ONCE (cpuctx->task_ctx != ctx)) + goto unlock; + } + }else { +WARN_ON_ONCE (&cpuctx->ctx != ctx); + } + +func (event, cpuctx, ctx, data); +unlock: +perf_ctx_unlock (cpuctx, task_ctx); +} +#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ PERF_FLAG_FD_OUTPUT |\ PERF_FLAG_PID_CGROUP |\
@@ -3513,9 +3549,10 @@ static int perf_event_read(struct perf_event *event, bool group) .group = group, .ret = 0, }; -smp_call_function_single (event->oncpu, - __perf_event_read, &data,1 ); - ret = data.ret; + ret =smp_call_function_single (event->oncpu, __perf_event_read, &data,1 ); +/* The event must have been read from an online CPU: */ +WARN_ON_ONCE (ret); + ret = ret ? : data.ret; }else if (event->state ==PERF_EVENT_STATE_INACTIVE ) {struct perf_event_context *ctx = event->ctx;unsigned long flags;
@@ -6584,15 +6621,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) }/* -* Whether this @filter depends on a dynamic object which is not loaded -* yet or its load addresses are not known. -*/ -static bool perf_addr_filter_needs_mmap (struct perf_addr_filter *filter) -{ -return filter->filter && filter->inode; -} - -/* * Check whether inode and address range match filter criteria. */ static bool perf_addr_filter_match(struct perf_addr_filter *filter,
@@ -6653,6 +6681,13 @@ static void perf_addr_filters_adjust(struct vm_area_struct *vma)struct perf_event_context *ctx;int ctxn; +/* +* Data tracing isn't supported yet and as such there is no need +* to keep track of anything that isn't related to executable code: +*/ +if (!(vma->vm_flags &VM_EXEC )) +return ; +rcu_read_lock ();for_each_task_context_nr (ctxn) { ctx =rcu_dereference (current->perf_event_ctxp[ctxn]);
@@ -7805,7 +7840,11 @@ static void perf_event_addr_filters_apply(struct perf_event *event)list_for_each_entry (filter, &ifh->list, entry) { event->addr_filters_offs[count] =0 ; -if (perf_addr_filter_needs_mmap (filter)) +/* +* Adjust base offset if the filter is associated to a binary +* that needs to be mapped: +*/ +if (filter->inode) event->addr_filters_offs[count] =perf_addr_filter_apply (filter, mm);
@@ -7936,8 +7975,10 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr, goto fail; } -if (token ==IF_SRC_FILE ) { - filename =match_strdup (&args[2 ]); +if (token ==IF_SRC_FILE || token ==IF_SRC_FILEADDR ) { +int fpos = filter->range ?2 :1 ; + + filename =match_strdup (&args[fpos]);if (!filename) { ret = -ENOMEM ; goto fail;
kernel/events/uprobes.c +3 -2
@@ -172,8 +172,10 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,mmu_notifier_invalidate_range_start (mm, mmun_start, mmun_end); err = -EAGAIN ; ptep =page_check_address (page, mm, addr, &ptl,0 ); -if (!ptep) +if (!ptep) { +mem_cgroup_cancel_charge (kpage, memcg, false); goto unlock; + }get_page (kpage);page_add_new_anon_rmap (kpage, vma, addr, false);
@@ -200,7 +202,6 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, err =0 ; unlock: -mem_cgroup_cancel_charge (kpage, memcg, false);mmu_notifier_invalidate_range_end (mm, mmun_start, mmun_end);unlock_page (page);return err;
tools/arch/arm64/include/uapi/asm/kvm.h +2 -0
@@ -87,9 +87,11 @@ struct kvm_regs {/* Supported VGICv3 address types */ #define KVM_VGIC_V3_ADDR_TYPE_DIST 2#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3 +#define KVM_VGIC_ITS_ADDR_TYPE 4#define KVM_VGIC_V3_DIST_SIZE SZ_64K#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K) +#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)#define KVM_ARM_VCPU_POWER_OFF 0/* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1/* CPU running a 32bit VM */
tools/arch/s390/include/uapi/asm/kvm.h +41 -0
47 lines not on this page · raw message
tools/arch/s390/include/uapi/asm/sie.h +1 -0
@@ -140,6 +140,7 @@exit_code_ipa0 (0xB2 ,0x4c ,"TAR" ), \exit_code_ipa0 (0xB2 ,0x50 ,"CSP" ), \exit_code_ipa0 (0xB2 ,0x54 ,"MVPG" ), \ +exit_code_ipa0 (0xB2 ,0x56 ,"STHYI" ), \exit_code_ipa0 (0xB2 ,0x58 ,"BSG" ), \exit_code_ipa0 (0xB2 ,0x5a ,"BSA" ), \ exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
tools/perf/arch/powerpc/util/sym-handling.c +2 -0
@@ -97,6 +97,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev, } } +#ifdef HAVE_LIBELF_SUPPORT void arch__post_process_probe_trace_events (struct perf_probe_event *pev,int ntevs) {
@@ -118,5 +119,6 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev, } } } +#endif /* HAVE_LIBELF_SUPPORT */ #endif
tools/perf/arch/x86/util/intel-pt.c +5 -1
@@ -501,7 +501,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,struct intel_pt_recording *ptr = container_of(itr, struct intel_pt_recording, itr);struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; -bool have_timing_info; +bool have_timing_info, need_immediate = false;struct perf_evsel *evsel, *intel_pt_evsel =NULL ;const struct cpu_map *cpus = evlist->cpus;bool privileged =geteuid () ==0 ||perf_event_paranoid () <0 ;
@@ -655,6 +655,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ptr->have_sched_switch =3 ; }else { opts->record_switch_events = true; + need_immediate = true;if (cpu_wide) ptr->have_sched_switch =3 ;else
@@ -700,6 +701,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, tracking_evsel->attr.freq =0 ; tracking_evsel->attr.sample_period =1 ; +if (need_immediate) + tracking_evsel->immediate = true; +/* In per-cpu case, always need the time of mmap events etc */ if (!cpu_map__empty (cpus)) {perf_evsel__set_sample_bit (tracking_evsel,TIME );
tools/perf/builtin-mem.c +3 -0
@@ -88,6 +88,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)if (mem->operation &MEM_OPERATION_LOAD ) perf_mem_events[PERF_MEM_EVENTS__LOAD ].record = true; +if (mem->operation &MEM_OPERATION_STORE ) + perf_mem_events[PERF_MEM_EVENTS__STORE ].record = true; +if (perf_mem_events[PERF_MEM_EVENTS__LOAD ].record) rec_argv[i++] ="-W" ;
tools/perf/builtin-script.c +10 -3
@@ -371,14 +371,16 @@ static int perf_session__check_output_opt(struct perf_session *session)if (!no_callchain) {bool use_callchain = false; +bool not_pipe = false;evlist__for_each_entry (session->evlist, evsel) { + not_pipe = true;if (evsel->attr.sample_type &PERF_SAMPLE_CALLCHAIN ) { use_callchain = true;break ; } } -if (!use_callchain) +if (not_pipe && !use_callchain) symbol_conf.use_callchain = false; }
@@ -1690,8 +1692,13 @@ static int list_available_scripts(const struct option *opt __maybe_unused,snprintf (scripts_path,MAXPATHLEN ,"%s/scripts" ,get_argv_exec_path ()); scripts_dir =opendir (scripts_path); -if (!scripts_dir) -return -1 ; +if (!scripts_dir) { +fprintf (stdout, +"open(%s) failed.\n" +"Check \"PERF_EXEC_PATH\" env to set scripts dir.\n" , + scripts_path); +exit (-1 ); + }for_each_lang (scripts_path, scripts_dir, lang_dirent) { snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +23 -21
108 lines not on this page · raw message
tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +17 -7
@@ -292,36 +292,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, const unsigned char *buf, size_t len, struct intel_pt_pkt *packet) { - switch (byte >> 5) { + int ip_len; + + packet->count = byte >>5 ; + +switch (packet->count) {case 0 : - packet->count = 0; + ip_len =0 ;break ;case 1 :if (len <3 )return INTEL_PT_NEED_MORE_BYTES ; - packet->count =2 ; + ip_len =2 ; packet->payload =le16_to_cpu (*(uint16_t *)(buf +1 ));break ;case 2 :if (len <5 )return INTEL_PT_NEED_MORE_BYTES ; - packet->count =4 ; + ip_len =4 ; packet->payload =le32_to_cpu (*(uint32_t *)(buf +1 ));break ;case 3 : -case 6 : +case 4 :if (len <7 )return INTEL_PT_NEED_MORE_BYTES ; - packet->count =6 ; + ip_len =6 ;memcpy_le64 (&packet->payload, buf +1 ,6 );break ; +case 6 : +if (len <9 ) +return INTEL_PT_NEED_MORE_BYTES ; + ip_len =8 ; + packet->payload =le64_to_cpu (*(uint64_t *)(buf +1 )); +break ;default :return INTEL_PT_BAD_PACKET ; } packet->type = type; -return packet->count +1 ; +return ip_len +1 ; } static int intel_pt_get_mode(const unsigned char *buf, size_t len,
tools/perf/util/jitdump.c +1 -0
@@ -1,3 +1,4 @@ +#include <sys/sysmacros.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h>
tools/perf/util/probe-file.c +29 -7
@@ -133,7 +133,7 @@ int probe_file__open_both(int *kfd, int *ufd, int flag)/* Get raw string list of current kprobe_events or uprobe_events */ struct strlist *probe_file__get_rawlist (int fd) { -int ret, idx; +int ret, idx, fddup;FILE *fp;char buf[MAX_CMDLEN ];char *p;
@@ -143,8 +143,17 @@ struct strlist *probe_file__get_rawlist(int fd)return NULL ; sl =strlist__new (NULL ,NULL ); +if (sl ==NULL ) +return NULL ; + + fddup =dup (fd); +if (fddup <0 ) + goto out_free_sl; + + fp =fdopen (fddup,"r" ); +if (!fp) + goto out_close_fddup; - fp =fdopen (dup (fd),"r" );while (!feof (fp)) { p =fgets (buf,MAX_CMDLEN , fp);if (!p)
@@ -156,13 +165,21 @@ struct strlist *probe_file__get_rawlist(int fd) ret =strlist__add (sl, buf);if (ret <0 ) {pr_debug ("strlist__add failed (%d)\n" , ret); -strlist__delete (sl); -return NULL ; + goto out_close_fp; } }fclose (fp);return sl; + +out_close_fp: +fclose (fp); + goto out_free_sl; +out_close_fddup: +close (fddup); +out_free_sl: +strlist__delete (sl); +return NULL ; }static struct strlist *__probe_file__get_namelist (int fd,bool include_group)
@@ -447,12 +464,17 @@ static int probe_cache__load(struct probe_cache *pcache) {struct probe_cache_entry *entry =NULL ;char buf[MAX_CMDLEN ], *p; -int ret =0 ; +int ret =0 , fddup;FILE *fp; - fp =fdopen (dup (pcache->fd),"r" ); -if (!fp) + fddup =dup (pcache->fd); +if (fddup <0 ) +return -errno; + fp =fdopen (fddup,"r" ); +if (!fp) { +close (fddup);return -EINVAL ; + }while (!feof (fp)) {if (!fgets (buf,MAX_CMDLEN , fp))
tools/perf/util/symbol-elf.c +2 -1
@@ -837,7 +837,8 @@ int dso__load_sym(struct dso *dso, struct map *map, sec = syms_ss->symtab; shdr = syms_ss->symshdr; -if (elf_section_by_name (elf, &ehdr, &tshdr,".text" ,NULL )) +if (elf_section_by_name (runtime_ss->elf, &runtime_ss->ehdr, &tshdr, +".text" ,NULL )) dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;if (runtime_ss->opdsec)