xref: /optee_os/core/drivers/tzc400.c (revision f45362f036b4f947575c9ac64e56efee6250e39d)
1 // SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause)
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28  /*
29  * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions are met:
33  *
34  * Redistributions of source code must retain the above copyright notice, this
35  * list of conditions and the following disclaimer.
36  *
37  * Redistributions in binary form must reproduce the above copyright notice,
38  * this list of conditions and the following disclaimer in the documentation
39  * and/or other materials provided with the distribution.
40  *
41  * Neither the name of ARM nor the names of its contributors may be used
42  * to endorse or promote products derived from this software without specific
43  * prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
46  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
49  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55  * POSSIBILITY OF SUCH DAMAGE.
56  */
57 
58 #include <assert.h>
59 #include <drivers/tzc400.h>
60 #include <io.h>
61 #include <kernel/panic.h>
62 #include <stddef.h>
63 #include <trace.h>
64 #include <util.h>
65 
66 /*
67  * Implementation defined values used to validate inputs later.
68  * Filters : max of 4 ; 0 to 3
69  * Regions : max of 9 ; 0 to 8
70  * Address width : Values between 32 to 64
71  */
72 struct tzc_instance {
73 	vaddr_t base;
74 	uint8_t addr_width;
75 	uint8_t num_filters;
76 	uint8_t num_regions;
77 };
78 
79 static struct tzc_instance tzc;
80 
81 
82 static uint32_t tzc_read_build_config(vaddr_t base)
83 {
84 	return io_read32(base + BUILD_CONFIG_OFF);
85 }
86 
87 static uint32_t tzc_read_gate_keeper(vaddr_t base)
88 {
89 	return io_read32(base + GATE_KEEPER_OFF);
90 }
91 
92 static void tzc_write_gate_keeper(vaddr_t base, uint32_t val)
93 {
94 	io_write32(base + GATE_KEEPER_OFF, val);
95 }
96 
97 static void tzc_write_action(vaddr_t base, enum tzc_action action)
98 {
99 	io_write32(base + ACTION_OFF, action);
100 }
101 
102 static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region)
103 {
104 	return io_read32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region));
105 }
106 
107 static void tzc_write_region_base_low(vaddr_t base, uint32_t region,
108 				      uint32_t val)
109 {
110 	io_write32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val);
111 }
112 
113 static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region)
114 {
115 	return io_read32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region));
116 }
117 
118 static void tzc_write_region_base_high(vaddr_t base, uint32_t region,
119 				       uint32_t val)
120 {
121 	io_write32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region), val);
122 }
123 
124 static uint32_t tzc_read_region_top_low(vaddr_t base, uint32_t region)
125 {
126 	return io_read32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region));
127 }
128 
129 static void tzc_write_region_top_low(vaddr_t base, uint32_t region,
130 				     uint32_t val)
131 {
132 	io_write32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val);
133 }
134 
135 static uint32_t tzc_read_region_top_high(vaddr_t base, uint32_t region)
136 {
137 	return io_read32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region));
138 }
139 
140 static void tzc_write_region_top_high(vaddr_t base, uint32_t region,
141 				      uint32_t val)
142 {
143 	io_write32(base + REGION_TOP_HIGH_OFF +	REGION_NUM_OFF(region), val);
144 }
145 
146 static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region)
147 {
148 	return io_read32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region));
149 }
150 
151 static void tzc_write_region_attributes(vaddr_t base, uint32_t region,
152 					uint32_t val)
153 {
154 	io_write32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region), val);
155 }
156 
157 static uint32_t tzc_read_region_id_access(vaddr_t base, uint32_t region)
158 {
159 	return io_read32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region));
160 }
161 
162 static void tzc_write_region_id_access(vaddr_t base, uint32_t region,
163 				       uint32_t val)
164 {
165 	io_write32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val);
166 }
167 
168 static uint32_t tzc_read_component_id(vaddr_t base)
169 {
170 	uint32_t id;
171 
172 	id = io_read8(base + CID0_OFF);
173 	id |= SHIFT_U32(io_read8(base + CID1_OFF), 8);
174 	id |= SHIFT_U32(io_read8(base + CID2_OFF), 16);
175 	id |= SHIFT_U32(io_read8(base + CID3_OFF), 24);
176 
177 	return id;
178 }
179 
180 static uint32_t tzc_get_gate_keeper(vaddr_t base, uint8_t filter)
181 {
182 	uint32_t tmp;
183 
184 	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
185 		GATE_KEEPER_OS_MASK;
186 
187 	return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
188 }
189 
190 /* This function is not MP safe. */
191 static void tzc_set_gate_keeper(vaddr_t base, uint8_t filter, uint32_t val)
192 {
193 	uint32_t tmp;
194 
195 	/* Upper half is current state. Lower half is requested state. */
196 	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
197 		GATE_KEEPER_OS_MASK;
198 
199 	if (val)
200 		tmp |=  (1 << filter);
201 	else
202 		tmp &= ~(1 << filter);
203 
204 	tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
205 			      GATE_KEEPER_OR_SHIFT);
206 
207 	/* Wait here until we see the change reflected in the TZC status. */
208 	while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
209 		GATE_KEEPER_OS_MASK) != tmp)
210 		;
211 }
212 
213 
214 void tzc_init(vaddr_t base)
215 {
216 	uint32_t tzc_id, tzc_build;
217 
218 	assert(base);
219 	tzc.base = base;
220 
221 	/*
222 	 * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
223 	 * component ID is expected to be "0xB105F00D".
224 	 */
225 	tzc_id = tzc_read_component_id(tzc.base);
226 	if (tzc_id != TZC400_COMPONENT_ID) {
227 		EMSG("TZC : Wrong device ID (0x%" PRIx32 ")", tzc_id);
228 		panic();
229 	}
230 
231 	/* Save values we will use later. */
232 	tzc_build = tzc_read_build_config(tzc.base);
233 	tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
234 			   BUILD_CONFIG_NF_MASK) + 1;
235 	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
236 			   BUILD_CONFIG_AW_MASK) + 1;
237 	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
238 			   BUILD_CONFIG_NR_MASK) + 1;
239 }
240 
241 static uint32_t addr_low(vaddr_t addr)
242 {
243 	return (uint32_t)addr;
244 }
245 
246 static uint32_t addr_high(vaddr_t addr __unused)
247 {
248 #if (UINTPTR_MAX == UINT64_MAX)
249 	return (addr >> 32);
250 #else
251 	return 0;
252 #endif
253 }
254 
255 
256 /*
257  * `tzc_configure_region` is used to program regions into the TrustZone
258  * controller. A region can be associated with more than one filter. The
259  * associated filters are passed in as a bitmap (bit0 = filter0).
260  * NOTE:
261  * The region 0 covers the whole address space and is enabled on all filters,
262  * this cannot be changed. It is, however, possible to change some region 0
263  * permissions.
264  */
265 void tzc_configure_region(uint32_t filters,
266 			  uint8_t  region,
267 			  vaddr_t  region_base,
268 			  vaddr_t  region_top,
269 			  enum tzc_region_attributes sec_attr,
270 			  uint32_t ns_device_access)
271 {
272 	assert(tzc.base);
273 
274 	/* Do range checks on filters and regions. */
275 	assert(((filters >> tzc.num_filters) == 0) &&
276 	       (region < tzc.num_regions));
277 
278 	/*
279 	 * Do address range check based on TZC configuration. A 64bit address is
280 	 * the max and expected case.
281 	 */
282 #if (UINTPTR_MAX == UINT64_MAX)
283 	assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
284 		(region_base < region_top)));
285 #endif
286 	/* region_base and (region_top + 1) must be 4KB aligned */
287 	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
288 
289 	assert(sec_attr <= TZC_REGION_S_RDWR);
290 
291 	/*
292 	 * Inputs look ok, start programming registers.
293 	 * All the address registers are 32 bits wide and have a LOW and HIGH
294 	 * component used to construct a up to a 64bit address.
295 	 */
296 	tzc_write_region_base_low(tzc.base, region,
297 				  addr_low(region_base));
298 	tzc_write_region_base_high(tzc.base, region,
299 				   addr_high(region_base));
300 
301 	tzc_write_region_top_low(tzc.base, region,
302 				addr_low(region_top));
303 	tzc_write_region_top_high(tzc.base, region,
304 				addr_high(region_top));
305 
306 	/* Assign the region to a filter and set secure attributes */
307 	tzc_write_region_attributes(tzc.base, region,
308 		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
309 
310 	/*
311 	 * Specify which non-secure devices have permission to access this
312 	 * region.
313 	 */
314 	tzc_write_region_id_access(tzc.base, region, ns_device_access);
315 }
316 
317 TEE_Result tzc_get_region_config(uint8_t region, struct tzc_region_config *cfg)
318 {
319 	uint32_t val32 = 0;
320 
321 	if (region >= tzc.num_regions)
322 		return TEE_ERROR_GENERIC;
323 
324 	cfg->base = reg_pair_to_64(tzc_read_region_base_high(tzc.base, region),
325 				   tzc_read_region_base_low(tzc.base, region));
326 	cfg->top = reg_pair_to_64(tzc_read_region_top_high(tzc.base, region),
327 				  tzc_read_region_top_low(tzc.base, region));
328 
329 	cfg->ns_device_access = tzc_read_region_id_access(tzc.base, region);
330 
331 	val32 = tzc_read_region_attributes(tzc.base, region);
332 	cfg->sec_attr = val32 >> REG_ATTR_SEC_SHIFT;
333 	cfg->filters = val32 & REG_ATTR_F_EN_MASK;
334 
335 	return TEE_SUCCESS;
336 }
337 
338 void tzc_set_action(enum tzc_action action)
339 {
340 	assert(tzc.base);
341 
342 	/*
343 	 * - Currently no handler is provided to trap an error via interrupt
344 	 *   or exception.
345 	 * - The interrupt action has not been tested.
346 	 */
347 	tzc_write_action(tzc.base, action);
348 }
349 
350 
351 void tzc_enable_filters(void)
352 {
353 	uint32_t state;
354 	uint32_t filter;
355 
356 	assert(tzc.base);
357 
358 	for (filter = 0; filter < tzc.num_filters; filter++) {
359 		state = tzc_get_gate_keeper(tzc.base, filter);
360 		if (state) {
361 			/*
362 			 * The TZC filter is already configured. Changing the
363 			 * programmer's view in an active system can cause
364 			 * unpredictable behavior therefore panic for now rather
365 			 * than try to determine whether this is safe in this
366 			 * instance. See:
367 			 * http://infocenter.arm.com/help/index.jsp?\
368 			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html
369 			 */
370 			EMSG("TZC : Filter %d Gatekeeper already enabled",
371 			     filter);
372 			panic();
373 		}
374 		tzc_set_gate_keeper(tzc.base, filter, 1);
375 	}
376 }
377 
378 
379 void tzc_disable_filters(void)
380 {
381 	uint32_t filter;
382 
383 	assert(tzc.base);
384 
385 	/*
386 	 * We don't do the same state check as above as the Gatekeepers are
387 	 * disabled after reset.
388 	 */
389 	for (filter = 0; filter < tzc.num_filters; filter++)
390 		tzc_set_gate_keeper(tzc.base, filter, 0);
391 }
392 
393 static bool __maybe_unused write_not_read(unsigned int filter)
394 {
395 	return io_read32(tzc.base + FAIL_CONTROL(filter)) &
396 	       FAIL_CONTROL_DIRECTION_WRITE;
397 }
398 
399 static bool __maybe_unused nonsecure_not_secure(unsigned int filter)
400 {
401 	return io_read32(tzc.base + FAIL_CONTROL(filter)) &
402 	       FAIL_CONTROL_NONSECURE;
403 }
404 
405 static bool __maybe_unused priv_not_unpriv(unsigned int filter)
406 {
407 	return io_read32(tzc.base + FAIL_CONTROL(filter)) &
408 	       FAIL_CONTROL_PRIVILEGED;
409 }
410 
411 static void dump_fail_filter(unsigned int filter)
412 {
413 	uint64_t __maybe_unused addr = 0;
414 	uint32_t status = io_read32(tzc.base + INT_STATUS);
415 
416 	if (!(status & BIT(filter + INT_STATUS_OVERLAP_SHIFT)) &&
417 	    !(status & BIT(filter + INT_STATUS_OVERRUN_SHIFT)) &&
418 	    !(status & BIT(filter + INT_STATUS_STATUS_SHIFT)))
419 		return;
420 
421 	if (status & BIT(filter + INT_STATUS_OVERLAP_SHIFT))
422 		EMSG("Overlap violation on filter %u", filter);
423 
424 	if (status & BIT(filter + INT_STATUS_OVERRUN_SHIFT))
425 		EMSG("Overrun violation on filter %u", filter);
426 
427 	if (status & BIT(filter + INT_STATUS_STATUS_SHIFT))
428 		EMSG("Permission violation on filter %u", filter);
429 
430 	addr = reg_pair_to_64(io_read32(tzc.base + FAIL_ADDRESS_HIGH(filter)),
431 			      io_read32(tzc.base + FAIL_ADDRESS_LOW(filter)));
432 
433 	EMSG("Violation @0x%"PRIx64", %ssecure %sprivileged %s, AXI ID %"PRIx32,
434 	     addr,
435 	     nonsecure_not_secure(filter) ? "non-" : "",
436 	     priv_not_unpriv(filter) ? "" : "un",
437 	     write_not_read(filter) ? "write" : "read",
438 	     io_read32(tzc.base + FAIL_ID(filter)));
439 }
440 
441 /*
442  * Dump info when TZC400 catches an unallowed access with TZC
443  * interrupt enabled.
444  */
445 void tzc_fail_dump(void)
446 {
447 	unsigned int filter = 0;
448 
449 	for (filter = 0; filter < tzc.num_filters; filter++)
450 		dump_fail_filter(filter);
451 }
452 
453 void tzc_int_clear(void)
454 {
455 	assert(tzc.base);
456 
457 	io_setbits32(tzc.base + INT_CLEAR, GENMASK_32(tzc.num_filters - 1, 0));
458 }
459 
460 #if TRACE_LEVEL >= TRACE_DEBUG
461 
462 #define	REGION_MAX		8
463 static const __maybe_unused char * const tzc_attr_msg[] = {
464 	"TZC_REGION_S_NONE",
465 	"TZC_REGION_S_RD",
466 	"TZC_REGION_S_WR",
467 	"TZC_REGION_S_RDWR"
468 };
469 
470 void tzc_dump_state(void)
471 {
472 	uint32_t n;
473 	uint32_t temp_32reg, temp_32reg_h;
474 	unsigned int filter = 0;
475 
476 	for (n = 0; n <= REGION_MAX; n++) {
477 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
478 		if (!(temp_32reg & REG_ATTR_F_EN_MASK))
479 			continue;
480 
481 		DMSG("region %d", n);
482 		temp_32reg = tzc_read_region_base_low(tzc.base, n);
483 		temp_32reg_h = tzc_read_region_base_high(tzc.base, n);
484 		DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg);
485 		temp_32reg = tzc_read_region_top_low(tzc.base, n);
486 		temp_32reg_h = tzc_read_region_top_high(tzc.base, n);
487 		DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg);
488 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
489 		DMSG("secure rw: %s",
490 		     tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]);
491 
492 		for (filter = 0; filter < tzc.num_filters; filter++)
493 			if (temp_32reg & BIT(filter))
494 				DMSG("filter %u enable", filter);
495 	}
496 }
497 
498 #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */
499