summaryrefslogtreecommitdiff
path: root/arch/arm/mach-stm32mp/cpu.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-06-07 19:12:04 -0400
committerTom Rini <trini@konsulko.com>2021-06-07 19:12:04 -0400
commit24e1e8841c59956aaf0bd65720d0dbdd61aa3632 (patch)
tree09d104dbed9bf79b7e4d05a799e18cc9485836ff /arch/arm/mach-stm32mp/cpu.c
parente3b64beda5dd1a6b6bedfd1fe0e50be1ddea7044 (diff)
parentade4e0428f4d85454fdb3818702facc7728a274a (diff)
Merge branch '2021-06-07-arm-cache-cp15-improvements' into next
To quote the series author, Patrick Delaunay: On STM32MP15x platform we can use OP-TEE, loaded in DDR in a region protected by a firewall. This region is reserved in the device with the "no-map" property as defined in the binding file doc/device-tree-bindings/reserved-memory/reserved-memory.txt. Sometime the platform boot failed in U-Boot on a Cortex A7 access to this region (depending of the binary and the issue can change with compiler version or with code alignment), then the firewall raise an error, for example: E/TC:0 tzc_it_handler:19 TZC permission failure E/TC:0 dump_fail_filter:420 Permission violation on filter 0 E/TC:0 dump_fail_filter:425 Violation @0xde5c6bf0, non-secure privileged read, AXI ID 5c0 E/TC:0 Panic After investigation, the forbidden access is a speculative request performed by the Cortex A7 because all the DDR is mapped as MEMORY with CACHEABLE property. The issue is solved only when the region reserved by OP-TEE is no more mapped in U-Boot as it is already done in Linux kernel. Tested on DK2 board with OP-TEE 3.12 / TF-A 2.4: With hard-coded address for OP-TEE reserved memory, the error doesn't occur. void dram_bank_mmu_setup(int bank) { .... for (i = start >> MMU_SECTION_SHIFT; i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT); i++) { option = DCACHE_DEFAULT_OPTION; if (i >= 0xde0) option = INVALID_ENTRY; set_section_dcache(i, option); } } Just by modifying the test on 0xde0 to 0xdf0, the OP-TEE memory protected by firewall is mapped cacheable and the error occurs. I think that it can be a general issue for ARM architecture: the "no-map" tag of reserved memory in device should be respected by U-Boot if firewall is configured before U-Boot execution. But I don't propose a generic solution in arm/lib/cache-cp15.c:dram_bank_mmu_setup() because the device tree parsing done in lmb_init_and_reserve() takes a long time when it is executed without data cache.
Diffstat (limited to 'arch/arm/mach-stm32mp/cpu.c')
-rw-r--r--arch/arm/mach-stm32mp/cpu.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index 8115d58b199..592bfd413df 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -12,6 +12,7 @@
#include <env.h>
#include <init.h>
#include <log.h>
+#include <lmb.h>
#include <misc.h>
#include <net.h>
#include <asm/io.h>
@@ -90,6 +91,8 @@
*/
u8 early_tlb[PGTABLE_SIZE] __section(".data") __aligned(0x4000);
+struct lmb lmb;
+
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_TFABOOT
static void security_init(void)
@@ -221,6 +224,8 @@ void dram_bank_mmu_setup(int bank)
int i;
phys_addr_t start;
phys_size_t size;
+ bool use_lmb = false;
+ enum dcache_option option;
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
start = ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE);
@@ -229,6 +234,7 @@ void dram_bank_mmu_setup(int bank)
/* bd->bi_dram is available only after relocation */
start = bd->bi_dram[bank].start;
size = bd->bi_dram[bank].size;
+ use_lmb = true;
} else {
/* mark cacheable and executable the beggining of the DDR */
start = STM32_DDR_BASE;
@@ -237,8 +243,12 @@ void dram_bank_mmu_setup(int bank)
for (i = start >> MMU_SECTION_SHIFT;
i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT);
- i++)
- set_section_dcache(i, DCACHE_DEFAULT_OPTION);
+ i++) {
+ option = DCACHE_DEFAULT_OPTION;
+ if (use_lmb && lmb_is_reserved_flags(&lmb, i << MMU_SECTION_SHIFT, LMB_NOMAP))
+ option = 0; /* INVALID ENTRY in TLB */
+ set_section_dcache(i, option);
+ }
}
/*
* initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage
@@ -302,6 +312,9 @@ int arch_cpu_init(void)
void enable_caches(void)
{
+ /* parse device tree when data cache is still activated */
+ lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
+
/* I-cache is already enabled in start.S: icache_enable() not needed */
/* deactivate the data cache, early enabled in arch_cpu_init() */