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