1 /* 2 * Copyright (c) 2016, 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 #include "tzc_common_private.c" 37 38 /* 39 * Macros which will be used by common core functions. 40 */ 41 #define TZC_400_REGION_BASE_LOW_0_OFFSET 0x100 42 #define TZC_400_REGION_BASE_HIGH_0_OFFSET 0x104 43 #define TZC_400_REGION_TOP_LOW_0_OFFSET 0x108 44 #define TZC_400_REGION_TOP_HIGH_0_OFFSET 0x10c 45 #define TZC_400_REGION_ATTR_0_OFFSET 0x110 46 #define TZC_400_REGION_ID_ACCESS_0_OFFSET 0x114 47 48 /* 49 * Implementation defined values used to validate inputs later. 50 * Filters : max of 4 ; 0 to 3 51 * Regions : max of 9 ; 0 to 8 52 * Address width : Values between 32 to 64 53 */ 54 typedef struct tzc400_instance { 55 uintptr_t base; 56 uint8_t addr_width; 57 uint8_t num_filters; 58 uint8_t num_regions; 59 } tzc400_instance_t; 60 61 tzc400_instance_t tzc400; 62 63 static inline unsigned int _tzc400_read_build_config(uintptr_t base) 64 { 65 return mmio_read_32(base + BUILD_CONFIG_OFF); 66 } 67 68 static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base) 69 { 70 return mmio_read_32(base + GATE_KEEPER_OFF); 71 } 72 73 static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val) 74 { 75 mmio_write_32(base + GATE_KEEPER_OFF, val); 76 } 77 78 /* 79 * Get the open status information for all filter units. 80 */ 81 #define get_gate_keeper_os(base) ((_tzc400_read_gate_keeper(base) >> \ 82 GATE_KEEPER_OS_SHIFT) & \ 83 GATE_KEEPER_OS_MASK) 84 85 86 /* Define common core functions used across different TZC peripherals. */ 87 DEFINE_TZC_COMMON_WRITE_ACTION(400, 400) 88 DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) 89 DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400) 90 DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400) 91 DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) 92 DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) 93 DEFINE_TZC_COMMON_CONFIGURE_REGION(400) 94 95 static unsigned int _tzc400_get_gate_keeper(uintptr_t base, 96 unsigned int filter) 97 { 98 unsigned int open_status; 99 100 open_status = get_gate_keeper_os(base); 101 102 return (open_status >> filter) & GATE_KEEPER_FILTER_MASK; 103 } 104 105 /* This function is not MP safe. */ 106 static void _tzc400_set_gate_keeper(uintptr_t base, 107 unsigned int filter, 108 int val) 109 { 110 unsigned int open_status; 111 112 /* Upper half is current state. Lower half is requested state. */ 113 open_status = get_gate_keeper_os(base); 114 115 if (val) 116 open_status |= (1 << filter); 117 else 118 open_status &= ~(1 << filter); 119 120 _tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) << 121 GATE_KEEPER_OR_SHIFT); 122 123 /* Wait here until we see the change reflected in the TZC status. */ 124 while ((get_gate_keeper_os(base)) != open_status) 125 ; 126 } 127 128 void tzc400_set_action(tzc_action_t action) 129 { 130 assert(tzc400.base); 131 assert(action <= TZC_ACTION_ERR_INT); 132 133 /* 134 * - Currently no handler is provided to trap an error via interrupt 135 * or exception. 136 * - The interrupt action has not been tested. 137 */ 138 _tzc400_write_action(tzc400.base, action); 139 } 140 141 void tzc400_init(uintptr_t base) 142 { 143 #if DEBUG 144 unsigned int tzc400_id; 145 #endif 146 unsigned int tzc400_build; 147 148 assert(base); 149 tzc400.base = base; 150 151 #if DEBUG 152 tzc400_id = _tzc_read_peripheral_id(base); 153 if (tzc400_id != TZC_400_PERIPHERAL_ID) { 154 ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id); 155 panic(); 156 } 157 #endif 158 159 /* Save values we will use later. */ 160 tzc400_build = _tzc400_read_build_config(tzc400.base); 161 tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) & 162 BUILD_CONFIG_NF_MASK) + 1; 163 tzc400.addr_width = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) & 164 BUILD_CONFIG_AW_MASK) + 1; 165 tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) & 166 BUILD_CONFIG_NR_MASK) + 1; 167 } 168 169 /* 170 * `tzc400_configure_region0` is used to program region 0 into the TrustZone 171 * controller. Region 0 covers the whole address space that is not mapped 172 * to any other region, and is enabled on all filters; this cannot be 173 * changed. This function only changes the access permissions. 174 */ 175 void tzc400_configure_region0(tzc_region_attributes_t sec_attr, 176 unsigned int ns_device_access) 177 { 178 assert(tzc400.base); 179 assert(sec_attr <= TZC_REGION_S_RDWR); 180 181 _tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access); 182 } 183 184 /* 185 * `tzc400_configure_region` is used to program regions into the TrustZone 186 * controller. A region can be associated with more than one filter. The 187 * associated filters are passed in as a bitmap (bit0 = filter0). 188 * NOTE: 189 * Region 0 is special; it is preferable to use tzc400_configure_region0 190 * for this region (see comment for that function). 191 */ 192 void tzc400_configure_region(unsigned int filters, 193 int region, 194 unsigned long long region_base, 195 unsigned long long region_top, 196 tzc_region_attributes_t sec_attr, 197 unsigned int nsaid_permissions) 198 { 199 assert(tzc400.base); 200 201 /* Do range checks on filters and regions. */ 202 assert(((filters >> tzc400.num_filters) == 0) && 203 (region >= 0) && (region < tzc400.num_regions)); 204 205 /* 206 * Do address range check based on TZC configuration. A 64bit address is 207 * the max and expected case. 208 */ 209 assert(((region_top <= _tzc_get_max_top_addr(tzc400.addr_width)) && 210 (region_base < region_top))); 211 212 /* region_base and (region_top + 1) must be 4KB aligned */ 213 assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0); 214 215 assert(sec_attr <= TZC_REGION_S_RDWR); 216 217 _tzc400_configure_region(tzc400.base, filters, region, region_base, 218 region_top, 219 sec_attr, nsaid_permissions); 220 } 221 222 void tzc400_enable_filters(void) 223 { 224 unsigned int state; 225 unsigned int filter; 226 227 assert(tzc400.base); 228 229 for (filter = 0; filter < tzc400.num_filters; filter++) { 230 state = _tzc400_get_gate_keeper(tzc400.base, filter); 231 if (state) { 232 /* The TZC filter is already configured. Changing the 233 * programmer's view in an active system can cause 234 * unpredictable behavior therefore panic for now rather 235 * than try to determine whether this is safe in this 236 * instance. See: 237 * http://infocenter.arm.com/help/index.jsp?\ 238 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */ 239 ERROR("TZC-400 : Filter %d Gatekeeper already" 240 " enabled.\n", filter); 241 panic(); 242 } 243 _tzc400_set_gate_keeper(tzc400.base, filter, 1); 244 } 245 } 246 247 void tzc400_disable_filters(void) 248 { 249 unsigned int filter; 250 251 assert(tzc400.base); 252 253 /* 254 * We don't do the same state check as above as the Gatekeepers are 255 * disabled after reset. 256 */ 257 for (filter = 0; filter < tzc400.num_filters; filter++) 258 _tzc400_set_gate_keeper(tzc400.base, filter, 0); 259 } 260