Memtest{16,32} pass.

Change-Id: I15c2a4fd2bb9a7b30762d07f3b3a74d2f477746b
This commit is contained in:
Tim Newsome 2017-10-16 20:38:35 -07:00
parent 7ec7bc32fe
commit d94b38279a
4 changed files with 125 additions and 216 deletions

View File

@ -32,17 +32,12 @@ int riscv_program_init(struct riscv_program *p, struct target *target)
for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i) for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
p->debug_buffer[i] = -1; p->debug_buffer[i] = -1;
if (riscv_debug_buffer_enter(target, p) != ERROR_OK) {
LOG_ERROR("unable to write progam buffer enter code");
return ERROR_FAIL;
}
return ERROR_OK; return ERROR_OK;
} }
int riscv_program_write(struct riscv_program *program) int riscv_program_write(struct riscv_program *program)
{ {
for (unsigned i = 0; i < riscv_debug_buffer_size(program->target); ++i) { for (unsigned i = 0; i < program->instruction_count; ++i) {
LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", program, i, program->debug_buffer[i]); LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", program, i, program->debug_buffer[i]);
if (riscv_write_debug_buffer(program->target, i, if (riscv_write_debug_buffer(program->target, i,
program->debug_buffer[i]) != ERROR_OK) program->debug_buffer[i]) != ERROR_OK)
@ -56,11 +51,6 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
{ {
keep_alive(); keep_alive();
if (riscv_debug_buffer_leave(t, p) != ERROR_OK) {
LOG_ERROR("unable to write program buffer exit code");
return ERROR_FAIL;
}
riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1]; riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1];
for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) { for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) {
if (p->writes_xreg[i]) { if (p->writes_xreg[i]) {
@ -290,6 +280,11 @@ int riscv_program_fence(struct riscv_program *p)
int riscv_program_ebreak(struct riscv_program *p) int riscv_program_ebreak(struct riscv_program *p)
{ {
if (p->instruction_count == riscv_debug_buffer_size(p->target)) {
// TODO: Check for impebreak bit.
// There's an implicit ebreak here, so no need for us to add one.
return ERROR_OK;
}
return riscv_program_insert(p, ebreak()); return riscv_program_insert(p, ebreak());
} }
@ -441,7 +436,7 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
LOG_ERROR(" instruction_count=%d", (int)p->instruction_count); LOG_ERROR(" instruction_count=%d", (int)p->instruction_count);
LOG_ERROR(" data_count =%d", (int)p->data_count); LOG_ERROR(" data_count =%d", (int)p->data_count);
LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target)); LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target));
return ERROR_FAIL; abort();
} }
p->debug_buffer[p->instruction_count] = i; p->debug_buffer[p->instruction_count] = i;

View File

