diff options
| author | Adrian Hunter <adrian.hunter@intel.com> | 2017-05-26 04:17:27 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-06-30 10:44:33 -0400 |
| commit | 0f3e53799cd5fad1dcc8c077a3d9cc260243328f (patch) | |
| tree | 6c02429573ca76c09ea0eb1b91652856457cb7e8 | |
| parent | 65c5e18f9df078f40abd22a3f6983eb9804b6d02 (diff) | |
perf intel-pt: Factor out common code synthesizing event samples
Factor out common code in functions synthesizing event samples i.e.
intel_pt_synth_branch_sample(), intel_pt_synth_instruction_sample() and
intel_pt_synth_transaction_sample().
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/1495786658-18063-27-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/util/intel-pt.c | 222 |
1 files changed, 100 insertions, 122 deletions
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 6df836469f2b..dbff5dca09f0 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
| @@ -1058,6 +1058,36 @@ static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq) | |||
| 1058 | bs->nr += 1; | 1058 | bs->nr += 1; |
| 1059 | } | 1059 | } |
| 1060 | 1060 | ||
| 1061 | static inline bool intel_pt_skip_event(struct intel_pt *pt) | ||
| 1062 | { | ||
| 1063 | return pt->synth_opts.initial_skip && | ||
| 1064 | pt->num_events++ < pt->synth_opts.initial_skip; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static void intel_pt_prep_b_sample(struct intel_pt *pt, | ||
| 1068 | struct intel_pt_queue *ptq, | ||
| 1069 | union perf_event *event, | ||
| 1070 | struct perf_sample *sample) | ||
| 1071 | { | ||
| 1072 | event->sample.header.type = PERF_RECORD_SAMPLE; | ||
| 1073 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
| 1074 | event->sample.header.size = sizeof(struct perf_event_header); | ||
| 1075 | |||
| 1076 | if (!pt->timeless_decoding) | ||
| 1077 | sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
| 1078 | |||
| 1079 | sample->cpumode = PERF_RECORD_MISC_USER; | ||
| 1080 | sample->ip = ptq->state->from_ip; | ||
| 1081 | sample->pid = ptq->pid; | ||
| 1082 | sample->tid = ptq->tid; | ||
| 1083 | sample->addr = ptq->state->to_ip; | ||
| 1084 | sample->period = 1; | ||
| 1085 | sample->cpu = ptq->cpu; | ||
| 1086 | sample->flags = ptq->flags; | ||
| 1087 | sample->insn_len = ptq->insn_len; | ||
| 1088 | memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
| 1089 | } | ||
| 1090 | |||
| 1061 | static int intel_pt_inject_event(union perf_event *event, | 1091 | static int intel_pt_inject_event(union perf_event *event, |
| 1062 | struct perf_sample *sample, u64 type, | 1092 | struct perf_sample *sample, u64 type, |
| 1063 | bool swapped) | 1093 | bool swapped) |
| @@ -1066,9 +1096,35 @@ static int intel_pt_inject_event(union perf_event *event, | |||
| 1066 | return perf_event__synthesize_sample(event, type, 0, sample, swapped); | 1096 | return perf_event__synthesize_sample(event, type, 0, sample, swapped); |
| 1067 | } | 1097 | } |
| 1068 | 1098 | ||
| 1069 | static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | 1099 | static inline int intel_pt_opt_inject(struct intel_pt *pt, |
| 1100 | union perf_event *event, | ||
| 1101 | struct perf_sample *sample, u64 type) | ||
| 1102 | { | ||
| 1103 | if (!pt->synth_opts.inject) | ||
| 1104 | return 0; | ||
| 1105 | |||
| 1106 | return intel_pt_inject_event(event, sample, type, pt->synth_needs_swap); | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | static int intel_pt_deliver_synth_b_event(struct intel_pt *pt, | ||
| 1110 | union perf_event *event, | ||
| 1111 | struct perf_sample *sample, u64 type) | ||
| 1070 | { | 1112 | { |
| 1071 | int ret; | 1113 | int ret; |
| 1114 | |||
| 1115 | ret = intel_pt_opt_inject(pt, event, sample, type); | ||
| 1116 | if (ret) | ||
| 1117 | return ret; | ||
| 1118 | |||
| 1119 | ret = perf_session__deliver_synth_event(pt->session, event, sample); | ||
| 1120 | if (ret) | ||
| 1121 | pr_err("Intel PT: failed to deliver event, error %d\n", ret); | ||
| 1122 | |||
| 1123 | return ret; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | ||
| 1127 | { | ||
| 1072 | struct intel_pt *pt = ptq->pt; | 1128 | struct intel_pt *pt = ptq->pt; |
| 1073 | union perf_event *event = ptq->event_buf; | 1129 | union perf_event *event = ptq->event_buf; |
| 1074 | struct perf_sample sample = { .ip = 0, }; | 1130 | struct perf_sample sample = { .ip = 0, }; |
| @@ -1080,29 +1136,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
| 1080 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) | 1136 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) |
| 1081 | return 0; | 1137 | return 0; |
| 1082 | 1138 | ||
| 1083 | if (pt->synth_opts.initial_skip && | 1139 | if (intel_pt_skip_event(pt)) |
| 1084 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
| 1085 | return 0; | 1140 | return 0; |
| 1086 | 1141 | ||
| 1087 | event->sample.header.type = PERF_RECORD_SAMPLE; | 1142 | intel_pt_prep_b_sample(pt, ptq, event, &sample); |
| 1088 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
| 1089 | event->sample.header.size = sizeof(struct perf_event_header); | ||
| 1090 | 1143 | ||
| 1091 | if (!pt->timeless_decoding) | ||
| 1092 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
| 1093 | |||
| 1094 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
| 1095 | sample.ip = ptq->state->from_ip; | ||
| 1096 | sample.pid = ptq->pid; | ||
| 1097 | sample.tid = ptq->tid; | ||
| 1098 | sample.addr = ptq->state->to_ip; | ||
| 1099 | sample.id = ptq->pt->branches_id; | 1144 | sample.id = ptq->pt->branches_id; |
| 1100 | sample.stream_id = ptq->pt->branches_id; | 1145 | sample.stream_id = ptq->pt->branches_id; |
| 1101 | sample.period = 1; | ||
| 1102 | sample.cpu = ptq->cpu; | ||
| 1103 | sample.flags = ptq->flags; | ||
| 1104 | sample.insn_len = ptq->insn_len; | ||
| 1105 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
| 1106 | 1146 | ||
| 1107 | /* | 1147 | /* |
| 1108 | * perf report cannot handle events without a branch stack when using | 1148 | * perf report cannot handle events without a branch stack when using |
| @@ -1119,78 +1159,38 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
| 1119 | sample.branch_stack = (struct branch_stack *)&dummy_bs; | 1159 | sample.branch_stack = (struct branch_stack *)&dummy_bs; |
| 1120 | } | 1160 | } |
| 1121 | 1161 | ||
| 1122 | if (pt->synth_opts.inject) { | 1162 | return intel_pt_deliver_synth_b_event(pt, event, &sample, |
| 1123 | ret = intel_pt_inject_event(event, &sample, | 1163 | pt->branches_sample_type); |
| 1124 | pt->branches_sample_type, | ||
| 1125 | pt->synth_needs_swap); | ||
| 1126 | if (ret) | ||
| 1127 | return ret; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | ||
| 1131 | if (ret) | ||
| 1132 | pr_err("Intel Processor Trace: failed to deliver branch event, error %d\n", | ||
| 1133 | ret); | ||
| 1134 | |||
| 1135 | return ret; | ||
| 1136 | } | 1164 | } |
| 1137 | 1165 | ||
| 1138 | static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | 1166 | static void intel_pt_prep_sample(struct intel_pt *pt, |
| 1167 | struct intel_pt_queue *ptq, | ||
| 1168 | union perf_event *event, | ||
| 1169 | struct perf_sample *sample) | ||
| 1139 | { | 1170 | { |
| 1140 | int ret; | 1171 | intel_pt_prep_b_sample(pt, ptq, event, sample); |
| 1141 | struct intel_pt *pt = ptq->pt; | ||
| 1142 | union perf_event *event = ptq->event_buf; | ||
| 1143 | struct perf_sample sample = { .ip = 0, }; | ||
| 1144 | |||
| 1145 | if (pt->synth_opts.initial_skip && | ||
| 1146 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
| 1147 | return 0; | ||
| 1148 | |||
| 1149 | event->sample.header.type = PERF_RECORD_SAMPLE; | ||
| 1150 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
| 1151 | event->sample.header.size = sizeof(struct perf_event_header); | ||
| 1152 | |||
| 1153 | if (!pt->timeless_decoding) | ||
| 1154 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
| 1155 | |||
| 1156 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
| 1157 | sample.ip = ptq->state->from_ip; | ||
| 1158 | sample.pid = ptq->pid; | ||
| 1159 | sample.tid = ptq->tid; | ||
| 1160 | sample.addr = ptq->state->to_ip; | ||
| 1161 | sample.id = ptq->pt->instructions_id; | ||
| 1162 | sample.stream_id = ptq->pt->instructions_id; | ||
| 1163 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; | ||
| 1164 | sample.cpu = ptq->cpu; | ||
| 1165 | sample.flags = ptq->flags; | ||
| 1166 | sample.insn_len = ptq->insn_len; | ||
| 1167 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
| 1168 | |||
| 1169 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; | ||
| 1170 | 1172 | ||
| 1171 | if (pt->synth_opts.callchain) { | 1173 | if (pt->synth_opts.callchain) { |
| 1172 | thread_stack__sample(ptq->thread, ptq->chain, | 1174 | thread_stack__sample(ptq->thread, ptq->chain, |
| 1173 | pt->synth_opts.callchain_sz, sample.ip); | 1175 | pt->synth_opts.callchain_sz, sample->ip); |
| 1174 | sample.callchain = ptq->chain; | 1176 | sample->callchain = ptq->chain; |
| 1175 | } | 1177 | } |
| 1176 | 1178 | ||
| 1177 | if (pt->synth_opts.last_branch) { | 1179 | if (pt->synth_opts.last_branch) { |
| 1178 | intel_pt_copy_last_branch_rb(ptq); | 1180 | intel_pt_copy_last_branch_rb(ptq); |
| 1179 | sample.branch_stack = ptq->last_branch; | 1181 | sample->branch_stack = ptq->last_branch; |
| 1180 | } | 1182 | } |
| 1183 | } | ||
| 1181 | 1184 | ||
| 1182 | if (pt->synth_opts.inject) { | 1185 | static inline int intel_pt_deliver_synth_event(struct intel_pt *pt, |
| 1183 | ret = intel_pt_inject_event(event, &sample, | 1186 | struct intel_pt_queue *ptq, |
| 1184 | pt->instructions_sample_type, | 1187 | union perf_event *event, |
| 1185 | pt->synth_needs_swap); | 1188 | struct perf_sample *sample, |
| 1186 | if (ret) | 1189 | u64 type) |
| 1187 | return ret; | 1190 | { |
| 1188 | } | 1191 | int ret; |
| 1189 | 1192 | ||
| 1190 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | 1193 | ret = intel_pt_deliver_synth_b_event(pt, event, sample, type); |
| 1191 | if (ret) | ||
| 1192 | pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", | ||
| 1193 | ret); | ||
| 1194 | 1194 | ||
| 1195 | if (pt->synth_opts.last_branch) | 1195 | if (pt->synth_opts.last_branch) |
| 1196 | intel_pt_reset_last_branch_rb(ptq); | 1196 | intel_pt_reset_last_branch_rb(ptq); |
| @@ -1198,65 +1198,43 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | |||
| 1198 | return ret; | 1198 | return ret; |
| 1199 | } | 1199 | } |
| 1200 | 1200 | ||
| 1201 | static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) | 1201 | static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) |
| 1202 | { | 1202 | { |
| 1203 | int ret; | ||
| 1204 | struct intel_pt *pt = ptq->pt; | 1203 | struct intel_pt *pt = ptq->pt; |
| 1205 | union perf_event *event = ptq->event_buf; | 1204 | union perf_event *event = ptq->event_buf; |
| 1206 | struct perf_sample sample = { .ip = 0, }; | 1205 | struct perf_sample sample = { .ip = 0, }; |
| 1207 | 1206 | ||
| 1208 | if (pt->synth_opts.initial_skip && | 1207 | if (intel_pt_skip_event(pt)) |
| 1209 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
| 1210 | return 0; | 1208 | return 0; |
| 1211 | 1209 | ||
| 1212 | event->sample.header.type = PERF_RECORD_SAMPLE; | 1210 | intel_pt_prep_sample(pt, ptq, event, &sample); |
| 1213 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
| 1214 | event->sample.header.size = sizeof(struct perf_event_header); | ||
| 1215 | 1211 | ||
| 1216 | if (!pt->timeless_decoding) | 1212 | sample.id = ptq->pt->instructions_id; |
| 1217 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | 1213 | sample.stream_id = ptq->pt->instructions_id; |
| 1214 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; | ||
| 1218 | 1215 | ||
| 1219 | sample.cpumode = PERF_RECORD_MISC_USER; | 1216 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; |
| 1220 | sample.ip = ptq->state->from_ip; | ||
| 1221 | sample.pid = ptq->pid; | ||
| 1222 | sample.tid = ptq->tid; | ||
| 1223 | sample.addr = ptq->state->to_ip; | ||
| 1224 | sample.id = ptq->pt->transactions_id; | ||
| 1225 | sample.stream_id = ptq->pt->transactions_id; | ||
| 1226 | sample.period = 1; | ||
| 1227 | sample.cpu = ptq->cpu; | ||
| 1228 | sample.flags = ptq->flags; | ||
| 1229 | sample.insn_len = ptq->insn_len; | ||
| 1230 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
| 1231 | 1217 | ||
| 1232 | if (pt->synth_opts.callchain) { | 1218 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, |
| 1233 | thread_stack__sample(ptq->thread, ptq->chain, | 1219 | pt->instructions_sample_type); |
| 1234 | pt->synth_opts.callchain_sz, sample.ip); | 1220 | } |
| 1235 | sample.callchain = ptq->chain; | ||
| 1236 | } | ||
| 1237 | 1221 | ||
| 1238 | if (pt->synth_opts.last_branch) { | 1222 | static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) |
| 1239 | intel_pt_copy_last_branch_rb(ptq); | 1223 | { |
| 1240 | sample.branch_stack = ptq->last_branch; | 1224 | struct intel_pt *pt = ptq->pt; |
| 1241 | } | 1225 | union perf_event *event = ptq->event_buf; |
| 1226 | struct perf_sample sample = { .ip = 0, }; | ||
| 1242 | 1227 | ||
| 1243 | if (pt->synth_opts.inject) { | 1228 | if (intel_pt_skip_event(pt)) |
| 1244 | ret = intel_pt_inject_event(event, &sample, | 1229 | return 0; |
| 1245 | pt->transactions_sample_type, | ||
| 1246 | pt->synth_needs_swap); | ||
| 1247 | if (ret) | ||
| 1248 | return ret; | ||
| 1249 | } | ||
| 1250 | 1230 | ||
| 1251 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | 1231 | intel_pt_prep_sample(pt, ptq, event, &sample); |
| 1252 | if (ret) | ||
| 1253 | pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", | ||
| 1254 | ret); | ||
| 1255 | 1232 | ||
| 1256 | if (pt->synth_opts.last_branch) | 1233 | sample.id = ptq->pt->transactions_id; |
| 1257 | intel_pt_reset_last_branch_rb(ptq); | 1234 | sample.stream_id = ptq->pt->transactions_id; |
| 1258 | 1235 | ||
| 1259 | return ret; | 1236 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, |
| 1237 | pt->transactions_sample_type); | ||
| 1260 | } | 1238 | } |
| 1261 | 1239 | ||
| 1262 | static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, | 1240 | static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, |
