X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftarget%2Farmv4_5.c;h=2759b4633af90094cf9d1b83d78d7889620ce90f;hb=057e566097b41f9bfeee50e97ba6ef624189ae6a;hp=6d03857152513e44200fdc4655cc6ef91240760e;hpb=f447c31b30f805725b7a09d51d786c88de4b7a4f;p=fw%2Fopenocd diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 6d0385715..2759b4633 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * @@ -10,19 +12,6 @@ * * * Copyright (C) 2018 by Liviu Ionescu * * * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -48,6 +37,7 @@ enum { ARMV4_5_SPSR_ABT = 35, ARMV4_5_SPSR_UND = 36, ARM_SPSR_MON = 41, + ARM_SPSR_HYP = 43, }; static const uint8_t arm_usr_indices[17] = { @@ -78,6 +68,10 @@ static const uint8_t arm_mon_indices[3] = { 39, 40, ARM_SPSR_MON, }; +static const uint8_t arm_hyp_indices[2] = { + 42, ARM_SPSR_HYP, +}; + static const struct { const char *name; unsigned short psr; @@ -163,6 +157,14 @@ static const struct { .name = "Handler", .psr = ARM_MODE_HANDLER, }, + + /* armv7-a with virtualization extension */ + { + .name = "Hypervisor", + .psr = ARM_MODE_HYP, + .n_indices = ARRAY_SIZE(arm_hyp_indices), + .indices = arm_hyp_indices, + }, }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ @@ -209,6 +211,8 @@ int arm_mode_to_number(enum arm_mode mode) case ARM_MODE_MON: case ARM_MODE_1176_MON: return 7; + case ARM_MODE_HYP: + return 8; default: LOG_ERROR("invalid mode value encountered %d", mode); return -1; @@ -235,6 +239,8 @@ enum arm_mode armv4_5_number_to_mode(int number) return ARM_MODE_SYS; case 7: return ARM_MODE_MON; + case 8: + return ARM_MODE_HYP; default: LOG_ERROR("mode index out of bounds %d", number); return ARM_MODE_ANY; @@ -342,6 +348,9 @@ static const struct { [40] = { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, }, [41] = { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, }, + /* These exist only when the Virtualization Extensions is present */ + [42] = { .name = "sp_hyp", .cookie = 13, .mode = ARM_MODE_HYP, .gdb_index = 51, }, + [43] = { .name = "spsr_hyp", .cookie = 16, .mode = ARM_MODE_HYP, .gdb_index = 52, }, }; static const struct { @@ -391,7 +400,7 @@ static const struct { /* map core mode (USR, FIQ, ...) and register number to * indices into the register cache */ -const int armv4_5_core_reg_map[8][17] = { +const int armv4_5_core_reg_map[9][17] = { { /* USR */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31 }, @@ -415,6 +424,9 @@ const int armv4_5_core_reg_map[8][17] = { }, { /* MON */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 39, 40, 15, 41, + }, + { /* HYP */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 42, 14, 15, 43, } }; @@ -658,7 +670,11 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) for (i = 0; i < num_core_regs; i++) { /* Skip registers this core doesn't expose */ if (arm_core_regs[i].mode == ARM_MODE_MON - && arm->core_type != ARM_MODE_MON) + && arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) continue; /* REVISIT handle Cortex-M, which only shadows R13/SP */ @@ -742,6 +758,27 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) return cache; } +void arm_free_reg_cache(struct arm *arm) +{ + if (!arm || !arm->core_cache) + return; + + struct reg_cache *cache = arm->core_cache; + + for (unsigned int i = 0; i < cache->num_regs; i++) { + struct reg *reg = &cache->reg_list[i]; + + free(reg->feature); + free(reg->reg_data_type); + } + + free(cache->reg_list[0].arch_info); + free(cache->reg_list); + free(cache); + + arm->core_cache = NULL; +} + int arm_arch_state(struct target *target) { struct arm *arm = target_to_arm(target); @@ -768,9 +805,6 @@ int arm_arch_state(struct target *target) return ERROR_OK; } -#define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \ - (cache->reg_list[armv4_5_core_reg_map[mode][num]]) - COMMAND_HANDLER(handle_armv4_5_reg_command) { struct target *target = get_current_target(CMD_CTX); @@ -787,7 +821,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) return ERROR_FAIL; } - if (arm->core_type != ARM_MODE_ANY) { + if (arm->core_type != ARM_CORE_TYPE_STD) { command_print(CMD, "Microcontroller Profile not supported - use standard reg cmd"); return ERROR_OK; @@ -811,6 +845,9 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) char *sep = "\n"; char *shadow = ""; + if (!arm_mode_data[mode].n_indices) + continue; + /* label this bank of registers (or shadows) */ switch (arm_mode_data[mode].psr) { case ARM_MODE_SYS: @@ -819,8 +856,14 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) name = "System and User"; sep = ""; break; + case ARM_MODE_HYP: + if (arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + /* FALLTHROUGH */ case ARM_MODE_MON: - if (arm->core_type != ARM_MODE_MON) + case ARM_MODE_1176_MON: + if (arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) continue; /* FALLTHROUGH */ default: @@ -872,7 +915,7 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) return ERROR_FAIL; } - if (arm->core_type == ARM_MODE_THREAD) { + if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) { /* armv7m not supported */ command_print(CMD, "Unsupported Command"); return ERROR_OK; @@ -892,82 +935,57 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) COMMAND_HANDLER(handle_arm_disassemble_command) { - int retval = ERROR_OK; +#if HAVE_CAPSTONE struct target *target = get_current_target(CMD_CTX); - if (target == NULL) { + if (!target) { LOG_ERROR("No target selected"); return ERROR_FAIL; } struct arm *arm = target_to_arm(target); target_addr_t address; - int count = 1; - int thumb = 0; + unsigned int count = 1; + bool thumb = false; if (!is_arm(arm)) { command_print(CMD, "current target isn't an ARM"); return ERROR_FAIL; } - if (arm->core_type == ARM_MODE_THREAD) { + if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) { /* armv7m is always thumb mode */ - thumb = 1; + thumb = true; } switch (CMD_ARGC) { case 3: if (strcmp(CMD_ARGV[2], "thumb") != 0) - goto usage; - thumb = 1; + return ERROR_COMMAND_SYNTAX_ERROR; + thumb = true; /* FALL THROUGH */ case 2: - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count); + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); /* FALL THROUGH */ case 1: COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); if (address & 0x01) { if (!thumb) { command_print(CMD, "Disassemble as Thumb"); - thumb = 1; + thumb = true; } address &= ~1; } break; default: -usage: - count = 0; - retval = ERROR_COMMAND_SYNTAX_ERROR; - } - - while (count-- > 0) { - struct arm_instruction cur_instruction; - - if (thumb) { - /* Always use Thumb2 disassembly for best handling - * of 32-bit BL/BLX, and to work with newer cores - * (some ARMv6, all ARMv7) that use Thumb2. - */ - retval = thumb2_opcode(target, address, - &cur_instruction); - if (retval != ERROR_OK) - break; - } else { - uint32_t opcode; - - retval = target_read_u32(target, address, &opcode); - if (retval != ERROR_OK) - break; - retval = arm_evaluate_opcode(opcode, address, - &cur_instruction) != ERROR_OK; - if (retval != ERROR_OK) - break; - } - command_print(CMD, "%s", cur_instruction.text); - address += cur_instruction.instruction_size; + return ERROR_COMMAND_SYNTAX_ERROR; } - return retval; + return arm_disassemble(CMD, target, address, count, thumb); +#else + command_print(CMD, "capstone disassembly framework required"); + return ERROR_FAIL; +#endif } static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) @@ -978,10 +996,10 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) int retval; context = current_command_context(interp); - assert(context != NULL); + assert(context); target = get_current_target(context); - if (target == NULL) { + if (!target) { LOG_ERROR("%s: no current target", __func__); return JIM_ERR; } @@ -1004,8 +1022,8 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) int cpnum; uint32_t op1; uint32_t op2; - uint32_t CRn; - uint32_t CRm; + uint32_t crn; + uint32_t crm; uint32_t value; long l; @@ -1042,7 +1060,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) "CRn", (int) l); return JIM_ERR; } - CRn = l; + crn = l; retval = Jim_GetLong(interp, argv[4], &l); if (retval != JIM_OK) @@ -1052,7 +1070,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) "CRm", (int) l); return JIM_ERR; } - CRm = l; + crm = l; retval = Jim_GetLong(interp, argv[5], &l); if (retval != JIM_OK) @@ -1081,14 +1099,14 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) value = l; /* NOTE: parameters reordered! */ - /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */ - retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value); + /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */ + retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value); if (retval != ERROR_OK) return JIM_ERR; } else { /* NOTE: parameters reordered! */ - /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */ - retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value); + /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */ + retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value); if (retval != ERROR_OK) return JIM_ERR; @@ -1120,7 +1138,7 @@ static const struct command_registration arm_exec_command_handlers[] = { .handler = handle_arm_disassemble_command, .mode = COMMAND_EXEC, .usage = "address [count ['thumb']]", - .help = "disassemble instructions ", + .help = "disassemble instructions", }, { .name = "mcr", @@ -1194,10 +1212,18 @@ int arm_get_gdb_reg_list(struct target *target, (*reg_list)[25] = arm->cpsr; return ERROR_OK; - break; case REG_CLASS_ALL: - *reg_list_size = (arm->core_type != ARM_MODE_MON ? 48 : 51); + switch (arm->core_type) { + case ARM_CORE_TYPE_SEC_EXT: + *reg_list_size = 51; + break; + case ARM_CORE_TYPE_VIRT_EXT: + *reg_list_size = 53; + break; + default: + *reg_list_size = 48; + } unsigned int list_size_core = *reg_list_size; if (arm->arm_vfp_version == ARM_VFP_V3) *reg_list_size += 33; @@ -1209,9 +1235,15 @@ int arm_get_gdb_reg_list(struct target *target, for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) { int reg_index = arm->core_cache->reg_list[i].number; - if (!(arm_core_regs[i].mode == ARM_MODE_MON - && arm->core_type != ARM_MODE_MON)) - (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); + + if (arm_core_regs[i].mode == ARM_MODE_MON + && arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); } /* When we supply the target description, there is no need for fake FPA */ @@ -1229,12 +1261,10 @@ int arm_get_gdb_reg_list(struct target *target, } return ERROR_OK; - break; default: LOG_ERROR("not a valid register class type in query."); return ERROR_FAIL; - break; } } @@ -1306,7 +1336,7 @@ int armv4_5_run_algorithm_inner(struct target *target, } /* armv5 and later can terminate with BKPT instruction; less overhead */ - if (!exit_point && arm->is_armv4) { + if (!exit_point && arm->arch == ARM_ARCH_V4) { LOG_ERROR("ARMv4 target needs HW breakpoint location"); return ERROR_FAIL; } @@ -1339,7 +1369,7 @@ int armv4_5_run_algorithm_inner(struct target *target, if (reg_params[i].direction == PARAM_IN) continue; - struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0); + struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, false); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; @@ -1411,7 +1441,7 @@ int armv4_5_run_algorithm_inner(struct target *target, struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, - 0); + false); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); retval = ERROR_COMMAND_SYNTAX_ERROR; @@ -1527,7 +1557,7 @@ int arm_checksum_memory(struct target *target, int timeout = 20000 * (1 + (count / (1024 * 1024))); /* armv4 must exit using a hardware breakpoint */ - if (arm->is_armv4) + if (arm->arch == ARM_ARCH_V4) exit_var = crc_algorithm->address + sizeof(arm_crc_code_le) - 8; retval = target_run_algorithm(target, 0, NULL, 2, reg_params, @@ -1608,7 +1638,7 @@ int arm_blank_check_memory(struct target *target, buf_set_u32(reg_params[2].value, 0, 32, erased_value); /* armv4 must exit using a hardware breakpoint */ - if (arm->is_armv4) + if (arm->arch == ARM_ARCH_V4) exit_var = check_algorithm->address + sizeof(check_code_le) - 4; retval = target_run_algorithm(target, 0, NULL, 3, reg_params, @@ -1640,7 +1670,7 @@ static int arm_full_context(struct target *target) int retval = ERROR_OK; for (; num_regs && retval == ERROR_OK; num_regs--, reg++) { - if (reg->valid) + if (!reg->exist || reg->valid) continue; retval = armv4_5_get_core_reg(reg); } @@ -1649,7 +1679,7 @@ static int arm_full_context(struct target *target) static int arm_default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, - uint32_t CRn, uint32_t CRm, + uint32_t crn, uint32_t crm, uint32_t *value) { LOG_ERROR("%s doesn't implement MRC", target_type_name(target)); @@ -1658,7 +1688,7 @@ static int arm_default_mrc(struct target *target, int cpnum, static int arm_default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, - uint32_t CRn, uint32_t CRm, + uint32_t crn, uint32_t crm, uint32_t value) { LOG_ERROR("%s doesn't implement MCR", target_type_name(target)); @@ -1673,8 +1703,8 @@ int arm_init_arch_info(struct target *target, struct arm *arm) arm->common_magic = ARM_COMMON_MAGIC; /* core_type may be overridden by subtype logic */ - if (arm->core_type != ARM_MODE_THREAD) { - arm->core_type = ARM_MODE_ANY; + if (arm->core_type != ARM_CORE_TYPE_M_PROFILE) { + arm->core_type = ARM_CORE_TYPE_STD; arm_set_cpsr(arm, ARM_MODE_USR); }