X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftarget%2Farmv7a.c;h=9511ed98a0950582c78102b494c9f23aaf212f27;hb=057e566097b41f9bfeee50e97ba6ef624189ae6a;hp=fab7363105c33c9f19a92d733c80eca87d9da1ae;hpb=2231da8ec4e7d7ae9b652f3dd1a7104f5a110f3f;p=fw%2Fopenocd diff --git a/src/target/armv7a.c b/src/target/armv7a.c index fab736310..9511ed98a 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -1,20 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /*************************************************************************** * Copyright (C) 2009 by David Brownell * * * * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com * - * * - * 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 @@ -24,6 +13,7 @@ #include #include "armv7a.h" +#include "armv7a_mmu.h" #include "arm_disassembler.h" #include "register.h" @@ -37,6 +27,7 @@ #include "arm_opcodes.h" #include "target.h" #include "target_type.h" +#include "smp.h" static void armv7a_show_fault_registers(struct target *target) { @@ -49,7 +40,7 @@ static void armv7a_show_fault_registers(struct target *target) if (retval != ERROR_OK) return; - /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */ + /* ARMV4_5_MRC(cpnum, op1, r0, crn, crm, op2) */ /* c5/c0 - {data, instruction} fault status registers */ retval = dpm->instr_read_data_r0(dpm, @@ -110,7 +101,7 @@ static int armv7a_read_midr(struct target *target) armv7a->arch = (midr >> 16) & 0xf; armv7a->variant = (midr >> 20) & 0xf; armv7a->implementor = (midr >> 24) & 0xff; - LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 + LOG_DEBUG("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 ", variant %" PRIx32 ", implementor %" PRIx32, target->cmd_name, armv7a->rev, @@ -124,7 +115,7 @@ 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; @@ -159,7 +150,7 @@ static int armv7a_read_ttbcr(struct target *target) } /* - * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition), + * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition), * document # ARM DDI 0406C */ armv7a->armv7a_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n; @@ -188,180 +179,11 @@ done: 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); - uint32_t ttbidx = 0; /* default to ttbr0 */ - uint32_t ttb_mask; - uint32_t va_mask; - uint32_t ttb; - - if (target->state != TARGET_HALTED) - LOG_INFO("target not halted, using cached values for translation table!"); - - /* if va is above the range handled by ttbr0, select ttbr1 */ - if (va > armv7a->armv7a_mmu.ttbr_range[0]) { - /* select ttb 1 */ - ttbidx = 1; - } - - ttb = armv7a->armv7a_mmu.ttbr[ttbidx]; - 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; -} - -/* 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"); - break; - default: - LOG_INFO("inner: %" PRIx32 " ???", INNER); - } - } - -done: - dpm->finish(dpm); - - return retval; -} - /* FIXME: remove it */ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) { struct armv7a_l2x_cache *l2x_cache; - struct target_list *head = target->head; - struct target *curr; + struct target_list *head; struct armv7a_common *armv7a = target_to_armv7a(target); l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache)); @@ -374,15 +196,14 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; /* initialize all target in this cluster (smp target) * l2 cache must be configured after smp declaration */ - while (head != (struct target_list *)NULL) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) LOG_ERROR("smp target : outer cache already initialized\n"); armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; } - head = head->next; } return JIM_OK; } @@ -396,7 +217,7 @@ COMMAND_HANDLER(handle_cache_l2x) if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */ + /* command_print(CMD, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way); @@ -406,7 +227,7 @@ COMMAND_HANDLER(handle_cache_l2x) return ERROR_OK; } -int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, +int armv7a_handle_cache_info_command(struct command_invocation *cmd, struct armv7a_cache_common *armv7a_cache) { struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) @@ -415,7 +236,7 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, int cl; if (armv7a_cache->info == -1) { - command_print(cmd_ctx, "cache not yet identified"); + command_print(cmd, "cache not yet identified"); return ERROR_OK; } @@ -423,11 +244,11 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, 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", + command_print(cmd, + "L%d I-Cache: linelen %" PRIu32 + ", associativity %" PRIu32 + ", nsets %" PRIu32 + ", cachesize %" PRIu32 " KBytes", cl+1, arch->i_size.linelen, arch->i_size.associativity, @@ -436,11 +257,11 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, } if (arch->ctype >= 2) { - command_print(cmd_ctx, - "L%d D-Cache: linelen %" PRIi32 - ", associativity %" PRIi32 - ", nsets %" PRIi32 - ", cachesize %" PRId32 " KBytes", + command_print(cmd, + "L%d D-Cache: linelen %" PRIu32 + ", associativity %" PRIu32 + ", nsets %" PRIu32 + ", cachesize %" PRIu32 " KBytes", cl+1, arch->d_u_size.linelen, arch->d_u_size.associativity, @@ -449,8 +270,8 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, } } - if (l2x_cache != NULL) - command_print(cmd_ctx, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways", + if (l2x_cache) + command_print(cmd, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRIu32 " ways", l2x_cache->base, l2x_cache->way); return ERROR_OK; @@ -474,23 +295,21 @@ static int armv7a_read_mpidr(struct target *target) if (retval != ERROR_OK) goto done; - /* ARMv7R uses a different format for MPIDR. - * When configured uniprocessor (most R cores) it reads as 0. - * This will need to be implemented for multiprocessor ARMv7R cores. */ - if (armv7a->is_armv7r) { - if (mpidr) - LOG_ERROR("MPIDR nonzero in ARMv7-R target"); - goto done; - } - - if (mpidr & 1<<31) { + /* Is register in Multiprocessing Extensions register format? */ + if (mpidr & MPIDR_MP_EXT) { + LOG_DEBUG("%s: MPIDR 0x%" PRIx32, target_name(target), mpidr); armv7a->multi_processor_system = (mpidr >> 30) & 1; + armv7a->multi_threading_processor = (mpidr >> 24) & 1; + armv7a->level2_id = (mpidr >> 16) & 0xf; armv7a->cluster_id = (mpidr >> 8) & 0xf; - armv7a->cpu_id = mpidr & 0x3; - LOG_INFO("%s cluster %x core %x %s", target_name(target), + armv7a->cpu_id = mpidr & 0xf; + LOG_INFO("%s: MPIDR level2 %x, cluster %x, core %x, %s, %s", + target_name(target), + armv7a->level2_id, armv7a->cluster_id, armv7a->cpu_id, - armv7a->multi_processor_system == 0 ? "multi core" : "mono core"); + armv7a->multi_processor_system == 0 ? "multi core" : "mono core", + armv7a->multi_threading_processor == 1 ? "SMT" : "no SMT"); } else LOG_ERROR("MPIDR not in multiprocessor format"); @@ -554,9 +373,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; @@ -571,7 +387,7 @@ int armv7a_identify_cache(struct target *target) cache->iminline = 4UL << (ctr & 0xf); cache->dminline = 4UL << ((ctr & 0xf0000) >> 16); - LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRId32 " ctr.dminline %" PRId32, + LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRIu32 " ctr.dminline %" PRIu32, ctr, cache->iminline, cache->dminline); /* retrieve CLIDR @@ -611,13 +427,13 @@ int armv7a_identify_cache(struct target *target) goto done; cache->arch[cl].d_u_size = decode_cache_reg(cache_reg); - LOG_DEBUG("data/unified cache index %d << %d, way %d << %d", + LOG_DEBUG("data/unified cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, cache->arch[cl].d_u_size.index, cache->arch[cl].d_u_size.index_shift, cache->arch[cl].d_u_size.way, cache->arch[cl].d_u_size.way_shift); - LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways", + LOG_DEBUG("cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", cache->arch[cl].d_u_size.linelen, cache->arch[cl].d_u_size.cachesize, cache->arch[cl].d_u_size.associativity); @@ -631,13 +447,13 @@ int armv7a_identify_cache(struct target *target) goto done; cache->arch[cl].i_size = decode_cache_reg(cache_reg); - LOG_DEBUG("instruction cache index %d << %d, way %d << %d", + LOG_DEBUG("instruction cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, cache->arch[cl].i_size.index, cache->arch[cl].i_size.index_shift, cache->arch[cl].i_size.way, cache->arch[cl].i_size.way_shift); - LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways", + LOG_DEBUG("cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", cache->arch[cl].i_size.linelen, cache->arch[cl].i_size.cachesize, cache->arch[cl].i_size.associativity); @@ -655,7 +471,7 @@ int armv7a_identify_cache(struct target *target) goto done; /* if no l2 cache initialize l1 data cache flush function function */ - if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) { + if (!armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache) { armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = armv7a_cache_auto_flush_all_data; } @@ -729,8 +545,6 @@ int armv7a_arch_state(struct target *target) arm_arch_state(target); - armv7a_read_ttbcr(target); - if (armv7a->is_armv7r) { LOG_USER("D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], @@ -744,9 +558,6 @@ int armv7a_arch_state(struct target *target) if (arm->core_mode == ARM_MODE_ABT) armv7a_show_fault_registers(target); - if (target->debug_reason == DBG_REASON_WATCHPOINT) - LOG_USER("Watchpoint triggered at PC %#08x", - (unsigned) armv7a->dpm.wp_pc); return ERROR_OK; } @@ -756,15 +567,14 @@ 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 }; -const struct command_registration l2x_cache_command_handlers[] = { +static const struct command_registration l2x_cache_command_handlers[] = { { .name = "cache_config", .mode = COMMAND_EXEC,