xref: /optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c (revision 5d5d7d0b1c038a6836be9f0b38585f5aa6a4dd01)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019-2020, STMicroelectronics
4  */
5 
6 #include <assert.h>
7 #include <config.h>
8 #include <drivers/clk.h>
9 #include <drivers/clk_dt.h>
10 #include <drivers/stm32mp_dt_bindings.h>
11 #include <drivers/tzc400.h>
12 #include <initcall.h>
13 #include <io.h>
14 #include <keep.h>
15 #include <kernel/dt.h>
16 #include <kernel/interrupt.h>
17 #include <kernel/panic.h>
18 #include <kernel/pm.h>
19 #include <kernel/tee_misc.h>
20 #include <libfdt.h>
21 #include <mm/core_memprot.h>
22 #include <platform_config.h>
23 #include <stm32_util.h>
24 #include <trace.h>
25 #include <util.h>
26 
27 #define IS_PAGE_ALIGNED(addr)		(((addr) & SMALL_PAGE_MASK) == 0)
28 #define FILTER_MASK(_width)		GENMASK_32(((_width) - U(1)), U(0))
29 
30 /*
31  * struct stm32mp_tzc_region - Define a TZC400 region configuration
32  * @cfg: Region configuration bit mask
33  * @addr: Region physical base address
34  * @len: Region byte size
35  */
36 struct stm32mp_tzc_region {
37 	uint32_t cfg;
38 	uint32_t addr;
39 	uint32_t len;
40 };
41 
42 /*
43  * struct stm32mp_tzc_platdata - Device platform data
44  * @name: Device name for debug purpose
45  * @base: TZC400 IOMEM base address
46  * @clk: TZC400 bus clocks (1 or 2 clocks, depending on the platform)
47  * @mem_base: Physical base address of the memory covered by the device
48  * @mem_size: Byte size of the physical memory covered by the device
49  * @itr_chip: Interrupt controller handle
50  * @itr_num: TZC400 interrupt number handled by @itr_chip
51  */
52 struct stm32mp_tzc_platdata {
53 	const char *name;
54 	vaddr_t base;
55 	struct clk *clk[2];
56 	uint32_t mem_base;
57 	uint32_t mem_size;
58 	struct itr_chip *itr_chip;
59 	size_t itr_num;
60 };
61 
62 /*
63  * struct stm32mp_tzc_driver_data - Device configuration read from the hardware
64  * @nb_filters: Number of TZC400 filter cells
65  * @nb_regions: Number of regions supported by the TZC400
66  */
67 struct stm32mp_tzc_driver_data {
68 	uint32_t nb_filters;
69 	uint32_t nb_regions;
70 };
71 
72 /*
73  * struct tzc_device - Device data
74  * @pdata: Device configuration read from the platform DT
75  * @ddata: Device configuration data read from the hardware
76  * @reg: Array of regions configured in the controller
77  * @nb_reg_used: Number of cells in @reg
78  */
79 struct tzc_device {
80 	struct stm32mp_tzc_platdata pdata;
81 	struct stm32mp_tzc_driver_data ddata;
82 	struct tzc_region_config *reg;
83 	uint32_t nb_reg_used;
84 };
85 
86 /*
87  * struct tzc_region_non_sec - Registered non-secure memory region
88  * @region: Memory region description
89  * @link: Link in non-secure memory list
90  *
91  * At TZC driver initialization, there are memory regions defined in the DT
92  * with TZC configuration information. TZC is first configured for each of
93  * these regions and each is carved out from the overall memory address range
94  * controlled by TZC. This results in a series a memory regions that, by
95  * construction, are assigned to non-secure world.
96  */
97 struct tzc_region_non_sec {
98 	struct tzc_region_config region;
99 	SLIST_ENTRY(tzc_region_non_sec) link;
100 };
101 
102 static SLIST_HEAD(nsec_list_head, tzc_region_non_sec) nsec_region_list =
103 	SLIST_HEAD_INITIALIZER(nsec_list_head);
104 
105 static enum itr_return tzc_it_handler(struct itr_handler *handler __unused)
106 {
107 	EMSG("TZC permission failure");
108 	tzc_fail_dump();
109 
110 	if (IS_ENABLED(CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION))
111 		panic();
112 	else
113 		tzc_int_clear();
114 
115 	return ITRR_HANDLED;
116 }
117 DECLARE_KEEP_PAGER(tzc_it_handler);
118 
119 static TEE_Result tzc_region_check_overlap(struct tzc_device *tzc_dev,
120 					   const struct tzc_region_config *reg)
121 {
122 	unsigned int i = 0;
123 
124 	/* Check if base address already defined in another region */
125 	for (i = 0; i < tzc_dev->nb_reg_used; i++)
126 		if (reg->base <= tzc_dev->reg[i].top &&
127 		    reg->top >= tzc_dev->reg[i].base)
128 			return TEE_ERROR_ACCESS_CONFLICT;
129 
130 	return TEE_SUCCESS;
131 }
132 
133 static void tzc_set_driverdata(struct tzc_device *tzc_dev)
134 {
135 	uintptr_t base = tzc_dev->pdata.base;
136 	uint32_t regval = 0;
137 
138 	regval = io_read32(base + BUILD_CONFIG_OFF);
139 	tzc_dev->ddata.nb_filters = ((regval >> BUILD_CONFIG_NF_SHIFT) &
140 				     BUILD_CONFIG_NF_MASK) + 1;
141 	tzc_dev->ddata.nb_regions = ((regval >>	BUILD_CONFIG_NR_SHIFT) &
142 				     BUILD_CONFIG_NR_MASK);
143 
144 	DMSG("TZC400 Filters %"PRIu32" Regions %"PRIu32,
145 	     tzc_dev->ddata.nb_filters, tzc_dev->ddata.nb_regions);
146 }
147 
148 static void stm32mp_tzc_region0(bool enable)
149 {
150 	struct tzc_region_config region_cfg_0 = {
151 		.base = 0,
152 		.top = UINT_MAX,
153 		.sec_attr = TZC_REGION_S_NONE,
154 		.ns_device_access = 0,
155 	};
156 
157 	if (enable)
158 		region_cfg_0.sec_attr = TZC_REGION_S_RDWR;
159 
160 	tzc_configure_region(0, &region_cfg_0);
161 }
162 
163 static void stm32mp_tzc_reset_region(struct tzc_device *tzc_dev)
164 {
165 	unsigned int i = 0;
166 	const struct tzc_region_config cfg = { .top = 0x00000FFF };
167 
168 	/* Clean old configuration */
169 	for (i = 0; i < tzc_dev->ddata.nb_regions; i++)
170 		tzc_configure_region(i + 1, &cfg);
171 }
172 
173 static TEE_Result append_region(struct tzc_device *tzc_dev,
174 				const struct tzc_region_config *region_cfg)
175 {
176 	TEE_Result res = TEE_SUCCESS;
177 	unsigned int index = tzc_dev->nb_reg_used;
178 
179 	if (index >= tzc_dev->ddata.nb_regions ||
180 	    !core_is_buffer_inside(region_cfg->base,
181 				   region_cfg->top + 1 - region_cfg->base,
182 				   tzc_dev->pdata.mem_base,
183 				   tzc_dev->pdata.mem_size))
184 		return TEE_ERROR_BAD_PARAMETERS;
185 
186 	res = tzc_region_check_overlap(tzc_dev, region_cfg);
187 	if (res)
188 		return res;
189 
190 	tzc_dev->reg[tzc_dev->nb_reg_used] = *region_cfg;
191 	tzc_dev->nb_reg_used++;
192 
193 	tzc_configure_region(tzc_dev->nb_reg_used, region_cfg);
194 
195 	return TEE_SUCCESS;
196 }
197 
198 static TEE_Result
199 exclude_region_from_nsec(const struct tzc_region_config *reg_exclude)
200 {
201 	struct tzc_region_non_sec *reg = NULL;
202 
203 	SLIST_FOREACH(reg, &nsec_region_list, link) {
204 		if (core_is_buffer_inside(reg_exclude->base,
205 					  reg_exclude->top + 1 -
206 					  reg_exclude->base,
207 					  reg->region.base,
208 					  reg->region.top + 1 -
209 					  reg->region.base))
210 			break;
211 	}
212 
213 	if (!reg)
214 		return TEE_ERROR_ITEM_NOT_FOUND;
215 
216 	if (reg_exclude->base == reg->region.base &&
217 	    reg_exclude->top == reg->region.top) {
218 		/* Remove this entry */
219 		SLIST_REMOVE(&nsec_region_list, reg, tzc_region_non_sec, link);
220 		free(reg);
221 	} else if (reg_exclude->base == reg->region.base) {
222 		reg->region.base = reg_exclude->top + 1;
223 	} else if (reg_exclude->top == reg->region.top) {
224 		reg->region.top = reg_exclude->base - 1;
225 	} else {
226 		struct tzc_region_non_sec *new_nsec =
227 			calloc(1, sizeof(*new_nsec));
228 
229 		if (!new_nsec)
230 			return TEE_ERROR_OUT_OF_MEMORY;
231 
232 		new_nsec->region = reg->region;
233 		reg->region.top = reg_exclude->base - 1;
234 		new_nsec->region.base = reg_exclude->top + 1;
235 		SLIST_INSERT_AFTER(reg, new_nsec, link);
236 	}
237 
238 	return TEE_SUCCESS;
239 }
240 
241 static void stm32mp_tzc_cfg_boot_region(struct tzc_device *tzc_dev)
242 {
243 	unsigned int idx = 0;
244 	static struct tzc_region_config boot_region[] = {
245 		{
246 			.base = CFG_TZDRAM_START,
247 			.top = CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1,
248 			.sec_attr = TZC_REGION_S_RDWR,
249 			.ns_device_access = 0,
250 		},
251 #ifdef CFG_CORE_RESERVED_SHM
252 		{
253 			.base = CFG_SHMEM_START,
254 			.top = CFG_SHMEM_START + CFG_SHMEM_SIZE - 1,
255 			.sec_attr = TZC_REGION_S_NONE,
256 			.ns_device_access =
257 				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID),
258 		}
259 #endif
260 	};
261 
262 	static_assert(IS_PAGE_ALIGNED(CFG_TZDRAM_START));
263 	static_assert(IS_PAGE_ALIGNED(CFG_TZDRAM_SIZE));
264 #ifdef CFG_CORE_RESERVED_SHM
265 	static_assert(IS_PAGE_ALIGNED(CFG_SHMEM_START));
266 	static_assert(IS_PAGE_ALIGNED(CFG_SHMEM_SIZE));
267 #endif
268 
269 	stm32mp_tzc_region0(true);
270 
271 	stm32mp_tzc_reset_region(tzc_dev);
272 
273 	for (idx = 0; idx < ARRAY_SIZE(boot_region); idx++) {
274 		TEE_Result res = TEE_ERROR_GENERIC;
275 
276 		boot_region[idx].filters =
277 			FILTER_MASK(tzc_dev->ddata.nb_filters);
278 
279 		res = append_region(tzc_dev, &boot_region[idx]);
280 		if (res) {
281 			EMSG("Failed to add region %u", idx);
282 			panic();
283 		}
284 
285 		res = exclude_region_from_nsec(&boot_region[idx]);
286 		if (res) {
287 			EMSG("Failed to configure region %u", idx);
288 			panic();
289 		}
290 	}
291 
292 	/* Remove region0 access */
293 	stm32mp_tzc_region0(false);
294 }
295 
296 static TEE_Result add_node_memory_regions(struct tzc_device *tzc_dev,
297 					  const void *fdt, int node)
298 {
299 	const fdt32_t *conf_list = NULL;
300 	unsigned int nregions = 0;
301 	unsigned int i = 0;
302 	int len = 0;
303 
304 	conf_list = fdt_getprop(fdt, node, "memory-region", &len);
305 	if (!conf_list)
306 		return TEE_SUCCESS;
307 
308 	nregions = len / sizeof(uint32_t);
309 	if (nregions > tzc_dev->ddata.nb_regions) {
310 		EMSG("Too many regions defined in %s",
311 		     fdt_get_name(fdt, node, NULL));
312 		return TEE_ERROR_BAD_PARAMETERS;
313 	}
314 
315 	for (i = 0; i < nregions; i++) {
316 		uint32_t phandle = fdt32_to_cpu(*(conf_list + i));
317 		struct tzc_region_config region_cfg = { };
318 		const fdt32_t *prop = NULL;
319 		paddr_t region_base = 0;
320 		size_t region_size = 0;
321 		int pnode = 0;
322 
323 		pnode = fdt_node_offset_by_phandle(fdt, phandle);
324 		if (pnode < 0)
325 			return TEE_ERROR_BAD_PARAMETERS;
326 
327 		region_base = fdt_reg_base_address(fdt, pnode);
328 		region_size = fdt_reg_size(fdt, pnode);
329 		assert(region_base != (paddr_t)-1 && region_size != (size_t)-1);
330 
331 		if (!IS_PAGE_ALIGNED(region_base) ||
332 		    !IS_PAGE_ALIGNED(region_size))
333 			return TEE_ERROR_BAD_PARAMETERS;
334 
335 		region_cfg.base = region_base;
336 		region_cfg.top = region_base + region_size - 1;
337 		region_cfg.filters = FILTER_MASK(tzc_dev->ddata.nb_filters);
338 
339 		prop = fdt_getprop(fdt, pnode, "st,protreg", &len);
340 		if (!prop || (unsigned int)len != (2 * sizeof(uint32_t)))
341 			return TEE_ERROR_BAD_PARAMETERS;
342 
343 		switch (fdt32_to_cpu(prop[0])) {
344 		case DT_TZC_REGION_S_NONE:
345 			region_cfg.sec_attr = TZC_REGION_S_NONE;
346 			break;
347 		case DT_TZC_REGION_S_RD:
348 			region_cfg.sec_attr = TZC_REGION_S_RD;
349 			break;
350 		case DT_TZC_REGION_S_WR:
351 			region_cfg.sec_attr = TZC_REGION_S_WR;
352 			break;
353 		case DT_TZC_REGION_S_RDWR:
354 			region_cfg.sec_attr = TZC_REGION_S_RDWR;
355 			break;
356 		default:
357 			return TEE_ERROR_BAD_PARAMETERS;
358 		}
359 		region_cfg.ns_device_access = fdt32_to_cpu(prop[1]);
360 
361 		DMSG("%#08"PRIxVA" - %#08"PRIxVA" : Sec access %i NS access %#"PRIx32,
362 		     region_cfg.base, region_cfg.top, region_cfg.sec_attr,
363 		     region_cfg.ns_device_access);
364 
365 		if (append_region(tzc_dev, &region_cfg))
366 			panic("Error adding region");
367 
368 		if (exclude_region_from_nsec(&region_cfg))
369 			panic("Not able to exclude region");
370 	}
371 
372 	return TEE_SUCCESS;
373 }
374 
375 /*
376  * Adds a TZC region entry for each non-secure memory area defined by
377  * nsec_region_list. The function releases resources used to build this
378  * non-secure region list.
379  */
380 static void add_carved_out_nsec(struct tzc_device *tzc_dev)
381 {
382 	struct tzc_region_non_sec *region = NULL;
383 	struct tzc_region_non_sec *region_safe = NULL;
384 
385 	SLIST_FOREACH_SAFE(region, &nsec_region_list, link, region_safe) {
386 		DMSG("%#08"PRIxVA" - %#08"PRIxVA" : Sec access %i NS access %#"PRIx32,
387 		     region->region.base, region->region.top,
388 		     region->region.sec_attr,
389 		     region->region.ns_device_access);
390 
391 		if (append_region(tzc_dev, &region->region))
392 			panic("Error adding region");
393 
394 		SLIST_REMOVE(&nsec_region_list, region,
395 			     tzc_region_non_sec, link);
396 		free(region);
397 	};
398 }
399 
400 static TEE_Result stm32mp_tzc_parse_fdt(struct tzc_device *tzc_dev,
401 					const void *fdt, int node)
402 {
403 	TEE_Result res = TEE_ERROR_GENERIC;
404 	struct io_pa_va base = { };
405 	size_t reg_size = 0;
406 	int offs = 0;
407 
408 	res = interrupt_dt_get(fdt, node, &tzc_dev->pdata.itr_chip,
409 			       &tzc_dev->pdata.itr_num);
410 	if (res)
411 		return res;
412 
413 	res = clk_dt_get_by_index(fdt, node, 0, tzc_dev->pdata.clk);
414 	if (res)
415 		return res;
416 
417 	res = clk_dt_get_by_index(fdt, node, 1, tzc_dev->pdata.clk + 1);
418 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
419 		DMSG("No secondary clock for %s",
420 		     fdt_get_name(fdt, node, NULL));
421 	else if (res)
422 		return res;
423 
424 	base.pa = fdt_reg_base_address(fdt, node);
425 	if (base.pa == DT_INFO_INVALID_REG)
426 		return TEE_ERROR_BAD_PARAMETERS;
427 
428 	reg_size = fdt_reg_size(fdt, node);
429 	if (reg_size == DT_INFO_INVALID_REG_SIZE)
430 		return TEE_ERROR_BAD_PARAMETERS;
431 
432 	tzc_dev->pdata.name = strdup(fdt_get_name(fdt, node, NULL));
433 	tzc_dev->pdata.base = io_pa_or_va_secure(&base, reg_size);
434 
435 	offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type",
436 					     "memory", sizeof("memory"));
437 	if (offs < 0)
438 		panic("No memory reference for TZC DT node");
439 
440 	tzc_dev->pdata.mem_base = fdt_reg_base_address(fdt, offs);
441 	tzc_dev->pdata.mem_size = fdt_reg_size(fdt, offs);
442 
443 	assert(tzc_dev->pdata.mem_base != DT_INFO_INVALID_REG &&
444 	       tzc_dev->pdata.mem_size != DT_INFO_INVALID_REG_SIZE);
445 
446 	return TEE_SUCCESS;
447 }
448 
449 static TEE_Result stm32mp1_tzc_pm(enum pm_op op,
450 				  unsigned int pm_hint __unused,
451 				  const struct pm_callback_handle *hdl)
452 {
453 	unsigned int i = 0;
454 	struct tzc_device *tzc_dev =
455 		(struct tzc_device *)PM_CALLBACK_GET_HANDLE(hdl);
456 
457 	if (op == PM_OP_RESUME) {
458 		stm32mp_tzc_region0(true);
459 
460 		stm32mp_tzc_reset_region(tzc_dev);
461 
462 		for (i = 0; i < tzc_dev->nb_reg_used; i++)
463 			tzc_configure_region(i + 1, &tzc_dev->reg[i]);
464 
465 		stm32mp_tzc_region0(false);
466 	}
467 
468 	return TEE_SUCCESS;
469 }
470 DECLARE_KEEP_PAGER(stm32mp1_tzc_pm);
471 
472 static TEE_Result stm32mp1_tzc_probe(const void *fdt, int node,
473 				     const void *compt_data __unused)
474 {
475 	TEE_Result res = TEE_ERROR_GENERIC;
476 	struct tzc_device *tzc_dev = NULL;
477 	struct tzc_region_non_sec *nsec_region = NULL;
478 
479 	tzc_dev = calloc(1, sizeof(*tzc_dev));
480 	if (!tzc_dev)
481 		panic();
482 
483 	res = stm32mp_tzc_parse_fdt(tzc_dev, fdt, node);
484 	if (res) {
485 		free(tzc_dev);
486 		return res;
487 	}
488 
489 	tzc_set_driverdata(tzc_dev);
490 	tzc_dev->reg = calloc(tzc_dev->ddata.nb_regions,
491 			      sizeof(*tzc_dev->reg));
492 	if (!tzc_dev->reg)
493 		panic();
494 
495 	if (clk_enable(tzc_dev->pdata.clk[0]))
496 		panic();
497 	if (tzc_dev->pdata.clk[1] && clk_enable(tzc_dev->pdata.clk[1]))
498 		panic();
499 
500 	tzc_init(tzc_dev->pdata.base);
501 
502 	nsec_region = calloc(1, sizeof(*nsec_region));
503 	if (!nsec_region)
504 		panic();
505 
506 	nsec_region->region.base = tzc_dev->pdata.mem_base;
507 	nsec_region->region.top = tzc_dev->pdata.mem_base +
508 				  tzc_dev->pdata.mem_size - 1;
509 	nsec_region->region.sec_attr = TZC_REGION_S_NONE;
510 	nsec_region->region.ns_device_access = TZC_REGION_NSEC_ALL_ACCESS_RDWR;
511 	nsec_region->region.filters = FILTER_MASK(tzc_dev->ddata.nb_filters);
512 
513 	SLIST_INSERT_HEAD(&nsec_region_list, nsec_region, link);
514 
515 	stm32mp_tzc_cfg_boot_region(tzc_dev);
516 
517 	res = add_node_memory_regions(tzc_dev, fdt, node);
518 	if (res) {
519 		EMSG("Can't add memory regions: %"PRIx32, res);
520 		panic();
521 	}
522 
523 	add_carved_out_nsec(tzc_dev);
524 
525 	tzc_dump_state();
526 
527 	res = interrupt_create_handler(tzc_dev->pdata.itr_chip,
528 				       tzc_dev->pdata.itr_num, tzc_it_handler,
529 				       NULL, 0, NULL);
530 	if (res)
531 		panic();
532 
533 	interrupt_enable(tzc_dev->pdata.itr_chip, tzc_dev->pdata.itr_num);
534 	tzc_set_action(TZC_ACTION_INT);
535 
536 	register_pm_core_service_cb(stm32mp1_tzc_pm, tzc_dev,
537 				    "stm32mp1-tzc400");
538 
539 	return TEE_SUCCESS;
540 }
541 
542 static const struct dt_device_match tzc_secu_match_table[] = {
543 	{ .compatible = "st,stm32mp1-tzc" },
544 	{ }
545 };
546 
547 DEFINE_DT_DRIVER(tzc_stm32mp1_dt_driver) = {
548 	.name = "stm32mp1-tzc400",
549 	.type = DT_DRIVER_NOTYPE,
550 	.match_table = tzc_secu_match_table,
551 	.probe = stm32mp1_tzc_probe,
552 };
553