• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef SPE_DECODER_H
16 #define SPE_DECODER_H
17 #if !IS_WASM && !is_mingw && !is_mac
18 #include <linux/const.h>
19 #endif
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include "utilities.h"
24 
25 #define BIT_ULL(x)    (_BITULL(x))
26 #define ULL(x)        (_ULL(x))
27 #define UL(x)         (_UL(x))
28 #define BIT(x)        (UL(1) << (x))
29 #define BITS_PER_LONG __BITS_PER_LONG
30 #define BITS_PER_LONG_LONG 64
31 
32 #define GENMASK_INPUT_CHECK(h, l) 0
33 
34 #define PR_GENMASK(h, l) \
35         (((~UL(0)) - (UL(1) << (l)) + 1) & \
36          (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
37 #define GENMASK(h, l) \
38         (GENMASK_INPUT_CHECK(h, l) + PR_GENMASK(h, l))
39 
40 #define PR_GENMASK_ULL(h, l) \
41         (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
42          (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
43 #define GENMASK_ULL(h, l) \
44         (GENMASK_INPUT_CHECK(h, l) + PR_GENMASK_ULL(h, l))
45 
46 #define PERF_SPE_PKT_DESC_MAX      256
47 #define PERF_SPE_NEED_MORE_BYTES   (-1)
48 #define PERF_SPE_BAD_PACKET        (-2)
49 #define PERF_SPE_PKT_MAX_SZ        16
50 
51 namespace OHOS {
52 namespace Developtools {
53 namespace HiPerf {
54 enum SpePktType {
55     PERF_SPE_BAD,
56     PERF_SPE_PAD,
57     PERF_SPE_END,
58     PERF_SPE_TIMESTAMP,
59     PERF_SPE_ADDRESS,
60     PERF_SPE_COUNTER,
61     PERF_SPE_CONTEXT,
62     PERF_SPE_OP_TYPE,
63     PERF_SPE_EVENTS,
64     PERF_SPE_DATA_SOURCE,
65 };
66 
67 struct SpePkt {
68     SpePktType      type;
69     unsigned char   index;
70     uint64_t payload;
71 };
72 
73 /* Short header (HEADER0) and extended header (HEADER1) */
74 #define PERF_SPE_HEADER0_PAD                 0x0
75 #define PERF_SPE_HEADER0_END                 0x1
76 #define PERF_SPE_HEADER0_TIMESTAMP           0x71
77 /* Mask for event & data source */
78 #define PERF_SPE_HEADER0_MASK1               (GENMASK_ULL(7, 6) | GENMASK_ULL(3, 0))
79 #define PERF_SPE_HEADER0_EVENTS              0x42
80 #define PERF_SPE_HEADER0_SOURCE              0x43
81 /* Mask for context & operation */
82 #define PERF_SPE_HEADER0_MASK2               GENMASK_ULL(7, 2)
83 #define PERF_SPE_HEADER0_CONTEXT             0x64
84 #define PERF_SPE_HEADER0_OP_TYPE             0x48
85 /* Mask for extended format */
86 #define PERF_SPE_HEADER0_EXTENDED            0x20
87 /* Mask for address & counter */
88 #define PERF_SPE_HEADER0_MASK3               GENMASK_ULL(7, 3)
89 #define PERF_SPE_HEADER0_ADDRESS             0xb0
90 #define PERF_SPE_HEADER0_COUNTER             0x98
91 #define PERF_SPE_HEADER1_ALIGNMENT           0x0
92 
93 #define PERF_SPE_HDR_SHORT_INDEX(h)         ((h) & GENMASK_ULL(2, 0))
94 #define PERF_SPE_HDR_EXTENDED_INDEX(h0, h1)     (((h0) & GENMASK_ULL(1, 0)) << 3 | \
95                                                  PERF_SPE_HDR_SHORT_INDEX(h1))
96 
97 /* Address packet header */
98 #define PERF_SPE_ADDR_PKT_HDR_INDEX_INS         0x0
99 #define PERF_SPE_ADDR_PKT_HDR_INDEX_BRANCH      0x1
100 #define PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT   0x2
101 #define PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS   0x3
102 #define PERF_SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH 0x4
103 
104 /* Address packet payload */
105 #define PERF_SPE_ADDR_PKT_ADDR_BYTE7_SHIFT      56
106 #define PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(v) ((v) & GENMASK_ULL(55, 0))
107 #define PERF_SPE_ADDR_PKT_ADDR_GET_BYTE_6(v)        (((v) & GENMASK_ULL(55, 48)) >> 48)
108 
109 #define PERF_SPE_ADDR_PKT_GET_NS(v)         (((v) & BIT_ULL(63)) >> 63)
110 #define PERF_SPE_ADDR_PKT_GET_EL(v)         (((v) & GENMASK_ULL(62, 61)) >> 61)
111 #define PERF_SPE_ADDR_PKT_GET_CH(v)         (((v) & BIT_ULL(62)) >> 62)
112 #define PERF_SPE_ADDR_PKT_GET_PAT(v)            (((v) & GENMASK_ULL(59, 56)) >> 56)
113 
114 #define PERF_SPE_ADDR_PKT_EL0                  0
115 #define PERF_SPE_ADDR_PKT_EL1                  1
116 #define PERF_SPE_ADDR_PKT_EL2                  2
117 #define PERF_SPE_ADDR_PKT_EL3                  3
118 
119 /* Context packet header */
120 #define PERF_SPE_CTX_PKT_HDR_INDEX(h)        ((h) & GENMASK_ULL(1, 0))
121 
122 /* Counter packet header */
123 #define PERF_SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT     0x0
124 #define PERF_SPE_CNT_PKT_HDR_INDEX_ISSUE_LAT     0x1
125 #define PERF_SPE_CNT_PKT_HDR_INDEX_TRANS_LAT     0x2
126 
127 /* Get bit 5th and 4th of the header */
128 #define PERF_SPE_HDR_GET_BYTES_5_4(h)       (((h) & (GENMASK_ULL(5, 4))) >> 4)
129 
130 /* Event packet payload */
131 enum SpeEvents {
132     EVENT_EXCEPTION_GEN        = 0,
133     EVENT_RETIRED              = 1,
134     EVENT_L1D_ACCESS           = 2,
135     EVENT_L1D_REFILL           = 3,
136     EVENT_TLB_ACCESS           = 4,
137     EVENT_TLB_WALK             = 5,
138     EVENT_NOT_TAKEN            = 6,
139     EVENT_MISPRED              = 7,
140     EVENT_LLC_ACCESS           = 8,
141     EVENT_LLC_MISS             = 9,
142     EVENT_REMOTE_ACCESS        = 10,
143     EVENT_ALIGNMENT            = 11,
144     EVENT_PARTIAL_PREDICATE    = 17,
145     EVENT_EMPTY_PREDICATE      = 18,
146 };
147 
148 
149 /* Operation packet header */
150 #define PERF_SPE_OP_PKT_HDR_CLASS(h)             ((h) & GENMASK_ULL(1, 0))
151 #define PERF_SPE_OP_PKT_HDR_CLASS_OTHER          0x0
152 #define PERF_SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC   0x1
153 #define PERF_SPE_OP_PKT_HDR_CLASS_BR_ERET        0x2
154 
155 #define PERF_SPE_OP_PKT_IS_OTHER_SVE_OP(v)       (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8)
156 
157 #define PERF_SPE_OP_PKT_COND                     BIT(0)
158 
159 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_GET(v)     ((v) & GENMASK_ULL(7, 1))
160 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_GP_REG     0x0
161 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP    0x4
162 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG 0x10
163 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG  0x30
164 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG    0x14
165 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_MEMCPY     0x20
166 #define PERF_SPE_OP_PKT_LDST_SUBCLASS_MEMSET     0x25
167 
168 #define PERF_SPE_OP_PKT_IS_LDST_ATOMIC(v)        (((v) & (GENMASK_ULL(7, 5) | BIT(1))) == 0x2)
169 
170 #define PERF_SPE_OP_PKT_AR                       BIT(4)
171 #define PERF_SPE_OP_PKT_EXCL                     BIT(3)
172 #define PERF_SPE_OP_PKT_AT                       BIT(2)
173 #define PERF_SPE_OP_PKT_ST                       BIT(0)
174 
175 #define PERF_SPE_OP_PKT_IS_LDST_SVE(v)           (((v) & (BIT(3) | BIT(1))) == 0x8)
176 
177 #define PERF_SPE_OP_PKT_SVE_SG                   BIT(7)
178 /*
179  * SVE effective vector length (EVL) is stored in byte 0 bits [6:4];
180  * the length is rounded up to a power of two and use 32 as one step,
181  * so EVL calculation is:
182  *
183  *   32 * (2 ^ bits [6:4]) = 32 << (bits [6:4])
184  */
185 #define PERF_SPE_OP_PKG_SVE_EVL(v)              (32 << (((v) & GENMASK_ULL(6, 4)) >> 4))
186 #define PERF_SPE_OP_PKT_SVE_PRED                BIT(2)
187 #define PERF_SPE_OP_PKT_SVE_FP                  BIT(1)
188 
189 #define PERF_SPE_OP_PKT_IS_INDIRECT_BRANCH(v)   (((v) & GENMASK_ULL(7, 1)) == 0x2)
190 
191 const int LEN_TYPE_BYTE    = 1;
192 const int LEN_TYPE_HLFWRD  = 2;
193 const int LEN_TYPE_WORD    = 4;
194 const int LEN_TYPE_DBLEWRD = 8;
195 /*16 bytes of width*/
196 const int BYTE_WIDTH = 16;
197 
198 enum SpeSampleType {
199     PERF_SPE_L1D_ACCESS          = 1 << 0,
200     PERF_SPE_L1D_MISS            = 1 << 1,
201     PERF_SPE_LLC_ACCESS          = 1 << 2,
202     PERF_SPE_LLC_MISS            = 1 << 3,
203     PERF_SPE_TLB_ACCESS          = 1 << 4,
204     PERF_SPE_TLB_MISS            = 1 << 5,
205     PERF_SPE_BRANCH_MISS         = 1 << 6,
206     PERF_SPE_REMOTE_ACCESS       = 1 << 7,
207     PERF_SPE_SVE_PARTIAL_PRED    = 1 << 8,
208     PERF_SPE_SVE_EMPTY_PRED      = 1 << 9,
209 };
210 
211 enum SpeOpType {
212     /* First level operation type */
213     PERF_SPE_OP_OTHER            = 1 << 0,
214     PERF_SPE_OP_LDST             = 1 << 1,
215     PERF_SPE_OP_BRANCH_ERET      = 1 << 2,
216 
217     /* Second level operation type for OTHER */
218     PERF_SPE_OP_SVE_OTHER        = 1 << 16,
219     PERF_SPE_OP_SVE_FP           = 1 << 17,
220     PERF_SPE_OP_SVE_PRED_OTHER   = 1 << 18,
221 
222     /* Second level operation type for LDST */
223     PERF_SPE_OP_LD               = 1 << 16,
224     PERF_SPE_OP_ST               = 1 << 17,
225     PERF_SPE_OP_ATOMIC           = 1 << 18,
226     PERF_SPE_OP_EXCL             = 1 << 19,
227     PERF_SPE_OP_AR               = 1 << 20,
228     PERF_SPE_OP_SIMD_FP          = 1 << 21,
229     PERF_SPE_OP_GP_REG           = 1 << 22,
230     PERF_SPE_OP_UNSPEC_REG       = 1 << 23,
231     PERF_SPE_OP_NV_SYSREG        = 1 << 24,
232     PERF_SPE_OP_SVE_LDST         = 1 << 25,
233     PERF_SPE_OP_SVE_PRED_LDST    = 1 << 26,
234     PERF_SPE_OP_SVE_SG           = 1 << 27,
235 
236     /* Second level operation type for BRANCH_ERET */
237     PERF_SPE_OP_BR_COND          = 1 << 16,
238     PERF_SPE_OP_BR_INDIRECT      = 1 << 17,
239 };
240 
241 enum SpeNeoverseDataSource {
242     PERF_SPE_NV_L1D           = 0x0,
243     PERF_SPE_NV_L2            = 0x8,
244     PERF_SPE_NV_PEER_CORE     = 0x9,
245     PERF_SPE_NV_LOCAL_CLUSTER = 0xa,
246     PERF_SPE_NV_SYS_CACHE     = 0xb,
247     PERF_SPE_NV_PEER_CLUSTER  = 0xc,
248     PERF_SPE_NV_REMOTE        = 0xd,
249     PERF_SPE_NV_DRAM          = 0xe,
250 };
251 
252 struct SpeRecord {
253     u32 type;
254     int err;
255     u32 op;
256     u32 latency;
257     u64 from_ip;
258     u64 to_ip;
259     u64 timestamp;
260     u64 virt_addr;
261     u64 phys_addr;
262     u64 context_id;
263     u16 source;
264 };
265 
266 struct SpeInsn;
267 
268 struct SpeBuffer {
269     const unsigned char *buf;
270     size_t len;
271     u64 offset;
272     u64 trace_nr;
273 };
274 
275 struct SpeParams {
276     void *data;
277 };
278 
279 struct SpeDecoder {
280     void *data;
281     struct SpeRecord record;
282     const unsigned char *buf;
283     size_t len;
284 
285     struct SpePkt packet;
286 };
287 
288 struct SpeDecoder *SpeDecoderDataNew(const unsigned char *speBuf, const size_t speLen);
289 void SpeDecoderFree(struct SpeDecoder *decoder);
290 
291 int SpeDecode(struct SpeDecoder *decoder);
292 
293 int SpePktDesc(const struct SpePkt *packet, char *buf, const size_t len);
294 bool SpeDumpRawData(unsigned char *buf, size_t len, const int indent, FILE *outputDump);
295 
296 struct ReportItemAuxRawData {
297     u32 type;
298     float heating;
299     u64 count;
300     std::string comm;
301     u64 pc;
302     std::string SharedObject;
303     std::string Symbol;
304     u64 offset;
305 };
306 
307 void AddReportItems(const std::vector<ReportItemAuxRawData>& auxRawData);
308 void UpdateHeating();
309 void DumpSpeReportData(const int indent, FILE *outputDump);
310 void DumpSpeReportHead(const int indent, const uint32_t type, const uint64_t count);
311 void GetSpeEventNameByType(const uint32_t type, std::string& eventName);
312 } // namespace HiPerf
313 } // namespace Developtools
314 } // namespace OHOS
315 #endif // SPE_DECODER_H
316