diff mbox series

[v2,4/5] stm32mp1: spl: Configure TrustZone controller for OP-TEE

Message ID 20210315154715.2258433-5-mr.nuke.me@gmail.com
State Superseded
Delegated to: Patrice Chotard
Headers show
Series stm32mp: Enable OP-TEE and TZC support in SPL | expand

Commit Message

Alexandru Gagniuc March 15, 2021, 3:47 p.m. UTC
OP-TEE is very particular about how the TZC should be configured.
When booting an OP-TEE payload, an incorrect TZC configuration will
result in a panic.

Most information can be derived from the SPL devicetree. The only
information we don't have is the split between TZDRAM and shared
memory. This has to be hardcoded. The rest of the configuration is
fairly easy, and only requires 3 TZC regions. Configure them.

Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
---
 arch/arm/mach-stm32mp/spl.c | 84 +++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

Comments

Patrick Delaunay April 7, 2021, 8:48 a.m. UTC | #1
Hi,

On 3/15/21 4:47 PM, Alexandru Gagniuc wrote:
> OP-TEE is very particular about how the TZC should be configured.
> When booting an OP-TEE payload, an incorrect TZC configuration will
> result in a panic.
>
> Most information can be derived from the SPL devicetree. The only
> information we don't have is the split between TZDRAM and shared
> memory. This has to be hardcoded. The rest of the configuration is
> fairly easy, and only requires 3 TZC regions. Configure them.
>
> Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
> ---
>   arch/arm/mach-stm32mp/spl.c | 84 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 84 insertions(+)
>
> diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
> index b53659a698..64882c67e3 100644
> --- a/arch/arm/mach-stm32mp/spl.c
> +++ b/arch/arm/mach-stm32mp/spl.c
> @@ -16,6 +16,7 @@
>   #include <asm/global_data.h>
>   #include <asm/io.h>
>   #include <asm/arch/sys_proto.h>
> +#include <mach/tzc.h>
>   #include <linux/libfdt.h>
>   
>   u32 spl_boot_device(void)
> @@ -92,6 +93,89 @@ __weak int board_early_init_f(void)
>   	return 0;
>   }
>   
> +uint32_t stm32mp_get_dram_size(void)
> +{
> +	uint32_t ram_size = 0;
> +	struct udevice *dev;
> +	ofnode node;
> +
> +	if (uclass_get_device(UCLASS_RAM, 0, &dev))
> +		return 0;
> +
> +	dev_for_each_subnode(node, dev) {
> +		ram_size = ofnode_read_u32_default(node, "st,mem-size", 0);
> +		if (ram_size)
> +			break;
> +	}
> +
> +	return ram_size;
> +}

no need to parse the device tree here, information is available in uclas API

see dram_init() in dram_init.c


uint32_t stm32mp_get_dram_size(void)
{

     struct ram_info ram;

    if (uclass_get_device(UCLASS_RAM, 0, &dev))
	return 0;

     ret = ram_get_info(dev, &ram);

     if (ret)

         return 0;

     return ram.size;
}


> +uint32_t optee_get_reserved_memory_base(void)
> +{
> +	ofnode node;
> +	fdt_addr_t start;
> +
> +	node = ofnode_path("/reserved-memory/optee");
> +	if (!ofnode_valid(node))
> +		return 0;
> +
> +	start = ofnode_get_addr(node);
> +	return (start < 0) ? 0 : (uintptr_t)start;
> +}
> +
> +#define CFG_TZDRAM_SIZE		0x01e00000

=> TEE reserved size should be get from device

     reserved-memory {
         optee@de000000 {
             reg = <0xde000000 0x02000000>;
             no-map;
         };
     };

     start = ofnode_get_addr_size(node, "reg", &size)

Then only the size of the shared memory is hardcoded

#define CFG_SHMEM_SIZE 		0x200000


