aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/lakemont.c129
-rw-r--r--src/target/x86_32_common.c32
-rw-r--r--src/target/x86_32_common.h2
3 files changed, 160 insertions, 3 deletions
diff --git a/src/target/lakemont.c b/src/target/lakemont.c
index 5f92f0d1..b81213eb 100644
--- a/src/target/lakemont.c
+++ b/src/target/lakemont.c
@@ -970,6 +970,7 @@ int lakemont_poll(struct target *t)
return target_call_event_callbacks(t, TARGET_EVENT_HALTED);
}
}
+
return ERROR_OK;
}
@@ -1115,15 +1116,137 @@ int lakemont_step(struct target *t, int current,
return retval;
}
-/* TODO - implement resetbreak fully through CLTAP registers */
+static int lakemont_reset_break(struct target *t)
+{
+ struct x86_32_common *x86_32 = target_to_x86_32(t);
+ struct jtag_tap *saved_tap = x86_32->curr_tap;
+ struct scan_field *fields = &scan.field;
+
+ int retval = ERROR_OK;
+
+ LOG_DEBUG("issuing port 0xcf9 reset");
+
+ /* prepare resetbreak setting the proper bits in CLTAPC_CPU_VPREQ */
+ x86_32->curr_tap = jtag_tap_by_position(1);
+ if (x86_32->curr_tap == NULL) {
+ x86_32->curr_tap = saved_tap;
+ LOG_ERROR("%s could not select quark_x10xx.cltap", __func__);
+ return ERROR_FAIL;
+ }
+
+ fields->in_value = NULL;
+ fields->num_bits = 8;
+
+ /* select CLTAPC_CPU_VPREQ instruction*/
+ scan.out[0] = 0x51;
+ fields->out_value = ((uint8_t *)scan.out);
+ jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE);
+ retval = jtag_execute_queue();
+ if (retval != ERROR_OK) {
+ x86_32->curr_tap = saved_tap;
+ LOG_ERROR("%s irscan failed to execute queue", __func__);
+ return retval;
+ }
+
+ /* set enable_preq_on_reset & enable_preq_on_reset2 bits*/
+ scan.out[0] = 0x06;
+ fields->out_value = ((uint8_t *)scan.out);
+ jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE);
+ retval = jtag_execute_queue();
+ if (retval != ERROR_OK) {
+ LOG_ERROR("%s drscan failed to execute queue", __func__);
+ x86_32->curr_tap = saved_tap;
+ return retval;
+ }
+
+ /* restore current tap */
+ x86_32->curr_tap = saved_tap;
+
+ return ERROR_OK;
+}
+
+/*
+ * If we ever get an adapter with support for PREQ# and PRDY#, we should
+ * update this function to add support for using those two signals.
+ *
+ * Meanwhile, we're assuming that we only support reset break.
+ */
int lakemont_reset_assert(struct target *t)
{
- LOG_DEBUG("-");
+ struct x86_32_common *x86_32 = target_to_x86_32(t);
+ /* write 0x6 to I/O port 0xcf9 to cause the reset */
+ uint8_t cf9_reset_val = 0x6;
+ int retval;
+
+ LOG_DEBUG(" ");
+
+ if (t->state != TARGET_HALTED) {
+ LOG_DEBUG("target must be halted first");
+ retval = lakemont_halt(t);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("could not halt target");
+ return retval;
+ }
+ x86_32->forced_halt_for_reset = true;
+ }
+
+ if (t->reset_halt) {
+ retval = lakemont_reset_break(t);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ retval = x86_32_common_write_io(t, 0xcf9, BYTE, &cf9_reset_val);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("could not write to port 0xcf9");
+ return retval;
+ }
+
+ if (!t->reset_halt && x86_32->forced_halt_for_reset) {
+ x86_32->forced_halt_for_reset = false;
+ retval = lakemont_resume(t, true, 0x00, false, true);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ /* remove breakpoints and watchpoints */
+ x86_32_common_reset_breakpoints_watchpoints(t);
+
return ERROR_OK;
}
int lakemont_reset_deassert(struct target *t)
{
- LOG_DEBUG("-");
+ int retval;
+
+ LOG_DEBUG(" ");
+
+ if (target_was_examined(t)) {
+ retval = lakemont_poll(t);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ if (t->reset_halt) {
+ /* entered PM after reset, update the state */
+ retval = lakemont_update_after_probemode_entry(t);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("could not update state after probemode entry");
+ return retval;
+ }
+
+ if (t->state != TARGET_HALTED) {
+ LOG_WARNING("%s: ran after reset and before halt ...",
+ target_name(t));
+ if (target_was_examined(t)) {
+ retval = target_halt(t);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ t->state = TARGET_UNKNOWN;
+ }
+ }
+ }
+
return ERROR_OK;
}
diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c
index 34f92eac..0d87ba5a 100644
--- a/src/target/x86_32_common.c
+++ b/src/target/x86_32_common.c
@@ -1260,6 +1260,38 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp)
return ERROR_OK;
}
+/* after reset breakpoints and watchpoints in memory are not valid anymore and
+ * debug registers are cleared.
+ * we can't afford to remove sw breakpoints using the default methods as the
+ * memory doesn't have the same layout yet and an access might crash the target,
+ * so we just clear the openocd breakpoints structures.
+ */
+void x86_32_common_reset_breakpoints_watchpoints(struct target *t)
+{
+ struct x86_32_common *x86_32 = target_to_x86_32(t);
+ struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
+ struct breakpoint *next_b;
+ struct watchpoint *next_w;
+
+ while (t->breakpoints) {
+ next_b = t->breakpoints->next;
+ free(t->breakpoints->orig_instr);
+ free(t->breakpoints);
+ t->breakpoints = next_b;
+ }
+
+ while (t->watchpoints) {
+ next_w = t->watchpoints->next;
+ free(t->watchpoints);
+ t->watchpoints = next_w;
+ }
+
+ for (int i = 0; i < x86_32->num_hw_bpoints; i++) {
+ debug_reg_list[i].used = 0;
+ debug_reg_list[i].bp_value = 0;
+ }
+}
+
static int read_hw_reg_to_cache(struct target *t, int num)
{
uint32_t reg_value;
diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h
index 0aaa963d..14e6e35f 100644
--- a/src/target/x86_32_common.h
+++ b/src/target/x86_32_common.h
@@ -217,6 +217,7 @@ struct x86_32_common {
struct reg_cache *cache;
struct jtag_tap *curr_tap;
uint32_t stored_pc;
+ int forced_halt_for_reset;
int flush;
/* pm_regs are for probemode save/restore state */
@@ -326,5 +327,6 @@ int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp);
int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp);
int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp);
int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp);
+void x86_32_common_reset_breakpoints_watchpoints(struct target *t);
#endif /* OPENOCD_TARGET_X86_32_COMMON_H */