1 /*************************************************************************/ /*!
3 @Title Device Memory Management internal utility functions
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Utility functions used internally by 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 #ifndef _DEVICEMEM_UTILS_H_
46 #define _DEVICEMEM_UTILS_H_
48 #include "devicemem.h"
49 #include "img_types.h"
50 #include "pvrsrv_error.h"
51 #include "pvr_debug.h"
57 #include "devicemem_utils.h"
58 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
59 #include "mm_common.h"
60 #include "devicemem_history_shared.h"
63 #define DEVMEM_HEAPNAME_MAXLENGTH 160
66 #if defined(DEVMEM_DEBUG) && defined(REFCOUNT_DEBUG)
67 #define DEVMEM_REFCOUNT_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_ERROR, __FILE__, __LINE__, fmt, __VA_ARGS__)
69 #define DEVMEM_REFCOUNT_PRINT(fmt, ...)
72 /* If we need a "hMapping" but we don't have a server-side mapping, we
73 poison the entry with this value so that it's easily recognised in
74 the debugger. Note that this is potentially a valid handle, but
75 then so is NULL, which is no better, indeed worse, as it's not
76 obvious in the debugger. The value doesn't matter. We _never_ use
77 it (and because it's valid, we never assert it isn't this) but it's
78 nice to have a value in the source code that we can grep for when
80 #define LACK_OF_MAPPING_POISON ((IMG_HANDLE)0x6116dead)
81 #define LACK_OF_RESERVATION_POISON ((IMG_HANDLE)0x7117dead)
83 struct _DEVMEM_CONTEXT_ {
85 SHARED_DEV_CONNECTION hDevConnection;
87 /* Number of heaps that have been created in this context
88 (regardless of whether they have allocations) */
89 IMG_UINT32 uiNumHeaps;
92 Each "DEVMEM_CONTEXT" has a counterpart in the server,
93 which is responsible for handling the mapping into device MMU.
94 We have a handle to that here.
96 IMG_HANDLE hDevMemServerContext;
98 /* Number of automagically created heaps in this context,
99 i.e. those that are born at context creation time from the
100 chosen "heap config" or "blueprint" */
101 IMG_UINT32 uiAutoHeapCount;
103 /* pointer to array of such heaps */
104 struct _DEVMEM_HEAP_ **ppsAutoHeapArray;
106 /* The cache line size for use when allocating memory, as it is not queryable on the client side */
107 IMG_UINT32 ui32CPUCacheLineSize;
109 /* Private data handle for device specific data */
110 IMG_HANDLE hPrivData;
116 DEVMEM_HEAP_TYPE_UNKNOWN = 0,
117 DEVMEM_HEAP_TYPE_USER_MANAGED,
118 DEVMEM_HEAP_TYPE_KERNEL_MANAGED,
119 DEVMEM_HEAP_TYPE_RA_MANAGED,
122 struct _DEVMEM_HEAP_ {
123 /* Name of heap - for debug and lookup purposes. */
126 /* Number of live imports in the heap */
127 ATOMIC_T hImportCount;
130 * Base address and size of heap, required by clients due to some requesters
131 * not being full range
133 IMG_DEV_VIRTADDR sBaseAddress;
134 DEVMEM_SIZE_T uiSize;
136 /* The heap type, describing if the space is managed by the user or an RA*/
137 DEVMEM_HEAP_TYPE eHeapType;
139 /* This RA is for managing sub-allocations in virtual space. Two
140 more RA's will be used under the Hood for managing the coarser
141 allocation of virtual space from the heap, and also for
142 managing the physical backing storage. */
143 RA_ARENA *psSubAllocRA;
144 IMG_CHAR *pszSubAllocRAName;
146 This RA is for the coarse allocation of virtual space from the heap
148 RA_ARENA *psQuantizedVMRA;
149 IMG_CHAR *pszQuantizedVMRAName;
151 /* We also need to store a copy of the quantum size in order to
152 feed this down to the server */
153 IMG_UINT32 uiLog2Quantum;
155 /* Store a copy of the minimum import alignment */
156 IMG_UINT32 uiLog2ImportAlignment;
158 /* The relationship between tiled heap alignment and heap byte-stride
159 * (dependent on tiling mode, abstracted here) */
160 IMG_UINT32 uiLog2TilingStrideFactor;
162 /* The parent memory context for this heap */
163 struct _DEVMEM_CONTEXT_ *psCtx;
165 /* Lock to protect this structure */
169 Each "DEVMEM_HEAP" has a counterpart in the server,
170 which is responsible for handling the mapping into device MMU.
171 We have a handle to that here.
173 IMG_HANDLE hDevMemServerHeap;
176 typedef IMG_UINT32 DEVMEM_PROPERTIES_T; /*!< Typedef for Devicemem properties */
177 #define DEVMEM_PROPERTIES_EXPORTABLE (1UL<<0) /*!< Is it exportable? */
178 #define DEVMEM_PROPERTIES_IMPORTED (1UL<<1) /*!< Is it imported from another process? */
179 #define DEVMEM_PROPERTIES_SUBALLOCATABLE (1UL<<2) /*!< Is it suballocatable? */
180 #define DEVMEM_PROPERTIES_UNPINNED (1UL<<3) /*!< Is it currently pinned? */
181 #define DEVMEM_PROPERTIES_IMPORT_IS_ZEROED (1UL<<4) /*!< Is the memory fully zeroed? */
182 #define DEVMEM_PROPERTIES_IMPORT_IS_CLEAN (1UL<<5) /*!< Is the memory clean, i.e. not been used before? */
183 #define DEVMEM_PROPERTIES_SECURE (1UL<<6) /*!< Is it a special secure buffer? No CPU maps allowed! */
186 typedef struct _DEVMEM_DEVICE_IMPORT_ {
187 DEVMEM_HEAP *psHeap; /*!< Heap this import is bound to */
188 IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the import */
189 IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
190 IMG_HANDLE hReservation; /*!< Device memory reservation handle */
191 IMG_HANDLE hMapping; /*!< Device mapping handle */
192 IMG_BOOL bMapped; /*!< This is import mapped? */
193 POS_LOCK hLock; /*!< Lock to protect the device import */
194 } DEVMEM_DEVICE_IMPORT;
196 typedef struct _DEVMEM_CPU_IMPORT_ {
197 void *pvCPUVAddr; /*!< CPU virtual address of the import */
198 IMG_UINT32 ui32RefCount; /*!< Refcount of the CPU virtual address */
199 IMG_HANDLE hOSMMapData; /*!< CPU mapping handle */
200 POS_LOCK hLock; /*!< Lock to protect the CPU import */
203 typedef struct _DEVMEM_IMPORT_ {
204 SHARED_DEV_CONNECTION hDevConnection;
205 IMG_DEVMEM_ALIGN_T uiAlign; /*!< Alignment of the PMR */
206 DEVMEM_SIZE_T uiSize; /*!< Size of import */
207 ATOMIC_T hRefCount; /*!< Refcount for this import */
208 DEVMEM_PROPERTIES_T uiProperties; /*!< Stores properties of an import like if
209 it is exportable, pinned or suballocatable */
210 IMG_HANDLE hPMR; /*!< Handle to the PMR */
211 DEVMEM_FLAGS_T uiFlags; /*!< Flags for this import */
212 POS_LOCK hLock; /*!< Lock to protect the import */
214 DEVMEM_DEVICE_IMPORT sDeviceImport; /*!< Device specifics of the import */
215 DEVMEM_CPU_IMPORT sCPUImport; /*!< CPU specifics of the import */
217 IMG_CHAR *pszAnnotation;
221 typedef struct _DEVMEM_DEVICE_MEMDESC_ {
222 IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the allocation */
223 IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
224 POS_LOCK hLock; /*!< Lock to protect device memdesc */
225 } DEVMEM_DEVICE_MEMDESC;
227 typedef struct _DEVMEM_CPU_MEMDESC_ {
228 void *pvCPUVAddr; /*!< CPU virtual address of the import */
229 IMG_UINT32 ui32RefCount; /*!< Refcount of the device CPU address */
230 POS_LOCK hLock; /*!< Lock to protect CPU memdesc */
231 } DEVMEM_CPU_MEMDESC;
233 struct _DEVMEM_MEMDESC_ {
234 DEVMEM_IMPORT *psImport; /*!< Import this memdesc is on */
235 IMG_DEVMEM_OFFSET_T uiOffset; /*!< Offset into import where our allocation starts */
236 IMG_DEVMEM_SIZE_T uiAllocSize; /*!< Size of the allocation */
237 ATOMIC_T hRefCount; /*!< Refcount of the memdesc */
238 POS_LOCK hLock; /*!< Lock to protect memdesc */
239 IMG_HANDLE hPrivData;
241 DEVMEM_DEVICE_MEMDESC sDeviceMemDesc; /*!< Device specifics of the memdesc */
242 DEVMEM_CPU_MEMDESC sCPUMemDesc; /*!< CPU specifics of the memdesc */
243 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
244 DEVICEMEM_HISTORY_MEMDESC_DATA sTraceData;
247 #if defined(PVR_RI_DEBUG)
248 IMG_HANDLE hRIHandle; /*!< Handle to RI information */
252 /* The physical descriptor used to store handles and information of
253 * device physical allocations. */
254 struct _DEVMEMX_PHYS_MEMDESC_ {
255 IMG_UINT32 uiNumPages; /*!< Number of pages that the import has*/
256 IMG_UINT32 uiLog2PageSize; /*!< Page size */
257 ATOMIC_T hRefCount; /*!< Refcount of the memdesc */
258 DEVMEM_FLAGS_T uiFlags; /*!< Flags for this import */
259 IMG_HANDLE hPMR; /*!< Handle to the PMR */
260 DEVMEM_CPU_IMPORT sCPUImport; /*!< CPU specifics of the memdesc */
261 DEVMEM_BRIDGE_HANDLE hBridge; /*!< Bridge connection for the server */
264 /* The virtual descriptor used to store handles and information of a
265 * device virtual range and the mappings to it. */
266 struct _DEVMEMX_VIRT_MEMDESC_ {
267 IMG_UINT32 uiNumPages; /*!< Number of pages that the import has*/
268 DEVMEM_FLAGS_T uiFlags; /*!< Flags for this import */
269 DEVMEMX_PHYSDESC **apsPhysDescTable; /*!< Table to store links to physical descs */
270 DEVMEM_DEVICE_IMPORT sDeviceImport; /*!< Device specifics of the memdesc */
272 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
273 DEVICEMEM_HISTORY_MEMDESC_DATA sTraceData; /*!< To track mappings in this range */
276 #if defined(PVR_RI_DEBUG)
277 IMG_HANDLE hRIHandle; /*!< Handle to RI information */
281 #define DEVICEMEM_UTILS_NO_ADDRESS 0
283 /******************************************************************************
284 @Function _DevmemValidateParams
285 @Description Check if flags are conflicting and if align is a size multiple.
287 @Input uiSize Size of the import.
288 @Input uiAlign Alignment of the import.
289 @Input puiFlags Pointer to the flags for the import.
291 ******************************************************************************/
292 PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
293 IMG_DEVMEM_ALIGN_T uiAlign,
294 DEVMEM_FLAGS_T *puiFlags);
296 /******************************************************************************
297 @Function _DevmemImportStructAlloc
298 @Description Allocates memory for an import struct. Does not allocate a PMR!
299 Create locks for CPU and Devmem mappings.
301 @Input hBridge Bridge to use for calls from the import.
302 @Input ppsImport The import to allocate.
304 ******************************************************************************/
305 PVRSRV_ERROR _DevmemImportStructAlloc(SHARED_DEV_CONNECTION hDevConnection,
306 DEVMEM_IMPORT **ppsImport);
308 /******************************************************************************
309 @Function _DevmemImportStructInit
310 @Description Initialises the import struct with the given parameters.
311 Set it's refcount to 1!
313 @Input psImport The import to initialise.
314 @Input uiSize Size of the import.
315 @Input uiAlign Alignment of allocations in the import.
317 @Input hPMR Reference to the PMR of this import struct.
318 @Input uiProperties Properties of the import. Is it exportable,
319 imported, suballocatable, unpinned?
320 ******************************************************************************/
321 void _DevmemImportStructInit(DEVMEM_IMPORT *psImport,
322 IMG_DEVMEM_SIZE_T uiSize,
323 IMG_DEVMEM_ALIGN_T uiAlign,
324 PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
326 DEVMEM_PROPERTIES_T uiProperties);
328 /******************************************************************************
329 @Function _DevmemImportStructDevMap
330 @Description NEVER call after the last _DevmemMemDescRelease()
331 Maps the PMR referenced by the import struct to the device's
332 virtual address space.
333 Does nothing but increase the cpu mapping refcount if the
334 import struct was already mapped.
336 @Input psHeap The heap to map to.
337 @Input bMap Caller can choose if the import should be really
338 mapped in the page tables or if just a virtual range
339 should be reserved and the refcounts increased.
340 @Input psImport The import we want to map.
341 @Input uiOptionalMapAddress An optional address to map to.
342 Pass DEVICEMEM_UTILS_NOADDRESS if not used.
344 ******************************************************************************/
345 PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
347 DEVMEM_IMPORT *psImport,
348 IMG_UINT64 uiOptionalMapAddress);
350 /******************************************************************************
351 @Function _DevmemImportStructDevUnmap
352 @Description Unmaps the PMR referenced by the import struct from the
353 device's virtual address space.
354 If this was not the last remaining CPU mapping on the import
355 struct only the cpu mapping refcount is decreased.
356 ******************************************************************************/
357 void _DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport);
359 /******************************************************************************
360 @Function _DevmemImportStructCPUMap
361 @Description NEVER call after the last _DevmemMemDescRelease()
362 Maps the PMR referenced by the import struct to the CPU's
363 virtual address space.
364 Does nothing but increase the cpu mapping refcount if the
365 import struct was already mapped.
367 ******************************************************************************/
368 PVRSRV_ERROR _DevmemImportStructCPUMap(DEVMEM_IMPORT *psImport);
370 /******************************************************************************
371 @Function _DevmemImportStructCPUUnmap
372 @Description Unmaps the PMR referenced by the import struct from the CPU's
373 virtual address space.
374 If this was not the last remaining CPU mapping on the import
375 struct only the cpu mapping refcount is decreased.
376 ******************************************************************************/
377 void _DevmemImportStructCPUUnmap(DEVMEM_IMPORT *psImport);
380 /******************************************************************************
381 @Function _DevmemImportStructAcquire
382 @Description Acquire an import struct by increasing it's refcount.
383 ******************************************************************************/
384 void _DevmemImportStructAcquire(DEVMEM_IMPORT *psImport);
386 /******************************************************************************
387 @Function _DevmemImportStructRelease
388 @Description Reduces the refcount of the import struct.
389 Destroys the import in the case it was the last reference.
390 Destroys underlying PMR if this import was the last reference
392 @return A boolean to signal if the import was destroyed. True = yes.
393 ******************************************************************************/
394 void _DevmemImportStructRelease(DEVMEM_IMPORT *psImport);
396 /******************************************************************************
397 @Function _DevmemImportDiscard
398 @Description Discard a created, but unitilised import structure.
399 This must only be called before _DevmemImportStructInit
400 after which _DevmemImportStructRelease must be used to
401 "free" the import structure.
402 ******************************************************************************/
403 void _DevmemImportDiscard(DEVMEM_IMPORT *psImport);
405 /******************************************************************************
406 @Function _DevmemMemDescAlloc
407 @Description Allocates a MemDesc and create it's various locks.
408 Zero the allocated memory.
410 ******************************************************************************/
411 PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc);
413 /******************************************************************************
414 @Function _DevmemMemDescInit
415 @Description Sets the given offset and import struct fields in the MemDesc.
416 Initialises refcount to 1 and other values to 0.
418 @Input psMemDesc MemDesc to initialise.
419 @Input uiOffset Offset in the import structure.
420 @Input psImport Import the MemDesc is on.
421 @Input uiAllocSize Size of the allocation
422 ******************************************************************************/
423 void _DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
424 IMG_DEVMEM_OFFSET_T uiOffset,
425 DEVMEM_IMPORT *psImport,
426 IMG_DEVMEM_SIZE_T uiAllocSize);
428 /******************************************************************************
429 @Function _DevmemMemDescAcquire
430 @Description Acquires the MemDesc by increasing it's refcount.
431 ******************************************************************************/
432 void _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc);
434 /******************************************************************************
435 @Function _DevmemMemDescRelease
436 @Description Releases the MemDesc by reducing it's refcount.
437 Destroy the MemDesc if it's recount is 0.
438 Destroy the import struct the MemDesc is on if that was the
439 last MemDesc on the import, probably following the destruction
440 of the underlying PMR.
441 ******************************************************************************/
442 void _DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc);
444 /******************************************************************************
445 @Function _DevmemMemDescDiscard
446 @Description Discard a created, but unitilised MemDesc structure.
447 This must only be called before _DevmemMemDescInit
448 after which _DevmemMemDescRelease must be used to
449 "free" the MemDesc structure.
450 ******************************************************************************/
451 void _DevmemMemDescDiscard(DEVMEM_MEMDESC *psMemDesc);
453 #endif /* _DEVICEMEM_UTILS_H_ */