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
This commit is contained in:
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);
}
void riscv_batch_run(struct riscv_batch *batch)
int riscv_batch_run(struct riscv_batch *batch)
{
if (batch->used_scans == 0) {
LOG_DEBUG("Ignoring empty batch.");
return;
return ERROR_OK;
}
keep_alive();
@ -63,11 +63,13 @@ void riscv_batch_run(struct riscv_batch *batch)
LOG_DEBUG("executing queue");
if (jtag_execute_queue() != ERROR_OK) {
LOG_ERROR("Unable to execute JTAG queue");
abort();
return ERROR_FAIL;
}
for (size_t i = 0; i < batch->used_scans; ++i)
dump_field(batch->fields + i);
return ERROR_OK;
}
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);
/* 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. */
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);
int result = ERROR_OK;
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
size, address);
@ -1456,13 +1458,15 @@ static int read_memory(struct target *target, target_addr_t address,
riscv_program_write(&program);
/* Write address to S0, and execute buffer. */
if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK)
return ERROR_FAIL;
result = register_write_direct(target, GDB_REGNO_S0, address);
if (result != ERROR_OK)
goto error;
uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_POSTEXEC);
if (execute_abstract_command(target, command) != ERROR_OK)
return ERROR_FAIL;
result = execute_abstract_command(target, command);
if (result != ERROR_OK)
goto error;
/* 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);
/* Clobbers DMI_DATA0. */
if (register_read_direct(target, &next_read_addr, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
result = register_read_direct(target, &next_read_addr,
GDB_REGNO_S0);
if (result != ERROR_OK) {
riscv_batch_free(batch);
goto error;
}
/* Restore the command, and execute it.
* Now DMI_DATA0 contains the next value just as it would if no
* error had occurred. */
@ -1571,12 +1579,10 @@ static int read_memory(struct target *target, target_addr_t address,
break;
default:
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);
riscv_batch_free(batch);
return ERROR_FAIL;
result = ERROR_FAIL;
goto error;
}
/* 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. */
uint64_t value;
if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
result = register_read_direct(target, &value, GDB_REGNO_S1);
if (result != ERROR_OK)
goto error;
write_to_buf(buffer + receive_addr - address, value, size);
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value);
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_S1, s1);
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,
@ -1648,6 +1662,7 @@ static int write_memory(struct target *target, target_addr_t address,
* s1 holds the next data value to write
*/
int result = ERROR_OK;
uint64_t s0, s1;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
@ -1670,13 +1685,15 @@ static int write_memory(struct target *target, target_addr_t address,
break;
default:
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);
if (riscv_program_ebreak(&program) != ERROR_OK)
return ERROR_FAIL;
result = riscv_program_ebreak(&program);
if (result != ERROR_OK)
goto error;
riscv_program_write(&program);
riscv_addr_t cur_addr = address;
@ -1715,16 +1732,21 @@ static int write_memory(struct target *target, target_addr_t address,
break;
default:
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);
cur_addr += size;
if (setup_needed) {
if (register_write_direct(target, GDB_REGNO_S0,
address + offset) != ERROR_OK)
return ERROR_FAIL;
result = register_write_direct(target, GDB_REGNO_S0,
address + offset);
if (result != ERROR_OK) {
riscv_batch_free(batch);
goto error;
}
/* Write 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_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
int result = execute_abstract_command(target, command);
if (result != ERROR_OK)
return result;
result = execute_abstract_command(target, command);
if (result != ERROR_OK) {
riscv_batch_free(batch);
goto error;
}
/* Turn on autoexec */
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);
if (result != ERROR_OK)
goto error;
/* Note that if the scan resulted in a Busy DMI response, it
* 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);
dmi_write(target, DMI_ABSTRACTAUTO, 0);
if (register_read_direct(target, &cur_addr, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
result = register_read_direct(target, &cur_addr, GDB_REGNO_S0);
if (result != ERROR_OK)
goto error;
setup_needed = true;
break;
default:
LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs);
dmi_write(target, DMI_ABSTRACTAUTO, 0);
riscv013_clear_abstract_error(target);
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
return ERROR_FAIL;
result = ERROR_FAIL;
goto error;
}
}
error:
dmi_write(target, DMI_ABSTRACTAUTO, 0);
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)
return ERROR_FAIL;
return ERROR_OK;
return result;
}
static int arch_state(struct target *target)