This is an automated email from Gerrit. "Jeremy Linton <lintonrjer...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7054
-- gerrit commit 6adb604762437da65488488897aa21aae63f4dba Author: Jeremy Linton <lintonrjer...@gmail.com> Date: Mon Jun 20 15:08:57 2022 -0500 aarch64: Add mrs/msr sysreg commands Armv8 has two modes, aarch32 which is intended to be backwards compatible with 32-bit armv7 and aarch64 which is an entirely new 64-bit mode. As such the older mcr/mrc commands aren't the correct method of accessing the newer 64-bit system registers. These newer system registers are accessed via mrs/msr and have a slightly different encoding mechanism. Because of that, lets add the 64-bit sys reg read/write commands of the form: aarch64 mrs sysreg | (op1 CRn op1 CRm op2) Which reports the value of the named system register, where sysreg is one of a limited number of ascii sysregs that openocd understands (ex: midr) or the individual instruction encoding fields described in the manuals. alternatively, aarch64 msr sysreg | (op1 CRn op1 CRm op2) value Writes `value` to the identified system register. Signed-off-by: Jeremy Linton <lintonrjer...@gmail.com> Change-Id: I4fe6dcc74a13a440e4aaf9375e41883f3fd2918f diff --git a/src/target/aarch64.c b/src/target/aarch64.c index e4d420f07a..b6fff89627 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2967,6 +2967,201 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command) return ERROR_OK; } + +static struct sysreg_nameop_t { + char *name; + uint32_t value; +} sysreg_nameop[] = { + {"ELR_EL1", SYSTEM_ELR_EL1}, + {"ELR_EL2", SYSTEM_ELR_EL2}, + {"ELR_EL3", SYSTEM_ELR_EL3}, + {"SCTLR_EL1", SYSTEM_SCTLR_EL1}, + {"SCTLR_EL2", SYSTEM_SCTLR_EL2}, + {"SCTLR_EL3", SYSTEM_SCTLR_EL3}, + {"FPCR", SYSTEM_FPCR}, + {"FPSR", SYSTEM_FPSR}, + {"DAIF", SYSTEM_DAIF}, + {"NZCV", SYSTEM_NZCV}, + {"SP_EL0", SYSTEM_SP_EL0}, + {"SP_EL1", SYSTEM_SP_EL1}, + {"SP_EL2", SYSTEM_SP_EL2}, + {"SP_SEL", SYSTEM_SP_SEL}, + {"SPSR_ABT", SYSTEM_SPSR_ABT}, + {"SPSR_FIQ", SYSTEM_SPSR_FIQ}, + {"SPSR_IRQ", SYSTEM_SPSR_IRQ}, + {"SPSR_UND", SYSTEM_SPSR_UND}, + {"SPSR_EL1", SYSTEM_SPSR_EL1}, + {"SPSR_EL2", SYSTEM_SPSR_EL2}, + {"SPSR_EL3", SYSTEM_SPSR_EL3}, + {"ISR_EL1", SYSTEM_ISR_EL1}, + {"DISR_EL1", SYSTEM_DISR_EL1}, + {"DBG_DSPSR_EL0", SYSTEM_DBG_DSPSR_EL0}, + {"DBG_DLR_EL0", SYSTEM_DBG_DLR_EL0}, + {"DBG_DTRRX_EL0", SYSTEM_DBG_DTRRX_EL0}, + {"DBG_DTRTX_EL0", SYSTEM_DBG_DTRTX_EL0}, + {"DBG_DBGDTR_EL0", SYSTEM_DBG_DBGDTR_EL0}, + {"CCSIDR", SYSTEM_CCSIDR}, + {"CLIDR", SYSTEM_CLIDR}, + {"CSSELR", SYSTEM_CSSELR}, + {"CTYPE", SYSTEM_CTYPE}, + {"CTR", SYSTEM_CTR}, + {"DCCISW", SYSTEM_DCCISW}, + {"DCCSW", SYSTEM_DCCSW}, + {"ICIVAU", SYSTEM_ICIVAU}, + {"DCCVAU", SYSTEM_DCCVAU}, + {"DCCIVAC", SYSTEM_DCCIVAC}, + {"MIDR", SYSTEM_MIDR}, + {"MPIDR", SYSTEM_MPIDR}, + {"REVIDR", SYSTEM_REVIDR}, + {"TCR_EL1", SYSTEM_TCR_EL1}, + {"TCR_EL2", SYSTEM_TCR_EL2}, + {"TCR_EL3", SYSTEM_TCR_EL3}, + {"TTBR0_EL1", SYSTEM_TTBR0_EL1}, + {"TTBR0_EL2", SYSTEM_TTBR0_EL2}, + {"TTBR0_EL3", SYSTEM_TTBR0_EL3}, + {"TTBR1_EL1", SYSTEM_TTBR1_EL1}, + {"PAR_EL1", SYSTEM_PAR_EL1}, + {"ATS12E0R", SYSTEM_ATS12E0R}, + {"ATS12E1R", SYSTEM_ATS12E1R}, + {"ATS1E2R", SYSTEM_ATS1E2R}, + {"ATS1E3R", SYSTEM_ATS1E3R}, + {"FAR_EL1", SYSTEM_FAR_EL1}, + {"FAR_EL2", SYSTEM_FAR_EL2}, + {"FAR_EL3", SYSTEM_FAR_EL3}, + {"ESR_EL1", SYSTEM_ESR_EL1}, + {"ESR_EL2", SYSTEM_ESR_EL2}, + {"ESR_EL3", SYSTEM_ESR_EL3}, + {NULL, 0} +}; + +/* read/write system registers (mrs=read) (msr=write)*/ +static int jim_mrsmsr(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct command *c = jim_to_command(interp); + struct command_context *context; + struct target *target; + struct armv8_common *armv8; + int retval; + bool is_msr = false; + uint64_t sr; + + if (!strcmp(c->name, "msr")) { + is_msr = true; + } + + context = current_command_context(interp); + assert(context); + + target = get_current_target(context); + if (!target) { + LOG_ERROR("%s: no current target", __func__); + return JIM_ERR; + } + if (!target_was_examined(target)) { + LOG_ERROR("%s: not yet examined", target_name(target)); + return JIM_ERR; + } + + armv8 = target_to_armv8(target); + if (!is_armv8(armv8)) { + LOG_ERROR("%s: not an ARMv8", target_name(target)); + return JIM_ERR; + } + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + if (armv8->arm.core_state != ARM_STATE_AARCH64) { + LOG_ERROR("%s: not 64-bit arm target", target_name(target)); + return JIM_ERR; + } + + long l; + int len; + int names = 0; + char *argv1 = (char *)Jim_GetString(argv[1], &len); + char name_buf[32]; + char jim_buf[256]; + uint32_t reg = 0; + + while (sysreg_nameop[names].name != NULL) + { + if (strcasecmp(argv1, sysreg_nameop[names].name) == 0) + { + reg = sysreg_nameop[names].value; + if (is_msr) { + if (Jim_GetLong(interp, argv[2],(int64_t*) &sr) != JIM_OK) + return JIM_ERR; + } + break; + } + names++; + } + + if (sysreg_nameop[names].name == NULL) + { + /* didn't find the name, try to form the register from vals */ + int arg[5]; + + for (names = 1; names < 6; names++ ) { + /* ok try value parsing */ + if (Jim_GetLong(interp, argv[names], &l) != JIM_OK) + return JIM_ERR; + if (l & ~0xf) { + LOG_ERROR("%s: %d %d out of range", __func__, names, (int) l); + return JIM_ERR; + } + arg[names-1] = l; + } + reg = ARMV8_SYSREG(arg[0], arg[1], arg[2], arg[3], arg[4]); + + // create a regname for the result + snprintf(name_buf, 32, "0x%X", reg); + argv1 = name_buf; + if (is_msr) { + if (Jim_GetLong(interp, argv[6],(int64_t*) &sr) != JIM_OK) + return JIM_ERR; + } + + } + + retval = armv8->dpm.prepare(&armv8->dpm); + if (retval != ERROR_OK) { + LOG_ERROR("%s: can't dpm->prepare", __func__); + return retval; + } + + if (is_msr) + { + retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, ARMV8_MSR_GP(reg, 0), sr); + if (retval != ERROR_OK) { + LOG_ERROR("%s: can't dpm->write64", __func__); + return retval; + } + sprintf(jim_buf, "msr %s: (wrote) 0x%lX", argv1, sr); + Jim_SetResultString(interp, jim_buf, -1); + } + else + { + retval = armv8->dpm.instr_read_data_r0_64(&armv8->dpm, ARMV8_MRS(reg, 0), &sr); + if (retval != ERROR_OK) { + LOG_ERROR("%s: can't dpm->read64", __func__); + return retval; + } + sprintf(jim_buf, "mrs %s: (read) 0x%lX", argv1, sr); + Jim_SetResultString(interp, jim_buf, -1); + } + + retval = armv8->dpm.finish(&armv8->dpm); + if (retval != ERROR_OK) { + LOG_ERROR("%s: can't dpm->finish", __func__); + return retval; + } + + return JIM_OK; +} + + static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command *c = jim_to_command(interp); @@ -3148,6 +3343,21 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, + { + .name = "mrs", + .mode = COMMAND_EXEC, + .jim_handler = jim_mrsmsr, + .help = "read system register", + .usage = "sysreg | [op0 CRn op1 CRm op2]", + }, + { + .name = "msr", + .mode = COMMAND_EXEC, + .jim_handler = jim_mrsmsr, + .help = "write system register", + .usage = "sysreg | op0 CRn op1 CRm op2 width, value", + }, + { .chain = smp_command_handlers, }, --