switch to jtag_add_dr_scan_check() - USB performance fix
[openocd.git] / src / target / etm.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "etm.h"
25 #include "etb.h"
26 #include "image.h"
27 #include "arm7_9_common.h"
28 #include "arm_disassembler.h"
29
30
31 /* ETM register access functionality
32 *
33 */
34
35 #if 0
36 static bitfield_desc_t etm_comms_ctrl_bitfield_desc[] =
37 {
38 {"R", 1},
39 {"W", 1},
40 {"reserved", 26},
41 {"version", 4}
42 };
43 #endif
44
45 static int etm_reg_arch_info[] =
46 {
47 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
48 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
49 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
50 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
51 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
52 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
53 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
54 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
55 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
56 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
57 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
58 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
59 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67,
60 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
61 };
62
63 static int etm_reg_arch_size_info[] =
64 {
65 32, 32, 17, 8, 3, 9, 32, 16,
66 17, 26, 25, 8, 17, 32, 32, 17,
67 32, 32, 32, 32, 32, 32, 32, 32,
68 32, 32, 32, 32, 32, 32, 32, 32,
69 7, 7, 7, 7, 7, 7, 7, 7,
70 7, 7, 7, 7, 7, 7, 7, 7,
71 32, 32, 32, 32, 32, 32, 32, 32,
72 32, 32, 32, 32, 32, 32, 32, 32,
73 32, 32, 32, 32, 32, 32, 32, 32,
74 32, 32, 32, 32, 32, 32, 32, 32,
75 16, 16, 16, 16, 18, 18, 18, 18,
76 17, 17, 17, 17, 16, 16, 16, 16,
77 17, 17, 17, 17, 17, 17, 2,
78 17, 17, 17, 17, 32, 32, 32, 32
79 };
80
81 static char* etm_reg_list[] =
82 {
83 "ETM_CTRL",
84 "ETM_CONFIG",
85 "ETM_TRIG_EVENT",
86 "ETM_MMD_CTRL",
87 "ETM_STATUS",
88 "ETM_SYS_CONFIG",
89 "ETM_TRACE_RESOURCE_CTRL",
90 "ETM_TRACE_EN_CTRL2",
91 "ETM_TRACE_EN_EVENT",
92 "ETM_TRACE_EN_CTRL1",
93 "ETM_FIFOFULL_REGION",
94 "ETM_FIFOFULL_LEVEL",
95 "ETM_VIEWDATA_EVENT",
96 "ETM_VIEWDATA_CTRL1",
97 "ETM_VIEWDATA_CTRL2",
98 "ETM_VIEWDATA_CTRL3",
99 "ETM_ADDR_COMPARATOR_VALUE1",
100 "ETM_ADDR_COMPARATOR_VALUE2",
101 "ETM_ADDR_COMPARATOR_VALUE3",
102 "ETM_ADDR_COMPARATOR_VALUE4",
103 "ETM_ADDR_COMPARATOR_VALUE5",
104 "ETM_ADDR_COMPARATOR_VALUE6",
105 "ETM_ADDR_COMPARATOR_VALUE7",
106 "ETM_ADDR_COMPARATOR_VALUE8",
107 "ETM_ADDR_COMPARATOR_VALUE9",
108 "ETM_ADDR_COMPARATOR_VALUE10",
109 "ETM_ADDR_COMPARATOR_VALUE11",
110 "ETM_ADDR_COMPARATOR_VALUE12",
111 "ETM_ADDR_COMPARATOR_VALUE13",
112 "ETM_ADDR_COMPARATOR_VALUE14",
113 "ETM_ADDR_COMPARATOR_VALUE15",
114 "ETM_ADDR_COMPARATOR_VALUE16",
115 "ETM_ADDR_ACCESS_TYPE1",
116 "ETM_ADDR_ACCESS_TYPE2",
117 "ETM_ADDR_ACCESS_TYPE3",
118 "ETM_ADDR_ACCESS_TYPE4",
119 "ETM_ADDR_ACCESS_TYPE5",
120 "ETM_ADDR_ACCESS_TYPE6",
121 "ETM_ADDR_ACCESS_TYPE7",
122 "ETM_ADDR_ACCESS_TYPE8",
123 "ETM_ADDR_ACCESS_TYPE9",
124 "ETM_ADDR_ACCESS_TYPE10",
125 "ETM_ADDR_ACCESS_TYPE11",
126 "ETM_ADDR_ACCESS_TYPE12",
127 "ETM_ADDR_ACCESS_TYPE13",
128 "ETM_ADDR_ACCESS_TYPE14",
129 "ETM_ADDR_ACCESS_TYPE15",
130 "ETM_ADDR_ACCESS_TYPE16",
131 "ETM_DATA_COMPARATOR_VALUE1",
132 "ETM_DATA_COMPARATOR_VALUE2",
133 "ETM_DATA_COMPARATOR_VALUE3",
134 "ETM_DATA_COMPARATOR_VALUE4",
135 "ETM_DATA_COMPARATOR_VALUE5",
136 "ETM_DATA_COMPARATOR_VALUE6",
137 "ETM_DATA_COMPARATOR_VALUE7",
138 "ETM_DATA_COMPARATOR_VALUE8",
139 "ETM_DATA_COMPARATOR_VALUE9",
140 "ETM_DATA_COMPARATOR_VALUE10",
141 "ETM_DATA_COMPARATOR_VALUE11",
142 "ETM_DATA_COMPARATOR_VALUE12",
143 "ETM_DATA_COMPARATOR_VALUE13",
144 "ETM_DATA_COMPARATOR_VALUE14",
145 "ETM_DATA_COMPARATOR_VALUE15",
146 "ETM_DATA_COMPARATOR_VALUE16",
147 "ETM_DATA_COMPARATOR_MASK1",
148 "ETM_DATA_COMPARATOR_MASK2",
149 "ETM_DATA_COMPARATOR_MASK3",
150 "ETM_DATA_COMPARATOR_MASK4",
151 "ETM_DATA_COMPARATOR_MASK5",
152 "ETM_DATA_COMPARATOR_MASK6",
153 "ETM_DATA_COMPARATOR_MASK7",
154 "ETM_DATA_COMPARATOR_MASK8",
155 "ETM_DATA_COMPARATOR_MASK9",
156 "ETM_DATA_COMPARATOR_MASK10",
157 "ETM_DATA_COMPARATOR_MASK11",
158 "ETM_DATA_COMPARATOR_MASK12",
159 "ETM_DATA_COMPARATOR_MASK13",
160 "ETM_DATA_COMPARATOR_MASK14",
161 "ETM_DATA_COMPARATOR_MASK15",
162 "ETM_DATA_COMPARATOR_MASK16",
163 "ETM_COUNTER_INITAL_VALUE1",
164 "ETM_COUNTER_INITAL_VALUE2",
165 "ETM_COUNTER_INITAL_VALUE3",
166 "ETM_COUNTER_INITAL_VALUE4",
167 "ETM_COUNTER_ENABLE1",
168 "ETM_COUNTER_ENABLE2",
169 "ETM_COUNTER_ENABLE3",
170 "ETM_COUNTER_ENABLE4",
171 "ETM_COUNTER_RELOAD_VALUE1",
172 "ETM_COUNTER_RELOAD_VALUE2",
173 "ETM_COUNTER_RELOAD_VALUE3",
174 "ETM_COUNTER_RELOAD_VALUE4",
175 "ETM_COUNTER_VALUE1",
176 "ETM_COUNTER_VALUE2",
177 "ETM_COUNTER_VALUE3",
178 "ETM_COUNTER_VALUE4",
179 "ETM_SEQUENCER_CTRL1",
180 "ETM_SEQUENCER_CTRL2",
181 "ETM_SEQUENCER_CTRL3",
182 "ETM_SEQUENCER_CTRL4",
183 "ETM_SEQUENCER_CTRL5",
184 "ETM_SEQUENCER_CTRL6",
185 "ETM_SEQUENCER_STATE",
186 "ETM_EXTERNAL_OUTPUT1",
187 "ETM_EXTERNAL_OUTPUT2",
188 "ETM_EXTERNAL_OUTPUT3",
189 "ETM_EXTERNAL_OUTPUT4",
190 "ETM_CONTEXTID_COMPARATOR_VALUE1",
191 "ETM_CONTEXTID_COMPARATOR_VALUE2",
192 "ETM_CONTEXTID_COMPARATOR_VALUE3",
193 "ETM_CONTEXTID_COMPARATOR_MASK"
194 };
195
196 static int etm_reg_arch_type = -1;
197
198 static int etm_get_reg(reg_t *reg);
199
200 static command_t *etm_cmd = NULL;
201
202 reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
203 {
204 reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
205 reg_t *reg_list = NULL;
206 etm_reg_t *arch_info = NULL;
207 int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);
208 int i;
209
210 /* register a register arch-type for etm registers only once */
211 if (etm_reg_arch_type == -1)
212 etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);
213
214 /* the actual registers are kept in two arrays */
215 reg_list = calloc(num_regs, sizeof(reg_t));
216 arch_info = calloc(num_regs, sizeof(etm_reg_t));
217
218 /* fill in values for the reg cache */
219 reg_cache->name = "etm registers";
220 reg_cache->next = NULL;
221 reg_cache->reg_list = reg_list;
222 reg_cache->num_regs = num_regs;
223
224 /* set up registers */
225 for (i = 0; i < num_regs; i++)
226 {
227 reg_list[i].name = etm_reg_list[i];
228 reg_list[i].size = 32;
229 reg_list[i].dirty = 0;
230 reg_list[i].valid = 0;
231 reg_list[i].bitfield_desc = NULL;
232 reg_list[i].num_bitfields = 0;
233 reg_list[i].value = calloc(1, 4);
234 reg_list[i].arch_info = &arch_info[i];
235 reg_list[i].arch_type = etm_reg_arch_type;
236 reg_list[i].size = etm_reg_arch_size_info[i];
237 arch_info[i].addr = etm_reg_arch_info[i];
238 arch_info[i].jtag_info = jtag_info;
239 }
240
241 /* the ETM might have an ETB connected */
242 if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
243 {
244 etb_t *etb = etm_ctx->capture_driver_priv;
245
246 if (!etb)
247 {
248 LOG_ERROR("etb selected as etm capture driver, but no ETB configured");
249 return ERROR_OK;
250 }
251
252 reg_cache->next = etb_build_reg_cache(etb);
253
254 etb->reg_cache = reg_cache->next;
255 }
256
257
258 return reg_cache;
259 }
260
261 int etm_setup(target_t *target)
262 {
263 int retval;
264 u32 etm_ctrl_value;
265 armv4_5_common_t *armv4_5 = target->arch_info;
266 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
267 etm_context_t *etm_ctx = arm7_9->etm_ctx;
268 reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
269
270 /* initialize some ETM control register settings */
271 etm_get_reg(etm_ctrl_reg);
272 etm_ctrl_value = buf_get_u32(etm_ctrl_reg->value, 0, etm_ctrl_reg->size);
273
274 /* clear the ETM powerdown bit (0) */
275 etm_ctrl_value &= ~0x1;
276
277 /* configure port width (6:4), mode (17:16) and clocking (13) */
278 etm_ctrl_value = (etm_ctrl_value &
279 ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
280 | etm_ctx->portmode;
281
282 buf_set_u32(etm_ctrl_reg->value, 0, etm_ctrl_reg->size, etm_ctrl_value);
283 etm_store_reg(etm_ctrl_reg);
284
285 if ((retval=jtag_execute_queue())!=ERROR_OK)
286 return retval;
287
288 if ((retval=etm_ctx->capture_driver->init(etm_ctx)) != ERROR_OK)
289 {
290 LOG_ERROR("ETM capture driver initialization failed");
291 return retval;
292 }
293 return ERROR_OK;
294 }
295
296 int etm_get_reg(reg_t *reg)
297 {
298 int retval;
299
300 if ((retval = etm_read_reg(reg)) != ERROR_OK)
301 {
302 LOG_ERROR("BUG: error scheduling etm register read");
303 return retval;
304 }
305
306 if ((retval = jtag_execute_queue()) != ERROR_OK)
307 {
308 LOG_ERROR("register read failed");
309 return retval;
310 }
311
312 return ERROR_OK;
313 }
314
315 int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
316 {
317 etm_reg_t *etm_reg = reg->arch_info;
318 u8 reg_addr = etm_reg->addr & 0x7f;
319 scan_field_t fields[3];
320
321 LOG_DEBUG("%i", etm_reg->addr);
322
323 jtag_add_end_state(TAP_IDLE);
324 arm_jtag_scann(etm_reg->jtag_info, 0x6);
325 arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
326
327 fields[0].tap = etm_reg->jtag_info->tap;
328 fields[0].num_bits = 32;
329 fields[0].out_value = reg->value;
330 fields[0].in_value = NULL;
331 fields[0].check_value = NULL;
332 fields[0].check_mask = NULL;
333
334 fields[1].tap = etm_reg->jtag_info->tap;
335 fields[1].num_bits = 7;
336 fields[1].out_value = malloc(1);
337 buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
338 fields[1].in_value = NULL;
339 fields[1].check_value = NULL;
340 fields[1].check_mask = NULL;
341
342 fields[2].tap = etm_reg->jtag_info->tap;
343 fields[2].num_bits = 1;
344 fields[2].out_value = malloc(1);
345 buf_set_u32(fields[2].out_value, 0, 1, 0);
346 fields[2].in_value = NULL;
347 fields[2].check_value = NULL;
348 fields[2].check_mask = NULL;
349
350 jtag_add_dr_scan(3, fields, TAP_INVALID);
351
352 fields[0].in_value = reg->value;
353 fields[0].check_value = check_value;
354 fields[0].check_mask = check_mask;
355
356 jtag_add_dr_scan_check(3, fields, TAP_INVALID);
357
358 free(fields[1].out_value);
359 free(fields[2].out_value);
360
361 return ERROR_OK;
362 }
363
364 int etm_read_reg(reg_t *reg)
365 {
366 return etm_read_reg_w_check(reg, NULL, NULL);
367 }
368
369 int etm_set_reg(reg_t *reg, u32 value)
370 {
371 int retval;
372
373 if ((retval = etm_write_reg(reg, value)) != ERROR_OK)
374 {
375 LOG_ERROR("BUG: error scheduling etm register write");
376 return retval;
377 }
378
379 buf_set_u32(reg->value, 0, reg->size, value);
380 reg->valid = 1;
381 reg->dirty = 0;
382
383 return ERROR_OK;
384 }
385
386 int etm_set_reg_w_exec(reg_t *reg, u8 *buf)
387 {
388 int retval;
389
390 etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));
391
392 if ((retval = jtag_execute_queue()) != ERROR_OK)
393 {
394 LOG_ERROR("register write failed");
395 return retval;
396 }
397 return ERROR_OK;
398 }
399
400 int etm_write_reg(reg_t *reg, u32 value)
401 {
402 etm_reg_t *etm_reg = reg->arch_info;
403 u8 reg_addr = etm_reg->addr & 0x7f;
404 scan_field_t fields[3];
405
406 LOG_DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
407
408 jtag_add_end_state(TAP_IDLE);
409 arm_jtag_scann(etm_reg->jtag_info, 0x6);
410 arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
411
412 fields[0].tap = etm_reg->jtag_info->tap;
413 fields[0].num_bits = 32;
414 fields[0].out_value = malloc(4);
415 buf_set_u32(fields[0].out_value, 0, 32, value);
416
417 fields[0].in_value = NULL;
418
419 fields[1].tap = etm_reg->jtag_info->tap;
420 fields[1].num_bits = 7;
421 fields[1].out_value = malloc(1);
422 buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
423
424 fields[1].in_value = NULL;
425
426 fields[2].tap = etm_reg->jtag_info->tap;
427 fields[2].num_bits = 1;
428 fields[2].out_value = malloc(1);
429 buf_set_u32(fields[2].out_value, 0, 1, 1);
430
431 fields[2].in_value = NULL;
432
433 jtag_add_dr_scan(3, fields, TAP_INVALID);
434
435 free(fields[0].out_value);
436 free(fields[1].out_value);
437 free(fields[2].out_value);
438
439 return ERROR_OK;
440 }
441
442 int etm_store_reg(reg_t *reg)
443 {
444 return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
445 }
446
447 /* ETM trace analysis functionality
448 *
449 */
450 extern etm_capture_driver_t etm_dummy_capture_driver;
451 #if BUILD_OOCD_TRACE == 1
452 extern etm_capture_driver_t oocd_trace_capture_driver;
453 #endif
454
455 static etm_capture_driver_t *etm_capture_drivers[] =
456 {
457 &etb_capture_driver,
458 &etm_dummy_capture_driver,
459 #if BUILD_OOCD_TRACE == 1
460 &oocd_trace_capture_driver,
461 #endif
462 NULL
463 };
464
465 char *etmv1v1_branch_reason_strings[] =
466 {
467 "normal PC change",
468 "tracing enabled",
469 "trace restarted after overflow",
470 "exit from debug",
471 "periodic synchronization",
472 "reserved",
473 "reserved",
474 "reserved",
475 };
476
477 static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
478 {
479 int i;
480 int section = -1;
481 u32 size_read;
482 u32 opcode;
483 int retval;
484
485 if (!ctx->image)
486 return ERROR_TRACE_IMAGE_UNAVAILABLE;
487
488 /* search for the section the current instruction belongs to */
489 for (i = 0; i < ctx->image->num_sections; i++)
490 {
491 if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
492 (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))
493 {
494 section = i;
495 break;
496 }
497 }
498
499 if (section == -1)
500 {
501 /* current instruction couldn't be found in the image */
502 return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
503 }
504
505 if (ctx->core_state == ARMV4_5_STATE_ARM)
506 {
507 u8 buf[4];
508 if ((retval = image_read_section(ctx->image, section,
509 ctx->current_pc - ctx->image->sections[section].base_address,
510 4, buf, &size_read)) != ERROR_OK)
511 {
512 LOG_ERROR("error while reading instruction: %i", retval);
513 return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
514 }
515 opcode = target_buffer_get_u32(ctx->target, buf);
516 arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
517 }
518 else if (ctx->core_state == ARMV4_5_STATE_THUMB)
519 {
520 u8 buf[2];
521 if ((retval = image_read_section(ctx->image, section,
522 ctx->current_pc - ctx->image->sections[section].base_address,
523 2, buf, &size_read)) != ERROR_OK)
524 {
525 LOG_ERROR("error while reading instruction: %i", retval);
526 return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
527 }
528 opcode = target_buffer_get_u16(ctx->target, buf);
529 thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
530 }
531 else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
532 {
533 LOG_ERROR("BUG: tracing of jazelle code not supported");
534 exit(-1);
535 }
536 else
537 {
538 LOG_ERROR("BUG: unknown core state encountered");
539 exit(-1);
540 }
541
542 return ERROR_OK;
543 }
544
545 static int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)
546 {
547 while (ctx->data_index < ctx->trace_depth)
548 {
549 /* if the caller specified an address packet offset, skip until the
550 * we reach the n-th cycle marked with tracesync */
551 if (apo > 0)
552 {
553 if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
554 apo--;
555
556 if (apo > 0)
557 {
558 ctx->data_index++;
559 ctx->data_half = 0;
560 }
561 continue;
562 }
563
564 /* no tracedata output during a TD cycle
565 * or in a trigger cycle */
566 if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
567 || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))
568 {
569 ctx->data_index++;
570 ctx->data_half = 0;
571 continue;
572 }
573
574 if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)
575 {
576 if (ctx->data_half == 0)
577 {
578 *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
579 ctx->data_half = 1;
580 }
581 else
582 {
583 *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
584 ctx->data_half = 0;
585 ctx->data_index++;
586 }
587 }
588 else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
589 {
590 *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
591 ctx->data_index++;
592 }
593 else
594 {
595 /* on a 4-bit port, a packet will be output during two consecutive cycles */
596 if (ctx->data_index > (ctx->trace_depth - 2))
597 return -1;
598
599 *packet = ctx->trace_data[ctx->data_index].packet & 0xf;
600 *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
601 ctx->data_index += 2;
602 }
603
604 return 0;
605 }
606
607 return -1;
608 }
609
610 static int etmv1_branch_address(etm_context_t *ctx)
611 {
612 int retval;
613 u8 packet;
614 int shift = 0;
615 int apo;
616 u32 i;
617
618 /* quit analysis if less than two cycles are left in the trace
619 * because we can't extract the APO */
620 if (ctx->data_index > (ctx->trace_depth - 2))
621 return -1;
622
623 /* a BE could be output during an APO cycle, skip the current
624 * and continue with the new one */
625 if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
626 return 1;
627 if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
628 return 2;
629
630 /* address packet offset encoded in the next two cycles' pipestat bits */
631 apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
632 apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
633
634 /* count number of tracesync cycles between current pipe_index and data_index
635 * i.e. the number of tracesyncs that data_index already passed by
636 * to subtract them from the APO */
637 for (i = ctx->pipe_index; i < ctx->data_index; i++)
638 {
639 if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
640 apo--;
641 }
642
643 /* extract up to four 7-bit packets */
644 do {
645 if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)
646 return -1;
647 ctx->last_branch &= ~(0x7f << shift);
648 ctx->last_branch |= (packet & 0x7f) << shift;
649 shift += 7;
650 } while ((packet & 0x80) && (shift < 28));
651
652 /* one last packet holding 4 bits of the address, plus the branch reason code */
653 if ((shift == 28) && (packet & 0x80))
654 {
655 if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
656 return -1;
657 ctx->last_branch &= 0x0fffffff;
658 ctx->last_branch |= (packet & 0x0f) << 28;
659 ctx->last_branch_reason = (packet & 0x70) >> 4;
660 shift += 4;
661 }
662 else
663 {
664 ctx->last_branch_reason = 0;
665 }
666
667 if (shift == 32)
668 {
669 ctx->pc_ok = 1;
670 }
671
672 /* if a full address was output, we might have branched into Jazelle state */
673 if ((shift == 32) && (packet & 0x80))
674 {
675 ctx->core_state = ARMV4_5_STATE_JAZELLE;
676 }
677 else
678 {
679 /* if we didn't branch into Jazelle state, the current processor state is
680 * encoded in bit 0 of the branch target address */
681 if (ctx->last_branch & 0x1)
682 {
683 ctx->core_state = ARMV4_5_STATE_THUMB;
684 ctx->last_branch &= ~0x1;
685 }
686 else
687 {
688 ctx->core_state = ARMV4_5_STATE_ARM;
689 ctx->last_branch &= ~0x3;
690 }
691 }
692
693 return 0;
694 }
695
696 static int etmv1_data(etm_context_t *ctx, int size, u32 *data)
697 {
698 int j;
699 u8 buf[4];
700 int retval;
701
702 for (j = 0; j < size; j++)
703 {
704 if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)
705 return -1;
706 }
707
708 if (size == 8)
709 {
710 LOG_ERROR("TODO: add support for 64-bit values");
711 return -1;
712 }
713 else if (size == 4)
714 *data = target_buffer_get_u32(ctx->target, buf);
715 else if (size == 2)
716 *data = target_buffer_get_u16(ctx->target, buf);
717 else if (size == 1)
718 *data = buf[0];
719 else
720 return -1;
721
722 return 0;
723 }
724
725 static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
726 {
727 int retval;
728 arm_instruction_t instruction;
729
730 /* read the trace data if it wasn't read already */
731 if (ctx->trace_depth == 0)
732 ctx->capture_driver->read_trace(ctx);
733
734 /* start at the beginning of the captured trace */
735 ctx->pipe_index = 0;
736 ctx->data_index = 0;
737 ctx->data_half = 0;
738
739 /* neither the PC nor the data pointer are valid */
740 ctx->pc_ok = 0;
741 ctx->ptr_ok = 0;
742
743 while (ctx->pipe_index < ctx->trace_depth)
744 {
745 u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
746 u32 next_pc = ctx->current_pc;
747 u32 old_data_index = ctx->data_index;
748 u32 old_data_half = ctx->data_half;
749 u32 old_index = ctx->pipe_index;
750 u32 last_instruction = ctx->last_instruction;
751 u32 cycles = 0;
752 int current_pc_ok = ctx->pc_ok;
753
754 if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
755 {
756 command_print(cmd_ctx, "--- trigger ---");
757 }
758
759 /* instructions execute in IE/D or BE/D cycles */
760 if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
761 ctx->last_instruction = ctx->pipe_index;
762
763 /* if we don't have a valid pc skip until we reach an indirect branch */
764 if ((!ctx->pc_ok) && (pipestat != STAT_BE))
765 {
766 ctx->pipe_index++;
767 continue;
768 }
769
770 /* any indirect branch could have interrupted instruction flow
771 * - the branch reason code could indicate a trace discontinuity
772 * - a branch to the exception vectors indicates an exception
773 */
774 if ((pipestat == STAT_BE) || (pipestat == STAT_BD))
775 {
776 /* backup current data index, to be able to consume the branch address
777 * before examining data address and values
778 */
779 old_data_index = ctx->data_index;
780 old_data_half = ctx->data_half;
781
782 ctx->last_instruction = ctx->pipe_index;
783
784 if ((retval = etmv1_branch_address(ctx)) != 0)
785 {
786 /* negative return value from etmv1_branch_address means we ran out of packets,
787 * quit analysing the trace */
788 if (retval < 0)
789 break;
790
791 /* a positive return values means the current branch was abandoned,
792 * and a new branch was encountered in cycle ctx->pipe_index + retval;
793 */
794 LOG_WARNING("abandoned branch encountered, correctnes of analysis uncertain");
795 ctx->pipe_index += retval;
796 continue;
797 }
798
799 /* skip over APO cycles */
800 ctx->pipe_index += 2;
801
802 switch (ctx->last_branch_reason)
803 {
804 case 0x0: /* normal PC change */
805 next_pc = ctx->last_branch;
806 break;
807 case 0x1: /* tracing enabled */
808 command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);
809 ctx->current_pc = ctx->last_branch;
810 ctx->pipe_index++;
811 continue;
812 break;
813 case 0x2: /* trace restarted after FIFO overflow */
814 command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);
815 ctx->current_pc = ctx->last_branch;
816 ctx->pipe_index++;
817 continue;
818 break;
819 case 0x3: /* exit from debug state */
820 command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);
821 ctx->current_pc = ctx->last_branch;
822 ctx->pipe_index++;
823 continue;
824 break;
825 case 0x4: /* periodic synchronization point */
826 next_pc = ctx->last_branch;
827 /* if we had no valid PC prior to this synchronization point,
828 * we have to move on with the next trace cycle
829 */
830 if (!current_pc_ok)
831 {
832 command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);
833 ctx->current_pc = next_pc;
834 ctx->pipe_index++;
835 continue;
836 }
837 break;
838 default: /* reserved */
839 LOG_ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);
840 exit(-1);
841 break;
842 }
843
844 /* if we got here the branch was a normal PC change
845 * (or a periodic synchronization point, which means the same for that matter)
846 * if we didn't accquire a complete PC continue with the next cycle
847 */
848 if (!ctx->pc_ok)
849 continue;
850
851 /* indirect branch to the exception vector means an exception occured */
852 if ((ctx->last_branch <= 0x20)
853 || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
854 {
855 if ((ctx->last_branch & 0xff) == 0x10)
856 {
857 command_print(cmd_ctx, "data abort");
858 }
859 else
860 {
861 command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);
862 ctx->current_pc = ctx->last_branch;
863 ctx->pipe_index++;
864 continue;
865 }
866 }
867 }
868
869 /* an instruction was executed (or not, depending on the condition flags)
870 * retrieve it from the image for displaying */
871 if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
872 !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
873 ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))
874 {
875 if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)
876 {
877 /* can't continue tracing with no image available */
878 if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
879 {
880 return retval;
881 }
882 else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
883 {
884 /* TODO: handle incomplete images
885 * for now we just quit the analsysis*/
886 return retval;
887 }
888 }
889
890 cycles = old_index - last_instruction;
891 }
892
893 if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
894 {
895 u32 new_data_index = ctx->data_index;
896 u32 new_data_half = ctx->data_half;
897
898 /* in case of a branch with data, the branch target address was consumed before
899 * we temporarily go back to the saved data index */
900 if (pipestat == STAT_BD)
901 {
902 ctx->data_index = old_data_index;
903 ctx->data_half = old_data_half;
904 }
905
906 if (ctx->tracemode & ETMV1_TRACE_ADDR)
907 {
908 u8 packet;
909 int shift = 0;
910
911 do {
912 if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
913 return ERROR_ETM_ANALYSIS_FAILED;
914 ctx->last_ptr &= ~(0x7f << shift);
915 ctx->last_ptr |= (packet & 0x7f) << shift;
916 shift += 7;
917 } while ((packet & 0x80) && (shift < 32));
918
919 if (shift >= 32)
920 ctx->ptr_ok = 1;
921
922 if (ctx->ptr_ok)
923 {
924 command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);
925 }
926 }
927
928 if (ctx->tracemode & ETMV1_TRACE_DATA)
929 {
930 if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
931 {
932 int i;
933 for (i = 0; i < 16; i++)
934 {
935 if (instruction.info.load_store_multiple.register_list & (1 << i))
936 {
937 u32 data;
938 if (etmv1_data(ctx, 4, &data) != 0)
939 return ERROR_ETM_ANALYSIS_FAILED;
940 command_print(cmd_ctx, "data: 0x%8.8x", data);
941 }
942 }
943 }
944 else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))
945 {
946 u32 data;
947 if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
948 return ERROR_ETM_ANALYSIS_FAILED;
949 command_print(cmd_ctx, "data: 0x%8.8x", data);
950 }
951 }
952
953 /* restore data index after consuming BD address and data */
954 if (pipestat == STAT_BD)
955 {
956 ctx->data_index = new_data_index;
957 ctx->data_half = new_data_half;
958 }
959 }
960
961 /* adjust PC */
962 if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
963 {
964 if (((instruction.type == ARM_B) ||
965 (instruction.type == ARM_BL) ||
966 (instruction.type == ARM_BLX)) &&
967 (instruction.info.b_bl_bx_blx.target_address != 0xffffffff))
968 {
969 next_pc = instruction.info.b_bl_bx_blx.target_address;
970 }
971 else
972 {
973 next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
974 }
975 }
976 else if (pipestat == STAT_IN)
977 {
978 next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
979 }
980
981 if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
982 {
983 char cycles_text[32] = "";
984
985 /* if the trace was captured with cycle accurate tracing enabled,
986 * output the number of cycles since the last executed instruction
987 */
988 if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)
989 {
990 snprintf(cycles_text, 32, " (%i %s)",
991 cycles,
992 (cycles == 1) ? "cycle" : "cycles");
993 }
994
995 command_print(cmd_ctx, "%s%s%s",
996 instruction.text,
997 (pipestat == STAT_IN) ? " (not executed)" : "",
998 cycles_text);
999
1000 ctx->current_pc = next_pc;
1001
1002 /* packets for an instruction don't start on or before the preceding
1003 * functional pipestat (i.e. other than WT or TD)
1004 */
1005 if (ctx->data_index <= ctx->pipe_index)
1006 {
1007 ctx->data_index = ctx->pipe_index + 1;
1008 ctx->data_half = 0;
1009 }
1010 }
1011
1012 ctx->pipe_index += 1;
1013 }
1014
1015 return ERROR_OK;
1016 }
1017
1018 static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1019 {
1020 target_t *target;
1021 armv4_5_common_t *armv4_5;
1022 arm7_9_common_t *arm7_9;
1023 etmv1_tracemode_t tracemode;
1024
1025 target = get_current_target(cmd_ctx);
1026
1027 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1028 {
1029 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1030 return ERROR_OK;
1031 }
1032
1033 if (!arm7_9->etm_ctx)
1034 {
1035 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1036 return ERROR_OK;
1037 }
1038
1039 tracemode = arm7_9->etm_ctx->tracemode;
1040
1041 if (argc == 4)
1042 {
1043 if (strcmp(args[0], "none") == 0)
1044 {
1045 tracemode = ETMV1_TRACE_NONE;
1046 }
1047 else if (strcmp(args[0], "data") == 0)
1048 {
1049 tracemode = ETMV1_TRACE_DATA;
1050 }
1051 else if (strcmp(args[0], "address") == 0)
1052 {
1053 tracemode = ETMV1_TRACE_ADDR;
1054 }
1055 else if (strcmp(args[0], "all") == 0)
1056 {
1057 tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
1058 }
1059 else
1060 {
1061 command_print(cmd_ctx, "invalid option '%s'", args[0]);
1062 return ERROR_OK;
1063 }
1064
1065 switch (strtol(args[1], NULL, 0))
1066 {
1067 case 0:
1068 tracemode |= ETMV1_CONTEXTID_NONE;
1069 break;
1070 case 8:
1071 tracemode |= ETMV1_CONTEXTID_8;
1072 break;
1073 case 16:
1074 tracemode |= ETMV1_CONTEXTID_16;
1075 break;
1076 case 32:
1077 tracemode |= ETMV1_CONTEXTID_32;
1078 break;
1079 default:
1080 command_print(cmd_ctx, "invalid option '%s'", args[1]);
1081 return ERROR_OK;
1082 }
1083
1084 if (strcmp(args[2], "enable") == 0)
1085 {
1086 tracemode |= ETMV1_CYCLE_ACCURATE;
1087 }
1088 else if (strcmp(args[2], "disable") == 0)
1089 {
1090 tracemode |= 0;
1091 }
1092 else
1093 {
1094 command_print(cmd_ctx, "invalid option '%s'", args[2]);
1095 return ERROR_OK;
1096 }
1097
1098 if (strcmp(args[3], "enable") == 0)
1099 {
1100 tracemode |= ETMV1_BRANCH_OUTPUT;
1101 }
1102 else if (strcmp(args[3], "disable") == 0)
1103 {
1104 tracemode |= 0;
1105 }
1106 else
1107 {
1108 command_print(cmd_ctx, "invalid option '%s'", args[2]);
1109 return ERROR_OK;
1110 }
1111 }
1112 else if (argc != 0)
1113 {
1114 command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");
1115 return ERROR_OK;
1116 }
1117
1118 command_print(cmd_ctx, "current tracemode configuration:");
1119
1120 switch (tracemode & ETMV1_TRACE_MASK)
1121 {
1122 case ETMV1_TRACE_NONE:
1123 command_print(cmd_ctx, "data tracing: none");
1124 break;
1125 case ETMV1_TRACE_DATA:
1126 command_print(cmd_ctx, "data tracing: data only");
1127 break;
1128 case ETMV1_TRACE_ADDR:
1129 command_print(cmd_ctx, "data tracing: address only");
1130 break;
1131 case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:
1132 command_print(cmd_ctx, "data tracing: address and data");
1133 break;
1134 }
1135
1136 switch (tracemode & ETMV1_CONTEXTID_MASK)
1137 {
1138 case ETMV1_CONTEXTID_NONE:
1139 command_print(cmd_ctx, "contextid tracing: none");
1140 break;
1141 case ETMV1_CONTEXTID_8:
1142 command_print(cmd_ctx, "contextid tracing: 8 bit");
1143 break;
1144 case ETMV1_CONTEXTID_16:
1145 command_print(cmd_ctx, "contextid tracing: 16 bit");
1146 break;
1147 case ETMV1_CONTEXTID_32:
1148 command_print(cmd_ctx, "contextid tracing: 32 bit");
1149 break;
1150 }
1151
1152 if (tracemode & ETMV1_CYCLE_ACCURATE)
1153 {
1154 command_print(cmd_ctx, "cycle-accurate tracing enabled");
1155 }
1156 else
1157 {
1158 command_print(cmd_ctx, "cycle-accurate tracing disabled");
1159 }
1160
1161 if (tracemode & ETMV1_BRANCH_OUTPUT)
1162 {
1163 command_print(cmd_ctx, "full branch address output enabled");
1164 }
1165 else
1166 {
1167 command_print(cmd_ctx, "full branch address output disabled");
1168 }
1169
1170 /* only update ETM_CTRL register if tracemode changed */
1171 if (arm7_9->etm_ctx->tracemode != tracemode)
1172 {
1173 reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
1174
1175 etm_get_reg(etm_ctrl_reg);
1176
1177 buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);
1178 buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);
1179 buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);
1180 buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);
1181 etm_store_reg(etm_ctrl_reg);
1182
1183 arm7_9->etm_ctx->tracemode = tracemode;
1184
1185 /* invalidate old trace data */
1186 arm7_9->etm_ctx->capture_status = TRACE_IDLE;
1187 if (arm7_9->etm_ctx->trace_depth > 0)
1188 {
1189 free(arm7_9->etm_ctx->trace_data);
1190 arm7_9->etm_ctx->trace_data = NULL;
1191 }
1192 arm7_9->etm_ctx->trace_depth = 0;
1193 }
1194
1195 return ERROR_OK;
1196 }
1197
1198 static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1199 {
1200 target_t *target;
1201 armv4_5_common_t *armv4_5;
1202 arm7_9_common_t *arm7_9;
1203 etm_portmode_t portmode = 0x0;
1204 etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));
1205 int i;
1206
1207 if (argc != 5)
1208 {
1209 return ERROR_COMMAND_SYNTAX_ERROR;
1210 }
1211
1212 target = get_target_by_num(strtoul(args[0], NULL, 0));
1213
1214 if (!target)
1215 {
1216 LOG_ERROR("target number '%s' not defined", args[0]);
1217 return ERROR_FAIL;
1218 }
1219
1220 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1221 {
1222 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1223 return ERROR_FAIL;
1224 }
1225
1226 switch (strtoul(args[1], NULL, 0))
1227 {
1228 case 4:
1229 portmode |= ETM_PORT_4BIT;
1230 break;
1231 case 8:
1232 portmode |= ETM_PORT_8BIT;
1233 break;
1234 case 16:
1235 portmode |= ETM_PORT_16BIT;
1236 break;
1237 default:
1238 command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);
1239 return ERROR_FAIL;
1240 }
1241
1242 if (strcmp("normal", args[2]) == 0)
1243 {
1244 portmode |= ETM_PORT_NORMAL;
1245 }
1246 else if (strcmp("multiplexed", args[2]) == 0)
1247 {
1248 portmode |= ETM_PORT_MUXED;
1249 }
1250 else if (strcmp("demultiplexed", args[2]) == 0)
1251 {
1252 portmode |= ETM_PORT_DEMUXED;
1253 }
1254 else
1255 {
1256 command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
1257 return ERROR_FAIL;
1258 }
1259
1260 if (strcmp("half", args[3]) == 0)
1261 {
1262 portmode |= ETM_PORT_HALF_CLOCK;
1263 }
1264 else if (strcmp("full", args[3]) == 0)
1265 {
1266 portmode |= ETM_PORT_FULL_CLOCK;
1267 }
1268 else
1269 {
1270 command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
1271 return ERROR_FAIL;
1272 }
1273
1274 for (i=0; etm_capture_drivers[i]; i++)
1275 {
1276 if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)
1277 {
1278 int retval;
1279 if ((retval=etm_capture_drivers[i]->register_commands(cmd_ctx)) != ERROR_OK)
1280 {
1281 free(etm_ctx);
1282 return retval;
1283 }
1284
1285 etm_ctx->capture_driver = etm_capture_drivers[i];
1286
1287 break;
1288 }
1289 }
1290
1291 if (!etm_capture_drivers[i])
1292 {
1293 /* no supported capture driver found, don't register an ETM */
1294 free(etm_ctx);
1295 LOG_ERROR("trace capture driver '%s' not found", args[4]);
1296 return ERROR_FAIL;
1297 }
1298
1299 etm_ctx->target = target;
1300 etm_ctx->trigger_percent = 50;
1301 etm_ctx->trace_data = NULL;
1302 etm_ctx->trace_depth = 0;
1303 etm_ctx->portmode = portmode;
1304 etm_ctx->tracemode = 0x0;
1305 etm_ctx->core_state = ARMV4_5_STATE_ARM;
1306 etm_ctx->image = NULL;
1307 etm_ctx->pipe_index = 0;
1308 etm_ctx->data_index = 0;
1309 etm_ctx->current_pc = 0x0;
1310 etm_ctx->pc_ok = 0;
1311 etm_ctx->last_branch = 0x0;
1312 etm_ctx->last_branch_reason = 0x0;
1313 etm_ctx->last_ptr = 0x0;
1314 etm_ctx->ptr_ok = 0x0;
1315 etm_ctx->context_id = 0x0;
1316 etm_ctx->last_instruction = 0;
1317
1318 arm7_9->etm_ctx = etm_ctx;
1319
1320 return etm_register_user_commands(cmd_ctx);
1321 }
1322
1323 int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1324 {
1325 target_t *target;
1326 armv4_5_common_t *armv4_5;
1327 arm7_9_common_t *arm7_9;
1328 reg_t *etm_config_reg;
1329 reg_t *etm_sys_config_reg;
1330
1331 int max_port_size;
1332
1333 target = get_current_target(cmd_ctx);
1334
1335 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1336 {
1337 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1338 return ERROR_OK;
1339 }
1340
1341 if (!arm7_9->etm_ctx)
1342 {
1343 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1344 return ERROR_OK;
1345 }
1346
1347 etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
1348 etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
1349
1350 etm_get_reg(etm_config_reg);
1351 command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));
1352 command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));
1353 command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));
1354 command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));
1355 command_print(cmd_ctx, "sequencer %spresent",
1356 (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");
1357 command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));
1358 command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));
1359 command_print(cmd_ctx, "FIFO full %spresent",
1360 (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");
1361 command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));
1362
1363 etm_get_reg(etm_sys_config_reg);
1364
1365 switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))
1366 {
1367 case 0:
1368 max_port_size = 4;
1369 break;
1370 case 1:
1371 max_port_size = 8;
1372 break;
1373 case 2:
1374 max_port_size = 16;
1375 break;
1376 default:
1377 LOG_ERROR("Illegal max_port_size");
1378 exit(-1);
1379 }
1380 command_print(cmd_ctx, "max. port size: %i", max_port_size);
1381
1382 command_print(cmd_ctx, "half-rate clocking %ssupported",
1383 (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");
1384 command_print(cmd_ctx, "full-rate clocking %ssupported",
1385 (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");
1386 command_print(cmd_ctx, "normal trace format %ssupported",
1387 (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");
1388 command_print(cmd_ctx, "multiplex trace format %ssupported",
1389 (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");
1390 command_print(cmd_ctx, "demultiplex trace format %ssupported",
1391 (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");
1392 command_print(cmd_ctx, "FIFO full %ssupported",
1393 (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");
1394
1395 return ERROR_OK;
1396 }
1397
1398 static int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1399 {
1400 target_t *target;
1401 armv4_5_common_t *armv4_5;
1402 arm7_9_common_t *arm7_9;
1403 trace_status_t trace_status;
1404
1405 target = get_current_target(cmd_ctx);
1406
1407 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1408 {
1409 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1410 return ERROR_OK;
1411 }
1412
1413 if (!arm7_9->etm_ctx)
1414 {
1415 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1416 return ERROR_OK;
1417 }
1418
1419 trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);
1420
1421 if (trace_status == TRACE_IDLE)
1422 {
1423 command_print(cmd_ctx, "tracing is idle");
1424 }
1425 else
1426 {
1427 static char *completed = " completed";
1428 static char *running = " is running";
1429 static char *overflowed = ", trace overflowed";
1430 static char *triggered = ", trace triggered";
1431
1432 command_print(cmd_ctx, "trace collection%s%s%s",
1433 (trace_status & TRACE_RUNNING) ? running : completed,
1434 (trace_status & TRACE_OVERFLOWED) ? overflowed : "",
1435 (trace_status & TRACE_TRIGGERED) ? triggered : "");
1436
1437 if (arm7_9->etm_ctx->trace_depth > 0)
1438 {
1439 command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);
1440 }
1441 }
1442
1443 return ERROR_OK;
1444 }
1445
1446 static int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1447 {
1448 target_t *target;
1449 armv4_5_common_t *armv4_5;
1450 arm7_9_common_t *arm7_9;
1451 etm_context_t *etm_ctx;
1452
1453 if (argc < 1)
1454 {
1455 command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
1456 return ERROR_OK;
1457 }
1458
1459 target = get_current_target(cmd_ctx);
1460
1461 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1462 {
1463 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1464 return ERROR_OK;
1465 }
1466
1467 if (!(etm_ctx = arm7_9->etm_ctx))
1468 {
1469 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1470 return ERROR_OK;
1471 }
1472
1473 if (etm_ctx->image)
1474 {
1475 image_close(etm_ctx->image);
1476 free(etm_ctx->image);
1477 command_print(cmd_ctx, "previously loaded image found and closed");
1478 }
1479
1480 etm_ctx->image = malloc(sizeof(image_t));
1481 etm_ctx->image->base_address_set = 0;
1482 etm_ctx->image->start_address_set = 0;
1483
1484 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
1485 if (argc >= 2)
1486 {
1487 etm_ctx->image->base_address_set = 1;
1488 etm_ctx->image->base_address = strtoul(args[1], NULL, 0);
1489 }
1490 else
1491 {
1492 etm_ctx->image->base_address_set = 0;
1493 }
1494
1495 if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
1496 {
1497 free(etm_ctx->image);
1498 etm_ctx->image = NULL;
1499 return ERROR_OK;
1500 }
1501
1502 return ERROR_OK;
1503 }
1504
1505 static int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1506 {
1507 fileio_t file;
1508 target_t *target;
1509 armv4_5_common_t *armv4_5;
1510 arm7_9_common_t *arm7_9;
1511 etm_context_t *etm_ctx;
1512 u32 i;
1513
1514 if (argc != 1)
1515 {
1516 command_print(cmd_ctx, "usage: etm dump <file>");
1517 return ERROR_OK;
1518 }
1519
1520 target = get_current_target(cmd_ctx);
1521
1522 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1523 {
1524 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1525 return ERROR_OK;
1526 }
1527
1528 if (!(etm_ctx = arm7_9->etm_ctx))
1529 {
1530 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1531 return ERROR_OK;
1532 }
1533
1534 if (etm_ctx->capture_driver->status == TRACE_IDLE)
1535 {
1536 command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");
1537 return ERROR_OK;
1538 }
1539
1540 if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
1541 {
1542 /* TODO: if on-the-fly capture is to be supported, this needs to be changed */
1543 command_print(cmd_ctx, "trace capture not completed");
1544 return ERROR_OK;
1545 }
1546
1547 /* read the trace data if it wasn't read already */
1548 if (etm_ctx->trace_depth == 0)
1549 etm_ctx->capture_driver->read_trace(etm_ctx);
1550
1551 if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
1552 {
1553 return ERROR_OK;
1554 }
1555
1556 fileio_write_u32(&file, etm_ctx->capture_status);
1557 fileio_write_u32(&file, etm_ctx->portmode);
1558 fileio_write_u32(&file, etm_ctx->tracemode);
1559 fileio_write_u32(&file, etm_ctx->trace_depth);
1560
1561 for (i = 0; i < etm_ctx->trace_depth; i++)
1562 {
1563 fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);
1564 fileio_write_u32(&file, etm_ctx->trace_data[i].packet);
1565 fileio_write_u32(&file, etm_ctx->trace_data[i].flags);
1566 }
1567
1568 fileio_close(&file);
1569
1570 return ERROR_OK;
1571 }
1572
1573 static int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1574 {
1575 fileio_t file;
1576 target_t *target;
1577 armv4_5_common_t *armv4_5;
1578 arm7_9_common_t *arm7_9;
1579 etm_context_t *etm_ctx;
1580 u32 i;
1581
1582 if (argc != 1)
1583 {
1584 command_print(cmd_ctx, "usage: etm load <file>");
1585 return ERROR_OK;
1586 }
1587
1588 target = get_current_target(cmd_ctx);
1589
1590 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1591 {
1592 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1593 return ERROR_OK;
1594 }
1595
1596 if (!(etm_ctx = arm7_9->etm_ctx))
1597 {
1598 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1599 return ERROR_OK;
1600 }
1601
1602 if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
1603 {
1604 command_print(cmd_ctx, "trace capture running, stop first");
1605 return ERROR_OK;
1606 }
1607
1608 if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
1609 {
1610 return ERROR_OK;
1611 }
1612
1613 if (file.size % 4)
1614 {
1615 command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
1616 fileio_close(&file);
1617 return ERROR_OK;
1618 }
1619
1620 if (etm_ctx->trace_depth > 0)
1621 {
1622 free(etm_ctx->trace_data);
1623 etm_ctx->trace_data = NULL;
1624 }
1625
1626 fileio_read_u32(&file, &etm_ctx->capture_status);
1627 fileio_read_u32(&file, &etm_ctx->portmode);
1628 fileio_read_u32(&file, &etm_ctx->tracemode);
1629 fileio_read_u32(&file, &etm_ctx->trace_depth);
1630
1631 etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
1632 if (etm_ctx->trace_data == NULL)
1633 {
1634 command_print(cmd_ctx, "not enough memory to perform operation");
1635 fileio_close(&file);
1636 return ERROR_OK;
1637 }
1638
1639 for (i = 0; i < etm_ctx->trace_depth; i++)
1640 {
1641 u32 pipestat, packet, flags;
1642 fileio_read_u32(&file, &pipestat);
1643 fileio_read_u32(&file, &packet);
1644 fileio_read_u32(&file, &flags);
1645 etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
1646 etm_ctx->trace_data[i].packet = packet & 0xffff;
1647 etm_ctx->trace_data[i].flags = flags;
1648 }
1649
1650 fileio_close(&file);
1651
1652 return ERROR_OK;
1653 }
1654
1655 static int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1656 {
1657 target_t *target;
1658 armv4_5_common_t *armv4_5;
1659 arm7_9_common_t *arm7_9;
1660 etm_context_t *etm_ctx;
1661
1662 target = get_current_target(cmd_ctx);
1663
1664 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1665 {
1666 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1667 return ERROR_OK;
1668 }
1669
1670 if (!(etm_ctx = arm7_9->etm_ctx))
1671 {
1672 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1673 return ERROR_OK;
1674 }
1675
1676 if (argc > 0)
1677 {
1678 u32 new_value = strtoul(args[0], NULL, 0);
1679
1680 if ((new_value < 2) || (new_value > 100))
1681 {
1682 command_print(cmd_ctx, "valid settings are 2% to 100%");
1683 }
1684 else
1685 {
1686 etm_ctx->trigger_percent = new_value;
1687 }
1688 }
1689
1690 command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);
1691
1692 return ERROR_OK;
1693 }
1694
1695 static int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1696 {
1697 target_t *target;
1698 armv4_5_common_t *armv4_5;
1699 arm7_9_common_t *arm7_9;
1700 etm_context_t *etm_ctx;
1701 reg_t *etm_ctrl_reg;
1702
1703 target = get_current_target(cmd_ctx);
1704
1705 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1706 {
1707 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1708 return ERROR_OK;
1709 }
1710
1711 if (!(etm_ctx = arm7_9->etm_ctx))
1712 {
1713 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1714 return ERROR_OK;
1715 }
1716
1717 /* invalidate old tracing data */
1718 arm7_9->etm_ctx->capture_status = TRACE_IDLE;
1719 if (arm7_9->etm_ctx->trace_depth > 0)
1720 {
1721 free(arm7_9->etm_ctx->trace_data);
1722 arm7_9->etm_ctx->trace_data = NULL;
1723 }
1724 arm7_9->etm_ctx->trace_depth = 0;
1725
1726 etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
1727 etm_get_reg(etm_ctrl_reg);
1728
1729 /* Clear programming bit (10), set port selection bit (11) */
1730 buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);
1731
1732 etm_store_reg(etm_ctrl_reg);
1733 jtag_execute_queue();
1734
1735 etm_ctx->capture_driver->start_capture(etm_ctx);
1736
1737 return ERROR_OK;
1738 }
1739
1740 static int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1741 {
1742 target_t *target;
1743 armv4_5_common_t *armv4_5;
1744 arm7_9_common_t *arm7_9;
1745 etm_context_t *etm_ctx;
1746 reg_t *etm_ctrl_reg;
1747
1748 target = get_current_target(cmd_ctx);
1749
1750 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1751 {
1752 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1753 return ERROR_OK;
1754 }
1755
1756 if (!(etm_ctx = arm7_9->etm_ctx))
1757 {
1758 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1759 return ERROR_OK;
1760 }
1761
1762 etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
1763 etm_get_reg(etm_ctrl_reg);
1764
1765 /* Set programming bit (10), clear port selection bit (11) */
1766 buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);
1767
1768 etm_store_reg(etm_ctrl_reg);
1769 jtag_execute_queue();
1770
1771 etm_ctx->capture_driver->stop_capture(etm_ctx);
1772
1773 return ERROR_OK;
1774 }
1775
1776 static int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1777 {
1778 target_t *target;
1779 armv4_5_common_t *armv4_5;
1780 arm7_9_common_t *arm7_9;
1781 etm_context_t *etm_ctx;
1782 int retval;
1783
1784 target = get_current_target(cmd_ctx);
1785
1786 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
1787 {
1788 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
1789 return ERROR_OK;
1790 }
1791
1792 if (!(etm_ctx = arm7_9->etm_ctx))
1793 {
1794 command_print(cmd_ctx, "current target doesn't have an ETM configured");
1795 return ERROR_OK;
1796 }
1797
1798 if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
1799 {
1800 switch (retval)
1801 {
1802 case ERROR_ETM_ANALYSIS_FAILED:
1803 command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");
1804 break;
1805 case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
1806 command_print(cmd_ctx, "no instruction for current address available, analysis aborted");
1807 break;
1808 case ERROR_TRACE_IMAGE_UNAVAILABLE:
1809 command_print(cmd_ctx, "no image available for trace analysis");
1810 break;
1811 default:
1812 command_print(cmd_ctx, "unknown error: %i", retval);
1813 }
1814 }
1815
1816 return ERROR_OK;
1817 }
1818
1819 int etm_register_commands(struct command_context_s *cmd_ctx)
1820 {
1821 etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");
1822
1823 register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, "etm config <target> <port_width> <port_mode> <clocking> <capture_driver>");
1824
1825 return ERROR_OK;
1826 }
1827
1828 int etm_register_user_commands(struct command_context_s *cmd_ctx)
1829 {
1830 register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
1831 COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");
1832
1833 register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,
1834 COMMAND_EXEC, "display info about the current target's ETM");
1835
1836 register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,
1837 COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");
1838 register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,
1839 COMMAND_EXEC, "display current target's ETM status");
1840 register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,
1841 COMMAND_EXEC, "start ETM trace collection");
1842 register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
1843 COMMAND_EXEC, "stop ETM trace collection");
1844
1845 register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
1846 COMMAND_EXEC, "anaylze collected ETM trace");
1847
1848 register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
1849 COMMAND_EXEC, "load image from <file> [base address]");
1850
1851 register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
1852 COMMAND_EXEC, "dump captured trace data <file>");
1853 register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
1854 COMMAND_EXEC, "load trace data for analysis <file>");
1855
1856 return ERROR_OK;
1857 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)