1 /*************************************************************************/ /*!
3 @Title Device Memory Management
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Front End (nominally Client side part, but now invokable
6 from server too) of device memory management
7 @License Dual MIT/GPLv2
9 The contents of this file are subject to the MIT license as set out below.
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
33 This License is also included in this distribution in the file called
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
45 #include "devicemem.h"
46 #include "img_types.h"
47 #include "pvr_debug.h"
48 #include "pvrsrv_error.h"
52 #include "devicemem_mmap.h"
53 #include "devicemem_utils.h"
54 #include "client_mm_bridge.h"
56 #include "devicemem_pdump.h"
58 #if defined(PVR_RI_DEBUG)
59 #include "client_ri_bridge.h"
61 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
62 #include "client_devicememhistory_bridge.h"
65 #if defined(__KERNEL__)
68 #include "linux/kernel.h"
73 * Should be initialised to the correct value at driver init time.
74 * Use macros from devicemem.h to access from outside this module.
76 IMG_UINT32 g_uiLog2PageSize = 0;
79 _Mapping_Export(DEVMEM_IMPORT *psImport,
80 DEVMEM_EXPORTHANDLE *phPMRExportHandlePtr,
81 DEVMEM_EXPORTKEY *puiExportKeyPtr,
82 DEVMEM_SIZE_T *puiSize,
83 DEVMEM_LOG2ALIGN_T *puiLog2Contig)
85 /* Gets an export handle and key for the PMR used for this mapping */
86 /* Can only be done if there are no suballocations for this mapping */
89 DEVMEM_EXPORTHANDLE hPMRExportHandle;
90 DEVMEM_EXPORTKEY uiExportKey;
91 IMG_DEVMEM_SIZE_T uiSize;
92 IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig;
94 if (psImport == IMG_NULL)
96 eError = PVRSRV_ERROR_INVALID_PARAMS;
100 if (!psImport->bExportable)
102 eError = PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION;
106 eError = BridgePMRExportPMR(psImport->hBridge,
112 if (eError != PVRSRV_OK)
117 PVR_ASSERT(uiSize == psImport->uiSize);
119 *phPMRExportHandlePtr = hPMRExportHandle;
120 *puiExportKeyPtr = uiExportKey;
122 *puiLog2Contig = uiLog2Contig;
127 error exit paths follow
133 PVR_ASSERT(eError != PVRSRV_OK);
139 _Mapping_Unexport(DEVMEM_IMPORT *psImport,
140 DEVMEM_EXPORTHANDLE hPMRExportHandle)
144 PVR_ASSERT (psImport != IMG_NULL);
146 eError = BridgePMRUnexportPMR(psImport->hBridge,
148 PVR_ASSERT(eError == PVRSRV_OK);
151 /*****************************************************************************
152 * Sub allocation internals *
153 *****************************************************************************/
156 _AllocateDeviceMemory(IMG_HANDLE hBridge,
157 IMG_HANDLE hDeviceNode,
158 IMG_UINT32 uiLog2Quantum,
159 IMG_DEVMEM_SIZE_T uiSize,
160 IMG_DEVMEM_SIZE_T uiChunkSize,
161 IMG_UINT32 ui32NumPhysChunks,
162 IMG_UINT32 ui32NumVirtChunks,
163 IMG_BOOL *pabMappingTable,
164 IMG_DEVMEM_ALIGN_T uiAlign,
165 DEVMEM_FLAGS_T uiFlags,
166 IMG_BOOL bExportable,
167 DEVMEM_IMPORT **ppsImport)
169 DEVMEM_IMPORT *psImport;
170 DEVMEM_FLAGS_T uiPMRFlags;
174 eError = _DevmemImportStructAlloc(hBridge,
177 if (eError != PVRSRV_OK)
182 /* Check the size is a multiple of the quantum */
183 PVR_ASSERT((uiSize & ((1ULL<<uiLog2Quantum)-1)) == 0);
185 /* Pass only the PMR flags down */
186 uiPMRFlags = uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK;
188 eError = BridgePhysmemNewRamBackedPMR(hBridge,
198 if (eError != PVRSRV_OK)
200 /* Our check above should have ensured this the "not page
201 multiple" error never happens */
202 PVR_ASSERT(eError != PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE);
207 _DevmemImportStructInit(psImport,
213 *ppsImport = psImport;
217 _DevmemImportDiscard(psImport);
219 PVR_ASSERT(eError != PVRSRV_OK);
225 _FreeDeviceMemory(DEVMEM_IMPORT *psImport)
227 _DevmemImportStructRelease(psImport);
231 _SubAllocImportAlloc(RA_PERARENA_HANDLE hArena,
236 RA_LENGTH_T *puiActualSize,
237 RA_PERISPAN_HANDLE *phImport)
239 /* When suballocations need a new lump of memory, the RA calls
240 back here. Later, in the kernel, we must construct a new PMR
241 and a pairing between the new lump of virtual memory and the
242 PMR (whether or not such PMR is backed by physical memory) */
244 DEVMEM_IMPORT *psImport;
245 IMG_DEVMEM_ALIGN_T uiAlign;
246 DEVMEM_FLAGS_T uiFlags;
248 IMG_BOOL bMappingTable = IMG_TRUE;
250 uiFlags = (DEVMEM_FLAGS_T) _flags;
252 /* Per-arena private handle is, for us, the heap */
255 /* align to the l.s.b. of the size... e.g. 96kiB aligned to
256 32kiB. NB: There is an argument to say that the RA should never
257 ask us for Non-power-of-2 size anyway, but I don't want to make
258 that restriction arbitrarily now */
259 uiAlign = uiSize & ~(uiSize-1);
261 /* The RA should not have invoked us with a size that is not a
262 multiple of the quantum anyway */
263 PVR_ASSERT((uiSize & ((1ULL<<psHeap->uiLog2Quantum)-1)) == 0);
265 eError = _AllocateDeviceMemory(psHeap->psCtx->hBridge,
266 psHeap->psCtx->hDeviceNode,
267 psHeap->uiLog2Quantum,
277 if (eError != PVRSRV_OK)
282 #if defined(PVR_RI_DEBUG)
284 eError = BridgeRIWritePMREntry (psImport->hBridge,
286 sizeof("PMR sub-allocated"),
289 if( eError != PVRSRV_OK)
291 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
296 Suballocations always get mapped into the device was we need to
297 key the RA off something and as we can't export suballocations
298 there is no valid reason to request an allocation an not map it
300 eError = _DevmemImportStructDevMap(psHeap,
303 if (eError != PVRSRV_OK)
308 *puiBase = psImport->sDeviceImport.sDevVAddr.uiAddr;
309 *puiActualSize = uiSize;
310 *phImport = psImport;
315 error exit paths follow
318 _FreeDeviceMemory(psImport);
325 _SubAllocImportFree(RA_PERARENA_HANDLE hArena,
327 RA_PERISPAN_HANDLE hImport)
329 DEVMEM_IMPORT *psImport = hImport;
331 PVR_ASSERT(psImport != IMG_NULL);
332 PVR_ASSERT(hArena == psImport->sDeviceImport.psHeap);
333 PVR_ASSERT(uiBase == psImport->sDeviceImport.sDevVAddr.uiAddr);
335 _DevmemImportStructDevUnmap(psImport);
336 _DevmemImportStructRelease(psImport);
339 /*****************************************************************************
340 * Devmem context internals *
341 *****************************************************************************/
344 _PopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx,
345 IMG_HANDLE hDeviceNode,
346 DEVMEM_HEAPCFGID uiHeapBlueprintID)
349 PVRSRV_ERROR eError2;
350 struct _DEVMEM_HEAP_ **ppsHeapArray;
351 IMG_UINT32 uiNumHeaps;
352 IMG_UINT32 uiHeapsToUnwindOnError;
353 IMG_UINT32 uiHeapIndex;
354 IMG_DEV_VIRTADDR sDevVAddrBase;
355 IMG_CHAR aszHeapName[DEVMEM_HEAPNAME_MAXLENGTH];
356 IMG_DEVMEM_SIZE_T uiHeapLength;
357 IMG_DEVMEM_LOG2ALIGN_T uiLog2DataPageSize;
358 IMG_DEVMEM_LOG2ALIGN_T uiLog2ImportAlignment;
360 eError = DevmemHeapCount(psCtx->hBridge,
364 if (eError != PVRSRV_OK)
371 ppsHeapArray = IMG_NULL;
375 ppsHeapArray = OSAllocMem(sizeof(*ppsHeapArray) * uiNumHeaps);
376 if (ppsHeapArray == IMG_NULL)
378 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
383 uiHeapsToUnwindOnError = 0;
385 for (uiHeapIndex = 0; uiHeapIndex < uiNumHeaps; uiHeapIndex++)
387 eError = DevmemHeapDetails(psCtx->hBridge,
396 &uiLog2ImportAlignment);
397 if (eError != PVRSRV_OK)
402 eError = DevmemCreateHeap(psCtx,
406 uiLog2ImportAlignment,
409 &ppsHeapArray[uiHeapIndex]);
410 if (eError != PVRSRV_OK)
415 uiHeapsToUnwindOnError = uiHeapIndex + 1;
418 psCtx->uiAutoHeapCount = uiNumHeaps;
419 psCtx->ppsAutoHeapArray = ppsHeapArray;
421 PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
422 PVR_ASSERT(psCtx->uiAutoHeapCount == uiNumHeaps);
430 for (uiHeapIndex = 0; uiHeapIndex < uiHeapsToUnwindOnError; uiHeapIndex++)
432 eError2 = DevmemDestroyHeap(ppsHeapArray[uiHeapIndex]);
433 PVR_ASSERT(eError2 == PVRSRV_OK);
438 OSFreeMem(ppsHeapArray);
442 PVR_ASSERT(eError != PVRSRV_OK);
447 _UnpopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx)
449 PVRSRV_ERROR eError2;
450 IMG_UINT32 uiHeapIndex;
451 IMG_BOOL bDoCheck = IMG_TRUE;
452 #if defined(__KERNEL__)
453 PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
454 if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
456 bDoCheck = IMG_FALSE;
460 PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
462 for (uiHeapIndex = 0; uiHeapIndex < psCtx->uiAutoHeapCount; uiHeapIndex++)
464 eError2 = DevmemDestroyHeap(psCtx->ppsAutoHeapArray[uiHeapIndex]);
467 PVR_ASSERT(eError2 == PVRSRV_OK);
471 if (psCtx->uiAutoHeapCount != 0)
473 OSFreeMem(psCtx->ppsAutoHeapArray);
474 psCtx->ppsAutoHeapArray = IMG_NULL;
476 psCtx->uiAutoHeapCount = 0;
478 PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
479 PVR_ASSERT(psCtx->ppsAutoHeapArray == IMG_NULL);
483 /*****************************************************************************
484 * Devmem context functions *
485 *****************************************************************************/
487 IMG_INTERNAL PVRSRV_ERROR
488 DevmemCreateContext(DEVMEM_BRIDGE_HANDLE hBridge,
489 IMG_HANDLE hDeviceNode,
490 DEVMEM_HEAPCFGID uiHeapBlueprintID,
491 DEVMEM_CONTEXT **ppsCtxPtr)
494 DEVMEM_CONTEXT *psCtx;
495 /* handle to the server-side counterpart of the device memory
496 context (specifically, for handling mapping to device MMU) */
497 IMG_HANDLE hDevMemServerContext;
498 IMG_HANDLE hPrivData;
501 if (ppsCtxPtr == IMG_NULL)
503 eError = PVRSRV_ERROR_INVALID_PARAMS;
507 psCtx = OSAllocMem(sizeof *psCtx);
508 if (psCtx == IMG_NULL)
510 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
514 psCtx->uiNumHeaps = 0;
516 psCtx->hBridge = hBridge;
518 /* Create (server-side) Device Memory context */
519 eError = BridgeDevmemIntCtxCreate(psCtx->hBridge,
521 &hDevMemServerContext,
523 if (eError != PVRSRV_OK)
528 psCtx->hDeviceNode = hDeviceNode;
529 psCtx->hDevMemServerContext = hDevMemServerContext;
530 psCtx->hPrivData = hPrivData;
532 /* automagic heap creation */
533 psCtx->uiAutoHeapCount = 0;
535 eError = _PopulateContextFromBlueprint(psCtx, hDeviceNode, uiHeapBlueprintID);
536 if (eError != PVRSRV_OK)
545 PVR_ASSERT(psCtx->uiNumHeaps == psCtx->uiAutoHeapCount);
549 error exit paths follow
553 PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
554 PVR_ASSERT(psCtx->uiNumHeaps == 0);
555 BridgeDevmemIntCtxDestroy(psCtx->hBridge, hDevMemServerContext);
561 PVR_ASSERT(eError != PVRSRV_OK);
565 IMG_INTERNAL PVRSRV_ERROR
566 DevmemAcquireDevPrivData(DEVMEM_CONTEXT *psCtx,
567 IMG_HANDLE *hPrivData)
571 if ((psCtx == IMG_NULL) || (hPrivData == IMG_NULL))
573 eError = PVRSRV_ERROR_INVALID_PARAMS;
577 *hPrivData = psCtx->hPrivData;
581 PVR_ASSERT(eError != PVRSRV_OK);
585 IMG_INTERNAL PVRSRV_ERROR
586 DevmemReleaseDevPrivData(DEVMEM_CONTEXT *psCtx)
590 if (psCtx == IMG_NULL)
592 eError = PVRSRV_ERROR_INVALID_PARAMS;
598 PVR_ASSERT(eError != PVRSRV_OK);
603 IMG_INTERNAL PVRSRV_ERROR
604 DevmemFindHeapByName(const struct _DEVMEM_CONTEXT_ *psCtx,
605 const IMG_CHAR *pszHeapName,
606 struct _DEVMEM_HEAP_ **ppsHeapRet)
608 IMG_UINT32 uiHeapIndex;
610 /* N.B. This func is only useful for finding "automagic" heaps by name */
611 for (uiHeapIndex = 0;
612 uiHeapIndex < psCtx->uiAutoHeapCount;
615 if (!OSStringCompare(psCtx->ppsAutoHeapArray[uiHeapIndex]->pszName, pszHeapName))
617 *ppsHeapRet = psCtx->ppsAutoHeapArray[uiHeapIndex];
622 return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_INDEX;
625 IMG_INTERNAL PVRSRV_ERROR
626 DevmemDestroyContext(DEVMEM_CONTEXT *psCtx)
629 IMG_BOOL bDoCheck = IMG_TRUE;
631 #if defined(__KERNEL__)
632 PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
633 if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
635 bDoCheck = IMG_FALSE;
639 if (psCtx == IMG_NULL)
641 return PVRSRV_ERROR_INVALID_PARAMS;
644 /* should be only the automagically instantiated heaps left */
645 if (psCtx->uiNumHeaps != psCtx->uiAutoHeapCount)
647 return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
650 _UnpopulateContextFromBlueprint(psCtx);
654 PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
655 PVR_ASSERT(psCtx->uiNumHeaps == 0);
657 eError = BridgeDevmemIntCtxDestroy(psCtx->hBridge,
658 psCtx->hDevMemServerContext);
661 PVR_ASSERT (eError == PVRSRV_OK);
669 /*****************************************************************************
670 * Devmem heap query functions *
671 *****************************************************************************/
673 IMG_INTERNAL PVRSRV_ERROR
674 DevmemHeapConfigCount(DEVMEM_BRIDGE_HANDLE hBridge,
675 IMG_HANDLE hDeviceNode,
676 IMG_UINT32 *puiNumHeapConfigsOut)
680 eError = BridgeHeapCfgHeapConfigCount(hBridge,
682 puiNumHeapConfigsOut);
686 IMG_INTERNAL PVRSRV_ERROR
687 DevmemHeapCount(DEVMEM_BRIDGE_HANDLE hBridge,
688 IMG_HANDLE hDeviceNode,
689 IMG_UINT32 uiHeapConfigIndex,
690 IMG_UINT32 *puiNumHeapsOut)
694 eError = BridgeHeapCfgHeapCount(hBridge,
701 IMG_INTERNAL PVRSRV_ERROR
702 DevmemHeapConfigName(DEVMEM_BRIDGE_HANDLE hBridge,
703 IMG_HANDLE hDeviceNode,
704 IMG_UINT32 uiHeapConfigIndex,
705 IMG_CHAR *pszConfigNameOut,
706 IMG_UINT32 uiConfigNameBufSz)
710 eError = BridgeHeapCfgHeapConfigName(hBridge,
718 IMG_INTERNAL PVRSRV_ERROR
719 DevmemHeapDetails(DEVMEM_BRIDGE_HANDLE hBridge,
720 IMG_HANDLE hDeviceNode,
721 IMG_UINT32 uiHeapConfigIndex,
722 IMG_UINT32 uiHeapIndex,
723 IMG_CHAR *pszHeapNameOut,
724 IMG_UINT32 uiHeapNameBufSz,
725 IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
726 IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
727 IMG_UINT32 *puiLog2DataPageSizeOut,
728 IMG_UINT32 *puiLog2ImportAlignmentOut)
732 eError = BridgeHeapCfgHeapDetails(hBridge,
740 puiLog2DataPageSizeOut,
741 puiLog2ImportAlignmentOut);
743 VG_MARK_INITIALIZED(pszHeapNameOut,uiHeapNameBufSz);
748 /*****************************************************************************
749 * Devmem heap functions *
750 *****************************************************************************/
752 /* See devicemem.h for important notes regarding the arguments
754 IMG_INTERNAL PVRSRV_ERROR
755 DevmemCreateHeap(DEVMEM_CONTEXT *psCtx,
756 IMG_DEV_VIRTADDR sBaseAddress,
757 IMG_DEVMEM_SIZE_T uiLength,
758 IMG_UINT32 ui32Log2Quantum,
759 IMG_UINT32 ui32Log2ImportAlignment,
760 const IMG_CHAR *pszName,
761 DEVMEM_HEAPCFGID uiHeapBlueprintID,
762 DEVMEM_HEAP **ppsHeapPtr)
764 PVRSRV_ERROR eError = PVRSRV_OK;
765 PVRSRV_ERROR eError2;
767 /* handle to the server-side counterpart of the device memory
768 heap (specifically, for handling mapping to device MMU */
769 IMG_HANDLE hDevMemServerHeap;
770 IMG_BOOL bRANoSplit = IMG_FALSE;
772 IMG_CHAR aszBuf[100];
775 if (ppsHeapPtr == IMG_NULL)
777 eError = PVRSRV_ERROR_INVALID_PARAMS;
781 psHeap = OSAllocMem(sizeof *psHeap);
782 if (psHeap == IMG_NULL)
784 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
788 /* Need to keep local copy of heap name, so caller may free
790 pszStr = OSAllocMem(OSStringLength(pszName)+1);
791 if (pszStr == IMG_NULL)
793 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
796 OSStringCopy(pszStr, pszName);
797 psHeap->pszName = pszStr;
799 psHeap->sBaseAddress = sBaseAddress;
800 OSAtomicWrite(&psHeap->hImportCount,0);
802 OSSNPrintf(aszBuf, sizeof(aszBuf),
803 "NDM heap '%s' (suballocs) ctx:%p",
805 pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
806 if (pszStr == IMG_NULL)
808 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
811 OSStringCopy(pszStr, aszBuf);
812 psHeap->pszSubAllocRAName = pszStr;
814 #if defined(PDUMP) && defined(ANDROID)
815 /* the META heap is shared globally so a single
816 * physical memory import may be used to satisfy
817 * allocations of different processes.
818 * This is problematic when PDumping because the
819 * physical memory import used to satisfy a new allocation
820 * may actually have been imported (and thus the PDump MALLOC
821 * generated) before the PDump client was started, leading to the
822 * MALLOC being missing.
823 * This is solved by disabling splitting of imports for the META physmem
824 * RA, meaning that every firmware allocation gets its own import, thus
825 * ensuring the MALLOC is present for every allocation made within the
826 * pdump capture range
828 if(uiHeapBlueprintID == DEVMEM_HEAPCFG_META)
830 bRANoSplit = IMG_TRUE;
833 PVR_UNREFERENCED_PARAMETER(uiHeapBlueprintID);
837 psHeap->psSubAllocRA = RA_Create(psHeap->pszSubAllocRAName,
838 /* Subsequent imports: */
841 _SubAllocImportAlloc,
843 (RA_PERARENA_HANDLE) psHeap,
845 if (psHeap->psSubAllocRA == IMG_NULL)
847 eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
851 psHeap->uiLog2ImportAlignment = ui32Log2ImportAlignment;
852 psHeap->uiLog2Quantum = ui32Log2Quantum;
854 OSSNPrintf(aszBuf, sizeof(aszBuf),
855 "NDM heap '%s' (QVM) ctx:%p",
857 pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
858 if (pszStr == IMG_NULL)
860 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
863 OSStringCopy(pszStr, aszBuf);
864 psHeap->pszQuantizedVMRAName = pszStr;
866 psHeap->psQuantizedVMRA = RA_Create(psHeap->pszQuantizedVMRAName,
867 /* Subsequent import: */
868 0, RA_LOCKCLASS_1, IMG_NULL, IMG_NULL,
869 (RA_PERARENA_HANDLE) psHeap,
872 if (psHeap->psQuantizedVMRA == IMG_NULL)
874 eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
878 if (!RA_Add(psHeap->psQuantizedVMRA,
879 (RA_BASE_T)sBaseAddress.uiAddr,
880 (RA_LENGTH_T)uiLength,
881 (RA_FLAGS_T)0, /* This RA doesn't use or need flags */
882 IMG_NULL /* per ispan handle */))
884 RA_Delete(psHeap->psQuantizedVMRA);
885 eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
890 psHeap->psCtx = psCtx;
893 /* Create server-side counterpart of Device Memory heap */
894 eError = BridgeDevmemIntHeapCreate(psCtx->hBridge,
895 psCtx->hDevMemServerContext,
900 if (eError != PVRSRV_OK)
904 psHeap->hDevMemServerHeap = hDevMemServerHeap;
906 eError = OSLockCreate(&psHeap->hLock, LOCK_TYPE_PASSIVE);
907 if (eError != PVRSRV_OK)
912 psHeap->psCtx->uiNumHeaps ++;
913 *ppsHeapPtr = psHeap;
915 #if defined PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING
916 psHeap->psMemDescList = IMG_NULL;
917 #endif /* PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING */
925 eError2 = BridgeDevmemIntHeapDestroy(psCtx->hBridge,
926 psHeap->hDevMemServerHeap);
927 PVR_ASSERT (eError2 == PVRSRV_OK);
929 RA_Delete(psHeap->psQuantizedVMRA);
931 OSFreeMem(psHeap->pszQuantizedVMRAName);
933 RA_Delete(psHeap->psSubAllocRA);
935 OSFreeMem(psHeap->pszSubAllocRAName);
937 OSFreeMem(psHeap->pszName);
941 PVR_ASSERT(eError != PVRSRV_OK);
945 IMG_INTERNAL PVRSRV_ERROR
946 DevmemGetHeapBaseDevVAddr(struct _DEVMEM_HEAP_ *psHeap,
947 IMG_DEV_VIRTADDR *pDevVAddr)
949 if (psHeap == IMG_NULL)
951 return PVRSRV_ERROR_INVALID_PARAMS;
954 *pDevVAddr = psHeap->sBaseAddress;
959 IMG_INTERNAL IMG_VOID
960 DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign)
962 IMG_DEVMEM_SIZE_T uiSize = *puiSize;
963 IMG_DEVMEM_ALIGN_T uiAlign = *puiAlign;
964 IMG_UINT32 uiLog2Quantum;
968 uiLog2Quantum = psHeap->uiLog2Quantum;
972 uiLog2Quantum = GET_LOG2_PAGESIZE();
975 if ((1ULL << uiLog2Quantum) > uiAlign)
977 uiAlign = 1ULL << uiLog2Quantum;
979 uiSize = (uiSize + uiAlign - 1) & ~(uiAlign - 1);
986 IMG_INTERNAL PVRSRV_ERROR
987 DevmemDestroyHeap(DEVMEM_HEAP *psHeap)
990 IMG_INT uiImportCount;
992 if (psHeap == IMG_NULL)
994 return PVRSRV_ERROR_INVALID_PARAMS;
997 uiImportCount = OSAtomicRead(&psHeap->hImportCount);
998 if (uiImportCount > 0)
1000 PVR_DPF((PVR_DBG_ERROR, "%d(%s) leaks remain", uiImportCount, psHeap->pszName));
1001 return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
1004 OSLockDestroy(psHeap->hLock);
1006 PVR_ASSERT(psHeap->psCtx->uiNumHeaps > 0);
1007 psHeap->psCtx->uiNumHeaps --;
1009 eError = BridgeDevmemIntHeapDestroy(psHeap->psCtx->hBridge,
1010 psHeap->hDevMemServerHeap);
1011 PVR_ASSERT (eError == PVRSRV_OK);
1013 RA_Delete(psHeap->psQuantizedVMRA);
1014 OSFreeMem(psHeap->pszQuantizedVMRAName);
1016 RA_Delete(psHeap->psSubAllocRA);
1017 OSFreeMem(psHeap->pszSubAllocRAName);
1019 OSFreeMem(psHeap->pszName);
1026 /*****************************************************************************
1027 * Devmem allocation/free functions *
1028 *****************************************************************************/
1030 IMG_INTERNAL PVRSRV_ERROR
1031 DevmemAllocate(DEVMEM_HEAP *psHeap,
1032 IMG_DEVMEM_SIZE_T uiSize,
1033 IMG_DEVMEM_ALIGN_T uiAlign,
1034 DEVMEM_FLAGS_T uiFlags,
1035 const IMG_PCHAR pszText,
1036 DEVMEM_MEMDESC **ppsMemDescPtr)
1038 IMG_BOOL bStatus; /* eError for RA */
1039 RA_BASE_T uiAllocatedAddr;
1040 RA_LENGTH_T uiAllocatedSize;
1041 RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
1042 RA_FLAGS_T uiFlagsForRA;
1043 PVRSRV_ERROR eError;
1044 DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1045 IMG_DEVMEM_OFFSET_T uiOffset = 0;
1046 DEVMEM_IMPORT *psImport;
1049 if (uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
1051 /* Deferred Allocation not supported on SubAllocs*/
1052 eError = PVRSRV_ERROR_INVALID_PARAMS;
1056 if (psHeap == IMG_NULL || ppsMemDescPtr == IMG_NULL)
1058 eError = PVRSRV_ERROR_INVALID_PARAMS;
1062 eError = _DevmemValidateParams(uiSize,
1065 if (eError != PVRSRV_OK)
1070 eError =_DevmemMemDescAlloc(&psMemDesc);
1071 if (eError != PVRSRV_OK)
1073 goto failMemDescAlloc;
1077 If zero flag is set we have to have write access to the page.
1079 uiFlags |= (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) ? PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE : 0;
1082 No request for exportable memory so use the RA
1084 uiFlagsForRA = (RA_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
1085 /* Check that the cast didn't lose any flags due to different integer widths */
1086 PVR_ASSERT(uiFlagsForRA == (uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK));
1089 When the RA suballocates memory from a Span it does not zero it. It only zeroes the
1090 memory if it allocates a new Span; but we don't know what is going to happen for this
1091 RA_Alloc call. Therefore, we zero the mem after the allocation below.
1093 uiFlagsForRA &= ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
1095 bStatus = RA_Alloc(psHeap->psSubAllocRA,
1104 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1105 goto failDeviceMemAlloc;
1109 uiOffset = uiAllocatedAddr - psImport->sDeviceImport.sDevVAddr.uiAddr;
1111 _DevmemMemDescInit(psMemDesc,
1115 /* zero the memory */
1116 if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
1119 eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
1120 if (eError != PVRSRV_OK)
1125 /* FIXME: uiSize is a 64-bit quantity whereas the 3rd argument
1126 * to OSDeviceMemSet is a 32-bit quantity on 32-bit systems
1127 * hence a compiler warning of implicit cast and loss of data.
1128 * Added explicit cast and assert to remove warning.
1130 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
1131 PVR_ASSERT(uiSize<IMG_UINT32_MAX);
1134 OSDeviceMemSet(pvAddr, 0x0, (IMG_SIZE_T) uiSize);
1136 DevmemReleaseCpuVirtAddr(psMemDesc);
1139 DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
1143 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
1144 /* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
1145 * the allocation gets mapped/unmapped
1147 OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
1148 psMemDesc->sTraceData.uiSize = uiSize;
1151 #if defined(PVR_RI_DEBUG)
1153 /* Attach RI information */
1154 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1155 psMemDesc->psImport->hPMR,
1156 OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1158 psMemDesc->uiOffset,
1162 &(psMemDesc->hRIHandle));
1163 if( eError != PVRSRV_OK)
1165 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1168 #else /* if defined(PVR_RI_DEBUG) */
1169 PVR_UNREFERENCED_PARAMETER (pszText);
1170 #endif /* if defined(PVR_RI_DEBUG) */
1172 *ppsMemDescPtr = psMemDesc;
1177 error exit paths follow
1181 _DevmemMemDescRelease(psMemDesc);
1182 psMemDesc = IMG_NULL; /* Make sure we don't do a discard after the release */
1185 _DevmemMemDescDiscard(psMemDesc);
1188 PVR_ASSERT(eError != PVRSRV_OK);
1194 IMG_INTERNAL PVRSRV_ERROR
1195 DevmemAllocateExportable(IMG_HANDLE hBridge,
1196 IMG_HANDLE hDeviceNode,
1197 IMG_DEVMEM_SIZE_T uiSize,
1198 IMG_DEVMEM_ALIGN_T uiAlign,
1199 DEVMEM_FLAGS_T uiFlags,
1200 const IMG_PCHAR pszText,
1201 DEVMEM_MEMDESC **ppsMemDescPtr)
1203 PVRSRV_ERROR eError;
1204 DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1205 DEVMEM_IMPORT *psImport;
1206 IMG_BOOL bMappingTable = IMG_TRUE;
1209 DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
1213 eError = _DevmemValidateParams(uiSize,
1216 if (eError != PVRSRV_OK)
1222 eError =_DevmemMemDescAlloc(&psMemDesc);
1223 if (eError != PVRSRV_OK)
1225 goto failMemDescAlloc;
1230 In the case of exportable memory we have no heap to
1231 query the pagesize from, so we assume host pagesize.
1233 eError = _AllocateDeviceMemory(hBridge,
1235 GET_LOG2_PAGESIZE(),
1245 if (eError != PVRSRV_OK)
1247 goto failDeviceMemAlloc;
1250 _DevmemMemDescInit(psMemDesc,
1254 *ppsMemDescPtr = psMemDesc;
1256 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
1257 /* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
1258 * the allocation gets mapped/unmapped
1260 OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
1261 psMemDesc->sTraceData.uiSize = uiSize;
1264 #if defined(PVR_RI_DEBUG)
1266 eError = BridgeRIWritePMREntry (psImport->hBridge,
1268 OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1269 (IMG_CHAR *)pszText,
1271 if( eError != PVRSRV_OK)
1273 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
1276 /* Attach RI information */
1277 eError = BridgeRIWriteMEMDESCEntry (psImport->hBridge,
1281 psMemDesc->uiOffset,
1285 &psMemDesc->hRIHandle);
1286 if( eError != PVRSRV_OK)
1288 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1291 #else /* if defined(PVR_RI_DEBUG) */
1292 PVR_UNREFERENCED_PARAMETER (pszText);
1293 #endif /* if defined(PVR_RI_DEBUG) */
1298 error exit paths follow
1302 _DevmemMemDescDiscard(psMemDesc);
1306 PVR_ASSERT(eError != PVRSRV_OK);
1310 IMG_INTERNAL PVRSRV_ERROR
1311 DevmemAllocateSparse(IMG_HANDLE hBridge,
1312 IMG_HANDLE hDeviceNode,
1313 IMG_DEVMEM_SIZE_T uiSize,
1314 IMG_DEVMEM_SIZE_T uiChunkSize,
1315 IMG_UINT32 ui32NumPhysChunks,
1316 IMG_UINT32 ui32NumVirtChunks,
1317 IMG_BOOL *pabMappingTable,
1318 IMG_DEVMEM_ALIGN_T uiAlign,
1319 DEVMEM_FLAGS_T uiFlags,
1320 const IMG_PCHAR pszText,
1321 DEVMEM_MEMDESC **ppsMemDescPtr)
1323 PVRSRV_ERROR eError;
1324 DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1325 DEVMEM_IMPORT *psImport;
1328 DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
1332 eError = _DevmemValidateParams(uiSize,
1335 if (eError != PVRSRV_OK)
1341 eError =_DevmemMemDescAlloc(&psMemDesc);
1342 if (eError != PVRSRV_OK)
1344 goto failMemDescAlloc;
1349 In the case of sparse memory we have no heap to
1350 query the pagesize from, so we assume host pagesize.
1352 eError = _AllocateDeviceMemory(hBridge,
1354 GET_LOG2_PAGESIZE(),
1364 if (eError != PVRSRV_OK)
1366 goto failDeviceMemAlloc;
1369 _DevmemMemDescInit(psMemDesc,
1373 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
1374 /* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
1375 * the allocation gets mapped/unmapped
1377 OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
1378 psMemDesc->sTraceData.uiSize = uiSize;
1381 #if defined(PVR_RI_DEBUG)
1383 eError = BridgeRIWritePMREntry (psImport->hBridge,
1385 OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1386 (IMG_CHAR *)pszText,
1388 if( eError != PVRSRV_OK)
1390 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
1393 /* Attach RI information */
1394 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1395 psMemDesc->psImport->hPMR,
1398 psMemDesc->uiOffset,
1402 &psMemDesc->hRIHandle);
1403 if( eError != PVRSRV_OK)
1405 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1408 #else /* if defined(PVR_RI_DEBUG) */
1409 PVR_UNREFERENCED_PARAMETER (pszText);
1410 #endif /* if defined(PVR_RI_DEBUG) */
1412 *ppsMemDescPtr = psMemDesc;
1417 error exit paths follow
1421 _DevmemMemDescDiscard(psMemDesc);
1425 PVR_ASSERT(eError != PVRSRV_OK);
1429 /*****************************************************************************
1430 * Devmem unsecure export functions *
1431 *****************************************************************************/
1433 IMG_INTERNAL PVRSRV_ERROR
1434 DevmemExport(DEVMEM_MEMDESC *psMemDesc,
1435 DEVMEM_EXPORTCOOKIE *psExportCookie)
1437 /* Caller to provide storage for export cookie struct */
1438 PVRSRV_ERROR eError;
1439 IMG_HANDLE hPMRExportHandle = 0;
1440 IMG_UINT64 uiPMRExportPassword = 0;
1441 IMG_DEVMEM_SIZE_T uiSize = 0;
1442 IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig = 0;
1444 if (psMemDesc == IMG_NULL || psExportCookie == IMG_NULL)
1446 eError = PVRSRV_ERROR_INVALID_PARAMS;
1450 eError = _Mapping_Export(psMemDesc->psImport,
1452 &uiPMRExportPassword,
1455 if (eError != PVRSRV_OK)
1457 psExportCookie->uiSize = 0;
1461 psExportCookie->hPMRExportHandle = hPMRExportHandle;
1462 psExportCookie->uiPMRExportPassword = uiPMRExportPassword;
1463 psExportCookie->uiSize = uiSize;
1464 psExportCookie->uiLog2ContiguityGuarantee = uiLog2Contig;
1469 error exit paths follow
1473 PVR_ASSERT(eError != PVRSRV_OK);
1477 IMG_INTERNAL PVRSRV_ERROR
1478 DevmemMakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
1479 DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie,
1480 DEVMEM_EXPORTCOOKIE *psExportCookie)
1482 DEVMEM_EXPORTHANDLE hPMRExportHandle;
1483 IMG_DEVMEM_SIZE_T uiPMRSize;
1484 IMG_DEVMEM_LOG2ALIGN_T uiPMRLog2Contig;
1485 DEVMEM_EXPORTKEY uiPMRExportKey;
1486 PVRSRV_ERROR eError = PVRSRV_OK;
1488 eError = BridgePMRMakeServerExportClientExport(hBridge,
1489 hServerExportCookie,
1495 if (eError == PVRSRV_OK)
1497 psExportCookie->hPMRExportHandle = hPMRExportHandle;
1498 psExportCookie->uiPMRExportPassword = uiPMRExportKey;
1499 psExportCookie->uiSize = uiPMRSize;
1500 psExportCookie->uiLog2ContiguityGuarantee = uiPMRLog2Contig;
1506 IMG_INTERNAL PVRSRV_ERROR
1507 DevmemUnmakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
1508 DEVMEM_EXPORTCOOKIE *psExportCookie)
1510 return BridgePMRUnmakeServerExportClientExport(hBridge, psExportCookie->hPMRExportHandle);
1513 IMG_INTERNAL IMG_BOOL
1514 DevmemIsValidExportCookie(DEVMEM_EXPORTCOOKIE *psExportCookie)
1516 /* Assume that if the size is set, the export cookie is used */
1517 return (psExportCookie->uiSize != 0x0);
1520 IMG_INTERNAL IMG_VOID
1521 DevmemUnexport(DEVMEM_MEMDESC *psMemDesc,
1522 DEVMEM_EXPORTCOOKIE *psExportCookie)
1524 _Mapping_Unexport(psMemDesc->psImport,
1525 psExportCookie->hPMRExportHandle);
1527 psExportCookie->uiSize = 0;
1530 IMG_INTERNAL PVRSRV_ERROR
1531 DevmemImport(IMG_HANDLE hBridge,
1532 DEVMEM_EXPORTCOOKIE *psCookie,
1533 DEVMEM_FLAGS_T uiFlags,
1534 DEVMEM_MEMDESC **ppsMemDescPtr)
1536 DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1537 DEVMEM_IMPORT *psImport;
1539 PVRSRV_ERROR eError;
1541 if (ppsMemDescPtr == IMG_NULL)
1543 eError = PVRSRV_ERROR_INVALID_PARAMS;
1547 eError =_DevmemMemDescAlloc(&psMemDesc);
1548 if (eError != PVRSRV_OK)
1550 goto failMemDescAlloc;
1553 eError = _DevmemImportStructAlloc(hBridge,
1556 if (eError != PVRSRV_OK)
1558 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1559 goto failImportAlloc;
1563 /* Get a handle to the PMR (inc refcount, checks authorization) */
1564 eError = BridgePMRImportPMR(hBridge,
1565 psCookie->hPMRExportHandle,
1566 psCookie->uiPMRExportPassword,
1567 psCookie->uiSize, /* not trusted - just for sanity checks */
1568 psCookie->uiLog2ContiguityGuarantee, /* not trusted - just for sanity checks */
1570 if (eError != PVRSRV_OK)
1575 _DevmemImportStructInit(psImport,
1577 1ULL << psCookie->uiLog2ContiguityGuarantee,
1581 _DevmemMemDescInit(psMemDesc,
1585 *ppsMemDescPtr = psMemDesc;
1587 #if defined(PVR_RI_DEBUG)
1589 /* Attach RI information */
1590 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1591 psMemDesc->psImport->hPMR,
1594 psMemDesc->uiOffset,
1595 psMemDesc->psImport->uiSize,
1598 &psMemDesc->hRIHandle);
1599 if( eError != PVRSRV_OK)
1601 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1604 #endif /* if defined(PVR_RI_DEBUG) */
1609 error exit paths follow
1613 _DevmemImportDiscard(psImport);
1615 _DevmemMemDescDiscard(psMemDesc);
1618 PVR_ASSERT(eError != PVRSRV_OK);
1623 /*****************************************************************************
1624 * Common MemDesc functions *
1625 *****************************************************************************/
1628 This function is called for freeing any class of memory
1630 IMG_INTERNAL IMG_VOID
1631 DevmemFree(DEVMEM_MEMDESC *psMemDesc)
1633 #if defined(PVR_RI_DEBUG)
1634 if (psMemDesc->hRIHandle)
1636 PVRSRV_ERROR eError;
1638 eError = BridgeRIDeleteMEMDESCEntry(psMemDesc->psImport->hBridge,
1639 psMemDesc->hRIHandle);
1640 if( eError != PVRSRV_OK)
1642 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIDeleteMEMDESCEntry failed (eError=%d)", __func__, eError));
1645 #endif /* if defined(PVR_RI_DEBUG) */
1646 _DevmemMemDescRelease(psMemDesc);
1649 IMG_INTERNAL PVRSRV_ERROR
1650 DevmemMapToDevice(DEVMEM_MEMDESC *psMemDesc,
1651 DEVMEM_HEAP *psHeap,
1652 IMG_DEV_VIRTADDR *psDevVirtAddr)
1654 DEVMEM_IMPORT *psImport;
1655 IMG_DEV_VIRTADDR sDevVAddr;
1656 PVRSRV_ERROR eError;
1657 IMG_BOOL bMap = IMG_TRUE;
1659 OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1660 if (psHeap == IMG_NULL)
1662 eError = PVRSRV_ERROR_INVALID_PARAMS;
1666 if (psMemDesc->sDeviceMemDesc.ui32RefCount != 0)
1668 eError = PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED;
1672 /* Don't map memory for deferred allocations */
1673 if (psMemDesc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
1675 PVR_ASSERT(psMemDesc->psImport->bExportable);
1679 DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1682 psMemDesc->sDeviceMemDesc.ui32RefCount,
1683 psMemDesc->sDeviceMemDesc.ui32RefCount+1);
1685 psImport = psMemDesc->psImport;
1686 _DevmemMemDescAcquire(psMemDesc);
1688 eError = _DevmemImportStructDevMap(psHeap,
1691 if (eError != PVRSRV_OK)
1696 sDevVAddr.uiAddr = psImport->sDeviceImport.sDevVAddr.uiAddr;
1697 sDevVAddr.uiAddr += psMemDesc->uiOffset;
1698 psMemDesc->sDeviceMemDesc.sDevVAddr = sDevVAddr;
1699 psMemDesc->sDeviceMemDesc.ui32RefCount++;
1701 *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
1703 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1705 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
1706 BridgeDevicememHistoryMap(psMemDesc->psImport->hBridge,
1707 psMemDesc->sDeviceMemDesc.sDevVAddr,
1708 psMemDesc->sTraceData.uiSize,
1709 psMemDesc->sTraceData.szText);
1712 #if defined(PVR_RI_DEBUG)
1713 if (psMemDesc->hRIHandle)
1715 eError = BridgeRIUpdateMEMDESCAddr(psImport->hBridge,
1716 psMemDesc->hRIHandle,
1717 psImport->sDeviceImport.sDevVAddr);
1718 if( eError != PVRSRV_OK)
1720 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
1728 _DevmemMemDescRelease(psMemDesc);
1731 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1732 PVR_ASSERT(eError != PVRSRV_OK);
1737 IMG_INTERNAL PVRSRV_ERROR
1738 DevmemAcquireDevVirtAddr(DEVMEM_MEMDESC *psMemDesc,
1739 IMG_DEV_VIRTADDR *psDevVirtAddr)
1741 PVRSRV_ERROR eError;
1743 OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1744 DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1747 psMemDesc->sDeviceMemDesc.ui32RefCount,
1748 psMemDesc->sDeviceMemDesc.ui32RefCount+1);
1750 if (psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
1752 eError = PVRSRV_ERROR_DEVICEMEM_NO_MAPPING;
1755 psMemDesc->sDeviceMemDesc.ui32RefCount++;
1757 *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
1758 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1763 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1764 PVR_ASSERT(eError != PVRSRV_OK);
1769 IMG_INTERNAL IMG_VOID
1770 DevmemReleaseDevVirtAddr(DEVMEM_MEMDESC *psMemDesc)
1772 PVR_ASSERT(psMemDesc != IMG_NULL);
1774 OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1775 DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1778 psMemDesc->sDeviceMemDesc.ui32RefCount,
1779 psMemDesc->sDeviceMemDesc.ui32RefCount-1);
1781 PVR_ASSERT(psMemDesc->sDeviceMemDesc.ui32RefCount != 0);
1783 if (--psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
1785 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
1786 BridgeDevicememHistoryUnmap(psMemDesc->psImport->hBridge,
1787 psMemDesc->sDeviceMemDesc.sDevVAddr,
1788 psMemDesc->sTraceData.uiSize,
1789 psMemDesc->sTraceData.szText);
1791 _DevmemImportStructDevUnmap(psMemDesc->psImport);
1792 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1794 _DevmemMemDescRelease(psMemDesc);
1798 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1802 IMG_INTERNAL PVRSRV_ERROR
1803 DevmemAcquireCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc,
1804 IMG_VOID **ppvCpuVirtAddr)
1806 PVRSRV_ERROR eError;
1808 OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
1809 DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1812 psMemDesc->sCPUMemDesc.ui32RefCount,
1813 psMemDesc->sCPUMemDesc.ui32RefCount+1);
1815 if (psMemDesc->sCPUMemDesc.ui32RefCount++ == 0)
1817 DEVMEM_IMPORT *psImport = psMemDesc->psImport;
1818 IMG_UINT8 *pui8CPUVAddr;
1820 _DevmemMemDescAcquire(psMemDesc);
1821 eError = _DevmemImportStructCPUMap(psImport);
1822 if (eError != PVRSRV_OK)
1827 pui8CPUVAddr = psImport->sCPUImport.pvCPUVAddr;
1828 pui8CPUVAddr += psMemDesc->uiOffset;
1829 psMemDesc->sCPUMemDesc.pvCPUVAddr = pui8CPUVAddr;
1831 *ppvCpuVirtAddr = psMemDesc->sCPUMemDesc.pvCPUVAddr;
1833 VG_MARK_INITIALIZED(*ppvCpuVirtAddr, psMemDesc->psImport->uiSize);
1835 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1840 PVR_ASSERT(eError != PVRSRV_OK);
1841 psMemDesc->sCPUMemDesc.ui32RefCount--;
1842 _DevmemMemDescRelease(psMemDesc);
1843 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1848 IMG_INTERNAL IMG_VOID
1849 DevmemReleaseCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc)
1851 PVR_ASSERT(psMemDesc != IMG_NULL);
1853 OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
1854 DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1857 psMemDesc->sCPUMemDesc.ui32RefCount,
1858 psMemDesc->sCPUMemDesc.ui32RefCount-1);
1860 PVR_ASSERT(psMemDesc->sCPUMemDesc.ui32RefCount != 0);
1862 if (--psMemDesc->sCPUMemDesc.ui32RefCount == 0)
1864 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1865 _DevmemImportStructCPUUnmap(psMemDesc->psImport);
1866 _DevmemMemDescRelease(psMemDesc);
1870 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1874 IMG_INTERNAL PVRSRV_ERROR
1875 DevmemLocalGetImportHandle(DEVMEM_MEMDESC *psMemDesc,
1876 IMG_HANDLE *phImport)
1878 if (psMemDesc->psImport->bExportable == IMG_FALSE)
1880 return PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION;
1883 *phImport = psMemDesc->psImport->hPMR;
1888 IMG_INTERNAL PVRSRV_ERROR
1889 DevmemGetImportUID(DEVMEM_MEMDESC *psMemDesc,
1890 IMG_UINT64 *pui64UID)
1892 DEVMEM_IMPORT *psImport = psMemDesc->psImport;
1893 PVRSRV_ERROR eError;
1895 eError = BridgePMRGetUID(psImport->hBridge,
1902 IMG_INTERNAL PVRSRV_ERROR
1903 DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
1904 IMG_HANDLE *hReservation)
1906 DEVMEM_IMPORT *psImport;
1908 PVR_ASSERT(psMemDesc);
1909 psImport = psMemDesc->psImport;
1911 PVR_ASSERT(psImport);
1912 *hReservation = psImport->sDeviceImport.hReservation;
1918 DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
1920 IMG_DEVMEM_OFFSET_T *puiPMROffset)
1922 DEVMEM_IMPORT *psImport;
1924 PVR_ASSERT(psMemDesc);
1925 *puiPMROffset = psMemDesc->uiOffset;
1926 psImport = psMemDesc->psImport;
1928 PVR_ASSERT(psImport);
1929 *phPMR = psImport->hPMR;
1934 IMG_INTERNAL PVRSRV_ERROR
1935 DevmemGetFlags(DEVMEM_MEMDESC *psMemDesc,
1936 DEVMEM_FLAGS_T *puiFlags)
1938 DEVMEM_IMPORT *psImport;
1940 PVR_ASSERT(psMemDesc);
1941 psImport = psMemDesc->psImport;
1943 PVR_ASSERT(psImport);
1944 *puiFlags = psImport->uiFlags;
1949 IMG_INTERNAL PVRSRV_ERROR
1950 DevmemLocalImport(IMG_HANDLE hBridge,
1951 IMG_HANDLE hExtHandle,
1952 DEVMEM_FLAGS_T uiFlags,
1953 DEVMEM_MEMDESC **ppsMemDescPtr,
1954 IMG_DEVMEM_SIZE_T *puiSizePtr)
1956 DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1957 DEVMEM_IMPORT *psImport;
1958 IMG_DEVMEM_SIZE_T uiSize;
1959 IMG_DEVMEM_ALIGN_T uiAlign;
1961 PVRSRV_ERROR eError;
1963 if (ppsMemDescPtr == IMG_NULL)
1965 eError = PVRSRV_ERROR_INVALID_PARAMS;
1969 eError =_DevmemMemDescAlloc(&psMemDesc);
1970 if (eError != PVRSRV_OK)
1972 goto failMemDescAlloc;
1975 eError = _DevmemImportStructAlloc(hBridge,
1978 if (eError != PVRSRV_OK)
1980 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1981 goto failImportAlloc;
1984 /* Get the PMR handle and it's size from the server */
1985 eError = BridgePMRLocalImportPMR(hBridge,
1990 if (eError != PVRSRV_OK)
1995 _DevmemImportStructInit(psImport,
2001 _DevmemMemDescInit(psMemDesc,
2005 *ppsMemDescPtr = psMemDesc;
2007 *puiSizePtr = uiSize;
2009 #if defined(PVR_RI_DEBUG)
2011 /* Attach RI information */
2012 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
2013 psMemDesc->psImport->hPMR,
2016 psMemDesc->uiOffset,
2017 psMemDesc->psImport->uiSize,
2020 &(psMemDesc->hRIHandle));
2021 if( eError != PVRSRV_OK)
2023 PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
2026 #endif /* if defined(PVR_RI_DEBUG) */
2030 _DevmemImportDiscard(psImport);
2032 _DevmemMemDescDiscard(psMemDesc);
2035 PVR_ASSERT(eError != PVRSRV_OK);
2040 IMG_INTERNAL PVRSRV_ERROR
2041 DevmemIsDevVirtAddrValid(DEVMEM_CONTEXT *psContext,
2042 IMG_DEV_VIRTADDR sDevVAddr)
2044 return BridgeDevmemIsVDevAddrValid(psContext->hBridge,
2045 psContext->hDevMemServerContext,
2049 IMG_INTERNAL IMG_UINT32
2050 DevmemGetHeapLog2ImportAlignment(DEVMEM_HEAP *psHeap)
2052 return psHeap->uiLog2ImportAlignment;