Example #1
0
int arm926ejs_soft_reset_halt(struct target *target)
{
	int retval = ERROR_OK;
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
	struct arm *arm = &arm7_9->arm;
	struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];

	retval = target_halt(target);
	if (retval != ERROR_OK)
		return retval;

	int64_t then = timeval_ms();
	int timeout;
	while (!(timeout = ((timeval_ms()-then) > 1000))) {
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
			embeddedice_read_reg(dbg_stat);
			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;
		} else
			break;
		if (debug_level >= 1) {
			/* do not eat all CPU, time out after 1 se*/
			alive_sleep(100);
		} else
			keep_alive();
	}
	if (timeout) {
		LOG_ERROR("Failed to halt CPU after 1 sec");
		return ERROR_TARGET_TIMEOUT;
	}

	target->state = TARGET_HALTED;

	/* SVC, ARM state, IRQ and FIQ disabled */
	uint32_t cpsr;

	cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
	cpsr &= ~0xff;
	cpsr |= 0xd3;
	arm_set_cpsr(arm, cpsr);
	arm->cpsr->dirty = 1;

	/* start fetching from 0x0 */
	buf_set_u32(arm->pc->value, 0, 32, 0x0);
	arm->pc->dirty = 1;
	arm->pc->valid = 1;

	retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1);
	if (retval != ERROR_OK)
		return retval;
	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;

	return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
Example #2
0
/**
 * Read basic registers of the the current context:  R0 to R15, and CPSR;
 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
 * In normal operation this is called on entry to halting debug state,
 * possibly after some other operations supporting restore of debug state
 * or making sure the CPU is fully idle (drain write buffer, etc).
 */
int arm_dpm_read_current_registers(struct arm_dpm *dpm)
{
	struct arm *arm = dpm->arm;
	uint32_t cpsr;
	int retval;
	struct reg *r;

	retval = dpm->prepare(dpm);
	if (retval != ERROR_OK)
		return retval;

	/* read R0 first (it's used for scratch), then CPSR */
	r = arm->core_cache->reg_list + 0;
	if (!r->valid) {
		retval = dpm_read_reg(dpm, r, 0);
		if (retval != ERROR_OK)
			goto fail;
	}
	r->dirty = true;

	retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr);
	if (retval != ERROR_OK)
		goto fail;

	/* update core mode and state, plus shadow mapping for R8..R14 */
	arm_set_cpsr(arm, cpsr);

	/* REVISIT we can probably avoid reading R1..R14, saving time... */
	for (unsigned i = 1; i < 16; i++) {
		r = arm_reg_current(arm, i);
		if (r->valid)
			continue;

		retval = dpm_read_reg(dpm, r, i);
		if (retval != ERROR_OK)
			goto fail;
	}

	/* NOTE: SPSR ignored (if it's even relevant). */

	/* REVISIT the debugger can trigger various exceptions.  See the
	 * ARMv7A architecture spec, section C5.7, for more info about
	 * what defenses are needed; v6 debug has the most issues.
	 */

