diff options
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/common/mem_debug.c')
-rw-r--r-- | drivers/gpu/pvr/services4/srvkm/common/mem_debug.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c b/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c new file mode 100644 index 000000000000..f79e7cb3d890 --- /dev/null +++ b/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /*************************************************************************/ /*! | ||
2 | @Title Memory debugging routines. | ||
3 | @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved | ||
4 | @Description Adds extra memory to the allocations to trace the memory bounds | ||
5 | and other runtime information. | ||
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 | #ifndef MEM_DEBUG_C | ||
45 | #define MEM_DEBUG_C | ||
46 | |||
47 | #if defined(PVRSRV_DEBUG_OS_MEMORY) | ||
48 | |||
49 | #include "img_types.h" | ||
50 | #include "services_headers.h" | ||
51 | |||
52 | #if defined (__cplusplus) | ||
53 | extern "C" | ||
54 | { | ||
55 | #endif | ||
56 | |||
57 | #define STOP_ON_ERROR 0 | ||
58 | |||
59 | /* | ||
60 | Allocated Memory Layout: | ||
61 | |||
62 | --------- \ | ||
63 | Status [OSMEM_DEBUG_INFO] |- TEST_BUFFER_PADDING_STATUS | ||
64 | --------- < | ||
65 | [0xBB]* [raw bytes] |- ui32Size | ||
66 | --------- < | ||
67 | [0xB2]* [raw bytes] |- TEST_BUFFER_PADDING_AFTER | ||
68 | --------- / | ||
69 | */ | ||
70 | |||
71 | IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize) | ||
72 | { | ||
73 | IMG_UINT8 *pui8Addr; | ||
74 | for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++) | ||
75 | { | ||
76 | if (*pui8Addr != ui8Pattern) | ||
77 | { | ||
78 | return IMG_FALSE; | ||
79 | } | ||
80 | } | ||
81 | return IMG_TRUE; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | This function expects the pointer to the user data, not the debug data. | ||
86 | */ | ||
87 | IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine) | ||
88 | { | ||
89 | OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINTPTR_T)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); | ||
90 | |||
91 | /* invalid pointer */ | ||
92 | if (pvCpuVAddr == IMG_NULL) | ||
93 | { | ||
94 | PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : null pointer" | ||
95 | " - referenced %s:%d - allocated %s:%d", | ||
96 | pvCpuVAddr, | ||
97 | pszFileName, uLine, | ||
98 | psInfo->sFileName, psInfo->uLineNo)); | ||
99 | while (STOP_ON_ERROR); | ||
100 | } | ||
101 | |||
102 | /* align */ | ||
103 | if (((IMG_UINT32)pvCpuVAddr&3) != 0) | ||
104 | { | ||
105 | PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : invalid alignment" | ||
106 | " - referenced %s:%d - allocated %s:%d", | ||
107 | pvCpuVAddr, | ||
108 | pszFileName, uLine, | ||
109 | psInfo->sFileName, psInfo->uLineNo)); | ||
110 | while (STOP_ON_ERROR); | ||
111 | } | ||
112 | |||
113 | /*check guard region before*/ | ||
114 | if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore))) | ||
115 | { | ||
116 | PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : guard region before overwritten" | ||
117 | " - referenced %s:%d - allocated %s:%d", | ||
118 | pvCpuVAddr, | ||
119 | pszFileName, uLine, | ||
120 | psInfo->sFileName, psInfo->uLineNo)); | ||
121 | while (STOP_ON_ERROR); | ||
122 | } | ||
123 | |||
124 | /*check size*/ | ||
125 | if (uSize != psInfo->uSize) | ||
126 | { | ||
127 | PVR_DPF((PVR_DBG_WARNING, | ||
128 | "Pointer 0x%p : supplied size was different to stored size (0x%" | ||
129 | SIZE_T_FMT_LEN "X != 0x%" SIZE_T_FMT_LEN "X)" | ||
130 | " - referenced %s:%d - allocated %s:%d", | ||
131 | pvCpuVAddr, uSize, psInfo->uSize, | ||
132 | pszFileName, uLine, | ||
133 | psInfo->sFileName, psInfo->uLineNo)); | ||
134 | while (STOP_ON_ERROR); | ||
135 | } | ||
136 | |||
137 | /*check size parity*/ | ||
138 | if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize) | ||
139 | { | ||
140 | PVR_DPF((PVR_DBG_WARNING, | ||
141 | "Pointer 0x%p : stored size parity error (0x%" | ||
142 | SIZE_T_FMT_LEN "X != 0x%" SIZE_T_FMT_LEN "X)" | ||
143 | " - referenced %s:%d - allocated %s:%d", | ||
144 | pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck, | ||
145 | pszFileName, uLine, | ||
146 | psInfo->sFileName, psInfo->uLineNo)); | ||
147 | while (STOP_ON_ERROR); | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | /*the stored size is ok, so we use it instead the supplied uSize*/ | ||
152 | uSize = psInfo->uSize; | ||
153 | } | ||
154 | |||
155 | /*check padding after*/ | ||
156 | if (uSize) | ||
157 | { | ||
158 | if (!MemCheck((IMG_VOID*)((IMG_UINTPTR_T)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER)) | ||
159 | { | ||
160 | PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : guard region after overwritten" | ||
161 | " - referenced from %s:%d - allocated from %s:%d", | ||
162 | pvCpuVAddr, | ||
163 | pszFileName, uLine, | ||
164 | psInfo->sFileName, psInfo->uLineNo)); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | /* allocated... */ | ||
169 | if (psInfo->eValid != isAllocated) | ||
170 | { | ||
171 | PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : not allocated (freed? %d)" | ||
172 | " - referenced %s:%d - freed %s:%d", | ||
173 | pvCpuVAddr, psInfo->eValid == isFree, | ||
174 | pszFileName, uLine, | ||
175 | psInfo->sFileName, psInfo->uLineNo)); | ||
176 | while (STOP_ON_ERROR); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc) | ||
181 | { | ||
182 | IMG_SIZE_T i = 0; | ||
183 | |||
184 | for (; i < 128; i++) /*changed to 128 to match the filename array size*/ | ||
185 | { | ||
186 | *pDest = *pSrc; | ||
187 | if (*pSrc == '\0') break; | ||
188 | pDest++; | ||
189 | pSrc++; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags, | ||
194 | IMG_UINT32 ui32Size, | ||
195 | IMG_PVOID *ppvCpuVAddr, | ||
196 | IMG_HANDLE *phBlockAlloc, | ||
197 | IMG_CHAR *pszFilename, | ||
198 | IMG_UINT32 ui32Line) | ||
199 | { | ||
200 | OSMEM_DEBUG_INFO *psInfo; | ||
201 | |||
202 | PVRSRV_ERROR eError; | ||
203 | |||
204 | eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags, | ||
205 | ui32Size + TEST_BUFFER_PADDING, | ||
206 | ppvCpuVAddr, | ||
207 | phBlockAlloc, | ||
208 | pszFilename, | ||
209 | ui32Line); | ||
210 | |||
211 | if (eError != PVRSRV_OK) | ||
212 | { | ||
213 | return eError; | ||
214 | } | ||
215 | |||
216 | OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size); | ||
217 | OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER); | ||
218 | |||
219 | /*fill the dbg info struct*/ | ||
220 | psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr); | ||
221 | |||
222 | OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)); | ||
223 | debug_strcpy(psInfo->sFileName, pszFilename); | ||
224 | psInfo->uLineNo = ui32Line; | ||
225 | psInfo->eValid = isAllocated; | ||
226 | psInfo->uSize = ui32Size; | ||
227 | psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size; | ||
228 | |||
229 | /*point to the user data section*/ | ||
230 | *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINTPTR_T)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS; | ||
231 | |||
232 | #ifdef PVRSRV_LOG_MEMORY_ALLOCS | ||
233 | /*this is here to simplify the surounding logging macro, that is a expression | ||
234 | maybe the macro should be an expression */ | ||
235 | PVR_TRACE(("Allocated pointer (after debug info): 0x%p from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line)); | ||
236 | #endif | ||
237 | |||
238 | return PVRSRV_OK; | ||
239 | } | ||
240 | |||
241 | PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags, | ||
242 | IMG_UINT32 ui32Size, | ||
243 | IMG_PVOID pvCpuVAddr, | ||
244 | IMG_HANDLE hBlockAlloc, | ||
245 | IMG_CHAR *pszFilename, | ||
246 | IMG_UINT32 ui32Line) | ||
247 | { | ||
248 | OSMEM_DEBUG_INFO *psInfo; | ||
249 | |||
250 | /*check dbginfo (arg pointing to user memory)*/ | ||
251 | OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line); | ||
252 | |||
253 | /*mark memory as freed*/ | ||
254 | OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER); | ||
255 | |||
256 | /*point to the starting address of the total allocated memory*/ | ||
257 | psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINTPTR_T) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); | ||
258 | |||
259 | /*update dbg info struct*/ | ||
260 | psInfo->uSize = 0; | ||
261 | psInfo->uSizeParityCheck = 0; | ||
262 | psInfo->eValid = isFree; | ||
263 | psInfo->uLineNo = ui32Line; | ||
264 | debug_strcpy(psInfo->sFileName, pszFilename); | ||
265 | |||
266 | return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line); | ||
267 | } | ||
268 | |||
269 | #if defined (__cplusplus) | ||
270 | |||
271 | } | ||
272 | #endif | ||
273 | |||
274 | #endif /* PVRSRV_DEBUG_OS_MEMORY */ | ||
275 | |||
276 | #endif /* MEM_DEBUG_C */ | ||