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