fail:
	/* (void) */ dpm->finish(dpm);
	return retval;
}
Example #3
0
static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
{
	struct arm_reg *reg_arch_info = reg->arch_info;
	struct target *target = reg_arch_info->target;
	struct arm *armv4_5_target = target_to_arm(target);
	uint32_t value = buf_get_u32(buf, 0, 32);

	if (target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/* Except for CPSR, the "reg" command exposes a writeback model
	 * for the register cache.
	 */
	if (reg == armv4_5_target->cpsr) {
		arm_set_cpsr(armv4_5_target, value);

		/* Older cores need help to be in ARM mode during halt
		 * mode debug, so we clear the J and T bits if we flush.
		 * For newer cores (v6/v7a/v7r) we don't need that, but
		 * it won't hurt since CPSR is always flushed anyway.
		 */
		if (armv4_5_target->core_mode !=
			(enum arm_mode)(value & 0x1f)) {
			LOG_DEBUG("changing ARM core mode to '%s'",
				arm_mode_name(value & 0x1f));
			value &= ~((1 << 24) | (1 << 5));
			uint8_t t[4];
			buf_set_u32(t, 0, 32, value);
			armv4_5_target->write_core_reg(target, reg,
				16, ARM_MODE_ANY, t);
		}
	} else {
		buf_set_u32(reg->value, 0, 32, value);
		reg->valid = 1;
	}
	reg->dirty = 1;

	return ERROR_OK;
}
Example #4
0
int arm_init_arch_info(struct target *target, struct arm *arm)
{
	target->arch_info = arm;
	arm->target = target;

	arm->common_magic = ARM_COMMON_MAGIC;

	/* core_type may be overridden by subtype logic */
	if (arm->core_type != ARM_MODE_THREAD) {
		arm->core_type = ARM_MODE_ANY;
		arm_set_cpsr(arm, ARM_MODE_USR);
	}

	/* default full_context() has no core-specific optimizations */
	if (!arm->full_context && arm->read_core_reg)
		arm->full_context = arm_full_context;

	if (!arm->mrc)
		arm->mrc = arm_default_mrc;
	if (!arm->mcr)
		arm->mcr = arm_default_mcr;

	return ERROR_OK;
}
Example #5
0
int armv4_5_run_algorithm_inner(struct target *target,
	int num_mem_params, struct mem_param *mem_params,
	int num_reg_params, struct reg_param *reg_params,
	uint32_t entry_point, uint32_t exit_point,
	int timeout_ms, void *arch_info,
	int (*run_it)(struct target *target, uint32_t exit_point,
	int timeout_ms, void *arch_info))
{
	struct arm *arm = target_to_arm(target);
	struct arm_algorithm *arm_algorithm_info = arch_info;
	enum arm_state core_state = arm->core_state;
	uint32_t context[17];
	uint32_t cpsr;
	int exit_breakpoint_size = 0;
	int i;
	int retval = ERROR_OK;

	LOG_DEBUG("Running algorithm");

	if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) {
		LOG_ERROR("current target isn't an ARMV4/5 target");
		return ERROR_TARGET_INVALID;
	}

	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (!is_arm_mode(arm->core_mode)) {
		LOG_ERROR("not a valid arm core mode - communication failure?");
		return ERROR_FAIL;
	}

	/* armv5 and later can terminate with BKPT instruction; less overhead */
	if (!exit_point && arm->is_armv4) {
		LOG_ERROR("ARMv4 target needs HW breakpoint location");
		return ERROR_FAIL;
	}

	/* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
	 * they'll be restored later.
	 */
	for (i = 0; i <= 16; i++) {
		struct reg *r;

		r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i);
		if (!r->valid)
			arm->read_core_reg(target, r, i,
				arm_algorithm_info->core_mode);
		context[i] = buf_get_u32(r->value, 0, 32);
	}
	cpsr = buf_get_u32(arm->cpsr->value, 0, 32);

	for (i = 0; i < num_mem_params; i++) {
		retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
				mem_params[i].value);
		if (retval != ERROR_OK)
			return retval;
	}

	for (i = 0; i < num_reg_params; i++) {
		struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
		if (!reg) {
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		if (reg->size != reg_params[i].size) {
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
				reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		retval = armv4_5_set_core_reg(reg, reg_params[i].value);
		if (retval != ERROR_OK)
			return retval;
	}

	arm->core_state = arm_algorithm_info->core_state;
	if (arm->core_state == ARM_STATE_ARM)
		exit_breakpoint_size = 4;
	else if (arm->core_state == ARM_STATE_THUMB)
		exit_breakpoint_size = 2;
	else {
		LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
		return ERROR_COMMAND_SYNTAX_ERROR;
	}

	if (arm_algorithm_info->core_mode != ARM_MODE_ANY) {
		LOG_DEBUG("setting core_mode: 0x%2.2x",
			arm_algorithm_info->core_mode);
		buf_set_u32(arm->cpsr->value, 0, 5,
			arm_algorithm_info->core_mode);
		arm->cpsr->dirty = 1;
		arm->cpsr->valid = 1;
	}

	/* terminate using a hardware or (ARMv5+) software breakpoint */
	if (exit_point) {
		retval = breakpoint_add(target, exit_point,
				exit_breakpoint_size, BKPT_HARD);
		if (retval != ERROR_OK) {
			LOG_ERROR("can't add HW breakpoint to terminate algorithm");
			return ERROR_TARGET_FAILURE;
		}
	}

	retval = target_resume(target, 0, entry_point, 1, 1);
	if (retval != ERROR_OK)
		return retval;
	retval = run_it(target, exit_point, timeout_ms, arch_info);

	if (exit_point)
		breakpoint_remove(target, exit_point);

	if (retval != ERROR_OK)
		return retval;

	for (i = 0; i < num_mem_params; i++) {
		if (mem_params[i].direction != PARAM_OUT) {
			int retvaltemp = target_read_buffer(target, mem_params[i].address,
					mem_params[i].size,
					mem_params[i].value);
			if (retvaltemp != ERROR_OK)
				retval = retvaltemp;
		}
	}

	for (i = 0; i < num_reg_params; i++) {
		if (reg_params[i].direction != PARAM_OUT) {

			struct reg *reg = register_get_by_name(arm->core_cache,
					reg_params[i].reg_name,
					0);
			if (!reg) {
				LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
				retval = ERROR_COMMAND_SYNTAX_ERROR;
				continue;
			}

			if (reg->size != reg_params[i].size) {
				LOG_ERROR(
					"BUG: register '%s' size doesn't match reg_params[i].size",
					reg_params[i].reg_name);
				retval = ERROR_COMMAND_SYNTAX_ERROR;
				continue;
			}

			buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
		}
	}

	/* restore everything we saved before (17 or 18 registers) */
	for (i = 0; i <= 16; i++) {
		uint32_t regvalue;
		regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).value, 0, 32);
		if (regvalue != context[i]) {
			LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "",
				ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).name, context[i]);
			buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
			ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
				i).valid = 1;
			ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
				i).dirty = 1;
		}
	}

	arm_set_cpsr(arm, cpsr);
	arm->cpsr->dirty = 1;

	arm->core_state = core_state;

	return retval;
}