This source file includes following definitions.
- arm_spe_dump
- arm_spe_dump_event
- arm_spe_process_event
- arm_spe_process_auxtrace_event
- arm_spe_flush
- arm_spe_free_queue
- arm_spe_free_events
- arm_spe_free
- arm_spe_print_info
- arm_spe_process_auxtrace_info
1
2
3
4
5
6
7 #include <endian.h>
8 #include <errno.h>
9 #include <byteswap.h>
10 #include <inttypes.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/bitops.h>
16 #include <linux/log2.h>
17 #include <linux/zalloc.h>
18
19 #include "color.h"
20 #include "evsel.h"
21 #include "machine.h"
22 #include "session.h"
23 #include "debug.h"
24 #include "auxtrace.h"
25 #include "arm-spe.h"
26 #include "arm-spe-pkt-decoder.h"
27
28 struct arm_spe {
29 struct auxtrace auxtrace;
30 struct auxtrace_queues queues;
31 struct auxtrace_heap heap;
32 u32 auxtrace_type;
33 struct perf_session *session;
34 struct machine *machine;
35 u32 pmu_type;
36 };
37
38 struct arm_spe_queue {
39 struct arm_spe *spe;
40 unsigned int queue_nr;
41 struct auxtrace_buffer *buffer;
42 bool on_heap;
43 bool done;
44 pid_t pid;
45 pid_t tid;
46 int cpu;
47 };
48
49 static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
50 unsigned char *buf, size_t len)
51 {
52 struct arm_spe_pkt packet;
53 size_t pos = 0;
54 int ret, pkt_len, i;
55 char desc[ARM_SPE_PKT_DESC_MAX];
56 const char *color = PERF_COLOR_BLUE;
57
58 color_fprintf(stdout, color,
59 ". ... ARM SPE data: size %zu bytes\n",
60 len);
61
62 while (len) {
63 ret = arm_spe_get_packet(buf, len, &packet);
64 if (ret > 0)
65 pkt_len = ret;
66 else
67 pkt_len = 1;
68 printf(".");
69 color_fprintf(stdout, color, " %08x: ", pos);
70 for (i = 0; i < pkt_len; i++)
71 color_fprintf(stdout, color, " %02x", buf[i]);
72 for (; i < 16; i++)
73 color_fprintf(stdout, color, " ");
74 if (ret > 0) {
75 ret = arm_spe_pkt_desc(&packet, desc,
76 ARM_SPE_PKT_DESC_MAX);
77 if (ret > 0)
78 color_fprintf(stdout, color, " %s\n", desc);
79 } else {
80 color_fprintf(stdout, color, " Bad packet!\n");
81 }
82 pos += pkt_len;
83 buf += pkt_len;
84 len -= pkt_len;
85 }
86 }
87
88 static void arm_spe_dump_event(struct arm_spe *spe, unsigned char *buf,
89 size_t len)
90 {
91 printf(".\n");
92 arm_spe_dump(spe, buf, len);
93 }
94
95 static int arm_spe_process_event(struct perf_session *session __maybe_unused,
96 union perf_event *event __maybe_unused,
97 struct perf_sample *sample __maybe_unused,
98 struct perf_tool *tool __maybe_unused)
99 {
100 return 0;
101 }
102
103 static int arm_spe_process_auxtrace_event(struct perf_session *session,
104 union perf_event *event,
105 struct perf_tool *tool __maybe_unused)
106 {
107 struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
108 auxtrace);
109 struct auxtrace_buffer *buffer;
110 off_t data_offset;
111 int fd = perf_data__fd(session->data);
112 int err;
113
114 if (perf_data__is_pipe(session->data)) {
115 data_offset = 0;
116 } else {
117 data_offset = lseek(fd, 0, SEEK_CUR);
118 if (data_offset == -1)
119 return -errno;
120 }
121
122 err = auxtrace_queues__add_event(&spe->queues, session, event,
123 data_offset, &buffer);
124 if (err)
125 return err;
126
127
128 if (dump_trace) {
129 if (auxtrace_buffer__get_data(buffer, fd)) {
130 arm_spe_dump_event(spe, buffer->data,
131 buffer->size);
132 auxtrace_buffer__put_data(buffer);
133 }
134 }
135
136 return 0;
137 }
138
139 static int arm_spe_flush(struct perf_session *session __maybe_unused,
140 struct perf_tool *tool __maybe_unused)
141 {
142 return 0;
143 }
144
145 static void arm_spe_free_queue(void *priv)
146 {
147 struct arm_spe_queue *speq = priv;
148
149 if (!speq)
150 return;
151 free(speq);
152 }
153
154 static void arm_spe_free_events(struct perf_session *session)
155 {
156 struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
157 auxtrace);
158 struct auxtrace_queues *queues = &spe->queues;
159 unsigned int i;
160
161 for (i = 0; i < queues->nr_queues; i++) {
162 arm_spe_free_queue(queues->queue_array[i].priv);
163 queues->queue_array[i].priv = NULL;
164 }
165 auxtrace_queues__free(queues);
166 }
167
168 static void arm_spe_free(struct perf_session *session)
169 {
170 struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
171 auxtrace);
172
173 auxtrace_heap__free(&spe->heap);
174 arm_spe_free_events(session);
175 session->auxtrace = NULL;
176 free(spe);
177 }
178
179 static const char * const arm_spe_info_fmts[] = {
180 [ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n",
181 };
182
183 static void arm_spe_print_info(__u64 *arr)
184 {
185 if (!dump_trace)
186 return;
187
188 fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
189 }
190
191 int arm_spe_process_auxtrace_info(union perf_event *event,
192 struct perf_session *session)
193 {
194 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
195 size_t min_sz = sizeof(u64) * ARM_SPE_PMU_TYPE;
196 struct arm_spe *spe;
197 int err;
198
199 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
200 min_sz)
201 return -EINVAL;
202
203 spe = zalloc(sizeof(struct arm_spe));
204 if (!spe)
205 return -ENOMEM;
206
207 err = auxtrace_queues__init(&spe->queues);
208 if (err)
209 goto err_free;
210
211 spe->session = session;
212 spe->machine = &session->machines.host;
213 spe->auxtrace_type = auxtrace_info->type;
214 spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE];
215
216 spe->auxtrace.process_event = arm_spe_process_event;
217 spe->auxtrace.process_auxtrace_event = arm_spe_process_auxtrace_event;
218 spe->auxtrace.flush_events = arm_spe_flush;
219 spe->auxtrace.free_events = arm_spe_free_events;
220 spe->auxtrace.free = arm_spe_free;
221 session->auxtrace = &spe->auxtrace;
222
223 arm_spe_print_info(&auxtrace_info->priv[0]);
224
225 return 0;
226
227 err_free:
228 free(spe);
229 return err;
230 }