This is an automated email from Gerrit.

"Evgeniy Naydanov <[email protected]>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/9720

-- gerrit

commit 5939cf4c84a3776f38f106b14ee6c7f8a9e7c794
Author: Evgeniy Naydanov <[email protected]>
Date:   Wed Feb 26 15:53:06 2025 +0300

    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()`.
    
    Change-Id: I4d8a5ba2451fc5a60f51b9143b6b140dfe3b73b8
    Signed-off-by: Evgeniy Naydanov <[email protected]>

diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 1b47d5e77f..35408b14ba 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1439,14 +1439,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;
 }
 
 /**

-- 

Reply via email to