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; --
