f5dd22d8b31677a57f8c8bb414e501c65e918443
[openocd.git] / src / target / arm_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 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "arm.h"
23 #include "arm_dpm.h"
24 #include "armv8_dpm.h"
25 #include <jtag/jtag.h>
26 #include "register.h"
27 #include "breakpoints.h"
28 #include "target_type.h"
29 #include "arm_opcodes.h"
30
31
32 /**
33 * @file
34 * Implements various ARM DPM operations using architectural debug registers.
35 * These routines layer over core-specific communication methods to cope with
36 * implementation differences between cores like ARM1136 and Cortex-A8.
37 *
38 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
39 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
40 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
41 * are abstracted through internal programming interfaces to share code and
42 * to minimize needless differences in debug behavior between cores.
43 */
44
45 /*----------------------------------------------------------------------*/
46
47 /*
48 * Coprocessor support
49 */
50
51 /* Read coprocessor */
52 static int dpm_mrc(struct target *target, int cpnum,
53 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
54 uint32_t *value)
55 {
56 struct arm *arm = target_to_arm(target);
57 struct arm_dpm *dpm = arm->dpm;
58 int retval;
59
60 retval = dpm->prepare(dpm);
61 if (retval != ERROR_OK)
62 return retval;
63
64 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
65 (int) op1, (int) CRn,
66 (int) CRm, (int) op2);
67
68 /* read coprocessor register into R0; return via DCC */
69 retval = dpm->instr_read_data_r0(dpm,
70 ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
71 value);
72
73 /* (void) */ dpm->finish(dpm);
74 return retval;
75 }
76
77 static int dpm_mcr(struct target *target, int cpnum,
78 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
79 uint32_t value)
80 {
81 struct arm *arm = target_to_arm(target);
82 struct arm_dpm *dpm = arm->dpm;
83 int retval;
84
85 retval = dpm->prepare(dpm);
86 if (retval != ERROR_OK)
87 return retval;
88
89 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
90 (int) op1, (int) CRn,
91 (int) CRm, (int) op2);
92
93 /* read DCC into r0; then write coprocessor register from R0 */
94 retval = dpm->instr_write_data_r0(dpm,
95 ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
96 value);
97
98 /* (void) */ dpm->finish(dpm);
99 return retval;
100 }
101
102 /*----------------------------------------------------------------------*/
103
104 /*
105 * Register access utilities
106 */
107
108 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
109 * Routines *must* restore the original mode before returning!!
110 */
111 int arm_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
112 {
113 int retval;
114 uint32_t cpsr;
115
116 /* restore previous mode */
117 if (mode == ARM_MODE_ANY)
118 cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32);
119
120 /* else force to the specified mode */
121 else
122 cpsr = mode;
123
124 retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr);
125 if (retval != ERROR_OK)
126 return retval;
127
128 if (dpm->instr_cpsr_sync)
129 retval = dpm->instr_cpsr_sync(dpm);
130
131 return retval;
132 }
133
134 /* Read 64bit VFP registers */
135 static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
136 {
137 int retval = ERROR_FAIL;
138 uint32_t value_r0, value_r1;
139
140 switch (regnum) {
141 case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
142 /* move from double word register to r0:r1: "vmov r0, r1, vm"
143 * then read r0 via dcc
144 */
145 retval = dpm->instr_read_data_r0(dpm,
146 ARMV4_5_VMOV(1, 1, 0, ((regnum - ARM_VFP_V3_D0) >> 4),
147 ((regnum - ARM_VFP_V3_D0) & 0xf)), &value_r0);
148 if (retval != ERROR_OK)
149 break;
150
151 /* read r1 via dcc */
152 retval = dpm->instr_read_data_dcc(dpm,
153 ARMV4_5_MCR(14, 0, 1, 0, 5, 0),
154 &value_r1);
155 break;
156 default:
157
158 break;
159 }
160
161 if (retval == ERROR_OK) {
162 buf_set_u32(r->value, 0, 32, value_r0);
163 buf_set_u32(r->value + 4, 0, 32, value_r1);
164 r->valid = true;
165 r->dirty = false;
166 LOG_DEBUG("READ: %s, %8.8x, %8.8x", r->name,
167 (unsigned) value_r0, (unsigned) value_r1);
168 }
169
170 return retval;
171 }
172
173 /* just read the register -- rely on the core mode being right */
174 int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
175 {
176 uint32_t value;
177 int retval;
178
179 switch (regnum) {
180 case 0 ... 14:
181 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
182 retval = dpm->instr_read_data_dcc(dpm,
183 ARMV4_5_MCR(14, 0, regnum, 0, 5, 0),
184 &value);
185 break;
186 case 15:/* PC
187 * "MOV r0, pc"; then return via DCC */
188 retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value);
189
190 /* NOTE: this seems like a slightly awkward place to update
191 * this value ... but if the PC gets written (the only way
192 * to change what we compute), the arch spec says subsequent
193 * reads return values which are "unpredictable". So this
194 * is always right except in those broken-by-intent cases.
195 */
196 switch (dpm->arm->core_state) {
197 case ARM_STATE_ARM:
198 value -= 8;
199 break;
200 case ARM_STATE_THUMB:
201 case ARM_STATE_THUMB_EE:
202 value -= 4;
203 break;
204 case ARM_STATE_JAZELLE:
205 /* core-specific ... ? */
206 LOG_WARNING("Jazelle PC adjustment unknown");
207 break;
208 default:
209 LOG_WARNING("unknow core state");
210 break;
211 }
212 break;
213 case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
214 return dpm_read_reg_u64(dpm, r, regnum);
215 break;
216 case ARM_VFP_V3_FPSCR:
217 /* "VMRS r0, FPSCR"; then return via DCC */
218 retval = dpm->instr_read_data_r0(dpm,
219 ARMV4_5_VMRS(0), &value);
220 break;
221 default:
222 /* 16: "MRS r0, CPSR"; then return via DCC
223 * 17: "MRS r0, SPSR"; then return via DCC
224 */
225 retval = dpm->instr_read_data_r0(dpm,
226 ARMV4_5_MRS(0, regnum & 1),
227 &value);
228 break;
229 }
230
231 if (retval == ERROR_OK) {
232 buf_set_u32(r->value, 0, 32, value);
233 r->valid = true;
234 r->dirty = false;
235 LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
236 }
237
238 return retval;
239 }
240
241 /* Write 64bit VFP registers */
242 static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
243 {
244 int retval = ERROR_FAIL;
245 uint32_t value_r0 = buf_get_u32(r->value, 0, 32);
246 uint32_t value_r1 = buf_get_u32(r->value + 4, 0, 32);
247
248 switch (regnum) {
249 case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
250 /* write value_r1 to r1 via dcc */
251 retval = dpm->instr_write_data_dcc(dpm,
252 ARMV4_5_MRC(14, 0, 1, 0, 5, 0),
253 value_r1);
254 if (retval != ERROR_OK)
255 break;
256
257 /* write value_r0 to r0 via dcc then,
258 * move to double word register from r0:r1: "vmov vm, r0, r1"
259 */
260 retval = dpm->instr_write_data_r0(dpm,
261 ARMV4_5_VMOV(0, 1, 0, ((regnum - ARM_VFP_V3_D0) >> 4),
262 ((regnum - ARM_VFP_V3_D0) & 0xf)), value_r0);
263 break;
264 default:
265
266 break;
267 }
268
269 if (retval == ERROR_OK) {
270 r->dirty = false;
271 LOG_DEBUG("WRITE: %s, %8.8x, %8.8x", r->name,
272 (unsigned) value_r0, (unsigned) value_r1);
273 }
274
275 return retval;
276 }
277
278 /* just write the register -- rely on the core mode being right */
279 static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
280 {
281 int retval;
282 uint32_t value = buf_get_u32(r->value, 0, 32);
283
284 switch (regnum) {
285 case 0 ... 14:
286 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
287 retval = dpm->instr_write_data_dcc(dpm,
288 ARMV4_5_MRC(14, 0, regnum, 0, 5, 0),
289 value);
290 break;
291 case 15:/* PC
292 * read r0 from DCC; then "MOV pc, r0" */
293 retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
294 break;
295 case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
296 return dpm_write_reg_u64(dpm, r, regnum);
297 break;
298 case ARM_VFP_V3_FPSCR:
299 /* move to r0 from DCC, then "VMSR FPSCR, r0" */
300 retval = dpm->instr_write_data_r0(dpm,
301 ARMV4_5_VMSR(0), value);
302 break;
303 default:
304 /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
305 * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
306 */
307 retval = dpm->instr_write_data_r0(dpm,
308 ARMV4_5_MSR_GP(0, 0xf, regnum & 1),
309 value);
310 if (retval != ERROR_OK)
311 return retval;
312
313 if (regnum == 16 && dpm->instr_cpsr_sync)
314 retval = dpm->instr_cpsr_sync(dpm);
315
316 break;
317 }
318
319 if (retval == ERROR_OK) {
320 r->dirty = false;
321 LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value);
322 }
323
324 return retval;
325 }
326
327 /**
328 * Write to program counter and switch the core state (arm/thumb) according to
329 * the address.
330 */
331 static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r)
332 {
333 uint32_t value = buf_get_u32(r->value, 0, 32);
334
335 /* read r0 from DCC; then "BX r0" */
336 return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value);
337 }
338
339 /**
340 * Read basic registers of the the current context: R0 to R15, and CPSR;
341 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
342 * In normal operation this is called on entry to halting debug state,
343 * possibly after some other operations supporting restore of debug state
344 * or making sure the CPU is fully idle (drain write buffer, etc).
345 */
346 int arm_dpm_read_current_registers(struct arm_dpm *dpm)
347 {
348 struct arm *arm = dpm->arm;
349 uint32_t cpsr;
350 int retval;
351 struct reg *r;
352
353 retval = dpm->prepare(dpm);
354 if (retval != ERROR_OK)
355 return retval;
356
357 /* read R0 and R1 first (it's used for scratch), then CPSR */
358 for (unsigned i = 0; i < 2; i++) {
359 r = arm->core_cache->reg_list + i;
360 if (!r->valid) {
361 retval = arm_dpm_read_reg(dpm, r, i);
362 if (retval != ERROR_OK)
363 goto fail;
364 }
365 r->dirty = true;
366 }
367
368 retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr);
369 if (retval != ERROR_OK)
370 goto fail;
371
372 /* update core mode and state, plus shadow mapping for R8..R14 */
373 arm_set_cpsr(arm, cpsr);
374
375 /* REVISIT we can probably avoid reading R1..R14, saving time... */
376 for (unsigned i = 2; i < 16; i++) {
377 r = arm_reg_current(arm, i);
378 if (r->valid)
379 continue;
380
381 retval = arm_dpm_read_reg(dpm, r, i);
382 if (retval != ERROR_OK)
383 goto fail;
384 }
385
386 /* NOTE: SPSR ignored (if it's even relevant). */
387
388 /* REVISIT the debugger can trigger various exceptions. See the
389 * ARMv7A architecture spec, section C5.7, for more info about
390 * what defenses are needed; v6 debug has the most issues.
391 */
392
393 fail:
394 /* (void) */ dpm->finish(dpm);
395 return retval;
396 }
397
398 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
399 * unless they're removed, or need updating because of single-stepping
400 * or running debugger code.
401 */
402 static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
403 struct dpm_bpwp *xp, int *set_p)
404 {
405 int retval = ERROR_OK;
406 bool disable;
407
408 if (!set_p) {
409 if (!xp->dirty)
410 goto done;
411 xp->dirty = false;
412 /* removed or startup; we must disable it */
413 disable = true;
414 } else if (bpwp) {
415 if (!xp->dirty)
416 goto done;
417 /* disabled, but we must set it */
418 xp->dirty = disable = false;
419 *set_p = true;
420 } else {
421 if (!*set_p)
422 goto done;
423 /* set, but we must temporarily disable it */
424 xp->dirty = disable = true;
425 *set_p = false;
426 }
427
428 if (disable)
429 retval = dpm->bpwp_disable(dpm, xp->number);
430 else
431 retval = dpm->bpwp_enable(dpm, xp->number,
432 xp->address, xp->control);
433
434 if (retval != ERROR_OK)
435 LOG_ERROR("%s: can't %s HW %spoint %d",
436 disable ? "disable" : "enable",
437 target_name(dpm->arm->target),
438 (xp->number < 16) ? "break" : "watch",
439 xp->number & 0xf);
440 done:
441 return retval;
442 }
443
444 static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp);
445
446 /**
447 * Writes all modified core registers for all processor modes. In normal
448 * operation this is called on exit from halting debug state.
449 *
450 * @param dpm: represents the processor
451 * @param bpwp: true ensures breakpoints and watchpoints are set,
452 * false ensures they are cleared
453 */
454 int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
455 {
456 struct arm *arm = dpm->arm;
457 struct reg_cache *cache = arm->core_cache;
458 int retval;
459 bool did_write;
460
461 retval = dpm->prepare(dpm);
462 if (retval != ERROR_OK)
463 goto done;
464
465 /* If we're managing hardware breakpoints for this core, enable
466 * or disable them as requested.
467 *
468 * REVISIT We don't yet manage them for ANY cores. Eventually
469 * we should be able to assume we handle them; but until then,
470 * cope with the hand-crafted breakpoint code.
471 */
472 if (arm->target->type->add_breakpoint == dpm_add_breakpoint) {
473 for (unsigned i = 0; i < dpm->nbp; i++) {
474 struct dpm_bp *dbp = dpm->dbp + i;
475 struct breakpoint *bp = dbp->bp;
476
477 retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
478 bp ? &bp->set : NULL);
479 if (retval != ERROR_OK)
480 goto done;
481 }
482 }
483
484 /* enable/disable watchpoints */
485 for (unsigned i = 0; i < dpm->nwp; i++) {
486 struct dpm_wp *dwp = dpm->dwp + i;
487 struct watchpoint *wp = dwp->wp;
488
489 retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
490 wp ? &wp->set : NULL);
491 if (retval != ERROR_OK)
492 goto done;
493 }
494
495 /* NOTE: writes to breakpoint and watchpoint registers might
496 * be queued, and need (efficient/batched) flushing later.
497 */
498
499 /* Scan the registers until we find one that's both dirty and
500 * eligible for flushing. Flush that and everything else that
501 * shares the same core mode setting. Typically this won't
502 * actually find anything to do...
503 */
504 do {
505 enum arm_mode mode = ARM_MODE_ANY;
506
507 did_write = false;
508
509 /* check everything except our scratch registers R0 and R1 */
510 for (unsigned i = 2; i < cache->num_regs; i++) {
511 struct arm_reg *r;
512 unsigned regnum;
513
514 /* also skip PC, CPSR, and non-dirty */
515 if (i == 15)
516 continue;
517 if (arm->cpsr == cache->reg_list + i)
518 continue;
519 if (!cache->reg_list[i].dirty)
520 continue;
521
522 r = cache->reg_list[i].arch_info;
523 regnum = r->num;
524
525 /* may need to pick and set a mode */
526 if (!did_write) {
527 enum arm_mode tmode;
528
529 did_write = true;
530 mode = tmode = r->mode;
531
532 /* cope with special cases */
533 switch (regnum) {
534 case 8 ... 12:
535 /* r8..r12 "anything but FIQ" case;
536 * we "know" core mode is accurate
537 * since we haven't changed it yet
538 */
539 if (arm->core_mode == ARM_MODE_FIQ
540 && ARM_MODE_ANY
541 != mode)
542 tmode = ARM_MODE_USR;
543 break;
544 case 16:
545 /* SPSR */
546 regnum++;
547 break;
548 }
549
550 /* REVISIT error checks */
551 if (tmode != ARM_MODE_ANY) {
552 retval = arm_dpm_modeswitch(dpm, tmode);
553 if (retval != ERROR_OK)
554 goto done;
555 }
556 }
557 if (r->mode != mode)
558 continue;
559
560 retval = dpm_write_reg(dpm,
561 &cache->reg_list[i],
562 regnum);
563 if (retval != ERROR_OK)
564 goto done;
565 }
566
567 } while (did_write);
568
569 /* Restore original CPSR ... assuming either that we changed it,
570 * or it's dirty. Must write PC to ensure the return address is
571 * defined, and must not write it before CPSR.
572 */
573 retval = arm_dpm_modeswitch(dpm, ARM_MODE_ANY);
574 if (retval != ERROR_OK)
575 goto done;
576 arm->cpsr->dirty = false;
577
578 /* restore the PC, make sure to also switch the core state
579 * to whatever it was set to with "arm core_state" command.
580 * target code will have set PC to an appropriate resume address.
581 */
582 retval = dpm_write_pc_core_state(dpm, arm->pc);
583 if (retval != ERROR_OK)
584 goto done;
585 /* on Cortex-A5 (as found on NXP VF610 SoC), BX instruction
586 * executed in debug state doesn't appear to set the PC,
587 * explicitly set it with a "MOV pc, r0". This doesn't influence
588 * CPSR on Cortex-A9 so it should be OK. Maybe due to different
589 * debug version?
590 */
591 retval = dpm_write_reg(dpm, arm->pc, 15);
592 if (retval != ERROR_OK)
593 goto done;
594 arm->pc->dirty = false;
595
596 /* flush R0 and R1 (our scratch registers) */
597 for (unsigned i = 0; i < 2; i++) {
598 retval = dpm_write_reg(dpm, &cache->reg_list[i], i);
599 if (retval != ERROR_OK)
600 goto done;
601 cache->reg_list[i].dirty = false;
602 }
603
604 /* (void) */ dpm->finish(dpm);
605 done:
606 return retval;
607 }
608
609 /* Returns ARM_MODE_ANY or temporary mode to use while reading the
610 * specified register ... works around flakiness from ARM core calls.
611 * Caller already filtered out SPSR access; mode is never MODE_SYS
612 * or MODE_ANY.
613 */
614 static enum arm_mode dpm_mapmode(struct arm *arm,
615 unsigned num, enum arm_mode mode)
616 {
617 enum arm_mode amode = arm->core_mode;
618
619 /* don't switch if the mode is already correct */
620 if (amode == ARM_MODE_SYS)
621 amode = ARM_MODE_USR;
622 if (mode == amode)
623 return ARM_MODE_ANY;
624
625 switch (num) {
626 /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
627 case 0 ... 7:
628 case 15:
629 case 16:
630 break;
631 /* r8..r12 aren't shadowed for anything except FIQ */
632 case 8 ... 12:
633 if (mode == ARM_MODE_FIQ)
634 return mode;
635 break;
636 /* r13/sp, and r14/lr are always shadowed */
637 case 13:
638 case 14:
639 case ARM_VFP_V3_D0 ... ARM_VFP_V3_FPSCR:
640 return mode;
641 default:
642 LOG_WARNING("invalid register #%u", num);
643 break;
644 }
645 return ARM_MODE_ANY;
646 }
647
648
649 /*
650 * Standard ARM register accessors ... there are three methods
651 * in "struct arm", to support individual read/write and bulk read
652 * of registers.
653 */
654
655 static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
656 int regnum, enum arm_mode mode)
657 {
658 struct arm_dpm *dpm = target_to_arm(target)->dpm;
659 int retval;
660
661 if (regnum < 0 || (regnum > 16 && regnum < ARM_VFP_V3_D0) ||
662 (regnum > ARM_VFP_V3_FPSCR))
663 return ERROR_COMMAND_SYNTAX_ERROR;
664
665 if (regnum == 16) {
666 if (mode != ARM_MODE_ANY)
667 regnum = 17;
668 } else
669 mode = dpm_mapmode(dpm->arm, regnum, mode);
670
671 /* REVISIT what happens if we try to read SPSR in a core mode
672 * which has no such register?
673 */
674
675 retval = dpm->prepare(dpm);
676 if (retval != ERROR_OK)
677 return retval;
678
679 if (mode != ARM_MODE_ANY) {
680 retval = arm_dpm_modeswitch(dpm, mode);
681 if (retval != ERROR_OK)
682 goto fail;
683 }
684
685 retval = arm_dpm_read_reg(dpm, r, regnum);
686 if (retval != ERROR_OK)
687 goto fail;
688 /* always clean up, regardless of error */
689
690 if (mode != ARM_MODE_ANY)
691 /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY);
692
693 fail:
694 /* (void) */ dpm->finish(dpm);
695 return retval;
696 }
697
698 static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
699 int regnum, enum arm_mode mode, uint8_t *value)
700 {
701 struct arm_dpm *dpm = target_to_arm(target)->dpm;
702 int retval;
703
704
705 if (regnum < 0 || (regnum > 16 && regnum < ARM_VFP_V3_D0) ||
706 (regnum > ARM_VFP_V3_FPSCR))
707 return ERROR_COMMAND_SYNTAX_ERROR;
708
709 if (regnum == 16) {
710 if (mode != ARM_MODE_ANY)
711 regnum = 17;
712 } else
713 mode = dpm_mapmode(dpm->arm, regnum, mode);
714
715 /* REVISIT what happens if we try to write SPSR in a core mode
716 * which has no such register?
717 */
718
719 retval = dpm->prepare(dpm);
720 if (retval != ERROR_OK)
721 return retval;
722
723 if (mode != ARM_MODE_ANY) {
724 retval = arm_dpm_modeswitch(dpm, mode);
725 if (retval != ERROR_OK)
726 goto fail;
727 }
728
729 retval = dpm_write_reg(dpm, r, regnum);
730 /* always clean up, regardless of error */
731
732 if (mode != ARM_MODE_ANY)
733 /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY);
734
735 fail:
736 /* (void) */ dpm->finish(dpm);
737 return retval;
738 }
739
740 static int arm_dpm_full_context(struct target *target)
741 {
742 struct arm *arm = target_to_arm(target);
743 struct arm_dpm *dpm = arm->dpm;
744 struct reg_cache *cache = arm->core_cache;
745 int retval;
746 bool did_read;
747
748 retval = dpm->prepare(dpm);
749 if (retval != ERROR_OK)
750 goto done;
751
752 do {
753 enum arm_mode mode = ARM_MODE_ANY;
754
755 did_read = false;
756
757 /* We "know" arm_dpm_read_current_registers() was called so
758 * the unmapped registers (R0..R7, PC, AND CPSR) and some
759 * view of R8..R14 are current. We also "know" oddities of
760 * register mapping: special cases for R8..R12 and SPSR.
761 *
762 * Pick some mode with unread registers and read them all.
763 * Repeat until done.
764 */
765 for (unsigned i = 0; i < cache->num_regs; i++) {
766 struct arm_reg *r;
767
768 if (cache->reg_list[i].valid)
769 continue;
770 r = cache->reg_list[i].arch_info;
771
772 /* may need to pick a mode and set CPSR */
773 if (!did_read) {
774 did_read = true;
775 mode = r->mode;
776
777 /* For regular (ARM_MODE_ANY) R8..R12
778 * in case we've entered debug state
779 * in FIQ mode we need to patch mode.
780 */
781 if (mode != ARM_MODE_ANY)
782 retval = arm_dpm_modeswitch(dpm, mode);
783 else
784 retval = arm_dpm_modeswitch(dpm, ARM_MODE_USR);
785
786 if (retval != ERROR_OK)
787 goto done;
788 }
789 if (r->mode != mode)
790 continue;
791
792 /* CPSR was read, so "R16" must mean SPSR */
793 retval = arm_dpm_read_reg(dpm,
794 &cache->reg_list[i],
795 (r->num == 16) ? 17 : r->num);
796 if (retval != ERROR_OK)
797 goto done;
798 }
799
800 } while (did_read);
801
802 retval = arm_dpm_modeswitch(dpm, ARM_MODE_ANY);
803 /* (void) */ dpm->finish(dpm);
804 done:
805 return retval;
806 }
807
808
809 /*----------------------------------------------------------------------*/
810
811 /*
812 * Breakpoint and Watchpoint support.
813 *
814 * Hardware {break,watch}points are usually left active, to minimize
815 * debug entry/exit costs. When they are set or cleared, it's done in
816 * batches. Also, DPM-conformant hardware can update debug registers
817 * regardless of whether the CPU is running or halted ... though that
818 * fact isn't currently leveraged.
819 */
820
821 static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
822 uint32_t addr, uint32_t length)
823 {
824 uint32_t control;
825
826 control = (1 << 0) /* enable */
827 | (3 << 1); /* both user and privileged access */
828
829 /* Match 1, 2, or all 4 byte addresses in this word.
830 *
831 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
832 * Support larger length, when addr is suitably aligned. In
833 * particular, allow watchpoints on 8 byte "double" values.
834 *
835 * REVISIT allow watchpoints on unaligned 2-bit values; and on
836 * v7 hardware, unaligned 4-byte ones too.
837 */
838 switch (length) {
839 case 1:
840 control |= (1 << (addr & 3)) << 5;
841 break;
842 case 2:
843 /* require 2-byte alignment */
844 if (!(addr & 1)) {
845 control |= (3 << (addr & 2)) << 5;
846 break;
847 }
848 /* FALL THROUGH */
849 case 4:
850 /* require 4-byte alignment */
851 if (!(addr & 3)) {
852 control |= 0xf << 5;
853 break;
854 }
855 /* FALL THROUGH */
856 default:
857 LOG_ERROR("unsupported {break,watch}point length/alignment");
858 return ERROR_COMMAND_SYNTAX_ERROR;
859 }
860
861 /* other shared control bits:
862 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
863 * bit 20 == 0 ... not linked to a context ID
864 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
865 */
866
867 xp->address = addr & ~3;
868 xp->control = control;
869 xp->dirty = true;
870
871 LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
872 xp->address, control, xp->number);
873
874 /* hardware is updated in write_dirty_registers() */
875 return ERROR_OK;
876 }
877
878 static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp)
879 {
880 struct arm *arm = target_to_arm(target);
881 struct arm_dpm *dpm = arm->dpm;
882 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
883
884 if (bp->length < 2)
885 return ERROR_COMMAND_SYNTAX_ERROR;
886 if (!dpm->bpwp_enable)
887 return retval;
888
889 /* FIXME we need a generic solution for software breakpoints. */
890 if (bp->type == BKPT_SOFT)
891 LOG_DEBUG("using HW bkpt, not SW...");
892
893 for (unsigned i = 0; i < dpm->nbp; i++) {
894 if (!dpm->dbp[i].bp) {
895 retval = dpm_bpwp_setup(dpm, &dpm->dbp[i].bpwp,
896 bp->address, bp->length);
897 if (retval == ERROR_OK)
898 dpm->dbp[i].bp = bp;
899 break;
900 }
901 }
902
903 return retval;
904 }
905
906 static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp)
907 {
908 struct arm *arm = target_to_arm(target);
909 struct arm_dpm *dpm = arm->dpm;
910 int retval = ERROR_COMMAND_SYNTAX_ERROR;
911
912 for (unsigned i = 0; i < dpm->nbp; i++) {
913 if (dpm->dbp[i].bp == bp) {
914 dpm->dbp[i].bp = NULL;
915 dpm->dbp[i].bpwp.dirty = true;
916
917 /* hardware is updated in write_dirty_registers() */
918 retval = ERROR_OK;
919 break;
920 }
921 }
922
923 return retval;
924 }
925
926 static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
927 struct watchpoint *wp)
928 {
929 int retval;
930 struct dpm_wp *dwp = dpm->dwp + index_t;
931 uint32_t control;
932
933 /* this hardware doesn't support data value matching or masking */
934 if (wp->value || wp->mask != ~(uint32_t)0) {
935 LOG_DEBUG("watchpoint values and masking not supported");
936 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
937 }
938
939 retval = dpm_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length);
940 if (retval != ERROR_OK)
941 return retval;
942
943 control = dwp->bpwp.control;
944 switch (wp->rw) {
945 case WPT_READ:
946 control |= 1 << 3;
947 break;
948 case WPT_WRITE:
949 control |= 2 << 3;
950 break;
951 case WPT_ACCESS:
952 control |= 3 << 3;
953 break;
954 }
955 dwp->bpwp.control = control;
956
957 dpm->dwp[index_t].wp = wp;
958
959 return retval;
960 }
961
962 static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp)
963 {
964 struct arm *arm = target_to_arm(target);
965 struct arm_dpm *dpm = arm->dpm;
966 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
967
968 if (dpm->bpwp_enable) {
969 for (unsigned i = 0; i < dpm->nwp; i++) {
970 if (!dpm->dwp[i].wp) {
971 retval = dpm_watchpoint_setup(dpm, i, wp);
972 break;
973 }
974 }
975 }
976
977 return retval;
978 }
979
980 static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp)
981 {
982 struct arm *arm = target_to_arm(target);
983 struct arm_dpm *dpm = arm->dpm;
984 int retval = ERROR_COMMAND_SYNTAX_ERROR;
985
986 for (unsigned i = 0; i < dpm->nwp; i++) {
987 if (dpm->dwp[i].wp == wp) {
988 dpm->dwp[i].wp = NULL;
989 dpm->dwp[i].bpwp.dirty = true;
990
991 /* hardware is updated in write_dirty_registers() */
992 retval = ERROR_OK;
993 break;
994 }
995 }
996
997 return retval;
998 }
999
1000 void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
1001 {
1002 switch (dpm->arm->core_state) {
1003 case ARM_STATE_ARM:
1004 addr -= 8;
1005 break;
1006 case ARM_STATE_THUMB:
1007 case ARM_STATE_THUMB_EE:
1008 addr -= 4;
1009 break;
1010 case ARM_STATE_JAZELLE:
1011 case ARM_STATE_AARCH64:
1012 /* ?? */
1013 break;
1014 }
1015 dpm->wp_pc = addr;
1016 }
1017
1018 /*----------------------------------------------------------------------*/
1019
1020 /*
1021 * Other debug and support utilities
1022 */
1023
1024 void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
1025 {
1026 struct target *target = dpm->arm->target;
1027
1028 dpm->dscr = dscr;
1029
1030 /* Examine debug reason */
1031 switch (DSCR_ENTRY(dscr)) {
1032 case DSCR_ENTRY_HALT_REQ: /* HALT request from debugger */
1033 case DSCR_ENTRY_EXT_DBG_REQ: /* EDBGRQ */
1034 target->debug_reason = DBG_REASON_DBGRQ;
1035 break;
1036 case DSCR_ENTRY_BREAKPOINT: /* HW breakpoint */
1037 case DSCR_ENTRY_BKPT_INSTR: /* vector catch */
1038 target->debug_reason = DBG_REASON_BREAKPOINT;
1039 break;
1040 case DSCR_ENTRY_IMPRECISE_WATCHPT: /* asynch watchpoint */
1041 case DSCR_ENTRY_PRECISE_WATCHPT:/* precise watchpoint */
1042 target->debug_reason = DBG_REASON_WATCHPOINT;
1043 break;
1044 default:
1045 target->debug_reason = DBG_REASON_UNDEFINED;
1046 break;
1047 }
1048 }
1049
1050 /*----------------------------------------------------------------------*/
1051
1052 /*
1053 * Setup and management support.
1054 */
1055
1056 /**
1057 * Hooks up this DPM to its associated target; call only once.
1058 * Initially this only covers the register cache.
1059 *
1060 * Oh, and watchpoints. Yeah.
1061 */
1062 int arm_dpm_setup(struct arm_dpm *dpm)
1063 {
1064 struct arm *arm = dpm->arm;
1065 struct target *target = arm->target;
1066 struct reg_cache *cache = 0;
1067
1068 arm->dpm = dpm;
1069
1070 /* register access setup */
1071 arm->full_context = arm_dpm_full_context;
1072 arm->read_core_reg = arm_dpm_read_core_reg;
1073 arm->write_core_reg = arm_dpm_write_core_reg;
1074
1075 if (arm->core_cache == NULL) {
1076 cache = arm_build_reg_cache(target, arm);
1077 if (!cache)
1078 return ERROR_FAIL;
1079
1080 *register_get_last_cache_p(&target->reg_cache) = cache;
1081 }
1082
1083 /* coprocessor access setup */
1084 arm->mrc = dpm_mrc;
1085 arm->mcr = dpm_mcr;
1086
1087 /* breakpoint setup -- optional until it works everywhere */
1088 if (!target->type->add_breakpoint) {
1089 target->type->add_breakpoint = dpm_add_breakpoint;
1090 target->type->remove_breakpoint = dpm_remove_breakpoint;
1091 }
1092
1093 /* watchpoint setup */
1094 target->type->add_watchpoint = dpm_add_watchpoint;
1095 target->type->remove_watchpoint = dpm_remove_watchpoint;
1096
1097 /* FIXME add vector catch support */
1098
1099 dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf);
1100 dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf);
1101 dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
1102 dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
1103
1104 if (!dpm->dbp || !dpm->dwp) {
1105 free(dpm->dbp);
1106 free(dpm->dwp);
1107 return ERROR_FAIL;
1108 }
1109
1110 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1111 target_name(target), dpm->nbp, dpm->nwp);
1112
1113 /* REVISIT ... and some of those breakpoints could match
1114 * execution context IDs...
1115 */
1116
1117 return ERROR_OK;
1118 }
1119
1120 /**
1121 * Reinitializes DPM state at the beginning of a new debug session
1122 * or after a reset which may have affected the debug module.
1123 */
1124 int arm_dpm_initialize(struct arm_dpm *dpm)
1125 {
1126 /* Disable all breakpoints and watchpoints at startup. */
1127 if (dpm->bpwp_disable) {
1128 unsigned i;
1129
1130 for (i = 0; i < dpm->nbp; i++) {
1131 dpm->dbp[i].bpwp.number = i;
1132 (void) dpm->bpwp_disable(dpm, i);
1133 }
1134 for (i = 0; i < dpm->nwp; i++) {
1135 dpm->dwp[i].bpwp.number = 16 + i;
1136 (void) dpm->bpwp_disable(dpm, 16 + i);
1137 }
1138 } else
1139 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
1140 target_name(dpm->arm->target));
1141
1142 return ERROR_OK;
1143 }

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)