]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - tools/perf/util/arm-spe.c
Merge tag 'fuse-update-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[mirror_ubuntu-jammy-kernel.git] / tools / perf / util / arm-spe.c
CommitLineData
ffd3d18c
KP
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Arm Statistical Profiling Extensions (SPE) support
4 * Copyright (c) 2017-2018, Arm Ltd.
5 */
6
7#include <endian.h>
8#include <errno.h>
9#include <byteswap.h>
10#include <inttypes.h>
7ae811b1
ACM
11#include <unistd.h>
12#include <stdlib.h>
ffd3d18c
KP
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/bitops.h>
16#include <linux/log2.h>
7f7c536f 17#include <linux/zalloc.h>
ffd3d18c 18
ffd3d18c
KP
19#include "color.h"
20#include "evsel.h"
ffd3d18c
KP
21#include "machine.h"
22#include "session.h"
ffd3d18c
KP
23#include "debug.h"
24#include "auxtrace.h"
25#include "arm-spe.h"
26#include "arm-spe-pkt-decoder.h"
27
28struct 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
38struct 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
49static 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
88static 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
95static 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
103static 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 /* Dump here now we have copied a piped trace out of the pipe */
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
139static int arm_spe_flush(struct perf_session *session __maybe_unused,
140 struct perf_tool *tool __maybe_unused)
141{
142 return 0;
143}
144
145static 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
154static 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
168static 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
179static const char * const arm_spe_info_fmts[] = {
180 [ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n",
181};
182
9a8dad04 183static void arm_spe_print_info(__u64 *arr)
ffd3d18c
KP
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
191int arm_spe_process_auxtrace_info(union perf_event *event,
192 struct perf_session *session)
193{
72932371 194 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
ffd3d18c
KP
195 size_t min_sz = sizeof(u64) * ARM_SPE_PMU_TYPE;
196 struct arm_spe *spe;
197 int err;
198
72932371 199 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
ffd3d18c
KP
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; /* No kvm support */
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
227err_free:
228 free(spe);
229 return err;
230}