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 <stdio.h>
8 #include <string.h>
9 #include <endian.h>
10 #include <byteswap.h>
11 #include <linux/bitops.h>
12 #include <stdarg.h>
13
14 #include "arm-spe-pkt-decoder.h"
15
16 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
17 #define le16_to_cpu bswap_16
18 #define le32_to_cpu bswap_32
19 #define le64_to_cpu bswap_64
20 #define memcpy_le64(d, s, n) do { \
21 memcpy((d), (s), (n)); \
22 *(d) = le64_to_cpu(*(d)); \
23 } while (0)
24 #else
25 #define le16_to_cpu
26 #define le32_to_cpu
27 #define le64_to_cpu
28 #define memcpy_le64 memcpy
29 #endif
30
31 static const char * const arm_spe_packet_name[] = {
32 [ARM_SPE_PAD] = "PAD",
33 [ARM_SPE_END] = "END",
34 [ARM_SPE_TIMESTAMP] = "TS",
35 [ARM_SPE_ADDRESS] = "ADDR",
36 [ARM_SPE_COUNTER] = "LAT",
37 [ARM_SPE_CONTEXT] = "CONTEXT",
38 [ARM_SPE_OP_TYPE] = "OP-TYPE",
39 [ARM_SPE_EVENTS] = "EVENTS",
40 [ARM_SPE_DATA_SOURCE] = "DATA-SOURCE",
41 };
42
arm_spe_pkt_name(enum arm_spe_pkt_type type)43 const char *arm_spe_pkt_name(enum arm_spe_pkt_type type)
44 {
45 return arm_spe_packet_name[type];
46 }
47
48 /*
49 * Extracts the field "sz" from header bits and converts to bytes:
50 * 00 : byte (1)
51 * 01 : halfword (2)
52 * 10 : word (4)
53 * 11 : doubleword (8)
54 */
arm_spe_payload_len(unsigned char hdr)55 static unsigned int arm_spe_payload_len(unsigned char hdr)
56 {
57 return 1U << ((hdr & GENMASK_ULL(5, 4)) >> 4);
58 }
59
arm_spe_get_payload(const unsigned char * buf,size_t len,unsigned char ext_hdr,struct arm_spe_pkt * packet)60 static int arm_spe_get_payload(const unsigned char *buf, size_t len,
61 unsigned char ext_hdr,
62 struct arm_spe_pkt *packet)
63 {
64 size_t payload_len = arm_spe_payload_len(buf[ext_hdr]);
65
66 if (len < 1 + ext_hdr + payload_len)
67 return ARM_SPE_NEED_MORE_BYTES;
68
69 buf += 1 + ext_hdr;
70
71 switch (payload_len) {
72 case 1: packet->payload = *(uint8_t *)buf; break;
73 case 2: packet->payload = le16_to_cpu(*(uint16_t *)buf); break;
74 case 4: packet->payload = le32_to_cpu(*(uint32_t *)buf); break;
75 case 8: packet->payload = le64_to_cpu(*(uint64_t *)buf); break;
76 default: return ARM_SPE_BAD_PACKET;
77 }
78
79 return 1 + ext_hdr + payload_len;
80 }
81
arm_spe_get_pad(struct arm_spe_pkt * packet)82 static int arm_spe_get_pad(struct arm_spe_pkt *packet)
83 {
84 packet->type = ARM_SPE_PAD;
85 return 1;
86 }
87
arm_spe_get_alignment(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)88 static int arm_spe_get_alignment(const unsigned char *buf, size_t len,
89 struct arm_spe_pkt *packet)
90 {
91 unsigned int alignment = 1 << ((buf[0] & 0xf) + 1);
92
93 if (len < alignment)
94 return ARM_SPE_NEED_MORE_BYTES;
95
96 packet->type = ARM_SPE_PAD;
97 return alignment - (((uintptr_t)buf) & (alignment - 1));
98 }
99
arm_spe_get_end(struct arm_spe_pkt * packet)100 static int arm_spe_get_end(struct arm_spe_pkt *packet)
101 {
102 packet->type = ARM_SPE_END;
103 return 1;
104 }
105
arm_spe_get_timestamp(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)106 static int arm_spe_get_timestamp(const unsigned char *buf, size_t len,
107 struct arm_spe_pkt *packet)
108 {
109 packet->type = ARM_SPE_TIMESTAMP;
110 return arm_spe_get_payload(buf, len, 0, packet);
111 }
112
arm_spe_get_events(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)113 static int arm_spe_get_events(const unsigned char *buf, size_t len,
114 struct arm_spe_pkt *packet)
115 {
116 packet->type = ARM_SPE_EVENTS;
117
118 /* we use index to identify Events with a less number of
119 * comparisons in arm_spe_pkt_desc(): E.g., the LLC-ACCESS,
120 * LLC-REFILL, and REMOTE-ACCESS events are identified if
121 * index > 1.
122 */
123 packet->index = arm_spe_payload_len(buf[0]);
124
125 return arm_spe_get_payload(buf, len, 0, packet);
126 }
127
arm_spe_get_data_source(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)128 static int arm_spe_get_data_source(const unsigned char *buf, size_t len,
129 struct arm_spe_pkt *packet)
130 {
131 packet->type = ARM_SPE_DATA_SOURCE;
132 return arm_spe_get_payload(buf, len, 0, packet);
133 }
134
arm_spe_get_context(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)135 static int arm_spe_get_context(const unsigned char *buf, size_t len,
136 struct arm_spe_pkt *packet)
137 {
138 packet->type = ARM_SPE_CONTEXT;
139 packet->index = SPE_CTX_PKT_HDR_INDEX(buf[0]);
140 return arm_spe_get_payload(buf, len, 0, packet);
141 }
142
arm_spe_get_op_type(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)143 static int arm_spe_get_op_type(const unsigned char *buf, size_t len,
144 struct arm_spe_pkt *packet)
145 {
146 packet->type = ARM_SPE_OP_TYPE;
147 packet->index = SPE_OP_PKT_HDR_CLASS(buf[0]);
148 return arm_spe_get_payload(buf, len, 0, packet);
149 }
150
arm_spe_get_counter(const unsigned char * buf,size_t len,const unsigned char ext_hdr,struct arm_spe_pkt * packet)151 static int arm_spe_get_counter(const unsigned char *buf, size_t len,
152 const unsigned char ext_hdr, struct arm_spe_pkt *packet)
153 {
154 packet->type = ARM_SPE_COUNTER;
155
156 if (ext_hdr)
157 packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
158 else
159 packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
160
161 return arm_spe_get_payload(buf, len, ext_hdr, packet);
162 }
163
arm_spe_get_addr(const unsigned char * buf,size_t len,const unsigned char ext_hdr,struct arm_spe_pkt * packet)164 static int arm_spe_get_addr(const unsigned char *buf, size_t len,
165 const unsigned char ext_hdr, struct arm_spe_pkt *packet)
166 {
167 packet->type = ARM_SPE_ADDRESS;
168
169 if (ext_hdr)
170 packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
171 else
172 packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
173
174 return arm_spe_get_payload(buf, len, ext_hdr, packet);
175 }
176
arm_spe_do_get_packet(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)177 static int arm_spe_do_get_packet(const unsigned char *buf, size_t len,
178 struct arm_spe_pkt *packet)
179 {
180 unsigned int hdr;
181 unsigned char ext_hdr = 0;
182
183 memset(packet, 0, sizeof(struct arm_spe_pkt));
184
185 if (!len)
186 return ARM_SPE_NEED_MORE_BYTES;
187
188 hdr = buf[0];
189
190 if (hdr == SPE_HEADER0_PAD)
191 return arm_spe_get_pad(packet);
192
193 if (hdr == SPE_HEADER0_END) /* no timestamp at end of record */
194 return arm_spe_get_end(packet);
195
196 if (hdr == SPE_HEADER0_TIMESTAMP)
197 return arm_spe_get_timestamp(buf, len, packet);
198
199 if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_EVENTS)
200 return arm_spe_get_events(buf, len, packet);
201
202 if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_SOURCE)
203 return arm_spe_get_data_source(buf, len, packet);
204
205 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_CONTEXT)
206 return arm_spe_get_context(buf, len, packet);
207
208 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_OP_TYPE)
209 return arm_spe_get_op_type(buf, len, packet);
210
211 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_EXTENDED) {
212 /* 16-bit extended format header */
213 if (len == 1)
214 return ARM_SPE_BAD_PACKET;
215
216 ext_hdr = 1;
217 hdr = buf[1];
218 if (hdr == SPE_HEADER1_ALIGNMENT)
219 return arm_spe_get_alignment(buf, len, packet);
220 }
221
222 /*
223 * The short format header's byte 0 or the extended format header's
224 * byte 1 has been assigned to 'hdr', which uses the same encoding for
225 * address packet and counter packet, so don't need to distinguish if
226 * it's short format or extended format and handle in once.
227 */
228 if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_ADDRESS)
229 return arm_spe_get_addr(buf, len, ext_hdr, packet);
230
231 if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_COUNTER)
232 return arm_spe_get_counter(buf, len, ext_hdr, packet);
233
234 return ARM_SPE_BAD_PACKET;
235 }
236
arm_spe_get_packet(const unsigned char * buf,size_t len,struct arm_spe_pkt * packet)237 int arm_spe_get_packet(const unsigned char *buf, size_t len,
238 struct arm_spe_pkt *packet)
239 {
240 int ret;
241
242 ret = arm_spe_do_get_packet(buf, len, packet);
243 /* put multiple consecutive PADs on the same line, up to
244 * the fixed-width output format of 16 bytes per line.
245 */
246 if (ret > 0 && packet->type == ARM_SPE_PAD) {
247 while (ret < 16 && len > (size_t)ret && !buf[ret])
248 ret += 1;
249 }
250 return ret;
251 }
252
arm_spe_pkt_out_string(int * err,char ** buf_p,size_t * blen,const char * fmt,...)253 static int arm_spe_pkt_out_string(int *err, char **buf_p, size_t *blen,
254 const char *fmt, ...)
255 {
256 va_list ap;
257 int ret;
258
259 /* Bail out if any error occurred */
260 if (err && *err)
261 return *err;
262
263 va_start(ap, fmt);
264 ret = vsnprintf(*buf_p, *blen, fmt, ap);
265 va_end(ap);
266
267 if (ret < 0) {
268 if (err && !*err)
269 *err = ret;
270
271 /*
272 * A return value of *blen or more means that the output was
273 * truncated and the buffer is overrun.
274 */
275 } else if ((size_t)ret >= *blen) {
276 (*buf_p)[*blen - 1] = '\0';
277
278 /*
279 * Set *err to 'ret' to avoid overflow if tries to
280 * fill this buffer sequentially.
281 */
282 if (err && !*err)
283 *err = ret;
284 } else {
285 *buf_p += ret;
286 *blen -= ret;
287 }
288
289 return ret;
290 }
291
arm_spe_pkt_desc_event(const struct arm_spe_pkt * packet,char * buf,size_t buf_len)292 static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
293 char *buf, size_t buf_len)
294 {
295 u64 payload = packet->payload;
296 int err = 0;
297
298 arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV");
299
300 if (payload & BIT(EV_EXCEPTION_GEN))
301 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCEPTION-GEN");
302 if (payload & BIT(EV_RETIRED))
303 arm_spe_pkt_out_string(&err, &buf, &buf_len, " RETIRED");
304 if (payload & BIT(EV_L1D_ACCESS))
305 arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-ACCESS");
306 if (payload & BIT(EV_L1D_REFILL))
307 arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-REFILL");
308 if (payload & BIT(EV_TLB_ACCESS))
309 arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-ACCESS");
310 if (payload & BIT(EV_TLB_WALK))
311 arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-REFILL");
312 if (payload & BIT(EV_NOT_TAKEN))
313 arm_spe_pkt_out_string(&err, &buf, &buf_len, " NOT-TAKEN");
314 if (payload & BIT(EV_MISPRED))
315 arm_spe_pkt_out_string(&err, &buf, &buf_len, " MISPRED");
316 if (payload & BIT(EV_LLC_ACCESS))
317 arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-ACCESS");
318 if (payload & BIT(EV_LLC_MISS))
319 arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-REFILL");
320 if (payload & BIT(EV_REMOTE_ACCESS))
321 arm_spe_pkt_out_string(&err, &buf, &buf_len, " REMOTE-ACCESS");
322 if (payload & BIT(EV_ALIGNMENT))
323 arm_spe_pkt_out_string(&err, &buf, &buf_len, " ALIGNMENT");
324 if (payload & BIT(EV_PARTIAL_PREDICATE))
325 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-PARTIAL-PRED");
326 if (payload & BIT(EV_EMPTY_PREDICATE))
327 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-EMPTY-PRED");
328
329 return err;
330 }
331
arm_spe_pkt_desc_op_type(const struct arm_spe_pkt * packet,char * buf,size_t buf_len)332 static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet,
333 char *buf, size_t buf_len)
334 {
335 u64 payload = packet->payload;
336 int err = 0;
337
338 switch (packet->index) {
339 case SPE_OP_PKT_HDR_CLASS_OTHER:
340 if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) {
341 arm_spe_pkt_out_string(&err, &buf, &buf_len, "SVE-OTHER");
342
343 /* SVE effective vector length */
344 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
345 SPE_OP_PKG_SVE_EVL(payload));
346
347 if (payload & SPE_OP_PKT_SVE_FP)
348 arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP");
349 if (payload & SPE_OP_PKT_SVE_PRED)
350 arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
351 } else {
352 arm_spe_pkt_out_string(&err, &buf, &buf_len, "OTHER");
353 arm_spe_pkt_out_string(&err, &buf, &buf_len, " %s",
354 payload & SPE_OP_PKT_COND ?
355 "COND-SELECT" : "INSN-OTHER");
356 }
357 break;
358 case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
359 arm_spe_pkt_out_string(&err, &buf, &buf_len,
360 payload & 0x1 ? "ST" : "LD");
361
362 if (SPE_OP_PKT_IS_LDST_ATOMIC(payload)) {
363 if (payload & SPE_OP_PKT_AT)
364 arm_spe_pkt_out_string(&err, &buf, &buf_len, " AT");
365 if (payload & SPE_OP_PKT_EXCL)
366 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCL");
367 if (payload & SPE_OP_PKT_AR)
368 arm_spe_pkt_out_string(&err, &buf, &buf_len, " AR");
369 }
370
371 switch (SPE_OP_PKT_LDST_SUBCLASS_GET(payload)) {
372 case SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP:
373 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SIMD-FP");
374 break;
375 case SPE_OP_PKT_LDST_SUBCLASS_GP_REG:
376 arm_spe_pkt_out_string(&err, &buf, &buf_len, " GP-REG");
377 break;
378 case SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG:
379 arm_spe_pkt_out_string(&err, &buf, &buf_len, " UNSPEC-REG");
380 break;
381 case SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG:
382 arm_spe_pkt_out_string(&err, &buf, &buf_len, " NV-SYSREG");
383 break;
384 case SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG:
385 arm_spe_pkt_out_string(&err, &buf, &buf_len, " MTE-TAG");
386 break;
387 case SPE_OP_PKT_LDST_SUBCLASS_MEMCPY:
388 arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMCPY");
389 break;
390 case SPE_OP_PKT_LDST_SUBCLASS_MEMSET:
391 arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMSET");
392 break;
393 default:
394 break;
395 }
396
397 if (SPE_OP_PKT_IS_LDST_SVE(payload)) {
398 /* SVE effective vector length */
399 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
400 SPE_OP_PKG_SVE_EVL(payload));
401
402 if (payload & SPE_OP_PKT_SVE_PRED)
403 arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
404 if (payload & SPE_OP_PKT_SVE_SG)
405 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SG");
406 }
407 break;
408 case SPE_OP_PKT_HDR_CLASS_BR_ERET:
409 arm_spe_pkt_out_string(&err, &buf, &buf_len, "B");
410
411 if (payload & SPE_OP_PKT_COND)
412 arm_spe_pkt_out_string(&err, &buf, &buf_len, " COND");
413
414 if (SPE_OP_PKT_IS_INDIRECT_BRANCH(payload))
415 arm_spe_pkt_out_string(&err, &buf, &buf_len, " IND");
416
417 break;
418 default:
419 /* Unknown index */
420 err = -1;
421 break;
422 }
423
424 return err;
425 }
426
arm_spe_pkt_desc_addr(const struct arm_spe_pkt * packet,char * buf,size_t buf_len)427 static int arm_spe_pkt_desc_addr(const struct arm_spe_pkt *packet,
428 char *buf, size_t buf_len)
429 {
430 int ns, el, idx = packet->index;
431 int ch, pat;
432 u64 payload = packet->payload;
433 int err = 0;
434 static const char *idx_name[] = {"PC", "TGT", "VA", "PA", "PBT"};
435
436 switch (idx) {
437 case SPE_ADDR_PKT_HDR_INDEX_INS:
438 case SPE_ADDR_PKT_HDR_INDEX_BRANCH:
439 case SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH:
440 ns = !!SPE_ADDR_PKT_GET_NS(payload);
441 el = SPE_ADDR_PKT_GET_EL(payload);
442 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
443 arm_spe_pkt_out_string(&err, &buf, &buf_len,
444 "%s 0x%llx el%d ns=%d",
445 idx_name[idx], payload, el, ns);
446 break;
447 case SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT:
448 arm_spe_pkt_out_string(&err, &buf, &buf_len,
449 "VA 0x%llx", payload);
450 break;
451 case SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS:
452 ns = !!SPE_ADDR_PKT_GET_NS(payload);
453 ch = !!SPE_ADDR_PKT_GET_CH(payload);
454 pat = SPE_ADDR_PKT_GET_PAT(payload);
455 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
456 arm_spe_pkt_out_string(&err, &buf, &buf_len,
457 "PA 0x%llx ns=%d ch=%d pat=%x",
458 payload, ns, ch, pat);
459 break;
460 default:
461 /* Unknown index */
462 err = -1;
463 break;
464 }
465
466 return err;
467 }
468
arm_spe_pkt_desc_counter(const struct arm_spe_pkt * packet,char * buf,size_t buf_len)469 static int arm_spe_pkt_desc_counter(const struct arm_spe_pkt *packet,
470 char *buf, size_t buf_len)
471 {
472 u64 payload = packet->payload;
473 const char *name = arm_spe_pkt_name(packet->type);
474 int err = 0;
475
476 arm_spe_pkt_out_string(&err, &buf, &buf_len, "%s %d ", name,
477 (unsigned short)payload);
478
479 switch (packet->index) {
480 case SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT:
481 arm_spe_pkt_out_string(&err, &buf, &buf_len, "TOT");
482 break;
483 case SPE_CNT_PKT_HDR_INDEX_ISSUE_LAT:
484 arm_spe_pkt_out_string(&err, &buf, &buf_len, "ISSUE");
485 break;
486 case SPE_CNT_PKT_HDR_INDEX_TRANS_LAT:
487 arm_spe_pkt_out_string(&err, &buf, &buf_len, "XLAT");
488 break;
489 default:
490 break;
491 }
492
493 return err;
494 }
495
arm_spe_pkt_desc(const struct arm_spe_pkt * packet,char * buf,size_t buf_len)496 int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf,
497 size_t buf_len)
498 {
499 int idx = packet->index;
500 unsigned long long payload = packet->payload;
501 const char *name = arm_spe_pkt_name(packet->type);
502 char *buf_orig = buf;
503 size_t blen = buf_len;
504 int err = 0;
505
506 switch (packet->type) {
507 case ARM_SPE_BAD:
508 case ARM_SPE_PAD:
509 case ARM_SPE_END:
510 arm_spe_pkt_out_string(&err, &buf, &blen, "%s", name);
511 break;
512 case ARM_SPE_EVENTS:
513 err = arm_spe_pkt_desc_event(packet, buf, buf_len);
514 break;
515 case ARM_SPE_OP_TYPE:
516 err = arm_spe_pkt_desc_op_type(packet, buf, buf_len);
517 break;
518 case ARM_SPE_DATA_SOURCE:
519 case ARM_SPE_TIMESTAMP:
520 arm_spe_pkt_out_string(&err, &buf, &blen, "%s %lld", name, payload);
521 break;
522 case ARM_SPE_ADDRESS:
523 err = arm_spe_pkt_desc_addr(packet, buf, buf_len);
524 break;
525 case ARM_SPE_CONTEXT:
526 arm_spe_pkt_out_string(&err, &buf, &blen, "%s 0x%lx el%d",
527 name, (unsigned long)payload, idx + 1);
528 break;
529 case ARM_SPE_COUNTER:
530 err = arm_spe_pkt_desc_counter(packet, buf, buf_len);
531 break;
532 default:
533 /* Unknown packet type */
534 err = -1;
535 break;
536 }
537
538 /* Output raw data if detect any error */
539 if (err) {
540 err = 0;
541 arm_spe_pkt_out_string(&err, &buf_orig, &buf_len, "%s 0x%llx (%d)",
542 name, payload, packet->index);
543 }
544
545 return err;
546 }
547