armv8_dpm: retrieve only necessary registers on halt
[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 #include "helper/time_support.h"
30
31 /* T32 ITR format */
32 #define T32_FMTITR(instr) (((instr & 0x0000FFFF) << 16) | ((instr & 0xFFFF0000) >> 16))
33
34 /**
35 * @file
36 * Implements various ARM DPM operations using architectural debug registers.
37 * These routines layer over core-specific communication methods to cope with
38 * implementation differences between cores like ARM1136 and Cortex-A8.
39 *
40 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
41 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
42 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
43 * are abstracted through internal programming interfaces to share code and
44 * to minimize needless differences in debug behavior between cores.
45 */
46
47 /**
48 * Get core state from EDSCR, without necessity to retrieve CPSR
49 */
50 enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm)
51 {
52 int el = (dpm->dscr >> 8) & 0x3;
53 int rw = (dpm->dscr >> 10) & 0xF;
54
55 dpm->last_el = el;
56
57 /* In Debug state, each bit gives the current Execution state of each EL */
58 if ((rw >> el) & 0b1)
59 return ARM_STATE_AARCH64;
60
61 return ARM_STATE_ARM;
62 }
63
64 /*----------------------------------------------------------------------*/
65
66 static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data)
67 {
68 return mem_ap_write_u32(armv8->debug_ap,
69 armv8->debug_base + CPUV8_DBG_DTRRX, data);
70 }
71
72 static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data)
73 {
74 int ret;
75 ret = mem_ap_write_u32(armv8->debug_ap,
76 armv8->debug_base + CPUV8_DBG_DTRRX, data);
77 if (ret == ERROR_OK)
78 ret = mem_ap_write_u32(armv8->debug_ap,
79 armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32);
80 return ret;
81 }
82
83 static int dpmv8_read_dcc(struct armv8_common *armv8, uint32_t *data,
84 uint32_t *dscr_p)
85 {
86 uint32_t dscr = DSCR_ITE;
87 int retval;
88
89 if (dscr_p)
90 dscr = *dscr_p;
91
92 /* Wait for DTRRXfull */
93 long long then = timeval_ms();
94 while ((dscr & DSCR_DTR_TX_FULL) == 0) {
95 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
96 armv8->debug_base + CPUV8_DBG_DSCR,
97 &dscr);
98 if (retval != ERROR_OK)
99 return retval;
100 if (timeval_ms() > then + 1000) {
101 LOG_ERROR("Timeout waiting for read dcc");
102 return ERROR_FAIL;
103 }
104 }
105
106 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
107 armv8->debug_base + CPUV8_DBG_DTRTX,
108 data);
109 if (retval != ERROR_OK)
110 return retval;
111
112 if (dscr_p)
113 *dscr_p = dscr;
114
115 return retval;
116 }
117
118 static int dpmv8_read_dcc_64(struct armv8_common *armv8, uint64_t *data,
119 uint32_t *dscr_p)
120 {
121 uint32_t dscr = DSCR_ITE;
122 uint32_t higher;
123 int retval;
124
125 if (dscr_p)
126 dscr = *dscr_p;
127
128 /* Wait for DTRRXfull */
129 long long then = timeval_ms();
130 while ((dscr & DSCR_DTR_TX_FULL) == 0) {
131 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
132 armv8->debug_base + CPUV8_DBG_DSCR,
133 &dscr);
134 if (retval != ERROR_OK)
135 return retval;
136 if (timeval_ms() > then + 1000) {
137 LOG_ERROR("Timeout waiting for DTR_TX_FULL, dscr = 0x%08" PRIx32, dscr);
138 return ERROR_FAIL;
139 }
140 }
141
142 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
143 armv8->debug_base + CPUV8_DBG_DTRTX,
144 (uint32_t *)data);
145 if (retval != ERROR_OK)
146 return retval;
147
148 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
149 armv8->debug_base + CPUV8_DBG_DTRRX,
150 &higher);
151 if (retval != ERROR_OK)
152 return retval;
153
154 *data = *(uint32_t *)data | (uint64_t)higher << 32;
155
156 if (dscr_p)
157 *dscr_p = dscr;
158
159 return retval;
160 }
161
162 static int dpmv8_dpm_prepare(struct arm_dpm *dpm)
163 {
164 struct armv8_common *armv8 = dpm->arm->arch_info;
165 uint32_t dscr;
166 int retval;
167
168 /* set up invariant: ITE is set after ever DPM operation */
169 long long then = timeval_ms();
170 for (;; ) {
171 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
172 armv8->debug_base + CPUV8_DBG_DSCR,
173 &dscr);
174 if (retval != ERROR_OK)
175 return retval;
176 if ((dscr & DSCR_ITE) != 0)
177 break;
178 if (timeval_ms() > then + 1000) {
179 LOG_ERROR("Timeout waiting for dpm prepare");
180 return ERROR_FAIL;
181 }
182 }
183
184 /* update the stored copy of dscr */
185 dpm->dscr = dscr;
186
187 /* this "should never happen" ... */
188 if (dscr & DSCR_DTR_RX_FULL) {
189 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
190 /* Clear DCCRX */
191 retval = mem_ap_read_u32(armv8->debug_ap,
192 armv8->debug_base + CPUV8_DBG_DTRRX, &dscr);
193 if (retval != ERROR_OK)
194 return retval;
195 }
196
197 return retval;
198 }
199
200 static int dpmv8_dpm_finish(struct arm_dpm *dpm)
201 {
202 /* REVISIT what could be done here? */
203 return ERROR_OK;
204 }
205
206 static int dpmv8_exec_opcode(struct arm_dpm *dpm,
207 uint32_t opcode, uint32_t *p_dscr)
208 {
209 struct armv8_common *armv8 = dpm->arm->arch_info;
210 uint32_t dscr = dpm->dscr;
211 int retval;
212
213 if (p_dscr)
214 dscr = *p_dscr;
215
216 /* Wait for InstrCompl bit to be set */
217 long long then = timeval_ms();
218 while ((dscr & DSCR_ITE) == 0) {
219 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
220 armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
221 if (retval != ERROR_OK) {
222 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
223 return retval;
224 }
225 if (timeval_ms() > then + 1000) {
226 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
227 return ERROR_FAIL;
228 }
229 }
230
231 if (armv8_dpm_get_core_state(dpm) != ARM_STATE_AARCH64)
232 opcode = T32_FMTITR(opcode);
233
234 retval = mem_ap_write_u32(armv8->debug_ap,
235 armv8->debug_base + CPUV8_DBG_ITR, opcode);
236 if (retval != ERROR_OK)
237 return retval;
238
239 then = timeval_ms();
240 do {
241 retval = mem_ap_read_atomic_u32(armv8->debug_ap,
242 armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
243 if (retval != ERROR_OK) {
244 LOG_ERROR("Could not read DSCR register");
245 return retval;
246 }
247 if (timeval_ms() > then + 1000) {
248 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
249 return ERROR_FAIL;
250 }
251 } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */
252
253 /* update dscr and el after each command execution */
254 dpm->dscr = dscr;
255 if (dpm->last_el != ((dscr >> 8) & 3))
256 LOG_DEBUG("EL %i -> %i", dpm->last_el, (dscr >> 8) & 3);
257 dpm->last_el = (dscr >> 8) & 3;
258
259 if (dscr & DSCR_ERR) {
260 LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
261 armv8_dpm_handle_exception(dpm);
262 retval = ERROR_FAIL;
263 }
264
265 if (p_dscr)
266 *p_dscr = dscr;
267
268 return retval;
269 }
270
271 static int dpmv8_instr_execute(struct arm_dpm *dpm, uint32_t opcode)
272 {
273 return dpmv8_exec_opcode(dpm, opcode, NULL);
274 }
275
276 static int dpmv8_instr_write_data_dcc(struct arm_dpm *dpm,
277 uint32_t opcode, uint32_t data)
278 {
279 struct armv8_common *armv8 = dpm->arm->arch_info;
280 int retval;
281
282 retval = dpmv8_write_dcc(armv8, data);
283 if (retval != ERROR_OK)
284 return retval;
285
286 return dpmv8_exec_opcode(dpm, opcode, 0);
287 }
288
289 static int dpmv8_instr_write_data_dcc_64(struct arm_dpm *dpm,
290 uint32_t opcode, uint64_t data)
291 {
292 struct armv8_common *armv8 = dpm->arm->arch_info;
293 int retval;
294
295 retval = dpmv8_write_dcc_64(armv8, data);
296 if (retval != ERROR_OK)
297 return retval;
298
299 return dpmv8_exec_opcode(dpm, opcode, 0);
300 }
301
302 static int dpmv8_instr_write_data_r0(struct arm_dpm *dpm,
303 uint32_t opcode, uint32_t data)
304 {
305 struct armv8_common *armv8 = dpm->arm->arch_info;
306 uint32_t dscr = DSCR_ITE;
307 int retval;
308
309 retval = dpmv8_write_dcc(armv8, data);
310 if (retval != ERROR_OK)
311 return retval;
312
313 retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, READ_REG_DTRRX), &dscr);
314 if (retval != ERROR_OK)
315 return retval;
316
317 /* then the opcode, taking data from R0 */
318 return dpmv8_exec_opcode(dpm, opcode, &dscr);
319 }
320
321 static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm,
322 uint32_t opcode, uint64_t data)
323 {
324 struct armv8_common *armv8 = dpm->arm->arch_info;
325 int retval;
326
327 if (dpm->arm->core_state != ARM_STATE_AARCH64)
328 return dpmv8_instr_write_data_r0(dpm, opcode, data);
329
330 /* transfer data from DCC to R0 */
331 retval = dpmv8_write_dcc_64(armv8, data);
332 if (retval == ERROR_OK)
333 retval = dpmv8_exec_opcode(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dpm->dscr);
334
335 /* then the opcode, taking data from R0 */
336 if (retval == ERROR_OK)
337 retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr);
338
339 return retval;
340 }
341
342 static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm)
343 {
344 int retval;
345 struct armv8_common *armv8 = dpm->arm->arch_info;
346
347 /* "Prefetch flush" after modifying execution status in CPSR */
348 retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), &dpm->dscr);
349 if (retval == ERROR_OK)
350 dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_ISB_SY), &dpm->dscr);
351 return retval;
352 }
353
354 static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm,
355 uint32_t opcode, uint32_t *data)
356 {
357 struct armv8_common *armv8 = dpm->arm->arch_info;
358 int retval;
359
360 /* the opcode, writing data to DCC */
361 retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr);
362 if (retval != ERROR_OK)
363 return retval;
364
365 return dpmv8_read_dcc(armv8, data, &dpm->dscr);
366 }
367
368 static int dpmv8_instr_read_data_dcc_64(struct arm_dpm *dpm,
369 uint32_t opcode, uint64_t *data)
370 {
371 struct armv8_common *armv8 = dpm->arm->arch_info;
372 int retval;
373
374 /* the opcode, writing data to DCC */
375 retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr);
376 if (retval != ERROR_OK)
377 return retval;
378
379 return dpmv8_read_dcc_64(armv8, data, &dpm->dscr);
380 }
381
382 static int dpmv8_instr_read_data_r0(struct arm_dpm *dpm,
383 uint32_t opcode, uint32_t *data)
384 {
385 struct armv8_common *armv8 = dpm->arm->arch_info;
386 int retval;
387
388 /* the opcode, writing data to R0 */
389 retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr);
390 if (retval != ERROR_OK)
391 return retval;
392
393 /* write R0 to DCC */
394 retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, WRITE_REG_DTRTX), &dpm->dscr);
395 if (retval != ERROR_OK)
396 return retval;
397
398 return dpmv8_read_dcc(armv8, data, &dpm->dscr);
399 }
400
401 static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm,
402 uint32_t opcode, uint64_t *data)
403 {
404 struct armv8_common *armv8 = dpm->arm->arch_info;
405 int retval;
406
407 if (dpm->arm->core_state != ARM_STATE_AARCH64) {
408 uint32_t tmp;
409 retval = dpmv8_instr_read_data_r0(dpm, opcode, &tmp);
410 if (retval == ERROR_OK)
411 *data = tmp;
412 return retval;
413 }
414
415 /* the opcode, writing data to R0 */
416 retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr);
417 if (retval != ERROR_OK)
418 return retval;
419
420 /* write R0 to DCC */
421 retval = dpmv8_exec_opcode(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dpm->dscr);
422 if (retval != ERROR_OK)
423 return retval;
424
425 return dpmv8_read_dcc_64(armv8, data, &dpm->dscr);
426 }
427
428 #if 0
429 static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
430 target_addr_t addr, uint32_t control)
431 {
432 struct armv8_common *armv8 = dpm->arm->arch_info;
433 uint32_t vr = armv8->debug_base;
434 uint32_t cr = armv8->debug_base;
435 int retval;
436
437 switch (index_t) {
438 case 0 ... 15: /* breakpoints */
439 vr += CPUV8_DBG_BVR_BASE;
440 cr += CPUV8_DBG_BCR_BASE;
441 break;
442 case 16 ... 31: /* watchpoints */
443 vr += CPUV8_DBG_WVR_BASE;
444 cr += CPUV8_DBG_WCR_BASE;
445 index_t -= 16;
446 break;
447 default:
448 return ERROR_FAIL;
449 }
450 vr += 16 * index_t;
451 cr += 16 * index_t;
452
453 LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
454 (unsigned) vr, (unsigned) cr);
455
456 retval = mem_ap_write_atomic_u32(armv8->debug_ap, vr, addr);
457 if (retval != ERROR_OK)
458 return retval;
459 return mem_ap_write_atomic_u32(armv8->debug_ap, cr, control);
460 }
461 #endif
462
463 static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
464 {
465 struct armv8_common *armv8 = dpm->arm->arch_info;
466 uint32_t cr;
467
468 switch (index_t) {
469 case 0 ... 15:
470 cr = armv8->debug_base + CPUV8_DBG_BCR_BASE;
471 break;
472 case 16 ... 31:
473 cr = armv8->debug_base + CPUV8_DBG_WCR_BASE;
474 index_t -= 16;
475 break;
476 default:
477 return ERROR_FAIL;
478 }
479 cr += 16 * index_t;
480
481 LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr);
482
483 /* clear control register */
484 return mem_ap_write_atomic_u32(armv8->debug_ap, cr, 0);
485 }
486
487 /*
488 * Coprocessor support
489 */
490
491 /* Read coprocessor */
492 static int dpmv8_mrc(struct target *target, int cpnum,
493 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
494 uint32_t *value)
495 {
496 struct arm *arm = target_to_arm(target);
497 struct arm_dpm *dpm = arm->dpm;
498 int retval;
499
500 retval = dpm->prepare(dpm);
501 if (retval != ERROR_OK)
502 return retval;
503
504 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
505 (int) op1, (int) CRn,
506 (int) CRm, (int) op2);
507
508 /* read coprocessor register into R0; return via DCC */
509 retval = dpm->instr_read_data_r0(dpm,
510 ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
511 value);
512
513 /* (void) */ dpm->finish(dpm);
514 return retval;
515 }
516
517 static int dpmv8_mcr(struct target *target, int cpnum,
518 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
519 uint32_t value)
520 {
521 struct arm *arm = target_to_arm(target);
522 struct arm_dpm *dpm = arm->dpm;
523 int retval;
524
525 retval = dpm->prepare(dpm);
526 if (retval != ERROR_OK)
527 return retval;
528
529 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
530 (int) op1, (int) CRn,
531 (int) CRm, (int) op2);
532
533 /* read DCC into r0; then write coprocessor register from R0 */
534 retval = dpm->instr_write_data_r0(dpm,
535 ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
536 value);
537
538 /* (void) */ dpm->finish(dpm);
539 return retval;
540 }
541
542 /*----------------------------------------------------------------------*/
543
544 /*
545 * Register access utilities
546 */
547
548 int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
549 {
550 struct armv8_common *armv8 = (struct armv8_common *)dpm->arm->arch_info;
551 int retval = ERROR_OK;
552 unsigned int target_el;
553 enum arm_state core_state;
554 uint32_t cpsr;
555
556 /* restore previous mode */
557 if (mode == ARM_MODE_ANY) {
558 cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32);
559
560 LOG_DEBUG("restoring mode, cpsr = 0x%08"PRIx32, cpsr);
561
562 } else {
563 LOG_DEBUG("setting mode 0x%"PRIx32, mode);
564
565 /* else force to the specified mode */
566 if (is_arm_mode(mode))
567 cpsr = mode;
568 else
569 cpsr = mode >> 4;
570 }
571
572 switch (cpsr & 0x1f) {
573 /* aarch32 modes */
574 case ARM_MODE_USR:
575 target_el = 0;
576 break;
577 case ARM_MODE_SVC:
578 case ARM_MODE_ABT:
579 case ARM_MODE_IRQ:
580 case ARM_MODE_FIQ:
581 target_el = 1;
582 break;
583 /*
584 * TODO: handle ARM_MODE_HYP
585 * case ARM_MODE_HYP:
586 * target_el = 2;
587 * break;
588 */
589 case ARM_MODE_MON:
590 target_el = 3;
591 break;
592 /* aarch64 modes */
593 default:
594 target_el = (cpsr >> 2) & 3;
595 }
596
597 if (target_el > SYSTEM_CUREL_EL3) {
598 LOG_ERROR("%s: Invalid target exception level %i", __func__, target_el);
599 return ERROR_FAIL;
600 }
601
602 LOG_DEBUG("target_el = %i, last_el = %i", target_el, dpm->last_el);
603 if (target_el > dpm->last_el) {
604 retval = dpm->instr_execute(dpm,
605 armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);
606
607 /* DCPS clobbers registers just like an exception taken */
608 armv8_dpm_handle_exception(dpm);
609 } else {
610 core_state = armv8_dpm_get_core_state(dpm);
611 if (core_state != ARM_STATE_AARCH64) {
612 /* cannot do DRPS/ERET when already in EL0 */
613 if (dpm->last_el != 0) {
614 /* load SPSR with the desired mode and execute DRPS */
615 LOG_DEBUG("SPSR = 0x%08"PRIx32, cpsr);
616 retval = dpm->instr_write_data_r0(dpm,
617 ARMV8_MSR_GP_xPSR_T1(1, 0, 15), cpsr);
618 if (retval == ERROR_OK)
619 retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_DRPS));
620 }
621 } else {
622 /*
623 * need to execute multiple DRPS instructions until target_el
624 * is reached
625 */
626 while (retval == ERROR_OK && dpm->last_el != target_el) {
627 unsigned int cur_el = dpm->last_el;
628 retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_DRPS));
629 if (cur_el == dpm->last_el) {
630 LOG_INFO("Cannot reach EL %i, SPSR corrupted?", target_el);
631 break;
632 }
633 }
634 }
635
636 /* On executing DRPS, DSPSR and DLR become UNKNOWN, mark them as dirty */
637 dpm->arm->cpsr->dirty = true;
638 dpm->arm->pc->dirty = true;
639
640 /*
641 * re-evaluate the core state, we might be in Aarch32 state now
642 * we rely on dpm->dscr being up-to-date
643 */
644 core_state = armv8_dpm_get_core_state(dpm);
645 armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
646 armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
647 }
648
649 return retval;
650 }
651
652 /*
653 * Common register read, relies on armv8_select_reg_access() having been called.
654 */
655 static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
656 {
657 struct armv8_common *armv8 = dpm->arm->arch_info;
658 uint64_t value_64;
659 int retval;
660
661 retval = armv8->read_reg_u64(armv8, regnum, &value_64);
662
663 if (retval == ERROR_OK) {
664 r->valid = true;
665 r->dirty = false;
666 buf_set_u64(r->value, 0, r->size, value_64);
667 if (r->size == 64)
668 LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
669 else
670 LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64);
671 }
672 return ERROR_OK;
673 }
674
675 /*
676 * Common register write, relies on armv8_select_reg_access() having been called.
677 */
678 static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
679 {
680 struct armv8_common *armv8 = dpm->arm->arch_info;
681 int retval = ERROR_FAIL;
682 uint64_t value_64;
683
684 value_64 = buf_get_u64(r->value, 0, r->size);
685
686 retval = armv8->write_reg_u64(armv8, regnum, value_64);
687 if (retval == ERROR_OK) {
688 r->dirty = false;
689 if (r->size == 64)
690 LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64);
691 else
692 LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64);
693 }
694
695 return ERROR_OK;
696 }
697
698 /**
699 * Read basic registers of the the current context: R0 to R15, and CPSR;
700 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
701 * In normal operation this is called on entry to halting debug state,
702 * possibly after some other operations supporting restore of debug state
703 * or making sure the CPU is fully idle (drain write buffer, etc).
704 */
705 int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
706 {
707 struct arm *arm = dpm->arm;
708 struct armv8_common *armv8 = (struct armv8_common *)arm->arch_info;
709 struct reg_cache *cache;
710 struct reg *r;
711 uint32_t cpsr;
712 int retval;
713
714 retval = dpm->prepare(dpm);
715 if (retval != ERROR_OK)
716 return retval;
717
718 cache = arm->core_cache;
719
720 /* read R0 first (it's used for scratch), then CPSR */
721 r = cache->reg_list + ARMV8_R0;
722 if (!r->valid) {
723 retval = dpmv8_read_reg(dpm, r, ARMV8_R0);
724 if (retval != ERROR_OK)
725 goto fail;
726 }
727 r->dirty = true;
728
729 /* read R1, too, it will be clobbered during memory access */
730 r = cache->reg_list + ARMV8_R1;
731 if (!r->valid) {
732 retval = dpmv8_read_reg(dpm, r, ARMV8_R1);
733 if (retval != ERROR_OK)
734 goto fail;
735 }
736
737 /* read cpsr to r0 and get it back */
738 retval = dpm->instr_read_data_r0(dpm,
739 armv8_opcode(armv8, READ_REG_DSPSR), &cpsr);
740 if (retval != ERROR_OK)
741 goto fail;
742
743 /* update core mode and state */
744 armv8_set_cpsr(arm, cpsr);
745
746 for (unsigned int i = ARMV8_PC; i < cache->num_regs ; i++) {
747 struct arm_reg *arm_reg;
748
749 r = armv8_reg_current(arm, i);
750 if (r->valid)
751 continue;
752
753 /*
754 * Only read registers that are available from the
755 * current EL (or core mode).
756 */
757 arm_reg = r->arch_info;
758 if (arm_reg->mode != ARM_MODE_ANY &&
759 dpm->last_el != armv8_curel_from_core_mode(arm_reg->mode))
760 continue;
761
762 retval = dpmv8_read_reg(dpm, r, i);
763 if (retval != ERROR_OK)
764 goto fail;
765
766 }
767
768 fail:
769 dpm->finish(dpm);
770 return retval;
771 }
772
773 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
774 * unless they're removed, or need updating because of single-stepping
775 * or running debugger code.
776 */
777 static int dpmv8_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
778 struct dpm_bpwp *xp, int *set_p)
779 {
780 int retval = ERROR_OK;
781 bool disable;
782
783 if (!set_p) {
784 if (!xp->dirty)
785 goto done;
786 xp->dirty = false;
787 /* removed or startup; we must disable it */
788 disable = true;
789 } else if (bpwp) {
790 if (!xp->dirty)
791 goto done;
792 /* disabled, but we must set it */
793 xp->dirty = disable = false;
794 *set_p = true;
795 } else {
796 if (!*set_p)
797 goto done;
798 /* set, but we must temporarily disable it */
799 xp->dirty = disable = true;
800 *set_p = false;
801 }
802
803 if (disable)
804 retval = dpm->bpwp_disable(dpm, xp->number);
805 else
806 retval = dpm->bpwp_enable(dpm, xp->number,
807 xp->address, xp->control);
808
809 if (retval != ERROR_OK)
810 LOG_ERROR("%s: can't %s HW %spoint %d",
811 disable ? "disable" : "enable",
812 target_name(dpm->arm->target),
813 (xp->number < 16) ? "break" : "watch",
814 xp->number & 0xf);
815 done:
816 return retval;
817 }
818
819 static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp);
820
821 /**
822 * Writes all modified core registers for all processor modes. In normal
823 * operation this is called on exit from halting debug state.
824 *
825 * @param dpm: represents the processor
826 * @param bpwp: true ensures breakpoints and watchpoints are set,
827 * false ensures they are cleared
828 */
829 int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
830 {
831 struct arm *arm = dpm->arm;
832 struct reg_cache *cache = arm->core_cache;
833 int retval;
834
835 retval = dpm->prepare(dpm);
836 if (retval != ERROR_OK)
837 goto done;
838
839 /* If we're managing hardware breakpoints for this core, enable
840 * or disable them as requested.
841 *
842 * REVISIT We don't yet manage them for ANY cores. Eventually
843 * we should be able to assume we handle them; but until then,
844 * cope with the hand-crafted breakpoint code.
845 */
846 if (arm->target->type->add_breakpoint == dpmv8_add_breakpoint) {
847 for (unsigned i = 0; i < dpm->nbp; i++) {
848 struct dpm_bp *dbp = dpm->dbp + i;
849 struct breakpoint *bp = dbp->bp;
850
851 retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
852 bp ? &bp->set : NULL);
853 if (retval != ERROR_OK)
854 goto done;
855 }
856 }
857
858 /* enable/disable watchpoints */
859 for (unsigned i = 0; i < dpm->nwp; i++) {
860 struct dpm_wp *dwp = dpm->dwp + i;
861 struct watchpoint *wp = dwp->wp;
862
863 retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
864 wp ? &wp->set : NULL);
865 if (retval != ERROR_OK)
866 goto done;
867 }
868
869 /* NOTE: writes to breakpoint and watchpoint registers might
870 * be queued, and need (efficient/batched) flushing later.
871 */
872
873 /* Restore original core mode and state */
874 retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
875 if (retval != ERROR_OK)
876 goto done;
877
878 /* check everything except our scratch register R0 */
879 for (unsigned i = 1; i < cache->num_regs; i++) {
880 struct arm_reg *r;
881
882 /* skip PC and CPSR */
883 if (i == ARMV8_PC || i == ARMV8_xPSR)
884 continue;
885 /* skip invalid */
886 if (!cache->reg_list[i].valid)
887 continue;
888 /* skip non-dirty */
889 if (!cache->reg_list[i].dirty)
890 continue;
891
892 /* skip all registers not on the current EL */
893 r = cache->reg_list[i].arch_info;
894 if (r->mode != ARM_MODE_ANY &&
895 dpm->last_el != armv8_curel_from_core_mode(r->mode))
896 continue;
897
898 retval = dpmv8_write_reg(dpm, &cache->reg_list[i], i);
899 if (retval != ERROR_OK)
900 break;
901 }
902
903 /* flush CPSR and PC */
904 if (retval == ERROR_OK)
905 retval = dpmv8_write_reg(dpm, &cache->reg_list[ARMV8_xPSR], ARMV8_xPSR);
906 if (retval == ERROR_OK)
907 retval = dpmv8_write_reg(dpm, &cache->reg_list[ARMV8_PC], ARMV8_PC);
908 /* flush R0 -- it's *very* dirty by now */
909 if (retval == ERROR_OK)
910 retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0);
911 if (retval == ERROR_OK)
912 dpm->instr_cpsr_sync(dpm);
913 done:
914 dpm->finish(dpm);
915 return retval;
916 }
917
918 /*
919 * Standard ARM register accessors ... there are three methods
920 * in "struct arm", to support individual read/write and bulk read
921 * of registers.
922 */
923
924 static int armv8_dpm_read_core_reg(struct target *target, struct reg *r,
925 int regnum, enum arm_mode mode)
926 {
927 struct arm *arm = target_to_arm(target);
928 struct arm_dpm *dpm = target_to_arm(target)->dpm;
929 int retval;
930 int max = arm->core_cache->num_regs;
931
932 if (regnum < 0 || regnum >= max)
933 return ERROR_COMMAND_SYNTAX_ERROR;
934
935 /*
936 * REVISIT what happens if we try to read SPSR in a core mode
937 * which has no such register?
938 */
939 retval = dpm->prepare(dpm);
940 if (retval != ERROR_OK)
941 return retval;
942
943 retval = dpmv8_read_reg(dpm, r, regnum);
944 if (retval != ERROR_OK)
945 goto fail;
946
947 fail:
948 /* (void) */ dpm->finish(dpm);
949 return retval;
950 }
951
952 static int armv8_dpm_write_core_reg(struct target *target, struct reg *r,
953 int regnum, enum arm_mode mode, uint8_t *value)
954 {
955 struct arm *arm = target_to_arm(target);
956 struct arm_dpm *dpm = target_to_arm(target)->dpm;
957 int retval;
958 int max = arm->core_cache->num_regs;
959
960 if (regnum < 0 || regnum > max)
961 return ERROR_COMMAND_SYNTAX_ERROR;
962
963 /* REVISIT what happens if we try to write SPSR in a core mode
964 * which has no such register?
965 */
966
967 retval = dpm->prepare(dpm);
968 if (retval != ERROR_OK)
969 return retval;
970
971 retval = dpmv8_write_reg(dpm, r, regnum);
972
973 /* always clean up, regardless of error */
974 dpm->finish(dpm);
975
976 return retval;
977 }
978
979 static int armv8_dpm_full_context(struct target *target)
980 {
981 struct arm *arm = target_to_arm(target);
982 struct arm_dpm *dpm = arm->dpm;
983 struct reg_cache *cache = arm->core_cache;
984 int retval;
985 bool did_read;
986
987 retval = dpm->prepare(dpm);
988 if (retval != ERROR_OK)
989 goto done;
990
991 do {
992 enum arm_mode mode = ARM_MODE_ANY;
993
994 did_read = false;
995
996 /* We "know" arm_dpm_read_current_registers() was called so
997 * the unmapped registers (R0..R7, PC, AND CPSR) and some
998 * view of R8..R14 are current. We also "know" oddities of
999 * register mapping: special cases for R8..R12 and SPSR.
1000 *
1001 * Pick some mode with unread registers and read them all.
1002 * Repeat until done.
1003 */
1004 for (unsigned i = 0; i < cache->num_regs; i++) {
1005 struct arm_reg *r;
1006
1007 if (cache->reg_list[i].valid)
1008 continue;
1009 r = cache->reg_list[i].arch_info;
1010
1011 /* may need to pick a mode and set CPSR */
1012 if (!did_read) {
1013 did_read = true;
1014 mode = r->mode;
1015
1016 /* For regular (ARM_MODE_ANY) R8..R12
1017 * in case we've entered debug state
1018 * in FIQ mode we need to patch mode.
1019 */
1020 if (mode != ARM_MODE_ANY)
1021 retval = armv8_dpm_modeswitch(dpm, mode);
1022 else
1023 retval = armv8_dpm_modeswitch(dpm, ARM_MODE_USR);
1024
1025 if (retval != ERROR_OK)
1026 goto done;
1027 }
1028 if (r->mode != mode)
1029 continue;
1030
1031 /* CPSR was read, so "R16" must mean SPSR */
1032 retval = dpmv8_read_reg(dpm,
1033 &cache->reg_list[i],
1034 (r->num == 16) ? 17 : r->num);
1035 if (retval != ERROR_OK)
1036 goto done;
1037 }
1038
1039 } while (did_read);
1040
1041 retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
1042 /* (void) */ dpm->finish(dpm);
1043 done:
1044 return retval;
1045 }
1046
1047
1048 /*----------------------------------------------------------------------*/
1049
1050 /*
1051 * Breakpoint and Watchpoint support.
1052 *
1053 * Hardware {break,watch}points are usually left active, to minimize
1054 * debug entry/exit costs. When they are set or cleared, it's done in
1055 * batches. Also, DPM-conformant hardware can update debug registers
1056 * regardless of whether the CPU is running or halted ... though that
1057 * fact isn't currently leveraged.
1058 */
1059
1060 static int dpmv8_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
1061 uint32_t addr, uint32_t length)
1062 {
1063 uint32_t control;
1064
1065 control = (1 << 0) /* enable */
1066 | (3 << 1); /* both user and privileged access */
1067
1068 /* Match 1, 2, or all 4 byte addresses in this word.
1069 *
1070 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
1071 * Support larger length, when addr is suitably aligned. In
1072 * particular, allow watchpoints on 8 byte "double" values.
1073 *
1074 * REVISIT allow watchpoints on unaligned 2-bit values; and on
1075 * v7 hardware, unaligned 4-byte ones too.
1076 */
1077 switch (length) {
1078 case 1:
1079 control |= (1 << (addr & 3)) << 5;
1080 break;
1081 case 2:
1082 /* require 2-byte alignment */
1083 if (!(addr & 1)) {
1084 control |= (3 << (addr & 2)) << 5;
1085 break;
1086 }
1087 /* FALL THROUGH */
1088 case 4:
1089 /* require 4-byte alignment */
1090 if (!(addr & 3)) {
1091 control |= 0xf << 5;
1092 break;
1093 }
1094 /* FALL THROUGH */
1095 default:
1096 LOG_ERROR("unsupported {break,watch}point length/alignment");
1097 return ERROR_COMMAND_SYNTAX_ERROR;
1098 }
1099
1100 /* other shared control bits:
1101 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
1102 * bit 20 == 0 ... not linked to a context ID
1103 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
1104 */
1105
1106 xp->address = addr & ~3;
1107 xp->control = control;
1108 xp->dirty = true;
1109
1110 LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
1111 xp->address, control, xp->number);
1112
1113 /* hardware is updated in write_dirty_registers() */
1114 return ERROR_OK;
1115 }
1116
1117 static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp)
1118 {
1119 struct arm *arm = target_to_arm(target);
1120 struct arm_dpm *dpm = arm->dpm;
1121 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1122
1123 if (bp->length < 2)
1124 return ERROR_COMMAND_SYNTAX_ERROR;
1125 if (!dpm->bpwp_enable)
1126 return retval;
1127
1128 /* FIXME we need a generic solution for software breakpoints. */
1129 if (bp->type == BKPT_SOFT)
1130 LOG_DEBUG("using HW bkpt, not SW...");
1131
1132 for (unsigned i = 0; i < dpm->nbp; i++) {
1133 if (!dpm->dbp[i].bp) {
1134 retval = dpmv8_bpwp_setup(dpm, &dpm->dbp[i].bpwp,
1135 bp->address, bp->length);
1136 if (retval == ERROR_OK)
1137 dpm->dbp[i].bp = bp;
1138 break;
1139 }
1140 }
1141
1142 return retval;
1143 }
1144
1145 static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp)
1146 {
1147 struct arm *arm = target_to_arm(target);
1148 struct arm_dpm *dpm = arm->dpm;
1149 int retval = ERROR_COMMAND_SYNTAX_ERROR;
1150
1151 for (unsigned i = 0; i < dpm->nbp; i++) {
1152 if (dpm->dbp[i].bp == bp) {
1153 dpm->dbp[i].bp = NULL;
1154 dpm->dbp[i].bpwp.dirty = true;
1155
1156 /* hardware is updated in write_dirty_registers() */
1157 retval = ERROR_OK;
1158 break;
1159 }
1160 }
1161
1162 return retval;
1163 }
1164
1165 static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
1166 struct watchpoint *wp)
1167 {
1168 int retval;
1169 struct dpm_wp *dwp = dpm->dwp + index_t;
1170 uint32_t control;
1171
1172 /* this hardware doesn't support data value matching or masking */
1173 if (wp->value || wp->mask != ~(uint32_t)0) {
1174 LOG_DEBUG("watchpoint values and masking not supported");
1175 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1176 }
1177
1178 retval = dpmv8_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length);
1179 if (retval != ERROR_OK)
1180 return retval;
1181
1182 control = dwp->bpwp.control;
1183 switch (wp->rw) {
1184 case WPT_READ:
1185 control |= 1 << 3;
1186 break;
1187 case WPT_WRITE:
1188 control |= 2 << 3;
1189 break;
1190 case WPT_ACCESS:
1191 control |= 3 << 3;
1192 break;
1193 }
1194 dwp->bpwp.control = control;
1195
1196 dpm->dwp[index_t].wp = wp;
1197
1198 return retval;
1199 }
1200
1201 static int dpmv8_add_watchpoint(struct target *target, struct watchpoint *wp)
1202 {
1203 struct arm *arm = target_to_arm(target);
1204 struct arm_dpm *dpm = arm->dpm;
1205 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1206
1207 if (dpm->bpwp_enable) {
1208 for (unsigned i = 0; i < dpm->nwp; i++) {
1209 if (!dpm->dwp[i].wp) {
1210 retval = dpmv8_watchpoint_setup(dpm, i, wp);
1211 break;
1212 }
1213 }
1214 }
1215
1216 return retval;
1217 }
1218
1219 static int dpmv8_remove_watchpoint(struct target *target, struct watchpoint *wp)
1220 {
1221 struct arm *arm = target_to_arm(target);
1222 struct arm_dpm *dpm = arm->dpm;
1223 int retval = ERROR_COMMAND_SYNTAX_ERROR;
1224
1225 for (unsigned i = 0; i < dpm->nwp; i++) {
1226 if (dpm->dwp[i].wp == wp) {
1227 dpm->dwp[i].wp = NULL;
1228 dpm->dwp[i].bpwp.dirty = true;
1229
1230 /* hardware is updated in write_dirty_registers() */
1231 retval = ERROR_OK;
1232 break;
1233 }
1234 }
1235
1236 return retval;
1237 }
1238
1239 void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr)
1240 {
1241 switch (dpm->arm->core_state) {
1242 case ARM_STATE_ARM:
1243 case ARM_STATE_AARCH64:
1244 addr -= 8;
1245 break;
1246 case ARM_STATE_THUMB:
1247 case ARM_STATE_THUMB_EE:
1248 addr -= 4;
1249 break;
1250 case ARM_STATE_JAZELLE:
1251 /* ?? */
1252 break;
1253 default:
1254 LOG_DEBUG("Unknown core_state");
1255 break;
1256 }
1257 dpm->wp_pc = addr;
1258 }
1259
1260 /*
1261 * Handle exceptions taken in debug state. This happens mostly for memory
1262 * accesses that violated a MMU policy. Taking an exception while in debug
1263 * state clobbers certain state registers on the target exception level.
1264 * Just mark those registers dirty so that they get restored on resume.
1265 * This works both for Aarch32 and Aarch64 states.
1266 *
1267 * This function must not perform any actions that trigger another exception
1268 * or a recursion will happen.
1269 */
1270 void armv8_dpm_handle_exception(struct arm_dpm *dpm)
1271 {
1272 struct armv8_common *armv8 = dpm->arm->arch_info;
1273 struct reg_cache *cache = dpm->arm->core_cache;
1274 enum arm_state core_state;
1275 uint64_t dlr;
1276 uint32_t dspsr;
1277 unsigned int el;
1278
1279 static const int clobbered_regs_by_el[3][5] = {
1280 { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL1, ARMV8_ESR_EL1, ARMV8_SPSR_EL1 },
1281 { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL2, ARMV8_ESR_EL2, ARMV8_SPSR_EL2 },
1282 { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL3, ARMV8_ESR_EL3, ARMV8_SPSR_EL3 },
1283 };
1284
1285 el = (dpm->dscr >> 8) & 3;
1286
1287 /* safety check, must not happen since EL0 cannot be a target for an exception */
1288 if (el < SYSTEM_CUREL_EL1 || el > SYSTEM_CUREL_EL3) {
1289 LOG_ERROR("%s: EL %i is invalid, DSCR corrupted?", __func__, el);
1290 return;
1291 }
1292
1293 /* Clear sticky error */
1294 mem_ap_write_u32(armv8->debug_ap,
1295 armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE);
1296
1297 armv8->read_reg_u64(armv8, ARMV8_xPSR, &dlr);
1298 dspsr = dlr;
1299 armv8->read_reg_u64(armv8, ARMV8_PC, &dlr);
1300
1301 LOG_DEBUG("Exception taken to EL %i, DLR=0x%016"PRIx64" DSPSR=0x%08"PRIx32,
1302 el, dlr, dspsr);
1303
1304 /* mark all clobbered registers as dirty */
1305 for (int i = 0; i < 5; i++)
1306 cache->reg_list[clobbered_regs_by_el[el-1][i]].dirty = true;
1307
1308 /*
1309 * re-evaluate the core state, we might be in Aarch64 state now
1310 * we rely on dpm->dscr being up-to-date
1311 */
1312 core_state = armv8_dpm_get_core_state(dpm);
1313 armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
1314 armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
1315 }
1316
1317 /*----------------------------------------------------------------------*/
1318
1319 /*
1320 * Other debug and support utilities
1321 */
1322
1323 void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
1324 {
1325 struct target *target = dpm->arm->target;
1326
1327 dpm->dscr = dscr;
1328 dpm->last_el = (dscr >> 8) & 3;
1329
1330 /* Examine debug reason */
1331 switch (DSCR_ENTRY(dscr)) {
1332 /* FALL THROUGH -- assume a v6 core in abort mode */
1333 case DSCRV8_ENTRY_EXT_DEBUG: /* EDBGRQ */
1334 target->debug_reason = DBG_REASON_DBGRQ;
1335 break;
1336 case DSCRV8_ENTRY_HALT_STEP_EXECLU: /* HALT step */
1337 case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/
1338 case DSCRV8_ENTRY_HALT_STEP:
1339 target->debug_reason = DBG_REASON_SINGLESTEP;
1340 break;
1341 case DSCRV8_ENTRY_HLT: /* HLT instruction (software breakpoint) */
1342 case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */
1343 case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */
1344 case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/
1345 case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/
1346 case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/
1347 target->debug_reason = DBG_REASON_BREAKPOINT;
1348 break;
1349 case DSCRV8_ENTRY_WATCHPOINT: /* asynch watchpoint */
1350 target->debug_reason = DBG_REASON_WATCHPOINT;
1351 break;
1352 default:
1353 target->debug_reason = DBG_REASON_UNDEFINED;
1354 break;
1355 }
1356
1357 }
1358
1359 /*----------------------------------------------------------------------*/
1360
1361 /*
1362 * Setup and management support.
1363 */
1364
1365 /**
1366 * Hooks up this DPM to its associated target; call only once.
1367 * Initially this only covers the register cache.
1368 *
1369 * Oh, and watchpoints. Yeah.
1370 */
1371 int armv8_dpm_setup(struct arm_dpm *dpm)
1372 {
1373 struct arm *arm = dpm->arm;
1374 struct target *target = arm->target;
1375 struct reg_cache *cache;
1376 arm->dpm = dpm;
1377
1378 /* register access setup */
1379 arm->full_context = armv8_dpm_full_context;
1380 arm->read_core_reg = armv8_dpm_read_core_reg;
1381 arm->write_core_reg = armv8_dpm_write_core_reg;
1382
1383 if (arm->core_cache == NULL) {
1384 cache = armv8_build_reg_cache(target);
1385 if (!cache)
1386 return ERROR_FAIL;
1387 }
1388
1389 /* coprocessor access setup */
1390 arm->mrc = dpmv8_mrc;
1391 arm->mcr = dpmv8_mcr;
1392
1393 dpm->prepare = dpmv8_dpm_prepare;
1394 dpm->finish = dpmv8_dpm_finish;
1395
1396 dpm->instr_execute = dpmv8_instr_execute;
1397 dpm->instr_write_data_dcc = dpmv8_instr_write_data_dcc;
1398 dpm->instr_write_data_dcc_64 = dpmv8_instr_write_data_dcc_64;
1399 dpm->instr_write_data_r0 = dpmv8_instr_write_data_r0;
1400 dpm->instr_write_data_r0_64 = dpmv8_instr_write_data_r0_64;
1401 dpm->instr_cpsr_sync = dpmv8_instr_cpsr_sync;
1402
1403 dpm->instr_read_data_dcc = dpmv8_instr_read_data_dcc;
1404 dpm->instr_read_data_dcc_64 = dpmv8_instr_read_data_dcc_64;
1405 dpm->instr_read_data_r0 = dpmv8_instr_read_data_r0;
1406 dpm->instr_read_data_r0_64 = dpmv8_instr_read_data_r0_64;
1407
1408 dpm->arm_reg_current = armv8_reg_current;
1409
1410 /* dpm->bpwp_enable = dpmv8_bpwp_enable; */
1411 dpm->bpwp_disable = dpmv8_bpwp_disable;
1412
1413 /* breakpoint setup -- optional until it works everywhere */
1414 if (!target->type->add_breakpoint) {
1415 target->type->add_breakpoint = dpmv8_add_breakpoint;
1416 target->type->remove_breakpoint = dpmv8_remove_breakpoint;
1417 }
1418
1419 /* watchpoint setup */
1420 target->type->add_watchpoint = dpmv8_add_watchpoint;
1421 target->type->remove_watchpoint = dpmv8_remove_watchpoint;
1422
1423 /* FIXME add vector catch support */
1424
1425 dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf);
1426 dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
1427
1428 dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf);
1429 dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
1430
1431 if (!dpm->dbp || !dpm->dwp) {
1432 free(dpm->dbp);
1433 free(dpm->dwp);
1434 return ERROR_FAIL;
1435 }
1436
1437 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1438 target_name(target), dpm->nbp, dpm->nwp);
1439
1440 /* REVISIT ... and some of those breakpoints could match
1441 * execution context IDs...
1442 */
1443
1444 return ERROR_OK;
1445 }
1446
1447 /**
1448 * Reinitializes DPM state at the beginning of a new debug session
1449 * or after a reset which may have affected the debug module.
1450 */
1451 int armv8_dpm_initialize(struct arm_dpm *dpm)
1452 {
1453 /* Disable all breakpoints and watchpoints at startup. */
1454 if (dpm->bpwp_disable) {
1455 unsigned i;
1456
1457 for (i = 0; i < dpm->nbp; i++) {
1458 dpm->dbp[i].bpwp.number = i;
1459 (void) dpm->bpwp_disable(dpm, i);
1460 }
1461 for (i = 0; i < dpm->nwp; i++) {
1462 dpm->dwp[i].bpwp.number = 16 + i;
1463 (void) dpm->bpwp_disable(dpm, 16 + i);
1464 }
1465 } else
1466 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
1467 target_name(dpm->arm->target));
1468
1469 return ERROR_OK;
1470 }

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)