aarch64: introduce dpm extension for ARMv8
[openocd.git] / src / target / armv8_dpm.c
1 /*
2 * Copyright (C) 2009 by David Brownell
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19
20 #include "arm.h"
21 #include "armv8.h"
22 #include "armv8_dpm.h"
23 #include <jtag/jtag.h>
24 #include "register.h"
25 #include "breakpoints.h"
26 #include "target_type.h"
27 #include "armv8_opcodes.h"
28
29
30 /**
31 * @file
32 * Implements various ARM DPM operations using architectural debug registers.
33 * These routines layer over core-specific communication methods to cope with
34 * implementation differences between cores like ARM1136 and Cortex-A8.
35 *
36 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
37 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
38 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
39 * are abstracted through internal programming interfaces to share code and
40 * to minimize needless differences in debug behavior between cores.
41 */
42
43 /*----------------------------------------------------------------------*/
44
45 /*
46 * Coprocessor support
47 */
48
49 /* Read coprocessor */
50 static int dpmv8_mrc(struct target *target, int cpnum,
51 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
52 uint32_t *value)
53 {
54 struct arm *arm = target_to_arm(target);
55 struct arm_dpm *dpm = arm->dpm;
56 int retval;
57
58 retval = dpm->prepare(dpm);
59 if (retval != ERROR_OK)
60 return retval;
61
62 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
63 (int) op1, (int) CRn,
64 (int) CRm, (int) op2);
65
66 /* read coprocessor register into R0; return via DCC */
67 retval = dpm->instr_read_data_r0(dpm,
68 T32_FMTITR(ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)),
69 value);
70
71 /* (void) */ dpm->finish(dpm);
72 return retval;
73 }
74
75 static int dpmv8_mcr(struct target *target, int cpnum,
76 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
77 uint32_t value)
78 {
79 struct arm *arm = target_to_arm(target);
80 struct arm_dpm *dpm = arm->dpm;
81 int retval;
82
83 retval = dpm->prepare(dpm);
84 if (retval != ERROR_OK)
85 return retval;
86
87 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
88 (int) op1, (int) CRn,
89 (int) CRm, (int) op2);
90
91 /* read DCC into r0; then write coprocessor register from R0 */
92 retval = dpm->instr_write_data_r0(dpm,
93 T32_FMTITR(ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)),
94 value);
95
96 /* (void) */ dpm->finish(dpm);
97 return retval;
98 }
99
100 static int dpmv8_mrs(struct target *target, uint32_t op0,
101 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
102 uint32_t *value)
103 {
104 struct arm *arm = target_to_arm(target);
105 struct arm_dpm *dpm = arm->dpm;
106 int retval;
107 uint32_t op_code;
108
109 retval = dpm->prepare(dpm);
110 if (retval != ERROR_OK)
111 return retval;
112 op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\
113 (CRm & 0xF) << 8 | (op2 & 0x7) << 5);
114 op_code >>= 5;
115 LOG_DEBUG("MRS p%d, %d, r0, c%d, c%d, %d", (int)op0,
116 (int) op1, (int) CRn,
117 (int) CRm, (int) op2);
118 /* read coprocessor register into R0; return via DCC */
119 retval = dpm->instr_read_data_r0(dpm,
120 ARMV8_MRS(op_code, 0),
121 value);
122
123 /* (void) */ dpm->finish(dpm);
124 return retval;
125 }
126
127 static int dpmv8_msr(struct target *target, uint32_t op0,
128 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
129 uint32_t value)
130 {
131 struct arm *arm = target_to_arm(target);
132 struct arm_dpm *dpm = arm->dpm;
133 int retval;
134 uint32_t op_code;
135
136 retval = dpm->prepare(dpm);
137 if (retval != ERROR_OK)
138 return retval;
139
140 op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\
141 (CRm & 0xF) << 8 | (op2 & 0x7) << 5);
142 op_code >>= 5;
143 LOG_DEBUG("MSR p%d, %d, r0, c%d, c%d, %d", (int)op0,
144 (int) op1, (int) CRn,
145 (int) CRm, (int) op2);
146
147 /* read DCC into r0; then write coprocessor register from R0 */
148 retval = dpm->instr_write_data_r0(dpm,
149 ARMV8_MSR_GP(op_code, 0),
150 value);
151
152 /* (void) */ dpm->finish(dpm);
153 return retval;
154 }
155
156 /*----------------------------------------------------------------------*/
157
158 /*
159 * Register access utilities
160 */
161
162 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
163 * Routines *must* restore the original mode before returning!!
164 */
165 int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
166 {
167 int retval;
168 uint32_t cpsr;
169
170 /* restore previous mode */
171 if (mode == ARM_MODE_ANY)
172 cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32);
173
174 /* else force to the specified mode */
175 else
176 cpsr = mode >> 4;
177
178 switch ((cpsr & 0xC) >> 2) {
179 case SYSTEM_CUREL_EL1:
180 retval = dpm->instr_execute(dpm, ARMV8_DCPS1(11));
181 if (retval != ERROR_OK)
182 return retval;
183 break;
184 case SYSTEM_CUREL_EL2:
185 retval = dpm->instr_execute(dpm, ARMV8_DCPS2(11));
186 if (retval != ERROR_OK)
187 return retval;
188 break;
189 break;
190 case SYSTEM_CUREL_EL3:
191 retval = dpm->instr_execute(dpm, ARMV8_DCPS3(11));
192 if (retval != ERROR_OK)
193 return retval;
194 break;
195 break;
196 default:
197 LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr & 0xC) >> 2));
198 break;
199 }
200
201
202 retval = dpm->instr_write_data_r0(dpm, ARMV8_MSR_DSPSR(0), cpsr);
203 if (retval != ERROR_OK)
204 return retval;
205
206 if (dpm->instr_cpsr_sync)
207 retval = dpm->instr_cpsr_sync(dpm);
208
209 return retval;
210 }
211
212 /* just read the register -- rely on the core mode being right */
213 static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
214 {
215 uint32_t value;
216 uint64_t value_64;
217 int retval = ERROR_FAIL;
218
219 switch (regnum) {
220 case 0 ... 30:
221 retval = dpm->instr_read_data_dcc_64(dpm,
222 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum),
223 &value_64);
224 break;
225 case 31:
226 retval = dpm->instr_read_data_r0_64(dpm,
227 ARMV8_MOVFSP_64(0),
228 &value_64);
229 break;
230 case 32:
231 retval = dpm->instr_read_data_r0_64(dpm,
232 ARMV8_MRS_DLR(0),
233 &value_64);
234 break;
235 case 33:
236 retval = dpm->instr_read_data_r0(dpm,
237 ARMV8_MRS_DSPSR(0),
238 &value);
239 default:
240 LOG_DEBUG("READ: %s fail", r->name);
241 break;
242 }
243
244 if (retval == ERROR_OK) {
245 r->valid = true;
246 r->dirty = false;
247 buf_set_u64(r->value, 0, 32, value_64);
248 if (r->size == 64)
249 LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
250 else
251 LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
252 }
253 return retval;
254 }
255
256 /* just write the register -- rely on the core mode being right */
257 static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
258 {
259 int retval = ERROR_FAIL;
260 uint32_t value = 0xFFFFFFFF;
261 uint64_t value_64 = 0xFFFFFFFFFFFFFFFF;
262
263 switch (regnum) {
264 case 0 ... 30:
265 value_64 = buf_get_u64(r->value, 0, 64);
266 retval = dpm->instr_write_data_dcc_64(dpm,
267 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum),
268 value_64);
269 break;
270 case 31:
271 value_64 = buf_get_u64(r->value, 0, 64);
272 retval = dpm->instr_write_data_r0_64(dpm,
273 ARMV8_MOVTSP_64(0),
274 value_64);
275 break;
276 case 32:
277 value_64 = buf_get_u64(r->value, 0, 64);
278 retval = dpm->instr_write_data_r0_64(dpm,
279 ARMV8_MSR_DLR(0),
280 value_64);
281 break;
282 case 33:
283 value = buf_get_u32(r->value, 0, 32);
284 retval = dpm->instr_write_data_r0(dpm,
285 ARMV8_MSR_DSPSR(0),
286 value);
287 default:
288 LOG_DEBUG("write: %s fail", r->name);
289 break;
290 }
291
292
293 if (retval == ERROR_OK) {
294 r->dirty = false;
295 if (r->size == 64)
296 LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long) value_64);
297 else
298 LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value);
299 }
300
301 return retval;
302 }
303
304 /**
305 * Read basic registers of the the current context: R0 to R15, and CPSR;
306 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
307 * In normal operation this is called on entry to halting debug state,
308 * possibly after some other operations supporting restore of debug state
309 * or making sure the CPU is fully idle (drain write buffer, etc).
310 */
311 int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
312 {
313 struct arm *arm = dpm->arm;
314 uint32_t cpsr;
315 int retval;
316 struct reg *r;
317
318 retval = dpm->prepare(dpm);
319 if (retval != ERROR_OK)
320 return retval;
321
322 /* read R0 first (it's used for scratch), then CPSR */
323 r = arm->core_cache->reg_list + 0;
324 if (!r->valid) {
325 retval = dpmv8_read_reg(dpm, r, 0);
326 if (retval != ERROR_OK)
327 goto fail;
328 }
329 r->dirty = true;
330 /* read cpsr to r0 and get it back */
331 retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), &cpsr);
332 if (retval != ERROR_OK)
333 goto fail;
334
335 /* update core mode and state, plus shadow mapping for R8..R14 */
336 armv8_set_cpsr(arm, cpsr);
337
338 /* REVISIT we can probably avoid reading R1..R14, saving time... */
339 for (unsigned i = 1; i < arm->core_cache->num_regs ; i++) {
340 r = armv8_reg_current(arm, i);
341 if (r->valid)
342 continue;
343
344 retval = dpmv8_read_reg(dpm, r, i);
345 if (retval != ERROR_OK)
346 goto fail;
347 }
348
349 /* NOTE: SPSR ignored (if it's even relevant). */
350
351 /* REVISIT the debugger can trigger various exceptions. See the
352 * ARMv7A architecture spec, section C5.7, for more info about
353 * what defenses are needed; v6 debug has the most issues.
354 */
355
356 fail:
357 /* (void) */ dpm->finish(dpm);
358 return retval;
359 }
360
361 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
362 * unless they're removed, or need updating because of single-stepping
363 * or running debugger code.
364 */
365 static int dpmv8_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
366 struct dpm_bpwp *xp, int *set_p)
367 {
368 int retval = ERROR_OK;
369 bool disable;
370
371 if (!set_p) {
372 if (!xp->dirty)
373 goto done;
374 xp->dirty = false;
375 /* removed or startup; we must disable it */
376 disable = true;
377 } else if (bpwp) {
378 if (!xp->dirty)
379 goto done;
380 /* disabled, but we must set it */
381 xp->dirty = disable = false;
382 *set_p = true;
383 } else {
384 if (!*set_p)
385 goto done;
386 /* set, but we must temporarily disable it */
387 xp->dirty = disable = true;
388 *set_p = false;
389 }
390
391 if (disable)
392 retval = dpm->bpwp_disable(dpm, xp->number);
393 else
394 retval = dpm->bpwp_enable(dpm, xp->number,
395 xp->address, xp->control);
396
397 if (retval != ERROR_OK)
398 LOG_ERROR("%s: can't %s HW %spoint %d",
399 disable ? "disable" : "enable",
400 target_name(dpm->arm->target),
401 (xp->number < 16) ? "break" : "watch",
402 xp->number & 0xf);
403 done:
404 return retval;
405 }
406
407 static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp);
408
409 /**
410 * Writes all modified core registers for all processor modes. In normal
411 * operation this is called on exit from halting debug state.
412 *
413 * @param dpm: represents the processor
414 * @param bpwp: true ensures breakpoints and watchpoints are set,
415 * false ensures they are cleared
416 */
417 int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
418 {
419 struct arm *arm = dpm->arm;
420 struct reg_cache *cache = arm->core_cache;
421 int retval;
422
423 retval = dpm->prepare(dpm);
424 if (retval != ERROR_OK)
425 goto done;
426
427 /* If we're managing hardware breakpoints for this core, enable
428 * or disable them as requested.
429 *
430 * REVISIT We don't yet manage them for ANY cores. Eventually
431 * we should be able to assume we handle them; but until then,
432 * cope with the hand-crafted breakpoint code.
433 */
434 if (arm->target->type->add_breakpoint == dpmv8_add_breakpoint) {
435 for (unsigned i = 0; i < dpm->nbp; i++) {
436 struct dpm_bp *dbp = dpm->dbp + i;
437 struct breakpoint *bp = dbp->bp;
438
439 retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
440 bp ? &bp->set : NULL);
441 if (retval != ERROR_OK)
442 goto done;
443 }
444 }
445
446 /* enable/disable watchpoints */
447 for (unsigned i = 0; i < dpm->nwp; i++) {
448 struct dpm_wp *dwp = dpm->dwp + i;
449 struct watchpoint *wp = dwp->wp;
450
451 retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
452 wp ? &wp->set : NULL);
453 if (retval != ERROR_OK)
454 goto done;
455 }
456
457 /* NOTE: writes to breakpoint and watchpoint registers might
458 * be queued, and need (efficient/batched) flushing later.
459 */
460
461 /* Scan the registers until we find one that's both dirty and
462 * eligible for flushing. Flush that and everything else that
463 * shares the same core mode setting. Typically this won't
464 * actually find anything to do...
465 */
466
467 /* check everything except our scratch register R0 */
468 for (unsigned i = 1; i < cache->num_regs; i++) {
469 struct arm_reg *r;
470 unsigned regnum;
471
472 /* also skip PC, CPSR, and non-dirty */
473 if (i == (arm->core_cache->num_regs - 2))
474 continue;
475 if (arm->cpsr == cache->reg_list + i)
476 continue;
477 if (!cache->reg_list[i].dirty)
478 continue;
479
480 r = cache->reg_list[i].arch_info;
481 regnum = r->num;
482
483 retval = dpmv8_write_reg(dpm,
484 &cache->reg_list[i],
485 regnum);
486 if (retval != ERROR_OK)
487 goto done;
488 }
489
490
491 /* Restore original CPSR ... assuming either that we changed it,
492 * or it's dirty. Must write PC to ensure the return address is
493 * defined, and must not write it before CPSR.
494 */
495 retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY);
496 if (retval != ERROR_OK)
497 goto done;
498 arm->cpsr->dirty = false;
499
500 retval = dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2));
501 if (retval != ERROR_OK)
502 goto done;
503 arm->pc->dirty = false;
504
505 /* flush R0 -- it's *very* dirty by now */
506 retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0);
507 if (retval != ERROR_OK)
508 goto done;
509 cache->reg_list[0].dirty = false;
510
511 /* (void) */ dpm->finish(dpm);
512 done:
513 return retval;
514 }
515
516 /*
517 * Standard ARM register accessors ... there are three methods
518 * in "struct arm", to support individual read/write and bulk read
519 * of registers.
520 */
521
522 static int armv8_dpm_read_core_reg(struct target *target, struct reg *r,
523 int regnum, enum arm_mode mode)
524 {
525 struct arm *arm = target_to_arm(target);
526 struct arm_dpm *dpm = target_to_arm(target)->dpm;
527 int retval;
528 int max = arm->core_cache->num_regs;
529
530 if (regnum < 0 || regnum > max)
531 return ERROR_COMMAND_SYNTAX_ERROR;
532
533 /* REVISIT what happens if we try to read SPSR in a core mode
534 * which has no such register?
535 */
536
537 retval = dpm->prepare(dpm);
538 if (retval != ERROR_OK)
539 return retval;
540
541 retval = dpmv8_read_reg(dpm, r, regnum);
542 if (retval != ERROR_OK)
543 goto fail;
544
545 fail:
546 /* (void) */ dpm->finish(dpm);
547 return retval;
548 }
549
550 static int armv8_dpm_write_core_reg(struct target *target, struct reg *r,
551 int regnum, enum arm_mode mode, uint8_t *value)
552 {
553 struct arm *arm = target_to_arm(target);
554 struct arm_dpm *dpm = target_to_arm(target)->dpm;
555 int retval;
556 int max = arm->core_cache->num_regs;
557
558 if (regnum < 0 || regnum > max)
559 return ERROR_COMMAND_SYNTAX_ERROR;
560
561 /* REVISIT what happens if we try to write SPSR in a core mode
562 * which has no such register?
563 */
564
565 retval = dpm->prepare(dpm);
566 if (retval != ERROR_OK)
567 return retval;
568
569 retval = dpmv8_write_reg(dpm, r, regnum);
570 /* always clean up, regardless of error */
571
572 /* (void) */ dpm->finish(dpm);
573 return retval;
574 }
575
576 static int armv8_dpm_full_context(struct target *target)
577 {
578 struct arm *arm = target_to_arm(target);
579 struct arm_dpm *dpm = arm->dpm;
580 struct reg_cache *cache = arm->core_cache;
581 int retval;
582 bool did_read;
583
584 retval = dpm->prepare(dpm);
585 if (retval != ERROR_OK)
586 goto done;
587
588 do {
589 enum arm_mode mode = ARM_MODE_ANY;
590
591 did_read = false;
592
593 /* We "know" arm_dpm_read_current_registers() was called so
594 * the unmapped registers (R0..R7, PC, AND CPSR) and some
595 * view of R8..R14 are current. We also "know" oddities of
596 * register mapping: special cases for R8..R12 and SPSR.
597 *
598 * Pick some mode with unread registers and read them all.
599 * Repeat until done.
600 */
601 for (unsigned i = 0; i < cache->num_regs; i++) {
602 struct arm_reg *r;
603
604 if (cache->reg_list[i].valid)
605 continue;
606 r = cache->reg_list[i].arch_info;
607
608 /* may need to pick a mode and set CPSR */
609 if (!did_read) {
610 did_read = true;
611 mode = r->mode;
612
613 /* For regular (ARM_MODE_ANY) R8..R12
614 * in case we've entered debug state
615 * in FIQ mode we need to patch mode.
616 */
617 if (mode != ARM_MODE_ANY)
618 retval = dpmv8_modeswitch(dpm, mode);
619 else
620 retval = dpmv8_modeswitch(dpm, ARM_MODE_USR);
621
622 if (retval != ERROR_OK)
623 goto done;
624 }
625 if (r->mode != mode)
626 continue;
627
628 /* CPSR was read, so "R16" must mean SPSR */
629 retval = dpmv8_read_reg(dpm,
630 &cache->reg_list[i],
631 (r->num == 16) ? 17 : r->num);
632 if (retval != ERROR_OK)
633 goto done;
634 }
635
636 } while (did_read);
637
638 retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY);
639 /* (void) */ dpm->finish(dpm);
640 done:
641 return retval;
642 }
643
644
645 /*----------------------------------------------------------------------*/
646
647 /*
648 * Breakpoint and Watchpoint support.
649 *
650 * Hardware {break,watch}points are usually left active, to minimize
651 * debug entry/exit costs. When they are set or cleared, it's done in
652 * batches. Also, DPM-conformant hardware can update debug registers
653 * regardless of whether the CPU is running or halted ... though that
654 * fact isn't currently leveraged.
655 */
656
657 static int dpmv8_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
658 uint32_t addr, uint32_t length)
659 {
660 uint32_t control;
661
662 control = (1 << 0) /* enable */
663 | (3 << 1); /* both user and privileged access */
664
665 /* Match 1, 2, or all 4 byte addresses in this word.
666 *
667 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
668 * Support larger length, when addr is suitably aligned. In
669 * particular, allow watchpoints on 8 byte "double" values.
670 *
671 * REVISIT allow watchpoints on unaligned 2-bit values; and on
672 * v7 hardware, unaligned 4-byte ones too.
673 */
674 switch (length) {
675 case 1:
676 control |= (1 << (addr & 3)) << 5;
677 break;
678 case 2:
679 /* require 2-byte alignment */
680 if (!(addr & 1)) {
681 control |= (3 << (addr & 2)) << 5;
682 break;
683 }
684 /* FALL THROUGH */
685 case 4:
686 /* require 4-byte alignment */
687 if (!(addr & 3)) {
688 control |= 0xf << 5;
689 break;
690 }
691 /* FALL THROUGH */
692 default:
693 LOG_ERROR("unsupported {break,watch}point length/alignment");
694 return ERROR_COMMAND_SYNTAX_ERROR;
695 }
696
697 /* other shared control bits:
698 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
699 * bit 20 == 0 ... not linked to a context ID
700 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
701 */
702
703 xp->address = addr & ~3;
704 xp->control = control;
705 xp->dirty = true;
706
707 LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
708 xp->address, control, xp->number);
709
710 /* hardware is updated in write_dirty_registers() */
711 return ERROR_OK;
712 }
713
714 static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp)
715 {
716 struct arm *arm = target_to_arm(target);
717 struct arm_dpm *dpm = arm->dpm;
718 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
719
720 if (bp->length < 2)
721 return ERROR_COMMAND_SYNTAX_ERROR;
722 if (!dpm->bpwp_enable)
723 return retval;
724
725 /* FIXME we need a generic solution for software breakpoints. */
726 if (bp->type == BKPT_SOFT)
727 LOG_DEBUG("using HW bkpt, not SW...");
728
729 for (unsigned i = 0; i < dpm->nbp; i++) {
730 if (!dpm->dbp[i].bp) {
731 retval = dpmv8_bpwp_setup(dpm, &dpm->dbp[i].bpwp,
732 bp->address, bp->length);
733 if (retval == ERROR_OK)
734 dpm->dbp[i].bp = bp;
735 break;
736 }
737 }
738
739 return retval;
740 }
741
742 static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp)
743 {
744 struct arm *arm = target_to_arm(target);
745 struct arm_dpm *dpm = arm->dpm;
746 int retval = ERROR_COMMAND_SYNTAX_ERROR;
747
748 for (unsigned i = 0; i < dpm->nbp; i++) {
749 if (dpm->dbp[i].bp == bp) {
750 dpm->dbp[i].bp = NULL;
751 dpm->dbp[i].bpwp.dirty = true;
752
753 /* hardware is updated in write_dirty_registers() */
754 retval = ERROR_OK;
755 break;
756 }
757 }
758
759 return retval;
760 }
761
762 static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
763 struct watchpoint *wp)
764 {
765 int retval;
766 struct dpm_wp *dwp = dpm->dwp + index_t;
767 uint32_t control;
768
769 /* this hardware doesn't support data value matching or masking */
770 if (wp->value || wp->mask != ~(uint32_t)0) {
771 LOG_DEBUG("watchpoint values and masking not supported");
772 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
773 }
774
775 retval = dpmv8_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length);
776 if (retval != ERROR_OK)
777 return retval;
778
779 control = dwp->bpwp.control;
780 switch (wp->rw) {
781 case WPT_READ:
782 control |= 1 << 3;
783 break;
784 case WPT_WRITE:
785 control |= 2 << 3;
786 break;
787 case WPT_ACCESS:
788 control |= 3 << 3;
789 break;
790 }
791 dwp->bpwp.control = control;
792
793 dpm->dwp[index_t].wp = wp;
794
795 return retval;
796 }
797
798 static int dpmv8_add_watchpoint(struct target *target, struct watchpoint *wp)
799 {
800 struct arm *arm = target_to_arm(target);
801 struct arm_dpm *dpm = arm->dpm;
802 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
803
804 if (dpm->bpwp_enable) {
805 for (unsigned i = 0; i < dpm->nwp; i++) {
806 if (!dpm->dwp[i].wp) {
807 retval = dpmv8_watchpoint_setup(dpm, i, wp);
808 break;
809 }
810 }
811 }
812
813 return retval;
814 }
815
816 static int dpmv8_remove_watchpoint(struct target *target, struct watchpoint *wp)
817 {
818 struct arm *arm = target_to_arm(target);
819 struct arm_dpm *dpm = arm->dpm;
820 int retval = ERROR_COMMAND_SYNTAX_ERROR;
821
822 for (unsigned i = 0; i < dpm->nwp; i++) {
823 if (dpm->dwp[i].wp == wp) {
824 dpm->dwp[i].wp = NULL;
825 dpm->dwp[i].bpwp.dirty = true;
826
827 /* hardware is updated in write_dirty_registers() */
828 retval = ERROR_OK;
829 break;
830 }
831 }
832
833 return retval;
834 }
835
836 void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr)
837 {
838 switch (dpm->arm->core_state) {
839 case ARM_STATE_ARM:
840 case ARM_STATE_AARCH64:
841 addr -= 8;
842 break;
843 case ARM_STATE_THUMB:
844 case ARM_STATE_THUMB_EE:
845 addr -= 4;
846 break;
847 case ARM_STATE_JAZELLE:
848 /* ?? */
849 break;
850 default:
851 LOG_DEBUG("Unknow core_state");
852 break;
853 }
854 dpm->wp_pc = addr;
855 }
856
857 /*----------------------------------------------------------------------*/
858
859 /*
860 * Other debug and support utilities
861 */
862
863 void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
864 {
865 struct target *target = dpm->arm->target;
866
867 dpm->dscr = dscr;
868
869 /* Examine debug reason */
870 switch (DSCR_ENTRY(dscr)) {
871 /* FALL THROUGH -- assume a v6 core in abort mode */
872 case DSCRV8_ENTRY_HLT: /* HALT request from debugger */
873 case DSCRV8_ENTRY_EXT_DEBUG: /* EDBGRQ */
874 target->debug_reason = DBG_REASON_DBGRQ;
875 break;
876 case DSCRV8_ENTRY_HALT_STEP_EXECLU: /* HALT step */
877 case DSCRV8_ENTRY_BKPT: /* SW BKPT */
878 case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */
879 case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/
880 case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/
881 case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/
882 case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/
883 target->debug_reason = DBG_REASON_BREAKPOINT;
884 break;
885 case DSCRV8_ENTRY_WATCHPOINT: /* asynch watchpoint */
886 target->debug_reason = DBG_REASON_WATCHPOINT;
887 break;
888 default:
889 target->debug_reason = DBG_REASON_UNDEFINED;
890 break;
891 }
892
893 }
894
895 /*----------------------------------------------------------------------*/
896
897 /*
898 * Setup and management support.
899 */
900
901 /**
902 * Hooks up this DPM to its associated target; call only once.
903 * Initially this only covers the register cache.
904 *
905 * Oh, and watchpoints. Yeah.
906 */
907 int armv8_dpm_setup(struct arm_dpm *dpm)
908 {
909 struct arm *arm = dpm->arm;
910 struct target *target = arm->target;
911 struct reg_cache *cache;
912 arm->dpm = dpm;
913
914 /* register access setup */
915 arm->full_context = armv8_dpm_full_context;
916 arm->read_core_reg = armv8_dpm_read_core_reg;
917 arm->write_core_reg = armv8_dpm_write_core_reg;
918
919 cache = armv8_build_reg_cache(target);
920 if (!cache)
921 return ERROR_FAIL;
922
923 /* coprocessor access setup */
924 arm->mrc = dpmv8_mrc;
925 arm->mcr = dpmv8_mcr;
926 arm->mrs = dpmv8_mrs;
927 arm->msr = dpmv8_msr;
928 /* breakpoint setup -- optional until it works everywhere */
929 if (!target->type->add_breakpoint) {
930 target->type->add_breakpoint = dpmv8_add_breakpoint;
931 target->type->remove_breakpoint = dpmv8_remove_breakpoint;
932 }
933
934 /* watchpoint setup */
935 target->type->add_watchpoint = dpmv8_add_watchpoint;
936 target->type->remove_watchpoint = dpmv8_remove_watchpoint;
937
938 /* FIXME add vector catch support */
939
940 dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf);
941 dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
942
943 dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf);
944 dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
945
946 if (!dpm->dbp || !dpm->dwp) {
947 free(dpm->dbp);
948 free(dpm->dwp);
949 return ERROR_FAIL;
950 }
951
952 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
953 target_name(target), dpm->nbp, dpm->nwp);
954
955 /* REVISIT ... and some of those breakpoints could match
956 * execution context IDs...
957 */
958
959 return ERROR_OK;
960 }
961
962 /**
963 * Reinitializes DPM state at the beginning of a new debug session
964 * or after a reset which may have affected the debug module.
965 */
966 int armv8_dpm_initialize(struct arm_dpm *dpm)
967 {
968 /* Disable all breakpoints and watchpoints at startup. */
969 if (dpm->bpwp_disable) {
970 unsigned i;
971
972 for (i = 0; i < dpm->nbp; i++) {
973 dpm->dbp[i].bpwp.number = i;
974 (void) dpm->bpwp_disable(dpm, i);
975 }
976 for (i = 0; i < dpm->nwp; i++) {
977 dpm->dwp[i].bpwp.number = 16 + i;
978 (void) dpm->bpwp_disable(dpm, 16 + i);
979 }
980 } else
981 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
982 target_name(dpm->arm->target));
983
984 return ERROR_OK;
985 }

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)