1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
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.
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.
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.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
28 #include "services_headers.h"
31 #if !defined(PDUMP_TEMP_BUFFER_SIZE)
32 #define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
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 #define MAX_PDUMP_MMU_CONTEXTS 10
40 static void *gpvTempBuffer;
41 static void *ghTempBufferBlockAlloc;
42 static u16 gui16MMUContextUsage;
44 static void *GetTempBuffer(void)
46 if (gpvTempBuffer == NULL) {
47 enum PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
48 PDUMP_TEMP_BUFFER_SIZE,
50 &ghTempBufferBlockAlloc);
51 if (eError != PVRSRV_OK)
52 PVR_DPF(PVR_DBG_ERROR,
53 "GetTempBuffer: OSAllocMem failed: %d",
60 static void FreeTempBuffer(void)
62 if (gpvTempBuffer != NULL) {
63 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PDUMP_TEMP_BUFFER_SIZE,
64 gpvTempBuffer, ghTempBufferBlockAlloc);
69 void PDumpInitCommon(void)
71 (void)GetTempBuffer();
75 void PDumpDeInitCommon(void)
81 enum PVRSRV_ERROR 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,
90 u32 ui32CurrentOffset;
92 if (psMemInfo->pvLinAddrKM != NULL && pvAltLinAddrUM == NULL)
93 return PDumpMemKM(NULL, psMemInfo, ui32Offset, ui32Bytes,
94 ui32Flags, hUniqueTag);
96 pvAddrUM = (pvAltLinAddrUM != NULL) ? pvAltLinAddrUM :
97 ((pvLinAddrUM != NULL) ? VPTR_PLUS(pvLinAddrUM,
100 pvAddrKM = GetTempBuffer();
102 PVR_ASSERT(pvAddrUM != NULL && pvAddrKM != NULL);
103 if (pvAddrUM == NULL || pvAddrKM == NULL) {
104 PVR_DPF(PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump");
105 return PVRSRV_ERROR_GENERIC;
108 if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
109 PDumpCommentWithFlags(ui32Flags,
110 "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes",
111 ui32Bytes, (u32) PDUMP_TEMP_BUFFER_SIZE);
113 ui32CurrentOffset = ui32Offset;
114 for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;) {
115 enum PVRSRV_ERROR eError;
116 u32 ui32BytesToDump =
117 MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
119 eError = OSCopyFromUser(psPerProc,
120 pvAddrKM, pvAddrUM, ui32BytesToDump);
121 if (eError != PVRSRV_OK) {
122 PVR_DPF(PVR_DBG_ERROR,
123 "PDumpMemUM: OSCopyFromUser failed (%d), eError");
124 return PVRSRV_ERROR_GENERIC;
127 eError = PDumpMemKM(pvAddrKM, psMemInfo, ui32CurrentOffset,
128 ui32BytesToDump, ui32Flags, hUniqueTag);
130 if (eError != PVRSRV_OK) {
131 if (ui32BytesDumped != 0)
132 PVR_DPF(PVR_DBG_ERROR,
133 "PDumpMemUM: PDumpMemKM failed (%d)",
135 PVR_ASSERT(ui32BytesDumped == 0);
139 VPTR_INC(pvAddrUM, ui32BytesToDump);
140 ui32CurrentOffset += ui32BytesToDump;
141 ui32BytesDumped += ui32BytesToDump;
147 static enum PVRSRV_ERROR _PdumpAllocMMUContext(u32 *pui32MMUContextID)
151 for (i = 0; i < MAX_PDUMP_MMU_CONTEXTS; i++)
152 if ((gui16MMUContextUsage & (1UL << i)) == 0) {
153 gui16MMUContextUsage |= 1UL << i;
154 *pui32MMUContextID = i;
158 PVR_DPF(PVR_DBG_ERROR,
159 "_PdumpAllocMMUContext: no free MMU context ids");
161 return PVRSRV_ERROR_GENERIC;
164 static enum PVRSRV_ERROR _PdumpFreeMMUContext(u32 ui32MMUContextID)
166 if (ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS) {
168 gui16MMUContextUsage &= ~(1UL << ui32MMUContextID);
172 PVR_DPF(PVR_DBG_ERROR,
173 "_PdumpFreeMMUContext: MMU context ids invalid");
175 return PVRSRV_ERROR_GENERIC;
178 enum PVRSRV_ERROR PDumpSetMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
179 char *pszMemSpace, u32 *pui32MMUContextID,
180 u32 ui32MMUType, void *hUniqueTag1,
183 u8 *pui8LinAddr = (u8 *) pvPDCPUAddr;
184 struct IMG_CPU_PHYADDR sCpuPAddr;
185 struct IMG_DEV_PHYADDR sDevPAddr;
186 u32 ui32MMUContextID;
187 enum PVRSRV_ERROR eError;
189 eError = _PdumpAllocMMUContext(&ui32MMUContextID);
190 if (eError != PVRSRV_OK) {
191 PVR_DPF(PVR_DBG_ERROR,
192 "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d",
197 sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
198 sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
200 sDevPAddr.uiAddr &= ~PVRSRV_4K_PAGE_SIZE;
202 PDumpComment("Set MMU Context\r\n");
204 PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n",
205 pszMemSpace, ui32MMUContextID, ui32MMUType, pszMemSpace,
206 hUniqueTag1, sDevPAddr.uiAddr);
208 *pui32MMUContextID = ui32MMUContextID;
213 enum PVRSRV_ERROR PDumpClearMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
215 u32 ui32MMUContextID, u32 ui32MMUType)
217 enum PVRSRV_ERROR eError;
219 PVR_UNREFERENCED_PARAMETER(eDeviceType);
221 PDumpComment("Clear MMU Context\r\n");
223 PDumpComment("MMU :%s:v%d %d\r\n",
224 pszMemSpace, ui32MMUContextID, ui32MMUType);
226 eError = _PdumpFreeMMUContext(ui32MMUContextID);
227 if (eError != PVRSRV_OK) {
228 PVR_DPF(PVR_DBG_ERROR,
229 "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d",