Propagate error instead of calling abort().

As part of this I improved the memory read/write fatal error handling a
bit. Now at least we try to leave autoexec turned off, and will even
restore the temp registers if the situation isn't too hosed for that.

Partly addresses Issue #142

Change-Id: I79fe3f862f11c6d20441f39162423357e73a40c1
fence_i_fix_for_release
Tim Newsome 2017-12-26 15:04:02 -08:00
parent ca700dcef0
commit 06445f5743
3 changed files with 62 additions and 34 deletions

View File

@ -42,11 +42,11 @@ bool riscv_batch_full(struct riscv_batch *batch)
return batch->used_scans > (batch->allocated_scans - 4); return batch->used_scans > (batch->allocated_scans - 4);
} }
void riscv_batch_run(struct riscv_batch *batch) int riscv_batch_run(struct riscv_batch *batch)
{ {
if (batch->used_scans == 0) { if (batch->used_scans == 0) {
LOG_DEBUG("Ignoring empty batch."); LOG_DEBUG("Ignoring empty batch.");
return; return ERROR_OK;
} }
keep_alive(); keep_alive();
@ -63,11 +63,13 @@ void riscv_batch_run(struct riscv_batch *batch)
LOG_DEBUG("executing queue"); LOG_DEBUG("executing queue");
if (jtag_execute_queue() != ERROR_OK) { if (jtag_execute_queue() != ERROR_OK) {
LOG_ERROR("Unable to execute JTAG queue"); LOG_ERROR("Unable to execute JTAG queue");
abort(); return ERROR_FAIL;
} }
for (size_t i = 0; i < batch->used_scans; ++i) for (size_t i = 0; i < batch->used_scans; ++i)
dump_field(batch->fields + i); dump_field(batch->fields + i);
return ERROR_OK;
} }
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data) void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data)

View File

@ -48,7 +48,7 @@ void riscv_batch_free(struct riscv_batch *batch);
bool riscv_batch_full(struct riscv_batch *batch); bool riscv_batch_full(struct riscv_batch *batch);
/* Executes this scan batch. */ /* Executes this scan batch. */
void riscv_batch_run(struct riscv_batch *batch); int riscv_batch_run(struct riscv_batch *batch);
/* Adds a DMI write to this batch. */ /* Adds a DMI write to this batch. */
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data); void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data);

View File

