This is an automated email from Gerrit. "Dietmar May <dietmar....@outlook.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6477
-- gerrit commit 6755d33786370d6659075a520d481a674b2f7888 Author: Dietmar May <dietmar....@outlook.com> Date: Fri Aug 20 19:34:39 2021 -0400 aarch64: reg cmd w/ force for rd & wr, sync In a multi-core (SMP) system, the 'reg' command is always associated with the last core to halt, which means that registers for another core can't be inspected. This patch adds a reg command to aarch64, allowing all cores to be inspected, and adds 'force' to register writes, causing an immediate flush of updated values to the target cpu register. By adding a reg command to the aarch64 command set, the correct target is already set at the time of the call. The existing target handler is invoked. Then, since the target handler only updates the cache, not the cpu, if 'force' is specified, the patch code flushes the register on write, and clears or displays the dirty flag. > ca53.0 aarch64 reg pc ca53.0:pc (/64): 0x00000000deadbeef (dirty) > ca53.1 aarch64 reg pc ca53.1:pc (/64): 0x000000000f1eaba11 (dirty) > ca53.0 aarch64 reg pc force ca53.0:pc (/64): 0x00000000codeace5 Signed-off-by: Dietmar May <dietmar....@outlook.com> Change-Id: I4e8c27b34361ed31acad136f705dc9c9b340234c diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 9e8a7cd91..79768c292 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2971,6 +2971,64 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command) return retval; } +COMMAND_HANDLER(aarch64_handle_reg_command) +{ + extern __COMMAND_HANDLER(target_handle_reg_command); + + struct target *target = get_current_target(CMD_CTX); + + bool force = false; + bool write = false; + + if (CMD_ARGC > 0) { + /* look for trailing "force" when a numeric value is being written */ + force = (strcmp(CMD_ARGV[CMD_ARGC-1], "force") == 0); + write = ((CMD_ARGC >= 2) && (CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')); + } + + int retval = CALL_COMMAND_HANDLER(target_handle_reg_command); + + if (retval == ERROR_OK) { + struct reg *reg = NULL; + + /* reg->->set only sets the dirty flag, so flush immediately if 'force' is specified */ + if (write) { + if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { + unsigned num; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); + + for (struct reg_cache *cache = target->reg_cache; cache && !reg; cache = cache->next) { + if (num >= cache->num_regs) + num -= cache->num_regs; + else + reg = &cache->reg_list[num]; + } + } else { + reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], true); + } + + } + + /* out of bounds register already reported in target_handle_reg_command */ + if (!reg) + return ERROR_OK; + + if (force) { + struct arm_reg *armv8_reg = reg->arch_info; + struct arm *arm = target_to_arm(target); + retval = arm->write_core_reg(target, reg, armv8_reg->num, arm->core_mode, reg->value); + if(retval == ERROR_OK) + reg->dirty = false; + else + LOG_ERROR("reg force failed while flushing register - %s", CMD_ARGV[0]); + } else if (write && reg->dirty) { + command_print(CMD, "(dirty)"); + } + } + + return retval; +} + /* Move to ARM register from coprocessor * o0: Coprocessor number (0 - general, 1 - system) * op1: Coprocessor opcode @@ -3281,6 +3339,14 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, + { + .name = "reg", + .mode = COMMAND_EXEC, + .handler = aarch64_handle_reg_command, + .help = "displays all registers, displays or sets a register, or marks all dirty: " + "force causes a reread or flush", + .usage = "[((register_number|register_name) [value] [force]) | sync]", + }, { .chain = smp_command_handlers, }, --