diff options
Diffstat (limited to 'drivers/gpu/pvr/mem_debug.c')
-rw-r--r-- | drivers/gpu/pvr/mem_debug.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/mem_debug.c b/drivers/gpu/pvr/mem_debug.c new file mode 100644 index 0000000..b9cc780 --- /dev/null +++ b/drivers/gpu/pvr/mem_debug.c @@ -0,0 +1,247 @@ +/********************************************************************** + * + * Copyright (C) Imagination Technologies Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful but, except + * as otherwise stated in writing, without any warranty; without even the + * implied warranty of merchantability or fitness for a particular purpose. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Imagination Technologies Ltd. <gpl-support@imgtec.com> + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef MEM_DEBUG_C +#define MEM_DEBUG_C + +#if defined(PVRSRV_DEBUG_OS_MEMORY) + +#include "img_types.h" +#include "services_headers.h" + +#if defined (__cplusplus) +extern "C" +{ +#endif + +#define STOP_ON_ERROR 0 + + + + + + + + IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize) + { + IMG_UINT8 *pui8Addr; + for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++) + { + if (*pui8Addr != ui8Pattern) + { + return IMG_FALSE; + } + } + return IMG_TRUE; + } + + + + IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine) + { + OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); + + + if (pvCpuVAddr == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer" + " - referenced %s:%d - allocated %s:%d", + pvCpuVAddr, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + + + if (((IMG_UINT32)pvCpuVAddr&3) != 0) + { + PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment" + " - referenced %s:%d - allocated %s:%d", + pvCpuVAddr, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + + + if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore))) + { + PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten" + " - referenced %s:%d - allocated %s:%d", + pvCpuVAddr, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + + + if (uSize != psInfo->uSize) + { + PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)" + " - referenced %s:%d - allocated %s:%d", + pvCpuVAddr, uSize, psInfo->uSize, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + + + if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize) + { + PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)" + " - referenced %s:%d - allocated %s:%d", + pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + else + { + + uSize = psInfo->uSize; + } + + + if (uSize) + { + if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER)) + { + PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten" + " - referenced from %s:%d - allocated from %s:%d", + pvCpuVAddr, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + } + } + + + if (psInfo->eValid != isAllocated) + { + PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)" + " - referenced %s:%d - freed %s:%d", + pvCpuVAddr, psInfo->eValid == isFree, + pszFileName, uLine, + psInfo->sFileName, psInfo->uLineNo)); + while (STOP_ON_ERROR); + } + } + + IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc) + { + IMG_SIZE_T i = 0; + + for (; i < 128; i++) + { + *pDest = *pSrc; + if (*pSrc == '\0') break; + pDest++; + pSrc++; + } + } + + PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags, + IMG_UINT32 ui32Size, + IMG_PVOID *ppvCpuVAddr, + IMG_HANDLE *phBlockAlloc, + IMG_CHAR *pszFilename, + IMG_UINT32 ui32Line) + { + OSMEM_DEBUG_INFO *psInfo; + + PVRSRV_ERROR eError; + + eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags, + ui32Size + TEST_BUFFER_PADDING, + ppvCpuVAddr, + phBlockAlloc, + pszFilename, + ui32Line); + + if (eError != PVRSRV_OK) + { + return eError; + } + + OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size); + OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER); + + + psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr); + + OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)); + debug_strcpy(psInfo->sFileName, pszFilename); + psInfo->uLineNo = ui32Line; + psInfo->eValid = isAllocated; + psInfo->uSize = ui32Size; + psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size; + + + *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS; + +#ifdef PVRSRV_LOG_MEMORY_ALLOCS + + PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line)); +#endif + + return PVRSRV_OK; + } + + PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags, + IMG_UINT32 ui32Size, + IMG_PVOID pvCpuVAddr, + IMG_HANDLE hBlockAlloc, + IMG_CHAR *pszFilename, + IMG_UINT32 ui32Line) + { + OSMEM_DEBUG_INFO *psInfo; + + + OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line); + + + OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER); + + + psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); + + + psInfo->uSize = 0; + psInfo->uSizeParityCheck = 0; + psInfo->eValid = isFree; + psInfo->uLineNo = ui32Line; + debug_strcpy(psInfo->sFileName, pszFilename); + + return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line); + } + +#if defined (__cplusplus) + +} +#endif + +#endif + +#endif |