/* talk to the target and set things up */ static int nds32_v3m_examine(struct target *target) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct nds32 *nds32 = &(nds32_v3m->nds32); struct aice_port_s *aice = target_to_aice(target); if (!target_was_examined(target)) { CHECK_RETVAL(nds32_edm_config(nds32)); if (nds32->reset_halt_as_examine) CHECK_RETVAL(nds32_reset_halt(nds32)); } uint32_t edm_cfg; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); /* get the number of hardware breakpoints */ nds32_v3m->n_hbr = (edm_cfg & 0x7) + 1; nds32_v3m->used_n_wp = 0; /* get the number of hardware watchpoints */ /* If the WP field is hardwired to zero, it means this is a * simple breakpoint. Otherwise, if the WP field is writable * then it means this is a regular watchpoints. */ nds32_v3m->n_hwp = 0; for (int32_t i = 0 ; i < nds32_v3m->n_hbr ; i++) { /** check the hardware breakpoint is simple or not */ uint32_t tmp_value; aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + i, 0x1); aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &tmp_value); if (tmp_value) nds32_v3m->n_hwp++; } /* hardware breakpoint is inserted from high index to low index */ nds32_v3m->next_hbr_index = nds32_v3m->n_hbr - 1; /* hardware watchpoint is inserted from low index to high index */ nds32_v3m->next_hwp_index = 0; LOG_INFO("%s: total hardware breakpoint %d (simple breakpoint %d)", target_name(target), nds32_v3m->n_hbr, nds32_v3m->n_hbr - nds32_v3m->n_hwp); LOG_INFO("%s: total hardware watchpoint %d", target_name(target), nds32_v3m->n_hwp); nds32->target->state = TARGET_RUNNING; nds32->target->debug_reason = DBG_REASON_NOTHALTED; target_set_examined(target); return ERROR_OK; }
int arc_ocd_examine(struct target *target) { uint32_t status; struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("-"); CHECK_RETVAL(arc_jtag_startup(&arc32->jtag_info)); if (!target_was_examined(target)) { /* read ARC core info */ if (strncmp(target_name(target), ARCEM_STR, 6) == 0) { arc32->processor_type = ARCEM_NUM; LOG_USER("Processor type: %s", ARCEM_STR); } else if (strncmp(target_name(target), ARC600_STR, 6) == 0) { arc32->processor_type = ARC600_NUM; LOG_USER("Processor type: %s", ARC600_STR); } else if (strncmp(target_name(target), ARC700_STR, 6) == 0) { arc32->processor_type = ARC700_NUM; LOG_USER("Processor type: %s", ARC700_STR); } else { LOG_WARNING(" THIS IS A UNSUPPORTED TARGET: %s", target_name(target)); } CHECK_RETVAL(arc_jtag_status(&arc32->jtag_info, &status)); if (status & ARC_JTAG_STAT_RU) { target->state = TARGET_RUNNING; } else { /* It is first time we examine the target, it is halted * and we don't know why. Let's set debug reason, * otherwise OpenOCD will complain that reason is * unknown. */ if (target->state == TARGET_UNKNOWN) target->debug_reason = DBG_REASON_DBGRQ; target->state = TARGET_HALTED; } /* Read BCRs and configure optinal registers. */ CHECK_RETVAL(arc_regs_read_bcrs(target)); arc_regs_build_reg_list(target); CHECK_RETVAL(arc32_configure(target)); target_set_examined(target); } return ERROR_OK; }
static int arm11_assert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); /* optionally catch reset vector */ if (target->reset_halt && !(arm11->vcr & 1)) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { target_handle_event(target, TARGET_EVENT_RESET_ASSERT); } else if (jtag_get_reset_config() & RESET_HAS_SRST) { /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ jtag_add_reset(0, 1); } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* registers are now invalid */ register_cache_invalidate(arm11->arm.core_cache); target->state = TARGET_RESET; return ERROR_OK; }
static int arm11_deassert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); int retval; /* be certain SRST is off */ jtag_add_reset(0, 0); /* WORKAROUND i.MX31 problems: SRST goofs the TAP, and resets * at least DSCR. OMAP24xx doesn't show that problem, though * SRST-only reset seems to be problematic for other reasons. * (Secure boot sequences being one likelihood!) */ jtag_add_tlr(); CHECK_RETVAL(arm11_poll(target)); if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); if ((retval = target_halt(target)) != ERROR_OK) return retval; } } /* maybe restore vector catch config */ if (target->reset_halt && !(arm11->vcr & 1)) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr)); return ERROR_OK; }
static void parse_answer_section(ns_msg *msg) { int rrnum, rrmax; ns_rr rr; uint16_t prio, weight, port, len; const unsigned char *rdata; char *tname; rrmax = ns_msg_count(*msg, ns_s_an); for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(msg, ns_s_an, rrnum, &rr)) { perror("ns_parserr"); exit(EXIT_FAILURE); } if (ns_rr_type(rr) == ns_t_srv) { len = ns_rr_rdlen(rr); rdata = ns_rr_rdata(rr); if (len > 3U * NS_INT16SZ) { NS_GET16(prio, rdata); NS_GET16(weight, rdata); NS_GET16(port, rdata); len -= 3U * NS_INT16SZ; tname = target_name(rdata); insert_tuple(tname, prio, weight, port); } } } }
/** * Hooks up this DPM to its associated target; call only once. * Initially this only covers the register cache. * * Oh, and watchpoints. Yeah. */ int arm_dpm_setup(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct target *target = arm->target; struct reg_cache *cache; arm->dpm = dpm; /* register access setup */ arm->full_context = arm_dpm_full_context; arm->read_core_reg = arm_dpm_read_core_reg; arm->write_core_reg = arm_dpm_write_core_reg; cache = arm_build_reg_cache(target, arm); if (!cache) return ERROR_FAIL; *register_get_last_cache_p(&target->reg_cache) = cache; /* coprocessor access setup */ arm->mrc = dpm_mrc; arm->mcr = dpm_mcr; /* breakpoint setup -- optional until it works everywhere */ if (!target->type->add_breakpoint) { target->type->add_breakpoint = dpm_add_breakpoint; target->type->remove_breakpoint = dpm_remove_breakpoint; } /* watchpoint setup */ target->type->add_watchpoint = dpm_add_watchpoint; target->type->remove_watchpoint = dpm_remove_watchpoint; /* FIXME add vector catch support */ dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); if (!dpm->dbp || !dpm->dwp) { free(dpm->dbp); free(dpm->dwp); return ERROR_FAIL; } LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", target_name(target), dpm->nbp, dpm->nwp); /* REVISIT ... and some of those breakpoints could match * execution context IDs... */ return ERROR_OK; }
void breakpoint_clear_target_internal(struct target *target) { struct breakpoint *breakpoint; LOG_DEBUG("Delete all breakpoints for target: %s", target_name(target)); while ((breakpoint = target->breakpoints) != NULL) { breakpoint_free(target, breakpoint); } }
void watchpoint_clear_target(struct target *target) { struct watchpoint *watchpoint; LOG_DEBUG("Delete all watchpoints for target: %s", target_name(target)); while ((watchpoint = target->watchpoints) != NULL) { watchpoint_free(target, watchpoint); } }
static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num) { char tmp_str[HW_THREAD_NAME_STR_SIZE]; threadid_t tid = threadid_from_target(curr); memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE); /* thread-id is the core-id of this core inside the SMP group plus 1 */ rtos->thread_details[thread_num].threadid = tid; /* create the thread name */ rtos->thread_details[thread_num].exists = true; rtos->thread_details[thread_num].thread_name_str = strdup(target_name(curr)); snprintf(tmp_str, HW_THREAD_NAME_STR_SIZE-1, "state: %s", debug_reason_name(curr)); rtos->thread_details[thread_num].extra_info_str = strdup(tmp_str); return ERROR_OK; }
static int nds32_v3m_deassert_reset(struct target *target) { int retval; CHECK_RETVAL(nds32_poll(target)); if (target->state != TARGET_HALTED) { /* reset only */ LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; }
/** * Reinitializes DPM state at the beginning of a new debug session * or after a reset which may have affected the debug module. */ int arm_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { unsigned i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; (void) dpm->bpwp_disable(dpm, i); } for (i = 0; i < dpm->nwp; i++) { dpm->dwp[i].bpwp.number = 16 + i; (void) dpm->bpwp_disable(dpm, 16 + i); } } else LOG_WARNING("%s: can't disable breakpoints and watchpoints", target_name(dpm->arm->target)); return ERROR_OK; }
/* Avoid needless I/O ... leave breakpoints and watchpoints alone * unless they're removed, or need updating because of single-stepping * or running debugger code. */ static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, struct dpm_bpwp *xp, int *set_p) { int retval = ERROR_OK; bool disable; if (!set_p) { if (!xp->dirty) goto done; xp->dirty = false; /* removed or startup; we must disable it */ disable = true; } else if (bpwp) { if (!xp->dirty) goto done; /* disabled, but we must set it */ xp->dirty = disable = false; *set_p = true; } else { if (!*set_p) goto done; /* set, but we must temporarily disable it */ xp->dirty = disable = true; *set_p = false; } if (disable) retval = dpm->bpwp_disable(dpm, xp->number); else retval = dpm->bpwp_enable(dpm, xp->number, xp->address, xp->control); if (retval != ERROR_OK) LOG_ERROR("%s: can't %s HW %spoint %d", disable ? "disable" : "enable", target_name(dpm->arm->target), (xp->number < 16) ? "break" : "watch", xp->number & 0xf); done: return retval; }
/* retrieve core id cluster id */ int armv8_read_mpidr(struct armv8_common *armv8) { int retval = ERROR_FAIL; struct arm_dpm *dpm = armv8->arm.dpm; uint32_t mpidr; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); if (retval != ERROR_OK) goto done; if (mpidr & 1<<31) { armv8->multi_processor_system = (mpidr >> 30) & 1; armv8->cluster_id = (mpidr >> 8) & 0xf; armv8->cpu_id = mpidr & 0x3; LOG_INFO("%s cluster %x core %x %s", target_name(armv8->arm.target), armv8->cluster_id, armv8->cpu_id, armv8->multi_processor_system == 0 ? "multi core" : "single core"); } else
static int arm11_assert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); if (!(target_was_examined(target))) { if (jtag_get_reset_config() & RESET_HAS_SRST) jtag_add_reset(0, 1); else { LOG_WARNING("Reset is not asserted because the target is not examined."); LOG_WARNING("Use a reset button or power cycle the target."); return ERROR_TARGET_NOT_EXAMINED; } } else { /* optionally catch reset vector */ if (target->reset_halt && !(arm11->vcr & 1)) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); else if (jtag_get_reset_config() & RESET_HAS_SRST) { /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ jtag_add_reset(0, 1); } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } } /* registers are now invalid */ register_cache_invalidate(arm11->arm.core_cache); target->state = TARGET_RESET; return ERROR_OK; }
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; struct arm *arm; int retval; context = current_command_context(interp); assert(context != NULL); target = get_current_target(context); if (target == NULL) { LOG_ERROR("%s: no current target", __func__); return JIM_ERR; } if (!target_was_examined(target)) { LOG_ERROR("%s: not yet examined", target_name(target)); return JIM_ERR; } arm = target_to_arm(target); if (!is_arm(arm)) { LOG_ERROR("%s: not an ARM", target_name(target)); return JIM_ERR; } if ((argc < 6) || (argc > 7)) { /* FIXME use the command name to verify # params... */ LOG_ERROR("%s: wrong number of arguments", __func__); return JIM_ERR; } int cpnum; uint32_t op1; uint32_t op2; uint32_t CRn; uint32_t CRm; uint32_t value; long l; /* NOTE: parameter sequence matches ARM instruction set usage: * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX * The "rX" is necessarily omitted; it uses Tcl mechanisms. */ retval = Jim_GetLong(interp, argv[1], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "coprocessor", (int) l); return JIM_ERR; } cpnum = l; retval = Jim_GetLong(interp, argv[2], &l); if (retval != JIM_OK) return retval; if (l & ~0x7) { LOG_ERROR("%s: %s %d out of range", __func__, "op1", (int) l); return JIM_ERR; } op1 = l; retval = Jim_GetLong(interp, argv[3], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "CRn", (int) l); return JIM_ERR; } CRn = l; retval = Jim_GetLong(interp, argv[4], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "CRm", (int) l); return JIM_ERR; } CRm = l; retval = Jim_GetLong(interp, argv[5], &l); if (retval != JIM_OK) return retval; if (l & ~0x7) { LOG_ERROR("%s: %s %d out of range", __func__, "op2", (int) l); return JIM_ERR; } op2 = l; value = 0; /* FIXME don't assume "mrc" vs "mcr" from the number of params; * that could easily be a typo! Check both... * * FIXME change the call syntax here ... simplest to just pass * the MRC() or MCR() instruction to be executed. That will also * let us support the "mrc2" and "mcr2" opcodes (toggling one bit) * if that's ever needed. */ if (argc == 7) { retval = Jim_GetLong(interp, argv[6], &l); if (retval != JIM_OK) return retval; value = l; /* NOTE: parameters reordered! */ /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */ retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value); if (retval != ERROR_OK) return JIM_ERR; } else { /* NOTE: parameters reordered! */ /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */ retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value); if (retval != ERROR_OK) return JIM_ERR; Jim_SetResult(interp, Jim_NewIntObj(interp, value)); } return JIM_OK; }
static void dependGraphOutput( TARGET *t, int depth ) { TARGETS *c; if ( (t->flags & T_FLAG_VISITED) != 0 || !t->name || !t->boundname) return; t->flags |= T_FLAG_VISITED; switch (t->fate) { case T_FATE_TOUCHED: case T_FATE_MISSING: case T_FATE_OUTDATED: case T_FATE_UPDATE: printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); break; default: printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); break; } if( strcmp (t->name, t->boundname) ) { printf( " %s Loc: %s\n", spaces(depth), t->boundname ); } switch( t->fate ) { case T_FATE_STABLE: printf( " %s : Stable\n", spaces(depth) ); break; case T_FATE_NEWER: printf( " %s : Newer\n", spaces(depth) ); break; case T_FATE_ISTMP: printf( " %s : Up to date temp file\n", spaces(depth) ); case T_FATE_NEEDTMP: printf( " %s : Temporary file, to be updated\n", spaces(depth) ); break; case T_FATE_TOUCHED: printf( " %s : Been touched, updating it\n", spaces(depth) ); break; case T_FATE_MISSING: printf( " %s : Missing, creating it\n", spaces(depth) ); break; case T_FATE_OUTDATED: printf( " %s : Outdated, updating it\n", spaces(depth) ); break; case T_FATE_REBUILD: printf( " %s : Rebuild, Updating it\n", spaces(depth) ); break; case T_FATE_UPDATE: printf( " %s : Updating it\n", spaces(depth) ); break; case T_FATE_CANTFIND: printf( " %s : Can't find it\n", spaces(depth) ); break; case T_FATE_CANTMAKE: printf( " %s : Can't make it\n", spaces(depth) ); break; } if( t->flags & ~T_FLAG_VISITED ) { printf( " %s : ", spaces(depth) ); if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY "); if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE "); if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE "); if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED "); if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES "); if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE "); printf( "\n" ); } for( c = t->depends; c; c = c->next ) { printf( " %s : Depends on %s (%s)", spaces(depth), target_name(c->target), target_fate[ c->target->fate ] ); if (c->target->time == t->time) printf( " (max time)"); printf("\n"); } for( c = t->depends; c; c = c->next ) { dependGraphOutput( c->target, depth + 1 ); } }
/** * Probe EmbeddedICE module and set up local records of its registers. * Different versions of the modules have different capabilities, such as * hardware support for vector_catch, single stepping, and monitor mode. */ struct reg_cache *embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9) { int retval; struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct embeddedice_reg *arch_info = NULL; struct arm_jtag *jtag_info = &arm7_9->jtag_info; int num_regs = ARRAY_SIZE(eice_regs); int i; int eice_version = 0; /* vector_catch isn't always present */ if (!arm7_9->has_vector_catch) num_regs--; /* the actual registers are kept in two arrays */ reg_list = calloc(num_regs, sizeof(struct reg)); arch_info = calloc(num_regs, sizeof(struct embeddedice_reg)); /* fill in values for the reg cache */ reg_cache->name = "EmbeddedICE registers"; reg_cache->next = NULL; reg_cache->reg_list = reg_list; reg_cache->num_regs = num_regs; /* FIXME the second watchpoint unit on Feroceon and Dragonite * seems not to work ... we should have a way to not set up * its four registers here! */ /* set up registers */ for (i = 0; i < num_regs; i++) { reg_list[i].name = eice_regs[i].name; reg_list[i].size = eice_regs[i].width; reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].value = calloc(1, 4); reg_list[i].arch_info = &arch_info[i]; reg_list[i].type = &eice_reg_type; arch_info[i].addr = eice_regs[i].addr; arch_info[i].jtag_info = jtag_info; } /* identify EmbeddedICE version by reading DCC control register */ embeddedice_read_reg(®_list[EICE_COMMS_CTRL]); retval = jtag_execute_queue(); if (retval != ERROR_OK) { for (i = 0; i < num_regs; i++) free(reg_list[i].value); free(reg_list); free(reg_cache); free(arch_info); return NULL; } eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4); LOG_INFO("Embedded ICE version %d", eice_version); switch (eice_version) { case 1: /* ARM7TDMI r3, ARM7TDMI-S r3 * * REVISIT docs say ARM7TDMI-S r4 uses version 1 but * that it has 6-bit CTRL and 5-bit STAT... doc bug? * ARM7TDMI r4 docs say EICE v4. */ reg_list[EICE_DBG_CTRL].size = 3; reg_list[EICE_DBG_STAT].size = 5; break; case 2: /* ARM9TDMI */ reg_list[EICE_DBG_CTRL].size = 4; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; break; case 3: LOG_ERROR("EmbeddedICE v%d handling might be broken", eice_version); reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; arm7_9->has_monitor_mode = 1; break; case 4: /* ARM7TDMI r4 */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_monitor_mode = 1; break; case 5: /* ARM9E-S rev 1 */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; arm7_9->has_monitor_mode = 1; break; case 6: /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 10; /* DBG_STAT has MOE bits */ arm7_9->has_monitor_mode = 1; break; case 7: LOG_ERROR("EmbeddedICE v%d handling might be broken", eice_version); reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_monitor_mode = 1; break; default: /* * The Feroceon implementation has the version number * in some unusual bits. Let feroceon.c validate it * and do the appropriate setup itself. */ if (strcmp(target_type_name(target), "feroceon") == 0 || strcmp(target_type_name(target), "dragonite") == 0) break; LOG_ERROR("unknown EmbeddedICE version " "(comms ctrl: 0x%8.8" PRIx32 ")", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32)); } /* On Feroceon and Dragonite the second unit is seemingly missing. */ LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s", target_name(target), arm7_9->wp_available_max, (arm7_9->wp_available_max != 1) ? "s" : ""); return reg_cache; }