1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2013 Andes Technology *
5 * Hsiangkai Wang <hkwang@andestech.com> *
6 ***************************************************************************/
12 #include <helper/time_support.h>
13 #include <helper/binarybuffer.h>
14 #include "breakpoints.h"
15 #include "nds32_insn.h"
16 #include "nds32_reg.h"
17 #include "nds32_edm.h"
18 #include "nds32_cmd.h"
20 #include "nds32_aice.h"
21 #include "target_type.h"
23 static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
25 uint32_t max_level = nds32->max_interrupt_level;
26 uint32_t cur_level = nds32->current_interrupt_level;
28 if ((cur_level >= 1) && (cur_level < max_level)) {
30 LOG_DEBUG("Map PSW to IPSW");
32 } else if (reg_no == PC) {
33 LOG_DEBUG("Map PC to IPC");
36 } else if ((cur_level >= 2) && (cur_level < max_level)) {
38 LOG_DEBUG("Mapping P0 to P_P0");
40 } else if (reg_no == R27) {
41 LOG_DEBUG("Mapping P1 to P_P1");
43 } else if (reg_no == IR1) {
44 LOG_DEBUG("Mapping IPSW to P_IPSW");
46 } else if (reg_no == IR4) {
47 LOG_DEBUG("Mapping EVA to P_EVA");
49 } else if (reg_no == IR6) {
50 LOG_DEBUG("Mapping ITYPE to P_ITYPE");
52 } else if (reg_no == IR9) {
53 LOG_DEBUG("Mapping IPC to P_IPC");
56 } else if (cur_level == max_level) {
58 LOG_DEBUG("Mapping PC to O_IPC");
66 static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
69 struct aice_port_s *aice = target_to_aice(nds32->target);
71 aice_read_register(aice, IR6, &val_itype);
73 *reason = val_itype & 0x0F;
78 static int nds32_v2_activate_hardware_breakpoint(struct target *target)
80 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
81 struct aice_port_s *aice = target_to_aice(target);
82 struct breakpoint *bp;
83 int32_t hbr_index = 0;
85 for (bp = target->breakpoints; bp; bp = bp->next) {
86 if (bp->type == BKPT_SOFT) {
87 /* already set at nds32_v2_add_breakpoint() */
89 } else if (bp->type == BKPT_HARD) {
91 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
93 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
95 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
97 if (nds32_v2->nds32.memory.address_translation)
98 /* enable breakpoint (virtual address) */
99 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
101 /* enable breakpoint (physical address) */
102 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
104 LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
116 static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
118 struct aice_port_s *aice = target_to_aice(target);
119 struct breakpoint *bp;
120 int32_t hbr_index = 0;
122 for (bp = target->breakpoints; bp; bp = bp->next) {
123 if (bp->type == BKPT_SOFT)
125 else if (bp->type == BKPT_HARD)
126 /* disable breakpoint */
127 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
131 LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
140 static int nds32_v2_activate_hardware_watchpoint(struct target *target)
142 struct aice_port_s *aice = target_to_aice(target);
143 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
144 struct watchpoint *wp;
145 int32_t wp_num = nds32_v2->next_hbr_index;
146 uint32_t wp_config = 0;
148 for (wp = target->watchpoints; wp; wp = wp->next) {
151 wp->mask = wp->length - 1;
152 if ((wp->address % wp->length) != 0)
153 wp->mask = (wp->mask << 1) + 1;
155 if (wp->rw == WPT_READ)
157 else if (wp->rw == WPT_WRITE)
159 else if (wp->rw == WPT_ACCESS)
162 /* set/unset physical address bit of BPCn according to PSW.DT */
163 if (nds32_v2->nds32.memory.address_translation == false)
167 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
168 wp->address - (wp->address % wp->length));
170 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
171 /* enable watchpoint */
172 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
174 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
176 LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num,
177 wp->address, wp->mask);
184 static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
186 struct aice_port_s *aice = target_to_aice(target);
187 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
188 int32_t wp_num = nds32_v2->next_hbr_index;
189 struct watchpoint *wp;
191 for (wp = target->watchpoints; wp; wp = wp->next) {
193 /* disable watchpoint */
194 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
196 LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32,
197 wp_num, wp->address, wp->mask);
203 static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
205 struct nds32 *nds32 = &(nds32_v2->nds32);
206 struct aice_port_s *aice = target_to_aice(nds32->target);
210 uint32_t modified_psw;
212 /* Save interrupt level */
213 aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
216 nds32_v2->backup_ir0 = val_ir0;
218 nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
220 if (nds32_reach_max_interrupt_level(nds32)) {
221 LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
222 nds32->current_interrupt_level);
224 /* decrease interrupt level */
225 modified_psw = val_ir0 - 0x2;
227 /* disable GIE, IT, DT, HSS */
228 modified_psw &= (~0x8C1);
230 aice_write_register(aice, IR0, modified_psw);
235 /* There is a case that single step also trigger another interrupt,
236 then HSS bit in psw(ir0) will push to ipsw(ir1).
237 Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
238 Therefore, HSS bit in p_ipsw(ir2) also need clear.
240 Only update $ir2 as current interrupt level is 2, because $ir2 will be random
241 value if the target never reaches interrupt level 2. */
242 if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
243 aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
244 val_ir2 &= ~(0x01 << 11);
245 aice_write_register(aice, IR2, val_ir2);
248 /* get original DT bit and set to current state let debugger has same memory view
249 PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
250 aice_read_register(aice, IR1, &val_ir1);
251 modified_psw = val_ir0 | (val_ir1 & 0x80);
252 aice_write_register(aice, IR0, modified_psw);
257 static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
259 struct nds32 *nds32 = &(nds32_v2->nds32);
260 struct aice_port_s *aice = target_to_aice(nds32->target);
262 /* restore origin $IR0 */
263 aice_write_register(aice, IR0, nds32_v2->backup_ir0);
269 * Save processor state. This is called after a HALT instruction
270 * succeeds, and on other occasions the processor enters debug mode
271 * (breakpoint, watchpoint, etc).
273 static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
275 LOG_DEBUG("nds32_v2_debug_entry");
277 if (nds32->virtual_hosting)
278 LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
279 "under V1/V2 architecture. -->");
281 enum target_state backup_state = nds32->target->state;
282 nds32->target->state = TARGET_HALTED;
284 if (nds32->init_arch_info_after_halted == false) {
285 /* init architecture info according to config registers */
286 CHECK_RETVAL(nds32_config(nds32));
288 nds32->init_arch_info_after_halted = true;
291 /* REVISIT entire cache should already be invalid !!! */
292 register_cache_invalidate(nds32->core_cache);
294 /* deactivate all hardware breakpoints */
295 CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
297 if (enable_watchpoint)
298 CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
300 if (nds32_examine_debug_reason(nds32) != ERROR_OK) {
301 nds32->target->state = backup_state;
303 /* re-activate all hardware breakpoints & watchpoints */
304 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
306 if (enable_watchpoint) {
307 /* activate all watchpoints */
308 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
314 /* check interrupt level before .full_context(), because
315 * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
317 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
318 nds32_v2_check_interrupt_stack(nds32_v2);
320 /* Save registers. */
321 nds32_full_context(nds32);
326 /* target request support */
327 static int nds32_v2_target_request_data(struct target *target,
328 uint32_t size, uint8_t *buffer)
330 /* AndesCore could use DTR register to communicate with OpenOCD
332 * Target data will be put in buffer
333 * The format of DTR is as follow
334 * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
335 * target_req_cmd has three possible values:
336 * TARGET_REQ_TRACEMSG
337 * TARGET_REQ_DEBUGMSG
338 * TARGET_REQ_DEBUGCHAR
339 * if size == 0, target will call target_asciimsg(),
340 * else call target_hexmsg()
342 LOG_WARNING("Not implemented: %s", __func__);
348 * Restore processor state.
350 static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
352 LOG_DEBUG("nds32_v2_leave_debug_state");
354 struct target *target = nds32->target;
356 /* activate all hardware breakpoints */
357 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
359 if (enable_watchpoint) {
360 /* activate all watchpoints */
361 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
364 /* restore interrupt stack */
365 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
366 nds32_v2_restore_interrupt_stack(nds32_v2);
368 /* restore PSW, PC, and R0 ... after flushing any modified
371 CHECK_RETVAL(nds32_restore_context(target));
373 register_cache_invalidate(nds32->core_cache);
378 static int nds32_v2_deassert_reset(struct target *target)
382 CHECK_RETVAL(nds32_poll(target));
384 if (target->state != TARGET_HALTED) {
386 LOG_WARNING("%s: ran after reset and before halt ...",
387 target_name(target));
388 retval = target_halt(target);
389 if (retval != ERROR_OK)
396 static int nds32_v2_checksum_memory(struct target *target,
397 target_addr_t address, uint32_t count, uint32_t *checksum)
399 LOG_WARNING("Not implemented: %s", __func__);
404 static int nds32_v2_add_breakpoint(struct target *target,
405 struct breakpoint *breakpoint)
407 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
408 struct nds32 *nds32 = &(nds32_v2->nds32);
411 if (breakpoint->type == BKPT_HARD) {
412 /* check hardware resource */
413 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
414 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
415 "breakpoints/watchpoints! The limit of "
416 "combined hardware breakpoints/watchpoints "
417 "is %" PRId32 ". -->", nds32_v2->n_hbr);
418 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
421 /* update next place to put hardware breakpoint */
422 nds32_v2->next_hbr_index++;
424 /* hardware breakpoint insertion occurs before 'continue' actually */
426 } else if (breakpoint->type == BKPT_SOFT) {
427 result = nds32_add_software_breakpoint(target, breakpoint);
428 if (result != ERROR_OK) {
429 /* auto convert to hardware breakpoint if failed */
430 if (nds32->auto_convert_hw_bp) {
431 /* convert to hardware breakpoint */
432 breakpoint->type = BKPT_HARD;
434 return nds32_v2_add_breakpoint(target, breakpoint);
439 } else /* unrecognized breakpoint type */
445 static int nds32_v2_remove_breakpoint(struct target *target,
446 struct breakpoint *breakpoint)
448 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
450 if (breakpoint->type == BKPT_HARD) {
451 if (nds32_v2->next_hbr_index <= 0)
454 /* update next place to put hardware breakpoint */
455 nds32_v2->next_hbr_index--;
457 /* hardware breakpoint removal occurs after 'halted' actually */
459 } else if (breakpoint->type == BKPT_SOFT) {
460 return nds32_remove_software_breakpoint(target, breakpoint);
461 } else /* unrecognized breakpoint type */
467 static int nds32_v2_add_watchpoint(struct target *target,
468 struct watchpoint *watchpoint)
470 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
472 /* check hardware resource */
473 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
474 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
475 "breakpoints/watchpoints! The limit of "
476 "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr);
477 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
480 /* update next place to put hardware watchpoint */
481 nds32_v2->next_hbr_index++;
486 static int nds32_v2_remove_watchpoint(struct target *target,
487 struct watchpoint *watchpoint)
489 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
491 if (nds32_v2->next_hbr_index <= 0)
494 /* update next place to put hardware breakpoint */
495 nds32_v2->next_hbr_index--;
500 static int nds32_v2_get_exception_address(struct nds32 *nds32,
501 uint32_t *address, uint32_t reason)
503 struct aice_port_s *aice = target_to_aice(nds32->target);
505 aice_read_register(aice, IR4, address); /* read $EVA directly */
507 /* TODO: hit multiple watchpoints */
513 * find out which watchpoint hits
514 * get exception address and compare the address to watchpoints
516 static int nds32_v2_hit_watchpoint(struct target *target,
517 struct watchpoint **hit_watchpoint)
519 uint32_t exception_address;
520 struct watchpoint *wp;
521 static struct watchpoint scan_all_watchpoint;
522 struct nds32 *nds32 = target_to_nds32(target);
524 scan_all_watchpoint.address = 0;
525 scan_all_watchpoint.rw = WPT_WRITE;
526 scan_all_watchpoint.next = 0;
527 scan_all_watchpoint.unique_id = 0x5CA8;
529 exception_address = nds32->watched_address;
531 if (exception_address == 0) {
532 /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
533 *hit_watchpoint = &scan_all_watchpoint;
537 for (wp = target->watchpoints; wp; wp = wp->next) {
538 if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
539 /* TODO: dispel false match */
540 *hit_watchpoint = wp;
548 static int nds32_v2_run_algorithm(struct target *target,
550 struct mem_param *mem_params,
552 struct reg_param *reg_params,
553 target_addr_t entry_point,
554 target_addr_t exit_point,
558 LOG_WARNING("Not implemented: %s", __func__);
563 static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
565 struct nds32_v2_common *nds32_v2;
567 nds32_v2 = calloc(1, sizeof(*nds32_v2));
571 nds32_v2->nds32.register_map = nds32_v2_register_mapping;
572 nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
573 nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
574 nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
575 nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
577 nds32_init_arch_info(target, &(nds32_v2->nds32));
582 static int nds32_v2_init_target(struct command_context *cmd_ctx,
583 struct target *target)
585 /* Initialize anything we can set up without talking to the target */
587 struct nds32 *nds32 = target_to_nds32(target);
594 /* talk to the target and set things up */
595 static int nds32_v2_examine(struct target *target)
597 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
598 struct nds32 *nds32 = &(nds32_v2->nds32);
599 struct aice_port_s *aice = target_to_aice(target);
601 if (!target_was_examined(target)) {
602 CHECK_RETVAL(nds32_edm_config(nds32));
604 if (nds32->reset_halt_as_examine)
605 CHECK_RETVAL(nds32_reset_halt(nds32));
609 aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
611 /* get the number of hardware breakpoints */
612 nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
614 nds32_v2->next_hbr_index = 0;
616 LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
619 nds32->target->state = TARGET_RUNNING;
620 nds32->target->debug_reason = DBG_REASON_NOTHALTED;
622 target_set_examined(target);
627 static int nds32_v2_translate_address(struct target *target, target_addr_t *address)
629 struct nds32 *nds32 = target_to_nds32(target);
630 struct nds32_memory *memory = &(nds32->memory);
631 target_addr_t physical_address;
633 /* Following conditions need to do address translation
635 * 2. CPU mode under maximum interrupt level */
636 if ((memory->access_channel == NDS_MEMORY_ACC_BUS) ||
637 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
638 nds32_reach_max_interrupt_level(nds32))) {
639 if (target->type->virt2phys(target, *address, &physical_address) == ERROR_OK)
640 *address = physical_address;
648 static int nds32_v2_read_buffer(struct target *target, target_addr_t address,
649 uint32_t size, uint8_t *buffer)
651 struct nds32 *nds32 = target_to_nds32(target);
652 struct nds32_memory *memory = &(nds32->memory);
654 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
655 (target->state != TARGET_HALTED)) {
656 LOG_WARNING("target was not halted");
657 return ERROR_TARGET_NOT_HALTED;
660 /* BUG: If access range crosses multiple pages, the translation will not correct
661 * for second page or so. */
663 nds32_v2_translate_address(target, &address);
665 return nds32_read_buffer(target, address, size, buffer);
668 static int nds32_v2_write_buffer(struct target *target, target_addr_t address,
669 uint32_t size, const uint8_t *buffer)
671 struct nds32 *nds32 = target_to_nds32(target);
672 struct nds32_memory *memory = &(nds32->memory);
674 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
675 (target->state != TARGET_HALTED)) {
676 LOG_WARNING("target was not halted");
677 return ERROR_TARGET_NOT_HALTED;
680 /* BUG: If access range crosses multiple pages, the translation will not correct
681 * for second page or so. */
683 nds32_v2_translate_address(target, &address);
685 return nds32_write_buffer(target, address, size, buffer);
688 static int nds32_v2_read_memory(struct target *target, target_addr_t address,
689 uint32_t size, uint32_t count, uint8_t *buffer)
691 struct nds32 *nds32 = target_to_nds32(target);
692 struct nds32_memory *memory = &(nds32->memory);
694 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
695 (target->state != TARGET_HALTED)) {
696 LOG_WARNING("target was not halted");
697 return ERROR_TARGET_NOT_HALTED;
700 /* BUG: If access range crosses multiple pages, the translation will not correct
701 * for second page or so. */
703 nds32_v2_translate_address(target, &address);
705 return nds32_read_memory(target, address, size, count, buffer);
708 static int nds32_v2_write_memory(struct target *target, target_addr_t address,
709 uint32_t size, uint32_t count, const uint8_t *buffer)
711 struct nds32 *nds32 = target_to_nds32(target);
712 struct nds32_memory *memory = &(nds32->memory);
714 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
715 (target->state != TARGET_HALTED)) {
716 LOG_WARNING("target was not halted");
717 return ERROR_TARGET_NOT_HALTED;
720 /* BUG: If access range crosses multiple pages, the translation will not correct
721 * for second page or so. */
723 nds32_v2_translate_address(target, &address);
725 return nds32_write_memory(target, address, size, count, buffer);
728 /** Holds methods for V2 targets. */
729 struct target_type nds32_v2_target = {
733 .arch_state = nds32_arch_state,
735 .target_request_data = nds32_v2_target_request_data,
738 .resume = nds32_resume,
741 .assert_reset = nds32_assert_reset,
742 .deassert_reset = nds32_v2_deassert_reset,
744 /* register access */
745 .get_gdb_reg_list = nds32_get_gdb_reg_list,
748 .read_buffer = nds32_v2_read_buffer,
749 .write_buffer = nds32_v2_write_buffer,
750 .read_memory = nds32_v2_read_memory,
751 .write_memory = nds32_v2_write_memory,
753 .checksum_memory = nds32_v2_checksum_memory,
755 /* breakpoint/watchpoint */
756 .add_breakpoint = nds32_v2_add_breakpoint,
757 .remove_breakpoint = nds32_v2_remove_breakpoint,
758 .add_watchpoint = nds32_v2_add_watchpoint,
759 .remove_watchpoint = nds32_v2_remove_watchpoint,
760 .hit_watchpoint = nds32_v2_hit_watchpoint,
764 .virt2phys = nds32_virtual_to_physical,
765 .read_phys_memory = nds32_read_phys_memory,
766 .write_phys_memory = nds32_write_phys_memory,
768 .run_algorithm = nds32_v2_run_algorithm,
770 .commands = nds32_command_handlers,
771 .target_create = nds32_v2_target_create,
772 .init_target = nds32_v2_init_target,
773 .examine = nds32_v2_examine,