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 read32(base + BUILD_CONFIG_OFF); 85 } 86 87 static uint32_t tzc_read_gate_keeper(vaddr_t base) 88 { 89 return read32(base + GATE_KEEPER_OFF); 90 } 91 92 static void tzc_write_gate_keeper(vaddr_t base, uint32_t val) 93 { 94 write32(val, base + GATE_KEEPER_OFF); 95 } 96 97 static void tzc_write_action(vaddr_t base, enum tzc_action action) 98 { 99 write32(action, base + ACTION_OFF); 100 } 101 102 static void tzc_write_region_base_low(vaddr_t base, uint32_t region, 103 uint32_t val) 104 { 105 write32(val, base + REGION_BASE_LOW_OFF + 106 REGION_NUM_OFF(region)); 107 } 108 109 static void tzc_write_region_base_high(vaddr_t base, uint32_t region, 110 uint32_t val) 111 { 112 write32(val, base + REGION_BASE_HIGH_OFF + 113 REGION_NUM_OFF(region)); 114 } 115 116 static void tzc_write_region_top_low(vaddr_t base, uint32_t region, 117 uint32_t val) 118 { 119 write32(val, base + REGION_TOP_LOW_OFF + 120 REGION_NUM_OFF(region)); 121 } 122 123 static void tzc_write_region_top_high(vaddr_t base, uint32_t region, 124 uint32_t val) 125 { 126 write32(val, base + REGION_TOP_HIGH_OFF + 127 REGION_NUM_OFF(region)); 128 } 129 130 static void tzc_write_region_attributes(vaddr_t base, uint32_t region, 131 uint32_t val) 132 { 133 write32(val, base + REGION_ATTRIBUTES_OFF + 134 REGION_NUM_OFF(region)); 135 } 136 137 static void tzc_write_region_id_access(vaddr_t base, uint32_t region, 138 uint32_t val) 139 { 140 write32(val, base + REGION_ID_ACCESS_OFF + 141 REGION_NUM_OFF(region)); 142 } 143 144 static uint32_t tzc_read_component_id(vaddr_t base) 145 { 146 uint32_t id; 147 148 id = read8(base + CID0_OFF); 149 id |= SHIFT_U32(read8(base + CID1_OFF), 8); 150 id |= SHIFT_U32(read8(base + CID2_OFF), 16); 151 id |= SHIFT_U32(read8(base + CID3_OFF), 24); 152 153 return id; 154 } 155 156 static uint32_t tzc_get_gate_keeper(vaddr_t base, uint8_t filter) 157 { 158 uint32_t tmp; 159 160 tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & 161 GATE_KEEPER_OS_MASK; 162 163 return (tmp >> filter) & GATE_KEEPER_FILTER_MASK; 164 } 165 166 /* This function is not MP safe. */ 167 static void tzc_set_gate_keeper(vaddr_t base, uint8_t filter, uint32_t val) 168 { 169 uint32_t tmp; 170 171 /* Upper half is current state. Lower half is requested state. */ 172 tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & 173 GATE_KEEPER_OS_MASK; 174 175 if (val) 176 tmp |= (1 << filter); 177 else 178 tmp &= ~(1 << filter); 179 180 tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) << 181 GATE_KEEPER_OR_SHIFT); 182 183 /* Wait here until we see the change reflected in the TZC status. */ 184 while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & 185 GATE_KEEPER_OS_MASK) != tmp) 186 ; 187 } 188 189 190 void tzc_init(vaddr_t base) 191 { 192 uint32_t tzc_id, tzc_build; 193 194 assert(base); 195 tzc.base = base; 196 197 /* 198 * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows 199 * component ID is expected to be "0xB105F00D". 200 */ 201 tzc_id = tzc_read_component_id(tzc.base); 202 if (tzc_id != TZC400_COMPONENT_ID) { 203 EMSG("TZC : Wrong device ID (0x%x).\n", tzc_id); 204 panic(); 205 } 206 207 /* Save values we will use later. */ 208 tzc_build = tzc_read_build_config(tzc.base); 209 tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) & 210 BUILD_CONFIG_NF_MASK) + 1; 211 tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & 212 BUILD_CONFIG_AW_MASK) + 1; 213 tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & 214 BUILD_CONFIG_NR_MASK) + 1; 215 } 216 217 static uint32_t addr_low(vaddr_t addr) 218 { 219 return (uint32_t)addr; 220 } 221 222 static uint32_t addr_high(vaddr_t addr __unused) 223 { 224 #if (UINTPTR_MAX == UINT64_MAX) 225 return (addr >> 32); 226 #else 227 return 0; 228 #endif 229 } 230 231 232 /* 233 * `tzc_configure_region` is used to program regions into the TrustZone 234 * controller. A region can be associated with more than one filter. The 235 * associated filters are passed in as a bitmap (bit0 = filter0). 236 * NOTE: 237 * The region 0 covers the whole address space and is enabled on all filters, 238 * this cannot be changed. It is, however, possible to change some region 0 239 * permissions. 240 */ 241 void tzc_configure_region(uint32_t filters, 242 uint8_t region, 243 vaddr_t region_base, 244 vaddr_t region_top, 245 enum tzc_region_attributes sec_attr, 246 uint32_t ns_device_access) 247 { 248 assert(tzc.base); 249 250 /* Do range checks on filters and regions. */ 251 assert(((filters >> tzc.num_filters) == 0) && 252 (region < tzc.num_regions)); 253 254 /* 255 * Do address range check based on TZC configuration. A 64bit address is 256 * the max and expected case. 257 */ 258 #if (UINTPTR_MAX == UINT64_MAX) 259 assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) && 260 (region_base < region_top))); 261 #endif 262 /* region_base and (region_top + 1) must be 4KB aligned */ 263 assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0); 264 265 assert(sec_attr <= TZC_REGION_S_RDWR); 266 267 /* 268 * Inputs look ok, start programming registers. 269 * All the address registers are 32 bits wide and have a LOW and HIGH 270 * component used to construct a up to a 64bit address. 271 */ 272 tzc_write_region_base_low(tzc.base, region, 273 addr_low(region_base)); 274 tzc_write_region_base_high(tzc.base, region, 275 addr_high(region_base)); 276 277 tzc_write_region_top_low(tzc.base, region, 278 addr_low(region_top)); 279 tzc_write_region_top_high(tzc.base, region, 280 addr_high(region_top)); 281 282 /* Assign the region to a filter and set secure attributes */ 283 tzc_write_region_attributes(tzc.base, region, 284 (sec_attr << REG_ATTR_SEC_SHIFT) | filters); 285 286 /* 287 * Specify which non-secure devices have permission to access this 288 * region. 289 */ 290 tzc_write_region_id_access(tzc.base, region, ns_device_access); 291 } 292 293 294 void tzc_set_action(enum tzc_action action) 295 { 296 assert(tzc.base); 297 298 /* 299 * - Currently no handler is provided to trap an error via interrupt 300 * or exception. 301 * - The interrupt action has not been tested. 302 */ 303 tzc_write_action(tzc.base, action); 304 } 305 306 307 void tzc_enable_filters(void) 308 { 309 uint32_t state; 310 uint32_t filter; 311 312 assert(tzc.base); 313 314 for (filter = 0; filter < tzc.num_filters; filter++) { 315 state = tzc_get_gate_keeper(tzc.base, filter); 316 if (state) { 317 /* 318 * The TZC filter is already configured. Changing the 319 * programmer's view in an active system can cause 320 * unpredictable behavior therefore panic for now rather 321 * than try to determine whether this is safe in this 322 * instance. See: 323 * http://infocenter.arm.com/help/index.jsp?\ 324 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html 325 */ 326 EMSG("TZC : Filter %d Gatekeeper already enabled.\n", 327 filter); 328 panic(); 329 } 330 tzc_set_gate_keeper(tzc.base, filter, 1); 331 } 332 } 333 334 335 void tzc_disable_filters(void) 336 { 337 uint32_t filter; 338 339 assert(tzc.base); 340 341 /* 342 * We don't do the same state check as above as the Gatekeepers are 343 * disabled after reset. 344 */ 345 for (filter = 0; filter < tzc.num_filters; filter++) 346 tzc_set_gate_keeper(tzc.base, filter, 0); 347 } 348 349 #if TRACE_LEVEL >= TRACE_DEBUG 350 351 static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) 352 { 353 return read32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region)); 354 } 355 356 static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) 357 { 358 return read32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region)); 359 } 360 361 static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) 362 { 363 return read32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region)); 364 } 365 366 static uint32_t tzc_read_region_top_low(vaddr_t base, uint32_t region) 367 { 368 return read32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region)); 369 } 370 371 static uint32_t tzc_read_region_top_high(vaddr_t base, uint32_t region) 372 { 373 return read32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region)); 374 } 375 376 #define REGION_MAX 8 377 static const __maybe_unused char * const tzc_attr_msg[] = { 378 "TZC_REGION_S_NONE", 379 "TZC_REGION_S_RD", 380 "TZC_REGION_S_WR", 381 "TZC_REGION_S_RDWR" 382 }; 383 384 void tzc_dump_state(void) 385 { 386 uint32_t n; 387 uint32_t temp_32reg, temp_32reg_h; 388 389 DMSG("enter"); 390 for (n = 0; n <= REGION_MAX; n++) { 391 temp_32reg = tzc_read_region_attributes(tzc.base, n); 392 if (!(temp_32reg & REG_ATTR_F_EN_MASK)) 393 continue; 394 395 DMSG("\n"); 396 DMSG("region %d", n); 397 temp_32reg = tzc_read_region_base_low(tzc.base, n); 398 temp_32reg_h = tzc_read_region_base_high(tzc.base, n); 399 DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); 400 temp_32reg = tzc_read_region_top_low(tzc.base, n); 401 temp_32reg_h = tzc_read_region_top_high(tzc.base, n); 402 DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg); 403 temp_32reg = tzc_read_region_attributes(tzc.base, n); 404 DMSG("secure rw: %s", 405 tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]); 406 if (temp_32reg & (1 << 0)) 407 DMSG("filter 0 enable"); 408 if (temp_32reg & (1 << 1)) 409 DMSG("filter 1 enable"); 410 if (temp_32reg & (1 << 2)) 411 DMSG("filter 2 enable"); 412 if (temp_32reg & (1 << 3)) 413 DMSG("filter 3 enable"); 414 } 415 DMSG("exit"); 416 } 417 418 #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ 419