Account for impebreak in size requirements for progbuf (#509)

* Account for impebreak in size requirements for progbuf

* add helper function
This commit is contained in:
Samuel Obuch 2020-08-17 22:07:11 +02:00 committed by GitHub
parent e2d3184eba
commit c1c88dccee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 30 deletions

View File

@ -1285,6 +1285,14 @@ static unsigned register_size(struct target *target, unsigned number)
return riscv_xlen(target); return riscv_xlen(target);
} }
static bool has_sufficient_progbuf(struct target *target, unsigned size)
{
RISCV013_INFO(info);
RISCV_INFO(r);
return info->progbufsize + r->impebreak >= size ;
}
/** /**
* Immediately write the new value to the requested register. This mechanism * Immediately write the new value to the requested register. This mechanism
* bypasses any caches. * bypasses any caches.
@ -1292,15 +1300,12 @@ static unsigned register_size(struct target *target, unsigned number)
static int register_write_direct(struct target *target, unsigned number, static int register_write_direct(struct target *target, unsigned number,
uint64_t value) uint64_t value)
{ {
RISCV013_INFO(info);
RISCV_INFO(r);
LOG_DEBUG("{%d} %s <- 0x%" PRIx64, riscv_current_hartid(target), LOG_DEBUG("{%d} %s <- 0x%" PRIx64, riscv_current_hartid(target),
gdb_regno_name(number), value); gdb_regno_name(number), value);
int result = register_write_abstract(target, number, value, int result = register_write_abstract(target, number, value,
register_size(target, number)); register_size(target, number));
if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 || if (result == ERROR_OK || !has_sufficient_progbuf(target, 2) ||
!riscv_is_halted(target)) !riscv_is_halted(target))
return result; return result;
@ -1409,14 +1414,11 @@ static int register_read(struct target *target, uint64_t *value, uint32_t number
/** Actually read registers from the target right now. */ /** Actually read registers from the target right now. */
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number) static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
{ {
RISCV013_INFO(info);
RISCV_INFO(r);
int result = register_read_abstract(target, value, number, int result = register_read_abstract(target, value, number,
register_size(target, number)); register_size(target, number));
if (result != ERROR_OK && if (result != ERROR_OK &&
info->progbufsize + r->impebreak >= 2 && has_sufficient_progbuf(target, 2) &&
number > GDB_REGNO_XPR31) { number > GDB_REGNO_XPR31) {
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
@ -1664,7 +1666,7 @@ static int examine(struct target *target)
RISCV_INFO(r); RISCV_INFO(r);
r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK); r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK);
if (info->progbufsize + r->impebreak < 2) { if (!has_sufficient_progbuf(target, 2)) {
LOG_WARNING("We won't be able to execute fence instructions on this " LOG_WARNING("We won't be able to execute fence instructions on this "
"target. Memory may not always appear consistent. " "target. Memory may not always appear consistent. "
"(progbufsize=%d, impebreak=%d)", info->progbufsize, "(progbufsize=%d, impebreak=%d)", info->progbufsize,
@ -1833,7 +1835,7 @@ static unsigned riscv013_data_bits(struct target *target)
/* TODO: Once there is a spec for discovering abstract commands, we can /* TODO: Once there is a spec for discovering abstract commands, we can
* take those into account as well. For now we assume abstract commands * take those into account as well. For now we assume abstract commands
* support XLEN-wide accesses. */ * support XLEN-wide accesses. */
if (info->progbufsize >= 2 && !riscv_prefer_sba) if (has_sufficient_progbuf(target, 3) && !riscv_prefer_sba)
return riscv_xlen(target); return riscv_xlen(target);
if (get_field(info->sbcs, DMI_SBCS_SBACCESS128)) if (get_field(info->sbcs, DMI_SBCS_SBACCESS128))
@ -2392,9 +2394,7 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old) static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old)
{ {
RISCV013_INFO(info); if (riscv_enable_virtual && has_sufficient_progbuf(target, 5)) {
if (riscv_enable_virtual && info->progbufsize >= 4) {
/* Read DCSR */ /* Read DCSR */
uint64_t dcsr; uint64_t dcsr;
if (register_read(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK) if (register_read(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
@ -2999,8 +2999,6 @@ error:
static int read_memory_progbuf_one(struct target *target, target_addr_t address, static int read_memory_progbuf_one(struct target *target, target_addr_t address,
uint32_t size, uint8_t *buffer) uint32_t size, uint8_t *buffer)
{ {
RISCV013_INFO(info);
uint64_t mstatus = 0; uint64_t mstatus = 0;
uint64_t mstatus_old = 0; uint64_t mstatus_old = 0;
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
@ -3014,7 +3012,7 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address,
/* Write the program (load, increment) */ /* Write the program (load, increment) */
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
switch (size) { switch (size) {
case 1: case 1:
@ -3033,7 +3031,7 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address,
LOG_ERROR("Unsupported size: %d", size); LOG_ERROR("Unsupported size: %d", size);
return ERROR_FAIL; return ERROR_FAIL;
} }
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
if (riscv_program_ebreak(&program) != ERROR_OK) if (riscv_program_ebreak(&program) != ERROR_OK)
@ -3073,8 +3071,6 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address,
static int read_memory_progbuf(struct target *target, target_addr_t address, static int read_memory_progbuf(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);
if (riscv_xlen(target) < size * 8) { if (riscv_xlen(target) < size * 8) {
LOG_ERROR("XLEN (%d) is too short for %d-bit memory read.", LOG_ERROR("XLEN (%d) is too short for %d-bit memory read.",
riscv_xlen(target), size * 8); riscv_xlen(target), size * 8);
@ -3113,7 +3109,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
/* Write the program (load, increment) */ /* Write the program (load, increment) */
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
switch (size) { switch (size) {
@ -3134,7 +3130,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
return ERROR_FAIL; return ERROR_FAIL;
} }
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
@ -3186,7 +3182,8 @@ 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);
if (info->progbufsize >= 2 && !riscv_prefer_sba)
if (has_sufficient_progbuf(target, 3) && !riscv_prefer_sba)
return read_memory_progbuf(target, address, size, count, buffer); return read_memory_progbuf(target, address, size, count, buffer);
if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) || if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
@ -3200,7 +3197,7 @@ static int read_memory(struct target *target, target_addr_t address,
return read_memory_bus_v1(target, address, size, count, buffer); return read_memory_bus_v1(target, address, size, count, buffer);
} }
if (info->progbufsize >= 2) if (has_sufficient_progbuf(target, 3))
return read_memory_progbuf(target, address, size, count, buffer); return read_memory_progbuf(target, address, size, count, buffer);
return read_memory_abstract(target, address, size, count, buffer); return read_memory_abstract(target, address, size, count, buffer);
@ -3446,7 +3443,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
/* Write the program (store, increment) */ /* Write the program (store, increment) */
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrsi(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
switch (size) { switch (size) {
@ -3468,7 +3465,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
goto error; goto error;
} }
if (riscv_enable_virtual && info->progbufsize >= 4 && get_field(mstatus, MSTATUS_MPRV)) if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR); riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
@ -3606,7 +3603,8 @@ static int write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer) uint32_t size, uint32_t count, const uint8_t *buffer)
{ {
RISCV013_INFO(info); RISCV013_INFO(info);
if (info->progbufsize >= 2 && !riscv_prefer_sba)
if (has_sufficient_progbuf(target, 3) && !riscv_prefer_sba)
return write_memory_progbuf(target, address, size, count, buffer); return write_memory_progbuf(target, address, size, count, buffer);
if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) || if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
@ -3620,7 +3618,7 @@ static int write_memory(struct target *target, target_addr_t address,
return write_memory_bus_v1(target, address, size, count, buffer); return write_memory_bus_v1(target, address, size, count, buffer);
} }
if (info->progbufsize >= 2) if (has_sufficient_progbuf(target, 3))
return write_memory_progbuf(target, address, size, count, buffer); return write_memory_progbuf(target, address, size, count, buffer);
return write_memory_abstract(target, address, size, count, buffer); return write_memory_abstract(target, address, size, count, buffer);
@ -4342,9 +4340,7 @@ int riscv013_dmi_write_u64_bits(struct target *target)
static int maybe_execute_fence_i(struct target *target) static int maybe_execute_fence_i(struct target *target)
{ {
RISCV013_INFO(info); if (has_sufficient_progbuf(target, 3))
RISCV_INFO(r);
if (info->progbufsize + r->impebreak >= 3)
return execute_fence(target); return execute_fence(target);
return ERROR_OK; return ERROR_OK;
} }