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

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)