Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | // SPDX-License-Identifier: GPL-2.0 /* * HiSilicon PCIe Trace and Tuning (PTT) support * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <endian.h> #include <byteswap.h> #include <linux/bitops.h> #include <stdarg.h> #include "../color.h" #include "hisi-ptt-pkt-decoder.h" /* * For 8DW format, the bit[31:11] of DW0 is always 0x1fffff, which can be * used to distinguish the data format. * 8DW format is like: * bits [ 31:11 ][ 10:0 ] * |---------------------------------------|-------------------| * DW0 [ 0x1fffff ][ Reserved (0x7ff) ] * DW1 [ Prefix ] * DW2 [ Header DW0 ] * DW3 [ Header DW1 ] * DW4 [ Header DW2 ] * DW5 [ Header DW3 ] * DW6 [ Reserved (0x0) ] * DW7 [ Time ] * * 4DW format is like: * bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ] * |-----|---------|---|---|---|---|-------------|-------------| * DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ] * DW1 [ Header DW1 ] * DW2 [ Header DW2 ] * DW3 [ Header DW3 ] */ enum hisi_ptt_8dw_pkt_field_type { HISI_PTT_8DW_CHK_AND_RSV0, HISI_PTT_8DW_PREFIX, HISI_PTT_8DW_HEAD0, HISI_PTT_8DW_HEAD1, HISI_PTT_8DW_HEAD2, HISI_PTT_8DW_HEAD3, HISI_PTT_8DW_RSV1, HISI_PTT_8DW_TIME, HISI_PTT_8DW_TYPE_MAX }; enum hisi_ptt_4dw_pkt_field_type { HISI_PTT_4DW_HEAD1, HISI_PTT_4DW_HEAD2, HISI_PTT_4DW_HEAD3, HISI_PTT_4DW_TYPE_MAX }; static const char * const hisi_ptt_8dw_pkt_field_name[] = { [HISI_PTT_8DW_PREFIX] = "Prefix", [HISI_PTT_8DW_HEAD0] = "Header DW0", [HISI_PTT_8DW_HEAD1] = "Header DW1", [HISI_PTT_8DW_HEAD2] = "Header DW2", [HISI_PTT_8DW_HEAD3] = "Header DW3", [HISI_PTT_8DW_TIME] = "Time" }; static const char * const hisi_ptt_4dw_pkt_field_name[] = { [HISI_PTT_4DW_HEAD1] = "Header DW1", [HISI_PTT_4DW_HEAD2] = "Header DW2", [HISI_PTT_4DW_HEAD3] = "Header DW3", }; union hisi_ptt_4dw { struct { uint32_t format : 2; uint32_t type : 5; uint32_t t9 : 1; uint32_t t8 : 1; uint32_t th : 1; uint32_t so : 1; uint32_t len : 10; uint32_t time : 11; }; uint32_t value; }; static void hisi_ptt_print_pkt(const unsigned char *buf, int pos, const char *desc) { const char *color = PERF_COLOR_BLUE; int i; printf("."); color_fprintf(stdout, color, " %08x: ", pos); for (i = 0; i < HISI_PTT_FIELD_LENTH; i++) color_fprintf(stdout, color, "%02x ", buf[pos + i]); for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) color_fprintf(stdout, color, " "); color_fprintf(stdout, color, " %s\n", desc); } static int hisi_ptt_8dw_kpt_desc(const unsigned char *buf, int pos) { int i; for (i = 0; i < HISI_PTT_8DW_TYPE_MAX; i++) { /* Do not show 8DW check field and reserved fields */ if (i == HISI_PTT_8DW_CHK_AND_RSV0 || i == HISI_PTT_8DW_RSV1) { pos += HISI_PTT_FIELD_LENTH; continue; } hisi_ptt_print_pkt(buf, pos, hisi_ptt_8dw_pkt_field_name[i]); pos += HISI_PTT_FIELD_LENTH; } return hisi_ptt_pkt_size[HISI_PTT_8DW_PKT]; } static void hisi_ptt_4dw_print_dw0(const unsigned char *buf, int pos) { const char *color = PERF_COLOR_BLUE; union hisi_ptt_4dw dw0; int i; dw0.value = *(uint32_t *)(buf + pos); printf("."); color_fprintf(stdout, color, " %08x: ", pos); for (i = 0; i < HISI_PTT_FIELD_LENTH; i++) color_fprintf(stdout, color, "%02x ", buf[pos + i]); for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) color_fprintf(stdout, color, " "); color_fprintf(stdout, color, " %s %x %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n", "Format", dw0.format, "Type", dw0.type, "T9", dw0.t9, "T8", dw0.t8, "TH", dw0.th, "SO", dw0.so, "Length", dw0.len, "Time", dw0.time); } static int hisi_ptt_4dw_kpt_desc(const unsigned char *buf, int pos) { int i; hisi_ptt_4dw_print_dw0(buf, pos); pos += HISI_PTT_FIELD_LENTH; for (i = 0; i < HISI_PTT_4DW_TYPE_MAX; i++) { hisi_ptt_print_pkt(buf, pos, hisi_ptt_4dw_pkt_field_name[i]); pos += HISI_PTT_FIELD_LENTH; } return hisi_ptt_pkt_size[HISI_PTT_4DW_PKT]; } int hisi_ptt_pkt_desc(const unsigned char *buf, int pos, enum hisi_ptt_pkt_type type) { if (type == HISI_PTT_8DW_PKT) return hisi_ptt_8dw_kpt_desc(buf, pos); return hisi_ptt_4dw_kpt_desc(buf, pos); } |