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

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)