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

perf kvm: Support printing attributions for dimensions

This patch adds header, entry callback and width for every dimension,
thus in TUI mode the tool can print items with the defined attributions.

Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230315145112.186603-2-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Leo Yan and committed by
Arnaldo Carvalho de Melo
fbb70bd3 c695d48a

+94 -3
+94 -3
tools/perf/builtin-kvm.c
··· 84 84 85 85 struct kvm_dimension { 86 86 const char *name; 87 + const char *header; 88 + int width; 87 89 int64_t (*cmp)(struct perf_hpp_fmt *fmt, struct hist_entry *left, 88 90 struct hist_entry *right); 91 + int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 92 + struct hist_entry *he); 89 93 }; 90 94 91 95 struct kvm_fmt { ··· 107 103 return -strcmp(left->kvm_info->name, right->kvm_info->name); 108 104 } 109 105 106 + static int fmt_width(struct perf_hpp_fmt *fmt, 107 + struct perf_hpp *hpp __maybe_unused, 108 + struct hists *hists __maybe_unused); 109 + 110 + static int ev_name_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 111 + struct hist_entry *he) 112 + { 113 + int width = fmt_width(fmt, hpp, he->hists); 114 + 115 + return scnprintf(hpp->buf, hpp->size, "%*s", width, he->kvm_info->name); 116 + } 117 + 110 118 static struct kvm_dimension dim_event = { 119 + .header = "Event name", 111 120 .name = "ev_name", 112 121 .cmp = ev_name_cmp, 122 + .entry = ev_name_entry, 123 + .width = 40, 113 124 }; 114 125 115 126 #define EV_METRIC_CMP(metric) \ ··· 150 131 EV_METRIC_CMP(min) 151 132 EV_METRIC_CMP(mean) 152 133 134 + #define EV_METRIC_ENTRY(metric) \ 135 + static int ev_entry_##metric(struct perf_hpp_fmt *fmt, \ 136 + struct perf_hpp *hpp, \ 137 + struct hist_entry *he) \ 138 + { \ 139 + struct kvm_event *event; \ 140 + int width = fmt_width(fmt, hpp, he->hists); \ 141 + struct perf_kvm_stat *perf_kvm; \ 142 + \ 143 + event = container_of(he, struct kvm_event, he); \ 144 + perf_kvm = event->perf_kvm; \ 145 + return scnprintf(hpp->buf, hpp->size, "%*lu", width, \ 146 + get_event_##metric(event, perf_kvm->trace_vcpu)); \ 147 + } 148 + 149 + EV_METRIC_ENTRY(time) 150 + EV_METRIC_ENTRY(count) 151 + EV_METRIC_ENTRY(max) 152 + EV_METRIC_ENTRY(min) 153 + 153 154 static struct kvm_dimension dim_time = { 155 + .header = "Time (ns)", 154 156 .name = "time", 155 157 .cmp = ev_cmp_time, 158 + .entry = ev_entry_time, 159 + .width = 12, 156 160 }; 157 161 158 162 static struct kvm_dimension dim_count = { 163 + .header = "Samples", 159 164 .name = "sample", 160 165 .cmp = ev_cmp_count, 166 + .entry = ev_entry_count, 167 + .width = 12, 161 168 }; 162 169 163 170 static struct kvm_dimension dim_max_time = { 171 + .header = "Max Time (ns)", 164 172 .name = "max_t", 165 173 .cmp = ev_cmp_max, 174 + .entry = ev_entry_max, 175 + .width = 14, 166 176 }; 167 177 168 178 static struct kvm_dimension dim_min_time = { 179 + .header = "Min Time (ns)", 169 180 .name = "min_t", 170 181 .cmp = ev_cmp_min, 182 + .entry = ev_entry_min, 183 + .width = 14, 171 184 }; 172 185 186 + static int ev_entry_mean(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 187 + struct hist_entry *he) 188 + { 189 + struct kvm_event *event; 190 + int width = fmt_width(fmt, hpp, he->hists); 191 + struct perf_kvm_stat *perf_kvm; 192 + 193 + event = container_of(he, struct kvm_event, he); 194 + perf_kvm = event->perf_kvm; 195 + return scnprintf(hpp->buf, hpp->size, "%*lu", width, 196 + get_event_mean(event, perf_kvm->trace_vcpu)); 197 + } 198 + 173 199 static struct kvm_dimension dim_mean_time = { 200 + .header = "Mean Time (ns)", 174 201 .name = "mean_t", 175 202 .cmp = ev_cmp_mean, 203 + .entry = ev_entry_mean, 204 + .width = 14, 176 205 }; 177 206 178 207 static struct kvm_dimension *dimensions[] = { ··· 232 165 &dim_mean_time, 233 166 NULL, 234 167 }; 168 + 169 + static int fmt_width(struct perf_hpp_fmt *fmt, 170 + struct perf_hpp *hpp __maybe_unused, 171 + struct hists *hists __maybe_unused) 172 + { 173 + struct kvm_fmt *kvm_fmt; 174 + 175 + kvm_fmt = container_of(fmt, struct kvm_fmt, fmt); 176 + return kvm_fmt->dim->width; 177 + } 178 + 179 + static int fmt_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 180 + struct hists *hists, int line __maybe_unused, 181 + int *span __maybe_unused) 182 + { 183 + struct kvm_fmt *kvm_fmt; 184 + struct kvm_dimension *dim; 185 + int width = fmt_width(fmt, hpp, hists); 186 + 187 + kvm_fmt = container_of(fmt, struct kvm_fmt, fmt); 188 + dim = kvm_fmt->dim; 189 + 190 + return scnprintf(hpp->buf, hpp->size, "%*s", width, dim->header); 191 + } 235 192 236 193 static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 237 194 { ··· 306 215 fmt->cmp = dim->cmp; 307 216 fmt->sort = dim->cmp; 308 217 fmt->color = NULL; 309 - fmt->entry = NULL; 310 - fmt->header = NULL; 311 - fmt->width = NULL; 218 + fmt->entry = dim->entry; 219 + fmt->header = fmt_header; 220 + fmt->width = fmt_width; 312 221 fmt->collapse = dim->cmp; 313 222 fmt->equal = fmt_equal; 314 223 fmt->free = fmt_free;