Example #1
0
static int enter_probemode(struct target *t)
{
	uint32_t tapstatus = 0;
	tapstatus = get_tapstatus(t);
	LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus);
	if (tapstatus & TS_PM_BIT) {
		LOG_DEBUG("core already in probemode");
		return ERROR_OK;
	}
	scan.out[0] = PROBEMODE;
	if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
		return ERROR_FAIL;
	scan.out[0] = 1;
	if (drscan(t, scan.out, scan.in, 1) != ERROR_OK)
		return ERROR_FAIL;

	/* HACK */
	int cnt = 5;
	do {
		tapstatus = get_tapstatus(t);
		if (tapstatus & TS_PM_BIT)
			return ERROR_OK;

		LOG_DEBUG("%s Waiting for PM, TS = 0x%08" PRIx32,
				__func__, tapstatus);
		usleep(100000);
		cnt--;
	} while (cnt);
	return ERROR_FAIL;
	/* TODO: find a nicer way to wait until PM_BIT changes*/
}
Example #2
0
static int enter_probemode(struct target *t)
{
	uint32_t tapstatus = 0;
	tapstatus = get_tapstatus(t);
	LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus);
	if (tapstatus & TS_PM_BIT) {
		LOG_DEBUG("core already in probemode");
		return ERROR_OK;
	}
	scan.out[0] = PROBEMODE;
	if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
		return ERROR_FAIL;
	scan.out[0] = 1;
	if (drscan(t, scan.out, scan.in, 1) != ERROR_OK)
		return ERROR_FAIL;
	tapstatus = get_tapstatus(t);
	LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus);
	if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT)))
		return ERROR_OK;
	else {
		LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32
				, __func__, tapstatus);
		return ERROR_FAIL;
	}
}
Example #3
0
static bool sw_bpts_supported(struct target *t)
{
	uint32_t tapstatus = get_tapstatus(t);
	if (tapstatus & TS_SBP_BIT)
		return true;
	else
		return false;
}
Example #4
0
static int transaction_status(struct target *t)
{
	uint32_t tapstatus = get_tapstatus(t);
	if ((TS_EN_PM_BIT | TS_PRDY_BIT) & tapstatus) {
		LOG_ERROR("%s transaction error tapstatus = 0x%08" PRIx32
				, __func__, tapstatus);
		return ERROR_FAIL;
	} else {
		return ERROR_OK;
	}
}
Example #5
0
static int exit_probemode(struct target *t)
{
	uint32_t tapstatus = get_tapstatus(t);
	LOG_DEBUG("TS before PM exit = 0x%08" PRIx32, tapstatus);

	if (!(tapstatus & TS_PM_BIT)) {
		LOG_USER("core not in PM");
		return ERROR_OK;
	}
	scan.out[0] = PROBEMODE;
	if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
		return ERROR_FAIL;
	scan.out[0] = 0;
	if (drscan(t, scan.out, scan.in, 1) != ERROR_OK)
		return ERROR_FAIL;
	return ERROR_OK;
}
Example #6
0
/*
 * PIR (Probe Mode Instruction Register), SUBMITPIR is an "IR only" TAP
 * command; there is no corresponding data register
 */
