Compare commits

...

15 Commits

6 changed files with 157 additions and 81 deletions

View File

@ -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);

View File

@ -390,7 +390,7 @@ static int gdb_put_packet_inner(struct connection *connection,
break;
}
LOG_WARNING("Discard unexpected char %c", reply);
LOG_DEBUG("Discard unexpected char %c", reply);
}
#endif
@ -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;
}

View File

@ -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);
}

View File

@ -1771,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,
@ -2040,53 +2065,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
* Read the requested memory, taking care to execute every read exactly once,
* even if cmderr=busy is encountered.
*/
static int read_memory_progbuf(struct target *target, target_addr_t address,
static int read_memory_progbuf_inner(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
RISCV013_INFO(info);
int result = ERROR_OK;
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
size, address);
select_dmi(target);
/* s0 holds the next address to write to
* s1 holds the next data value to write
*/
uint64_t s0, s1;
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
if (execute_fence(target) != ERROR_OK)
return ERROR_FAIL;
/* Write the program (load, increment) */
struct riscv_program program;
riscv_program_init(&program, target);
switch (size) {
case 1:
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
case 2:
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
case 4:
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
default:
LOG_ERROR("Unsupported size: %d", size);
return ERROR_FAIL;
}
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
if (riscv_program_ebreak(&program) != ERROR_OK)
return ERROR_FAIL;
riscv_program_write(&program);
/* Write address to S0, and execute buffer. */
result = register_write_direct(target, GDB_REGNO_S0, address);
if (result != ERROR_OK)
@ -2214,7 +2199,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
break;
default:
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
riscv013_clear_abstract_error(target);
riscv_batch_free(batch);
result = ERROR_FAIL;
@ -2272,13 +2257,88 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
write_to_buf(buffer + receive_addr - address, value, size);
log_memory_access(receive_addr, value, size, true);
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
return ERROR_OK;
error:
dmi_write(target, DMI_ABSTRACTAUTO, 0);
return result;
}
/**
* Read the requested memory, silently handling memory access errors.
*/
static int read_memory_progbuf(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
int result = ERROR_OK;
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
size, address);
select_dmi(target);
/* s0 holds the next address to write to
* s1 holds the next data value to write
*/
uint64_t s0, s1;
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
if (execute_fence(target) != ERROR_OK)
return ERROR_FAIL;
/* Write the program (load, increment) */
struct riscv_program program;
riscv_program_init(&program, target);
switch (size) {
case 1:
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
case 2:
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
case 4:
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
break;
default:
LOG_ERROR("Unsupported size: %d", size);
return ERROR_FAIL;
}
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
if (riscv_program_ebreak(&program) != ERROR_OK)
return ERROR_FAIL;
riscv_program_write(&program);
result = read_memory_progbuf_inner(target, address, size, count, buffer);
/* The full read did not succeed, so we will try to read each word individually. */
/* This will not be fast, but reading outside actual memory is a special case anyway. */
/* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */
if (result != ERROR_OK) {
target_addr_t address_i = address;
uint32_t size_i = size;
uint32_t count_i = 1;
uint8_t *buffer_i = buffer;
for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) {
result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i);
/* The read of a single word failed, so we will just return 0 for that instead */
if (result != ERROR_OK) {
LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR,
size_i, address_i);
uint64_t value_i = 0;
write_to_buf(buffer_i, value_i, size_i);
}
}
result = ERROR_OK;
}
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
return result;
@ -3305,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. */

View File

@ -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;
}
@ -860,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);
}
@ -1200,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;
@ -1821,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;
}
@ -1873,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;
}
}
@ -1946,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;
@ -2035,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;
}

View File

@ -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"
}
}