RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / server / env / linux / physmem_tdsecbuf_linux.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Implementation of PMR functions for Trusted Device secure buffers
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 secure buffer 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    sTDSecureBufPMRFuncTab 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 *psTDSecureBufPhysHeap;
97     IMG_HANDLE hPDumpAllocInfo;
98 } sTDSecureBufPageList;
99
100 static void
101 _FreeTDSecureBufPageContainer(void *pvPagecontainer)
102 {
103         sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) 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->psTDSecureBufPhysHeap);
124
125     PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
126
127         OSFreeMem(psPageContainer);
128 }
129
130 static PVRSRV_ERROR
131 PMRSysPhysAddrTDSecureBuf(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         sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPriv;
138         IMG_UINT32 ui32PageOffset;
139         IMG_UINT64 ui64PageNum;
140         IMG_UINT32 idx;
141
142         for (idx=0; idx < ui32NumOfPages; idx++)
143         {
144                 if (pbValid[idx])
145                 {
146                         ui64PageNum = puiOffset[idx] >> psPageContainer->ui32Log2PageSizeBytes;
147                         ui32PageOffset = puiOffset[idx] - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
148                         PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
149
150                         psDevPAddr[idx].uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
151                 }
152         }
153
154         return PVRSRV_OK;
155 }
156
157
158 static PVRSRV_ERROR
159 PMRFinalizeTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv)
160 {
161         _FreeTDSecureBufPageContainer((void *) pvPriv);
162         return PVRSRV_OK;
163 }
164
165 static PVRSRV_ERROR
166 PMRReadBytesTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
167                        IMG_DEVMEM_OFFSET_T uiOffset,
168                        IMG_UINT8 *pcBuffer,
169                        IMG_SIZE_T uiBufSz,
170                        IMG_SIZE_T *puiNumBytes)
171 {
172         sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPriv;
173     IMG_UINT8 *pvMapping;
174         IMG_UINT32 uiPageSize = 1 << psPageContainer->ui32Log2PageSizeBytes;
175         IMG_UINT32 uiPageIndex;
176         IMG_UINT32 uiReadOffset;
177         IMG_UINT32 uiReadBytes;
178
179         *puiNumBytes = 0;
180         
181         while(uiBufSz)
182         {
183         uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
184                 uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
185                 uiReadBytes = uiPageSize - uiReadOffset;
186
187                 if(uiReadBytes > uiBufSz)
188                 {
189                         uiReadBytes = uiBufSz;
190                 }
191                 
192         pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
193         PVR_ASSERT(pvMapping);
194         memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
195         kunmap(psPageContainer->apsPageArray[uiPageIndex]);
196                 
197                 uiBufSz -= uiReadBytes;
198                 pcBuffer += uiReadBytes;
199                 *puiNumBytes += uiReadBytes;
200
201                 uiOffset += uiReadBytes;
202         }
203     return PVRSRV_OK;
204 }
205
206 static PVRSRV_ERROR
207 PMRKernelMapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
208                        IMG_SIZE_T uiOffset,
209                        IMG_SIZE_T uiSize,
210                        void **ppvKernelAddressOut,
211                        IMG_HANDLE *phHandleOut,
212                        PMR_FLAGS_T ulFlags)
213 {
214     sTDSecureBufPageList *psPageContainer;
215     void *pvAddress;
216
217     psPageContainer = pvPriv;
218
219         pvAddress = vm_map_ram(psPageContainer->apsPageArray,
220                                                    psPageContainer->ui64NumPages,
221                                                    -1,
222                                                    PAGE_KERNEL);
223
224         if(! pvAddress)
225         {
226                 return PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
227         }
228
229     *ppvKernelAddressOut = pvAddress + uiOffset;
230     *phHandleOut = pvAddress;
231
232     return PVRSRV_OK;
233 }
234
235 static void
236 PMRKernelUnmapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
237                          IMG_HANDLE hHandle)
238 {
239     sTDSecureBufPageList *psPageContainer;
240     psPageContainer = pvPriv;
241     vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
242 }
243
244 static PMR_IMPL_FUNCTAB sTDSecureBufPMRFuncTab = {
245         .pfnLockPhysAddresses = IMG_NULL,           /* pages are always available in these PMRs */
246         .pfnUnlockPhysAddresses = IMG_NULL,         /* as above */
247         .pfnDevPhysAddr = PMRSysPhysAddrTDSecureBuf,
248         .pfnPDumpSymbolicAddr = IMG_NULL,           /* nothing special needed */
249         .pfnAcquireKernelMappingData = PMRKernelMapTDSecureBuf,
250         .pfnReleaseKernelMappingData = PMRKernelUnmapTDSecureBuf,
251         .pfnReadBytes = PMRReadBytesTDSecureBuf,
252         .pfnFinalize = PMRFinalizeTDSecureBuf
253 };
254
255
256 static PVRSRV_ERROR
257 _AllocTDSecureBufPageContainer(IMG_UINT64 ui64NumPages,
258                               IMG_UINT32 uiLog2PageSize,
259                               PHYS_HEAP *psTDSecureBufPhysHeap,
260                               void **ppvPageContainer)
261 {
262         IMG_UINT64 i;
263         PVRSRV_ERROR eStatus = PVRSRV_OK;
264         sTDSecureBufPageList *psPageContainer;
265
266         psPageContainer = OSAllocMem(sizeof(sTDSecureBufPageList));
267         if(!psPageContainer)
268         {
269                 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
270                 goto fail;
271         }
272         psPageContainer->ui32Log2PageSizeBytes = uiLog2PageSize;
273         psPageContainer->ui64NumPages = ui64NumPages;
274         psPageContainer->psTDSecureBufPhysHeap = psTDSecureBufPhysHeap;
275         psPageContainer->apsPageArray = OSAllocMem(ui64NumPages * sizeof(psPageContainer->apsPageArray[0]));
276         if(!psPageContainer->apsPageArray)
277         {
278                 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
279                 goto fail;
280         }
281         for(i = 0; i < ui64NumPages; i++)
282         {
283                 psPageContainer->apsPageArray[i] = IMG_NULL;
284         }
285
286         for(i = 0; i < ui64NumPages; i++)
287         {
288                 psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
289                 if(! psPageContainer->apsPageArray[i])
290                 {
291                         eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
292                         goto fail;
293                 }
294         }
295
296         *ppvPageContainer = psPageContainer;
297         return eStatus;
298
299 fail:
300         _FreeTDSecureBufPageContainer((void *) psPageContainer);
301         *ppvPageContainer = IMG_NULL;
302         return eStatus;
303 }
304
305 PVRSRV_ERROR
306 PhysmemNewTDSecureBufPMR(PVRSRV_DEVICE_NODE *psDevNode,
307                         IMG_DEVMEM_SIZE_T uiSize,
308                         IMG_UINT32 uiLog2PageSize,
309                         PVRSRV_MEMALLOCFLAGS_T uiFlags,
310                         PMR **ppsPMRPtr)
311 {
312         sTDSecureBufPageList *psPageContainer = IMG_NULL;
313         IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
314         IMG_UINT64 ui64NumPages = (uiSize >> uiLog2PageSize) + ((uiSize & (uiPageSize-1)) != 0);
315         PVRSRV_ERROR eStatus;
316         PHYS_HEAP *psTDSecureBufPhysHeap;
317         IMG_BOOL bMappingTable = IMG_TRUE;
318         IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
319         RGX_DATA *psRGXData;
320
321     IMG_UINT32 uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
322     /* check no significant bits were lost in cast due to different
323        bit widths for flags */
324     PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
325         
326         /* get the physical heap for TD secure buffers */
327         psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
328         if(! psRGXData->bHasTDSecureBufPhysHeap)
329         {
330                 PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
331                 eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
332                 goto fail;
333         }
334         eStatus = PhysHeapAcquire(psRGXData->uiTDSecureBufPhysHeapID,
335                                   &psTDSecureBufPhysHeap);
336         if(eStatus)
337         {
338                 goto fail;
339         }
340
341         /* allocate and initialize the page container structure */
342         eStatus = _AllocTDSecureBufPageContainer(ui64NumPages,
343                                                 uiLog2PageSize,
344                                                 psTDSecureBufPhysHeap,
345                                                 (void *)&psPageContainer);
346         if(eStatus)
347         {
348                 goto fail;
349         }
350
351         /* wrap the container in a PMR */
352     eStatus = PMRCreatePMR(psTDSecureBufPhysHeap,
353                            ui64NumPages * uiPageSize,
354                            ui64NumPages * uiPageSize,
355                            1,
356                            1,
357                            &bMappingTable,
358                            uiLog2PageSize,
359                            uiPMRFlags,
360                            "PMRTDSECUREBUF",
361                            &sTDSecureBufPMRFuncTab,
362                            (void *)psPageContainer,
363                            ppsPMRPtr,
364                            &hPDumpAllocInfo,
365                            IMG_FALSE);
366         
367 #if defined(PVR_RI_DEBUG)
368         {
369                 RIWritePMREntryKM (*ppsPMRPtr,
370                                                    sizeof("TD Secure Buffer"),
371                                                    "TD Secure Buffer",
372                                                    (ui64NumPages * uiPageSize));
373         }
374 #endif
375
376         /* this is needed when the allocation is finalized and we need to free it. */
377         psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;
378
379         return eStatus;
380
381         /* error cleanup */
382
383 fail:
384         return eStatus;
385 }