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