X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7a.c;h=437a2f26669e58a57a3ec5c56c2d38625ae77c3c;hp=18416e5a94ab0527e5d0b49eeab8c28b781506dd;hb=a5a882c5c808baa9da543a20d50aa134423e45cc;hpb=8704e53665910ba71e5bc3f99b32ead0060e1a3e diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 18416e5a94..437a2f2666 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -14,9 +14,7 @@ * 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -26,6 +24,7 @@ #include #include "armv7a.h" +#include "armv7a_mmu.h" #include "arm_disassembler.h" #include "register.h" @@ -126,14 +125,18 @@ done: return retval; } -static int armv7a_read_ttbcr(struct target *target) +int armv7a_read_ttbcr(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t ttbcr, ttbcr_n; - int retval = dpm->prepare(dpm); + int ttbidx; + int retval; + + retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; + /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 2, 0, 2), @@ -147,6 +150,15 @@ static int armv7a_read_ttbcr(struct target *target) armv7a->armv7a_mmu.ttbcr = ttbcr; armv7a->armv7a_mmu.cached = 1; + for (ttbidx = 0; ttbidx < 2; ttbidx++) { + /* MRC p15,0,,c2,c0,ttbidx */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx), + &armv7a->armv7a_mmu.ttbr[ttbidx]); + if (retval != ERROR_OK) + goto done; + } + /* * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition), * document # ARM DDI 0406C @@ -172,253 +184,11 @@ static int armv7a_read_ttbcr(struct target *target) armv7a->armv7a_mmu.ttbr_mask[0], armv7a->armv7a_mmu.ttbr_mask[1]); - /* FIXME: default is hard coded LINUX border */ - armv7a->armv7a_mmu.os_border = 0xc0000000; - if (ttbcr_n != 0) { - LOG_INFO("SVC access above %" PRIx32, - armv7a->armv7a_mmu.ttbr_range[0] + 1); - armv7a->armv7a_mmu.os_border = armv7a->armv7a_mmu.ttbr_range[0] + 1; - } -done: - dpm->finish(dpm); - return retval; -} - -/* method adapted to cortex A : reused arm v4 v5 method*/ -int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) -{ - uint32_t first_lvl_descriptor = 0x0; - uint32_t second_lvl_descriptor = 0x0; - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct arm_dpm *dpm = armv7a->arm.dpm; - uint32_t ttbidx = 0; /* default to ttbr0 */ - uint32_t ttb_mask; - uint32_t va_mask; - uint32_t ttbcr; - uint32_t ttb; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - - /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ - retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 2, 0, 2), - &ttbcr); - if (retval != ERROR_OK) - goto done; - - /* if ttbcr has changed or was not read before, re-read the information */ - if ((armv7a->armv7a_mmu.cached == 0) || - (armv7a->armv7a_mmu.ttbcr != ttbcr)) { - armv7a_read_ttbcr(target); - } - - /* if va is above the range handled by ttbr0, select ttbr1 */ - if (va > armv7a->armv7a_mmu.ttbr_range[0]) { - /* select ttb 1 */ - ttbidx = 1; - } - /* MRC p15,0,,c2,c0,ttbidx */ - retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx), - &ttb); - if (retval != ERROR_OK) - return retval; - - ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx]; - va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx]; - - LOG_DEBUG("ttb_mask %" PRIx32 " va_mask %" PRIx32 " ttbidx %i", - ttb_mask, va_mask, ttbidx); - retval = armv7a->armv7a_mmu.read_physical_memory(target, - (ttb & ttb_mask) | ((va & va_mask) >> 18), - 4, 1, (uint8_t *)&first_lvl_descriptor); - if (retval != ERROR_OK) - return retval; - first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) - &first_lvl_descriptor); - /* reuse armv4_5 piece of code, specific armv7a changes may come later */ - LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor); - - if ((first_lvl_descriptor & 0x3) == 0) { - LOG_ERROR("Address translation failure"); - return ERROR_TARGET_TRANSLATION_FAULT; - } - - - if ((first_lvl_descriptor & 0x40002) == 2) { - /* section descriptor */ - *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff); - return ERROR_OK; - } else if ((first_lvl_descriptor & 0x40002) == 0x40002) { - /* supersection descriptor */ - if (first_lvl_descriptor & 0x00f001e0) { - LOG_ERROR("Physical address does not fit into 32 bits"); - return ERROR_TARGET_TRANSLATION_FAULT; - } - *val = (first_lvl_descriptor & 0xff000000) | (va & 0x00ffffff); - return ERROR_OK; - } - - /* page table */ - retval = armv7a->armv7a_mmu.read_physical_memory(target, - (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10), - 4, 1, (uint8_t *)&second_lvl_descriptor); - if (retval != ERROR_OK) - return retval; - - second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) - &second_lvl_descriptor); - - LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor); - - if ((second_lvl_descriptor & 0x3) == 0) { - LOG_ERROR("Address translation failure"); - return ERROR_TARGET_TRANSLATION_FAULT; - } - - if ((second_lvl_descriptor & 0x3) == 1) { - /* large page descriptor */ - *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff); - } else { - /* small page descriptor */ - *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff); - } - - return ERROR_OK; - -done: - return retval; -} - -/* V7 method VA TO PA */ -int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va, - uint32_t *val, int meminfo) -{ - int retval = ERROR_FAIL; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct arm_dpm *dpm = armv7a->arm.dpm; - uint32_t virt = va & ~0xfff; - uint32_t NOS, NS, INNER, OUTER; - *val = 0xdeadbeef; - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - /* mmu must be enable in order to get a correct translation - * use VA to PA CP15 register for conversion */ - retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 8, 0), - virt); - if (retval != ERROR_OK) - goto done; - retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 7, 4, 0), - val); - /* decode memory attribute */ - NOS = (*val >> 10) & 1; /* Not Outer shareable */ - NS = (*val >> 9) & 1; /* Non secure */ - INNER = (*val >> 4) & 0x7; - OUTER = (*val >> 2) & 0x3; - - if (retval != ERROR_OK) - goto done; - *val = (*val & ~0xfff) + (va & 0xfff); - if (*val == va) - LOG_WARNING("virt = phys : MMU disable !!"); - if (meminfo) { - LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured", - va, *val, - NOS == 1 ? "not" : " ", - NS == 1 ? "not" : ""); - switch (OUTER) { - case 0: - LOG_INFO("outer: Non-Cacheable"); - break; - case 1: - LOG_INFO("outer: Write-Back, Write-Allocate"); - break; - case 2: - LOG_INFO("outer: Write-Through, No Write-Allocate"); - break; - case 3: - LOG_INFO("outer: Write-Back, no Write-Allocate"); - break; - } - switch (INNER) { - case 0: - LOG_INFO("inner: Non-Cacheable"); - break; - case 1: - LOG_INFO("inner: Strongly-ordered"); - break; - case 3: - LOG_INFO("inner: Device"); - break; - case 5: - LOG_INFO("inner: Write-Back, Write-Allocate"); - break; - case 6: - LOG_INFO("inner: Write-Through"); - break; - case 7: - LOG_INFO("inner: Write-Back, no Write-Allocate"); - - default: - LOG_INFO("inner: %" PRIx32 " ???", INNER); - } - } - done: dpm->finish(dpm); - return retval; } -static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx, - struct armv7a_cache_common *armv7a_cache) -{ - int cl; - - if (armv7a_cache->info == -1) { - command_print(cmd_ctx, "cache not yet identified"); - return ERROR_OK; - } - - for (cl = 0; cl < armv7a_cache->loc; cl++) { - struct armv7a_arch_cache *arch = &(armv7a_cache->arch[cl]); - - if (arch->ctype & 1) { - command_print(cmd_ctx, - "L%d I-Cache: linelen %" PRIi32 - ", associativity %" PRIi32 - ", nsets %" PRIi32 - ", cachesize %" PRId32 " KBytes", - cl+1, - arch->i_size.linelen, - arch->i_size.associativity, - arch->i_size.nsets, - arch->i_size.cachesize); - } - - if (arch->ctype >= 2) { - command_print(cmd_ctx, - "L%d D-Cache: linelen %" PRIi32 - ", associativity %" PRIi32 - ", nsets %" PRIi32 - ", cachesize %" PRId32 " KBytes", - cl+1, - arch->d_u_size.linelen, - arch->d_u_size.associativity, - arch->d_u_size.nsets, - arch->d_u_size.cachesize); - } - } - - return ERROR_OK; -} - /* FIXME: remove it */ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) { @@ -475,13 +245,43 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) (armv7a_cache->outer_cache); + int cl; + if (armv7a_cache->info == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } - if (armv7a_cache->display_cache_info) - armv7a_cache->display_cache_info(cmd_ctx, armv7a_cache); + for (cl = 0; cl < armv7a_cache->loc; cl++) { + struct armv7a_arch_cache *arch = &(armv7a_cache->arch[cl]); + + if (arch->ctype & 1) { + command_print(cmd_ctx, + "L%d I-Cache: linelen %" PRIi32 + ", associativity %" PRIi32 + ", nsets %" PRIi32 + ", cachesize %" PRId32 " KBytes", + cl+1, + arch->i_size.linelen, + arch->i_size.associativity, + arch->i_size.nsets, + arch->i_size.cachesize); + } + + if (arch->ctype >= 2) { + command_print(cmd_ctx, + "L%d D-Cache: linelen %" PRIi32 + ", associativity %" PRIi32 + ", nsets %" PRIi32 + ", cachesize %" PRId32 " KBytes", + cl+1, + arch->d_u_size.linelen, + arch->d_u_size.associativity, + arch->d_u_size.nsets, + arch->d_u_size.cachesize); + } + } + if (l2x_cache != NULL) command_print(cmd_ctx, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways", l2x_cache->base, l2x_cache->way); @@ -587,9 +387,6 @@ int armv7a_identify_cache(struct target *target) struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache); - if (!armv7a->is_armv7r) - armv7a_read_ttbcr(target); - retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; @@ -689,8 +486,6 @@ int armv7a_identify_cache(struct target *target) /* if no l2 cache initialize l1 data cache flush function function */ if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) { - armv7a->armv7a_mmu.armv7a_cache.display_cache_info = - armv7a_handle_inner_cache_info_command; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = armv7a_cache_auto_flush_all_data; } @@ -703,11 +498,40 @@ done: } +static int armv7a_setup_semihosting(struct target *target, int enable) +{ + struct armv7a_common *armv7a = target_to_armv7a(target); + uint32_t vcr; + int ret; + + ret = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + &vcr); + if (ret < 0) { + LOG_ERROR("Failed to read VCR register\n"); + return ret; + } + + if (enable) + vcr |= DBG_VCR_SVC_MASK; + else + vcr &= ~DBG_VCR_SVC_MASK; + + ret = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + vcr); + if (ret < 0) + LOG_ERROR("Failed to write VCR register\n"); + + return ret; +} + int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) { struct arm *arm = &armv7a->arm; arm->arch_info = armv7a; target->arch_info = &armv7a->arm; + arm->setup_semihosting = armv7a_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv7a->arm.target = target; armv7a->arm.common_magic = ARM_COMMON_MAGIC; @@ -715,7 +539,6 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) armv7a->armv7a_mmu.armv7a_cache.info = -1; armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL; - armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL; armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1; return ERROR_OK; } @@ -761,8 +584,7 @@ static const struct command_registration l2_cache_commands[] = { .name = "l2x", .handler = handle_cache_l2x, .mode = COMMAND_EXEC, - .help = "configure l2x cache " - "", + .help = "configure l2x cache", .usage = "[base_addr] [number_of_way]", }, COMMAND_REGISTRATION_DONE @@ -781,9 +603,6 @@ const struct command_registration l2x_cache_command_handlers[] = { }; const struct command_registration armv7a_command_handlers[] = { - { - .chain = dap_command_handlers, - }, { .chain = l2x_cache_command_handlers, },