db440d05115148e928c02028fb7dfb9029b91119
[platform/kernel/linux-starfive.git] /
1 /*******************************************************************************
2 @File
3 @Title          Server bridge for devicememhistory
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Implements the server side of the bridge for devicememhistory
6 @License        Dual MIT/GPLv2
7
8 The contents of this file are subject to the MIT license as set out below.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
23
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 *******************************************************************************/
43
44 #include <linux/uaccess.h>
45
46 #include "img_defs.h"
47
48 #include "devicemem_history_server.h"
49
50 #include "common_devicememhistory_bridge.h"
51
52 #include "allocmem.h"
53 #include "pvr_debug.h"
54 #include "connection_server.h"
55 #include "pvr_bridge.h"
56 #if defined(SUPPORT_RGX)
57 #include "rgx_bridge.h"
58 #endif
59 #include "srvcore.h"
60 #include "handle.h"
61
62 #include <linux/slab.h>
63
64 #include "lock.h"
65
66 /* ***************************************************************************
67  * Server-side bridge entry points
68  */
69
70 static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
71               "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
72
73 static IMG_INT
74 PVRSRVBridgeDevicememHistoryMap(IMG_UINT32 ui32DispatchTableEntry,
75                                 IMG_UINT8 * psDevicememHistoryMapIN_UI8,
76                                 IMG_UINT8 * psDevicememHistoryMapOUT_UI8,
77                                 CONNECTION_DATA * psConnection)
78 {
79         PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAP *psDevicememHistoryMapIN =
80             (PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAP *) IMG_OFFSET_ADDR(psDevicememHistoryMapIN_UI8,
81                                                                      0);
82         PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAP *psDevicememHistoryMapOUT =
83             (PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAP *) IMG_OFFSET_ADDR(psDevicememHistoryMapOUT_UI8,
84                                                                       0);
85
86         IMG_HANDLE hPMR = psDevicememHistoryMapIN->hPMR;
87         PMR *psPMRInt = NULL;
88         IMG_CHAR *uiTextInt = NULL;
89
90         IMG_UINT32 ui32NextOffset = 0;
91         IMG_BYTE *pArrayArgsBuffer = NULL;
92 #if !defined(INTEGRITY_OS)
93         IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
94 #endif
95
96         IMG_UINT32 ui32BufferSize = 0;
97         IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
98
99         if (ui64BufferSize > IMG_UINT32_MAX)
100         {
101                 psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
102                 goto DevicememHistoryMap_exit;
103         }
104
105         ui32BufferSize = (IMG_UINT32) ui64BufferSize;
106
107         if (ui32BufferSize != 0)
108         {
109 #if !defined(INTEGRITY_OS)
110                 /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
111                 IMG_UINT32 ui32InBufferOffset =
112                     PVR_ALIGN(sizeof(*psDevicememHistoryMapIN), sizeof(unsigned long));
113                 IMG_UINT32 ui32InBufferExcessSize =
114                     ui32InBufferOffset >=
115                     PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
116
117                 bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
118                 if (bHaveEnoughSpace)
119                 {
120                         IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psDevicememHistoryMapIN;
121
122                         pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
123                 }
124                 else
125 #endif
126                 {
127                         pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
128
129                         if (!pArrayArgsBuffer)
130                         {
131                                 psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
132                                 goto DevicememHistoryMap_exit;
133                         }
134                 }
135         }
136
137         {
138                 uiTextInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
139                 ui32NextOffset += DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR);
140         }
141
142         /* Copy the data over */
143         if (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR) > 0)
144         {
145                 if (OSCopyFromUser
146                     (NULL, uiTextInt, (const void __user *)psDevicememHistoryMapIN->puiText,
147                      DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) != PVRSRV_OK)
148                 {
149                         psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
150
151                         goto DevicememHistoryMap_exit;
152                 }
153                 ((IMG_CHAR *) uiTextInt)[(DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
154         }
155
156         /* Lock over handle lookup. */
157         LockHandle(psConnection->psHandleBase);
158
159         /* Look up the address from the handle */
160         psDevicememHistoryMapOUT->eError =
161             PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
162                                        (void **)&psPMRInt,
163                                        hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR, IMG_TRUE);
164         if (unlikely(psDevicememHistoryMapOUT->eError != PVRSRV_OK))
165         {
166                 UnlockHandle(psConnection->psHandleBase);
167                 goto DevicememHistoryMap_exit;
168         }
169         /* Release now we have looked up handles. */
170         UnlockHandle(psConnection->psHandleBase);
171
172         psDevicememHistoryMapOUT->eError =
173             DevicememHistoryMapKM(psPMRInt,
174                                   psDevicememHistoryMapIN->uiOffset,
175                                   psDevicememHistoryMapIN->sDevVAddr,
176                                   psDevicememHistoryMapIN->uiSize,
177                                   uiTextInt,
178                                   psDevicememHistoryMapIN->ui32Log2PageSize,
179                                   psDevicememHistoryMapIN->ui32AllocationIndex,
180                                   &psDevicememHistoryMapOUT->ui32AllocationIndexOut);
181
182 DevicememHistoryMap_exit:
183
184         /* Lock over handle lookup cleanup. */
185         LockHandle(psConnection->psHandleBase);
186
187         /* Unreference the previously looked up handle */
188         if (psPMRInt)
189         {
190                 PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
191                                             hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
192         }
193         /* Release now we have cleaned up look up handles. */
194         UnlockHandle(psConnection->psHandleBase);
195
196         /* Allocated space should be equal to the last updated offset */
197 #ifdef PVRSRV_NEED_PVR_ASSERT
198         if (psDevicememHistoryMapOUT->eError == PVRSRV_OK)
199                 PVR_ASSERT(ui32BufferSize == ui32NextOffset);
200 #endif /* PVRSRV_NEED_PVR_ASSERT */
201
202 #if defined(INTEGRITY_OS)
203         if (pArrayArgsBuffer)
204 #else
205         if (!bHaveEnoughSpace && pArrayArgsBuffer)
206 #endif
207                 OSFreeMemNoStats(pArrayArgsBuffer);
208
209         return 0;
210 }
211
212 static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
213               "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
214
215 static IMG_INT
216 PVRSRVBridgeDevicememHistoryUnmap(IMG_UINT32 ui32DispatchTableEntry,
217                                   IMG_UINT8 * psDevicememHistoryUnmapIN_UI8,
218                                   IMG_UINT8 * psDevicememHistoryUnmapOUT_UI8,
219                                   CONNECTION_DATA * psConnection)
220 {
221         PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAP *psDevicememHistoryUnmapIN =
222             (PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAP *)
223             IMG_OFFSET_ADDR(psDevicememHistoryUnmapIN_UI8, 0);
224         PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAP *psDevicememHistoryUnmapOUT =
225             (PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAP *)
226             IMG_OFFSET_ADDR(psDevicememHistoryUnmapOUT_UI8, 0);
227
228         IMG_HANDLE hPMR = psDevicememHistoryUnmapIN->hPMR;
229         PMR *psPMRInt = NULL;
230         IMG_CHAR *uiTextInt = NULL;
231
232         IMG_UINT32 ui32NextOffset = 0;
233         IMG_BYTE *pArrayArgsBuffer = NULL;
234 #if !defined(INTEGRITY_OS)
235         IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
236 #endif
237
238         IMG_UINT32 ui32BufferSize = 0;
239         IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
240
241         if (ui64BufferSize > IMG_UINT32_MAX)
242         {
243                 psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
244                 goto DevicememHistoryUnmap_exit;
245         }
246
247         ui32BufferSize = (IMG_UINT32) ui64BufferSize;
248
249         if (ui32BufferSize != 0)
250         {
251 #if !defined(INTEGRITY_OS)
252                 /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
253                 IMG_UINT32 ui32InBufferOffset =
254                     PVR_ALIGN(sizeof(*psDevicememHistoryUnmapIN), sizeof(unsigned long));
255                 IMG_UINT32 ui32InBufferExcessSize =
256                     ui32InBufferOffset >=
257                     PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
258
259                 bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
260                 if (bHaveEnoughSpace)
261                 {
262                         IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psDevicememHistoryUnmapIN;
263
264                         pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
265                 }
266                 else
267 #endif
268                 {
269                         pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
270
271                         if (!pArrayArgsBuffer)
272                         {
273                                 psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
274                                 goto DevicememHistoryUnmap_exit;
275                         }
276                 }
277         }
278
279         {
280                 uiTextInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
281                 ui32NextOffset += DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR);
282         }
283
284         /* Copy the data over */
285         if (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR) > 0)
286         {
287                 if (OSCopyFromUser
288                     (NULL, uiTextInt, (const void __user *)psDevicememHistoryUnmapIN->puiText,
289                      DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) != PVRSRV_OK)
290                 {
291                         psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
292
293                         goto DevicememHistoryUnmap_exit;
294                 }
295                 ((IMG_CHAR *) uiTextInt)[(DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
296         }
297
298         /* Lock over handle lookup. */
299         LockHandle(psConnection->psHandleBase);
300
301         /* Look up the address from the handle */
302         psDevicememHistoryUnmapOUT->eError =
303             PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
304                                        (void **)&psPMRInt,
305                                        hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR, IMG_TRUE);
306         if (unlikely(psDevicememHistoryUnmapOUT->eError != PVRSRV_OK))
307         {
308                 UnlockHandle(psConnection->psHandleBase);
309                 goto DevicememHistoryUnmap_exit;
310         }
311         /* Release now we have looked up handles. */
312         UnlockHandle(psConnection->psHandleBase);
313
314         psDevicememHistoryUnmapOUT->eError =
315             DevicememHistoryUnmapKM(psPMRInt,
316                                     psDevicememHistoryUnmapIN->uiOffset,
317                                     psDevicememHistoryUnmapIN->sDevVAddr,
318                                     psDevicememHistoryUnmapIN->uiSize,
319                                     uiTextInt,
320                                     psDevicememHistoryUnmapIN->ui32Log2PageSize,
321                                     psDevicememHistoryUnmapIN->ui32AllocationIndex,
322                                     &psDevicememHistoryUnmapOUT->ui32AllocationIndexOut);
323
324 DevicememHistoryUnmap_exit:
325
326         /* Lock over handle lookup cleanup. */
327         LockHandle(psConnection->psHandleBase);
328
329         /* Unreference the previously looked up handle */
330         if (psPMRInt)
331         {
332                 PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
333                                             hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
334         }
335         /* Release now we have cleaned up look up handles. */
336         UnlockHandle(psConnection->psHandleBase);
337
338         /* Allocated space should be equal to the last updated offset */
339 #ifdef PVRSRV_NEED_PVR_ASSERT
340         if (psDevicememHistoryUnmapOUT->eError == PVRSRV_OK)
341                 PVR_ASSERT(ui32BufferSize == ui32NextOffset);
342 #endif /* PVRSRV_NEED_PVR_ASSERT */
343
344 #if defined(INTEGRITY_OS)
345         if (pArrayArgsBuffer)
346 #else
347         if (!bHaveEnoughSpace && pArrayArgsBuffer)
348 #endif
349                 OSFreeMemNoStats(pArrayArgsBuffer);
350
351         return 0;
352 }
353
354 static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
355               "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
356
357 static IMG_INT
358 PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
359                                       IMG_UINT8 * psDevicememHistoryMapVRangeIN_UI8,
360                                       IMG_UINT8 * psDevicememHistoryMapVRangeOUT_UI8,
361                                       CONNECTION_DATA * psConnection)
362 {
363         PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPVRANGE *psDevicememHistoryMapVRangeIN =
364             (PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPVRANGE *)
365             IMG_OFFSET_ADDR(psDevicememHistoryMapVRangeIN_UI8, 0);
366         PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPVRANGE *psDevicememHistoryMapVRangeOUT =
367             (PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPVRANGE *)
368             IMG_OFFSET_ADDR(psDevicememHistoryMapVRangeOUT_UI8, 0);
369
370         IMG_CHAR *uiTextInt = NULL;
371
372         IMG_UINT32 ui32NextOffset = 0;
373         IMG_BYTE *pArrayArgsBuffer = NULL;
374 #if !defined(INTEGRITY_OS)
375         IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
376 #endif
377
378         IMG_UINT32 ui32BufferSize = 0;
379         IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
380
381         if (ui64BufferSize > IMG_UINT32_MAX)
382         {
383                 psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
384                 goto DevicememHistoryMapVRange_exit;
385         }
386
387         ui32BufferSize = (IMG_UINT32) ui64BufferSize;
388
389         if (ui32BufferSize != 0)
390         {
391 #if !defined(INTEGRITY_OS)
392                 /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
393                 IMG_UINT32 ui32InBufferOffset =
394                     PVR_ALIGN(sizeof(*psDevicememHistoryMapVRangeIN), sizeof(unsigned long));
395                 IMG_UINT32 ui32InBufferExcessSize =
396                     ui32InBufferOffset >=
397                     PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
398
399                 bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
400                 if (bHaveEnoughSpace)
401                 {
402                         IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psDevicememHistoryMapVRangeIN;
403
404                         pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
405                 }
406                 else
407 #endif
408                 {
409                         pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
410
411                         if (!pArrayArgsBuffer)
412                         {
413                                 psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
414                                 goto DevicememHistoryMapVRange_exit;
415                         }
416                 }
417         }
418
419         {
420                 uiTextInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
421                 ui32NextOffset += DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR);
422         }
423
424         /* Copy the data over */
425         if (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR) > 0)
426         {
427                 if (OSCopyFromUser
428                     (NULL, uiTextInt, (const void __user *)psDevicememHistoryMapVRangeIN->puiText,
429                      DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) != PVRSRV_OK)
430                 {
431                         psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
432
433                         goto DevicememHistoryMapVRange_exit;
434                 }
435                 ((IMG_CHAR *) uiTextInt)[(DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
436         }
437
438         psDevicememHistoryMapVRangeOUT->eError =
439             DevicememHistoryMapVRangeKM(psConnection, OSGetDevNode(psConnection),
440                                         psDevicememHistoryMapVRangeIN->sBaseDevVAddr,
441                                         psDevicememHistoryMapVRangeIN->ui32ui32StartPage,
442                                         psDevicememHistoryMapVRangeIN->ui32NumPages,
443                                         psDevicememHistoryMapVRangeIN->uiAllocSize,
444                                         uiTextInt,
445                                         psDevicememHistoryMapVRangeIN->ui32Log2PageSize,
446                                         psDevicememHistoryMapVRangeIN->ui32AllocationIndex,
447                                         &psDevicememHistoryMapVRangeOUT->ui32AllocationIndexOut);
448
449 DevicememHistoryMapVRange_exit:
450
451         /* Allocated space should be equal to the last updated offset */
452 #ifdef PVRSRV_NEED_PVR_ASSERT
453         if (psDevicememHistoryMapVRangeOUT->eError == PVRSRV_OK)
454                 PVR_ASSERT(ui32BufferSize == ui32NextOffset);
455 #endif /* PVRSRV_NEED_PVR_ASSERT */
456
457 #if defined(INTEGRITY_OS)
458         if (pArrayArgsBuffer)
459 #else
460         if (!bHaveEnoughSpace && pArrayArgsBuffer)
461 #endif
462                 OSFreeMemNoStats(pArrayArgsBuffer);
463
464         return 0;
465 }
466
467 static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
468               "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
469
470 static IMG_INT
471 PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
472                                         IMG_UINT8 * psDevicememHistoryUnmapVRangeIN_UI8,
473                                         IMG_UINT8 * psDevicememHistoryUnmapVRangeOUT_UI8,
474                                         CONNECTION_DATA * psConnection)
475 {
476         PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPVRANGE *psDevicememHistoryUnmapVRangeIN =
477             (PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPVRANGE *)
478             IMG_OFFSET_ADDR(psDevicememHistoryUnmapVRangeIN_UI8, 0);
479         PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPVRANGE *psDevicememHistoryUnmapVRangeOUT =
480             (PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPVRANGE *)
481             IMG_OFFSET_ADDR(psDevicememHistoryUnmapVRangeOUT_UI8, 0);
482
483         IMG_CHAR *uiTextInt = NULL;
484
485         IMG_UINT32 ui32NextOffset = 0;
486         IMG_BYTE *pArrayArgsBuffer = NULL;
487 #if !defined(INTEGRITY_OS)
488         IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
489 #endif
490
491         IMG_UINT32 ui32BufferSize = 0;
492         IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
493
494         if (ui64BufferSize > IMG_UINT32_MAX)
495         {
496                 psDevicememHistoryUnmapVRangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
497                 goto DevicememHistoryUnmapVRange_exit;
498         }
499
500         ui32BufferSize = (IMG_UINT32) ui64BufferSize;
501
502         if (ui32BufferSize != 0)
503         {
504 #if !defined(INTEGRITY_OS)
505                 /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
506                 IMG_UINT32 ui32InBufferOffset =
507                     PVR_ALIGN(sizeof(*psDevicememHistoryUnmapVRangeIN), sizeof(unsigned long));
508                 IMG_UINT32 ui32InBufferExcessSize =
509                     ui32InBufferOffset >=
510                     PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
511
512                 bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
513                 if (bHaveEnoughSpace)
514                 {
515                         IMG_BYTE *pInputBuffer =
516                             (IMG_BYTE *) (void *)psDevicememHistoryUnmapVRangeIN;
517
518                         pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
519                 }
520                 else
521 #endif
522                 {
523                         pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
524
525                         if (!pArrayArgsBuffer)
526                         {
527                                 psDevicememHistoryUnmapVRangeOUT->eError =
528                                     PVRSRV_ERROR_OUT_OF_MEMORY;
529                                 goto DevicememHistoryUnmapVRange_exit;
530                         }
531                 }
532         }
533
534         {
535                 uiTextInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
536                 ui32NextOffset += DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR);
537         }
538
539         /* Copy the data over */
540         if (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR) > 0)
541         {
542                 if (OSCopyFromUser
543                     (NULL, uiTextInt, (const void __user *)psDevicememHistoryUnmapVRangeIN->puiText,
544                      DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) != PVRSRV_OK)
545                 {
546                         psDevicememHistoryUnmapVRangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
547
548                         goto DevicememHistoryUnmapVRange_exit;
549                 }
550                 ((IMG_CHAR *) uiTextInt)[(DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
551         }
552
553         psDevicememHistoryUnmapVRangeOUT->eError =
554             DevicememHistoryUnmapVRangeKM(psConnection, OSGetDevNode(psConnection),
555                                           psDevicememHistoryUnmapVRangeIN->sBaseDevVAddr,
556                                           psDevicememHistoryUnmapVRangeIN->ui32ui32StartPage,
557                                           psDevicememHistoryUnmapVRangeIN->ui32NumPages,
558                                           psDevicememHistoryUnmapVRangeIN->uiAllocSize,
559                                           uiTextInt,
560                                           psDevicememHistoryUnmapVRangeIN->ui32Log2PageSize,
561                                           psDevicememHistoryUnmapVRangeIN->ui32AllocationIndex,
562                                           &psDevicememHistoryUnmapVRangeOUT->
563                                           ui32AllocationIndexOut);
564
565 DevicememHistoryUnmapVRange_exit:
566
567         /* Allocated space should be equal to the last updated offset */
568 #ifdef PVRSRV_NEED_PVR_ASSERT
569         if (psDevicememHistoryUnmapVRangeOUT->eError == PVRSRV_OK)
570                 PVR_ASSERT(ui32BufferSize == ui32NextOffset);
571 #endif /* PVRSRV_NEED_PVR_ASSERT */
572
573 #if defined(INTEGRITY_OS)
574         if (pArrayArgsBuffer)
575 #else
576         if (!bHaveEnoughSpace && pArrayArgsBuffer)
577 #endif
578                 OSFreeMemNoStats(pArrayArgsBuffer);
579
580         return 0;
581 }
582
583 static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
584               "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
585
586 static IMG_INT
587 PVRSRVBridgeDevicememHistorySparseChange(IMG_UINT32 ui32DispatchTableEntry,
588                                          IMG_UINT8 * psDevicememHistorySparseChangeIN_UI8,
589                                          IMG_UINT8 * psDevicememHistorySparseChangeOUT_UI8,
590                                          CONNECTION_DATA * psConnection)
591 {
592         PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYSPARSECHANGE *psDevicememHistorySparseChangeIN =
593             (PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYSPARSECHANGE *)
594             IMG_OFFSET_ADDR(psDevicememHistorySparseChangeIN_UI8, 0);
595         PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYSPARSECHANGE *psDevicememHistorySparseChangeOUT =
596             (PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYSPARSECHANGE *)
597             IMG_OFFSET_ADDR(psDevicememHistorySparseChangeOUT_UI8, 0);
598
599         IMG_HANDLE hPMR = psDevicememHistorySparseChangeIN->hPMR;
600         PMR *psPMRInt = NULL;
601         IMG_CHAR *uiTextInt = NULL;
602         IMG_UINT32 *ui32AllocPageIndicesInt = NULL;
603         IMG_UINT32 *ui32FreePageIndicesInt = NULL;
604
605         IMG_UINT32 ui32NextOffset = 0;
606         IMG_BYTE *pArrayArgsBuffer = NULL;
607 #if !defined(INTEGRITY_OS)
608         IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
609 #endif
610
611         IMG_UINT32 ui32BufferSize = 0;
612         IMG_UINT64 ui64BufferSize =
613             ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) +
614             ((IMG_UINT64) psDevicememHistorySparseChangeIN->ui32AllocPageCount *
615              sizeof(IMG_UINT32)) +
616             ((IMG_UINT64) psDevicememHistorySparseChangeIN->ui32FreePageCount *
617              sizeof(IMG_UINT32)) + 0;
618
619         if (ui64BufferSize > IMG_UINT32_MAX)
620         {
621                 psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
622                 goto DevicememHistorySparseChange_exit;
623         }
624
625         ui32BufferSize = (IMG_UINT32) ui64BufferSize;
626
627         if (ui32BufferSize != 0)
628         {
629 #if !defined(INTEGRITY_OS)
630                 /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
631                 IMG_UINT32 ui32InBufferOffset =
632                     PVR_ALIGN(sizeof(*psDevicememHistorySparseChangeIN), sizeof(unsigned long));
633                 IMG_UINT32 ui32InBufferExcessSize =
634                     ui32InBufferOffset >=
635                     PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
636
637                 bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
638                 if (bHaveEnoughSpace)
639                 {
640                         IMG_BYTE *pInputBuffer =
641                             (IMG_BYTE *) (void *)psDevicememHistorySparseChangeIN;
642
643                         pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
644                 }
645                 else
646 #endif
647                 {
648                         pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
649
650                         if (!pArrayArgsBuffer)
651                         {
652                                 psDevicememHistorySparseChangeOUT->eError =
653                                     PVRSRV_ERROR_OUT_OF_MEMORY;
654                                 goto DevicememHistorySparseChange_exit;
655                         }
656                 }
657         }
658
659         {
660                 uiTextInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
661                 ui32NextOffset += DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR);
662         }
663
664         /* Copy the data over */
665         if (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR) > 0)
666         {
667                 if (OSCopyFromUser
668                     (NULL, uiTextInt,
669                      (const void __user *)psDevicememHistorySparseChangeIN->puiText,
670                      DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) != PVRSRV_OK)
671                 {
672                         psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
673
674                         goto DevicememHistorySparseChange_exit;
675                 }
676                 ((IMG_CHAR *) uiTextInt)[(DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
677         }
678         if (psDevicememHistorySparseChangeIN->ui32AllocPageCount != 0)
679         {
680                 ui32AllocPageIndicesInt =
681                     (IMG_UINT32 *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
682                 ui32NextOffset +=
683                     psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32);
684         }
685
686         /* Copy the data over */
687         if (psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32) > 0)
688         {
689                 if (OSCopyFromUser
690                     (NULL, ui32AllocPageIndicesInt,
691                      (const void __user *)psDevicememHistorySparseChangeIN->pui32AllocPageIndices,
692                      psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32)) !=
693                     PVRSRV_OK)
694                 {
695                         psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
696
697                         goto DevicememHistorySparseChange_exit;
698                 }
699         }
700         if (psDevicememHistorySparseChangeIN->ui32FreePageCount != 0)
701         {
702                 ui32FreePageIndicesInt =
703                     (IMG_UINT32 *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
704                 ui32NextOffset +=
705                     psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32);
706         }
707
708         /* Copy the data over */
709         if (psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32) > 0)
710         {
711                 if (OSCopyFromUser
712                     (NULL, ui32FreePageIndicesInt,
713                      (const void __user *)psDevicememHistorySparseChangeIN->pui32FreePageIndices,
714                      psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32)) !=
715                     PVRSRV_OK)
716                 {
717                         psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
718
719                         goto DevicememHistorySparseChange_exit;
720                 }
721         }
722
723         /* Lock over handle lookup. */
724         LockHandle(psConnection->psHandleBase);
725
726         /* Look up the address from the handle */
727         psDevicememHistorySparseChangeOUT->eError =
728             PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
729                                        (void **)&psPMRInt,
730                                        hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR, IMG_TRUE);
731         if (unlikely(psDevicememHistorySparseChangeOUT->eError != PVRSRV_OK))
732         {
733                 UnlockHandle(psConnection->psHandleBase);
734                 goto DevicememHistorySparseChange_exit;
735         }
736         /* Release now we have looked up handles. */
737         UnlockHandle(psConnection->psHandleBase);
738
739         psDevicememHistorySparseChangeOUT->eError =
740             DevicememHistorySparseChangeKM(psPMRInt,
741                                            psDevicememHistorySparseChangeIN->uiOffset,
742                                            psDevicememHistorySparseChangeIN->sDevVAddr,
743                                            psDevicememHistorySparseChangeIN->uiSize,
744                                            uiTextInt,
745                                            psDevicememHistorySparseChangeIN->ui32Log2PageSize,
746                                            psDevicememHistorySparseChangeIN->ui32AllocPageCount,
747                                            ui32AllocPageIndicesInt,
748                                            psDevicememHistorySparseChangeIN->ui32FreePageCount,
749                                            ui32FreePageIndicesInt,
750                                            psDevicememHistorySparseChangeIN->ui32AllocationIndex,
751                                            &psDevicememHistorySparseChangeOUT->
752                                            ui32AllocationIndexOut);
753
754 DevicememHistorySparseChange_exit:
755
756         /* Lock over handle lookup cleanup. */
757         LockHandle(psConnection->psHandleBase);
758
759         /* Unreference the previously looked up handle */
760         if (psPMRInt)
761         {
762                 PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
763                                             hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
764         }
765         /* Release now we have cleaned up look up handles. */
766         UnlockHandle(psConnection->psHandleBase);
767
768         /* Allocated space should be equal to the last updated offset */
769 #ifdef PVRSRV_NEED_PVR_ASSERT
770         if (psDevicememHistorySparseChangeOUT->eError == PVRSRV_OK)
771                 PVR_ASSERT(ui32BufferSize == ui32NextOffset);
772 #endif /* PVRSRV_NEED_PVR_ASSERT */
773
774 #if defined(INTEGRITY_OS)
775         if (pArrayArgsBuffer)
776 #else
777         if (!bHaveEnoughSpace && pArrayArgsBuffer)
778 #endif
779                 OSFreeMemNoStats(pArrayArgsBuffer);
780
781         return 0;
782 }
783
784 /* ***************************************************************************
785  * Server bridge dispatch related glue
786  */
787
788 static POS_LOCK pDEVICEMEMHISTORYBridgeLock;
789
790 PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void);
791 void DeinitDEVICEMEMHISTORYBridge(void);
792
793 /*
794  * Register all DEVICEMEMHISTORY functions with services
795  */
796 PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void)
797 {
798         PVR_LOG_RETURN_IF_ERROR(OSLockCreate(&pDEVICEMEMHISTORYBridgeLock), "OSLockCreate");
799
800         SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
801                               PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAP,
802                               PVRSRVBridgeDevicememHistoryMap, pDEVICEMEMHISTORYBridgeLock);
803
804         SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
805                               PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAP,
806                               PVRSRVBridgeDevicememHistoryUnmap, pDEVICEMEMHISTORYBridgeLock);
807
808         SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
809                               PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPVRANGE,
810                               PVRSRVBridgeDevicememHistoryMapVRange, pDEVICEMEMHISTORYBridgeLock);
811
812         SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
813                               PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPVRANGE,
814                               PVRSRVBridgeDevicememHistoryUnmapVRange, pDEVICEMEMHISTORYBridgeLock);
815
816         SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
817                               PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYSPARSECHANGE,
818                               PVRSRVBridgeDevicememHistorySparseChange,
819                               pDEVICEMEMHISTORYBridgeLock);
820
821         return PVRSRV_OK;
822 }
823
824 /*
825  * Unregister all devicememhistory functions with services
826  */
827 void DeinitDEVICEMEMHISTORYBridge(void)
828 {
829         OSLockDestroy(pDEVICEMEMHISTORYBridgeLock);
830
831         UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
832                                 PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAP);
833
834         UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
835                                 PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAP);
836
837         UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
838                                 PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPVRANGE);
839
840         UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
841                                 PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPVRANGE);
842
843         UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
844                                 PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYSPARSECHANGE);
845
846 }