This is an automated email from Gerrit.

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

-- gerrit

commit 68f666b5761bc826a2230cbfa6af7756dcf73d87
Author: Jan Matyas <[email protected]>
Date:   Thu Jun 11 12:23:12 2026 +0200

    target: Hotfix: refuse to force-read a dirty register
    
    As a temporary hotfix for the register caching issue
    described in [1], refuse to perform force-read of
    a register that is dirty.
    
    If such a force-read was allowed to take place,
    the unwritten (cached, dirty) register value would
    get lost.
    
    This is a temporary solution to prevent users from
    hitting this hidden bug - until a proper register
    cache control is implemented.
    
    [1] https://review.openocd.org/c/openocd/+/8070
    
    Change-Id: If3aa47f7f94e2d0e82b427bcb9fc18f97897b5fe
    Signed-off-by: Jan Matyas <[email protected]>

diff --git a/src/target/target.c b/src/target/target.c
index e6c0ae9aa7..94702f6939 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -3100,8 +3100,25 @@ COMMAND_HANDLER(handle_reg_command)
        /* display a register */
        if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
                        && (CMD_ARGV[1][0] <= '9')))) {
-               if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
+               if (CMD_ARGC == 2 && (strcmp(CMD_ARGV[1], "force") == 0)) {
+                       /* TODO: This is a temporary hotfix for cache issues 
when
+                        * force-reading a dirty register. For detailed 
discussion, see:
+                        * https://review.openocd.org/c/openocd/+/8070 */
+                       if (reg->valid && reg->dirty) {
+                               /* We currently don't have any API to flush 
(write back) the register's
+                                * dirty (unwritten) cached value before the 
force-read.
+                                * The force-read would destroy the unwritten 
value.
+                                * So refuse to perform the operation - prevent 
the data loss.
+                                */
+                               LOG_TARGET_ERROR(target, "Cannot force-read 
register '%s' because it "
+                                       "is dirty (cached value not written 
back)", reg->name);
+                               LOG_TARGET_ERROR(target, "This is an OpenOCD 
limitation that will "
+                                       "be lifted in a future version");
+                               return ERROR_FAIL;
+                       }
+
                        reg->valid = false;
+               }
 
                if (!reg->valid) {
                        int retval = reg->type->get(reg);
@@ -4778,6 +4795,22 @@ COMMAND_HANDLER(handle_target_get_reg)
 
                struct reg *reg = register_get_by_name(target->reg_cache, 
reg_name, true);
 
+               /* TODO: This is a temporary hotfix for cache issues when
+                * force-reading a dirty register. For detailed discussion, see:
+                * https://review.openocd.org/c/openocd/+/8070 */
+               if (force && reg->valid && reg->dirty) {
+                               /* We currently don't have any API to flush 
(write back) the register's
+                                * dirty (unwritten) cached value before the 
force-read.
+                                * The force-read would destroy the unwritten 
value.
+                                * So refuse to perform the operation - prevent 
the data loss.
+                                */
+                       LOG_TARGET_ERROR(target, "Cannot force-read register 
'%s' because it "
+                               "is dirty (cached value not written back)", 
reg_name);
+                       LOG_TARGET_ERROR(target, "This is an OpenOCD limitation 
that will "
+                               "be lifted in a future version");
+                       return ERROR_FAIL;
+               }
+
                if (!reg || !reg->exist) {
                        command_print(CMD, "unknown register '%s'", reg_name);
                        return ERROR_COMMAND_ARGUMENT_INVALID;

-- 

Reply via email to