@ -1415,6 +1415,8 @@ static int read_memory(struct target *target, target_addr_t address,
{ {
RISCV013_INFO(info); RISCV013_INFO(info);
int result = ERROR_OK;
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
size, address); size, address);
@ -1456,13 +1458,15 @@ static int read_memory(struct target *target, target_addr_t address,
riscv_program_write(&program); riscv_program_write(&program);
/* Write address to S0, and execute buffer. */ /* Write address to S0, and execute buffer. */
if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK) result = register_write_direct(target, GDB_REGNO_S0, address);
return ERROR_FAIL; if (result != ERROR_OK)
goto error;
uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target), uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_POSTEXEC); AC_ACCESS_REGISTER_POSTEXEC);
if (execute_abstract_command(target, command) != ERROR_OK) result = execute_abstract_command(target, command);
return ERROR_FAIL; if (result != ERROR_OK)
goto error;
/* First read has just triggered. Result is in s1. */ /* First read has just triggered. Result is in s1. */
@ -1559,8 +1563,12 @@ static int read_memory(struct target *target, target_addr_t address,
dmi_data0 = dmi_read(target, DMI_DATA0); dmi_data0 = dmi_read(target, DMI_DATA0);
/* Clobbers DMI_DATA0. */ /* Clobbers DMI_DATA0. */
if (register_read_direct(target, &next_read_addr, GDB_REGNO_S0) != ERROR_OK) result = register_read_direct(target, &next_read_addr,
return ERROR_FAIL; GDB_REGNO_S0);
if (result != ERROR_OK) {
riscv_batch_free(batch);
goto error;
}
/* Restore the command, and execute it. /* Restore the command, and execute it.
* Now DMI_DATA0 contains the next value just as it would if no * Now DMI_DATA0 contains the next value just as it would if no
* error had occurred. */ * error had occurred. */
@ -1571,12 +1579,10 @@ static int read_memory(struct target *target, target_addr_t address,
break; break;
default: default:
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
dmi_write(target, DMI_ABSTRACTAUTO, 0);
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
riscv013_clear_abstract_error(target); riscv013_clear_abstract_error(target);
riscv_batch_free(batch); riscv_batch_free(batch);
return ERROR_FAIL; result = ERROR_FAIL;
goto error;
} }
/* Now read whatever we got out of the batch. */ /* Now read whatever we got out of the batch. */
@ -1624,8 +1630,9 @@ static int read_memory(struct target *target, target_addr_t address,
/* Read the last word. */ /* Read the last word. */
uint64_t value; uint64_t value;
if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK) result = register_read_direct(target, &value, GDB_REGNO_S1);
return ERROR_FAIL; if (result != ERROR_OK)
goto error;
write_to_buf(buffer + receive_addr - address, value, size); write_to_buf(buffer + receive_addr - address, value, size);
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value); LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value);
receive_addr += size; receive_addr += size;
@ -1633,6 +1640,13 @@ static int read_memory(struct target *target, target_addr_t address,
riscv_set_register(target, GDB_REGNO_S0, s0); riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1); riscv_set_register(target, GDB_REGNO_S1, s1);
return ERROR_OK; return ERROR_OK;
error:
dmi_write(target, DMI_ABSTRACTAUTO, 0);
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
return result;
} }
static int write_memory(struct target *target, target_addr_t address, static int write_memory(struct target *target, target_addr_t address,
@ -1648,6 +1662,7 @@ static int write_memory(struct target *target, target_addr_t address,
* s1 holds the next data value to write * s1 holds the next data value to write
*/ */
int result = ERROR_OK;
uint64_t s0, s1; uint64_t s0, s1;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -1670,13 +1685,15 @@ static int write_memory(struct target *target, target_addr_t address,
break; break;
default: default:
LOG_ERROR("Unsupported size: %d", size); LOG_ERROR("Unsupported size: %d", size);
return ERROR_FAIL; result = ERROR_FAIL;
goto error;
} }
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
if (riscv_program_ebreak(&program) != ERROR_OK) result = riscv_program_ebreak(&program);
return ERROR_FAIL; if (result != ERROR_OK)
goto error;
riscv_program_write(&program); riscv_program_write(&program);
riscv_addr_t cur_addr = address; riscv_addr_t cur_addr = address;
@ -1715,16 +1732,21 @@ static int write_memory(struct target *target, target_addr_t address,
break; break;
default: default:
LOG_ERROR("unsupported access size: %d", size); LOG_ERROR("unsupported access size: %d", size);
return ERROR_FAIL; riscv_batch_free(batch);
result = ERROR_FAIL;
goto error;
} }
LOG_DEBUG("M[0x%08" PRIx64 "] writes 0x%08x", address + offset, value); LOG_DEBUG("M[0x%08" PRIx64 "] writes 0x%08x", address + offset, value);
cur_addr += size; cur_addr += size;
if (setup_needed) { if (setup_needed) {
if (register_write_direct(target, GDB_REGNO_S0, result = register_write_direct(target, GDB_REGNO_S0,
address + offset) != ERROR_OK) address + offset);
return ERROR_FAIL; if (result != ERROR_OK) {
riscv_batch_free(batch);
goto error;
}
/* Write value. */ /* Write value. */
dmi_write(target, DMI_DATA0, value); dmi_write(target, DMI_DATA0, value);
@ -1735,9 +1757,11 @@ static int write_memory(struct target *target, target_addr_t address,
AC_ACCESS_REGISTER_POSTEXEC | AC_ACCESS_REGISTER_POSTEXEC |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE); AC_ACCESS_REGISTER_WRITE);
int result = execute_abstract_command(target, command); result = execute_abstract_command(target, command);
if (result != ERROR_OK) if (result != ERROR_OK) {
return result; riscv_batch_free(batch);
goto error;
}
/* Turn on autoexec */ /* Turn on autoexec */
dmi_write(target, DMI_ABSTRACTAUTO, dmi_write(target, DMI_ABSTRACTAUTO,
@ -1751,8 +1775,10 @@ static int write_memory(struct target *target, target_addr_t address,
} }
} }
riscv_batch_run(batch); result = riscv_batch_run(batch);
riscv_batch_free(batch); riscv_batch_free(batch);
if (result != ERROR_OK)
goto error;
/* Note that if the scan resulted in a Busy DMI response, it /* Note that if the scan resulted in a Busy DMI response, it
* is this read to abstractcs that will cause the dmi_busy_delay * is this read to abstractcs that will cause the dmi_busy_delay
@ -1772,21 +1798,21 @@ static int write_memory(struct target *target, target_addr_t address,
increase_ac_busy_delay(target); increase_ac_busy_delay(target);
dmi_write(target, DMI_ABSTRACTAUTO, 0); dmi_write(target, DMI_ABSTRACTAUTO, 0);
if (register_read_direct(target, &cur_addr, GDB_REGNO_S0) != ERROR_OK) result = register_read_direct(target, &cur_addr, GDB_REGNO_S0);
return ERROR_FAIL; if (result != ERROR_OK)
goto error;
setup_needed = true; setup_needed = true;
break; break;
default: default:
LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs); LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs);
dmi_write(target, DMI_ABSTRACTAUTO, 0);
riscv013_clear_abstract_error(target); riscv013_clear_abstract_error(target);
riscv_set_register(target, GDB_REGNO_S0, s0); result = ERROR_FAIL;
riscv_set_register(target, GDB_REGNO_S1, s1); goto error;
return ERROR_FAIL;
} }
} }
error:
dmi_write(target, DMI_ABSTRACTAUTO, 0); dmi_write(target, DMI_ABSTRACTAUTO, 0);
if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK)
@ -1797,7 +1823,7 @@ static int write_memory(struct target *target, target_addr_t address,
if (execute_fence(target) != ERROR_OK) if (execute_fence(target) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
return ERROR_OK; return result;
} }
static int arch_state(struct target *target) static int arch_state(struct target *target)