xref: /arm-trusted-firmware/plat/qemu/common/qemu_spm.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /* SPDX-License-Identifier: BSD-3-Clause
2*91f16700Schasinglulu  *
3*91f16700Schasinglulu  * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved.
4*91f16700Schasinglulu  */
5*91f16700Schasinglulu 
6*91f16700Schasinglulu #include <libfdt.h>
7*91f16700Schasinglulu 
8*91f16700Schasinglulu #include <bl31/ehf.h>
9*91f16700Schasinglulu #include <common/debug.h>
10*91f16700Schasinglulu #include <common/fdt_fixup.h>
11*91f16700Schasinglulu #include <common/fdt_wrappers.h>
12*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h>
13*91f16700Schasinglulu #include <services/spm_mm_partition.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include <platform_def.h>
16*91f16700Schasinglulu 
17*91f16700Schasinglulu /* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */
18*91f16700Schasinglulu #define MAP_DEVICE1_EL0	MAP_REGION_FLAT(DEVICE1_BASE,			\
19*91f16700Schasinglulu 					DEVICE1_SIZE,			\
20*91f16700Schasinglulu 					MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
21*91f16700Schasinglulu 
22*91f16700Schasinglulu mmap_region_t plat_qemu_secure_partition_mmap[] = {
23*91f16700Schasinglulu 	QEMU_SP_IMAGE_NS_BUF_MMAP,	/* must be placed at first entry */
24*91f16700Schasinglulu 	MAP_DEVICE1_EL0,		/* for the UART */
25*91f16700Schasinglulu 	QEMU_SP_IMAGE_MMAP,
26*91f16700Schasinglulu 	QEMU_SPM_BUF_EL0_MMAP,
27*91f16700Schasinglulu 	QEMU_SP_IMAGE_RW_MMAP,
28*91f16700Schasinglulu 	MAP_SECURE_VARSTORE,
29*91f16700Schasinglulu 	{0}
30*91f16700Schasinglulu };
31*91f16700Schasinglulu 
32*91f16700Schasinglulu /* Boot information passed to a secure partition during initialisation. */
33*91f16700Schasinglulu static spm_mm_mp_info_t sp_mp_info[PLATFORM_CORE_COUNT];
34*91f16700Schasinglulu 
35*91f16700Schasinglulu spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
36*91f16700Schasinglulu 	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
37*91f16700Schasinglulu 	.h.version           = VERSION_1,
38*91f16700Schasinglulu 	.h.size              = sizeof(spm_mm_boot_info_t),
39*91f16700Schasinglulu 	.h.attr              = 0,
40*91f16700Schasinglulu 	.sp_mem_base         = PLAT_QEMU_SP_IMAGE_BASE,
41*91f16700Schasinglulu 	.sp_mem_limit        = BL32_LIMIT,
42*91f16700Schasinglulu 	.sp_image_base       = PLAT_QEMU_SP_IMAGE_BASE,
43*91f16700Schasinglulu 	.sp_stack_base       = PLAT_SP_IMAGE_STACK_BASE,
44*91f16700Schasinglulu 	.sp_heap_base        = PLAT_QEMU_SP_IMAGE_HEAP_BASE,
45*91f16700Schasinglulu 	.sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE,
46*91f16700Schasinglulu 	.sp_shared_buf_base  = PLAT_SPM_BUF_BASE,
47*91f16700Schasinglulu 	.sp_image_size       = PLAT_QEMU_SP_IMAGE_SIZE,
48*91f16700Schasinglulu 	.sp_pcpu_stack_size  = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
49*91f16700Schasinglulu 	.sp_heap_size        = PLAT_QEMU_SP_IMAGE_HEAP_SIZE,
50*91f16700Schasinglulu 	.sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE,
51*91f16700Schasinglulu 	.sp_shared_buf_size  = PLAT_SPM_BUF_SIZE,
52*91f16700Schasinglulu 	.num_sp_mem_regions  = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS,
53*91f16700Schasinglulu 	.num_cpus            = PLATFORM_CORE_COUNT,
54*91f16700Schasinglulu 	.mp_info             = sp_mp_info
55*91f16700Schasinglulu };
56*91f16700Schasinglulu 
57*91f16700Schasinglulu /* Enumeration of priority levels on QEMU platforms. */
58*91f16700Schasinglulu ehf_pri_desc_t qemu_exceptions[] = {
59*91f16700Schasinglulu 	EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI)
60*91f16700Schasinglulu };
61*91f16700Schasinglulu 
62*91f16700Schasinglulu static void qemu_initialize_mp_info(spm_mm_mp_info_t *mp_info)
63*91f16700Schasinglulu {
64*91f16700Schasinglulu 	unsigned int i, j;
65*91f16700Schasinglulu 	spm_mm_mp_info_t *tmp = mp_info;
66*91f16700Schasinglulu 
67*91f16700Schasinglulu 	for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) {
68*91f16700Schasinglulu 		for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) {
69*91f16700Schasinglulu 			tmp->mpidr = (0x80000000 | (i << MPIDR_AFF1_SHIFT)) + j;
70*91f16700Schasinglulu 			/*
71*91f16700Schasinglulu 			 * Linear indices and flags will be filled
72*91f16700Schasinglulu 			 * in the spm_mm service.
73*91f16700Schasinglulu 			 */
74*91f16700Schasinglulu 			tmp->linear_id = 0;
75*91f16700Schasinglulu 			tmp->flags = 0;
76*91f16700Schasinglulu 			tmp++;
77*91f16700Schasinglulu 		}
78*91f16700Schasinglulu 	}
79*91f16700Schasinglulu }
80*91f16700Schasinglulu 
81*91f16700Schasinglulu int dt_add_ns_buf_node(uintptr_t *base)
82*91f16700Schasinglulu {
83*91f16700Schasinglulu 	uintptr_t addr;
84*91f16700Schasinglulu 	size_t size;
85*91f16700Schasinglulu 	uintptr_t ns_buf_addr;
86*91f16700Schasinglulu 	int node;
87*91f16700Schasinglulu 	int err;
88*91f16700Schasinglulu 	void *fdt = (void *)ARM_PRELOADED_DTB_BASE;
89*91f16700Schasinglulu 
90*91f16700Schasinglulu 	err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
91*91f16700Schasinglulu 	if (err < 0) {
92*91f16700Schasinglulu 		ERROR("Invalid Device Tree at %p: error %d\n", fdt, err);
93*91f16700Schasinglulu 		return err;
94*91f16700Schasinglulu 	}
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	/*
97*91f16700Schasinglulu 	 * reserved-memory for standaloneMM non-secure buffer
98*91f16700Schasinglulu 	 * is allocated at the top of the first system memory region.
99*91f16700Schasinglulu 	 */
100*91f16700Schasinglulu 	node = fdt_path_offset(fdt, "/memory");
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size);
103*91f16700Schasinglulu 	if (err < 0) {
104*91f16700Schasinglulu 		ERROR("Failed to get the memory node information\n");
105*91f16700Schasinglulu 		return err;
106*91f16700Schasinglulu 	}
107*91f16700Schasinglulu 	INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1);
108*91f16700Schasinglulu 
109*91f16700Schasinglulu 	ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
110*91f16700Schasinglulu 	INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr,
111*91f16700Schasinglulu 	     ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1);
112*91f16700Schasinglulu 
113*91f16700Schasinglulu 	err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr,
114*91f16700Schasinglulu 				      PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
115*91f16700Schasinglulu 	if (err < 0) {
116*91f16700Schasinglulu 		ERROR("Failed to add the reserved-memory node\n");
117*91f16700Schasinglulu 		return err;
118*91f16700Schasinglulu 	}
119*91f16700Schasinglulu 
120*91f16700Schasinglulu 	*base = ns_buf_addr;
121*91f16700Schasinglulu 	return 0;
122*91f16700Schasinglulu }
123*91f16700Schasinglulu 
124*91f16700Schasinglulu /* Plug in QEMU exceptions to Exception Handling Framework. */
125*91f16700Schasinglulu EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions),
126*91f16700Schasinglulu 			QEMU_PRI_BITS);
127*91f16700Schasinglulu 
128*91f16700Schasinglulu const mmap_region_t *plat_get_secure_partition_mmap(void *cookie)
129*91f16700Schasinglulu {
130*91f16700Schasinglulu 	uintptr_t ns_buf_base;
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	dt_add_ns_buf_node(&ns_buf_base);
133*91f16700Schasinglulu 
134*91f16700Schasinglulu 	plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base;
135*91f16700Schasinglulu 	plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base;
136*91f16700Schasinglulu 	plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base;
137*91f16700Schasinglulu 
138*91f16700Schasinglulu 	return plat_qemu_secure_partition_mmap;
139*91f16700Schasinglulu }
140*91f16700Schasinglulu 
141*91f16700Schasinglulu const spm_mm_boot_info_t *
142*91f16700Schasinglulu plat_get_secure_partition_boot_info(void *cookie)
143*91f16700Schasinglulu {
144*91f16700Schasinglulu 	qemu_initialize_mp_info(sp_mp_info);
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	return &plat_qemu_secure_partition_boot_info;
147*91f16700Schasinglulu }
148