1 /*************************************************************************/ /*!
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
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 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.
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.
92 IMG_UINT32 ui32Log2PageSizeBytes;
93 struct page **apsPageArray;
94 IMG_UINT64 ui64NumPages;
96 PHYS_HEAP *psTDMetaCodePhysHeap;
97 IMG_HANDLE hPDumpAllocInfo;
98 } sTDMetaCodePageList;
101 _FreeTDMetaCodePageContainer(void *pvPagecontainer)
103 sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) 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->psTDMetaCodePhysHeap);
125 PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
127 OSFreeMem(psPageContainer);
131 PMRSysPhysAddrTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
132 IMG_UINT32 ui32NumOfPages,
133 IMG_DEVMEM_OFFSET_T *puiOffset,
135 IMG_DEV_PHYADDR *psDevPAddr)
137 sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPriv;
138 IMG_UINT64 ui64PageNum;
141 for (idx=0; idx < ui32NumOfPages; idx++)
145 IMG_UINT32 ui32PageOffset;
147 ui64PageNum = puiOffset[idx] >> psPageContainer->ui32Log2PageSizeBytes;
148 ui32PageOffset = puiOffset[idx] - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
149 PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
151 psDevPAddr[idx].uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
160 PMRFinalizeTDMetaCode(PMR_IMPL_PRIVDATA pvPriv)
162 _FreeTDMetaCodePageContainer((void *) pvPriv);
167 PMRReadBytesTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
168 IMG_DEVMEM_OFFSET_T uiOffset,
171 IMG_SIZE_T *puiNumBytes)
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;
184 uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
185 uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
186 uiReadBytes = uiPageSize - uiReadOffset;
188 if(uiReadBytes > uiBufSz)
190 uiReadBytes = uiBufSz;
193 pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
194 PVR_ASSERT(pvMapping);
195 memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
196 kunmap(psPageContainer->apsPageArray[uiPageIndex]);
198 uiBufSz -= uiReadBytes;
199 pcBuffer += uiReadBytes;
200 *puiNumBytes += uiReadBytes;
202 uiOffset += uiReadBytes;
208 PMRKernelMapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
211 void **ppvKernelAddressOut,
212 IMG_HANDLE *phHandleOut,
215 sTDMetaCodePageList *psPageContainer;
218 psPageContainer = pvPriv;
220 pvAddress = vm_map_ram(psPageContainer->apsPageArray,
221 psPageContainer->ui64NumPages,
227 return PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
230 *ppvKernelAddressOut = pvAddress + uiOffset;
231 *phHandleOut = pvAddress;
237 PMRKernelUnmapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
240 sTDMetaCodePageList *psPageContainer;
241 psPageContainer = pvPriv;
242 vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
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
258 _AllocTDMetaCodePageContainer(IMG_UINT64 ui64NumPages,
259 IMG_UINT32 uiLog2PageSize,
260 PHYS_HEAP *psTDMetaCodePhysHeap,
261 void **ppvPageContainer)
264 PVRSRV_ERROR eStatus = PVRSRV_OK;
265 sTDMetaCodePageList *psPageContainer;
267 psPageContainer = OSAllocMem(sizeof(sTDMetaCodePageList));
270 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
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)
279 eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
282 for(i = 0; i < ui64NumPages; i++)
284 psPageContainer->apsPageArray[i] = IMG_NULL;
287 for(i = 0; i < ui64NumPages; i++)
289 psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
290 if(! psPageContainer->apsPageArray[i])
292 eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
297 *ppvPageContainer = psPageContainer;
301 _FreeTDMetaCodePageContainer((void *) psPageContainer);
302 *ppvPageContainer = IMG_NULL;
307 PhysmemNewTDMetaCodePMR(PVRSRV_DEVICE_NODE *psDevNode,
308 IMG_DEVMEM_SIZE_T uiSize,
309 IMG_UINT32 uiLog2PageSize,
310 PVRSRV_MEMALLOCFLAGS_T uiFlags,
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;
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));
327 /* get the physical heap for TD Meta Code */
328 psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
329 if(! psRGXData->bHasTDMetaCodePhysHeap)
331 PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
332 eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
335 eStatus = PhysHeapAcquire(psRGXData->uiTDMetaCodePhysHeapID,
336 &psTDMetaCodePhysHeap);
342 /* allocate and initialize the page container structure */
343 eStatus = _AllocTDMetaCodePageContainer(ui64NumPages,
345 psTDMetaCodePhysHeap,
346 (void *)&psPageContainer);
352 /* wrap the container in a PMR */
353 eStatus = PMRCreatePMR(psTDMetaCodePhysHeap,
354 ui64NumPages * uiPageSize,
355 ui64NumPages * uiPageSize,
362 &sTDMETACodePMRFuncTab,
363 (void *)psPageContainer,
368 #if defined(PVR_RI_DEBUG)
370 RIWritePMREntryKM (*ppsPMRPtr,
371 sizeof("TD META Code"),
373 (ui64NumPages * uiPageSize));
377 /* this is needed when the allocation is finalized and we need to free it. */
378 psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;