static int submit_pir(struct target *t, uint64_t op)
{
	struct x86_32_common *x86_32 = target_to_x86_32(t);
	uint32_t tapstatus = 0;

	uint8_t op_buf[8];
	buf_set_u64(op_buf, 0, 64, op);
	int flush = x86_32->flush;
	x86_32->flush = 0;
	scan.out[0] = WRPIR;
	if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
		return ERROR_FAIL;
	if (drscan(t, op_buf, scan.out, PIR_SIZE) != ERROR_OK)
		return ERROR_FAIL;
	scan.out[0] = SUBMITPIR;
	x86_32->flush = flush;
	if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
		return ERROR_FAIL;
	jtag_add_sleep(DELAY_SUBMITPIR);

	/* HACK */
	if (x86_32->flush) {
		int cnt = 10;
		do {
			tapstatus = get_tapstatus(t);
			if (!(tapstatus & TS_PIR_BIT))
				return ERROR_OK;

			LOG_DEBUG("%s Waiting for TS_PIR_BIT, TS = 0x%08" PRIx32,
					__func__, tapstatus);
			usleep(100);
			cnt--;
		} while (cnt);
		LOG_ERROR("%s TS_PIR_BIT did not clear, TS = 0x%08" PRIx32,
				__func__, tapstatus);
		return ERROR_FAIL;
		/* TODO: find a nicer way to wait until PM_BIT changes*/
	}

	return ERROR_OK;

}
Example #7
0
static int transaction_status(struct target *t)
{
	uint32_t tapstatus = 0;

	/* HACK */
	int cnt = 5;
	do {
		tapstatus = get_tapstatus(t);
		if (!((TS_EN_PM_BIT | TS_PRDY_BIT) & tapstatus))
			return ERROR_OK;

		LOG_DEBUG("%s Waiting for PRDY & PM, TS = 0x%08" PRIx32,
						 __func__, tapstatus);
		usleep(100000);
		cnt--;
	} while (cnt);

	return ERROR_FAIL;
	/* TODO: find a nicer way to wait until PM_BIT & PRDY_BIT changes*/

}
Example #8
0
int lakemont_poll(struct target *t)
{
	/* LMT1 PMCR register currently allows code breakpoints, data breakpoints,
	 * single stepping and shutdowns to be redirected to PM but does not allow
	 * redirecting into PM as a result of SMM enter and SMM exit
	 */
	uint32_t ts = get_tapstatus(t);

	if (ts == 0xFFFFFFFF && t->state != TARGET_DEBUG_RUNNING) {
		/* something is wrong here */
		LOG_ERROR("tapstatus invalid - scan_chain serialization or locked JTAG access issues");
		/* TODO: Give a hint that unlocking is wrong or maybe a
		 * 'jtag arp_init' helps
		 */
		t->state = TARGET_DEBUG_RUNNING;
		return ERROR_OK;
	}

	if ((!(ts & TS_PM_BIT))) {
		if (t->state == TARGET_HALTED) {
			LOG_USER("target running for unknown reason");
		} else if (t->state == TARGET_DEBUG_RUNNING) {
			LOG_USER("Debug running tapstatus=0x%08" PRIx32, ts);
		}
		LOG_DEBUG("tapstatus=0x%08" PRIx32, ts);
		t->state = TARGET_RUNNING;
	}


	if (t->state == TARGET_RUNNING ||
		t->state == TARGET_DEBUG_RUNNING) {

		if (ts & TS_PM_BIT) {

			LOG_USER("redirect to PM, tapstatus=0x%08" PRIx32, get_tapstatus(t));

			t->state = TARGET_DEBUG_RUNNING;
			if (save_context(t) != ERROR_OK)
				return ERROR_FAIL;
			if (halt_prep(t) != ERROR_OK)
				return ERROR_FAIL;
			t->state = TARGET_HALTED;
			t->debug_reason = DBG_REASON_UNDEFINED;

			struct x86_32_common *x86_32 = target_to_x86_32(t);
			uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32);
			uint32_t dr6 = buf_get_u32(x86_32->cache->reg_list[DR6].value, 0, 32);
			uint32_t hwbreakpoint = (uint32_t)-1;

			if (dr6 & DR6_BRKDETECT_0)
				hwbreakpoint = 0;
			if (dr6 & DR6_BRKDETECT_1)
				hwbreakpoint = 1;
			if (dr6 & DR6_BRKDETECT_2)
				hwbreakpoint = 2;
			if (dr6 & DR6_BRKDETECT_3)
				hwbreakpoint = 3;

			if (hwbreakpoint != (uint32_t)-1) {
				uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32);
				uint32_t type = dr7 & (0x03 << (DR7_RW_SHIFT + hwbreakpoint*DR7_RW_LEN_SIZE));
				if (type == DR7_BP_EXECUTE) {
					LOG_USER("hit hardware breakpoint (hwreg=%" PRIu32 ") at 0x%08" PRIx32, hwbreakpoint, eip);
				} else {
					uint32_t address = 0;
					switch (hwbreakpoint) {
					default:
					case 0:
						address = buf_get_u32(x86_32->cache->reg_list[DR0].value, 0, 32);
					break;
					case 1:
						address = buf_get_u32(x86_32->cache->reg_list[DR1].value, 0, 32);
					break;
					case 2:
						address = buf_get_u32(x86_32->cache->reg_list[DR2].value, 0, 32);
					break;
					case 3:
						address = buf_get_u32(x86_32->cache->reg_list[DR3].value, 0, 32);
					break;
					}
					LOG_USER("hit '%s' watchpoint for 0x%08" PRIx32 " (hwreg=%" PRIu32 ") at 0x%08" PRIx32,
								type == DR7_BP_WRITE ? "write" : "access", address,
								hwbreakpoint, eip);
				}
				t->debug_reason = DBG_REASON_BREAKPOINT;
			} else {
				/* Check if the target hit a software breakpoint.
				 * ! Watch out: EIP is currently pointing after the breakpoint opcode
				 */
				struct breakpoint *bp = NULL;
				bp = breakpoint_find(t, eip-1);
				if (bp != NULL) {
					t->debug_reason = DBG_REASON_BREAKPOINT;
					if (bp->type == BKPT_SOFT) {
						/* The EIP is now pointing the the next byte after the
						 * breakpoint instruction. This needs to be corrected.
						 */
						buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1);
						x86_32->cache->reg_list[EIP].dirty = 1;
						x86_32->cache->reg_list[EIP].valid = 1;
						LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1);
					} else {
						/* it's not a hardware breakpoint (checked already in DR6 state)
						 * and it's also not a software breakpoint ...
						 */
						LOG_USER("hit unknown breakpoint at 0x%08" PRIx32, eip);
					}
				} else {

					/* There is also the case that we hit an breakpoint instruction,
					 * which was not set by us. This needs to be handled be the
					 * application that introduced the breakpoint.
					 */

					LOG_USER("unknown break reason at 0x%08" PRIx32, eip);
				}
			}

			return target_call_event_callbacks(t, TARGET_EVENT_HALTED);
		}
	}
	return ERROR_OK;
}
Example #9
0
int lakemont_step(struct target *t, int current,
			uint32_t address, int handle_breakpoints)
{
	struct x86_32_common *x86_32 = target_to_x86_32(t);
	uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32);
	uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32);
	uint32_t pmcr = buf_get_u32(x86_32->cache->reg_list[PMCR].value, 0, 32);
	struct breakpoint *bp = NULL;
	int retval = ERROR_OK;
	uint32_t tapstatus = 0;

	if (check_not_halted(t))
		return ERROR_TARGET_NOT_HALTED;
	bp = breakpoint_find(t, eip);
	if (retval == ERROR_OK && bp != NULL/*&& bp->type == BKPT_SOFT*/) {
		/* TODO: This should only be done for software breakpoints.
		 * Stepping from hardware breakpoints should be possible with the resume flag
		 * Needs testing.
		 */
		retval = x86_32_common_remove_breakpoint(t, bp);
	}

	/* Set EFLAGS[TF] and PMCR[IR], exit pm and wait for PRDY# */
	LOG_DEBUG("modifying PMCR = 0x%08" PRIx32 " and EFLAGS = 0x%08" PRIx32, pmcr, eflags);
	eflags = eflags | (EFLAGS_TF | EFLAGS_RF);
	buf_set_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32, eflags);
	buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1);
	LOG_DEBUG("EFLAGS [TF] [RF] bits set=0x%08" PRIx32 ", PMCR=0x%08" PRIx32 ", EIP=0x%08" PRIx32,
			eflags, pmcr, eip);

	tapstatus = get_tapstatus(t);

	t->debug_reason = DBG_REASON_SINGLESTEP;
	t->state = TARGET_DEBUG_RUNNING;
	if (restore_context(t) != ERROR_OK)
		return ERROR_FAIL;
	if (exit_probemode(t) != ERROR_OK)
		return ERROR_FAIL;

	target_call_event_callbacks(t, TARGET_EVENT_RESUMED);

	tapstatus = get_tapstatus(t);
	if (tapstatus & (TS_PM_BIT | TS_EN_PM_BIT | TS_PRDY_BIT | TS_PMCR_BIT)) {
		/* target has stopped */
		if (save_context(t) != ERROR_OK)
			return ERROR_FAIL;
		if (halt_prep(t) != ERROR_OK)
			return ERROR_FAIL;
		t->state = TARGET_HALTED;

		LOG_USER("step done from EIP 0x%08" PRIx32 " to 0x%08" PRIx32, eip,
				buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32));
		target_call_event_callbacks(t, TARGET_EVENT_HALTED);
	} else {
		/* target didn't stop
		 * I hope the poll() will catch it, but the deleted breakpoint is gone
		 */
		LOG_ERROR("%s target didn't stop after executing a single step", __func__);
		t->state = TARGET_RUNNING;
		return ERROR_FAIL;
	}

	/* try to re-apply the breakpoint, even of step failed
	 * TODO: When a bp was set, we should try to stop the target - fix the return above
	 */
	if (bp != NULL/*&& bp->type == BKPT_SOFT*/) {
		/* TODO: This should only be done for software breakpoints.
		 * Stepping from hardware breakpoints should be possible with the resume flag
		 * Needs testing.
		 */
		retval = x86_32_common_add_breakpoint(t, bp);
	}

	return retval;
}