aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jtag/drivers/mpsse.c7
-rw-r--r--src/rtos/riscv_debug.c8
-rw-r--r--src/server/gdb_server.c4
-rw-r--r--src/target/riscv/batch.c14
-rw-r--r--src/target/riscv/riscv-013.c63
-rw-r--r--src/target/riscv/riscv.c50
-rw-r--r--src/target/startup.tcl1
7 files changed, 102 insertions, 45 deletions
diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
index 06d008b..6c70be6 100644
--- a/src/jtag/drivers/mpsse.c
+++ b/src/jtag/drivers/mpsse.c
@@ -22,6 +22,7 @@
#include "mpsse.h"
#include "helper/log.h"
+#include "helper/time_support.h"
#include <libusb.h>
/* Compatibility define for older libusb-1.0 */
@@ -892,6 +893,7 @@ int mpsse_flush(struct mpsse_ctx *ctx)
}
/* Polling loop, more or less taken from libftdi */
+ int64_t start = timeval_ms();
while (!write_result.done || !read_result.done) {
struct timeval timeout_usb;
@@ -914,6 +916,11 @@ int mpsse_flush(struct mpsse_ctx *ctx)
break;
}
}
+
+ if (timeval_ms() - start > 2000) {
+ LOG_ERROR("Timed out handling USB events in mpsse_flush().");
+ break;
+ }
}
error_check:
diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c
index 6703008..dade798 100644
--- a/src/rtos/riscv_debug.c
+++ b/src/rtos/riscv_debug.c
@@ -124,7 +124,12 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
return ERROR_OK;
}
- if (strcmp(packet, "qC") == 0) {
+ if (strncmp(packet, "qTStatus", 8) == 0) {
+ gdb_put_packet(connection, "T0", strlen("T0"));
+ return ERROR_OK;
+ }
+
+ if (strncmp(packet, "qC", 2) == 0) {
char rep_str[32];
snprintf(rep_str, 32, "QC%" PRIx64, rtos->current_threadid);
gdb_put_packet(connection, rep_str, strlen(rep_str));
@@ -250,6 +255,7 @@ static int riscv_gdb_v_packet(struct connection *connection, const char *packet,
if (strcmp(packet_stttrr, "vCont;c") == 0) {
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
target_call_event_callbacks(target, TARGET_EVENT_RESUME_START);
+ riscv_set_all_rtos_harts(target);
riscv_openocd_resume(target, 1, 0, 0, 0);
target->state = TARGET_RUNNING;
gdb_set_frontend_state_running(connection);
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 3ea3242..918f99b 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -781,6 +781,10 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
gdb_connection->ctrl_c = 0;
}
+ char sig_reply_str[46];
+ memset(sig_reply_str, '\0', 46);
+ strncpy(sig_reply_str, sig_reply, 46);
+ LOG_DEBUG("signal reply: %s", sig_reply_str);
gdb_put_packet(connection, sig_reply, sig_reply_len);
gdb_connection->frontend_state = TARGET_HALTED;
}
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 9327cb3..6b3bede 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -51,7 +51,7 @@ int riscv_batch_run(struct riscv_batch *batch)
keep_alive();
- LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans);
+ LOG_DEBUG_IO("running a batch of %ld scans", (long)batch->used_scans);
riscv_batch_add_nop(batch);
for (size_t i = 0; i < batch->used_scans; ++i) {
@@ -60,7 +60,7 @@ int riscv_batch_run(struct riscv_batch *batch)
jtag_add_runtest(batch->idle_count, TAP_IDLE);
}
- LOG_DEBUG("executing queue");
+ LOG_DEBUG_IO("executing queue");
if (jtag_execute_queue() != ERROR_OK) {
LOG_ERROR("Unable to execute JTAG queue");
return ERROR_FAIL;
@@ -102,7 +102,7 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
riscv_batch_add_nop(batch);
batch->read_keys[batch->read_keys_used] = batch->used_scans - 1;
- LOG_DEBUG("read key %u for batch 0x%p is %u (0x%p)",
+ LOG_DEBUG_IO("read key %u for batch 0x%p is %u (0x%p)",
(unsigned) batch->read_keys_used, batch, (unsigned) (batch->used_scans - 1),
batch->data_in + sizeof(uint64_t) * (batch->used_scans + 1));
return batch->read_keys_used++;
@@ -135,7 +135,7 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
batch->last_scan = RISCV_SCAN_TYPE_NOP;
batch->used_scans++;
- LOG_DEBUG(" added NOP with in_value=0x%p", field->in_value);
+ LOG_DEBUG_IO(" added NOP with in_value=0x%p", field->in_value);
}
void dump_field(const struct scan_field *field)
@@ -143,7 +143,7 @@ void dump_field(const struct scan_field *field)
static const char * const op_string[] = {"-", "r", "w", "?"};
static const char * const status_string[] = {"+", "?", "F", "b"};
- if (debug_level < LOG_LVL_DEBUG)
+ if (debug_level < LOG_LVL_DEBUG_IO)
return;
assert(field->out_value != NULL);
@@ -158,14 +158,14 @@ void dump_field(const struct scan_field *field)
unsigned int in_data = get_field(in, DTM_DMI_DATA);
unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
- log_printf_lf(LOG_LVL_DEBUG,
+ log_printf_lf(LOG_LVL_DEBUG_IO,
__FILE__, __LINE__, __PRETTY_FUNCTION__,
"%db %s %08x @%02x -> %s %08x @%02x",
field->num_bits,
op_string[out_op], out_data, out_address,
status_string[in_op], in_data, in_address);
} else {
- log_printf_lf(LOG_LVL_DEBUG,
+ log_printf_lf(LOG_LVL_DEBUG_IO,
__FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?",
field->num_bits, op_string[out_op], out_data, out_address);
}
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 7a7245f..350d333 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -458,14 +458,18 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
bool exec)
{
riscv013_info_t *info = get_info(target);
- uint8_t in[8] = {0};
- uint8_t out[8];
+ unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH;
+ size_t num_bytes = (num_bits + 7) / 8;
+ uint8_t in[num_bytes];
+ uint8_t out[num_bytes];
struct scan_field field = {
- .num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH,
+ .num_bits = num_bits,
.out_value = out,
.in_value = in
};
+ memset(in, 0, num_bytes);
+
assert(info->abits != 0);
buf_set_u32(out, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, op);
@@ -1767,13 +1771,38 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
static int execute_fence(struct target *target)
{
- struct riscv_program program;
- riscv_program_init(&program, target);
- riscv_program_fence(&program);
- int result = riscv_program_exec(&program, target);
- if (result != ERROR_OK)
- LOG_ERROR("Unable to execute fence");
- return result;
+ int old_hartid = riscv_current_hartid(target);
+
+ /* FIXME: For non-coherent systems we need to flush the caches right
+ * here, but there's no ISA-defined way of doing that. */
+ {
+ struct riscv_program program;
+ riscv_program_init(&program, target);
+ riscv_program_fence_i(&program);
+ riscv_program_fence(&program);
+ int result = riscv_program_exec(&program, target);
+ if (result != ERROR_OK)
+ LOG_DEBUG("Unable to execute pre-fence");
+ }
+
+ for (int i = 0; i < riscv_count_harts(target); ++i) {
+ if (!riscv_hart_enabled(target, i))
+ continue;
+
+ riscv_set_current_hartid(target, i);
+
+ struct riscv_program program;
+ riscv_program_init(&program, target);
+ riscv_program_fence_i(&program);
+ riscv_program_fence(&program);
+ int result = riscv_program_exec(&program, target);
+ if (result != ERROR_OK)
+ LOG_DEBUG("Unable to execute fence on hart %d", i);
+ }
+
+ riscv_set_current_hartid(target, old_hartid);
+
+ return ERROR_OK;
}
static void log_memory_access(target_addr_t address, uint64_t value,
@@ -3336,19 +3365,7 @@ int riscv013_dmi_write_u64_bits(struct target *target)
static int maybe_execute_fence_i(struct target *target)
{
- RISCV013_INFO(info);
- RISCV_INFO(r);
- if (info->progbufsize + r->impebreak >= 2) {
- struct riscv_program program;
- riscv_program_init(&program, target);
- if (riscv_program_fence_i(&program) != ERROR_OK)
- return ERROR_FAIL;
- if (riscv_program_exec(&program, target) != ERROR_OK) {
- LOG_ERROR("Failed to execute fence.i");
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
+ return execute_fence(target);
}
/* Helper Functions. */
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 0ba2e15..30efc8b 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -266,6 +266,8 @@ static int riscv_init_target(struct command_context *cmd_ctx,
riscv_semihosting_init(target);
+ target->debug_reason = DBG_REASON_DBGRQ;
+
return ERROR_OK;
}
@@ -280,12 +282,17 @@ static void riscv_deinit_target(struct target *target)
free(info);
}
/* Free the shared structure use for most registers. */
- free(target->reg_cache->reg_list[0].arch_info);
- /* Free the ones we allocated separately. */
- for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++)
- free(target->reg_cache->reg_list[i].arch_info);
- free(target->reg_cache->reg_list);
- free(target->reg_cache);
+ if (target->reg_cache) {
+ if (target->reg_cache->reg_list) {
+ if (target->reg_cache->reg_list[0].arch_info)
+ free(target->reg_cache->reg_list[0].arch_info);
+ /* Free the ones we allocated separately. */
+ for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++)
+ free(target->reg_cache->reg_list[i].arch_info);
+ free(target->reg_cache->reg_list);
+ }
+ free(target->reg_cache);
+ }
target->arch_info = NULL;
}
@@ -855,9 +862,11 @@ static int old_or_new_riscv_resume(
static int riscv_select_current_hart(struct target *target)
{
RISCV_INFO(r);
- if (r->rtos_hartid != -1 && riscv_rtos_enabled(target))
+ if (riscv_rtos_enabled(target)) {
+ if (r->rtos_hartid == -1)
+ r->rtos_hartid = target->rtos->current_threadid - 1;
return riscv_set_current_hartid(target, r->rtos_hartid);
- else
+ } else
return riscv_set_current_hartid(target, target->coreid);
}
@@ -1195,8 +1204,12 @@ int riscv_openocd_halt(struct target *target)
register_cache_invalidate(target->reg_cache);
if (riscv_rtos_enabled(target)) {
- target->rtos->current_threadid = r->rtos_hartid + 1;
- target->rtos->current_thread = r->rtos_hartid + 1;
+ if (r->rtos_hartid != -1) {
+ LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid);
+ target->rtos->current_threadid = r->rtos_hartid + 1;
+ target->rtos->current_thread = r->rtos_hartid + 1;
+ } else
+ LOG_DEBUG("halt requested, but no known RTOS hartid");
}
target->state = TARGET_HALTED;
@@ -1816,6 +1829,8 @@ int riscv_halt_all_harts(struct target *target)
riscv_halt_one_hart(target, i);
}
+ riscv_invalidate_register_cache(target);
+
return ERROR_OK;
}
@@ -1868,7 +1883,7 @@ int riscv_step_rtos_hart(struct target *target)
if (riscv_rtos_enabled(target)) {
hartid = r->rtos_hartid;
if (hartid == -1) {
- LOG_USER("GDB has asked me to step \"any\" thread, so I'm stepping hart 0.");
+ LOG_DEBUG("GDB has asked me to step \"any\" thread, so I'm stepping hart 0.");
hartid = 0;
}
}
@@ -1941,14 +1956,15 @@ int riscv_set_current_hartid(struct target *target, int hartid)
if (!target_was_examined(target))
return ERROR_OK;
+#if 0
/* Avoid invalidating the register cache all the time. */
if (r->registers_initialized
&& (!riscv_rtos_enabled(target) || (previous_hartid == hartid))
- && target->reg_cache->reg_list[GDB_REGNO_ZERO].size == (unsigned)riscv_xlen(target)
- && (!riscv_rtos_enabled(target) || (r->rtos_hartid != -1))) {
+ && target->reg_cache->reg_list[GDB_REGNO_ZERO].size == (unsigned)riscv_xlen(target) {
return ERROR_OK;
} else
LOG_DEBUG("Initializing registers: xlen=%d", riscv_xlen(target));
+#endif
riscv_invalidate_register_cache(target);
return ERROR_OK;
@@ -2030,7 +2046,15 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
int hartid, enum gdb_regno regid)
{
RISCV_INFO(r);
+
+ if (hartid != riscv_current_hartid(target))
+ riscv_invalidate_register_cache(target);
+
int result = r->get_register(target, value, hartid, regid);
+
+ if (hartid != riscv_current_hartid(target))
+ riscv_invalidate_register_cache(target);
+
LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), *value);
return result;
}
diff --git a/src/target/startup.tcl b/src/target/startup.tcl
index cf844e1..9bbc6e3 100644
--- a/src/target/startup.tcl
+++ b/src/target/startup.tcl
@@ -203,7 +203,6 @@ proc init_target_events {} {
foreach t $targets {
set_default_target_event $t gdb-flash-erase-start "reset init"
set_default_target_event $t gdb-flash-write-end "reset halt"
- set_default_target_event $t gdb-attach "halt"
}
}