1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright(C) 2015-2018 Linaro Limited. 4 * 5 * Author: Tor Jeremiassen <tor@ti.com> 6 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 7 */ 8 9 #include <linux/err.h> 10 #include <linux/list.h> 11 #include <stdlib.h> 12 #include <opencsd/c_api/opencsd_c_api.h> 13 #include <opencsd/etmv4/trc_pkt_types_etmv4.h> 14 #include <opencsd/ocsd_if_types.h> 15 16 #include "cs-etm.h" 17 #include "cs-etm-decoder.h" 18 #include "intlist.h" 19 #include "util.h" 20 21 #define MAX_BUFFER 1024 22 23 /* use raw logging */ 24 #ifdef CS_DEBUG_RAW 25 #define CS_LOG_RAW_FRAMES 26 #ifdef CS_RAW_PACKED 27 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT | \ 28 OCSD_DFRMTR_PACKED_RAW_OUT) 29 #else 30 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT) 31 #endif 32 #endif 33 34 #define CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL 35 36 struct cs_etm_decoder { 37 void *data; 38 void (*packet_printer)(const char *msg); 39 bool trace_on; 40 dcd_tree_handle_t dcd_tree; 41 cs_etm_mem_cb_type mem_access; 42 ocsd_datapath_resp_t prev_return; 43 u32 packet_count; 44 u32 head; 45 u32 tail; 46 struct cs_etm_packet packet_buffer[MAX_BUFFER]; 47 }; 48 49 static u32 50 cs_etm_decoder__mem_access(const void *context, 51 const ocsd_vaddr_t address, 52 const ocsd_mem_space_acc_t mem_space __maybe_unused, 53 const u32 req_size, 54 u8 *buffer) 55 { 56 struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context; 57 58 return decoder->mem_access(decoder->data, 59 address, 60 req_size, 61 buffer); 62 } 63 64 int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, 65 u64 start, u64 end, 66 cs_etm_mem_cb_type cb_func) 67 { 68 decoder->mem_access = cb_func; 69 70 if (ocsd_dt_add_callback_mem_acc(decoder->dcd_tree, start, end, 71 OCSD_MEM_SPACE_ANY, 72 cs_etm_decoder__mem_access, decoder)) 73 return -1; 74 75 return 0; 76 } 77 78 int cs_etm_decoder__reset(struct cs_etm_decoder *decoder) 79 { 80 ocsd_datapath_resp_t dp_ret; 81 82 decoder->prev_return = OCSD_RESP_CONT; 83 84 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET, 85 0, 0, NULL, NULL); 86 if (OCSD_DATA_RESP_IS_FATAL(dp_ret)) 87 return -1; 88 89 return 0; 90 } 91 92 int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder, 93 struct cs_etm_packet *packet) 94 { 95 if (!decoder || !packet) 96 return -EINVAL; 97 98 /* Nothing to do, might as well just return */ 99 if (decoder->packet_count == 0) 100 return 0; 101 /* 102 * The queueing process in function cs_etm_decoder__buffer_packet() 103 * increments the tail *before* using it. This is somewhat counter 104 * intuitive but it has the advantage of centralizing tail management 105 * at a single location. Because of that we need to follow the same 106 * heuristic with the head, i.e we increment it before using its 107 * value. Otherwise the first element of the packet queue is not 108 * used. 109 */ 110 decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1); 111 112 *packet = decoder->packet_buffer[decoder->head]; 113 114 decoder->packet_count--; 115 116 return 1; 117 } 118 119 static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params, 120 ocsd_etmv4_cfg *config) 121 { 122 config->reg_configr = params->etmv4.reg_configr; 123 config->reg_traceidr = params->etmv4.reg_traceidr; 124 config->reg_idr0 = params->etmv4.reg_idr0; 125 config->reg_idr1 = params->etmv4.reg_idr1; 126 config->reg_idr2 = params->etmv4.reg_idr2; 127 config->reg_idr8 = params->etmv4.reg_idr8; 128 config->reg_idr9 = 0; 129 config->reg_idr10 = 0; 130 config->reg_idr11 = 0; 131 config->reg_idr12 = 0; 132 config->reg_idr13 = 0; 133 config->arch_ver = ARCH_V8; 134 config->core_prof = profile_CortexA; 135 } 136 137 static void cs_etm_decoder__print_str_cb(const void *p_context, 138 const char *msg, 139 const int str_len) 140 { 141 if (p_context && str_len) 142 ((struct cs_etm_decoder *)p_context)->packet_printer(msg); 143 } 144 145 static int 146 cs_etm_decoder__init_def_logger_printing(struct cs_etm_decoder_params *d_params, 147 struct cs_etm_decoder *decoder) 148 { 149 int ret = 0; 150 151 if (d_params->packet_printer == NULL) 152 return -1; 153 154 decoder->packet_printer = d_params->packet_printer; 155 156 /* 157 * Set up a library default logger to process any printers 158 * (packet/raw frame) we add later. 159 */ 160 ret = ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1); 161 if (ret != 0) 162 return -1; 163 164 /* no stdout / err / file output */ 165 ret = ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL); 166 if (ret != 0) 167 return -1; 168 169 /* 170 * Set the string CB for the default logger, passes strings to 171 * perf print logger. 172 */ 173 ret = ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree, 174 (void *)decoder, 175 cs_etm_decoder__print_str_cb); 176 if (ret != 0) 177 ret = -1; 178 179 return 0; 180 } 181 182 #ifdef CS_LOG_RAW_FRAMES 183 static void 184 cs_etm_decoder__init_raw_frame_logging(struct cs_etm_decoder_params *d_params, 185 struct cs_etm_decoder *decoder) 186 { 187 /* Only log these during a --dump operation */ 188 if (d_params->operation == CS_ETM_OPERATION_PRINT) { 189 /* set up a library default logger to process the 190 * raw frame printer we add later 191 */ 192 ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1); 193 194 /* no stdout / err / file output */ 195 ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL); 196 197 /* set the string CB for the default logger, 198 * passes strings to perf print logger. 199 */ 200 ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree, 201 (void *)decoder, 202 cs_etm_decoder__print_str_cb); 203 204 /* use the built in library printer for the raw frames */ 205 ocsd_dt_set_raw_frame_printer(decoder->dcd_tree, 206 CS_RAW_DEBUG_FLAGS); 207 } 208 } 209 #else 210 static void 211 cs_etm_decoder__init_raw_frame_logging( 212 struct cs_etm_decoder_params *d_params __maybe_unused, 213 struct cs_etm_decoder *decoder __maybe_unused) 214 { 215 } 216 #endif 217 218 static int cs_etm_decoder__create_packet_printer(struct cs_etm_decoder *decoder, 219 const char *decoder_name, 220 void *trace_config) 221 { 222 u8 csid; 223 224 if (ocsd_dt_create_decoder(decoder->dcd_tree, decoder_name, 225 OCSD_CREATE_FLG_PACKET_PROC, 226 trace_config, &csid)) 227 return -1; 228 229 if (ocsd_dt_set_pkt_protocol_printer(decoder->dcd_tree, csid, 0)) 230 return -1; 231 232 return 0; 233 } 234 235 static int 236 cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params *t_params, 237 struct cs_etm_decoder *decoder) 238 { 239 const char *decoder_name; 240 ocsd_etmv4_cfg trace_config_etmv4; 241 void *trace_config; 242 243 switch (t_params->protocol) { 244 case CS_ETM_PROTO_ETMV4i: 245 cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4); 246 decoder_name = OCSD_BUILTIN_DCD_ETMV4I; 247 trace_config = &trace_config_etmv4; 248 break; 249 default: 250 return -1; 251 } 252 253 return cs_etm_decoder__create_packet_printer(decoder, 254 decoder_name, 255 trace_config); 256 } 257 258 static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder) 259 { 260 int i; 261 262 decoder->head = 0; 263 decoder->tail = 0; 264 decoder->packet_count = 0; 265 for (i = 0; i < MAX_BUFFER; i++) { 266 decoder->packet_buffer[i].start_addr = CS_ETM_INVAL_ADDR; 267 decoder->packet_buffer[i].end_addr = CS_ETM_INVAL_ADDR; 268 decoder->packet_buffer[i].last_instr_taken_branch = false; 269 decoder->packet_buffer[i].exc = false; 270 decoder->packet_buffer[i].exc_ret = false; 271 decoder->packet_buffer[i].cpu = INT_MIN; 272 } 273 } 274 275 static ocsd_datapath_resp_t 276 cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, 277 const u8 trace_chan_id, 278 enum cs_etm_sample_type sample_type) 279 { 280 u32 et = 0; 281 struct int_node *inode = NULL; 282 283 if (decoder->packet_count >= MAX_BUFFER - 1) 284 return OCSD_RESP_FATAL_SYS_ERR; 285 286 /* Search the RB tree for the cpu associated with this traceID */ 287 inode = intlist__find(traceid_list, trace_chan_id); 288 if (!inode) 289 return OCSD_RESP_FATAL_SYS_ERR; 290 291 et = decoder->tail; 292 et = (et + 1) & (MAX_BUFFER - 1); 293 decoder->tail = et; 294 decoder->packet_count++; 295 296 decoder->packet_buffer[et].sample_type = sample_type; 297 decoder->packet_buffer[et].exc = false; 298 decoder->packet_buffer[et].exc_ret = false; 299 decoder->packet_buffer[et].cpu = *((int *)inode->priv); 300 decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; 301 decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; 302 303 if (decoder->packet_count == MAX_BUFFER - 1) 304 return OCSD_RESP_WAIT; 305 306 return OCSD_RESP_CONT; 307 } 308 309 static ocsd_datapath_resp_t 310 cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder, 311 const ocsd_generic_trace_elem *elem, 312 const uint8_t trace_chan_id) 313 { 314 int ret = 0; 315 struct cs_etm_packet *packet; 316 317 ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id, 318 CS_ETM_RANGE); 319 if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT) 320 return ret; 321 322 packet = &decoder->packet_buffer[decoder->tail]; 323 324 packet->start_addr = elem->st_addr; 325 packet->end_addr = elem->en_addr; 326 switch (elem->last_i_type) { 327 case OCSD_INSTR_BR: 328 case OCSD_INSTR_BR_INDIRECT: 329 packet->last_instr_taken_branch = elem->last_instr_exec; 330 break; 331 case OCSD_INSTR_ISB: 332 case OCSD_INSTR_DSB_DMB: 333 case OCSD_INSTR_OTHER: 334 default: 335 packet->last_instr_taken_branch = false; 336 break; 337 } 338 339 return ret; 340 } 341 342 static ocsd_datapath_resp_t 343 cs_etm_decoder__buffer_trace_on(struct cs_etm_decoder *decoder, 344 const uint8_t trace_chan_id) 345 { 346 return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, 347 CS_ETM_TRACE_ON); 348 } 349 350 static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( 351 const void *context, 352 const ocsd_trc_index_t indx __maybe_unused, 353 const u8 trace_chan_id __maybe_unused, 354 const ocsd_generic_trace_elem *elem) 355 { 356 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 357 struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context; 358 359 switch (elem->elem_type) { 360 case OCSD_GEN_TRC_ELEM_UNKNOWN: 361 break; 362 case OCSD_GEN_TRC_ELEM_NO_SYNC: 363 decoder->trace_on = false; 364 break; 365 case OCSD_GEN_TRC_ELEM_TRACE_ON: 366 resp = cs_etm_decoder__buffer_trace_on(decoder, 367 trace_chan_id); 368 decoder->trace_on = true; 369 break; 370 case OCSD_GEN_TRC_ELEM_INSTR_RANGE: 371 resp = cs_etm_decoder__buffer_range(decoder, elem, 372 trace_chan_id); 373 break; 374 case OCSD_GEN_TRC_ELEM_EXCEPTION: 375 decoder->packet_buffer[decoder->tail].exc = true; 376 break; 377 case OCSD_GEN_TRC_ELEM_EXCEPTION_RET: 378 decoder->packet_buffer[decoder->tail].exc_ret = true; 379 break; 380 case OCSD_GEN_TRC_ELEM_PE_CONTEXT: 381 case OCSD_GEN_TRC_ELEM_EO_TRACE: 382 case OCSD_GEN_TRC_ELEM_ADDR_NACC: 383 case OCSD_GEN_TRC_ELEM_TIMESTAMP: 384 case OCSD_GEN_TRC_ELEM_CYCLE_COUNT: 385 case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN: 386 case OCSD_GEN_TRC_ELEM_EVENT: 387 case OCSD_GEN_TRC_ELEM_SWTRACE: 388 case OCSD_GEN_TRC_ELEM_CUSTOM: 389 default: 390 break; 391 } 392 393 return resp; 394 } 395 396 static int cs_etm_decoder__create_etm_packet_decoder( 397 struct cs_etm_trace_params *t_params, 398 struct cs_etm_decoder *decoder) 399 { 400 const char *decoder_name; 401 ocsd_etmv4_cfg trace_config_etmv4; 402 void *trace_config; 403 u8 csid; 404 405 switch (t_params->protocol) { 406 case CS_ETM_PROTO_ETMV4i: 407 cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4); 408 decoder_name = OCSD_BUILTIN_DCD_ETMV4I; 409 trace_config = &trace_config_etmv4; 410 break; 411 default: 412 return -1; 413 } 414 415 if (ocsd_dt_create_decoder(decoder->dcd_tree, 416 decoder_name, 417 OCSD_CREATE_FLG_FULL_DECODER, 418 trace_config, &csid)) 419 return -1; 420 421 if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree, 422 cs_etm_decoder__gen_trace_elem_printer, 423 decoder)) 424 return -1; 425 426 return 0; 427 } 428 429 static int 430 cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params, 431 struct cs_etm_trace_params *t_params, 432 struct cs_etm_decoder *decoder) 433 { 434 if (d_params->operation == CS_ETM_OPERATION_PRINT) 435 return cs_etm_decoder__create_etm_packet_printer(t_params, 436 decoder); 437 else if (d_params->operation == CS_ETM_OPERATION_DECODE) 438 return cs_etm_decoder__create_etm_packet_decoder(t_params, 439 decoder); 440 441 return -1; 442 } 443 444 struct cs_etm_decoder * 445 cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params, 446 struct cs_etm_trace_params t_params[]) 447 { 448 struct cs_etm_decoder *decoder; 449 ocsd_dcd_tree_src_t format; 450 u32 flags; 451 int i, ret; 452 453 if ((!t_params) || (!d_params)) 454 return NULL; 455 456 decoder = zalloc(sizeof(*decoder)); 457 458 if (!decoder) 459 return NULL; 460 461 decoder->data = d_params->data; 462 decoder->prev_return = OCSD_RESP_CONT; 463 cs_etm_decoder__clear_buffer(decoder); 464 format = (d_params->formatted ? OCSD_TRC_SRC_FRAME_FORMATTED : 465 OCSD_TRC_SRC_SINGLE); 466 flags = 0; 467 flags |= (d_params->fsyncs ? OCSD_DFRMTR_HAS_FSYNCS : 0); 468 flags |= (d_params->hsyncs ? OCSD_DFRMTR_HAS_HSYNCS : 0); 469 flags |= (d_params->frame_aligned ? OCSD_DFRMTR_FRAME_MEM_ALIGN : 0); 470 471 /* 472 * Drivers may add barrier frames when used with perf, set up to 473 * handle this. Barriers const of FSYNC packet repeated 4 times. 474 */ 475 flags |= OCSD_DFRMTR_RESET_ON_4X_FSYNC; 476 477 /* Create decode tree for the data source */ 478 decoder->dcd_tree = ocsd_create_dcd_tree(format, flags); 479 480 if (decoder->dcd_tree == 0) 481 goto err_free_decoder; 482 483 /* init library print logging support */ 484 ret = cs_etm_decoder__init_def_logger_printing(d_params, decoder); 485 if (ret != 0) 486 goto err_free_decoder_tree; 487 488 /* init raw frame logging if required */ 489 cs_etm_decoder__init_raw_frame_logging(d_params, decoder); 490 491 for (i = 0; i < num_cpu; i++) { 492 ret = cs_etm_decoder__create_etm_decoder(d_params, 493 &t_params[i], 494 decoder); 495 if (ret != 0) 496 goto err_free_decoder_tree; 497 } 498 499 return decoder; 500 501 err_free_decoder_tree: 502 ocsd_destroy_dcd_tree(decoder->dcd_tree); 503 err_free_decoder: 504 free(decoder); 505 return NULL; 506 } 507 508 int cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder, 509 u64 indx, const u8 *buf, 510 size_t len, size_t *consumed) 511 { 512 int ret = 0; 513 ocsd_datapath_resp_t cur = OCSD_RESP_CONT; 514 ocsd_datapath_resp_t prev_return = decoder->prev_return; 515 size_t processed = 0; 516 u32 count; 517 518 while (processed < len) { 519 if (OCSD_DATA_RESP_IS_WAIT(prev_return)) { 520 cur = ocsd_dt_process_data(decoder->dcd_tree, 521 OCSD_OP_FLUSH, 522 0, 523 0, 524 NULL, 525 NULL); 526 } else if (OCSD_DATA_RESP_IS_CONT(prev_return)) { 527 cur = ocsd_dt_process_data(decoder->dcd_tree, 528 OCSD_OP_DATA, 529 indx + processed, 530 len - processed, 531 &buf[processed], 532 &count); 533 processed += count; 534 } else { 535 ret = -EINVAL; 536 break; 537 } 538 539 /* 540 * Return to the input code if the packet buffer is full. 541 * Flushing will get done once the packet buffer has been 542 * processed. 543 */ 544 if (OCSD_DATA_RESP_IS_WAIT(cur)) 545 break; 546 547 prev_return = cur; 548 } 549 550 decoder->prev_return = cur; 551 *consumed = processed; 552 553 return ret; 554 } 555 556 void cs_etm_decoder__free(struct cs_etm_decoder *decoder) 557 { 558 if (!decoder) 559 return; 560 561 ocsd_destroy_dcd_tree(decoder->dcd_tree); 562 decoder->dcd_tree = NULL; 563 free(decoder); 564 } 565