target/riscv: warn about truncating register values
When reading a register via Program Buffer the actual value is read from
a GPR. The GPR size (XLEN) can be greater than the length of the target
register (e.g. `dcsr` is always 32-bit wide). Due to some HW issue GPR
read may return a value that needs to be truncated to fit into the
target register. Warn the user about it.
Moreover, the value in cache was and is truncated, but the `riscv_reg_t`
that is filled by `riscv_reg_get()` didn't use to be. This may lead to
an assertion failure in `abstract_data_write_fill_batch()`:
Link: fa7e2351c8/src/target/riscv/riscv-013.c (L757)
Change-Id: I4d8a5ba2451fc5a60f51b9143b6b140dfe3b73b8
Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
This commit is contained in:
parent
fa7e2351c8
commit
96b7d46c45
|
@ -1370,14 +1370,31 @@ static int register_read_progbuf(struct target *target, uint64_t *value,
|
|||
{
|
||||
assert(target->state == TARGET_HALTED);
|
||||
|
||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31)
|
||||
return fpr_read_progbuf(target, value, number);
|
||||
else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095)
|
||||
return csr_read_progbuf(target, value, number);
|
||||
int res;
|
||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||
res = fpr_read_progbuf(target, value, number);
|
||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||
res = csr_read_progbuf(target, value, number);
|
||||
} else {
|
||||
LOG_TARGET_ERROR(target, "Unexpected read of %s via program buffer.",
|
||||
riscv_reg_gdb_regno_name(target, number));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (res != ERROR_OK)
|
||||
return res;
|
||||
|
||||
LOG_TARGET_ERROR(target, "Unexpected read of %s via program buffer.",
|
||||
riscv_reg_gdb_regno_name(target, number));
|
||||
return ERROR_FAIL;
|
||||
unsigned int size_bits = register_size(target, number);
|
||||
unsigned int value_bits = sizeof(*value) * CHAR_BIT;
|
||||
assert(size_bits <= value_bits);
|
||||
if (size_bits == value_bits || *value >> size_bits == 0)
|
||||
return ERROR_OK;
|
||||
|
||||
LOG_TARGET_WARNING(target, "Value read for register %s of %" PRIx64
|
||||
" does not fit into the size of the register (%u bits)."
|
||||
" This is a HW bug. Truncating the value to fit into the register.",
|
||||
riscv_reg_gdb_regno_name(target, number), *value, size_bits);
|
||||
*value &= GENMASK_ULL(size_bits - 1U, 0U);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue