1 /*************************************************************************/ /*!
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
10 The contents of this file are subject to the MIT license as set out below.
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:
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
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.
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.
34 This License is also included in this distribution in the file called
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 */ /**************************************************************************/
47 #include "img_types.h"
48 #include "pvr_debug.h"
49 #include "pvrsrv_error.h"
50 #include "pvrsrv_memallocflags.h"
52 /* services/server/include/ */
55 #include "pdump_physmem.h"
61 #include "physmem_osmem.h"
63 #if defined(PVR_RI_DEBUG)
64 #include "ri_server.h"
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>
74 #if defined(CONFIG_X86)
75 #include <asm/cacheflush.h>
78 #include "rgxdevice.h"
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.
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.
92 IMG_UINT32 ui32Log2PageSizeBytes;
93 struct page **apsPageArray;
94 IMG_UINT64 ui64NumPages;
96 PHYS_HEAP *psTDSecureBufPhysHeap;
97 IMG_HANDLE hPDumpAllocInfo;
98 } sTDSecureBufPageList;
101 _FreeTDSecureBufPageContainer(void *pvPagecontainer)
103 sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPagecontainer;
105 if(! psPageContainer)
110 if(psPageContainer->apsPageArray)
113 for(i = 0; i < psPageContainer->ui64NumPages; i++)
115 if(psPageContainer->apsPageArray[i])
117 __free_page(psPageContainer->apsPageArray[i]);
120 OSFreeMem(psPageContainer->apsPageArray);
123 PhysHeapRelease(psPageContainer->psTDSecureBufPhysHeap);
125 PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
127 OSFreeMem(psPageContainer);
131 PMRSysPhysAddrTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
132 IMG_UINT32 ui32NumOfPages,
133 IMG_DEVMEM_OFFSET_T *puiOffset,
135 IMG_DEV_PHYADDR *psDevPAddr)
137 sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPriv;
138 IMG_UINT32 ui32PageOffset;
139 IMG_UINT64 ui64PageNum;
142 for (idx=0; idx < ui32NumOfPages; idx++)
146 ui64PageNum = puiOffset[idx] >> psPageContainer->ui32Log2PageSizeBytes;
147 ui32PageOffset = puiOffset[idx] - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
148 PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
150 psDevPAddr[idx].uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
159 PMRFinalizeTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv)
161 _FreeTDSecureBufPageContainer((void *) pvPriv);
166 PMRReadBytesTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
167 IMG_DEVMEM_OFFSET_T uiOffset,
170 IMG_SIZE_T *puiNumBytes)
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;
183 uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
184 uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
185 uiReadBytes = uiPageSize - uiReadOffset;
187 if(uiReadBytes > uiBufSz)
189 uiReadBytes = uiBufSz;
192 pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
193 PVR_ASSERT(pvMapping);
194 memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
195 kunmap(psPageContainer->apsPageArray[uiPageIndex]);
197 uiBufSz -= uiReadBytes;
198 pcBuffer += uiReadBytes;
199 *puiNumBytes += uiReadBytes;
201 uiOffset += uiReadBytes;
207 PMRKernelMapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
210 void **ppvKernelAddressOut,
211 IMG_HANDLE *phHandleOut,
214 sTDSecureBufPageList *psPageContainer;
217 psPageContainer = pvPriv;
219 pvAddress = vm_map_ram(psPageContainer->apsPageArray,
220 psPageContainer->ui64NumPages,
226 return PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
229 *ppvKernelAddressOut = pvAddress + uiOffset;
230 *phHandleOut = pvAddress;
236 PMRKernelUnmapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
239 sTDSecureBufPageList *psPageContainer;
240 psPageContainer = pvPriv;
241 vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
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
257 _AllocTDSecureBufPageContainer(IMG_UINT64 ui64NumPages,
258 IMG_UINT32 uiLog2PageSize,
259 PHYS_HEAP *psTDSecureBufPhysHeap,
260 void **ppvPageContainer)
263 PVRSRV_ERROR eStatus = PVRSRV_OK;
264 sTDSecureBufPageList *psPageContainer;
266 psPageContainer = OSAllocMem(sizeof(sTDSecureBufPageList));
269 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
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)
278 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
281 for(i = 0; i < ui64NumPages; i++)
283 psPageContainer->apsPageArray[i] = IMG_NULL;
286 for(i = 0; i < ui64NumPages; i++)
288 psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
289 if(! psPageContainer->apsPageArray[i])
291 eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
296 *ppvPageContainer = psPageContainer;
300 _FreeTDSecureBufPageContainer((void *) psPageContainer);
301 *ppvPageContainer = IMG_NULL;
306 PhysmemNewTDSecureBufPMR(PVRSRV_DEVICE_NODE *psDevNode,
307 IMG_DEVMEM_SIZE_T uiSize,
308 IMG_UINT32 uiLog2PageSize,
309 PVRSRV_MEMALLOCFLAGS_T uiFlags,
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;
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));
326 /* get the physical heap for TD secure buffers */
327 psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
328 if(! psRGXData->bHasTDSecureBufPhysHeap)
330 PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
331 eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
334 eStatus = PhysHeapAcquire(psRGXData->uiTDSecureBufPhysHeapID,
335 &psTDSecureBufPhysHeap);
341 /* allocate and initialize the page container structure */
342 eStatus = _AllocTDSecureBufPageContainer(ui64NumPages,
344 psTDSecureBufPhysHeap,
345 (void *)&psPageContainer);
351 /* wrap the container in a PMR */
352 eStatus = PMRCreatePMR(psTDSecureBufPhysHeap,
353 ui64NumPages * uiPageSize,
354 ui64NumPages * uiPageSize,
361 &sTDSecureBufPMRFuncTab,
362 (void *)psPageContainer,
367 #if defined(PVR_RI_DEBUG)
369 RIWritePMREntryKM (*ppsPMRPtr,
370 sizeof("TD Secure Buffer"),
372 (ui64NumPages * uiPageSize));
376 /* this is needed when the allocation is finalized and we need to free it. */
377 psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;