hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/tools/perf/util/arm-spe.c
....@@ -4,47 +4,86 @@
44 * Copyright (c) 2017-2018, Arm Ltd.
55 */
66
7
+#include <byteswap.h>
78 #include <endian.h>
89 #include <errno.h>
9
-#include <byteswap.h>
1010 #include <inttypes.h>
11
-#include <linux/kernel.h>
12
-#include <linux/types.h>
1311 #include <linux/bitops.h>
12
+#include <linux/kernel.h>
1413 #include <linux/log2.h>
14
+#include <linux/types.h>
15
+#include <linux/zalloc.h>
16
+#include <stdlib.h>
17
+#include <unistd.h>
1518
16
-#include "cpumap.h"
19
+#include "auxtrace.h"
1720 #include "color.h"
18
-#include "evsel.h"
21
+#include "debug.h"
1922 #include "evlist.h"
23
+#include "evsel.h"
2024 #include "machine.h"
2125 #include "session.h"
22
-#include "util.h"
26
+#include "symbol.h"
2327 #include "thread.h"
24
-#include "debug.h"
25
-#include "auxtrace.h"
28
+#include "thread-stack.h"
29
+#include "tool.h"
30
+#include "util/synthetic-events.h"
31
+
2632 #include "arm-spe.h"
27
-#include "arm-spe-pkt-decoder.h"
33
+#include "arm-spe-decoder/arm-spe-decoder.h"
34
+#include "arm-spe-decoder/arm-spe-pkt-decoder.h"
35
+
36
+#define MAX_TIMESTAMP (~0ULL)
2837
2938 struct arm_spe {
3039 struct auxtrace auxtrace;
3140 struct auxtrace_queues queues;
3241 struct auxtrace_heap heap;
42
+ struct itrace_synth_opts synth_opts;
3343 u32 auxtrace_type;
3444 struct perf_session *session;
3545 struct machine *machine;
3646 u32 pmu_type;
47
+
48
+ u8 timeless_decoding;
49
+ u8 data_queued;
50
+
51
+ u64 sample_type;
52
+ u8 sample_flc;
53
+ u8 sample_llc;
54
+ u8 sample_tlb;
55
+ u8 sample_branch;
56
+ u8 sample_remote_access;
57
+
58
+ u64 l1d_miss_id;
59
+ u64 l1d_access_id;
60
+ u64 llc_miss_id;
61
+ u64 llc_access_id;
62
+ u64 tlb_miss_id;
63
+ u64 tlb_access_id;
64
+ u64 branch_miss_id;
65
+ u64 remote_access_id;
66
+
67
+ u64 kernel_start;
68
+
69
+ unsigned long num_events;
3770 };
3871
3972 struct arm_spe_queue {
40
- struct arm_spe *spe;
41
- unsigned int queue_nr;
42
- struct auxtrace_buffer *buffer;
43
- bool on_heap;
44
- bool done;
45
- pid_t pid;
46
- pid_t tid;
47
- int cpu;
73
+ struct arm_spe *spe;
74
+ unsigned int queue_nr;
75
+ struct auxtrace_buffer *buffer;
76
+ struct auxtrace_buffer *old_buffer;
77
+ union perf_event *event_buf;
78
+ bool on_heap;
79
+ bool done;
80
+ pid_t pid;
81
+ pid_t tid;
82
+ int cpu;
83
+ struct arm_spe_decoder *decoder;
84
+ u64 time;
85
+ u64 timestamp;
86
+ struct thread *thread;
4887 };
4988
5089 static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
....@@ -93,12 +132,497 @@
93132 arm_spe_dump(spe, buf, len);
94133 }
95134
96
-static int arm_spe_process_event(struct perf_session *session __maybe_unused,
97
- union perf_event *event __maybe_unused,
98
- struct perf_sample *sample __maybe_unused,
99
- struct perf_tool *tool __maybe_unused)
135
+static int arm_spe_get_trace(struct arm_spe_buffer *b, void *data)
100136 {
137
+ struct arm_spe_queue *speq = data;
138
+ struct auxtrace_buffer *buffer = speq->buffer;
139
+ struct auxtrace_buffer *old_buffer = speq->old_buffer;
140
+ struct auxtrace_queue *queue;
141
+
142
+ queue = &speq->spe->queues.queue_array[speq->queue_nr];
143
+
144
+ buffer = auxtrace_buffer__next(queue, buffer);
145
+ /* If no more data, drop the previous auxtrace_buffer and return */
146
+ if (!buffer) {
147
+ if (old_buffer)
148
+ auxtrace_buffer__drop_data(old_buffer);
149
+ b->len = 0;
150
+ return 0;
151
+ }
152
+
153
+ speq->buffer = buffer;
154
+
155
+ /* If the aux_buffer doesn't have data associated, try to load it */
156
+ if (!buffer->data) {
157
+ /* get the file desc associated with the perf data file */
158
+ int fd = perf_data__fd(speq->spe->session->data);
159
+
160
+ buffer->data = auxtrace_buffer__get_data(buffer, fd);
161
+ if (!buffer->data)
162
+ return -ENOMEM;
163
+ }
164
+
165
+ b->len = buffer->size;
166
+ b->buf = buffer->data;
167
+
168
+ if (b->len) {
169
+ if (old_buffer)
170
+ auxtrace_buffer__drop_data(old_buffer);
171
+ speq->old_buffer = buffer;
172
+ } else {
173
+ auxtrace_buffer__drop_data(buffer);
174
+ return arm_spe_get_trace(b, data);
175
+ }
176
+
101177 return 0;
178
+}
179
+
180
+static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
181
+ unsigned int queue_nr)
182
+{
183
+ struct arm_spe_params params = { .get_trace = 0, };
184
+ struct arm_spe_queue *speq;
185
+
186
+ speq = zalloc(sizeof(*speq));
187
+ if (!speq)
188
+ return NULL;
189
+
190
+ speq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
191
+ if (!speq->event_buf)
192
+ goto out_free;
193
+
194
+ speq->spe = spe;
195
+ speq->queue_nr = queue_nr;
196
+ speq->pid = -1;
197
+ speq->tid = -1;
198
+ speq->cpu = -1;
199
+
200
+ /* params set */
201
+ params.get_trace = arm_spe_get_trace;
202
+ params.data = speq;
203
+
204
+ /* create new decoder */
205
+ speq->decoder = arm_spe_decoder_new(&params);
206
+ if (!speq->decoder)
207
+ goto out_free;
208
+
209
+ return speq;
210
+
211
+out_free:
212
+ zfree(&speq->event_buf);
213
+ free(speq);
214
+
215
+ return NULL;
216
+}
217
+
218
+static inline u8 arm_spe_cpumode(struct arm_spe *spe, u64 ip)
219
+{
220
+ return ip >= spe->kernel_start ?
221
+ PERF_RECORD_MISC_KERNEL :
222
+ PERF_RECORD_MISC_USER;
223
+}
224
+
225
+static void arm_spe_prep_sample(struct arm_spe *spe,
226
+ struct arm_spe_queue *speq,
227
+ union perf_event *event,
228
+ struct perf_sample *sample)
229
+{
230
+ struct arm_spe_record *record = &speq->decoder->record;
231
+
232
+ if (!spe->timeless_decoding)
233
+ sample->time = speq->timestamp;
234
+
235
+ sample->ip = record->from_ip;
236
+ sample->cpumode = arm_spe_cpumode(spe, sample->ip);
237
+ sample->pid = speq->pid;
238
+ sample->tid = speq->tid;
239
+ sample->addr = record->to_ip;
240
+ sample->period = 1;
241
+ sample->cpu = speq->cpu;
242
+
243
+ event->sample.header.type = PERF_RECORD_SAMPLE;
244
+ event->sample.header.misc = sample->cpumode;
245
+ event->sample.header.size = sizeof(struct perf_event_header);
246
+}
247
+
248
+static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
249
+{
250
+ event->header.size = perf_event__sample_event_size(sample, type, 0);
251
+ return perf_event__synthesize_sample(event, type, 0, sample);
252
+}
253
+
254
+static inline int
255
+arm_spe_deliver_synth_event(struct arm_spe *spe,
256
+ struct arm_spe_queue *speq __maybe_unused,
257
+ union perf_event *event,
258
+ struct perf_sample *sample)
259
+{
260
+ int ret;
261
+
262
+ if (spe->synth_opts.inject) {
263
+ ret = arm_spe__inject_event(event, sample, spe->sample_type);
264
+ if (ret)
265
+ return ret;
266
+ }
267
+
268
+ ret = perf_session__deliver_synth_event(spe->session, event, sample);
269
+ if (ret)
270
+ pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
271
+
272
+ return ret;
273
+}
274
+
275
+static int
276
+arm_spe_synth_spe_events_sample(struct arm_spe_queue *speq,
277
+ u64 spe_events_id)
278
+{
279
+ struct arm_spe *spe = speq->spe;
280
+ union perf_event *event = speq->event_buf;
281
+ struct perf_sample sample = { .ip = 0, };
282
+
283
+ arm_spe_prep_sample(spe, speq, event, &sample);
284
+
285
+ sample.id = spe_events_id;
286
+ sample.stream_id = spe_events_id;
287
+
288
+ return arm_spe_deliver_synth_event(spe, speq, event, &sample);
289
+}
290
+
291
+static int arm_spe_sample(struct arm_spe_queue *speq)
292
+{
293
+ const struct arm_spe_record *record = &speq->decoder->record;
294
+ struct arm_spe *spe = speq->spe;
295
+ int err;
296
+
297
+ if (spe->sample_flc) {
298
+ if (record->type & ARM_SPE_L1D_MISS) {
299
+ err = arm_spe_synth_spe_events_sample(
300
+ speq, spe->l1d_miss_id);
301
+ if (err)
302
+ return err;
303
+ }
304
+
305
+ if (record->type & ARM_SPE_L1D_ACCESS) {
306
+ err = arm_spe_synth_spe_events_sample(
307
+ speq, spe->l1d_access_id);
308
+ if (err)
309
+ return err;
310
+ }
311
+ }
312
+
313
+ if (spe->sample_llc) {
314
+ if (record->type & ARM_SPE_LLC_MISS) {
315
+ err = arm_spe_synth_spe_events_sample(
316
+ speq, spe->llc_miss_id);
317
+ if (err)
318
+ return err;
319
+ }
320
+
321
+ if (record->type & ARM_SPE_LLC_ACCESS) {
322
+ err = arm_spe_synth_spe_events_sample(
323
+ speq, spe->llc_access_id);
324
+ if (err)
325
+ return err;
326
+ }
327
+ }
328
+
329
+ if (spe->sample_tlb) {
330
+ if (record->type & ARM_SPE_TLB_MISS) {
331
+ err = arm_spe_synth_spe_events_sample(
332
+ speq, spe->tlb_miss_id);
333
+ if (err)
334
+ return err;
335
+ }
336
+
337
+ if (record->type & ARM_SPE_TLB_ACCESS) {
338
+ err = arm_spe_synth_spe_events_sample(
339
+ speq, spe->tlb_access_id);
340
+ if (err)
341
+ return err;
342
+ }
343
+ }
344
+
345
+ if (spe->sample_branch && (record->type & ARM_SPE_BRANCH_MISS)) {
346
+ err = arm_spe_synth_spe_events_sample(speq,
347
+ spe->branch_miss_id);
348
+ if (err)
349
+ return err;
350
+ }
351
+
352
+ if (spe->sample_remote_access &&
353
+ (record->type & ARM_SPE_REMOTE_ACCESS)) {
354
+ err = arm_spe_synth_spe_events_sample(speq,
355
+ spe->remote_access_id);
356
+ if (err)
357
+ return err;
358
+ }
359
+
360
+ return 0;
361
+}
362
+
363
+static int arm_spe_run_decoder(struct arm_spe_queue *speq, u64 *timestamp)
364
+{
365
+ struct arm_spe *spe = speq->spe;
366
+ int ret;
367
+
368
+ if (!spe->kernel_start)
369
+ spe->kernel_start = machine__kernel_start(spe->machine);
370
+
371
+ while (1) {
372
+ ret = arm_spe_decode(speq->decoder);
373
+ if (!ret) {
374
+ pr_debug("No data or all data has been processed.\n");
375
+ return 1;
376
+ }
377
+
378
+ /*
379
+ * Error is detected when decode SPE trace data, continue to
380
+ * the next trace data and find out more records.
381
+ */
382
+ if (ret < 0)
383
+ continue;
384
+
385
+ ret = arm_spe_sample(speq);
386
+ if (ret)
387
+ return ret;
388
+
389
+ if (!spe->timeless_decoding && speq->timestamp >= *timestamp) {
390
+ *timestamp = speq->timestamp;
391
+ return 0;
392
+ }
393
+ }
394
+
395
+ return 0;
396
+}
397
+
398
+static int arm_spe__setup_queue(struct arm_spe *spe,
399
+ struct auxtrace_queue *queue,
400
+ unsigned int queue_nr)
401
+{
402
+ struct arm_spe_queue *speq = queue->priv;
403
+ struct arm_spe_record *record;
404
+
405
+ if (list_empty(&queue->head) || speq)
406
+ return 0;
407
+
408
+ speq = arm_spe__alloc_queue(spe, queue_nr);
409
+
410
+ if (!speq)
411
+ return -ENOMEM;
412
+
413
+ queue->priv = speq;
414
+
415
+ if (queue->cpu != -1)
416
+ speq->cpu = queue->cpu;
417
+
418
+ if (!speq->on_heap) {
419
+ int ret;
420
+
421
+ if (spe->timeless_decoding)
422
+ return 0;
423
+
424
+retry:
425
+ ret = arm_spe_decode(speq->decoder);
426
+
427
+ if (!ret)
428
+ return 0;
429
+
430
+ if (ret < 0)
431
+ goto retry;
432
+
433
+ record = &speq->decoder->record;
434
+
435
+ speq->timestamp = record->timestamp;
436
+ ret = auxtrace_heap__add(&spe->heap, queue_nr, speq->timestamp);
437
+ if (ret)
438
+ return ret;
439
+ speq->on_heap = true;
440
+ }
441
+
442
+ return 0;
443
+}
444
+
445
+static int arm_spe__setup_queues(struct arm_spe *spe)
446
+{
447
+ unsigned int i;
448
+ int ret;
449
+
450
+ for (i = 0; i < spe->queues.nr_queues; i++) {
451
+ ret = arm_spe__setup_queue(spe, &spe->queues.queue_array[i], i);
452
+ if (ret)
453
+ return ret;
454
+ }
455
+
456
+ return 0;
457
+}
458
+
459
+static int arm_spe__update_queues(struct arm_spe *spe)
460
+{
461
+ if (spe->queues.new_data) {
462
+ spe->queues.new_data = false;
463
+ return arm_spe__setup_queues(spe);
464
+ }
465
+
466
+ return 0;
467
+}
468
+
469
+static bool arm_spe__is_timeless_decoding(struct arm_spe *spe)
470
+{
471
+ struct evsel *evsel;
472
+ struct evlist *evlist = spe->session->evlist;
473
+ bool timeless_decoding = true;
474
+
475
+ /*
476
+ * Circle through the list of event and complain if we find one
477
+ * with the time bit set.
478
+ */
479
+ evlist__for_each_entry(evlist, evsel) {
480
+ if ((evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
481
+ timeless_decoding = false;
482
+ }
483
+
484
+ return timeless_decoding;
485
+}
486
+
487
+static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,
488
+ struct auxtrace_queue *queue)
489
+{
490
+ struct arm_spe_queue *speq = queue->priv;
491
+ pid_t tid;
492
+
493
+ tid = machine__get_current_tid(spe->machine, speq->cpu);
494
+ if (tid != -1) {
495
+ speq->tid = tid;
496
+ thread__zput(speq->thread);
497
+ } else
498
+ speq->tid = queue->tid;
499
+
500
+ if ((!speq->thread) && (speq->tid != -1)) {
501
+ speq->thread = machine__find_thread(spe->machine, -1,
502
+ speq->tid);
503
+ }
504
+
505
+ if (speq->thread) {
506
+ speq->pid = speq->thread->pid_;
507
+ if (queue->cpu == -1)
508
+ speq->cpu = speq->thread->cpu;
509
+ }
510
+}
511
+
512
+static int arm_spe_process_queues(struct arm_spe *spe, u64 timestamp)
513
+{
514
+ unsigned int queue_nr;
515
+ u64 ts;
516
+ int ret;
517
+
518
+ while (1) {
519
+ struct auxtrace_queue *queue;
520
+ struct arm_spe_queue *speq;
521
+
522
+ if (!spe->heap.heap_cnt)
523
+ return 0;
524
+
525
+ if (spe->heap.heap_array[0].ordinal >= timestamp)
526
+ return 0;
527
+
528
+ queue_nr = spe->heap.heap_array[0].queue_nr;
529
+ queue = &spe->queues.queue_array[queue_nr];
530
+ speq = queue->priv;
531
+
532
+ auxtrace_heap__pop(&spe->heap);
533
+
534
+ if (spe->heap.heap_cnt) {
535
+ ts = spe->heap.heap_array[0].ordinal + 1;
536
+ if (ts > timestamp)
537
+ ts = timestamp;
538
+ } else {
539
+ ts = timestamp;
540
+ }
541
+
542
+ arm_spe_set_pid_tid_cpu(spe, queue);
543
+
544
+ ret = arm_spe_run_decoder(speq, &ts);
545
+ if (ret < 0) {
546
+ auxtrace_heap__add(&spe->heap, queue_nr, ts);
547
+ return ret;
548
+ }
549
+
550
+ if (!ret) {
551
+ ret = auxtrace_heap__add(&spe->heap, queue_nr, ts);
552
+ if (ret < 0)
553
+ return ret;
554
+ } else {
555
+ speq->on_heap = false;
556
+ }
557
+ }
558
+
559
+ return 0;
560
+}
561
+
562
+static int arm_spe_process_timeless_queues(struct arm_spe *spe, pid_t tid,
563
+ u64 time_)
564
+{
565
+ struct auxtrace_queues *queues = &spe->queues;
566
+ unsigned int i;
567
+ u64 ts = 0;
568
+
569
+ for (i = 0; i < queues->nr_queues; i++) {
570
+ struct auxtrace_queue *queue = &spe->queues.queue_array[i];
571
+ struct arm_spe_queue *speq = queue->priv;
572
+
573
+ if (speq && (tid == -1 || speq->tid == tid)) {
574
+ speq->time = time_;
575
+ arm_spe_set_pid_tid_cpu(spe, queue);
576
+ arm_spe_run_decoder(speq, &ts);
577
+ }
578
+ }
579
+ return 0;
580
+}
581
+
582
+static int arm_spe_process_event(struct perf_session *session,
583
+ union perf_event *event,
584
+ struct perf_sample *sample,
585
+ struct perf_tool *tool)
586
+{
587
+ int err = 0;
588
+ u64 timestamp;
589
+ struct arm_spe *spe = container_of(session->auxtrace,
590
+ struct arm_spe, auxtrace);
591
+
592
+ if (dump_trace)
593
+ return 0;
594
+
595
+ if (!tool->ordered_events) {
596
+ pr_err("SPE trace requires ordered events\n");
597
+ return -EINVAL;
598
+ }
599
+
600
+ if (sample->time && (sample->time != (u64) -1))
601
+ timestamp = sample->time;
602
+ else
603
+ timestamp = 0;
604
+
605
+ if (timestamp || spe->timeless_decoding) {
606
+ err = arm_spe__update_queues(spe);
607
+ if (err)
608
+ return err;
609
+ }
610
+
611
+ if (spe->timeless_decoding) {
612
+ if (event->header.type == PERF_RECORD_EXIT) {
613
+ err = arm_spe_process_timeless_queues(spe,
614
+ event->fork.tid,
615
+ sample->time);
616
+ }
617
+ } else if (timestamp) {
618
+ if (event->header.type == PERF_RECORD_EXIT) {
619
+ err = arm_spe_process_queues(spe, timestamp);
620
+ if (err)
621
+ return err;
622
+ }
623
+ }
624
+
625
+ return err;
102626 }
103627
104628 static int arm_spe_process_auxtrace_event(struct perf_session *session,
....@@ -107,30 +631,33 @@
107631 {
108632 struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
109633 auxtrace);
110
- struct auxtrace_buffer *buffer;
111
- off_t data_offset;
112
- int fd = perf_data__fd(session->data);
113
- int err;
114634
115
- if (perf_data__is_pipe(session->data)) {
116
- data_offset = 0;
117
- } else {
118
- data_offset = lseek(fd, 0, SEEK_CUR);
119
- if (data_offset == -1)
120
- return -errno;
121
- }
635
+ if (!spe->data_queued) {
636
+ struct auxtrace_buffer *buffer;
637
+ off_t data_offset;
638
+ int fd = perf_data__fd(session->data);
639
+ int err;
122640
123
- err = auxtrace_queues__add_event(&spe->queues, session, event,
124
- data_offset, &buffer);
125
- if (err)
126
- return err;
641
+ if (perf_data__is_pipe(session->data)) {
642
+ data_offset = 0;
643
+ } else {
644
+ data_offset = lseek(fd, 0, SEEK_CUR);
645
+ if (data_offset == -1)
646
+ return -errno;
647
+ }
127648
128
- /* Dump here now we have copied a piped trace out of the pipe */
129
- if (dump_trace) {
130
- if (auxtrace_buffer__get_data(buffer, fd)) {
131
- arm_spe_dump_event(spe, buffer->data,
132
- buffer->size);
133
- auxtrace_buffer__put_data(buffer);
649
+ err = auxtrace_queues__add_event(&spe->queues, session, event,
650
+ data_offset, &buffer);
651
+ if (err)
652
+ return err;
653
+
654
+ /* Dump here now we have copied a piped trace out of the pipe */
655
+ if (dump_trace) {
656
+ if (auxtrace_buffer__get_data(buffer, fd)) {
657
+ arm_spe_dump_event(spe, buffer->data,
658
+ buffer->size);
659
+ auxtrace_buffer__put_data(buffer);
660
+ }
134661 }
135662 }
136663
....@@ -140,7 +667,25 @@
140667 static int arm_spe_flush(struct perf_session *session __maybe_unused,
141668 struct perf_tool *tool __maybe_unused)
142669 {
143
- return 0;
670
+ struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
671
+ auxtrace);
672
+ int ret;
673
+
674
+ if (dump_trace)
675
+ return 0;
676
+
677
+ if (!tool->ordered_events)
678
+ return -EINVAL;
679
+
680
+ ret = arm_spe__update_queues(spe);
681
+ if (ret < 0)
682
+ return ret;
683
+
684
+ if (spe->timeless_decoding)
685
+ return arm_spe_process_timeless_queues(spe, -1,
686
+ MAX_TIMESTAMP - 1);
687
+
688
+ return arm_spe_process_queues(spe, MAX_TIMESTAMP);
144689 }
145690
146691 static void arm_spe_free_queue(void *priv)
....@@ -149,6 +694,9 @@
149694
150695 if (!speq)
151696 return;
697
+ thread__zput(speq->thread);
698
+ arm_spe_decoder_free(speq->decoder);
699
+ zfree(&speq->event_buf);
152700 free(speq);
153701 }
154702
....@@ -177,11 +725,19 @@
177725 free(spe);
178726 }
179727
728
+static bool arm_spe_evsel_is_auxtrace(struct perf_session *session,
729
+ struct evsel *evsel)
730
+{
731
+ struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe, auxtrace);
732
+
733
+ return evsel->core.attr.type == spe->pmu_type;
734
+}
735
+
180736 static const char * const arm_spe_info_fmts[] = {
181737 [ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n",
182738 };
183739
184
-static void arm_spe_print_info(u64 *arr)
740
+static void arm_spe_print_info(__u64 *arr)
185741 {
186742 if (!dump_trace)
187743 return;
....@@ -189,15 +745,195 @@
189745 fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
190746 }
191747
748
+struct arm_spe_synth {
749
+ struct perf_tool dummy_tool;
750
+ struct perf_session *session;
751
+};
752
+
753
+static int arm_spe_event_synth(struct perf_tool *tool,
754
+ union perf_event *event,
755
+ struct perf_sample *sample __maybe_unused,
756
+ struct machine *machine __maybe_unused)
757
+{
758
+ struct arm_spe_synth *arm_spe_synth =
759
+ container_of(tool, struct arm_spe_synth, dummy_tool);
760
+
761
+ return perf_session__deliver_synth_event(arm_spe_synth->session,
762
+ event, NULL);
763
+}
764
+
765
+static int arm_spe_synth_event(struct perf_session *session,
766
+ struct perf_event_attr *attr, u64 id)
767
+{
768
+ struct arm_spe_synth arm_spe_synth;
769
+
770
+ memset(&arm_spe_synth, 0, sizeof(struct arm_spe_synth));
771
+ arm_spe_synth.session = session;
772
+
773
+ return perf_event__synthesize_attr(&arm_spe_synth.dummy_tool, attr, 1,
774
+ &id, arm_spe_event_synth);
775
+}
776
+
777
+static void arm_spe_set_event_name(struct evlist *evlist, u64 id,
778
+ const char *name)
779
+{
780
+ struct evsel *evsel;
781
+
782
+ evlist__for_each_entry(evlist, evsel) {
783
+ if (evsel->core.id && evsel->core.id[0] == id) {
784
+ if (evsel->name)
785
+ zfree(&evsel->name);
786
+ evsel->name = strdup(name);
787
+ break;
788
+ }
789
+ }
790
+}
791
+
792
+static int
793
+arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
794
+{
795
+ struct evlist *evlist = session->evlist;
796
+ struct evsel *evsel;
797
+ struct perf_event_attr attr;
798
+ bool found = false;
799
+ u64 id;
800
+ int err;
801
+
802
+ evlist__for_each_entry(evlist, evsel) {
803
+ if (evsel->core.attr.type == spe->pmu_type) {
804
+ found = true;
805
+ break;
806
+ }
807
+ }
808
+
809
+ if (!found) {
810
+ pr_debug("No selected events with SPE trace data\n");
811
+ return 0;
812
+ }
813
+
814
+ memset(&attr, 0, sizeof(struct perf_event_attr));
815
+ attr.size = sizeof(struct perf_event_attr);
816
+ attr.type = PERF_TYPE_HARDWARE;
817
+ attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
818
+ attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
819
+ PERF_SAMPLE_PERIOD;
820
+ if (spe->timeless_decoding)
821
+ attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
822
+ else
823
+ attr.sample_type |= PERF_SAMPLE_TIME;
824
+
825
+ spe->sample_type = attr.sample_type;
826
+
827
+ attr.exclude_user = evsel->core.attr.exclude_user;
828
+ attr.exclude_kernel = evsel->core.attr.exclude_kernel;
829
+ attr.exclude_hv = evsel->core.attr.exclude_hv;
830
+ attr.exclude_host = evsel->core.attr.exclude_host;
831
+ attr.exclude_guest = evsel->core.attr.exclude_guest;
832
+ attr.sample_id_all = evsel->core.attr.sample_id_all;
833
+ attr.read_format = evsel->core.attr.read_format;
834
+
835
+ /* create new id val to be a fixed offset from evsel id */
836
+ id = evsel->core.id[0] + 1000000000;
837
+
838
+ if (!id)
839
+ id = 1;
840
+
841
+ if (spe->synth_opts.flc) {
842
+ spe->sample_flc = true;
843
+
844
+ /* Level 1 data cache miss */
845
+ err = arm_spe_synth_event(session, &attr, id);
846
+ if (err)
847
+ return err;
848
+ spe->l1d_miss_id = id;
849
+ arm_spe_set_event_name(evlist, id, "l1d-miss");
850
+ id += 1;
851
+
852
+ /* Level 1 data cache access */
853
+ err = arm_spe_synth_event(session, &attr, id);
854
+ if (err)
855
+ return err;
856
+ spe->l1d_access_id = id;
857
+ arm_spe_set_event_name(evlist, id, "l1d-access");
858
+ id += 1;
859
+ }
860
+
861
+ if (spe->synth_opts.llc) {
862
+ spe->sample_llc = true;
863
+
864
+ /* Last level cache miss */
865
+ err = arm_spe_synth_event(session, &attr, id);
866
+ if (err)
867
+ return err;
868
+ spe->llc_miss_id = id;
869
+ arm_spe_set_event_name(evlist, id, "llc-miss");
870
+ id += 1;
871
+
872
+ /* Last level cache access */
873
+ err = arm_spe_synth_event(session, &attr, id);
874
+ if (err)
875
+ return err;
876
+ spe->llc_access_id = id;
877
+ arm_spe_set_event_name(evlist, id, "llc-access");
878
+ id += 1;
879
+ }
880
+
881
+ if (spe->synth_opts.tlb) {
882
+ spe->sample_tlb = true;
883
+
884
+ /* TLB miss */
885
+ err = arm_spe_synth_event(session, &attr, id);
886
+ if (err)
887
+ return err;
888
+ spe->tlb_miss_id = id;
889
+ arm_spe_set_event_name(evlist, id, "tlb-miss");
890
+ id += 1;
891
+
892
+ /* TLB access */
893
+ err = arm_spe_synth_event(session, &attr, id);
894
+ if (err)
895
+ return err;
896
+ spe->tlb_access_id = id;
897
+ arm_spe_set_event_name(evlist, id, "tlb-access");
898
+ id += 1;
899
+ }
900
+
901
+ if (spe->synth_opts.branches) {
902
+ spe->sample_branch = true;
903
+
904
+ /* Branch miss */
905
+ err = arm_spe_synth_event(session, &attr, id);
906
+ if (err)
907
+ return err;
908
+ spe->branch_miss_id = id;
909
+ arm_spe_set_event_name(evlist, id, "branch-miss");
910
+ id += 1;
911
+ }
912
+
913
+ if (spe->synth_opts.remote_access) {
914
+ spe->sample_remote_access = true;
915
+
916
+ /* Remote access */
917
+ err = arm_spe_synth_event(session, &attr, id);
918
+ if (err)
919
+ return err;
920
+ spe->remote_access_id = id;
921
+ arm_spe_set_event_name(evlist, id, "remote-access");
922
+ id += 1;
923
+ }
924
+
925
+ return 0;
926
+}
927
+
192928 int arm_spe_process_auxtrace_info(union perf_event *event,
193929 struct perf_session *session)
194930 {
195
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
196
- size_t min_sz = sizeof(u64) * ARM_SPE_PMU_TYPE;
931
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
932
+ size_t min_sz = sizeof(u64) * ARM_SPE_AUXTRACE_PRIV_MAX;
197933 struct arm_spe *spe;
198934 int err;
199935
200
- if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
936
+ if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
201937 min_sz)
202938 return -EINVAL;
203939
....@@ -214,17 +950,41 @@
214950 spe->auxtrace_type = auxtrace_info->type;
215951 spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE];
216952
953
+ spe->timeless_decoding = arm_spe__is_timeless_decoding(spe);
217954 spe->auxtrace.process_event = arm_spe_process_event;
218955 spe->auxtrace.process_auxtrace_event = arm_spe_process_auxtrace_event;
219956 spe->auxtrace.flush_events = arm_spe_flush;
220957 spe->auxtrace.free_events = arm_spe_free_events;
221958 spe->auxtrace.free = arm_spe_free;
959
+ spe->auxtrace.evsel_is_auxtrace = arm_spe_evsel_is_auxtrace;
222960 session->auxtrace = &spe->auxtrace;
223961
224962 arm_spe_print_info(&auxtrace_info->priv[0]);
225963
964
+ if (dump_trace)
965
+ return 0;
966
+
967
+ if (session->itrace_synth_opts && session->itrace_synth_opts->set)
968
+ spe->synth_opts = *session->itrace_synth_opts;
969
+ else
970
+ itrace_synth_opts__set_default(&spe->synth_opts, false);
971
+
972
+ err = arm_spe_synth_events(spe, session);
973
+ if (err)
974
+ goto err_free_queues;
975
+
976
+ err = auxtrace_queues__process_index(&spe->queues, session);
977
+ if (err)
978
+ goto err_free_queues;
979
+
980
+ if (spe->queues.populated)
981
+ spe->data_queued = true;
982
+
226983 return 0;
227984
985
+err_free_queues:
986
+ auxtrace_queues__free(&spe->queues);
987
+ session->auxtrace = NULL;
228988 err_free:
229989 free(spe);
230990 return err;