diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 165 |
1 files changed, 150 insertions, 15 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2d2af2ac2b1e..6a93ff5d8db5 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/kernel.h> #include <linux/bitops.h> +#include <linux/string.h> #include <linux/stringify.h> #include <sys/stat.h> #include <sys/utsname.h> @@ -43,7 +44,7 @@ #include "cputopo.h" #include "bpf-event.h" -#include "sane_ctype.h" +#include <linux/ctype.h> /* * magic2 = "PERFILE2" @@ -416,10 +417,8 @@ static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc) while (*p) { if (isspace(*p)) { char *r = p + 1; - char *q = r; + char *q = skip_spaces(r); *p = ' '; - while (*q && isspace(*q)) - q++; if (q != (p+1)) while ((*r++ = *q++)); } @@ -599,6 +598,27 @@ static int write_cpu_topology(struct feat_fd *ff, if (ret < 0) return ret; } + + if (!tp->die_sib) + goto done; + + ret = do_write(ff, &tp->die_sib, sizeof(tp->die_sib)); + if (ret < 0) + goto done; + + for (i = 0; i < tp->die_sib; i++) { + ret = do_write_string(ff, tp->die_siblings[i]); + if (ret < 0) + goto done; + } + + for (j = 0; j < perf_env.nr_cpus_avail; j++) { + ret = do_write(ff, &perf_env.cpu[j].die_id, + sizeof(perf_env.cpu[j].die_id)); + if (ret < 0) + return ret; + } + done: cpu_topology__delete(tp); return ret; @@ -1028,7 +1048,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev return -1; cache->type[len] = 0; - cache->type = rtrim(cache->type); + cache->type = strim(cache->type); scnprintf(file, PATH_MAX, "%s/size", path); if (sysfs__read_str(file, &cache->size, &len)) { @@ -1037,7 +1057,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev } cache->size[len] = 0; - cache->size = rtrim(cache->size); + cache->size = strim(cache->size); scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path); if (sysfs__read_str(file, &cache->map, &len)) { @@ -1047,7 +1067,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev } cache->map[len] = 0; - cache->map = rtrim(cache->map); + cache->map = strim(cache->map); return 0; } @@ -1100,7 +1120,7 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp) return 0; } -#define MAX_CACHES 2000 +#define MAX_CACHES (MAX_NR_CPUS * 4) static int write_cache(struct feat_fd *ff, struct perf_evlist *evlist __maybe_unused) @@ -1344,6 +1364,30 @@ out: return ret; } +static int write_compressed(struct feat_fd *ff __maybe_unused, + struct perf_evlist *evlist __maybe_unused) +{ + int ret; + + ret = do_write(ff, &(ff->ph->env.comp_ver), sizeof(ff->ph->env.comp_ver)); + if (ret) + return ret; + + ret = do_write(ff, &(ff->ph->env.comp_type), sizeof(ff->ph->env.comp_type)); + if (ret) + return ret; + + ret = do_write(ff, &(ff->ph->env.comp_level), sizeof(ff->ph->env.comp_level)); + if (ret) + return ret; + + ret = do_write(ff, &(ff->ph->env.comp_ratio), sizeof(ff->ph->env.comp_ratio)); + if (ret) + return ret; + + return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len)); +} + static void print_hostname(struct feat_fd *ff, FILE *fp) { fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); @@ -1415,10 +1459,20 @@ static void print_cpu_topology(struct feat_fd *ff, FILE *fp) str = ph->env.sibling_cores; for (i = 0; i < nr; i++) { - fprintf(fp, "# sibling cores : %s\n", str); + fprintf(fp, "# sibling sockets : %s\n", str); str += strlen(str) + 1; } + if (ph->env.nr_sibling_dies) { + nr = ph->env.nr_sibling_dies; + str = ph->env.sibling_dies; + + for (i = 0; i < nr; i++) { + fprintf(fp, "# sibling dies : %s\n", str); + str += strlen(str) + 1; + } + } + nr = ph->env.nr_sibling_threads; str = ph->env.sibling_threads; @@ -1427,12 +1481,28 @@ static void print_cpu_topology(struct feat_fd *ff, FILE *fp) str += strlen(str) + 1; } - if (ph->env.cpu != NULL) { - for (i = 0; i < cpu_nr; i++) - fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i, - ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id); - } else - fprintf(fp, "# Core ID and Socket ID information is not available\n"); + if (ph->env.nr_sibling_dies) { + if (ph->env.cpu != NULL) { + for (i = 0; i < cpu_nr; i++) + fprintf(fp, "# CPU %d: Core ID %d, " + "Die ID %d, Socket ID %d\n", + i, ph->env.cpu[i].core_id, + ph->env.cpu[i].die_id, + ph->env.cpu[i].socket_id); + } else + fprintf(fp, "# Core ID, Die ID and Socket ID " + "information is not available\n"); + } else { + if (ph->env.cpu != NULL) { + for (i = 0; i < cpu_nr; i++) + fprintf(fp, "# CPU %d: Core ID %d, " + "Socket ID %d\n", + i, ph->env.cpu[i].core_id, + ph->env.cpu[i].socket_id); + } else + fprintf(fp, "# Core ID and Socket ID " + "information is not available\n"); + } } static void print_clockid(struct feat_fd *ff, FILE *fp) @@ -1688,6 +1758,13 @@ static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused) } } +static void print_compressed(struct feat_fd *ff, FILE *fp) +{ + fprintf(fp, "# compressed : %s, level = %d, ratio = %d\n", + ff->ph->env.comp_type == PERF_COMP_ZSTD ? "Zstd" : "Unknown", + ff->ph->env.comp_level, ff->ph->env.comp_ratio); +} + static void print_pmu_mappings(struct feat_fd *ff, FILE *fp) { const char *delimiter = "# pmu mappings: "; @@ -2183,6 +2260,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) goto free_cpu; ph->env.cpu[i].core_id = nr; + size += sizeof(u32); if (do_read_u32(ff, &nr)) goto free_cpu; @@ -2194,6 +2272,40 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) } ph->env.cpu[i].socket_id = nr; + size += sizeof(u32); + } + + /* + * The header may be from old perf, + * which doesn't include die information. + */ + if (ff->size <= size) + return 0; + + if (do_read_u32(ff, &nr)) + return -1; + + ph->env.nr_sibling_dies = nr; + size += sizeof(u32); + + for (i = 0; i < nr; i++) { + str = do_read_string(ff); + if (!str) + goto error; + + /* include a NULL character at the end */ + if (strbuf_add(&sb, str, strlen(str) + 1) < 0) + goto error; + size += string_size(str); + free(str); + } + ph->env.sibling_dies = strbuf_detach(&sb, NULL); + + for (i = 0; i < (u32)cpu_nr; i++) { + if (do_read_u32(ff, &nr)) + goto free_cpu; + + ph->env.cpu[i].die_id = nr; } return 0; @@ -2667,6 +2779,27 @@ out: return err; } +static int process_compressed(struct feat_fd *ff, + void *data __maybe_unused) +{ + if (do_read_u32(ff, &(ff->ph->env.comp_ver))) + return -1; + + if (do_read_u32(ff, &(ff->ph->env.comp_type))) + return -1; + + if (do_read_u32(ff, &(ff->ph->env.comp_level))) + return -1; + + if (do_read_u32(ff, &(ff->ph->env.comp_ratio))) + return -1; + + if (do_read_u32(ff, &(ff->ph->env.comp_mmap_len))) + return -1; + + return 0; +} + struct feature_ops { int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); void (*print)(struct feat_fd *ff, FILE *fp); @@ -2730,6 +2863,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPN(DIR_FORMAT, dir_format, false), FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), FEAT_OPR(BPF_BTF, bpf_btf, false), + FEAT_OPR(COMPRESSED, compressed, false), }; struct header_print_data { @@ -3549,6 +3683,7 @@ int perf_event__synthesize_features(struct perf_tool *tool, return -ENOMEM; ff.size = sz - sz_hdr; + ff.ph = &session->header; for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { if (!feat_ops[feat].synthesize) { |