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);
}
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
* 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,
uint64_t value)
{
RISCV013_INFO(info);
RISCV_INFO(r);
LOG_DEBUG("{%d} %s <- 0x%" PRIx64, riscv_current_hartid(target),
gdb_regno_name(number), value);
int result = register_write_abstract(target, number, value,
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))
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. */
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,
register_size(target, number));
if (result != ERROR_OK &&
info->progbufsize + r->impebreak >= 2 &&
has_sufficient_progbuf(target, 2) &&
number > GDB_REGNO_XPR31) {
struct riscv_program program;
riscv_program_init(&program, target);
@ -1664,7 +1666,7 @@ static int examine(struct target *target)
RISCV_INFO(r);
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 "
"target. Memory may not always appear consistent. "
"(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
* take those into account as well. For now we assume abstract commands
* support XLEN-wide accesses. */
if (info->progbufsize >= 2 && !riscv_prefer_sba)
if (has_sufficient_progbuf(target, 3) && !riscv_prefer_sba)
return riscv_xlen(target);
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)
{
RISCV013_INFO(info);
if (riscv_enable_virtual && info->progbufsize >= 4) {
if (riscv_enable_virtual && has_sufficient_progbuf(target, 5)) {
/* Read DCSR */
uint64_t dcsr;
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,
uint32_t size, uint8_t *buffer)
{
RISCV013_INFO(info);
uint64_t mstatus = 0;
uint64_t mstatus_old = 0;
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) */
struct riscv_program program;
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);
switch (size) {
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);
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);
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,
uint32_t size, uint32_t count, uint8_t *buffer)
{
RISCV013_INFO(info);
if (riscv_xlen(target) < size * 8) {
LOG_ERROR("XLEN (%d) is too short for %d-bit memory read.",
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) */
struct riscv_program program;
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);
switch (size) {
@ -3134,7 +3130,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
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_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)
{
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);
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);
}
if (info->progbufsize >= 2)
if (has_sufficient_progbuf(target, 3))
return read_memory_progbuf(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) */
struct riscv_program program;
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);
switch (size) {
@ -3468,7 +3465,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
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_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)
{
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);
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);
}
if (info->progbufsize >= 2)
if (has_sufficient_progbuf(target, 3))
return write_memory_progbuf(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)
{
RISCV013_INFO(info);
RISCV_INFO(r);
if (info->progbufsize + r->impebreak >= 3)
if (has_sufficient_progbuf(target, 3))
return execute_fence(target);
return ERROR_OK;
}