> +#define STM32_TZC_NSID_ALL		0xffff
> +#define STM32_TZC_FILTER_ALL		3
> +
> +void stm32_init_tzc_for_optee(void)
> +{
> +	const uint32_t dram_size = stm32mp_get_dram_size();
> +	const uintptr_t dram_top = STM32_DDR_BASE + (dram_size - 1);
> +	uint32_t optee_base = optee_get_reserved_memory_base();
> +	uint32_t tee_shmem_base = optee_base + CFG_TZDRAM_SIZE;


uint32_t tee_shmem_base = optee_base + optee_size + CFG_SHMEM_SIZE;

> +	const uintptr_t tzc = STM32_TZC_BASE;
> +
> +	if (dram_size == 0)
> +		panic("Cannot determine DRAM size from devicetree\n");
> +
> +	const struct tzc_region optee_config[] = {
> +		{
> +			.base = STM32_DDR_BASE,
> +			.top = optee_base - 1,
> +			.sec_mode = TZC_ATTR_SEC_NONE,
> +			.nsec_id = STM32_TZC_NSID_ALL,
> +			.filters_mask = STM32_TZC_FILTER_ALL,
> +		}, {
> +			.base = optee_base,
> +			.top = tee_shmem_base - 1,
> +			.sec_mode = TZC_ATTR_SEC_RW,
> +			.nsec_id = 0,
> +			.filters_mask = STM32_TZC_FILTER_ALL,
> +		}, {
> +			.base = tee_shmem_base,
> +			.top = dram_top,
> +			.sec_mode = TZC_ATTR_SEC_NONE,
> +			.nsec_id = STM32_TZC_NSID_ALL,
> +			.filters_mask = STM32_TZC_FILTER_ALL,
> +		}, {
> +			.top = 0,
> +		}
> +	};
> +
> +	flush_dcache_all();
> +
> +	tzc_configure(tzc, optee_config);
> +	tzc_dump_config(tzc);
> +
> +	dcache_disable();
> +}
> +
> +void spl_board_prepare_for_optee(void *fdt)
> +{
> +	stm32_init_tzc_for_optee();
> +}
> +
>   void board_init_f(ulong dummy)
>   {
>   	struct udevice *dev;


Regards,

Patrick
diff mbox series

Patch

diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
index b53659a698..64882c67e3 100644
--- a/arch/arm/mach-stm32mp/spl.c
+++ b/arch/arm/mach-stm32mp/spl.c
@@ -16,6 +16,7 @@ 
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/arch/sys_proto.h>
+#include <mach/tzc.h>
 #include <linux/libfdt.h>
 
 u32 spl_boot_device(void)
@@ -92,6 +93,89 @@  __weak int board_early_init_f(void)
 	return 0;
 }
 
+uint32_t stm32mp_get_dram_size(void)
+{
+	uint32_t ram_size = 0;
+	struct udevice *dev;
+	ofnode node;
+
+	if (uclass_get_device(UCLASS_RAM, 0, &dev))
+		return 0;
+
+	dev_for_each_subnode(node, dev) {
+		ram_size = ofnode_read_u32_default(node, "st,mem-size", 0);
+		if (ram_size)
+			break;
+	}
+
+	return ram_size;
+}
+
+uint32_t optee_get_reserved_memory_base(void)
+{
+	ofnode node;
+	fdt_addr_t start;
+
+	node = ofnode_path("/reserved-memory/optee");
+	if (!ofnode_valid(node))
+		return 0;
+
+	start = ofnode_get_addr(node);
+	return (start < 0) ? 0 : (uintptr_t)start;
+}
+
+#define CFG_TZDRAM_SIZE		0x01e00000
+#define STM32_TZC_NSID_ALL		0xffff
+#define STM32_TZC_FILTER_ALL		3
+
+void stm32_init_tzc_for_optee(void)
+{
+	const uint32_t dram_size = stm32mp_get_dram_size();
+	const uintptr_t dram_top = STM32_DDR_BASE + (dram_size - 1);
+	uint32_t optee_base = optee_get_reserved_memory_base();
+	uint32_t tee_shmem_base = optee_base + CFG_TZDRAM_SIZE;
+	const uintptr_t tzc = STM32_TZC_BASE;
+
+	if (dram_size == 0)
+		panic("Cannot determine DRAM size from devicetree\n");
+
+	const struct tzc_region optee_config[] = {
+		{
+			.base = STM32_DDR_BASE,
+			.top = optee_base - 1,
+			.sec_mode = TZC_ATTR_SEC_NONE,
+			.nsec_id = STM32_TZC_NSID_ALL,
+			.filters_mask = STM32_TZC_FILTER_ALL,
+		}, {
+			.base = optee_base,
+			.top = tee_shmem_base - 1,
+			.sec_mode = TZC_ATTR_SEC_RW,
+			.nsec_id = 0,
+			.filters_mask = STM32_TZC_FILTER_ALL,
+		}, {
+			.base = tee_shmem_base,
+			.top = dram_top,
+			.sec_mode = TZC_ATTR_SEC_NONE,
+			.nsec_id = STM32_TZC_NSID_ALL,
+			.filters_mask = STM32_TZC_FILTER_ALL,
+		}, {
+			.top = 0,
+		}
+	};
+
+	flush_dcache_all();
+
+	tzc_configure(tzc, optee_config);
+	tzc_dump_config(tzc);
+
+	dcache_disable();
+}
+
+void spl_board_prepare_for_optee(void *fdt)
+{
+	stm32_init_tzc_for_optee();
+}
+
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;