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