1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <stdbool.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include "dx_reg_base_host.h"
16 #include "test_log.h"
17 #include "tests_phys_map.h"
18
19
20
21 /////////////////////////////////////
22 // macro defines //
23 /////////////////////////////////////
24
25 #define MAX_MAPPED_ALLOWED 5
26 /*************************/
27 /* Global variables */
28 /*************************/
29 int32_t g_reeHwFd = 0;
30 int32_t processHwFd = 0;
31 int32_t userSpaceFd = 0;
32 uint32_t map_used = 0;
33
34 unsigned long g_testHwEnvBaseAddr = 0;
35 unsigned long g_testHwRegBaseAddr = 0;
36 unsigned long g_testHwReeRegBaseAddr = 0;
37 unsigned long g_testHwRndCtxBaseAddr = 0;
38 unsigned long g_testHwRndWorkBuffBaseAddr = 0;
39 unsigned long g_testHwUserStackBaseAddr = 0;
40 unsigned long g_testHwUserBaseAddr = 0;
41
42
43 #define VALID_MAPPED_ADDR(addr) ((addr != 0) && (addr != 0xFFFFFFFF))
44
45 ProcessMappingArea_t processMap;
46
47 /******************************/
48 /* function definitions */
49 /*****************************/
50 /*
51 * @brief This function
52 *
53 * @param[in]
54 *
55 * @param[out]
56 *
57 * caution: the user will get unexpected results using that API with MEM_MAP_USR_DATA flag while using dx_cclib or sbrom testser
58 * since all use the same user physical continues address space!!!
59 *
60 * @return void -
61 */
TestMapCCRegs(void)62 unsigned int TestMapCCRegs(void)
63 {
64 unsigned int rc;
65
66 rc = TestMapProcessAddrs(0, &processMap);
67 if (rc != 0){
68 TEST_PRINTF_ERROR("TestMapProcessAddrs Failed\n");
69 return 1;
70 }
71 g_testHwRndCtxBaseAddr = processMap.processHwRndCtxBaseAddr;
72 g_testHwRndWorkBuffBaseAddr = g_testHwRndCtxBaseAddr + PROCESS_RND_WORKBUFF_OFFSET;
73 g_testHwUserStackBaseAddr = g_testHwRndCtxBaseAddr + PROCESS_RND_CTX_SIZE; // the address and size of teh stack must be page aligned
74 g_testHwUserBaseAddr = g_testHwUserStackBaseAddr + THREAD_STACK_SIZE;
75 TEST_PRINTF("g_testHwRndCtxBaseAddr = 0x%lx\n", (unsigned long)g_testHwRndCtxBaseAddr);
76 TEST_PRINTF("g_testHwRndWorkBuffBaseAddr = 0x%lx\n", (unsigned long)g_testHwRndWorkBuffBaseAddr);
77 TEST_PRINTF("g_testHwUserStackBaseAddr = 0x%lx\n", (unsigned long)g_testHwUserStackBaseAddr);
78 TEST_PRINTF("g_testHwUserBaseAddr = 0x%lx\n", (unsigned long)g_testHwUserBaseAddr);
79
80 return 0;
81
82 }
83
84
85 /*
86 * @brief This function
87 *
88 * @param[in]
89 *
90 * @param[out]
91 *
92 * @return void -
93
94 */
TestUnmapCCRegs(void)95 void TestUnmapCCRegs(void)
96 {
97 TestMunMapProcessAddrs(&processMap);
98 g_testHwRndCtxBaseAddr = 0;
99 g_testHwRndWorkBuffBaseAddr = 0;
100 g_testHwUserStackBaseAddr = 0;
101 g_testHwUserBaseAddr = 0;
102 }
103
104
mapUserSpace(uint32_t numOfThreads,ProcessMappingArea_t * processMap,uint32_t userSpaceSize)105 unsigned int mapUserSpace(uint32_t numOfThreads, ProcessMappingArea_t *processMap, uint32_t userSpaceSize)
106 {
107 uint32_t i = 0;
108 uint32_t threadSize = 0;
109 unsigned long threadOffset = 0;
110 #ifdef DX_PLAT_JUNO
111 char drvName[50] = "/dev/cc_linux_driver";
112 #endif
113
114
115 if (processMap == NULL) {
116 TEST_PRINTF_ERROR("Invalid processMap, exiting...\n");
117 return 1;
118 }
119 if (userSpaceSize < PROCESS_RND_CTX_SIZE) {
120 TEST_PRINTF_ERROR("userSpaceSize Too small, exiting...\n");
121 return 1;
122 }
123 if (userSpaceSize > USER_WORKSPACE_MEM_SIZE) {
124 TEST_PRINTF_ERROR("userSpaceSize Too big, exiting...\n");
125 return 1;
126 }
127 if (numOfThreads > TEST_MAX_THREADS) {
128 TEST_PRINTF_ERROR("Too many threads, exiting...\n");
129 return 1;
130 }
131
132 //TEST_PRINTF("about to open\n");
133 #ifdef DX_PLAT_JUNO
134 // need special driver that overwrites the Linux mmap.
135 // Linux threats this memory as device memory, therfore each access to that memory must be word ligned.
136 // and we need to have byte access.
137 userSpaceFd = open(drvName, O_RDWR|O_SYNC);
138 if (userSpaceFd < 0) {
139 TEST_PRINTF_ERROR("Failed openning %s\n", drvName);
140 goto end_error;
141 }
142 #else
143 userSpaceFd = processHwFd;
144 #endif
145 //TEST_PRINTF("about to mmap for WORKSPACE for RND_CTX\n");
146 processMap->processHwRndCtxBaseAddr = (unsigned long)mmap((unsigned int *)USER_WORKSPACE_MEM_BASE_ADDR,
147 userSpaceSize,
148 PROT_READ|PROT_WRITE|PROT_EXEC,
149 MAP_SHARED|MAP_FIXED, // must use MAP_FIXED to align with secure boot image table
150 userSpaceFd,
151 USER_WORKSPACE_MEM_BASE_ADDR);
152 if (!VALID_MAPPED_ADDR(processMap->processHwRndCtxBaseAddr)) {
153 TEST_PRINTF_ERROR("Error: mmap failed for processHwRndCtxBaseAddr\n");
154 goto end_error;
155 }
156 processMap->userSpaceSize = userSpaceSize;
157 processMap->processHwRndWorkBuffBaseAddr = processMap->processHwRndCtxBaseAddr + PROCESS_RND_WORKBUFF_OFFSET;
158 //TEST_PRINTF("processHwRndCtxBaseAddr = 0x%lx\n", (unsigned long)processMap->processHwRndCtxBaseAddr);
159 if (numOfThreads == 0) {
160 g_testHwRndCtxBaseAddr = processMap->processHwRndCtxBaseAddr;
161 g_testHwRndWorkBuffBaseAddr = g_testHwRndCtxBaseAddr + PROCESS_RND_WORKBUFF_OFFSET;
162 g_testHwUserStackBaseAddr = g_testHwRndCtxBaseAddr + PROCESS_RND_CTX_SIZE;
163 g_testHwUserBaseAddr = g_testHwUserStackBaseAddr + THREAD_STACK_SIZE;
164 return 0;
165 }
166 processMap->numOfThreads = numOfThreads;
167 threadOffset = processMap->processHwRndCtxBaseAddr + PROCESS_RND_CTX_SIZE;
168 threadSize = (userSpaceSize-PROCESS_RND_CTX_SIZE)/numOfThreads;
169 if (threadSize <= (THREAD_RND_CTX_SIZE+THREAD_STACK_SIZE)) {
170 TEST_PRINTF_ERROR("Error: threadSize too small\n"); // should not happen
171 goto end_error;
172 }
173 for (i = 0; i < numOfThreads; i++) {
174 processMap->threadMapAddr[i].threadHwRndCtxBaseAddr = threadOffset;
175 processMap->threadMapAddr[i].threadHwRndWorkBuffBaseAddr = processMap->threadMapAddr[i].threadHwRndCtxBaseAddr + PROCESS_RND_WORKBUFF_OFFSET;
176 processMap->threadMapAddr[i].threadHwUserStackBaseAddr = processMap->threadMapAddr[i].threadHwRndCtxBaseAddr + THREAD_RND_CTX_SIZE;
177 processMap->threadMapAddr[i].threadHwUserBaseAddr = processMap->threadMapAddr[i].threadHwUserStackBaseAddr + THREAD_STACK_SIZE;
178 threadOffset += threadSize;
179
180 TEST_PRINTF("threadHwRndCtxBaseAddr = 0x%lx\n", (unsigned long)processMap->threadMapAddr[i].threadHwRndCtxBaseAddr);
181 TEST_PRINTF("UserStackBaseAddr for thread #%d = 0x%lx\n", i, (unsigned long)processMap->threadMapAddr[i].threadHwUserStackBaseAddr);
182 TEST_PRINTF("UserBaseAddr for thread #%d = 0x%lx\n", i, (unsigned long)processMap->threadMapAddr[i].threadHwUserBaseAddr);
183 }
184 return 0;
185 end_error:
186 if (processMap->processHwRndCtxBaseAddr != 0) {
187 munmap((void *)processMap->processHwRndCtxBaseAddr, processMap->userSpaceSize);
188 }
189 #ifdef DX_PLAT_JUNO
190 close(userSpaceFd);
191 #endif
192 return 1;
193 }
194
195
196 // workspace mapping supports 1 process and up to 16 threads:
197 // process RND CTX - 16KB
198 // for each thread:
199 // RND CTX - 16KB
200 // stack - 16KB
201 // user Data - (((256MB-16KB)/16)-32KB)
TestMapProcessAddrs(uint32_t numOfThreads,ProcessMappingArea_t * processMap)202 unsigned int TestMapProcessAddrs(uint32_t numOfThreads, ProcessMappingArea_t *processMap)
203 {
204 uint32_t rc = 0;
205
206 if (processMap == NULL) {
207 TEST_PRINTF_ERROR("Invalid processMap, exiting...\n");
208 return 1;
209 }
210 if (map_used > 0) {
211 if (map_used == MAX_MAPPED_ALLOWED) {
212 TEST_PRINTF_ERROR("too many mapping, exiting...\n");
213 return 1;
214 }
215 map_used++;
216 TEST_PRINTF_ERROR("process FD already opened, nothing to map\n");
217 return 0;
218 }
219
220 map_used++;
221 memset(processMap, 0, sizeof(ProcessMappingArea_t));
222
223 processHwFd = open("/dev/mem", O_RDWR|O_SYNC);
224 if(processHwFd < 0) {
225 TEST_PRINTF_ERROR("Error: Can not open /dev/mem\n");
226 goto end_with_error;
227 }
228 processMap->numOfThreads = 0;
229 processMap->processHwRegBaseAddr = (unsigned long)mmap(NULL, REG_MAP_AREA_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, processHwFd, DX_BASE_CC);
230 if (!VALID_MAPPED_ADDR(processMap->processHwRegBaseAddr)) {
231 TEST_PRINTF_ERROR("Error: mmap failed for processHwRegBaseAddr 0x%lx\n", (unsigned long)processMap->processHwRegBaseAddr);
232 goto end_with_error;
233 }
234 TEST_PRINTF("processHwRegBaseAddr = 0x%lx\n", (unsigned long)processMap->processHwRegBaseAddr);
235
236 processMap->processHwEnvBaseAddr = (unsigned long)mmap(NULL, REG_MAP_AREA_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, processHwFd, DX_BASE_ENV_REGS);
237 if (!VALID_MAPPED_ADDR(processMap->processHwEnvBaseAddr)) {
238 TEST_PRINTF_ERROR("Error: mmap failed for processHwEnvBaseAddr\n");
239 goto end_with_error;
240 }
241 TEST_PRINTF("processHwEnvBaseAddr = 0x%lx\n", (unsigned long)processMap->processHwEnvBaseAddr);
242
243 rc = mapUserSpace(numOfThreads, processMap, USER_WORKSPACE_MEM_SIZE);
244 if (rc != 0) {
245 TEST_PRINTF_ERROR("Error: failed for mapUserSpace %d\n", rc);
246 goto end_with_error;
247 }
248 g_testHwRegBaseAddr = processMap->processHwRegBaseAddr;
249 g_testHwEnvBaseAddr = processMap->processHwEnvBaseAddr;
250
251 return 0;
252 end_with_error:
253 TestMunMapProcessAddrs(processMap);
254 return 1;
255
256 }
257
258
259 /*
260 * @brief This function
261 *
262 * @param[in]
263 *
264 * @param[out]
265 *
266 * @return void -
267
268 */
TestMunMapProcessAddrs(ProcessMappingArea_t * processMap)269 void TestMunMapProcessAddrs(ProcessMappingArea_t *processMap)
270 {
271
272 if (processMap == NULL) {
273 TEST_PRINTF_ERROR("processMap == NULL\n");
274 return;
275 }
276 if (map_used > 0) {
277 map_used--;
278 } else {
279 TEST_PRINTF_ERROR("nothing is mapped. returning...\n");
280 return;
281 }
282 if (map_used > 0) {
283 TEST_PRINTF_ERROR("waiting for others to Munmap before closing...\n");
284 return;
285 }
286 if (processMap->processHwRegBaseAddr != 0) {
287 munmap((void *)processMap->processHwRegBaseAddr, REG_MAP_AREA_LEN);
288 }
289 if (processMap->processHwEnvBaseAddr != 0) {
290 munmap((void *)processMap->processHwEnvBaseAddr, REG_MAP_AREA_LEN);
291 }
292 if (processMap->processHwRndCtxBaseAddr != 0) {
293 munmap((void *)processMap->processHwRndCtxBaseAddr, processMap->userSpaceSize);
294 }
295 #ifdef DX_PLAT_JUNO
296 close(userSpaceFd);
297 #endif
298 close(processHwFd);
299 memset((uint8_t *)processMap, 0, sizeof(ProcessMappingArea_t));
300 g_testHwRegBaseAddr = 0;
301 g_testHwEnvBaseAddr = 0;
302 userSpaceFd = 0;
303 processHwFd = 0;
304 }
305
306
307 // map the REE CC HW base, to write to some registers to enable TEE works
TestMapRee(void)308 unsigned int TestMapRee(void)
309 {
310 //TEST_PRINTF("about to open\n");
311 g_reeHwFd = open("/dev/mem", O_RDWR|O_SYNC);
312 if(g_reeHwFd < 0) {
313 TEST_PRINTF_ERROR("Error: Can not open /dev/mem\n");
314 goto end_error;
315 }
316 TEST_PRINTF("about to mmap for DX_REE_BASE_CC 0x%lx", (unsigned long)DX_REE_BASE_CC);
317 g_testHwReeRegBaseAddr = (unsigned long)mmap(NULL, REG_MAP_AREA_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, g_reeHwFd, DX_REE_BASE_CC);
318 if (!VALID_MAPPED_ADDR(g_testHwReeRegBaseAddr)) {
319 TEST_PRINTF_ERROR("Error: mmap failed for g_testHwReeRegBaseAddr\n");
320 goto end_error;
321 }
322 TEST_PRINTF("g_testHwReeRegBaseAddr = 0x%lx\n", (unsigned long)g_testHwReeRegBaseAddr);
323 return 0;
324
325 end_error:
326 TestMunMapRee();
327
328 return 1;
329
330 }
331
332
333 /*
334 * @brief This function
335 *
336 * @param[in]
337 *
338 * @param[out]
339 *
340 * @return void -
341
342 */
TestMunMapRee(void)343 void TestMunMapRee(void)
344 {
345
346
347 if (g_testHwReeRegBaseAddr != 0) {
348 munmap((void *)g_testHwReeRegBaseAddr, REG_MAP_AREA_LEN);
349 }
350 g_testHwReeRegBaseAddr = 0;
351
352 if (g_reeHwFd > 0) {
353 close(g_reeHwFd);
354 }
355 g_reeHwFd = 0;
356 }
357
358
359