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:
parent
e2d3184eba
commit
c1c88dccee
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue