2 * Copyright (C) 2009 by David Brownell
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.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "armv4_5.h" /* REVISIT to become arm.h */
28 #include "breakpoints.h"
29 #include "target_type.h"
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.
39 /*----------------------------------------------------------------------*/
45 /* Read coprocessor */
46 static int dpm_mrc(struct target
*target
, int cpnum
,
47 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
50 struct arm
*arm
= target_to_arm(target
);
51 struct arm_dpm
*dpm
= arm
->dpm
;
54 retval
= dpm
->prepare(dpm
);
55 if (retval
!= ERROR_OK
)
58 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum
, op1
, CRn
, CRm
, op2
);
60 /* read coprocessor register into R0; return via DCC */
61 retval
= dpm
->instr_read_data_r0(dpm
,
62 ARMV4_5_MRC(cpnum
, op1
, 0, CRn
, CRm
, op2
),
65 /* (void) */ dpm
->finish(dpm
);
69 static int dpm_mcr(struct target
*target
, int cpnum
,
70 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
73 struct arm
*arm
= target_to_arm(target
);
74 struct arm_dpm
*dpm
= arm
->dpm
;
77 retval
= dpm
->prepare(dpm
);
78 if (retval
!= ERROR_OK
)
81 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum
, op1
, CRn
, CRm
, op2
);
83 /* read DCC into r0; then write coprocessor register from R0 */
84 retval
= dpm
->instr_write_data_r0(dpm
,
85 ARMV4_5_MCR(cpnum
, op1
, 0, CRn
, CRm
, op2
),
88 /* (void) */ dpm
->finish(dpm
);
92 /*----------------------------------------------------------------------*/
95 * Register access utilities
98 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
99 * Routines *must* restore the original mode before returning!!
101 static int dpm_modeswitch(struct arm_dpm
*dpm
, enum armv4_5_mode mode
)
106 /* restore previous mode */
107 if (mode
== ARMV4_5_MODE_ANY
)
108 cpsr
= buf_get_u32(dpm
->arm
->cpsr
->value
, 0, 32);
110 /* else force to the specified mode */
114 retval
= dpm
->instr_write_data_r0(dpm
, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr
);
116 if (dpm
->instr_cpsr_sync
)
117 retval
= dpm
->instr_cpsr_sync(dpm
);
122 /* just read the register -- rely on the core mode being right */
123 static int dpm_read_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
130 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
131 retval
= dpm
->instr_read_data_dcc(dpm
,
132 ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0),
136 /* "MOV r0, pc"; then return via DCC */
137 retval
= dpm
->instr_read_data_r0(dpm
, 0xe1a0000f, &value
);
139 /* NOTE: this seems like a slightly awkward place to update
140 * this value ... but if the PC gets written (the only way
141 * to change what we compute), the arch spec says subsequent
142 * reads return values which are "unpredictable". So this
143 * is always right except in those broken-by-intent cases.
145 switch (dpm
->arm
->core_state
) {
146 case ARMV4_5_STATE_ARM
:
149 case ARMV4_5_STATE_THUMB
:
150 case ARM_STATE_THUMB_EE
:
153 case ARMV4_5_STATE_JAZELLE
:
154 /* core-specific ... ? */
155 LOG_WARNING("Jazelle PC adjustment unknown");
160 /* 16: "MRS r0, CPSR"; then return via DCC
161 * 17: "MRS r0, SPSR"; then return via DCC
163 retval
= dpm
->instr_read_data_r0(dpm
,
164 ARMV4_5_MRS(0, regnum
& 1),
169 if (retval
== ERROR_OK
) {
170 buf_set_u32(r
->value
, 0, 32, value
);
173 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
179 /* just write the register -- rely on the core mode being right */
180 static int dpm_write_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
183 uint32_t value
= buf_get_u32(r
->value
, 0, 32);
187 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
188 retval
= dpm
->instr_write_data_dcc(dpm
,
189 ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0),
193 /* read r0 from DCC; then "MOV pc, r0" */
194 retval
= dpm
->instr_write_data_r0(dpm
, 0xe1a0f000, value
);
197 /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
198 * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
200 retval
= dpm
->instr_write_data_r0(dpm
,
201 ARMV4_5_MSR_GP(0, 0xf, regnum
& 1),
204 if (regnum
== 16 && dpm
->instr_cpsr_sync
)
205 retval
= dpm
->instr_cpsr_sync(dpm
);
210 if (retval
== ERROR_OK
) {
212 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
219 * Read basic registers of the the current context: R0 to R15, and CPSR;
220 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
221 * In normal operation this is called on entry to halting debug state,
222 * possibly after some other operations supporting restore of debug state
223 * or making sure the CPU is fully idle (drain write buffer, etc).
225 int arm_dpm_read_current_registers(struct arm_dpm
*dpm
)
227 struct arm
*arm
= dpm
->arm
;
232 retval
= dpm
->prepare(dpm
);
233 if (retval
!= ERROR_OK
)
236 /* read R0 first (it's used for scratch), then CPSR */
237 r
= arm
->core_cache
->reg_list
+ 0;
239 retval
= dpm_read_reg(dpm
, r
, 0);
240 if (retval
!= ERROR_OK
)
245 retval
= dpm
->instr_read_data_r0(dpm
, ARMV4_5_MRS(0, 0), &cpsr
);
246 if (retval
!= ERROR_OK
)
249 /* update core mode and state, plus shadow mapping for R8..R14 */
250 arm_set_cpsr(arm
, cpsr
);
252 /* REVISIT we can probably avoid reading R1..R14, saving time... */
253 for (unsigned i
= 1; i
< 16; i
++) {
254 r
= arm_reg_current(arm
, i
);
258 retval
= dpm_read_reg(dpm
, r
, i
);
259 if (retval
!= ERROR_OK
)
263 /* NOTE: SPSR ignored (if it's even relevant). */
265 /* REVISIT the debugger can trigger various exceptions. See the
266 * ARMv7A architecture spec, section C5.7, for more info about
267 * what defenses are needed; v6 debug has the most issues.
271 /* (void) */ dpm
->finish(dpm
);
276 * Writes all modified core registers for all processor modes. In normal
277 * operation this is called on exit from halting debug state.
279 * @param bpwp: true ensures breakpoints and watchpoints are set,
280 * false ensures they are cleared
282 int arm_dpm_write_dirty_registers(struct arm_dpm
*dpm
, bool bpwp
)
284 struct arm
*arm
= dpm
->arm
;
285 struct reg_cache
*cache
= arm
->core_cache
;
289 retval
= dpm
->prepare(dpm
);
290 if (retval
!= ERROR_OK
)
293 /* enable/disable watchpoints */
294 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
295 struct dpm_wp
*dwp
= dpm
->dwp
+ i
;
296 struct watchpoint
*wp
= dwp
->wp
;
299 /* Avoid needless I/O ... leave watchpoints alone
300 * unless they're removed, or need updating because
301 * of single-stepping or running debugger code.
307 /* removed or startup; we must disable it */
312 /* disabled, but we must set it */
313 dwp
->dirty
= disable
= false;
318 /* set, but we must temporarily disable it */
319 dwp
->dirty
= disable
= true;
324 retval
= dpm
->bpwp_disable(dpm
, 16 + i
);
326 retval
= dpm
->bpwp_enable(dpm
, 16 + i
,
327 wp
->address
, dwp
->control
);
329 if (retval
!= ERROR_OK
)
330 LOG_ERROR("%s: can't %s HW watchpoint %d",
331 target_name(arm
->target
),
332 disable
? "disable" : "enable",
336 /* NOTE: writes to breakpoint and watchpoint registers might
337 * be queued, and need (efficient/batched) flushing later.
340 /* Scan the registers until we find one that's both dirty and
341 * eligible for flushing. Flush that and everything else that
342 * shares the same core mode setting. Typically this won't
343 * actually find anything to do...
346 enum armv4_5_mode mode
= ARMV4_5_MODE_ANY
;
350 /* check everything except our scratch register R0 */
351 for (unsigned i
= 1; i
< cache
->num_regs
; i
++) {
355 /* also skip PC, CPSR, and non-dirty */
358 if (arm
->cpsr
== cache
->reg_list
+ i
)
360 if (!cache
->reg_list
[i
].dirty
)
363 r
= cache
->reg_list
[i
].arch_info
;
366 /* may need to pick and set a mode */
368 enum armv4_5_mode tmode
;
371 mode
= tmode
= r
->mode
;
373 /* cope with special cases */
376 /* r8..r12 "anything but FIQ" case;
377 * we "know" core mode is accurate
378 * since we haven't changed it yet
380 if (arm
->core_mode
== ARMV4_5_MODE_FIQ
383 tmode
= ARMV4_5_MODE_USR
;
391 /* REVISIT error checks */
392 if (tmode
!= ARMV4_5_MODE_ANY
)
393 retval
= dpm_modeswitch(dpm
, tmode
);
398 retval
= dpm_write_reg(dpm
,
406 /* Restore original CPSR ... assuming either that we changed it,
407 * or it's dirty. Must write PC to ensure the return address is
408 * defined, and must not write it before CPSR.
410 retval
= dpm_modeswitch(dpm
, ARMV4_5_MODE_ANY
);
411 arm
->cpsr
->dirty
= false;
413 retval
= dpm_write_reg(dpm
, &cache
->reg_list
[15], 15);
414 cache
->reg_list
[15].dirty
= false;
416 /* flush R0 -- it's *very* dirty by now */
417 retval
= dpm_write_reg(dpm
, &cache
->reg_list
[0], 0);
418 cache
->reg_list
[0].dirty
= false;
420 /* (void) */ dpm
->finish(dpm
);
425 /* Returns ARMV4_5_MODE_ANY or temporary mode to use while reading the
426 * specified register ... works around flakiness from ARM core calls.
427 * Caller already filtered out SPSR access; mode is never MODE_SYS
430 static enum armv4_5_mode
dpm_mapmode(struct arm
*arm
,
431 unsigned num
, enum armv4_5_mode mode
)
433 enum armv4_5_mode amode
= arm
->core_mode
;
435 /* don't switch if the mode is already correct */
436 if (amode
== ARMV4_5_MODE_SYS
)
437 amode
= ARMV4_5_MODE_USR
;
439 return ARMV4_5_MODE_ANY
;
442 /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
447 /* r8..r12 aren't shadowed for anything except FIQ */
449 if (mode
== ARMV4_5_MODE_FIQ
)
452 /* r13/sp, and r14/lr are always shadowed */
457 LOG_WARNING("invalid register #%u", num
);
460 return ARMV4_5_MODE_ANY
;
465 * Standard ARM register accessors ... there are three methods
466 * in "struct arm", to support individual read/write and bulk read
470 static int arm_dpm_read_core_reg(struct target
*target
, struct reg
*r
,
471 int regnum
, enum armv4_5_mode mode
)
473 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
476 if (regnum
< 0 || regnum
> 16)
477 return ERROR_INVALID_ARGUMENTS
;
480 if (mode
!= ARMV4_5_MODE_ANY
)
483 mode
= dpm_mapmode(dpm
->arm
, regnum
, mode
);
485 /* REVISIT what happens if we try to read SPSR in a core mode
486 * which has no such register?
489 retval
= dpm
->prepare(dpm
);
490 if (retval
!= ERROR_OK
)
493 if (mode
!= ARMV4_5_MODE_ANY
) {
494 retval
= dpm_modeswitch(dpm
, mode
);
495 if (retval
!= ERROR_OK
)
499 retval
= dpm_read_reg(dpm
, r
, regnum
);
500 /* always clean up, regardless of error */
502 if (mode
!= ARMV4_5_MODE_ANY
)
503 /* (void) */ dpm_modeswitch(dpm
, ARMV4_5_MODE_ANY
);
506 /* (void) */ dpm
->finish(dpm
);
510 static int arm_dpm_write_core_reg(struct target
*target
, struct reg
*r
,
511 int regnum
, enum armv4_5_mode mode
, uint32_t value
)
513 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
517 if (regnum
< 0 || regnum
> 16)
518 return ERROR_INVALID_ARGUMENTS
;
521 if (mode
!= ARMV4_5_MODE_ANY
)
524 mode
= dpm_mapmode(dpm
->arm
, regnum
, mode
);
526 /* REVISIT what happens if we try to write SPSR in a core mode
527 * which has no such register?
530 retval
= dpm
->prepare(dpm
);
531 if (retval
!= ERROR_OK
)
534 if (mode
!= ARMV4_5_MODE_ANY
) {
535 retval
= dpm_modeswitch(dpm
, mode
);
536 if (retval
!= ERROR_OK
)
540 retval
= dpm_write_reg(dpm
, r
, regnum
);
541 /* always clean up, regardless of error */
543 if (mode
!= ARMV4_5_MODE_ANY
)
544 /* (void) */ dpm_modeswitch(dpm
, ARMV4_5_MODE_ANY
);
547 /* (void) */ dpm
->finish(dpm
);
551 static int arm_dpm_full_context(struct target
*target
)
553 struct arm
*arm
= target_to_arm(target
);
554 struct arm_dpm
*dpm
= arm
->dpm
;
555 struct reg_cache
*cache
= arm
->core_cache
;
559 retval
= dpm
->prepare(dpm
);
560 if (retval
!= ERROR_OK
)
564 enum armv4_5_mode mode
= ARMV4_5_MODE_ANY
;
568 /* We "know" arm_dpm_read_current_registers() was called so
569 * the unmapped registers (R0..R7, PC, AND CPSR) and some
570 * view of R8..R14 are current. We also "know" oddities of
571 * register mapping: special cases for R8..R12 and SPSR.
573 * Pick some mode with unread registers and read them all.
576 for (unsigned i
= 0; i
< cache
->num_regs
; i
++) {
579 if (cache
->reg_list
[i
].valid
)
581 r
= cache
->reg_list
[i
].arch_info
;
583 /* may need to pick a mode and set CPSR */
588 /* For R8..R12 when we've entered debug
589 * state in FIQ mode... patch mode.
591 if (mode
== ARMV4_5_MODE_ANY
)
592 mode
= ARMV4_5_MODE_USR
;
594 /* REVISIT error checks */
595 retval
= dpm_modeswitch(dpm
, mode
);
600 /* CPSR was read, so "R16" must mean SPSR */
601 retval
= dpm_read_reg(dpm
,
603 (r
->num
== 16) ? 17 : r
->num
);
609 retval
= dpm_modeswitch(dpm
, ARMV4_5_MODE_ANY
);
610 /* (void) */ dpm
->finish(dpm
);
616 /*----------------------------------------------------------------------*/
619 * Breakpoint and Watchpoint support.
621 * Hardware {break,watch}points are usually left active, to minimize
622 * debug entry/exit costs. When they are set or cleared, it's done in
623 * batches. Also, DPM-conformant hardware can update debug registers
624 * regardless of whether the CPU is running or halted ... though that
625 * fact isn't currently leveraged.
628 static int dpm_watchpoint_setup(struct arm_dpm
*dpm
, unsigned index
,
629 struct watchpoint
*wp
)
631 uint32_t addr
= wp
->address
;
634 /* this hardware doesn't support data value matching or masking */
635 if (wp
->value
|| wp
->mask
!= ~(uint32_t)0) {
636 LOG_DEBUG("watchpoint values and masking not supported");
637 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
640 control
= (1 << 0) /* enable */
641 | (3 << 1); /* both user and privileged access */
655 /* Match 1, 2, or all 4 byte addresses in this word.
657 * FIXME: v7 hardware allows lengths up to 2 GB, and has eight
658 * byte address select bits. Support larger wp->length, if addr
659 * is suitably aligned.
661 switch (wp
->length
) {
663 control
|= (1 << (addr
& 3)) << 5;
667 /* require 2-byte alignment */
669 control
|= (3 << (addr
& 2)) << 5;
674 /* require 4-byte alignment */
681 LOG_DEBUG("bad watchpoint length or alignment");
682 return ERROR_INVALID_ARGUMENTS
;
685 /* other control bits:
686 * bits 9:12 == 0 ... only checking up to four byte addresses (v7 only)
687 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
688 * bit 20 == 0 ... not linked to a context ID
689 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
692 dpm
->dwp
[index
].wp
= wp
;
693 dpm
->dwp
[index
].control
= control
;
694 dpm
->dwp
[index
].dirty
= true;
696 /* hardware is updated in write_dirty_registers() */
701 static int dpm_add_watchpoint(struct target
*target
, struct watchpoint
*wp
)
703 struct arm
*arm
= target_to_arm(target
);
704 struct arm_dpm
*dpm
= arm
->dpm
;
705 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
707 if (dpm
->bpwp_enable
) {
708 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
709 if (!dpm
->dwp
[i
].wp
) {
710 retval
= dpm_watchpoint_setup(dpm
, i
, wp
);
719 static int dpm_remove_watchpoint(struct target
*target
, struct watchpoint
*wp
)
721 struct arm
*arm
= target_to_arm(target
);
722 struct arm_dpm
*dpm
= arm
->dpm
;
723 int retval
= ERROR_INVALID_ARGUMENTS
;
725 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
726 if (dpm
->dwp
[i
].wp
== wp
) {
727 dpm
->dwp
[i
].wp
= NULL
;
728 dpm
->dwp
[i
].dirty
= true;
730 /* hardware is updated in write_dirty_registers() */
739 void arm_dpm_report_wfar(struct arm_dpm
*dpm
, uint32_t addr
)
741 switch (dpm
->arm
->core_state
) {
742 case ARMV4_5_STATE_ARM
:
745 case ARMV4_5_STATE_THUMB
:
746 case ARM_STATE_THUMB_EE
:
749 case ARMV4_5_STATE_JAZELLE
:
756 /*----------------------------------------------------------------------*/
759 * Setup and management support.
763 * Hooks up this DPM to its associated target; call only once.
764 * Initially this only covers the register cache.
766 * Oh, and watchpoints. Yeah.
768 int arm_dpm_setup(struct arm_dpm
*dpm
)
770 struct arm
*arm
= dpm
->arm
;
771 struct target
*target
= arm
->target
;
772 struct reg_cache
*cache
;
776 /* register access setup */
777 arm
->full_context
= arm_dpm_full_context
;
778 arm
->read_core_reg
= arm_dpm_read_core_reg
;
779 arm
->write_core_reg
= arm_dpm_write_core_reg
;
781 cache
= armv4_5_build_reg_cache(target
, arm
);
785 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
787 /* coprocessor access setup */
791 /* breakpoint and watchpoint setup */
792 target
->type
->add_watchpoint
= dpm_add_watchpoint
;
793 target
->type
->remove_watchpoint
= dpm_remove_watchpoint
;
795 /* FIXME add breakpoint support */
796 /* FIXME add vector catch support */
798 dpm
->nbp
= 1 + ((dpm
->didr
>> 24) & 0xf);
799 dpm
->dbp
= calloc(dpm
->nbp
, sizeof *dpm
->dbp
);
801 dpm
->nwp
= 1 + ((dpm
->didr
>> 28) & 0xf);
802 dpm
->dwp
= calloc(dpm
->nwp
, sizeof *dpm
->dwp
);
804 if (!dpm
->dbp
|| !dpm
->dwp
) {
810 /* Disable all breakpoints and watchpoints at startup. */
811 if (dpm
->bpwp_disable
) {
814 for (i
= 0; i
< dpm
->nbp
; i
++)
815 (void) dpm
->bpwp_disable(dpm
, i
);
816 for (i
= 0; i
< dpm
->nwp
; i
++)
817 (void) dpm
->bpwp_disable(dpm
, 16 + i
);
819 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
820 target_name(target
));
822 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
823 target_name(target
), dpm
->nbp
, dpm
->nwp
);
825 /* REVISIT ... and some of those breakpoints could match
826 * execution context IDs...
833 * Reinitializes DPM state at the beginning of a new debug session
834 * or after a reset which may have affected the debug module.
836 int arm_dpm_initialize(struct arm_dpm
*dpm
)
838 /* FIXME -- nothing yet */
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)