1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2017 Marvell International Ltd.
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 #include <initcall.h>
30 #include <io.h>
31 #include <kernel/panic.h>
32 #include <mm/core_memprot.h>
33 #include <util.h>
34
35 #define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1))
36
37 #define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044)
38 #define TRUSTZONE_LOCK BIT(31)
39
40 #define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3))
41 #define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3))
42
43 #define RW_PERM 0x0
44 #define RO_PERM 0x1
45 #define WO_PERM 0x2
46 #define ABORT_PERM 0x3
47
48 #define MAX_RANGE_NUM 16
49 #define INVALID_SIZE_CODE 0xff
50
51 #ifdef TEE_RES_CFG_16M
52 #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M)
53 #elif defined(TEE_RES_CFG_24M)
54 #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M)
55 #elif defined(TEE_RES_CFG_8M)
56 #define RSVD_SEC_MEM SIZE_8M
57 #else
58 #error "no reserved secure memory defined."
59 #endif
60
61 #define RA_ADDR TZDRAM_BASE
62 #define RA_SIZE TZDRAM_SIZE
63 #define RA_PERM ABORT_PERM
64
65 #define TZ_IS_VALID(data) ((data) & (0x1))
66 #define TZ_SET_VALID(data) ((data) |= (0x1))
67
68 #define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1))
69 #define TZ_SET_PERM(data, val) \
70 do { \
71 (data) &= (~(0x3 << 1)); \
72 (data) |= (((val) & 0x3) << 1); \
73 } while (0)
74
75 #define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3))
76 #define TZ_SET_RZ_EN(data, val) \
77 do { \
78 (data) &= (~(0x1 << 3)); \
79 (data) |= (((val) & 0x1) << 3); \
80 } while (0)
81
82 #define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 7)) >> 7))
83
84 #define TZ_SET_AREA_LEN_CODE(data, val) \
85 do { \
86 (data) &= (~(0x1F << 7)); \
87 (data) |= (((val) & 0x1F) << 7); \
88 } while (0)
89
90 #define TZ_GET_START_ADDR_L(data, ret) \
91 ((ret) = (((data) & 0xFFFFF000)))
92
93 #define TZ_SET_START_ADDR_L(data, val) \
94 do { \
95 (data) &= (~0xFFFFF000); \
96 (data) |= (((val) & 0xFFFFF000)); \
97 } while (0)
98
99 #define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4))
100 #define TZ_SET_UR_PERM(data, val) \
101 do { \
102 (data) &= (~(0x3 << 4)); \
103 (data) |= (((val) & 0x3) << 4); \
104 } while (0)
105
106 #define TZ_GET_UR_RZ_EN(data, val) \
107 ((ret) = (((data) & (0x1 << 6)) >> 6))
108
109 #define TZ_SET_UR_RZ_EN(data, val) \
110 do { \
111 (data) &= (~(0x1 << 6)); \
112 (data) |= (((val) & 0x1) << 6); \
113 } while (0)
114
115 /* armada mini region size is 1M */
116 #define RANGE_SIZE_TO_CODE(size, code, i) \
117 do { \
118 (code) = INVALID_SIZE_CODE; \
119 for ((i) = 8; (i) <= 0x1f; (i)++) { \
120 if (((uint32_t)0x1 << (i)) == ((size) >> 12)) { \
121 (code) = (i); \
122 break; \
123 } \
124 } \
125 } while (0)
126
127 #define RANGE_CODE_TO_SIZE_K(code, sizek) ((sizek) = ((4) << (code)))
128
129 #define TZ_LOCK_MC(x) \
130 do { \
131 (x) = io_read32(MCU_MC_CONTROL_0_REG); \
132 (x) |= (TRUSTZONE_LOCK); \
133 io_write32(MCU_MC_CONTROL_0_REG, (x)); \
134 } while (0)
135
136 register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE);
137 register_phys_mem_pgdir(MEM_AREA_IO_SEC, MC_SCR_REGISTER, CORE_MMU_PGDIR_SIZE);
138
_find_valid_range(void)139 static int32_t _find_valid_range(void)
140 {
141 uint32_t i;
142 uint32_t tmp;
143
144 for (i = 0; i < MAX_RANGE_NUM; i++) {
145 tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i));
146 if (!TZ_IS_VALID(tmp))
147 return i;
148 }
149 return -1;
150 }
151
set_range(uint32_t addr,uint32_t size,uint32_t perm)152 static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm)
153 {
154 uint32_t data;
155 uint32_t sizecode;
156 int32_t valid_range;
157 uint32_t i;
158
159 if (!IS_ALIGNED(addr, SIZE_1M)) {
160 EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!",
161 addr);
162 return -1;
163 }
164
165 if (!IS_ALIGNED(size, SIZE_1M)) {
166 EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!",
167 size);
168 return -1;
169 }
170
171 if (!IS_ALIGNED(addr, size)) {
172 EMSG("region size(0x%" PRIx32
173 ") not align with addr(0x%" PRIx32 ")",
174 size, addr);
175 return -1;
176 }
177
178 RANGE_SIZE_TO_CODE(size, sizecode, i);
179 if (sizecode == INVALID_SIZE_CODE) {
180 EMSG("not valid region size(2^n)! size:0x%" PRIx32, size);
181 return -1;
182 }
183
184 valid_range = _find_valid_range();
185 if (valid_range == -1) {
186 EMSG("ERR: can't find valid range!");
187 return -1;
188 }
189
190 data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range));
191
192 TZ_SET_VALID(data);
193 TZ_SET_PERM(data, perm);
194 TZ_SET_AREA_LEN_CODE(data, sizecode);
195 TZ_SET_START_ADDR_L(data, addr);
196
197 if (!valid_range) {
198 /* Set Undefine Range RW */
199 TZ_SET_UR_PERM(data, RW_PERM);
200 TZ_SET_UR_RZ_EN(data, 0);
201 }
202
203 io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data);
204
205 return 0;
206 }
207
_dump_range(void)208 static void _dump_range(void)
209 {
210 uint32_t i;
211 uint32_t tmp;
212 uint32_t sizek;
213 uint32_t sizecode_read;
214 uint32_t __maybe_unused sizem;
215 uint32_t __maybe_unused addr_read;
216 uint32_t __maybe_unused perm_read;
217
218 for (i = 0; i < MAX_RANGE_NUM; i++) {
219 tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i));
220
221 if (TZ_IS_VALID(tmp)) {
222 TZ_GET_PERM(tmp, perm_read);
223 TZ_GET_AREA_LEN_CODE(tmp, sizecode_read);
224 TZ_GET_START_ADDR_L(tmp, addr_read);
225
226 DMSG("Range Num%" PRIu32
227 ": Reg 0x%" PRIx64 " = 0x%" PRIx32,
228 i, MCU_TZ_RANGE_LOW_REG(i), tmp);
229 DMSG("AddrL: 0x%08" PRIx32, addr_read);
230 RANGE_CODE_TO_SIZE_K(sizecode_read, sizek);
231 sizem = sizek >> 10;
232 DMSG("Size: %" PRIu32 "K, %" PRIu32 "M", sizek, sizem);
233 DMSG("Perm: %" PRIu32, perm_read);
234 }
235 }
236 }
237
_find_granule(uint32_t addr,uint32_t size)238 static uint32_t _find_granule(uint32_t addr, uint32_t size)
239 {
240 /* max supported granule for armada is 8TB
241 * but 2GB is far enough here
242 */
243 uint32_t max_granule = SIZE_2G;
244
245 while (max_granule >= SIZE_4K) { /* min granule is 4kB */
246 if (max_granule <= size && IS_ALIGNED(addr, max_granule))
247 return max_granule;
248
249 max_granule >>= 1;
250 }
251
252 return 0; /* cannot find a valid granule */
253 }
254
_set_range(uint32_t addr,uint32_t size,uint32_t perm)255 static void _set_range(uint32_t addr, uint32_t size, uint32_t perm)
256 {
257 uint32_t rgn_addr = addr;
258 uint32_t rgn_size = size;
259 uint32_t p;
260
261 while (rgn_size) {
262 p = _find_granule(rgn_addr, rgn_size);
263 if (!p)
264 panic("cannot find a suitable granule!");
265 if (set_range(rgn_addr, p, perm))
266 panic("set_range failed!");
267
268 rgn_addr += p;
269 rgn_size -= p;
270 }
271 }
272
init_sec_perf(void)273 static TEE_Result init_sec_perf(void)
274 {
275 uint32_t tmp;
276
277 /* MC_SCR config: deny NS access to MC registers */
278 tmp = io_read32(PHY_2_VIR(MC_SCR_REGISTER));
279 tmp |= 0x1;
280 io_write32(PHY_2_VIR(MC_SCR_REGISTER), tmp);
281
282 /* Set Secure Memory Region */
283 DMSG("sec-rgn size: ra = 0x%08" PRIx32 ", size = 0x%" PRIx32,
284 RA_ADDR, RA_SIZE);
285 _set_range(RA_ADDR, RA_SIZE, RA_PERM);
286
287 /* Close TZ register modification */
288 TZ_LOCK_MC(tmp);
289
290 _dump_range();
291
292 return TEE_SUCCESS;
293 }
294
295 service_init(init_sec_perf);
296