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

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)