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