DDR has been set as secure in MMU tables. Non-secure master such as SDHC DMA cannot access data correctly. Mixing secure and non- secure MMU entries requirs the MMU tables themselves in secure memory. This patch moves MMU tables into a secure DDR area reserved for TrustZone with size CONFIG_FSL_PPA_RESERVED_DRAM_SIZE.
Early MMU tables are changed to set DDR as non-secure. Before setting final MMU tables in secure DDR, existing MMU needs to be updated with a secure DDR entry. A new table is added into final MMU tables so secure memory can have 2MB granuality. A new global data variable secure_ram is introduced to host the address of secure memory. "bdinfo" command shows its value. Signed-off-by: York Sun <york...@freescale.com> --- Changes in v1: None arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 126 ++++++++++++++++++++++-- arch/arm/include/asm/arch-fsl-layerscape/cpu.h | 12 ++- arch/arm/include/asm/global_data.h | 3 + board/freescale/ls2085a/ddr.c | 10 ++ board/freescale/ls2085aqds/ddr.c | 10 ++ board/freescale/ls2085ardb/ddr.c | 10 ++ common/cmd_bdinfo.c | 4 + 7 files changed, 162 insertions(+), 13 deletions(-) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 690c263..5ce6f8f 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -207,10 +207,86 @@ static inline void early_mmu_setup(void) } /* + * Called from early mmu setup. The phys_addr needs to be in + * the table and aligned. This function sets the block to secure. + */ +static inline int fixup_early_secure_ddr(u64 *level0_table, + phys_addr_t phys_addr) +{ + int ret = 0; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + struct table_info table = {}; + struct sys_mmu_table ddr_entry = { + 0, 0, BLOCK_SIZE_L1, MT_NORMAL, PMD_SECT_OUTER_SHARE + }; + + ddr_entry.virt_addr = phys_addr; + ddr_entry.phys_addr = phys_addr; + ret = find_table(&ddr_entry, &table, level0_table); + if (!ret) + ret = set_block_entry(&ddr_entry, &table); +#endif + + return ret; +} +/* + * Called from final mmu setup. The phys_addr is new, non-existing + * address. A new sub table is created @level2_table_secure. + */ +static inline int final_secure_ddr(u64 *level0_table, + u64 *level2_table_secure, + phys_addr_t phys_addr) +{ + int ret = 0; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + struct table_info table = {}; + struct sys_mmu_table ddr_entry = { + 0, 0, BLOCK_SIZE_L1, MT_NORMAL, + PMD_SECT_OUTER_SHARE | PMD_SECT_NS + }; + u64 index; + + /* Need to create a new table */ + ddr_entry.virt_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1); + ddr_entry.phys_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1); + ret = find_table(&ddr_entry, &table, level0_table); + if (ret) + return ret; + index = (ddr_entry.virt_addr - table.table_base) >> SECTION_SHIFT_L1; + set_pgtable_table(table.ptr, index, level2_table_secure); + table.ptr = level2_table_secure; + table.table_base = ddr_entry.virt_addr; + table.entry_size = BLOCK_SIZE_L2; + ret = set_block_entry(&ddr_entry, &table); + if (ret) { + printf("MMU error: could not fill non-secure ddr block entries\n"); + return ret; + } + ddr_entry.virt_addr = phys_addr; + ddr_entry.phys_addr = phys_addr; + ddr_entry.size = CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; + ddr_entry.attribute = PMD_SECT_OUTER_SHARE; + ret = find_table(&ddr_entry, &table, level0_table); + if (ret) { + printf("MMU error: could not find secure ddr table\n"); + return ret; + } + ret = set_block_entry(&ddr_entry, &table); + if (ret) + printf("MMU error: could not set secure ddr block entry\n"); +#endif + + return ret; +} + +/* * The final tables look similar to early tables, but different in detail. * These tables are in DRAM. Sub tables are added to enable cache for * QBMan and OCRAM. * + * Put the MMU table in secure memory if gd->arch.secure_ram is set. + * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0. + * * Level 1 table 0 contains 512 entries for each 1GB from 0 to 512GB. * Level 1 table 1 contains 512 entries for each 1GB from 512GB to 1TB. * Level 2 table 0 contains 512 entries for each 2MB from 0 to 1GB. @@ -224,17 +300,35 @@ static inline void early_mmu_setup(void) static inline void final_mmu_setup(void) { unsigned int el, i; - u64 *level0_table = (u64 *)gd->arch.tlb_addr; - u64 *level1_table0 = (u64 *)(gd->arch.tlb_addr + 0x1000); - u64 *level1_table1 = (u64 *)(gd->arch.tlb_addr + 0x2000); - u64 *level2_table0 = (u64 *)(gd->arch.tlb_addr + 0x3000); -#ifdef CONFIG_FSL_LSCH3 - u64 *level2_table1 = (u64 *)(gd->arch.tlb_addr + 0x4000); -#elif defined(CONFIG_FSL_LSCH2) - u64 *level2_table1 = (u64 *)(gd->arch.tlb_addr + 0x4000); - u64 *level2_table2 = (u64 *)(gd->arch.tlb_addr + 0x5000); + u64 *level0_table = gd->arch.secure_ram ? (u64 *)gd->arch.secure_ram + : (u64 *)gd->arch.tlb_addr; + u64 *level1_table0 = level0_table + 512; + u64 *level1_table1 = level1_table0 + 512; + u64 *level2_table0 = level1_table1 + 512; + u64 *level2_table1 = level2_table0 + 512; +#ifdef CONFIG_FSL_LSCH2 + u64 *level2_table2 = level2_table1 + 512; #endif + u64 *level2_table_secure; struct table_info table = {level0_table, 0, BLOCK_SIZE_L0}; + u64 secure_ram = gd->arch.secure_ram & ~(BLOCK_SIZE_L1 - 1); + + /* + * Modify the early MMU table to create a secure memory + * to host the table + */ + if (!fixup_early_secure_ddr((u64 *)CONFIG_SYS_FSL_OCRAM_BASE, + secure_ram)) { + flush_dcache_range(CONFIG_SYS_FSL_OCRAM_BASE, + CONFIG_SYS_FSL_OCRAM_BASE + 0x5000); + asm volatile( + "tlbi vae3, %0\n" + "dsb sy\n" + "isb" + : : "r" (secure_ram) : "memory"); + } else { + printf("MMU error: Failed to create early MMU secure DDR\n"); + } /* Invalidate all table entries */ memset(level0_table, 0, PGTABLE_SIZE); @@ -269,6 +363,20 @@ static inline void final_mmu_setup(void) &final_mmu_table[i]); } } + /* Set the PPA memory to secure */ + if (gd->arch.secure_ram) { +#ifdef CONFIG_FSL_LSCH3 + level2_table_secure = level2_table1 + 512; +#elif defined(CONFIG_FSL_LSCH2) + level2_table_secure = level2_table2 + 512; +#endif + /* update tlb pointer */ + gd->arch.tlb_addr = gd->arch.secure_ram; + if (!final_secure_ddr(level0_table, + level2_table_secure, + gd->arch.secure_ram)) + gd->arch.secure_ram |= 1; /* set the valid flag */ + } /* flush new MMU table */ flush_dcache_range(gd->arch.tlb_addr, diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h index b4b85a8..a13a3d3 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h @@ -129,12 +129,14 @@ static const struct sys_mmu_table early_mmu_table[] = { { CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_SIZE1, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE }, { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, - CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, PMD_SECT_OUTER_SHARE }, + CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, + PMD_SECT_OUTER_SHARE | PMD_SECT_NS}, { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN }, { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, - CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PMD_SECT_OUTER_SHARE }, + CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, + PMD_SECT_OUTER_SHARE | PMD_SECT_NS }, #elif defined(CONFIG_FSL_LSCH2) { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE, @@ -161,7 +163,8 @@ static const struct sys_mmu_table final_mmu_table[] = { { CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PMD_SECT_NON_SHARE }, { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, - CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, PMD_SECT_OUTER_SHARE }, + CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, + PMD_SECT_OUTER_SHARE | PMD_SECT_NS }, { CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_SIZE2, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN }, @@ -208,7 +211,8 @@ static const struct sys_mmu_table final_mmu_table[] = { CONFIG_SYS_FSL_PEBUF_SIZE, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN }, { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, - CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PMD_SECT_OUTER_SHARE }, + CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, + PMD_SECT_OUTER_SHARE | PMD_SECT_NS }, #elif defined(CONFIG_FSL_LSCH2) { CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_SIZE, MT_DEVICE_NGNRNE, diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 4e3ea55..d0c7fc4 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -49,6 +49,9 @@ struct arch_global_data { #ifdef CONFIG_FSL_LSCH3 unsigned long mem2_clk; #endif +#ifdef CONFIG_FSL_LAYERSCAPE + phys_addr_t secure_ram; /* lsb is a valid flag */ +#endif }; #include <asm-generic/global_data.h> diff --git a/board/freescale/ls2085a/ddr.c b/board/freescale/ls2085a/ddr.c index 4884fa2..b7c939b 100644 --- a/board/freescale/ls2085a/ddr.c +++ b/board/freescale/ls2085a/ddr.c @@ -180,8 +180,18 @@ void dram_init_banksize(void) gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; gd->bd->bi_dram[1].size = gd->ram_size - CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } else { gd->bd->bi_dram[0].size = gd->ram_size; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } #ifdef CONFIG_SYS_DP_DDR_BASE_PHY diff --git a/board/freescale/ls2085aqds/ddr.c b/board/freescale/ls2085aqds/ddr.c index 8d71ae1..f24ef12 100644 --- a/board/freescale/ls2085aqds/ddr.c +++ b/board/freescale/ls2085aqds/ddr.c @@ -170,8 +170,18 @@ void dram_init_banksize(void) gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; gd->bd->bi_dram[1].size = gd->ram_size - CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } else { gd->bd->bi_dram[0].size = gd->ram_size; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } #ifdef CONFIG_SYS_DP_DDR_BASE_PHY diff --git a/board/freescale/ls2085ardb/ddr.c b/board/freescale/ls2085ardb/ddr.c index 8d71ae1..f24ef12 100644 --- a/board/freescale/ls2085ardb/ddr.c +++ b/board/freescale/ls2085ardb/ddr.c @@ -170,8 +170,18 @@ void dram_init_banksize(void) gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; gd->bd->bi_dram[1].size = gd->ram_size - CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } else { gd->bd->bi_dram[0].size = gd->ram_size; +#ifdef CONFIG_FSL_PPA_RESERVED_DRAM_SIZE + gd->arch.secure_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + CONFIG_FSL_PPA_RESERVED_DRAM_SIZE; +#endif } #ifdef CONFIG_SYS_DP_DDR_BASE_PHY diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index ed3b935..408d020 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -377,6 +377,10 @@ static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, print_num("-> size", bd->bi_dram[i].size); } +#ifdef CONFIG_FSL_LAYERSCAPE + if (gd->arch.secure_ram & 0x1) + print_num("Secure ram", gd->arch.secure_ram & ~1); +#endif #if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH) print_eths(); #endif -- 1.7.9.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot