X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv8.c;h=4054c954fbaac890b0feadf44677f867c6ba21fd;hp=b88f37d6bd02a033c325f387eca48b1d77a05d1c;hb=c867806f0d3bd8e8b175093b9024bf781758cd07;hpb=1756f393e45c2a23dd29ff8bc85d188b547624f9 diff --git a/src/target/armv8.c b/src/target/armv8.c index b88f37d6bd..4054c954fb 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1,6 +1,9 @@ /*************************************************************************** * Copyright (C) 2015 by David Ung * * * + * 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 * @@ -36,6 +39,7 @@ #include "armv8_opcodes.h" #include "target.h" #include "target_type.h" +#include "semihosting_common.h" static const char * const armv8_state_strings[] = { "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", @@ -69,6 +73,10 @@ static const struct { .name = "ABT", .psr = ARM_MODE_ABT, }, + { + .name = "SYS", + .psr = ARM_MODE_SYS, + }, { .name = "EL0T", .psr = ARMV8_64_EL0T, @@ -638,7 +646,7 @@ int armv8_read_mpidr(struct armv8_common *armv8) retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); if (retval != ERROR_OK) goto done; - if (mpidr & 1<<31) { + if (mpidr & 1U<<31) { armv8->multi_processor_system = (mpidr >> 30) & 1; armv8->cluster_id = (mpidr >> 8) & 0xf; armv8->cpu_id = mpidr & 0x3; @@ -670,8 +678,8 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) */ if (arm->cpsr) { buf_set_u32(arm->cpsr->value, 0, 32, cpsr); - arm->cpsr->valid = 1; - arm->cpsr->dirty = 0; + arm->cpsr->valid = true; + arm->cpsr->dirty = false; } /* Older ARMs won't have the J bit */ @@ -932,6 +940,11 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, "Secure", "Not Secure" }; + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s not halted", target_name(target)); + return ERROR_TARGET_NOT_HALTED; + } + retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; @@ -1000,16 +1013,94 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, return retval; } -int armv8_handle_cache_info_command(struct command_context *cmd_ctx, +COMMAND_HANDLER(armv8_handle_exception_catch_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct armv8_common *armv8 = target_to_armv8(target); + uint32_t edeccr = 0; + unsigned int argp = 0; + int retval; + + static const Jim_Nvp nvp_ecatch_modes[] = { + { .name = "off", .value = 0 }, + { .name = "nsec_el1", .value = (1 << 5) }, + { .name = "nsec_el2", .value = (2 << 5) }, + { .name = "nsec_el12", .value = (3 << 5) }, + { .name = "sec_el1", .value = (1 << 1) }, + { .name = "sec_el3", .value = (4 << 1) }, + { .name = "sec_el13", .value = (5 << 1) }, + { .name = NULL, .value = -1 }, + }; + const Jim_Nvp *n; + + if (CMD_ARGC == 0) { + const char *sec = NULL, *nsec = NULL; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_ECCR, &edeccr); + if (retval != ERROR_OK) + return retval; + + n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0x0f); + if (n->name != NULL) + sec = n->name; + + n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0xf0); + if (n->name != NULL) + nsec = n->name; + + if (sec == NULL || nsec == NULL) { + LOG_WARNING("Exception Catch: unknown exception catch configuration: EDECCR = %02x", edeccr & 0xff); + return ERROR_FAIL; + } + + command_print(CMD_CTX, "Exception Catch: Secure: %s, Non-Secure: %s", sec, nsec); + return ERROR_OK; + } + + while (CMD_ARGC > argp) { + n = Jim_Nvp_name2value_simple(nvp_ecatch_modes, CMD_ARGV[argp]); + if (n->name == NULL) { + LOG_ERROR("Unknown option: %s", CMD_ARGV[argp]); + return ERROR_FAIL; + } + + LOG_DEBUG("found: %s", n->name); + + edeccr |= n->value; + argp++; + } + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_ECCR, edeccr); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +int armv8_handle_cache_info_command(struct command_invocation *cmd, struct armv8_cache_common *armv8_cache) { if (armv8_cache->info == -1) { - command_print(cmd_ctx, "cache not yet identified"); + command_print(cmd->ctx, "cache not yet identified"); return ERROR_OK; } if (armv8_cache->display_cache_info) - armv8_cache->display_cache_info(cmd_ctx, armv8_cache); + armv8_cache->display_cache_info(cmd, armv8_cache); + return ERROR_OK; +} + +static int armv8_setup_semihosting(struct target *target, int enable) +{ + struct arm *arm = target_to_arm(target); + + if (arm->core_state != ARM_STATE_AARCH64) { + LOG_ERROR("semihosting only supported in AArch64 state\n"); + return ERROR_FAIL; + } + return ERROR_OK; } @@ -1018,6 +1109,7 @@ int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) struct arm *arm = &armv8->arm; arm->arch_info = armv8; target->arch_info = &armv8->arm; + arm->setup_semihosting = armv8_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv8->arm.target = target; armv8->arm.common_magic = ARM_COMMON_MAGIC; @@ -1046,7 +1138,7 @@ int armv8_aarch64_state(struct target *target) armv8_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u64(arm->pc->value, 0, 64), - arm->is_semihosting ? ", semihosting" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : ""); return ERROR_OK; } @@ -1426,17 +1518,17 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) armv8_set_cpsr(arm, (uint32_t)value); else { buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = 1; + reg->valid = true; } } else if (reg->size <= 128) { uint64_t hvalue = buf_get_u64(buf + 8, 0, reg->size - 64); buf_set_u64(reg->value, 0, 64, value); buf_set_u64(reg->value + 8, 0, reg->size - 64, hvalue); - reg->valid = 1; + reg->valid = true; } - reg->dirty = 1; + reg->dirty = true; return ERROR_OK; } @@ -1455,6 +1547,9 @@ static int armv8_get_core_reg32(struct reg *reg) struct reg *reg64; int retval; + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + /* get the corresponding Aarch64 register */ reg64 = cache->reg_list + armv8_reg->num; if (reg64->valid) { @@ -1478,6 +1573,9 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) struct reg *reg64 = cache->reg_list + armv8_reg->num; uint32_t value = buf_get_u32(buf, 0, 32); + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + if (reg64 == arm->cpsr) { armv8_set_cpsr(arm, value); } else { @@ -1487,11 +1585,11 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) uint64_t value64 = buf_get_u64(buf, 0, 64); buf_set_u64(reg->value, 0, 64, value64); } - reg->valid = 1; - reg64->valid = 1; + reg->valid = true; + reg64->valid = true; } - reg64->dirty = 1; + reg64->dirty = true; return ERROR_OK; } @@ -1547,15 +1645,14 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) } else LOG_ERROR("unable to allocate feature list"); - if (armv8_regs[i].data_type == NULL) { - reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); - if (reg_list[i].reg_data_type) + reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); + if (reg_list[i].reg_data_type) { + if (armv8_regs[i].data_type == NULL) reg_list[i].reg_data_type->type = armv8_regs[i].type; else - LOG_ERROR("unable to allocate reg type list"); + *reg_list[i].reg_data_type = *armv8_regs[i].data_type; } else - reg_list[i].reg_data_type = armv8_regs[i].data_type; - + LOG_ERROR("unable to allocate reg type list"); } arm->cpsr = reg_list + ARMV8_xPSR; @@ -1608,13 +1705,56 @@ struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) return r; } +static void armv8_free_cache(struct reg_cache *cache, bool regs32) +{ + struct reg *reg; + unsigned int i; + + if (!cache) + return; + + for (i = 0; i < cache->num_regs; i++) { + reg = &cache->reg_list[i]; + + free(reg->feature); + free(reg->reg_data_type); + } + + if (!regs32) + free(cache->reg_list[0].arch_info); + free(cache->reg_list); + free(cache); +} + +void armv8_free_reg_cache(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + struct reg_cache *cache = NULL, *cache32 = NULL; + + cache = arm->core_cache; + if (cache != NULL) + cache32 = cache->next; + armv8_free_cache(cache32, true); + armv8_free_cache(cache, false); + arm->core_cache = NULL; +} + const struct command_registration armv8_command_handlers[] = { { - .chain = dap_command_handlers, + .name = "catch_exc", + .handler = armv8_handle_exception_catch_command, + .mode = COMMAND_EXEC, + .help = "configure exception catch", + .usage = "[(nsec_el1,nsec_el2,sec_el1,sec_el3)+,off]", }, COMMAND_REGISTRATION_DONE }; +const char *armv8_get_gdb_arch(struct target *target) +{ + return "aarch64"; +} int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size,