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 #if TRACE_LEVEL >= TRACE_DEBUG 394 395 #define REGION_MAX 8 396 static const __maybe_unused char * const tzc_attr_msg[] = { 397 "TZC_REGION_S_NONE", 398 "TZC_REGION_S_RD", 399 "TZC_REGION_S_WR", 400 "TZC_REGION_S_RDWR" 401 }; 402 403 void tzc_dump_state(void) 404 { 405 uint32_t n; 406 uint32_t temp_32reg, temp_32reg_h; 407 unsigned int filter = 0; 408 409 for (n = 0; n <= REGION_MAX; n++) { 410 temp_32reg = tzc_read_region_attributes(tzc.base, n); 411 if (!(temp_32reg & REG_ATTR_F_EN_MASK)) 412 continue; 413 414 DMSG("region %d", n); 415 temp_32reg = tzc_read_region_base_low(tzc.base, n); 416 temp_32reg_h = tzc_read_region_base_high(tzc.base, n); 417 DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); 418 temp_32reg = tzc_read_region_top_low(tzc.base, n); 419 temp_32reg_h = tzc_read_region_top_high(tzc.base, n); 420 DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg); 421 temp_32reg = tzc_read_region_attributes(tzc.base, n); 422 DMSG("secure rw: %s", 423 tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]); 424 425 for (filter = 0; filter < tzc.num_filters; filter++) 426 if (temp_32reg & BIT(filter)) 427 DMSG("filter %u enable", filter); 428 } 429 } 430 431 #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ 432