RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / server / env / linux / physmem_tdmetacode_linux.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Implementation of PMR functions for Trusted Device firmware code memory
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Part of the memory management.  This module is responsible for
6                 implementing the function callbacks for physical memory borrowed
7                 from that normally managed by the operating system.
8 @License        Dual MIT/GPLv2
9
10 The contents of this file are subject to the MIT license as set out below.
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
21
22 Alternatively, the contents of this file may be used under the terms of
23 the GNU General Public License Version 2 ("GPL") in which case the provisions
24 of GPL are applicable instead of those above.
25
26 If you wish to allow use of your version of this file only under the terms of
27 GPL, and not to allow others to use your version of this file under the terms
28 of the MIT license, indicate your decision by deleting the provisions above
29 and replace them with the notice and other provisions required by GPL as set
30 out in the file called "GPL-COPYING" included in this distribution. If you do
31 not delete the provisions above, a recipient may use your version of this file
32 under the terms of either the MIT license or GPL.
33
34 This License is also included in this distribution in the file called
35 "MIT-COPYING".
36
37 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
38 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
39 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
40 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
41 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
42 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
43 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 */ /**************************************************************************/
45
46 /* include5/ */
47 #include "img_types.h"
48 #include "pvr_debug.h"
49 #include "pvrsrv_error.h"
50 #include "pvrsrv_memallocflags.h"
51
52 /* services/server/include/ */
53 #include "allocmem.h"
54 #include "osfunc.h"
55 #include "pdump_physmem.h"
56 #include "pdump_km.h"
57 #include "pmr.h"
58 #include "pmr_impl.h"
59
60 /* ourselves */
61 #include "physmem_osmem.h"
62
63 #if defined(PVR_RI_DEBUG)
64 #include "ri_server.h"
65 #endif
66
67 #include <linux/slab.h>
68 #include <linux/highmem.h>
69 #include <linux/mm_types.h>
70 #include <linux/vmalloc.h>
71 #include <linux/gfp.h>
72 #include <linux/sched.h>
73 #include <asm/io.h>
74 #if defined(CONFIG_X86)
75 #include <asm/cacheflush.h>
76 #endif
77
78 #include "rgxdevice.h"
79
80 /* This is a placeholder implementation of a PMR factory to wrap allocations into
81    the protected META code regions. It has been consciously heavily inspired by the
82    standard osmem PMR factory to supply dummy functionality. Most things here will
83    change in a real implementation.
84
85    Your starting point for re-implementing this module should be by inspecting the 
86    sTDMETACodePMRFuncTab structure below and determining which callbacks you need
87    to implement for your system.
88 */
89
90 typedef struct {
91         void *token;
92         IMG_UINT32 ui32Log2PageSizeBytes;
93         struct page **apsPageArray;
94         IMG_UINT64 ui64NumPages;
95
96         PHYS_HEAP *psTDMetaCodePhysHeap;
97     IMG_HANDLE hPDumpAllocInfo;
98 } sTDMetaCodePageList;
99
100 static void
101 _FreeTDMetaCodePageContainer(void *pvPagecontainer)
102 {
103         sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPagecontainer;
104
105         if(! psPageContainer)
106         {
107                 return;
108         }
109
110         if(psPageContainer->apsPageArray)
111         {
112                 IMG_UINT64 i;
113                 for(i = 0; i < psPageContainer->ui64NumPages; i++)
114                 {
115                         if(psPageContainer->apsPageArray[i])
116                         {
117                                 __free_page(psPageContainer->apsPageArray[i]);
118                         }
119                 }
120                 OSFreeMem(psPageContainer->apsPageArray);
121         }
122
123         PhysHeapRelease(psPageContainer->psTDMetaCodePhysHeap);
124
125     PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
126
127     OSFreeMem(psPageContainer);
128 }
129
130 static PVRSRV_ERROR
131 PMRSysPhysAddrTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
132                          IMG_UINT32 ui32NumOfPages,
133                          IMG_DEVMEM_OFFSET_T *puiOffset,
134                                                  IMG_BOOL *pbValid,
135                          IMG_DEV_PHYADDR *psDevPAddr)
136 {
137         sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPriv;
138         IMG_UINT64 ui64PageNum;
139         IMG_UINT32 idx;
140
141         for (idx=0; idx < ui32NumOfPages; idx++)
142         {
143                 if (pbValid[idx])
144                 {
145                         IMG_UINT32 ui32PageOffset;
146
147                         ui64PageNum = puiOffset[idx] >> psPageContainer->ui32Log2PageSizeBytes;
148                         ui32PageOffset = puiOffset[idx] - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
149                         PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
150
151                         psDevPAddr[idx].uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
152                 }
153         }
154         
155         return PVRSRV_OK;
156 }
157
158
159 static PVRSRV_ERROR
160 PMRFinalizeTDMetaCode(PMR_IMPL_PRIVDATA pvPriv)
161 {
162         _FreeTDMetaCodePageContainer((void *) pvPriv);
163         return PVRSRV_OK;
164 }
165
166 static PVRSRV_ERROR
167 PMRReadBytesTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
168                        IMG_DEVMEM_OFFSET_T uiOffset,
169                        IMG_UINT8 *pcBuffer,
170                        IMG_SIZE_T uiBufSz,
171                        IMG_SIZE_T *puiNumBytes)
172 {
173         sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPriv;
174     IMG_UINT8 *pvMapping;
175         IMG_UINT32 uiPageSize = 1 << psPageContainer->ui32Log2PageSizeBytes;
176         IMG_UINT32 uiPageIndex;
177         IMG_UINT32 uiReadOffset;
178         IMG_UINT32 uiReadBytes;
179
180         *puiNumBytes = 0;
181         
182         while(uiBufSz)
183         {
184         uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
185                 uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
186                 uiReadBytes = uiPageSize - uiReadOffset;
187
188                 if(uiReadBytes > uiBufSz)
189                 {
190                         uiReadBytes = uiBufSz;
191                 }
192                 
193         pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
194         PVR_ASSERT(pvMapping);
195         memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
196         kunmap(psPageContainer->apsPageArray[uiPageIndex]);
197                 
198                 uiBufSz -= uiReadBytes;
199                 pcBuffer += uiReadBytes;
200                 *puiNumBytes += uiReadBytes;
201
202                 uiOffset += uiReadBytes;
203         }
204     return PVRSRV_OK;
205 }
206
207 static PVRSRV_ERROR
208 PMRKernelMapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
209                        IMG_SIZE_T uiOffset,
210                        IMG_SIZE_T uiSize,
211                        void **ppvKernelAddressOut,
212                        IMG_HANDLE *phHandleOut,
213                        PMR_FLAGS_T ulFlags)
214 {
215     sTDMetaCodePageList *psPageContainer;
216     void *pvAddress;
217
218     psPageContainer = pvPriv;
219
220         pvAddress = vm_map_ram(psPageContainer->apsPageArray,
221                                                    psPageContainer->ui64NumPages,
222                                                    -1,
223                                                    PAGE_KERNEL);
224
225         if(! pvAddress)
226         {
227                 return PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
228         }
229
230     *ppvKernelAddressOut = pvAddress + uiOffset;
231     *phHandleOut = pvAddress;
232
233     return PVRSRV_OK;
234 }
235
236 static void
237 PMRKernelUnmapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
238                          IMG_HANDLE hHandle)
239 {
240     sTDMetaCodePageList *psPageContainer;
241     psPageContainer = pvPriv;
242     vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
243 }
244
245 static PMR_IMPL_FUNCTAB sTDMETACodePMRFuncTab = {
246         .pfnLockPhysAddresses = IMG_NULL,           /* pages are always available in these PMRs */
247         .pfnUnlockPhysAddresses = IMG_NULL,         /* as above */
248         .pfnDevPhysAddr = PMRSysPhysAddrTDMetaCode,
249         .pfnPDumpSymbolicAddr = IMG_NULL,           /* nothing special needed */
250         .pfnAcquireKernelMappingData = PMRKernelMapTDMetaCode,
251         .pfnReleaseKernelMappingData = PMRKernelUnmapTDMetaCode,
252         .pfnReadBytes = PMRReadBytesTDMetaCode,
253         .pfnFinalize = PMRFinalizeTDMetaCode
254 };
255
256
257 static PVRSRV_ERROR
258 _AllocTDMetaCodePageContainer(IMG_UINT64 ui64NumPages,
259                               IMG_UINT32 uiLog2PageSize,
260                               PHYS_HEAP *psTDMetaCodePhysHeap,
261                               void **ppvPageContainer)
262 {
263         IMG_UINT64 i;
264         PVRSRV_ERROR eStatus = PVRSRV_OK;
265         sTDMetaCodePageList *psPageContainer;
266
267         psPageContainer = OSAllocMem(sizeof(sTDMetaCodePageList));
268         if(!psPageContainer)
269         {
270                 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
271                 goto fail;
272         }
273         psPageContainer->ui32Log2PageSizeBytes = uiLog2PageSize;
274         psPageContainer->ui64NumPages = ui64NumPages;
275         psPageContainer->psTDMetaCodePhysHeap = psTDMetaCodePhysHeap;
276         psPageContainer->apsPageArray = OSAllocMem(ui64NumPages * sizeof(psPageContainer->apsPageArray[0]));
277         if(!psPageContainer->apsPageArray)
278         {
279                 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
280                 goto fail;
281         }
282         for(i = 0; i < ui64NumPages; i++)
283         {
284                 psPageContainer->apsPageArray[i] = IMG_NULL;
285         }
286
287         for(i = 0; i < ui64NumPages; i++)
288         {
289                 psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
290                 if(! psPageContainer->apsPageArray[i])
291                 {
292                         eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
293                         goto fail;
294                 }
295         }
296
297         *ppvPageContainer = psPageContainer;
298         return eStatus;
299
300 fail:
301         _FreeTDMetaCodePageContainer((void *) psPageContainer);
302         *ppvPageContainer = IMG_NULL;
303         return eStatus;
304 }
305
306 PVRSRV_ERROR
307 PhysmemNewTDMetaCodePMR(PVRSRV_DEVICE_NODE *psDevNode,
308                         IMG_DEVMEM_SIZE_T uiSize,
309                         IMG_UINT32 uiLog2PageSize,
310                         PVRSRV_MEMALLOCFLAGS_T uiFlags,
311                         PMR **ppsPMRPtr)
312 {
313         sTDMetaCodePageList *psPageContainer = IMG_NULL;
314         IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
315         IMG_UINT64 ui64NumPages = (uiSize >> uiLog2PageSize) + ((uiSize & (uiPageSize-1)) != 0);
316         PVRSRV_ERROR eStatus;
317         PHYS_HEAP *psTDMetaCodePhysHeap;
318         IMG_BOOL bMappingTable = IMG_TRUE;
319     IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
320         RGX_DATA *psRGXData;
321
322     IMG_UINT32 uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
323     /* check no significant bits were lost in cast due to different
324        bit widths for flags */
325     PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
326         
327         /* get the physical heap for TD Meta Code */
328         psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
329         if(! psRGXData->bHasTDMetaCodePhysHeap)
330         {
331                 PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
332                 eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
333                 goto fail;
334         }
335         eStatus = PhysHeapAcquire(psRGXData->uiTDMetaCodePhysHeapID,
336                                   &psTDMetaCodePhysHeap);
337         if(eStatus)
338         {
339                 goto fail;
340         }
341
342         /* allocate and initialize the page container structure */
343         eStatus = _AllocTDMetaCodePageContainer(ui64NumPages,
344                                                 uiLog2PageSize,
345                                                 psTDMetaCodePhysHeap,
346                                                 (void *)&psPageContainer);
347         if(eStatus)
348         {
349                 goto fail;
350         }
351
352         /* wrap the container in a PMR */
353     eStatus = PMRCreatePMR(psTDMetaCodePhysHeap,
354                            ui64NumPages * uiPageSize,
355                            ui64NumPages * uiPageSize,
356                            1,
357                            1,
358                            &bMappingTable,
359                            uiLog2PageSize,
360                            uiPMRFlags,
361                            "PMRTDMETACODE",
362                            &sTDMETACodePMRFuncTab,
363                            (void *)psPageContainer,
364                            ppsPMRPtr,
365                            &hPDumpAllocInfo,
366                            IMG_FALSE);
367         
368 #if defined(PVR_RI_DEBUG)
369         {
370                 RIWritePMREntryKM (*ppsPMRPtr,
371                                                    sizeof("TD META Code"),
372                                                    "TD META Code",
373                                                    (ui64NumPages * uiPageSize));
374         }
375 #endif
376
377         /* this is needed when the allocation is finalized and we need to free it. */
378         psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;
379
380         return eStatus;
381
382         /* error cleanup */
383
384 fail:
385         return eStatus;
386 }