@ -49,8 +49,6 @@ static void riscv013_on_step(struct target *target);
static void riscv013_on_resume(struct target *target); static void riscv013_on_resume(struct target *target);
static bool riscv013_is_halted(struct target *target); static bool riscv013_is_halted(struct target *target);
static enum riscv_halt_reason riscv013_halt_reason(struct target *target); static enum riscv_halt_reason riscv013_halt_reason(struct target *target);
static void riscv013_debug_buffer_enter(struct target *target, struct riscv_program *p);
static void riscv013_debug_buffer_leave(struct target *target, struct riscv_program *p);
static void riscv013_write_debug_buffer(struct target *target, unsigned index, static void riscv013_write_debug_buffer(struct target *target, unsigned index,
riscv_insn_t d); riscv_insn_t d);
static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned
@ -637,11 +635,12 @@ static int write_abstract_arg(struct target *target, unsigned index,
return ERROR_OK; return ERROR_OK;
} }
static int register_read_abstract(struct target *target, uint64_t *value, /**
uint32_t number, unsigned size) * @size in bits
*/
static uint32_t access_register_command(uint32_t number, unsigned size,
uint32_t flags)
{ {
RISCV013_INFO(r);
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
switch (size) { switch (size) {
case 32: case 32:
@ -651,38 +650,50 @@ static int register_read_abstract(struct target *target, uint64_t *value,
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3); command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
break; break;
default: default:
LOG_ERROR("Unsupported abstract register read size: %d", size); assert(0);
return ERROR_FAIL;
} }
command = set_field(command, AC_ACCESS_REGISTER_POSTEXEC, 0);
command = set_field(command, AC_ACCESS_REGISTER_TRANSFER, 1);
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 0);
if (number <= GDB_REGNO_XPR31) { if (number <= GDB_REGNO_XPR31) {
command = set_field(command, AC_ACCESS_REGISTER_REGNO, command = set_field(command, AC_ACCESS_REGISTER_REGNO,
0x1000 + number - GDB_REGNO_XPR0); 0x1000 + number - GDB_REGNO_XPR0);
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (!r->abstract_read_fpr_supported)
return ERROR_FAIL;
command = set_field(command, AC_ACCESS_REGISTER_REGNO, command = set_field(command, AC_ACCESS_REGISTER_REGNO,
0x1020 + number - GDB_REGNO_FPR0); 0x1020 + number - GDB_REGNO_FPR0);
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
if (!r->abstract_read_csr_supported)
return ERROR_FAIL;
command = set_field(command, AC_ACCESS_REGISTER_REGNO, command = set_field(command, AC_ACCESS_REGISTER_REGNO,
number - GDB_REGNO_CSR0); number - GDB_REGNO_CSR0);
} else { } else {
return ERROR_FAIL; assert(0);
} }
command |= flags;
return command;
}
static int register_read_abstract(struct target *target, uint64_t *value,
uint32_t number, unsigned size)
{
RISCV013_INFO(info);
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
!info->abstract_read_fpr_supported)
return ERROR_FAIL;
if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 &&
!info->abstract_read_csr_supported)
return ERROR_FAIL;
uint32_t command = access_register_command(number, size,
AC_ACCESS_REGISTER_TRANSFER);
int result = execute_abstract_command(target, command); int result = execute_abstract_command(target, command);
if (result != ERROR_OK) { if (result != ERROR_OK) {
if (r->cmderr == CMDERR_NOT_SUPPORTED) { if (info->cmderr == CMDERR_NOT_SUPPORTED) {
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
r->abstract_read_fpr_supported = false; info->abstract_read_fpr_supported = false;
LOG_INFO("Disabling abstract command reads from FPRs."); LOG_INFO("Disabling abstract command reads from FPRs.");
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
r->abstract_read_csr_supported = false; info->abstract_read_csr_supported = false;
LOG_INFO("Disabling abstract command reads from CSRs."); LOG_INFO("Disabling abstract command reads from CSRs.");
} }
} }
@ -699,38 +710,16 @@ static int register_write_abstract(struct target *target, uint32_t number,
{ {
RISCV013_INFO(info); RISCV013_INFO(info);
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
switch (size) { !info->abstract_write_fpr_supported)
case 32:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2);
break;
case 64:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
break;
default:
LOG_ERROR("Unsupported abstract register read size: %d", size);
return ERROR_FAIL;
}
command = set_field(command, AC_ACCESS_REGISTER_POSTEXEC, 0);
command = set_field(command, AC_ACCESS_REGISTER_TRANSFER, 1);
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 1);
if (number <= GDB_REGNO_XPR31) {
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
0x1000 + number - GDB_REGNO_XPR0);
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (!info->abstract_read_fpr_supported)
return ERROR_FAIL;
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
0x1020 + number - GDB_REGNO_FPR0);
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
if (!info->abstract_read_csr_supported)
return ERROR_FAIL;
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
number - GDB_REGNO_CSR0);
} else {
return ERROR_FAIL; return ERROR_FAIL;
} if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 &&
!info->abstract_write_csr_supported)
return ERROR_FAIL;
uint32_t command = access_register_command(number, size,
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
if (write_abstract_arg(target, 0, value) != ERROR_OK) { if (write_abstract_arg(target, 0, value) != ERROR_OK) {
return ERROR_FAIL; return ERROR_FAIL;
@ -905,8 +894,6 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->on_resume = &riscv013_on_resume; generic_info->on_resume = &riscv013_on_resume;
generic_info->on_step = &riscv013_on_step; generic_info->on_step = &riscv013_on_step;
generic_info->halt_reason = &riscv013_halt_reason; generic_info->halt_reason = &riscv013_halt_reason;
generic_info->debug_buffer_enter = &riscv013_debug_buffer_enter;
generic_info->debug_buffer_leave = &riscv013_debug_buffer_leave;
generic_info->read_debug_buffer = &riscv013_read_debug_buffer; generic_info->read_debug_buffer = &riscv013_read_debug_buffer;
generic_info->write_debug_buffer = &riscv013_write_debug_buffer; generic_info->write_debug_buffer = &riscv013_write_debug_buffer;
generic_info->execute_debug_buffer = &riscv013_execute_debug_buffer; generic_info->execute_debug_buffer = &riscv013_execute_debug_buffer;
@ -1249,7 +1236,9 @@ static int deassert_reset(struct target *target)
return ERROR_OK; return ERROR_OK;
} }
#if 0 /**
* @size in bytes
*/
static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size) static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
{ {
switch (size) { switch (size) {
@ -1270,7 +1259,6 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
assert(false); assert(false);
} }
} }
#endif
/** /**
* Read the requested memory, taking care to execute every read exactly once, * Read the requested memory, taking care to execute every read exactly once,
@ -1279,30 +1267,27 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
static int read_memory(struct target *target, target_addr_t address, static int read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer) uint32_t size, uint32_t count, uint8_t *buffer)
{ {
//RISCV013_INFO(info); RISCV013_INFO(info);
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);
select_dmi(target); select_dmi(target);
/* This program uses two temporary registers. A word of data and the /* s0 holds the next address to write to
* associated address are stored at some location in memory. The * s1 holds the next data value to write
* program loads the word from that address and then increments the */
* address. The debugger is expected to pull the memory word-by-word uint64_t s0, s1;
* from the chip with AUTOEXEC set in order to trigger program if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
* execution on every word. */ return ERROR_FAIL;
uint64_t s0 = riscv_get_register(target, GDB_REGNO_S0); if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
uint64_t s1 = riscv_get_register(target, GDB_REGNO_S1); return ERROR_FAIL;
// Write the program (load, increment)
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
assert(0);
#if 0 // TODO: riscv_program_fence(&program);
riscv_addr_t r_data = riscv_program_alloc_w(&program);
riscv_addr_t r_addr = riscv_program_alloc_x(&program);
riscv_program_fence(&program);
riscv_program_lx(&program, GDB_REGNO_S0, r_addr);
switch (size) { switch (size) {
case 1: case 1:
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
@ -1318,70 +1303,43 @@ static int read_memory(struct target *target, target_addr_t address,
return ERROR_FAIL; return ERROR_FAIL;
} }
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
riscv_program_sw(&program, GDB_REGNO_S1, r_data);
riscv_program_sx(&program, GDB_REGNO_S0, r_addr);
/* The first round through the program's execution we use the regular if (riscv_program_ebreak(&program) != ERROR_OK)
* program execution mechanism. */
switch (riscv_xlen(target)) {
case 64:
riscv_program_write_ram(&program, r_addr + 4, ((riscv_addr_t) address) >> 32);
case 32:
riscv_program_write_ram(&program, r_addr, (riscv_addr_t) address);
break;
default:
LOG_ERROR("unknown XLEN %d", riscv_xlen(target));
return ERROR_FAIL; return ERROR_FAIL;
} riscv_program_write(&program);
if (riscv_program_exec(&program, target) != ERROR_OK) { // Write address to S0, and execute buffer.
uint32_t acs = dmi_read(target, DMI_ABSTRACTCS); if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK)
LOG_ERROR("failed to execute program, abstractcs=0x%08x", acs); return ERROR_FAIL;
riscv013_clear_abstract_error(target); if (execute_abstract_command(target,
riscv_set_register(target, GDB_REGNO_S0, s0); access_register_command(GDB_REGNO_S1, riscv_xlen(target),
riscv_set_register(target, GDB_REGNO_S1, s1); AC_ACCESS_REGISTER_TRANSFER |
LOG_ERROR(" exiting with ERROR_FAIL"); AC_ACCESS_REGISTER_POSTEXEC)) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
// Program has been executed once. d_addr contains address+size, and d_data dmi_write(target, DMI_ABSTRACTAUTO,
// contains *address. 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
/* The rest of this program is designed to be fast so it reads various
* DMI registers directly. */
int d_data = (r_data - riscv_debug_buffer_addr(target)) / 4;
int d_addr = (r_addr - riscv_debug_buffer_addr(target)) / 4;
riscv013_set_autoexec(target, d_data, 1);
/* Copying memory might fail because we're going too quickly, in which /* Copying memory might fail because we're going too quickly, in which
* case we need to back off a bit and try again. There's two * case we need to back off a bit and try again. */
* termination conditions to this loop: a non-BUSY error message, or riscv_addr_t cur_addr = address;
* the data was all copied. */
riscv_addr_t cur_addr = riscv_read_debug_buffer_x(target, d_addr);
riscv_addr_t fin_addr = address + (count * size); riscv_addr_t fin_addr = address + (count * size);
LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr); LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr);
while (cur_addr < fin_addr) { while (cur_addr < fin_addr - size) {
// Invariant: // Invariant:
// d_data contains *addr // s0 contains the next address to read
// d_addr contains addr + size // s1 contains the data read at the previous address
unsigned start = (cur_addr - address) / size; unsigned start = (cur_addr - address) / size;
LOG_DEBUG("creating burst to read address 0x%" TARGET_PRIxADDR LOG_DEBUG("creating burst to read address 0x%" TARGET_PRIxADDR
" up to 0x%" TARGET_PRIxADDR "; start=0x%d", cur_addr, fin_addr, start); " up to 0x%" TARGET_PRIxADDR "; start=0x%d", cur_addr, fin_addr, start);
assert(cur_addr >= address && cur_addr < fin_addr); assert(cur_addr >= address && cur_addr < fin_addr);
struct riscv_batch *batch = riscv_batch_alloc( struct riscv_batch *batch = riscv_batch_alloc(target, 32,
target, info->dmi_busy_delay + info->ac_busy_delay);
32,
info->dmi_busy_delay + info->ac_busy_delay);
size_t reads = 0; size_t reads = 0;
for (riscv_addr_t addr = cur_addr; addr < fin_addr; addr += size) { for (riscv_addr_t addr = cur_addr; addr < fin_addr - size; addr += size) {
size_t const index = riscv_batch_add_dmi_read(batch, DMI_DATA0);
riscv_batch_add_dmi_read(
batch,
riscv013_debug_buffer_register(target, r_data));
assert(index == reads);
reads++; reads++;
if (riscv_batch_full(batch)) if (riscv_batch_full(batch))
@ -1397,37 +1355,37 @@ static int read_memory(struct target *target, target_addr_t address,
abstractcs = dmi_read(target, DMI_ABSTRACTCS); abstractcs = dmi_read(target, DMI_ABSTRACTCS);
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
riscv_addr_t next_addr;
switch (info->cmderr) { switch (info->cmderr) {
case CMDERR_NONE: case CMDERR_NONE:
LOG_DEBUG("successful (partial?) memory read"); LOG_DEBUG("successful (partial?) memory read");
break; next_addr = cur_addr + reads * size;
case CMDERR_BUSY: break;
LOG_DEBUG("memory read resulted in busy response"); case CMDERR_BUSY:
increase_ac_busy_delay(target); LOG_DEBUG("memory read resulted in busy response");
riscv013_clear_abstract_error(target); increase_ac_busy_delay(target);
break; riscv013_clear_abstract_error(target);
default:
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
riscv013_set_autoexec(target, d_data, 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;
}
// Figure out how far we managed to read. dmi_write(target, DMI_ABSTRACTAUTO, 0);
riscv_addr_t next_addr = riscv_read_debug_buffer_x(target, d_addr); if (register_read_direct(target, &next_addr, GDB_REGNO_S0) != ERROR_OK)
LOG_DEBUG("Batch read [0x%" TARGET_PRIxADDR ", 0x%" TARGET_PRIxADDR return ERROR_FAIL;
"); reads=%d", cur_addr, next_addr, (unsigned) reads); next_addr -= size;
assert(next_addr >= address && next_addr <= fin_addr); dmi_write(target, DMI_ABSTRACTAUTO,
assert(info->cmderr != CMDERR_NONE || 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
next_addr == cur_addr + reads * size); 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;
}
// Now read whatever we got out of the batch. // Now read whatever we got out of the batch.
unsigned rereads = 0; unsigned rereads = 0;
for (riscv_addr_t addr = cur_addr - size; addr < next_addr - size; for (riscv_addr_t addr = cur_addr; addr < next_addr; addr += size) {
addr += size) {
riscv_addr_t offset = addr - address; riscv_addr_t offset = addr - address;
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads); uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
@ -1443,17 +1401,14 @@ static int read_memory(struct target *target, target_addr_t address,
cur_addr = next_addr; cur_addr = next_addr;
} }
riscv013_set_autoexec(target, d_data, 0); dmi_write(target, DMI_ABSTRACTAUTO, 0);
// Read the last word. // Read the last word.
uint64_t value;
// Access debug buffer without executing a program. This if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK)
// address logic was taken from program.c. return ERROR_FAIL;
uint32_t value = riscv013_read_debug_buffer(target, d_data); write_to_buf(buffer + cur_addr - address, value, size);
riscv_addr_t addr = cur_addr - size; LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, cur_addr, value);
write_to_buf(buffer + addr - address, value, size);
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%08x", addr, value);
#endif
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);
@ -1467,13 +1422,12 @@ static int write_memory(struct target *target, target_addr_t address,
LOG_DEBUG("writing %d words of %d bytes to 0x%08lx", count, size, (long)address); LOG_DEBUG("writing %d words of %d bytes to 0x%08lx", count, size, (long)address);
/* select_dmi(target);
* s0 holds the next address to write to
/* s0 holds the next address to write to
* s1 holds the next data value to write * s1 holds the next data value to write
*/ */
select_dmi(target);
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;
@ -1501,14 +1455,10 @@ static int write_memory(struct target *target, target_addr_t address,
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
if (riscv_debug_buffer_leave(target, &program) != ERROR_OK) if (riscv_program_ebreak(&program) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
riscv_program_write(&program); riscv_program_write(&program);
if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK)
return ERROR_FAIL;
riscv_addr_t cur_addr = address; riscv_addr_t cur_addr = address;
riscv_addr_t fin_addr = address + (count * size); riscv_addr_t fin_addr = address + (count * size);
bool setup_needed = true; bool setup_needed = true;
@ -1551,28 +1501,19 @@ static int write_memory(struct target *target, target_addr_t address,
LOG_DEBUG("M[0x%08" PRIx64 "] writes 0x%08x", address + offset, value); LOG_DEBUG("M[0x%08" PRIx64 "] writes 0x%08x", address + offset, value);
if (setup_needed) { if (setup_needed) {
if (register_write_direct(target, GDB_REGNO_S0,
address + offset) != ERROR_OK)
return ERROR_FAIL;
// Write value. // Write value.
dmi_write(target, DMI_DATA0, value); dmi_write(target, DMI_DATA0, value);
// Write and execute command that moves value into S0 and // Write and execute command that moves value into S0 and
// executes program buffer. // executes program buffer.
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); uint32_t command = access_register_command(GDB_REGNO_S1, 32,
switch (size) { AC_ACCESS_REGISTER_POSTEXEC |
case 32: AC_ACCESS_REGISTER_TRANSFER |
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2); AC_ACCESS_REGISTER_WRITE);
break;
case 64:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
break;
default:
LOG_ERROR("Unsupported abstract register read size: %d", size);
return ERROR_FAIL;
}
command = set_field(command, AC_ACCESS_REGISTER_POSTEXEC, 1);
command = set_field(command, AC_ACCESS_REGISTER_TRANSFER, 1);
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 1);
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
0x1000 + GDB_REGNO_S1 - GDB_REGNO_XPR0);
int result = execute_abstract_command(target, command); int result = execute_abstract_command(target, command);
if (result != ERROR_OK) if (result != ERROR_OK)
return result; return result;
@ -1810,14 +1751,6 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
abort(); abort();
} }
void riscv013_debug_buffer_enter(struct target *target, struct riscv_program *program)
{
}
void riscv013_debug_buffer_leave(struct target *target, struct riscv_program *program)
{
}
void riscv013_write_debug_buffer(struct target *target, unsigned index, riscv_insn_t data) void riscv013_write_debug_buffer(struct target *target, unsigned index, riscv_insn_t data)
{ {
RISCV013_INFO(info); RISCV013_INFO(info);

View File

@ -1482,20 +1482,6 @@ size_t riscv_debug_buffer_size(struct target *target)
return r->debug_buffer_size[riscv_current_hartid(target)]; return r->debug_buffer_size[riscv_current_hartid(target)];
} }
int riscv_debug_buffer_enter(struct target *target, struct riscv_program *program)
{
RISCV_INFO(r);
r->debug_buffer_enter(target, program);
return ERROR_OK;
}
int riscv_debug_buffer_leave(struct target *target, struct riscv_program *program)
{
RISCV_INFO(r);
r->debug_buffer_leave(target, program);
return ERROR_OK;
}
int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn) int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn)
{ {
RISCV_INFO(r); RISCV_INFO(r);

View File

@ -92,8 +92,6 @@ typedef struct {
void (*on_resume)(struct target *target); void (*on_resume)(struct target *target);
void (*on_step)(struct target *target); void (*on_step)(struct target *target);
enum riscv_halt_reason (*halt_reason)(struct target *target); enum riscv_halt_reason (*halt_reason)(struct target *target);
void (*debug_buffer_enter)(struct target *target, struct riscv_program *program);
void (*debug_buffer_leave)(struct target *target, struct riscv_program *program);
void (*write_debug_buffer)(struct target *target, unsigned index, void (*write_debug_buffer)(struct target *target, unsigned index,
riscv_insn_t d); riscv_insn_t d);
riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index); riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index);
@ -211,9 +209,6 @@ int riscv_count_triggers_of_hart(struct target *target, int hartid);
* information. */ * information. */
size_t riscv_debug_buffer_size(struct target *target); size_t riscv_debug_buffer_size(struct target *target);
int riscv_debug_buffer_enter(struct target *target, struct riscv_program *program);
int riscv_debug_buffer_leave(struct target *target, struct riscv_program *program);
riscv_insn_t riscv_read_debug_buffer(struct target *target, int index); riscv_insn_t riscv_read_debug_buffer(struct target *target, int index);
riscv_addr_t riscv_read_debug_buffer_x(struct target *target, int index); riscv_addr_t riscv_read_debug_buffer_x(struct target *target, int index);
int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn); int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn);