[U-Boot] [RFC PATCH v1 2/2] armv8: fsl-layerscape: Make DDR non secure in MMU tables
York Sun
yorksun at freescale.com
Tue Nov 10 20:17:11 CET 2015
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 <yorksun at 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
More information about the U-Boot
mailing list