Esempio n. 1
0
/** Logs summary of ARM920 state for a halted target. */
int arm920t_arch_state(struct target *target)
{
	static const char *state[] =
	{
		"disabled", "enabled"
	};

	struct arm920t_common *arm920t = target_to_arm920(target);
	struct arm *armv4_5;

	if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
	{
		LOG_ERROR("BUG: %s", arm920_not);
		return ERROR_TARGET_INVALID;
	}

	armv4_5 = &arm920t->arm7_9_common.armv4_5_common;

	arm_arch_state(target);
	LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
		 state[arm920t->armv4_5_mmu.mmu_enabled],
		 state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
		 state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);

	return ERROR_OK;
}
Esempio n. 2
0
static int arm920t_write_phys_memory(struct target *target,
		uint32_t address, uint32_t size,
		uint32_t count, uint8_t *buffer)
{
	struct arm920t_common *arm920t = target_to_arm920(target);

	return armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu,
			address, size, count, buffer);
}
Esempio n. 3
0
/* EXPORTED to FA256 */
int arm920t_soft_reset_halt(struct target *target)
{
	int retval = ERROR_OK;
	struct arm920t_common *arm920t = target_to_arm920(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;

	long long 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 >= 3) {
			/* 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;

	arm920t_disable_mmu_caches(target, 1, 1, 1);
	arm920t->armv4_5_mmu.mmu_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;

	return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
Esempio n. 4
0
static int arm920_mmu(struct target *target, int *enabled)
{
	if (target->state != TARGET_HALTED) {
		LOG_ERROR("%s: target not halted", __func__);
		return ERROR_TARGET_INVALID;
	}

	*enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled;
	return ERROR_OK;
}
Esempio n. 5
0
/* See table 9-10 for scan chain 15 format during interpreted access mode.
 * If the TESTSTATE register is set for interpreted access, certain CP15
 * MRC and MCR instructions may be executed through scan chain 15.
 *
 * Tables 9-11, 9-12, and 9-13 show which MRC and MCR instructions can be
 * executed using scan chain 15 interpreted mode.
 */
static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode,
		uint32_t arm_opcode)
{
	int retval;
	struct arm920t_common *arm920t = target_to_arm920(target);
	struct arm_jtag *jtag_info;
	struct scan_field fields[4];
	uint8_t access_type_buf = 0;		/* interpreted access */
	uint8_t reg_addr_buf = 0x0;
	uint8_t nr_w_buf = 0;
	uint8_t cp15_opcode_buf[4];

	jtag_info = &arm920t->arm7_9_common.jtag_info;

	retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;
	retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;

	buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);

	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;

	fields[1].num_bits = 32;
	fields[1].out_value = cp15_opcode_buf;
	fields[1].in_value = NULL;

	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;

	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;

	jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

	arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
	retval = arm7_9_execute_sys_speed(target);
	if (retval != ERROR_OK)
		return retval;

	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		LOG_ERROR("failed executing JTAG queue");
		return retval;
	}

	return ERROR_OK;
}
Esempio n. 6
0
static int arm920t_read_cp15_physical(struct target *target,
		int reg_addr, uint32_t *value)
{
	struct arm920t_common *arm920t = target_to_arm920(target);
	struct arm_jtag *jtag_info;
	struct scan_field fields[4];
	uint8_t access_type_buf = 1;
	uint8_t reg_addr_buf = reg_addr & 0x3f;
	uint8_t nr_w_buf = 0;
	int retval;

	jtag_info = &arm920t->arm7_9_common.jtag_info;

	retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;
	retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;

	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;

	fields[1].num_bits = 32;
	fields[1].out_value = NULL;
	fields[1].in_value = NULL;

	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;

	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;

	jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

	fields[1].in_value = (uint8_t *)value;

	jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

	jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
	jtag_execute_queue();
	LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
#endif

	return ERROR_OK;
}
Esempio n. 7
0
static int arm920_virt2phys(struct target *target,
		uint32_t virt, uint32_t *phys)
{
	uint32_t cb;
	struct arm920t_common *arm920t = target_to_arm920(target);

	uint32_t ret;
	int retval = armv4_5_mmu_translate_va(target,
			&arm920t->armv4_5_mmu, virt, &cb, &ret);
	if (retval != ERROR_OK)
		return retval;
	*phys = ret;
	return ERROR_OK;
}
Esempio n. 8
0
static int arm920t_write_cp15_physical(struct target *target,
		int reg_addr, uint32_t value)
{
	struct arm920t_common *arm920t = target_to_arm920(target);
	struct arm_jtag *jtag_info;
	struct scan_field fields[4];
	uint8_t access_type_buf = 1;
	uint8_t reg_addr_buf = reg_addr & 0x3f;
	uint8_t nr_w_buf = 1;
	uint8_t value_buf[4];
	int retval;

	jtag_info = &arm920t->arm7_9_common.jtag_info;

	buf_set_u32(value_buf, 0, 32, value);

	retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;
	retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;

	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;

	fields[1].num_bits = 32;
	fields[1].out_value = value_buf;
	fields[1].in_value = NULL;

	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;

	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;

	jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
	LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
#endif

	return ERROR_OK;
}
Esempio n. 9
0
/* EXPORTED to FA256 */
void arm920t_pre_restore_context(struct target *target)
{
	uint32_t cp15c15;
	struct arm920t_common *arm920t = target_to_arm920(target);

	/* restore i/d fault status and address register */
	arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);

	/* read-modify-write CP15 test state register
	* to reenable I/D-cache linefills */
	if (arm920t->preserve_cache) {
		arm920t_read_cp15_physical(target,
			CP15PHYS_TESTSTATE, &cp15c15);
		jtag_execute_queue();
		cp15c15 &= ~0x600U;
		arm920t_write_cp15_physical(target,
			CP15PHYS_TESTSTATE, cp15c15);
	}
}
Esempio n. 10
0
/** Writes a buffer, in the specified word size, with current MMU settings. */
int arm920t_write_memory(struct target *target, uint32_t address,
		uint32_t size, uint32_t count, uint8_t *buffer)
{
	int retval;
	const uint32_t cache_mask = ~0x1f; /* cache line size : 32 byte */
	struct arm920t_common *arm920t = target_to_arm920(target);

	/* FIX!!!! this should be cleaned up and made much more general. The
	 * plan is to write up and test on arm920t specifically and
	 * then generalize and clean up afterwards.
	 *
	 * Also it should be moved to the callbacks that handle breakpoints
	 * specifically and not the generic memory write fn's. See XScale code.
	 */
	if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) &&
			((size==2) || (size==4)))
	{
		/* special case the handling of single word writes to
		 * bypass MMU, to allow implementation of breakpoints
		 * in memory marked read only
		 * by MMU
		 */
		uint32_t cb;
		uint32_t pa;

		/*
		 * We need physical address and cb
		 */
		retval = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu,
				address, &cb, &pa);
		if (retval != ERROR_OK)
			return retval;

		if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
		{
			if (cb & 0x1)
			{
				LOG_DEBUG("D-Cache buffered, "
						"drain write buffer");
				/*
				 * Buffered ?
				 * Drain write buffer - MCR p15,0,Rd,c7,c10,4
				 */

				retval = arm920t_write_cp15_interpreted(target,
					ARMV4_5_MCR(15, 0, 0, 7, 10, 4),
					0x0, 0);
				if (retval != ERROR_OK)
					return retval;
			}

			if (cb == 0x3)
			{
				/*
				 * Write back memory ? -> clean cache
				 *
				 * There is no way to clean cache lines using
				 * cp15 scan chain, so copy the full cache
				 * line from cache to physical memory.
				 */
				uint8_t data[32];

				LOG_DEBUG("D-Cache in 'write back' mode, "
						"flush cache line");

				retval = target_read_memory(target,
						address & cache_mask, 1,
						sizeof(data), &data[0]);
				if (retval != ERROR_OK)
					return retval;

				retval = armv4_5_mmu_write_physical(target,
						&arm920t->armv4_5_mmu,
						pa & cache_mask, 1,
						sizeof(data), &data[0]);
				if (retval != ERROR_OK)
					return retval;
			}

			/* Cached ? */
			if (cb & 0x2)
			{
				/*
				 * Cached ? -> Invalidate data cache using MVA
				 *
				 * MCR p15,0,Rd,c7,c6,1
				 */
				LOG_DEBUG("D-Cache enabled, "
					"invalidate cache line");

				retval = arm920t_write_cp15_interpreted(target,
					ARMV4_5_MCR(15, 0, 0, 7, 6, 1), 0x0,
					address & cache_mask);
				if (retval != ERROR_OK)
					return retval;
			}
		}

		/* write directly to physical memory,
		 * bypassing any read only MMU bits, etc.
		 */
		retval = armv4_5_mmu_write_physical(target,
				&arm920t->armv4_5_mmu, pa, size,
				count, buffer);
		if (retval != ERROR_OK)
			return retval;
	} else
	{
		if ((retval = arm7_9_write_memory(target, address,
					size, count, buffer)) != ERROR_OK)
			return retval;
	}

	/* If ICache is enabled, we have to invalidate affected ICache lines
	 * the DCache is forced to write-through,
	 * so we don't have to clean it here
	 */
	if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
	{
		if (count <= 1)
		{
			/* invalidate ICache single entry with MVA
			 *   mcr	15, 0, r0, cr7, cr5, {1}
			 */
			LOG_DEBUG("I-Cache enabled, "
				"invalidating affected I-Cache line");
			retval = arm920t_write_cp15_interpreted(target,
					ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
					0x0, address & cache_mask);
			if (retval != ERROR_OK)
				return retval;
		}
		else
		{
			/* invalidate ICache
			 *  mcr	15, 0, r0, cr7, cr5, {0}
			 */
			retval = arm920t_write_cp15_interpreted(target,
					ARMV4_5_MCR(15, 0, 0, 7, 5, 0),
					0x0, 0x0);
			if (retval != ERROR_OK)
				return retval;
		}
	}

	return ERROR_OK;
}
Esempio n. 11
0
// EXPORTED to FA256
int arm920t_post_debug_entry(struct target *target)
{
	uint32_t cp15c15;
	struct arm920t_common *arm920t = target_to_arm920(target);
	int retval;

	/* examine cp15 control reg */
	retval = arm920t_read_cp15_physical(target,
			CP15PHYS_CTRL, &arm920t->cp15_control_reg);
	if (retval != ERROR_OK)
		return retval;
	retval = jtag_execute_queue();
	if (retval != ERROR_OK)
		return retval;
	LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm920t->cp15_control_reg);

	if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
	{
		uint32_t cache_type_reg;
		/* identify caches */
		retval = arm920t_read_cp15_physical(target,
				CP15PHYS_CACHETYPE, &cache_type_reg);
		if (retval != ERROR_OK)
			return retval;
		retval = jtag_execute_queue();
		if (retval != ERROR_OK)
			return retval;
		armv4_5_identify_cache(cache_type_reg,
				&arm920t->armv4_5_mmu.armv4_5_cache);
	}

	arm920t->armv4_5_mmu.mmu_enabled =
			(arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
			(arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
			(arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;

	/* save i/d fault status and address register */
			/* FIXME use opcode macros */
	retval = arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
	if (retval != ERROR_OK)
		return retval;
	retval = arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
	if (retval != ERROR_OK)
		return retval;
	retval = arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
	if (retval != ERROR_OK)
		return retval;
	retval = arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
	if (retval != ERROR_OK)
		return retval;

	LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32
		", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32,
		arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);

	if (arm920t->preserve_cache)
	{
		/* read-modify-write CP15 test state register
		 * to disable I/D-cache linefills */
		retval = arm920t_read_cp15_physical(target,
				CP15PHYS_TESTSTATE, &cp15c15);
		if (retval != ERROR_OK)
			return retval;
		retval = jtag_execute_queue();
		if (retval != ERROR_OK)
			return retval;
		cp15c15 |= 0x600;
		retval = arm920t_write_cp15_physical(target,
				CP15PHYS_TESTSTATE, cp15c15);
		if (retval != ERROR_OK)
			return retval;
	}
	return ERROR_OK;
}