xref: /rk3399_ARM-atf/services/std_svc/spm/el3_spmc/spmc_setup.c (revision 80684b7e9e9ed4574bc64948740b99cb31d1e10a)
15096aeb2SMarc Bonnici /*
2aae2370cSYeoreum Yun  * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
35096aeb2SMarc Bonnici  *
45096aeb2SMarc Bonnici  * SPDX-License-Identifier: BSD-3-Clause
55096aeb2SMarc Bonnici  */
65096aeb2SMarc Bonnici 
75096aeb2SMarc Bonnici #include <assert.h>
84053a647SLevi Yun #include <errno.h>
95096aeb2SMarc Bonnici #include <string.h>
105096aeb2SMarc Bonnici 
115096aeb2SMarc Bonnici #include <arch.h>
125096aeb2SMarc Bonnici #include <arch_helpers.h>
135096aeb2SMarc Bonnici #include <common/debug.h>
142e219215SAchin Gupta #include <common/fdt_wrappers.h>
154053a647SLevi Yun 
165096aeb2SMarc Bonnici #include <context.h>
175096aeb2SMarc Bonnici #include <lib/el3_runtime/context_mgmt.h>
184053a647SLevi Yun #if HOB_LIST
194053a647SLevi Yun #include <lib/hob/hob.h>
204053a647SLevi Yun #include <lib/hob/hob_guid.h>
214053a647SLevi Yun #include <lib/hob/mmram.h>
224053a647SLevi Yun #include <lib/hob/mpinfo.h>
234053a647SLevi Yun #endif
245096aeb2SMarc Bonnici #include <lib/utils.h>
255096aeb2SMarc Bonnici #include <lib/xlat_tables/xlat_tables_v2.h>
262e219215SAchin Gupta #include <libfdt.h>
275096aeb2SMarc Bonnici #include <plat/common/common_def.h>
285096aeb2SMarc Bonnici #include <plat/common/platform.h>
295096aeb2SMarc Bonnici #include <services/ffa_svc.h>
305096aeb2SMarc Bonnici #include "spm_common.h"
3148db2b01SNishant Sharma #include "spm_shim_private.h"
325096aeb2SMarc Bonnici #include "spmc.h"
33aae2370cSYeoreum Yun #if TRANSFER_LIST
34aae2370cSYeoreum Yun #include <transfer_list.h>
35*982e702eSHarrison Mutai #include <tpm_event_log.h>
36aae2370cSYeoreum Yun #endif
372e219215SAchin Gupta #include <tools_share/firmware_image_package.h>
385096aeb2SMarc Bonnici 
395096aeb2SMarc Bonnici #include <platform_def.h>
405096aeb2SMarc Bonnici 
414e5247c1SYeoreum Yun #define FFA_BOOT_INFO_SIZE	(PAGE_SIZE * 2)
424e5247c1SYeoreum Yun 
435096aeb2SMarc Bonnici /*
442e219215SAchin Gupta  * Statically allocate a page of memory for passing boot information to an SP.
452e219215SAchin Gupta  */
464e5247c1SYeoreum Yun static uint8_t ffa_boot_info_mem[FFA_BOOT_INFO_SIZE] __aligned(PAGE_SIZE);
474e5247c1SYeoreum Yun 
484e5247c1SYeoreum Yun #if HOB_LIST
494e5247c1SYeoreum Yun static void *tpm_evtlog_addr;
504e5247c1SYeoreum Yun static size_t tpm_evtlog_size;
514e5247c1SYeoreum Yun #endif
522e219215SAchin Gupta 
532e219215SAchin Gupta /*
5448db2b01SNishant Sharma  * We need to choose one execution context from all those available for a S-EL0
5548db2b01SNishant Sharma  * SP. This execution context will be used subsequently irrespective of which
5648db2b01SNishant Sharma  * physical CPU the SP runs on.
5748db2b01SNishant Sharma  */
5848db2b01SNishant Sharma #define SEL0_SP_EC_INDEX 0
5983c3da77SNishant Sharma #define SP_MEM_READ 0x1
6083c3da77SNishant Sharma #define SP_MEM_WRITE 0x2
6183c3da77SNishant Sharma #define SP_MEM_EXECUTE 0x4
6283c3da77SNishant Sharma #define SP_MEM_NON_SECURE 0x8
6383c3da77SNishant Sharma #define SP_MEM_READ_ONLY SP_MEM_READ
6483c3da77SNishant Sharma #define SP_MEM_READ_WRITE (SP_MEM_READ | SP_MEM_WRITE)
6548db2b01SNishant Sharma 
66727ab1c4SNishant Sharma /* Type of the memory region in SP's manifest. */
67727ab1c4SNishant Sharma enum sp_memory_region_type {
68727ab1c4SNishant Sharma 	SP_MEM_REGION_DEVICE,
69727ab1c4SNishant Sharma 	SP_MEM_REGION_MEMORY,
70727ab1c4SNishant Sharma 	SP_MEM_REGION_NOT_SPECIFIED
71727ab1c4SNishant Sharma };
72727ab1c4SNishant Sharma 
734053a647SLevi Yun #if HOB_LIST
744e5247c1SYeoreum Yun #if TRANSFER_LIST
get_tpm_event_log(void * secure_tl)754e5247c1SYeoreum Yun static void get_tpm_event_log(void *secure_tl)
764e5247c1SYeoreum Yun {
774e5247c1SYeoreum Yun 	struct transfer_list_entry *te;
784e5247c1SYeoreum Yun 	void *evlog;
794e5247c1SYeoreum Yun 
804e5247c1SYeoreum Yun 	if (secure_tl == NULL) {
814e5247c1SYeoreum Yun 		tpm_evtlog_addr = NULL;
824e5247c1SYeoreum Yun 		tpm_evtlog_size = 0;
834e5247c1SYeoreum Yun 		return;
844e5247c1SYeoreum Yun 	}
854e5247c1SYeoreum Yun 
864e5247c1SYeoreum Yun 	te = transfer_list_find((struct transfer_list_header *)secure_tl,
874e5247c1SYeoreum Yun 				TL_TAG_TPM_EVLOG);
884e5247c1SYeoreum Yun 	if (te == NULL) {
894e5247c1SYeoreum Yun 		tpm_evtlog_addr = NULL;
904e5247c1SYeoreum Yun 		tpm_evtlog_size = 0;
914e5247c1SYeoreum Yun 		return;
924e5247c1SYeoreum Yun 	}
934e5247c1SYeoreum Yun 
944e5247c1SYeoreum Yun 	evlog = transfer_list_entry_data(te);
954e5247c1SYeoreum Yun 	assert(evlog != NULL);
964e5247c1SYeoreum Yun 
974e5247c1SYeoreum Yun 	tpm_evtlog_addr = evlog + EVENT_LOG_RESERVED_BYTES;
984e5247c1SYeoreum Yun 	tpm_evtlog_size = te->data_size - EVENT_LOG_RESERVED_BYTES;
994e5247c1SYeoreum Yun }
1004e5247c1SYeoreum Yun #else
get_tpm_event_log(void * secure_tl)1014e5247c1SYeoreum Yun static void get_tpm_event_log(void *secure_tl)
1024e5247c1SYeoreum Yun {
1034e5247c1SYeoreum Yun 	tpm_evtlog_addr = NULL;
1044e5247c1SYeoreum Yun 	tpm_evtlog_size = 0;
1054e5247c1SYeoreum Yun }
1064e5247c1SYeoreum Yun #endif
1074e5247c1SYeoreum Yun 
get_memory_region_info(void * sp_manifest,int mem_region_node,const char * name,uint32_t granularity,uint64_t * base_address,uint32_t * size)1084053a647SLevi Yun static int get_memory_region_info(void *sp_manifest, int mem_region_node,
1094053a647SLevi Yun 		const char *name, uint32_t granularity,
1104053a647SLevi Yun 		uint64_t *base_address, uint32_t *size)
1114053a647SLevi Yun {
1124053a647SLevi Yun 	char *property;
1134053a647SLevi Yun 	int node, ret;
1144053a647SLevi Yun 
1154053a647SLevi Yun 	if (name != NULL) {
1164053a647SLevi Yun 		node = fdt_subnode_offset_namelen(sp_manifest, mem_region_node,
1174053a647SLevi Yun 				name, strlen(name));
1184053a647SLevi Yun 		if (node < 0) {
1194053a647SLevi Yun 			ERROR("Not found '%s' region in memory regions configuration for SP.\n",
1204053a647SLevi Yun 					name);
1214053a647SLevi Yun 			return -ENOENT;
1224053a647SLevi Yun 		}
1234053a647SLevi Yun 	} else {
1244053a647SLevi Yun 		node = mem_region_node;
1254053a647SLevi Yun 	}
1264053a647SLevi Yun 
1274053a647SLevi Yun 	property = "base-address";
1284053a647SLevi Yun 	ret = fdt_read_uint64(sp_manifest, node, property, base_address);
1294053a647SLevi Yun 	if (ret < 0) {
1304053a647SLevi Yun 		ERROR("Not found property(%s) in memory region(%s).\n",
1314053a647SLevi Yun 				property, name);
1324053a647SLevi Yun 		return -ENOENT;
1334053a647SLevi Yun 	}
1344053a647SLevi Yun 
1354053a647SLevi Yun 	property = "pages-count";
1364053a647SLevi Yun 	ret = fdt_read_uint32(sp_manifest, node, property, size);
1374053a647SLevi Yun 	if (ret < 0) {
1384053a647SLevi Yun 		ERROR("Not found property(%s) in memory region(%s).\n",
1394053a647SLevi Yun 				property, name);
1404053a647SLevi Yun 		return -ENOENT;
1414053a647SLevi Yun 	}
1424053a647SLevi Yun 
1434053a647SLevi Yun 	*size = ((*size) << (PAGE_SIZE_SHIFT + (granularity << 1)));
1444053a647SLevi Yun 
1454053a647SLevi Yun 	return 0;
1464053a647SLevi Yun }
1474053a647SLevi Yun 
build_sp_boot_hob_list(void * secure_tl,void * sp_manifest,uintptr_t hob_table_start,size_t * hob_table_size)1484053a647SLevi Yun static struct efi_hob_handoff_info_table *build_sp_boot_hob_list(
1494e5247c1SYeoreum Yun 		void *secure_tl, void *sp_manifest,
1504e5247c1SYeoreum Yun 		uintptr_t hob_table_start, size_t *hob_table_size)
1514053a647SLevi Yun {
1524053a647SLevi Yun 	struct efi_hob_handoff_info_table *hob_table;
1534053a647SLevi Yun 	uintptr_t base_address;
1544053a647SLevi Yun 	int mem_region_node;
1554053a647SLevi Yun 	int32_t node, ret;
1564053a647SLevi Yun 	const char *name;
1574053a647SLevi Yun 	uint32_t granularity, size;
1584053a647SLevi Yun 	uint32_t mem_region_num;
1594053a647SLevi Yun 	struct efi_guid ns_buf_guid = MM_NS_BUFFER_GUID;
1604053a647SLevi Yun 	struct efi_guid mmram_resv_guid = MM_PEI_MMRAM_MEMORY_RESERVE_GUID;
1614e5247c1SYeoreum Yun 	struct efi_guid tpm_evtlog_guid = MM_TPM_EVENT_LOG_GUID;
1624053a647SLevi Yun 	struct efi_mmram_descriptor *mmram_desc_data;
1634053a647SLevi Yun 	struct efi_mmram_hob_descriptor_block *mmram_hob_desc_data;
1644053a647SLevi Yun 
1654053a647SLevi Yun 	if (sp_manifest == NULL || hob_table_size == NULL || *hob_table_size == 0) {
1664053a647SLevi Yun 		return NULL;
1674053a647SLevi Yun 	}
1684053a647SLevi Yun 
1694053a647SLevi Yun 	node = fdt_path_offset(sp_manifest, "/");
1704053a647SLevi Yun 	if (node < 0) {
1714053a647SLevi Yun 		ERROR("Failed to get root in sp_manifest.\n");
1724053a647SLevi Yun 		return NULL;
1734053a647SLevi Yun 	}
1744053a647SLevi Yun 
1754053a647SLevi Yun 	ret = fdt_read_uint32(sp_manifest, node, "xlat-granule", &granularity);
1764053a647SLevi Yun 	if (ret < 0) {
1774053a647SLevi Yun 		ERROR("Not found property(xlat-granule) in sp_manifest.\n");
1784053a647SLevi Yun 		return NULL;
1794053a647SLevi Yun 	}
1804053a647SLevi Yun 
1814053a647SLevi Yun 	if (granularity > 0x02) {
1824053a647SLevi Yun 		ERROR("Invalid granularity value: 0x%x\n", granularity);
1834053a647SLevi Yun 		return NULL;
1844053a647SLevi Yun 	}
1854053a647SLevi Yun 
1864053a647SLevi Yun 	mem_region_node = fdt_subnode_offset_namelen(sp_manifest, 0, "memory-regions",
1874053a647SLevi Yun 			sizeof("memory-regions") - 1);
1884053a647SLevi Yun 	if (node < 0) {
1894053a647SLevi Yun 		ERROR("Not found memory-region configuration for SP.\n");
1904053a647SLevi Yun 		return NULL;
1914053a647SLevi Yun 	}
1924053a647SLevi Yun 
1934053a647SLevi Yun 	INFO("Generating PHIT_HOB...\n");
1944053a647SLevi Yun 
1954053a647SLevi Yun 	hob_table = create_hob_list(BL32_BASE, BL32_LIMIT,
1964053a647SLevi Yun 			hob_table_start, *hob_table_size);
1974053a647SLevi Yun 	if (hob_table == NULL) {
1984053a647SLevi Yun 		ERROR("Failed to create Hob Table.\n");
1994053a647SLevi Yun 		return NULL;
2004053a647SLevi Yun 	}
2014053a647SLevi Yun 
2024053a647SLevi Yun 	/*
2034053a647SLevi Yun 	 * Create fv hob.
2044053a647SLevi Yun 	 */
2054053a647SLevi Yun 	ret = get_memory_region_info(sp_manifest, mem_region_node,
2064053a647SLevi Yun 			"stmm_region", granularity, &base_address, &size);
2074053a647SLevi Yun 	if (ret < 0) {
2084053a647SLevi Yun 		return NULL;
2094053a647SLevi Yun 	}
2104053a647SLevi Yun 
2114053a647SLevi Yun 	if (base_address != BL32_BASE &&
2124053a647SLevi Yun 			base_address + size > BL32_LIMIT) {
2134053a647SLevi Yun 		ERROR("Image is ouf of bound(0x%lx/0x%x), should be in (0x%llx/0x%llx)\n",
2144053a647SLevi Yun 				base_address, size, BL32_BASE, BL32_LIMIT - BL32_BASE);
2154053a647SLevi Yun 		return NULL;
2164053a647SLevi Yun 	}
2174053a647SLevi Yun 
2184053a647SLevi Yun 	ret = create_fv_hob(hob_table, base_address, size);
2194053a647SLevi Yun 	if (ret < 0) {
2204053a647SLevi Yun 		ERROR("Failed to create fv hob... ret:%d\n", ret);
2214053a647SLevi Yun 		return NULL;
2224053a647SLevi Yun 	}
2234053a647SLevi Yun 
2244053a647SLevi Yun 	INFO("Success to create FV hob(0x%lx/0x%x).\n", base_address, size);
2254053a647SLevi Yun 
2264053a647SLevi Yun 	/*
2274053a647SLevi Yun 	 * Create Ns Buffer hob.
2284053a647SLevi Yun 	 */
2294053a647SLevi Yun 	ret = get_memory_region_info(sp_manifest, mem_region_node,
2304053a647SLevi Yun 			"ns_comm_buffer", granularity, &base_address, &size);
2314053a647SLevi Yun 	if (ret < 0) {
2324053a647SLevi Yun 		return NULL;
2334053a647SLevi Yun 	}
2344053a647SLevi Yun 
2354053a647SLevi Yun 	ret = create_guid_hob(hob_table, &ns_buf_guid,
2364053a647SLevi Yun 			sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
2374053a647SLevi Yun 	if (ret < 0) {
2384053a647SLevi Yun 		ERROR("Failed to create ns buffer hob\n");
2394053a647SLevi Yun 		return NULL;
2404053a647SLevi Yun 	}
2414053a647SLevi Yun 
2424053a647SLevi Yun 	mmram_desc_data->physical_start = base_address;
2434053a647SLevi Yun 	mmram_desc_data->physical_size = size;
2444053a647SLevi Yun 	mmram_desc_data->cpu_start = base_address;
2454053a647SLevi Yun 	mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
2464053a647SLevi Yun 
2474053a647SLevi Yun 	/*
2484053a647SLevi Yun 	 * Create mmram_resv hob.
2494053a647SLevi Yun 	 */
2504053a647SLevi Yun 	for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
2514053a647SLevi Yun 			node >= 0;
2524053a647SLevi Yun 			node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
2534053a647SLevi Yun 		ret = get_memory_region_info(sp_manifest, node, NULL, granularity,
2544053a647SLevi Yun 				&base_address, &size);
2554053a647SLevi Yun 		if (ret < 0) {
2564053a647SLevi Yun 			name = fdt_get_name(sp_manifest, node, NULL);
2574053a647SLevi Yun 			ERROR("Invalid memory region(%s) found!\n", name);
2584053a647SLevi Yun 			return NULL;
2594053a647SLevi Yun 		}
2604053a647SLevi Yun 	}
2614053a647SLevi Yun 
2624053a647SLevi Yun 	ret = create_guid_hob(hob_table, &mmram_resv_guid,
2634053a647SLevi Yun 			(sizeof(struct efi_mmram_hob_descriptor_block) +
2644e5247c1SYeoreum Yun 			 (sizeof(struct efi_mmram_descriptor) * (mem_region_num))),
2654053a647SLevi Yun 			(void **) &mmram_hob_desc_data);
2664053a647SLevi Yun 	if (ret < 0) {
2674053a647SLevi Yun 		ERROR("Failed to create mmram_resv hob. ret: %d\n", ret);
2684053a647SLevi Yun 		return NULL;
2694053a647SLevi Yun 	}
2704053a647SLevi Yun 
2714053a647SLevi Yun 	mmram_hob_desc_data->number_of_mm_reserved_regions = mem_region_num;
2724053a647SLevi Yun 
2734053a647SLevi Yun 	for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
2744053a647SLevi Yun 			node >= 0;
2754053a647SLevi Yun 			node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
2764053a647SLevi Yun 		get_memory_region_info(sp_manifest, node, NULL, granularity,
2774053a647SLevi Yun 				&base_address, &size);
2784053a647SLevi Yun 		name = fdt_get_name(sp_manifest, node, NULL);
2794053a647SLevi Yun 
2804053a647SLevi Yun 		mmram_desc_data = &mmram_hob_desc_data->descriptor[mem_region_num];
2814053a647SLevi Yun 		mmram_desc_data->physical_start = base_address;
2824053a647SLevi Yun 		mmram_desc_data->physical_size = size;
2834053a647SLevi Yun 		mmram_desc_data->cpu_start = base_address;
2844053a647SLevi Yun 
2854053a647SLevi Yun 		if (!strcmp(name, "heap")) {
2864053a647SLevi Yun 			mmram_desc_data->region_state = EFI_CACHEABLE;
2874053a647SLevi Yun 		} else {
2884053a647SLevi Yun 			mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
2894053a647SLevi Yun 		}
2904053a647SLevi Yun 	}
2914053a647SLevi Yun 
2924e5247c1SYeoreum Yun 	/*
2934e5247c1SYeoreum Yun 	 * Add tpm mmram descriptor.
2944e5247c1SYeoreum Yun 	 */
2954e5247c1SYeoreum Yun 	get_tpm_event_log(secure_tl);
2964e5247c1SYeoreum Yun 
2974e5247c1SYeoreum Yun 	if (tpm_evtlog_addr != NULL && tpm_evtlog_size != 0) {
2984e5247c1SYeoreum Yun 		ret = create_guid_hob(hob_table, &tpm_evtlog_guid,
2994e5247c1SYeoreum Yun 				sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
3004e5247c1SYeoreum Yun 		if (ret < 0) {
3014e5247c1SYeoreum Yun 			ERROR("Failed to create tpm_event_log hob\n");
3024e5247c1SYeoreum Yun 			return NULL;
3034e5247c1SYeoreum Yun 		}
3044e5247c1SYeoreum Yun 
3054e5247c1SYeoreum Yun 		mmram_desc_data->physical_start = (uintptr_t)tpm_evtlog_addr;
3064e5247c1SYeoreum Yun 		mmram_desc_data->physical_size = tpm_evtlog_size;
3074e5247c1SYeoreum Yun 		mmram_desc_data->cpu_start = (uintptr_t)tpm_evtlog_addr;
3084e5247c1SYeoreum Yun 		mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
3094e5247c1SYeoreum Yun 	}
3104e5247c1SYeoreum Yun 
3114053a647SLevi Yun 	*hob_table_size = hob_table->efi_free_memory_bottom -
3124053a647SLevi Yun 		(efi_physical_address_t) hob_table;
3134053a647SLevi Yun 
3144053a647SLevi Yun   return hob_table;
3154053a647SLevi Yun }
3164053a647SLevi Yun #endif
3174053a647SLevi Yun 
31848db2b01SNishant Sharma /*
3192e219215SAchin Gupta  * This function creates a initialization descriptor in the memory reserved
3202e219215SAchin Gupta  * for passing boot information to an SP. It then copies the partition manifest
3212e219215SAchin Gupta  * into this region and ensures that its reference in the initialization
3222e219215SAchin Gupta  * descriptor is updated.
3232e219215SAchin Gupta  */
spmc_create_boot_info(entry_point_info_t * ep_info,struct secure_partition_desc * sp)3242e219215SAchin Gupta static void spmc_create_boot_info(entry_point_info_t *ep_info,
3252e219215SAchin Gupta 				  struct secure_partition_desc *sp)
3262e219215SAchin Gupta {
3272e219215SAchin Gupta 	struct ffa_boot_info_header *boot_header;
3282e219215SAchin Gupta 	struct ffa_boot_info_desc *boot_descriptor;
3294053a647SLevi Yun 	uintptr_t content_addr;
330aae2370cSYeoreum Yun 	void *sp_manifest;
331aae2370cSYeoreum Yun 	void *tl __maybe_unused;
332aae2370cSYeoreum Yun #if TRANSFER_LIST && !RESET_TO_BL31
333aae2370cSYeoreum Yun 	struct transfer_list_entry *te;
334aae2370cSYeoreum Yun 
335aae2370cSYeoreum Yun 	tl = (void *)((uintptr_t)ep_info->args.arg3);
336aae2370cSYeoreum Yun 	te = transfer_list_find((struct transfer_list_header *)tl,
337aae2370cSYeoreum Yun 				TL_TAG_DT_FFA_MANIFEST);
338aae2370cSYeoreum Yun 	assert(te != NULL);
339aae2370cSYeoreum Yun 
340aae2370cSYeoreum Yun 	sp_manifest = (void *)transfer_list_entry_data(te);
341aae2370cSYeoreum Yun #else
3424e5247c1SYeoreum Yun 	tl = NULL;
343aae2370cSYeoreum Yun 	sp_manifest = (void *)ep_info->args.arg0;
344aae2370cSYeoreum Yun #endif
3452e219215SAchin Gupta 
3462e219215SAchin Gupta 	/*
3472e219215SAchin Gupta 	 * Calculate the maximum size of the manifest that can be accommodated
3482e219215SAchin Gupta 	 * in the boot information memory region.
3492e219215SAchin Gupta 	 */
3504053a647SLevi Yun 	size_t max_sz = sizeof(ffa_boot_info_mem) -
3512e219215SAchin Gupta 			  (sizeof(struct ffa_boot_info_header) +
3522e219215SAchin Gupta 			   sizeof(struct ffa_boot_info_desc));
3532e219215SAchin Gupta 
3542e219215SAchin Gupta 	/*
3552e219215SAchin Gupta 	 * The current implementation only supports the FF-A v1.1
3562e219215SAchin Gupta 	 * implementation of the boot protocol, therefore check
3572e219215SAchin Gupta 	 * that a v1.0 SP has not requested use of the protocol.
3582e219215SAchin Gupta 	 */
3592e219215SAchin Gupta 	if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) {
3602e219215SAchin Gupta 		ERROR("FF-A boot protocol not supported for v1.0 clients\n");
3612e219215SAchin Gupta 		return;
3622e219215SAchin Gupta 	}
3632e219215SAchin Gupta 
3642e219215SAchin Gupta 	/* Zero the memory region before populating. */
3654e5247c1SYeoreum Yun 	memset(ffa_boot_info_mem, 0, FFA_BOOT_INFO_SIZE);
3662e219215SAchin Gupta 
3672e219215SAchin Gupta 	/*
3682e219215SAchin Gupta 	 * Populate the ffa_boot_info_header at the start of the boot info
3692e219215SAchin Gupta 	 * region.
3702e219215SAchin Gupta 	 */
3712e219215SAchin Gupta 	boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem;
3722e219215SAchin Gupta 
3732e219215SAchin Gupta 	/* Position the ffa_boot_info_desc after the ffa_boot_info_header. */
3742e219215SAchin Gupta 	boot_header->offset_boot_info_desc =
3752e219215SAchin Gupta 					sizeof(struct ffa_boot_info_header);
3762e219215SAchin Gupta 	boot_descriptor = (struct ffa_boot_info_desc *)
3772e219215SAchin Gupta 			  (ffa_boot_info_mem +
3782e219215SAchin Gupta 			   boot_header->offset_boot_info_desc);
3792e219215SAchin Gupta 
3802e219215SAchin Gupta 	/*
3811b491eeaSElyes Haouas 	 * We must use the FF-A version corresponding to the version implemented
3822e219215SAchin Gupta 	 * by the SP. Currently this can only be v1.1.
3832e219215SAchin Gupta 	 */
3842e219215SAchin Gupta 	boot_header->version = sp->ffa_version;
3852e219215SAchin Gupta 
3862e219215SAchin Gupta 	/* Populate the boot information header. */
3872e219215SAchin Gupta 	boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc);
3882e219215SAchin Gupta 
3892e219215SAchin Gupta 	/* Set the signature "0xFFA". */
3902e219215SAchin Gupta 	boot_header->signature = FFA_INIT_DESC_SIGNATURE;
3912e219215SAchin Gupta 
3922e219215SAchin Gupta 	/* Set the count. Currently 1 since only the manifest is specified. */
3932e219215SAchin Gupta 	boot_header->count_boot_info_desc = 1;
3942e219215SAchin Gupta 
3954053a647SLevi Yun 	boot_descriptor->flags =
3964053a647SLevi Yun 		FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
3974053a647SLevi Yun 		FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
3984053a647SLevi Yun 
3994053a647SLevi Yun 	content_addr = (uintptr_t) (ffa_boot_info_mem +
4004053a647SLevi Yun 				     boot_header->offset_boot_info_desc +
4014053a647SLevi Yun 				     boot_header->size_boot_info_desc);
4024053a647SLevi Yun 
4034053a647SLevi Yun #if HOB_LIST
4044053a647SLevi Yun 	/* Populate the boot information descriptor for the hob_list. */
4054053a647SLevi Yun 	boot_descriptor->type =
4064053a647SLevi Yun 		FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
4074053a647SLevi Yun 		FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_HOB);
4084053a647SLevi Yun 
4094053a647SLevi Yun 	content_addr = (uintptr_t) build_sp_boot_hob_list(
4104e5247c1SYeoreum Yun 			tl, sp_manifest, content_addr, &max_sz);
4114053a647SLevi Yun 	if (content_addr == (uintptr_t) NULL) {
4124053a647SLevi Yun 		WARN("Unable to create phit hob properly.");
4134053a647SLevi Yun 		return;
4144053a647SLevi Yun 	}
4154053a647SLevi Yun 
4164053a647SLevi Yun 	boot_descriptor->size_boot_info = max_sz;
4174053a647SLevi Yun 	boot_descriptor->content = content_addr;
4184053a647SLevi Yun #else
4194053a647SLevi Yun 	/*
4204053a647SLevi Yun 	 * Check if the manifest will fit into the boot info memory region else
4214053a647SLevi Yun 	 * bail.
4224053a647SLevi Yun 	 */
4234053a647SLevi Yun 	if (ep_info->args.arg1 > max_sz) {
4244053a647SLevi Yun 		WARN("Unable to copy manifest into boot information. ");
4254053a647SLevi Yun 		WARN("Max sz = %lu bytes. Manifest sz = %lu bytes\n",
4264053a647SLevi Yun 		     max_sz, ep_info->args.arg1);
4274053a647SLevi Yun 		return;
4284053a647SLevi Yun 	}
4294053a647SLevi Yun 
4302e219215SAchin Gupta 	/* Populate the boot information descriptor for the manifest. */
4312e219215SAchin Gupta 	boot_descriptor->type =
4322e219215SAchin Gupta 		FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
4332e219215SAchin Gupta 		FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
4342e219215SAchin Gupta 
4352e219215SAchin Gupta 	/*
4362e219215SAchin Gupta 	 * Copy the manifest into boot info region after the boot information
4372e219215SAchin Gupta 	 * descriptor.
4382e219215SAchin Gupta 	 */
4392e219215SAchin Gupta 	boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
4402e219215SAchin Gupta 
441aae2370cSYeoreum Yun 	memcpy((void *) content_addr, sp_manifest, boot_descriptor->size_boot_info);
4422e219215SAchin Gupta 
4434053a647SLevi Yun 	boot_descriptor->content = content_addr;
4444053a647SLevi Yun #endif
4452e219215SAchin Gupta 
4462e219215SAchin Gupta 	/* Calculate the size of the total boot info blob. */
4472e219215SAchin Gupta 	boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
4482e219215SAchin Gupta 					   boot_descriptor->size_boot_info +
4492e219215SAchin Gupta 					   (boot_header->count_boot_info_desc *
4502e219215SAchin Gupta 					    boot_header->size_boot_info_desc);
4512e219215SAchin Gupta 
4522e219215SAchin Gupta 	INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
4532e219215SAchin Gupta 	     (uintptr_t) ffa_boot_info_mem,
4542e219215SAchin Gupta 	     boot_header->size_boot_info_blob);
4554053a647SLevi Yun 	INFO("SP content @ 0x%lx, size: %u bytes.\n",
4562e219215SAchin Gupta 	     boot_descriptor->content,
4572e219215SAchin Gupta 	     boot_descriptor->size_boot_info);
4582e219215SAchin Gupta }
4592e219215SAchin Gupta 
4602e219215SAchin Gupta /*
46148db2b01SNishant Sharma  * S-EL1 partitions can be assigned with multiple execution contexts, each
46248db2b01SNishant Sharma  * pinned to the physical CPU. Each execution context index corresponds to the
46348db2b01SNishant Sharma  * respective liner core position.
46448db2b01SNishant Sharma  * S-EL0 partitions execute in a single execution context (index 0).
4655096aeb2SMarc Bonnici  */
get_ec_index(struct secure_partition_desc * sp)4665096aeb2SMarc Bonnici unsigned int get_ec_index(struct secure_partition_desc *sp)
4675096aeb2SMarc Bonnici {
46848db2b01SNishant Sharma 	return (sp->runtime_el == S_EL0) ?
46948db2b01SNishant Sharma 		SEL0_SP_EC_INDEX : plat_my_core_pos();
4705096aeb2SMarc Bonnici }
4715096aeb2SMarc Bonnici 
47248db2b01SNishant Sharma #if SPMC_AT_EL3_SEL0_SP
47348db2b01SNishant Sharma /* Setup spsr in entry point info for common context management code to use. */
spmc_el0_sp_spsr_setup(entry_point_info_t * ep_info)47448db2b01SNishant Sharma void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
47548db2b01SNishant Sharma {
47648db2b01SNishant Sharma 	/* Setup Secure Partition SPSR for S-EL0 SP. */
47748db2b01SNishant Sharma 	ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
47848db2b01SNishant Sharma }
47948db2b01SNishant Sharma 
read_optional_string(void * manifest,int32_t offset,char * property,char * out,size_t len)48083c3da77SNishant Sharma static void read_optional_string(void *manifest, int32_t offset,
48183c3da77SNishant Sharma 				 char *property, char *out, size_t len)
48283c3da77SNishant Sharma {
48383c3da77SNishant Sharma 	const fdt32_t *prop;
48483c3da77SNishant Sharma 	int lenp;
48583c3da77SNishant Sharma 
48683c3da77SNishant Sharma 	prop = fdt_getprop(manifest, offset, property, &lenp);
48783c3da77SNishant Sharma 	if (prop == NULL) {
48883c3da77SNishant Sharma 		out[0] = '\0';
48983c3da77SNishant Sharma 	} else {
49083c3da77SNishant Sharma 		memcpy(out, prop, MIN(lenp, (int)len));
4914053a647SLevi Yun 		out[MIN(lenp, (int)len) - 1] = '\0';
49283c3da77SNishant Sharma 	}
49383c3da77SNishant Sharma }
49483c3da77SNishant Sharma 
49583c3da77SNishant Sharma /*******************************************************************************
49683c3da77SNishant Sharma  * This function will parse the Secure Partition Manifest for fetching secure
497727ab1c4SNishant Sharma  * partition specific memory/device region details. It will find base address,
498727ab1c4SNishant Sharma  * size, memory attributes for each region and then add the respective region
49983c3da77SNishant Sharma  * into secure parition's translation context.
50083c3da77SNishant Sharma  ******************************************************************************/
populate_sp_regions(struct secure_partition_desc * sp,void * sp_manifest,int node,enum sp_memory_region_type type)501727ab1c4SNishant Sharma static void populate_sp_regions(struct secure_partition_desc *sp,
502727ab1c4SNishant Sharma 				void *sp_manifest, int node,
503727ab1c4SNishant Sharma 				enum sp_memory_region_type type)
50483c3da77SNishant Sharma {
50583c3da77SNishant Sharma 	uintptr_t base_address;
50683c3da77SNishant Sharma 	uint32_t mem_attr, mem_region, size;
507727ab1c4SNishant Sharma 	struct mmap_region sp_mem_regions = {0};
50883c3da77SNishant Sharma 	int32_t offset, ret;
509727ab1c4SNishant Sharma 	char *compatibility[SP_MEM_REGION_NOT_SPECIFIED] = {
510727ab1c4SNishant Sharma 		"arm,ffa-manifest-device-regions",
511727ab1c4SNishant Sharma 		"arm,ffa-manifest-memory-regions"
512727ab1c4SNishant Sharma 	};
51383c3da77SNishant Sharma 	char description[10];
51483c3da77SNishant Sharma 	char *property;
515727ab1c4SNishant Sharma 	char *region[SP_MEM_REGION_NOT_SPECIFIED] = {
516727ab1c4SNishant Sharma 		"device regions",
517727ab1c4SNishant Sharma 		"memory regions"
518727ab1c4SNishant Sharma 	};
51983c3da77SNishant Sharma 
520727ab1c4SNishant Sharma 	if (type >= SP_MEM_REGION_NOT_SPECIFIED) {
521727ab1c4SNishant Sharma 		WARN("Invalid region type\n");
52283c3da77SNishant Sharma 		return;
52383c3da77SNishant Sharma 	}
52483c3da77SNishant Sharma 
525727ab1c4SNishant Sharma 	INFO("Mapping SP's %s\n", region[type]);
526727ab1c4SNishant Sharma 
527727ab1c4SNishant Sharma 	if (fdt_node_check_compatible(sp_manifest, node,
528727ab1c4SNishant Sharma 				      compatibility[type]) != 0) {
529727ab1c4SNishant Sharma 		WARN("Incompatible region node in manifest\n");
530727ab1c4SNishant Sharma 		return;
531727ab1c4SNishant Sharma 	}
53283c3da77SNishant Sharma 
53383c3da77SNishant Sharma 	for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0;
53483c3da77SNishant Sharma 	     offset >= 0;
53583c3da77SNishant Sharma 	     offset = fdt_next_subnode(sp_manifest, offset), mem_region++) {
53683c3da77SNishant Sharma 		read_optional_string(sp_manifest, offset, "description",
53783c3da77SNishant Sharma 				     description, sizeof(description));
53883c3da77SNishant Sharma 
53983c3da77SNishant Sharma 		INFO("Mapping: region: %d, %s\n", mem_region, description);
54083c3da77SNishant Sharma 
54183c3da77SNishant Sharma 		property = "base-address";
54283c3da77SNishant Sharma 		ret = fdt_read_uint64(sp_manifest, offset, property,
54383c3da77SNishant Sharma 					&base_address);
54483c3da77SNishant Sharma 		if (ret < 0) {
54583c3da77SNishant Sharma 			WARN("Missing:%s for %s.\n", property, description);
54683c3da77SNishant Sharma 			continue;
54783c3da77SNishant Sharma 		}
54883c3da77SNishant Sharma 
54983c3da77SNishant Sharma 		property = "pages-count";
55083c3da77SNishant Sharma 		ret = fdt_read_uint32(sp_manifest, offset, property, &size);
55183c3da77SNishant Sharma 		if (ret < 0) {
55283c3da77SNishant Sharma 			WARN("Missing: %s for %s.\n", property, description);
55383c3da77SNishant Sharma 			continue;
55483c3da77SNishant Sharma 		}
55583c3da77SNishant Sharma 		size *= PAGE_SIZE;
55683c3da77SNishant Sharma 
55783c3da77SNishant Sharma 		property = "attributes";
55883c3da77SNishant Sharma 		ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr);
55983c3da77SNishant Sharma 		if (ret < 0) {
56083c3da77SNishant Sharma 			WARN("Missing: %s for %s.\n", property, description);
56183c3da77SNishant Sharma 			continue;
56283c3da77SNishant Sharma 		}
56383c3da77SNishant Sharma 
56483c3da77SNishant Sharma 		sp_mem_regions.attr = MT_USER;
565727ab1c4SNishant Sharma 		if (type == SP_MEM_REGION_DEVICE) {
566727ab1c4SNishant Sharma 			sp_mem_regions.attr |= MT_EXECUTE_NEVER;
567727ab1c4SNishant Sharma 		} else {
568727ab1c4SNishant Sharma 			sp_mem_regions.attr |= MT_MEMORY;
56983c3da77SNishant Sharma 			if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) {
570727ab1c4SNishant Sharma 				sp_mem_regions.attr &= ~MT_EXECUTE_NEVER;
571727ab1c4SNishant Sharma 			} else {
572727ab1c4SNishant Sharma 				sp_mem_regions.attr |= MT_EXECUTE_NEVER;
573727ab1c4SNishant Sharma 			}
574727ab1c4SNishant Sharma 		}
575727ab1c4SNishant Sharma 
576727ab1c4SNishant Sharma 		if ((mem_attr & SP_MEM_READ_WRITE) == SP_MEM_READ_WRITE) {
577727ab1c4SNishant Sharma 			sp_mem_regions.attr |= MT_RW;
57883c3da77SNishant Sharma 		}
57983c3da77SNishant Sharma 
58083c3da77SNishant Sharma 		if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) {
58183c3da77SNishant Sharma 			sp_mem_regions.attr |= MT_NS;
58283c3da77SNishant Sharma 		} else {
58383c3da77SNishant Sharma 			sp_mem_regions.attr |= MT_SECURE;
58483c3da77SNishant Sharma 		}
58583c3da77SNishant Sharma 
58683c3da77SNishant Sharma 		sp_mem_regions.base_pa = base_address;
58783c3da77SNishant Sharma 		sp_mem_regions.base_va = base_address;
58883c3da77SNishant Sharma 		sp_mem_regions.size = size;
589727ab1c4SNishant Sharma 
5904053a647SLevi Yun 		INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx mem_attr: 0x%x, attr:0x%x\n",
591727ab1c4SNishant Sharma 		     sp_mem_regions.base_pa,
592727ab1c4SNishant Sharma 		     sp_mem_regions.base_va,
593727ab1c4SNishant Sharma 		     sp_mem_regions.size,
5944053a647SLevi Yun 		     mem_attr,
595727ab1c4SNishant Sharma 		     sp_mem_regions.attr);
596727ab1c4SNishant Sharma 
597727ab1c4SNishant Sharma 		if (type == SP_MEM_REGION_DEVICE) {
598727ab1c4SNishant Sharma 			sp_mem_regions.granularity = XLAT_BLOCK_SIZE(1);
599727ab1c4SNishant Sharma 		} else {
60083c3da77SNishant Sharma 			sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
601727ab1c4SNishant Sharma 		}
60283c3da77SNishant Sharma 		mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
60383c3da77SNishant Sharma 	}
60483c3da77SNishant Sharma }
60583c3da77SNishant Sharma 
spmc_el0_sp_setup_mmu(struct secure_partition_desc * sp,cpu_context_t * ctx)60683c3da77SNishant Sharma static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
60783c3da77SNishant Sharma 				  cpu_context_t *ctx)
60883c3da77SNishant Sharma {
60983c3da77SNishant Sharma 	xlat_ctx_t *xlat_ctx;
61083c3da77SNishant Sharma 	uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
61183c3da77SNishant Sharma 
61283c3da77SNishant Sharma 	xlat_ctx = sp->xlat_ctx_handle;
61383c3da77SNishant Sharma 	init_xlat_tables_ctx(sp->xlat_ctx_handle);
61483c3da77SNishant Sharma 	setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
61583c3da77SNishant Sharma 		      xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
61683c3da77SNishant Sharma 		      EL1_EL0_REGIME);
61783c3da77SNishant Sharma 
61842e35d2fSJayanth Dodderi Chidanand 	write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
61983c3da77SNishant Sharma 		      mmu_cfg_params[MMU_CFG_MAIR]);
62083c3da77SNishant Sharma 
621a0d9a973SJayanth Dodderi Chidanand 	write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
62283c3da77SNishant Sharma 
62342e35d2fSJayanth Dodderi Chidanand 	write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
62483c3da77SNishant Sharma 		      mmu_cfg_params[MMU_CFG_TTBR0]);
62583c3da77SNishant Sharma }
62683c3da77SNishant Sharma 
spmc_el0_sp_setup_sctlr_el1(cpu_context_t * ctx)62783c3da77SNishant Sharma static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
62883c3da77SNishant Sharma {
62942e35d2fSJayanth Dodderi Chidanand 	u_register_t sctlr_el1_val;
63083c3da77SNishant Sharma 
63183c3da77SNishant Sharma 	/* Setup SCTLR_EL1 */
632a0d9a973SJayanth Dodderi Chidanand 	sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
63383c3da77SNishant Sharma 
63442e35d2fSJayanth Dodderi Chidanand 	sctlr_el1_val |=
63583c3da77SNishant Sharma 		/*SCTLR_EL1_RES1 |*/
63683c3da77SNishant Sharma 		/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
63783c3da77SNishant Sharma 		SCTLR_UCI_BIT |
63883c3da77SNishant Sharma 		/* RW regions at xlat regime EL1&0 are forced to be XN. */
63983c3da77SNishant Sharma 		SCTLR_WXN_BIT |
64083c3da77SNishant Sharma 		/* Don't trap to EL1 execution of WFI or WFE at EL0. */
64183c3da77SNishant Sharma 		SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
64283c3da77SNishant Sharma 		/* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
64383c3da77SNishant Sharma 		SCTLR_UCT_BIT |
64483c3da77SNishant Sharma 		/* Don't trap to EL1 execution of DZ ZVA at EL0. */
64583c3da77SNishant Sharma 		SCTLR_DZE_BIT |
64683c3da77SNishant Sharma 		/* Enable SP Alignment check for EL0 */
64783c3da77SNishant Sharma 		SCTLR_SA0_BIT |
64883c3da77SNishant Sharma 		/* Don't change PSTATE.PAN on taking an exception to EL1 */
64983c3da77SNishant Sharma 		SCTLR_SPAN_BIT |
65083c3da77SNishant Sharma 		/* Allow cacheable data and instr. accesses to normal memory. */
65183c3da77SNishant Sharma 		SCTLR_C_BIT | SCTLR_I_BIT |
65283c3da77SNishant Sharma 		/* Enable MMU. */
65383c3da77SNishant Sharma 		SCTLR_M_BIT;
65483c3da77SNishant Sharma 
65542e35d2fSJayanth Dodderi Chidanand 	sctlr_el1_val &= ~(
65683c3da77SNishant Sharma 		/* Explicit data accesses at EL0 are little-endian. */
65783c3da77SNishant Sharma 		SCTLR_E0E_BIT |
65883c3da77SNishant Sharma 		/*
65983c3da77SNishant Sharma 		 * Alignment fault checking disabled when at EL1 and EL0 as
66083c3da77SNishant Sharma 		 * the UEFI spec permits unaligned accesses.
66183c3da77SNishant Sharma 		 */
66283c3da77SNishant Sharma 		SCTLR_A_BIT |
66383c3da77SNishant Sharma 		/* Accesses to DAIF from EL0 are trapped to EL1. */
66483c3da77SNishant Sharma 		SCTLR_UMA_BIT
66583c3da77SNishant Sharma 	);
66683c3da77SNishant Sharma 
66759b7c0a0SJayanth Dodderi Chidanand 	/* Store the initialised SCTLR_EL1 value in the cpu_context */
668a0d9a973SJayanth Dodderi Chidanand 	write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
66983c3da77SNishant Sharma }
67083c3da77SNishant Sharma 
spmc_el0_sp_setup_system_registers(struct secure_partition_desc * sp,cpu_context_t * ctx)67183c3da77SNishant Sharma static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
67283c3da77SNishant Sharma 					       cpu_context_t *ctx)
67383c3da77SNishant Sharma {
67483c3da77SNishant Sharma 
67583c3da77SNishant Sharma 	spmc_el0_sp_setup_mmu(sp, ctx);
67683c3da77SNishant Sharma 
67783c3da77SNishant Sharma 	spmc_el0_sp_setup_sctlr_el1(ctx);
67883c3da77SNishant Sharma 
67983c3da77SNishant Sharma 	/* Setup other system registers. */
68083c3da77SNishant Sharma 
68183c3da77SNishant Sharma 	/* Shim Exception Vector Base Address */
68242e35d2fSJayanth Dodderi Chidanand 	write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
68383c3da77SNishant Sharma 			SPM_SHIM_EXCEPTIONS_PTR);
68419082c20SLevi Yun 	write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1,
68583c3da77SNishant Sharma 		      EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
68683c3da77SNishant Sharma 
68783c3da77SNishant Sharma 	/*
68883c3da77SNishant Sharma 	 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
68983c3da77SNishant Sharma 	 * Note that SPM will not do any saving/restoring of these registers on
69083c3da77SNishant Sharma 	 * behalf of the SP. This falls under the SP's responsibility.
69183c3da77SNishant Sharma 	 * TTA: Enable access to trace registers.
69283c3da77SNishant Sharma 	 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
69383c3da77SNishant Sharma 	 */
69442e35d2fSJayanth Dodderi Chidanand 	write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
69583c3da77SNishant Sharma 			CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
69683c3da77SNishant Sharma }
69783c3da77SNishant Sharma 
69848db2b01SNishant Sharma /* Setup context of an EL0 Secure Partition.  */
spmc_el0_sp_setup(struct secure_partition_desc * sp,int32_t boot_info_reg,void * sp_manifest)69948db2b01SNishant Sharma void spmc_el0_sp_setup(struct secure_partition_desc *sp,
70083c3da77SNishant Sharma 		       int32_t boot_info_reg,
70183c3da77SNishant Sharma 		       void *sp_manifest)
70248db2b01SNishant Sharma {
70348db2b01SNishant Sharma 	mmap_region_t sel1_exception_vectors =
70448db2b01SNishant Sharma 		MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
70548db2b01SNishant Sharma 				SPM_SHIM_EXCEPTIONS_SIZE,
70648db2b01SNishant Sharma 				MT_CODE | MT_SECURE | MT_PRIVILEGED);
70748db2b01SNishant Sharma 	cpu_context_t *ctx;
70883c3da77SNishant Sharma 	int node;
70983c3da77SNishant Sharma 	int offset = 0;
7104e5247c1SYeoreum Yun 	struct mmap_region sp_mem_regions __unused = {0};
71148db2b01SNishant Sharma 
71248db2b01SNishant Sharma 	ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
71348db2b01SNishant Sharma 
71448db2b01SNishant Sharma 	sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
71548db2b01SNishant Sharma 
71648db2b01SNishant Sharma 	/* This region contains the exception vectors used at S-EL1. */
71748db2b01SNishant Sharma 	mmap_add_region_ctx(sp->xlat_ctx_handle,
71848db2b01SNishant Sharma 			    &sel1_exception_vectors);
71948db2b01SNishant Sharma 
72048db2b01SNishant Sharma 	/*
72148db2b01SNishant Sharma 	 * If the SP manifest specified the register to pass the address of the
72248db2b01SNishant Sharma 	 * boot information, then map the memory region to pass boot
72348db2b01SNishant Sharma 	 * information.
72448db2b01SNishant Sharma 	 */
72548db2b01SNishant Sharma 	if (boot_info_reg >= 0) {
72648db2b01SNishant Sharma 		mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
72748db2b01SNishant Sharma 			(uintptr_t) ffa_boot_info_mem,
7284e5247c1SYeoreum Yun 			FFA_BOOT_INFO_SIZE,
72948db2b01SNishant Sharma 			MT_RO_DATA | MT_SECURE | MT_USER);
73048db2b01SNishant Sharma 		mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
73148db2b01SNishant Sharma 	}
73248db2b01SNishant Sharma 
73348db2b01SNishant Sharma 	/*
734727ab1c4SNishant Sharma 	 * Parse the manifest for any device regions that the SP wants to be
735727ab1c4SNishant Sharma 	 * mapped in its translation regime.
736727ab1c4SNishant Sharma 	 */
737727ab1c4SNishant Sharma 	node = fdt_subnode_offset_namelen(sp_manifest, offset,
738727ab1c4SNishant Sharma 					  "device-regions",
739727ab1c4SNishant Sharma 					  sizeof("device-regions") - 1);
740727ab1c4SNishant Sharma 	if (node < 0) {
741727ab1c4SNishant Sharma 		WARN("Not found device-region configuration for SP.\n");
742727ab1c4SNishant Sharma 	} else {
743727ab1c4SNishant Sharma 		populate_sp_regions(sp, sp_manifest, node,
744727ab1c4SNishant Sharma 				    SP_MEM_REGION_DEVICE);
745727ab1c4SNishant Sharma 	}
746727ab1c4SNishant Sharma 
747727ab1c4SNishant Sharma 	/*
74883c3da77SNishant Sharma 	 * Parse the manifest for any memory regions that the SP wants to be
74983c3da77SNishant Sharma 	 * mapped in its translation regime.
75048db2b01SNishant Sharma 	 */
75183c3da77SNishant Sharma 	node = fdt_subnode_offset_namelen(sp_manifest, offset,
75283c3da77SNishant Sharma 					  "memory-regions",
75383c3da77SNishant Sharma 					  sizeof("memory-regions") - 1);
75483c3da77SNishant Sharma 	if (node < 0) {
75583c3da77SNishant Sharma 		WARN("Not found memory-region configuration for SP.\n");
75683c3da77SNishant Sharma 	} else {
757727ab1c4SNishant Sharma 		populate_sp_regions(sp, sp_manifest, node,
758727ab1c4SNishant Sharma 				    SP_MEM_REGION_MEMORY);
75983c3da77SNishant Sharma 	}
76048db2b01SNishant Sharma 
7614e5247c1SYeoreum Yun #if HOB_LIST
7624e5247c1SYeoreum Yun 	/*
7634e5247c1SYeoreum Yun 	 * Add tpm event log region with RO permission.
7644e5247c1SYeoreum Yun 	 */
7654e5247c1SYeoreum Yun 	if (tpm_evtlog_addr != NULL && tpm_evtlog_size != 0) {
7664e5247c1SYeoreum Yun 		INFO("Mapping SP's TPM event log\n");
7674e5247c1SYeoreum Yun 		INFO("TPM event log addr(0x%lx), size(0x%lx)\n",
7684e5247c1SYeoreum Yun 				(uintptr_t)tpm_evtlog_addr, tpm_evtlog_size);
7694e5247c1SYeoreum Yun 		sp_mem_regions.base_pa = (uintptr_t)
7704e5247c1SYeoreum Yun 			((unsigned long)tpm_evtlog_addr & ~(PAGE_SIZE_MASK));
7714e5247c1SYeoreum Yun 		sp_mem_regions.base_va = sp_mem_regions.base_pa;
7724e5247c1SYeoreum Yun 		sp_mem_regions.size = (tpm_evtlog_size & ~(PAGE_SIZE_MASK)) + PAGE_SIZE;
7734e5247c1SYeoreum Yun 		sp_mem_regions.attr = MT_USER | MT_SECURE | MT_RO_DATA;
7744e5247c1SYeoreum Yun 		sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
7754e5247c1SYeoreum Yun 
7764e5247c1SYeoreum Yun 		INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx attr:0x%x\n",
7774e5247c1SYeoreum Yun 		     sp_mem_regions.base_pa,
7784e5247c1SYeoreum Yun 		     sp_mem_regions.base_va,
7794e5247c1SYeoreum Yun 		     sp_mem_regions.size,
7804e5247c1SYeoreum Yun 		     sp_mem_regions.attr);
7814e5247c1SYeoreum Yun 
7824e5247c1SYeoreum Yun 		mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
7834e5247c1SYeoreum Yun 	}
7844e5247c1SYeoreum Yun #endif
7854e5247c1SYeoreum Yun 
78683c3da77SNishant Sharma 	spmc_el0_sp_setup_system_registers(sp, ctx);
78748db2b01SNishant Sharma }
78848db2b01SNishant Sharma #endif /* SPMC_AT_EL3_SEL0_SP */
78948db2b01SNishant Sharma 
7905096aeb2SMarc Bonnici /* S-EL1 partition specific initialisation. */
spmc_el1_sp_setup(struct secure_partition_desc * sp,entry_point_info_t * ep_info)7915096aeb2SMarc Bonnici void spmc_el1_sp_setup(struct secure_partition_desc *sp,
7925096aeb2SMarc Bonnici 		       entry_point_info_t *ep_info)
7935096aeb2SMarc Bonnici {
7945096aeb2SMarc Bonnici 	/* Sanity check input arguments. */
7955096aeb2SMarc Bonnici 	assert(sp != NULL);
7965096aeb2SMarc Bonnici 	assert(ep_info != NULL);
7975096aeb2SMarc Bonnici 
7985096aeb2SMarc Bonnici 	/* Initialise the SPSR for S-EL1 SPs. */
7995096aeb2SMarc Bonnici 	ep_info->spsr =	SPSR_64(MODE_EL1, MODE_SP_ELX,
8005096aeb2SMarc Bonnici 				DISABLE_ALL_EXCEPTIONS);
8015096aeb2SMarc Bonnici 
8025096aeb2SMarc Bonnici 	/*
803f0143004SMarc Bonnici 	 * TF-A Implementation defined behaviour to provide the linear
804f0143004SMarc Bonnici 	 * core ID in the x4 register.
805f0143004SMarc Bonnici 	 */
806f0143004SMarc Bonnici 	ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
807f0143004SMarc Bonnici 
808f0143004SMarc Bonnici 	/*
8095096aeb2SMarc Bonnici 	 * Check whether setup is being performed for the primary or a secondary
8105096aeb2SMarc Bonnici 	 * execution context. In the latter case, indicate to the SP that this
8115096aeb2SMarc Bonnici 	 * is a warm boot.
8125096aeb2SMarc Bonnici 	 * TODO: This check would need to be reworked if the same entry point is
8135096aeb2SMarc Bonnici 	 * used for both primary and secondary initialisation.
8145096aeb2SMarc Bonnici 	 */
8155096aeb2SMarc Bonnici 	if (sp->secondary_ep != 0U) {
8165096aeb2SMarc Bonnici 		/*
8175096aeb2SMarc Bonnici 		 * Sanity check that the secondary entry point is still what was
8185096aeb2SMarc Bonnici 		 * originally set.
8195096aeb2SMarc Bonnici 		 */
8205096aeb2SMarc Bonnici 		assert(sp->secondary_ep == ep_info->pc);
8215096aeb2SMarc Bonnici 		ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
8225096aeb2SMarc Bonnici 	}
8235096aeb2SMarc Bonnici }
8245096aeb2SMarc Bonnici 
8255096aeb2SMarc Bonnici /* Common initialisation for all SPs. */
spmc_sp_common_setup(struct secure_partition_desc * sp,entry_point_info_t * ep_info,int32_t boot_info_reg)8265096aeb2SMarc Bonnici void spmc_sp_common_setup(struct secure_partition_desc *sp,
8272e219215SAchin Gupta 			  entry_point_info_t *ep_info,
8282e219215SAchin Gupta 			  int32_t boot_info_reg)
8295096aeb2SMarc Bonnici {
8305096aeb2SMarc Bonnici 	uint16_t sp_id;
8315096aeb2SMarc Bonnici 
8325096aeb2SMarc Bonnici 	/* Assign FF-A Partition ID if not already assigned. */
8335096aeb2SMarc Bonnici 	if (sp->sp_id == INV_SP_ID) {
8345096aeb2SMarc Bonnici 		sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
8355096aeb2SMarc Bonnici 		/*
8365096aeb2SMarc Bonnici 		 * Ensure we don't clash with previously assigned partition
8375096aeb2SMarc Bonnici 		 * IDs.
8385096aeb2SMarc Bonnici 		 */
8395096aeb2SMarc Bonnici 		while (!is_ffa_secure_id_valid(sp_id)) {
8405096aeb2SMarc Bonnici 			sp_id++;
8415096aeb2SMarc Bonnici 
8425096aeb2SMarc Bonnici 			if (sp_id == FFA_SWD_ID_LIMIT) {
8435096aeb2SMarc Bonnici 				ERROR("Unable to determine valid SP ID.\n");
8445096aeb2SMarc Bonnici 				panic();
8455096aeb2SMarc Bonnici 			}
8465096aeb2SMarc Bonnici 		}
8475096aeb2SMarc Bonnici 		sp->sp_id = sp_id;
8485096aeb2SMarc Bonnici 	}
8495096aeb2SMarc Bonnici 
8502e219215SAchin Gupta 	/* Check if the SP wants to use the FF-A boot protocol. */
8512e219215SAchin Gupta 	if (boot_info_reg >= 0) {
8525096aeb2SMarc Bonnici 		/*
8532e219215SAchin Gupta 		 * Create a boot information descriptor and copy the partition
8542e219215SAchin Gupta 		 * manifest into the reserved memory region for consumption by
8552e219215SAchin Gupta 		 * the SP.
8562e219215SAchin Gupta 		 */
8572e219215SAchin Gupta 		spmc_create_boot_info(ep_info, sp);
8582e219215SAchin Gupta 
8592e219215SAchin Gupta 		/*
8602e219215SAchin Gupta 		 * We have consumed what we need from ep args so we can now
8612e219215SAchin Gupta 		 * zero them before we start populating with new information
8622e219215SAchin Gupta 		 * specifically for the SP.
8635096aeb2SMarc Bonnici 		 */
8645096aeb2SMarc Bonnici 		zeromem(&ep_info->args, sizeof(ep_info->args));
8652e219215SAchin Gupta 
8662e219215SAchin Gupta 		/*
8672e219215SAchin Gupta 		 * Pass the address of the boot information in the
8682e219215SAchin Gupta 		 * boot_info_reg.
8692e219215SAchin Gupta 		 */
8702e219215SAchin Gupta 		switch (boot_info_reg) {
8712e219215SAchin Gupta 		case 0:
8722e219215SAchin Gupta 			ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem;
8732e219215SAchin Gupta 			break;
8742e219215SAchin Gupta 		case 1:
8752e219215SAchin Gupta 			ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem;
8762e219215SAchin Gupta 			break;
8772e219215SAchin Gupta 		case 2:
8782e219215SAchin Gupta 			ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem;
8792e219215SAchin Gupta 			break;
8802e219215SAchin Gupta 		case 3:
8812e219215SAchin Gupta 			ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem;
8822e219215SAchin Gupta 			break;
8832e219215SAchin Gupta 		default:
8842e219215SAchin Gupta 			ERROR("Invalid value for \"gp-register-num\" %d.\n",
8852e219215SAchin Gupta 			      boot_info_reg);
8862e219215SAchin Gupta 		}
8872e219215SAchin Gupta 	} else {
8882e219215SAchin Gupta 		/*
8892e219215SAchin Gupta 		 * We don't need any of the information that was populated
8902e219215SAchin Gupta 		 * in ep_args so we can clear them.
8912e219215SAchin Gupta 		 */
8922e219215SAchin Gupta 		zeromem(&ep_info->args, sizeof(ep_info->args));
8932e219215SAchin Gupta 	}
8945096aeb2SMarc Bonnici }
8955096aeb2SMarc Bonnici 
8965096aeb2SMarc Bonnici /*
8975096aeb2SMarc Bonnici  * Initialise the SP context now we have populated the common and EL specific
8985096aeb2SMarc Bonnici  * entrypoint information.
8995096aeb2SMarc Bonnici  */
spmc_sp_common_ep_commit(struct secure_partition_desc * sp,entry_point_info_t * ep_info)9005096aeb2SMarc Bonnici void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
9015096aeb2SMarc Bonnici 			      entry_point_info_t *ep_info)
9025096aeb2SMarc Bonnici {
9035096aeb2SMarc Bonnici 	cpu_context_t *cpu_ctx;
9045096aeb2SMarc Bonnici 
9055096aeb2SMarc Bonnici 	cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
9065096aeb2SMarc Bonnici 	print_entry_point_info(ep_info);
9075096aeb2SMarc Bonnici 	cm_setup_context(cpu_ctx, ep_info);
9085096aeb2SMarc Bonnici }
909