gpu: pvr: pdump: sanitise stream handling
[sgx.git] / pvr / pdump_common.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #if defined(PDUMP)
28 #include "services_headers.h"
29 #include "pdump_km.h"
30
31 #if !defined(PDUMP_TEMP_BUFFER_SIZE)
32 #define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
33 #endif
34
35 #define MIN(x, y)               (((x) < (y)) ? (x) : (y))
36 #define PTR_PLUS(t, p, x)       ((t *)(((char *)(p)) + (x)))
37 #define VPTR_PLUS(p, x)         PTR_PLUS(void, p, x)
38 #define VPTR_INC(p, x)          (p = VPTR_PLUS(p, x))
39
40 static void *gpvTempBuffer;
41 static void *ghTempBufferBlockAlloc;
42
43 static void *GetTempBuffer(void)
44 {
45         if (gpvTempBuffer == NULL) {
46                 enum PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
47                                                       PDUMP_TEMP_BUFFER_SIZE,
48                                                       &gpvTempBuffer,
49                                                       &ghTempBufferBlockAlloc);
50                 if (eError != PVRSRV_OK)
51                         PVR_DPF(PVR_DBG_ERROR,
52                                  "GetTempBuffer: OSAllocMem failed: %d",
53                                  eError);
54         }
55
56         return gpvTempBuffer;
57 }
58
59 static void FreeTempBuffer(void)
60 {
61         if (gpvTempBuffer != NULL) {
62                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PDUMP_TEMP_BUFFER_SIZE,
63                              gpvTempBuffer, ghTempBufferBlockAlloc);
64                 gpvTempBuffer = NULL;
65         }
66 }
67
68 void PDumpInitCommon(void)
69 {
70         (void)GetTempBuffer();
71         PDumpInit();
72 }
73
74 void PDumpDeInitCommon(void)
75 {
76         FreeTempBuffer();
77         PDumpDeInit();
78 }
79
80 enum PVRSRV_ERROR
81 PDumpMemUM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
82            void *pvAltLinAddrUM, void *pvLinAddrUM,
83            struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
84            u32 ui32Offset, u32 ui32Bytes, u32 ui32Flags,
85            void *hUniqueTag)
86 {
87         void *pvAddrUM;
88         void *pvAddrKM;
89         u32 ui32BytesDumped;
90         u32 ui32CurrentOffset;
91
92         if (psMemInfo->pvLinAddrKM != NULL && pvAltLinAddrUM == NULL) {
93                 return PDumpMemKM(NULL, psMemInfo, ui32Offset, ui32Bytes,
94                                   ui32Flags, hUniqueTag);
95         }
96
97         pvAddrUM = (pvAltLinAddrUM != NULL) ? pvAltLinAddrUM :
98                         ((pvLinAddrUM != NULL) ? VPTR_PLUS(pvLinAddrUM,
99                                                           ui32Offset) : NULL);
100
101         pvAddrKM = GetTempBuffer();
102
103         PVR_ASSERT(pvAddrUM != NULL && pvAddrKM != NULL);
104         if (pvAddrUM == NULL || pvAddrKM == NULL) {
105                 PVR_DPF(PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump");
106                 return PVRSRV_ERROR_GENERIC;
107         }
108
109         if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
110                 PDumpCommentWithFlags(ui32Flags,
111                 "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes",
112                                       ui32Bytes, (u32) PDUMP_TEMP_BUFFER_SIZE);
113
114         ui32CurrentOffset = ui32Offset;
115         for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;) {
116                 enum PVRSRV_ERROR eError;
117                 u32 ui32BytesToDump =
118                     MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
119
120                 eError = OSCopyFromUser(psPerProc,
121                                         pvAddrKM, pvAddrUM, ui32BytesToDump);
122                 if (eError != PVRSRV_OK) {
123                         PVR_DPF(PVR_DBG_ERROR,
124                         "PDumpMemUM: OSCopyFromUser failed (%d)", eError);
125                         return eError;
126                 }
127
128                 eError = PDumpMemKM(pvAddrKM, psMemInfo, ui32CurrentOffset,
129                                     ui32BytesToDump, ui32Flags, hUniqueTag);
130                 if (eError != PVRSRV_OK)
131                         return eError;
132
133                 VPTR_INC(pvAddrUM, ui32BytesToDump);
134                 ui32CurrentOffset += ui32BytesToDump;
135                 ui32BytesDumped += ui32BytesToDump;
136         }
137
138         return PVRSRV_OK;
139 }
140
141 #endif