Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'perf-urgent-2020-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Thomas Gleixner:
"A set of fixes and improvements for the perf subsystem:

Kernel fixes:

- Install cgroup events to the correct CPU context to prevent a
potential list double add

- Prevent an integer underflow in the perf mlock accounting

- Add a missing prototype for arch_perf_update_userpage()

Tooling:

- Add a missing unlock in the error path of maps__insert() in perf
maps.

- Fix the build with the latest libbfd

- Fix the perf parser so it does not delete parse event terms, which
caused a regression for using perf with the ARM CoreSight as the
sink configuration was missing due to the deletion.

- Fix the double free in the perf CPU map merging test case

- Add the missing ustring support for the perf probe command"

* tag 'perf-urgent-2020-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf maps: Add missing unlock to maps__insert() error case
perf probe: Add ustring support for perf probe command
perf: Make perf able to build with latest libbfd
perf test: Fix test case Merge cpu map
perf parse: Copy string to perf_evsel_config_term
perf parse: Refactor 'struct perf_evsel_config_term'
kernel/events: Add a missing prototype for arch_perf_update_userpage()
perf/cgroups: Install cgroup events to correct cpuctx
perf/core: Fix mlock accounting in perf_mmap()

+88 -36
+4
include/linux/perf_event.h
··· 1544 1544 #define perf_event_exit_cpu NULL 1545 1545 #endif 1546 1546 1547 + extern void __weak arch_perf_update_userpage(struct perf_event *event, 1548 + struct perf_event_mmap_page *userpg, 1549 + u64 now); 1550 + 1547 1551 #endif /* _LINUX_PERF_EVENT_H */
+13 -4
kernel/events/core.c
··· 951 951 952 952 /* 953 953 * Because cgroup events are always per-cpu events, 954 - * this will always be called from the right CPU. 954 + * @ctx == &cpuctx->ctx. 955 955 */ 956 - cpuctx = __get_cpu_context(ctx); 956 + cpuctx = container_of(ctx, struct perf_cpu_context, ctx); 957 957 958 958 /* 959 959 * Since setting cpuctx->cgrp is conditional on the current @cgrp ··· 979 979 980 980 cpuctx_entry = &cpuctx->cgrp_cpuctx_entry; 981 981 if (add) 982 - list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list)); 982 + list_add(cpuctx_entry, 983 + per_cpu_ptr(&cgrp_cpuctx_list, event->cpu)); 983 984 else 984 985 list_del(cpuctx_entry); 985 986 } ··· 5917 5916 */ 5918 5917 user_lock_limit *= num_online_cpus(); 5919 5918 5920 - user_locked = atomic_long_read(&user->locked_vm) + user_extra; 5919 + user_locked = atomic_long_read(&user->locked_vm); 5920 + 5921 + /* 5922 + * sysctl_perf_event_mlock may have changed, so that 5923 + * user->locked_vm > user_lock_limit 5924 + */ 5925 + if (user_locked > user_lock_limit) 5926 + user_locked = user_lock_limit; 5927 + user_locked += user_extra; 5921 5928 5922 5929 if (user_locked > user_lock_limit) { 5923 5930 /*
+1 -1
tools/perf/arch/arm/util/cs-etm.c
··· 226 226 if (term->type != PERF_EVSEL__CONFIG_TERM_DRV_CFG) 227 227 continue; 228 228 229 - sink = term->val.drv_cfg; 229 + sink = term->val.str; 230 230 snprintf(path, PATH_MAX, "sinks/%s", sink); 231 231 232 232 ret = perf_pmu__scan_file(pmu, path, "%x", &hash);
-1
tools/perf/tests/cpumap.c
··· 131 131 TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr == 5); 132 132 cpu_map__snprint(c, buf, sizeof(buf)); 133 133 TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,7")); 134 - perf_cpu_map__put(a); 135 134 perf_cpu_map__put(b); 136 135 perf_cpu_map__put(c); 137 136 return 0;
+5 -3
tools/perf/util/evsel.c
··· 808 808 perf_evsel__reset_sample_bit(evsel, TIME); 809 809 break; 810 810 case PERF_EVSEL__CONFIG_TERM_CALLGRAPH: 811 - callgraph_buf = term->val.callgraph; 811 + callgraph_buf = term->val.str; 812 812 break; 813 813 case PERF_EVSEL__CONFIG_TERM_BRANCH: 814 - if (term->val.branch && strcmp(term->val.branch, "no")) { 814 + if (term->val.str && strcmp(term->val.str, "no")) { 815 815 perf_evsel__set_sample_bit(evsel, BRANCH_STACK); 816 - parse_branch_str(term->val.branch, 816 + parse_branch_str(term->val.str, 817 817 &attr->branch_sample_type); 818 818 } else 819 819 perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); ··· 1265 1265 1266 1266 list_for_each_entry_safe(term, h, &evsel->config_terms, list) { 1267 1267 list_del_init(&term->list); 1268 + if (term->free_str) 1269 + zfree(&term->val.str); 1268 1270 free(term); 1269 1271 } 1270 1272 }
+2 -3
tools/perf/util/evsel_config.h
··· 32 32 struct perf_evsel_config_term { 33 33 struct list_head list; 34 34 enum evsel_term_type type; 35 + bool free_str; 35 36 union { 36 37 u64 period; 37 38 u64 freq; 38 39 bool time; 39 - char *callgraph; 40 - char *drv_cfg; 41 40 u64 stack_user; 42 41 int max_stack; 43 42 bool inherit; 44 43 bool overwrite; 45 - char *branch; 46 44 unsigned long max_events; 47 45 bool percore; 48 46 bool aux_output; 49 47 u32 aux_sample_size; 50 48 u64 cfg_chg; 49 + char *str; 51 50 } val; 52 51 bool weak; 53 52 };
+1
tools/perf/util/map.c
··· 549 549 550 550 if (maps_by_name == NULL) { 551 551 __maps__free_maps_by_name(maps); 552 + up_write(&maps->lock); 552 553 return; 553 554 } 554 555
+45 -22
tools/perf/util/parse-events.c
··· 1219 1219 static int get_config_terms(struct list_head *head_config, 1220 1220 struct list_head *head_terms __maybe_unused) 1221 1221 { 1222 - #define ADD_CONFIG_TERM(__type, __name, __val) \ 1223 - do { \ 1222 + #define ADD_CONFIG_TERM(__type) \ 1224 1223 struct perf_evsel_config_term *__t; \ 1225 1224 \ 1226 1225 __t = zalloc(sizeof(*__t)); \ ··· 1228 1229 \ 1229 1230 INIT_LIST_HEAD(&__t->list); \ 1230 1231 __t->type = PERF_EVSEL__CONFIG_TERM_ ## __type; \ 1231 - __t->val.__name = __val; \ 1232 1232 __t->weak = term->weak; \ 1233 - list_add_tail(&__t->list, head_terms); \ 1233 + list_add_tail(&__t->list, head_terms) 1234 + 1235 + #define ADD_CONFIG_TERM_VAL(__type, __name, __val) \ 1236 + do { \ 1237 + ADD_CONFIG_TERM(__type); \ 1238 + __t->val.__name = __val; \ 1239 + } while (0) 1240 + 1241 + #define ADD_CONFIG_TERM_STR(__type, __val) \ 1242 + do { \ 1243 + ADD_CONFIG_TERM(__type); \ 1244 + __t->val.str = strdup(__val); \ 1245 + if (!__t->val.str) { \ 1246 + zfree(&__t); \ 1247 + return -ENOMEM; \ 1248 + } \ 1249 + __t->free_str = true; \ 1234 1250 } while (0) 1235 1251 1236 1252 struct parse_events_term *term; ··· 1253 1239 list_for_each_entry(term, head_config, list) { 1254 1240 switch (term->type_term) { 1255 1241 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 1256 - ADD_CONFIG_TERM(PERIOD, period, term->val.num); 1242 + ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num); 1257 1243 break; 1258 1244 case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 1259 - ADD_CONFIG_TERM(FREQ, freq, term->val.num); 1245 + ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num); 1260 1246 break; 1261 1247 case PARSE_EVENTS__TERM_TYPE_TIME: 1262 - ADD_CONFIG_TERM(TIME, time, term->val.num); 1248 + ADD_CONFIG_TERM_VAL(TIME, time, term->val.num); 1263 1249 break; 1264 1250 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1265 - ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str); 1251 + ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str); 1266 1252 break; 1267 1253 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 1268 - ADD_CONFIG_TERM(BRANCH, branch, term->val.str); 1254 + ADD_CONFIG_TERM_STR(BRANCH, term->val.str); 1269 1255 break; 1270 1256 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1271 - ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); 1257 + ADD_CONFIG_TERM_VAL(STACK_USER, stack_user, 1258 + term->val.num); 1272 1259 break; 1273 1260 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1274 - ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0); 1261 + ADD_CONFIG_TERM_VAL(INHERIT, inherit, 1262 + term->val.num ? 1 : 0); 1275 1263 break; 1276 1264 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1277 - ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); 1265 + ADD_CONFIG_TERM_VAL(INHERIT, inherit, 1266 + term->val.num ? 0 : 1); 1278 1267 break; 1279 1268 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1280 - ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); 1269 + ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack, 1270 + term->val.num); 1281 1271 break; 1282 1272 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1283 - ADD_CONFIG_TERM(MAX_EVENTS, max_events, term->val.num); 1273 + ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events, 1274 + term->val.num); 1284 1275 break; 1285 1276 case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1286 - ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); 1277 + ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 1278 + term->val.num ? 1 : 0); 1287 1279 break; 1288 1280 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1289 - ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1); 1281 + ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 1282 + term->val.num ? 0 : 1); 1290 1283 break; 1291 1284 case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 1292 - ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str); 1285 + ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str); 1293 1286 break; 1294 1287 case PARSE_EVENTS__TERM_TYPE_PERCORE: 1295 - ADD_CONFIG_TERM(PERCORE, percore, 1296 - term->val.num ? true : false); 1288 + ADD_CONFIG_TERM_VAL(PERCORE, percore, 1289 + term->val.num ? true : false); 1297 1290 break; 1298 1291 case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1299 - ADD_CONFIG_TERM(AUX_OUTPUT, aux_output, term->val.num ? 1 : 0); 1292 + ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output, 1293 + term->val.num ? 1 : 0); 1300 1294 break; 1301 1295 case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1302 - ADD_CONFIG_TERM(AUX_SAMPLE_SIZE, aux_sample_size, term->val.num); 1296 + ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size, 1297 + term->val.num); 1303 1298 break; 1304 1299 default: 1305 1300 break; ··· 1345 1322 } 1346 1323 1347 1324 if (bits) 1348 - ADD_CONFIG_TERM(CFG_CHG, cfg_chg, bits); 1325 + ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits); 1349 1326 1350 1327 #undef ADD_CONFIG_TERM 1351 1328 return 0;
+2 -1
tools/perf/util/probe-finder.c
··· 303 303 char prefix; 304 304 305 305 /* TODO: check all types */ 306 - if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 && 306 + if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "ustring") && 307 + strcmp(cast, "x") != 0 && 307 308 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) { 308 309 /* Non string type is OK */ 309 310 /* and respect signedness/hexadecimal cast */
+15 -1
tools/perf/util/srcline.c
··· 193 193 bfd_vma pc, vma; 194 194 bfd_size_type size; 195 195 struct a2l_data *a2l = data; 196 + flagword flags; 196 197 197 198 if (a2l->found) 198 199 return; 199 200 200 - if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) 201 + #ifdef bfd_get_section_flags 202 + flags = bfd_get_section_flags(abfd, section); 203 + #else 204 + flags = bfd_section_flags(section); 205 + #endif 206 + if ((flags & SEC_ALLOC) == 0) 201 207 return; 202 208 203 209 pc = a2l->addr; 210 + #ifdef bfd_get_section_vma 204 211 vma = bfd_get_section_vma(abfd, section); 212 + #else 213 + vma = bfd_section_vma(section); 214 + #endif 215 + #ifdef bfd_get_section_size 205 216 size = bfd_get_section_size(section); 217 + #else 218 + size = bfd_section_size(section); 219 + #endif 206 220 207 221 if (pc < vma || pc >= vma + size) 208 222 return;