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:
parent
ca700dcef0
commit
06445f5743
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue