1 /*
2 * Copyright (c) 2015-2026, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8
9 #include <arch.h>
10 #include <arch_features.h>
11 #include <arch_helpers.h>
12 #include <common/bl_common.h>
13 #include <drivers/arm/pl061_gpio.h>
14 #include <lib/gpt_rme/gpt_rme.h>
15 #if TRANSFER_LIST
16 #include <transfer_list.h>
17 #endif
18 #include <plat/common/platform.h>
19 #if ENABLE_FEAT_RME
20 #ifdef PLAT_qemu
21 #include <qemu_pas_def.h>
22 #elif PLAT_qemu_sbsa
23 #include <qemu_sbsa_pas_def.h>
24 #endif /* PLAT_qemu */
25 #endif /* ENABLE_FEAT_RME */
26 #ifdef PLAT_qemu_sbsa
27 #include <sbsa_platform.h>
28 #endif
29
30 #include "qemu_private.h"
31
32 #define MAP_BL31_TOTAL MAP_REGION_FLAT( \
33 BL31_BASE, \
34 BL31_END - BL31_BASE, \
35 MT_MEMORY | MT_RW | EL3_PAS)
36 #define MAP_BL31_RO MAP_REGION_FLAT( \
37 BL_CODE_BASE, \
38 BL_CODE_END - BL_CODE_BASE, \
39 MT_CODE | EL3_PAS), \
40 MAP_REGION_FLAT( \
41 BL_RO_DATA_BASE, \
42 BL_RO_DATA_END \
43 - BL_RO_DATA_BASE, \
44 MT_RO_DATA | EL3_PAS)
45
46 #if USE_COHERENT_MEM
47 #define MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
48 BL_COHERENT_RAM_BASE, \
49 BL_COHERENT_RAM_END \
50 - BL_COHERENT_RAM_BASE, \
51 MT_DEVICE | MT_RW | EL3_PAS)
52 #endif
53
54 #if ENABLE_FEAT_RME && (RME_GPT_BITLOCK_BLOCK != 0)
55 /*
56 * Number of bitlock_t entries in the gpt_bitlock array for this platform's
57 * Protected Physical Size. One 8-bit bitlock_t entry covers
58 * 8 * RME_GPT_BITLOCK_BLOCK * 512MB.
59 */
60 #if (PLAT_QEMU_PPS > (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)))
61 #define BITLOCKS_NUM (PLAT_QEMU_PPS / \
62 (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)))
63 #else
64 #define BITLOCKS_NUM 1
65 #endif
66
67 static bitlock_t gpt_bitlock[BITLOCKS_NUM];
68 #define BITLOCK_BASE (uintptr_t)gpt_bitlock
69 #define BITLOCK_SIZE sizeof(gpt_bitlock)
70 #else /* !(ENABLE_FEAT_RME && (RME_GPT_BITLOCK_BLOCK != 0)) */
71 #define BITLOCK_BASE UL(0)
72 #define BITLOCK_SIZE UL(0)
73 #endif /* ENABLE_FEAT_RME && (RME_GPT_BITLOCK_BLOCK != 0) */
74
75 /*
76 * Placeholder variables for copying the arguments that have been passed to
77 * BL3-1 from BL2.
78 */
79 static entry_point_info_t bl32_image_ep_info;
80 static entry_point_info_t bl33_image_ep_info;
81 #if ENABLE_RMM
82 static entry_point_info_t rmm_image_ep_info;
83 #endif
84 static struct transfer_list_header __maybe_unused *bl31_tl;
85
86 /*******************************************************************************
87 * Perform any BL3-1 early platform setup. Here is an opportunity to copy
88 * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
89 * they are lost (potentially). This needs to be done before the MMU is
90 * initialized so that the memory layout can be used while creating page
91 * tables. BL2 has flushed this information to memory, so we are guaranteed
92 * to pick up good data.
93 ******************************************************************************/
bl31_early_platform_setup2(u_register_t arg0,u_register_t arg1,u_register_t arg2,u_register_t arg3)94 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
95 u_register_t arg2, u_register_t arg3)
96 {
97 bool __maybe_unused is64 = false;
98 uint64_t __maybe_unused hval;
99
100 /*
101 * There's a crash on QEMU when initializing SVE in BL31 if FP
102 * traps is enabled in EL3. So disable it until we have permenant
103 * fix for the QEMU platform.
104 */
105 disable_fpregs_traps_el3();
106
107 /* Initialize the console to provide early debug support */
108 qemu_console_init();
109
110 /* Platform names have to be lowercase. */
111 #ifdef PLAT_qemu_sbsa
112 sbsa_platform_init();
113 #endif
114
115 /*
116 * Check params passed from BL2
117 */
118 bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
119
120 assert(params_from_bl2);
121 assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
122 assert(params_from_bl2->h.version >= VERSION_2);
123
124 bl_params_node_t *bl_params = params_from_bl2->head;
125
126 /*
127 * Copy BL33, BL32 and RMM (if present), entry point information.
128 * They are stored in Secure RAM, in BL2's address space.
129 */
130 while (bl_params) {
131 #if defined(__aarch64__) && TRANSFER_LIST
132 if (bl_params->image_id == BL31_IMAGE_ID &&
133 GET_RW(bl_params->ep_info->spsr) == MODE_RW_64)
134 is64 = true;
135 #endif /* defined(__aarch64__) && TRANSFER_LIST */
136 if (bl_params->image_id == BL32_IMAGE_ID)
137 bl32_image_ep_info = *bl_params->ep_info;
138
139 #if ENABLE_RMM
140 if (bl_params->image_id == RMM_IMAGE_ID)
141 rmm_image_ep_info = *bl_params->ep_info;
142 #endif
143
144 if (bl_params->image_id == BL33_IMAGE_ID)
145 bl33_image_ep_info = *bl_params->ep_info;
146
147 bl_params = bl_params->next_params_info;
148 }
149
150 if (!bl33_image_ep_info.pc)
151 panic();
152 #if ENABLE_RMM
153 if (!rmm_image_ep_info.pc)
154 panic();
155 #endif
156
157 #if TRANSFER_LIST
158 if (!transfer_list_check_header((void *)arg3))
159 return;
160
161 if (is64)
162 hval = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
163 else
164 hval = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
165
166 if (arg1 != hval)
167 return;
168 #endif
169
170 bl31_tl = (void *)arg3; /* saved TL address from BL2 */
171 }
172
173 #if ENABLE_FEAT_RME
174 #if PLAT_qemu
175 /*
176 * The GPT library might modify the gpt regions structure to optimize
177 * the layout, so the array cannot be constant.
178 */
179 static pas_region_t pas_regions[] = {
180 QEMU_PAS_ROOT,
181 QEMU_PAS_SECURE,
182 QEMU_PAS_GPTS,
183 QEMU_PAS_NS0,
184 #if ENABLE_RMM
185 QEMU_PAS_REALM,
186 QEMU_PAS_NS1,
187 #endif
188 };
189
bl31_adjust_pas_regions(void)190 static inline void bl31_adjust_pas_regions(void) {}
191 #elif PLAT_qemu_sbsa
192 /*
193 * The GPT library might modify the gpt regions structure to optimize
194 * the layout, so the array cannot be constant.
195 */
196 static pas_region_t pas_regions[] = {
197 QEMU_PAS_ROOT,
198 QEMU_PAS_SECURE,
199 QEMU_PAS_GPTS,
200 QEMU_PAS_NS0,
201 #if ENABLE_RMM
202 QEMU_PAS_REALM,
203 #endif
204 };
205
bl31_adjust_pas_regions(void)206 static void bl31_adjust_pas_regions(void)
207 {
208 uint64_t base_addr = 0, total_size = 0;
209 struct platform_memory_data data;
210 uint32_t node;
211
212 /*
213 * The amount of memory supported by the SBSA platform is dynamic
214 * and dependent on user input. Since the configuration of the GPT
215 * needs to reflect the system memory, QEMU_PAS_NS0 needs to be set
216 * based on the information found in the device tree.
217 */
218
219 for (node = 0; node < sbsa_platform_num_memnodes(); node++) {
220 data = sbsa_platform_memory_node(node);
221
222 if (data.nodeid == 0) {
223 base_addr = data.addr_base;
224 }
225
226 total_size += data.addr_size;
227 }
228
229 /* Index '3' correspond to QEMU_PAS_NS0, see pas_regions[] above */
230 pas_regions[3].base_pa = base_addr;
231 pas_regions[3].size = total_size;
232 }
233 #endif /* PLAT_qemu */
234
bl31_plat_gpt_setup(void)235 static void bl31_plat_gpt_setup(void)
236 {
237 /*
238 * Initialize entire protected space to GPT_GPI_ANY. With each L0 entry
239 * covering 1GB (currently the only supported option), then covering
240 * 256TB of RAM (48-bit PA) would require a 2MB L0 region. At the
241 * moment we use a 8KB table, which covers 1TB of RAM (40-bit PA).
242 */
243 if (gpt_init_l0_tables(PLAT_QEMU_GPCCR_PPS, PLAT_QEMU_L0_GPT_BASE,
244 PLAT_QEMU_L0_GPT_SIZE) < 0) {
245 ERROR("gpt_init_l0_tables() failed!\n");
246 panic();
247 }
248
249 bl31_adjust_pas_regions();
250
251 /* Carve out defined PAS ranges. */
252 if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
253 PLAT_QEMU_L1_GPT_BASE,
254 PLAT_QEMU_L1_GPT_SIZE,
255 pas_regions,
256 (unsigned int)(sizeof(pas_regions) /
257 sizeof(pas_region_t))) < 0) {
258 ERROR("gpt_init_pas_l1_tables() failed!\n");
259 panic();
260 }
261
262 INFO("Enabling Granule Protection Checks\n");
263 if (gpt_enable() < 0) {
264 ERROR("gpt_enable() failed!\n");
265 panic();
266 }
267 }
268 #endif /* ENABLE_FEAT_RME */
269
bl31_plat_arch_setup(void)270 void bl31_plat_arch_setup(void)
271 {
272 const mmap_region_t bl_regions[] = {
273 MAP_BL31_TOTAL,
274 MAP_BL31_RO,
275 #if USE_COHERENT_MEM
276 MAP_BL_COHERENT_RAM,
277 #endif
278 #if ENABLE_FEAT_RME
279 MAP_GPT_L0_REGION,
280 MAP_GPT_L1_REGION,
281 #endif
282 #if ENABLE_RMM
283 MAP_RMM_SHARED_MEM,
284 #endif
285 {0}
286 };
287
288 setup_page_tables(bl_regions, plat_qemu_get_mmap());
289
290 enable_mmu_el3(0);
291
292 /*
293 * Initialise and enable granule protection after MMU.
294 *
295 * Although FEAT_RME supports feature detection, a build with
296 * ENABLE_FEAT_RME=0 and -O0 (no optimization) fails due to undefined
297 * reference to gpt library calls as the compiler doesn't optimise the
298 * check done using is_feat_rme_supported(). So calls to gpt library
299 * are gated using ENABLE_FEAT_RME.
300 */
301 #if ENABLE_FEAT_RME
302 if (is_feat_rme_supported()) {
303 assert(is_feat_rme_present());
304
305 bl31_plat_gpt_setup();
306
307 /*
308 * Initialise Granule Protection library and enable GPC for the
309 * primary processor. The tables have already been initialized
310 * by a previous BL stage, so there is no need to provide any
311 * PAS here. This function sets up pointers to those tables.
312 */
313 if (gpt_runtime_init(BITLOCK_BASE, BITLOCK_SIZE) < 0) {
314 ERROR("gpt_runtime_init() failed!\n");
315 panic();
316 }
317 }
318 #endif /* ENABLE_FEAT_RME */
319
320 }
321
qemu_gpio_init(void)322 static void qemu_gpio_init(void)
323 {
324 #ifdef SECURE_GPIO_BASE
325 pl061_gpio_init();
326 pl061_gpio_register(SECURE_GPIO_BASE, 0);
327 #endif
328 }
329
bl31_platform_setup(void)330 void bl31_platform_setup(void)
331 {
332 plat_qemu_gic_init();
333 qemu_gpio_init();
334 }
335
plat_get_syscnt_freq2(void)336 unsigned int plat_get_syscnt_freq2(void)
337 {
338 return read_cntfrq_el0();
339 }
340
341 /*******************************************************************************
342 * Return a pointer to the 'entry_point_info' structure of the next image
343 * for the security state specified. BL3-3 corresponds to the non-secure
344 * image type while BL3-2 corresponds to the secure image type. A NULL
345 * pointer is returned if the image does not exist.
346 ******************************************************************************/
bl31_plat_get_next_image_ep_info(uint32_t type)347 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
348 {
349 entry_point_info_t *next_image_info;
350
351 assert(sec_state_is_valid(type));
352 if (type == NON_SECURE) {
353 next_image_info = &bl33_image_ep_info;
354 }
355 #if ENABLE_RMM
356 else if (type == REALM) {
357 next_image_info = &rmm_image_ep_info;
358 }
359 #endif
360 else {
361 next_image_info = &bl32_image_ep_info;
362 }
363
364 /*
365 * None of the images on the ARM development platforms can have 0x0
366 * as the entrypoint
367 */
368 if (next_image_info->pc)
369 return next_image_info;
370 else
371 return NULL;
372 }
373
bl31_plat_runtime_setup(void)374 void bl31_plat_runtime_setup(void)
375 {
376 #if TRANSFER_LIST
377 if (bl31_tl) {
378 /*
379 * Relocate the TL from S to NS memory before EL3 exit
380 * to reflect all changes in TL done by BL32
381 */
382 if (!transfer_list_relocate(bl31_tl, (void *)FW_NS_HANDOFF_BASE,
383 bl31_tl->max_size))
384 ERROR("Relocate TL to NS memory failed\n");
385 }
386 #endif
387
388 console_flush();
389 console_switch_state(CONSOLE_FLAG_RUNTIME);
390 }
391