diff options
author | Alistair Strachan <alistair.strachan@imgtec.com> | 2012-06-14 10:08:18 +0100 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2012-06-14 21:36:42 -0700 |
commit | ca5c535e1e9cae41831adae5a29a76f848f7f792 (patch) | |
tree | ce4884871e95ef05346a5b91c4037cfb2fcf84bb /drivers/gpu | |
parent | fb49c21c25ded40a7616268d0be84422ceb0f709 (diff) | |
download | kernel_samsung_crespo-ca5c535e1e9cae41831adae5a29a76f848f7f792.zip kernel_samsung_crespo-ca5c535e1e9cae41831adae5a29a76f848f7f792.tar.gz kernel_samsung_crespo-ca5c535e1e9cae41831adae5a29a76f848f7f792.tar.bz2 |
gpu: pvr: Add thread safety checks to SGX MMU code.
The SGX MMU code was not designed to be used from multiple driver
threads. One theory is that somehow the driver does sometimes use
the MMU code from multiple threads, which could cause corruption
of meta data.
We must allow PID 1 through because the kernel uses this ID before
userspace is up, and the module_init code interacts with the MMU
subsystem.
Otherwise, check that the outer bridge lock is held. If it is held,
check the PID of the caller matches the PID holding the bridge lock.
Change-Id: I35f42f251316b158576e5d853f8099e24942b4f2
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/pvr/mutex.c | 16 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/mmu.c | 93 |
2 files changed, 107 insertions, 2 deletions
diff --git a/drivers/gpu/pvr/mutex.c b/drivers/gpu/pvr/mutex.c index 742fa03..aedc8d0 100644 --- a/drivers/gpu/pvr/mutex.c +++ b/drivers/gpu/pvr/mutex.c @@ -37,10 +37,13 @@ #include <services.h> #include "mutex.h" - +#include "osfunc.h" #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +extern PVRSRV_LINUX_MUTEX gPVRSRVLock; +IMG_UINT32 ui32BridgeLockPID = 0; + IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) { mutex_init(psPVRSRVMutex); @@ -49,6 +52,8 @@ IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) { mutex_lock(psPVRSRVMutex); + if(psPVRSRVMutex == &gPVRSRVLock) + ui32BridgeLockPID = OSGetCurrentProcessIDKM(); } PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) @@ -59,17 +64,24 @@ PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) } else { + if(psPVRSRVMutex == &gPVRSRVLock) + ui32BridgeLockPID = OSGetCurrentProcessIDKM(); return PVRSRV_OK; } } IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) { - return mutex_trylock(psPVRSRVMutex); + IMG_UINT32 err = mutex_trylock(psPVRSRVMutex); + if(psPVRSRVMutex == &gPVRSRVLock) + ui32BridgeLockPID = OSGetCurrentProcessIDKM(); + return err; } IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) { + if(psPVRSRVMutex == &gPVRSRVLock) + ui32BridgeLockPID = 0; mutex_unlock(psPVRSRVMutex); } diff --git a/drivers/gpu/pvr/sgx/mmu.c b/drivers/gpu/pvr/sgx/mmu.c index 9d124f5..d4c7e0b 100644 --- a/drivers/gpu/pvr/sgx/mmu.c +++ b/drivers/gpu/pvr/sgx/mmu.c @@ -39,6 +39,8 @@ #include "sgx_bridge_km.h" #include "pdump_osfunc.h" +extern IMG_UINT32 ui32BridgeLockPID; + #define UINT32_MAX_VALUE 0xFFFFFFFFUL #define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT)) @@ -733,6 +735,12 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS SysAcquireData(&psSysData); + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift; @@ -912,6 +920,13 @@ _DeferredFreePageTables (MMU_HEAP *pMMUHeap) IMG_UINT32 *pui32Tmp; IMG_UINT32 j; #endif + + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + #if defined(PDUMP) PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)", pMMUHeap->psMMUContext->ui32PDumpMMUContextID, @@ -981,6 +996,12 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT IMG_UINT32 ui32ModifiedCachelines[BRN31620_CACHE_FLUSH_INDEX_SIZE]; #endif + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + #if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32 PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE)); @@ -1993,6 +2014,12 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext) MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList; #endif + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + SysAcquireData(&psSysData); #if defined(PDUMP) @@ -2194,6 +2221,12 @@ MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap) IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE; #endif + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; @@ -2270,6 +2303,12 @@ MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap, IMG_UINT32 *pui32Tmp; IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + #if !defined (PDUMP) PVR_UNREFERENCED_PARAMETER(hUniqueTag); #endif @@ -2405,6 +2444,12 @@ MMU_Create (MMU_CONTEXT *psMMUContext, PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib); + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + PVR_ASSERT (psDevArena != IMG_NULL); if (psDevArena == IMG_NULL) @@ -2594,6 +2639,12 @@ ErrorFreeHeap: IMG_VOID MMU_Delete (MMU_HEAP *pMMUHeap) { + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + if (pMMUHeap != IMG_NULL) { PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete")); @@ -2633,6 +2684,12 @@ MMU_Alloc (MMU_HEAP *pMMUHeap, { IMG_BOOL bStatus; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x", uSize, uFlags, uDevVAddrAlignment)); @@ -2698,6 +2755,12 @@ MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size) { PVR_ASSERT (pMMUHeap != IMG_NULL); + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + if (pMMUHeap == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter")); @@ -2834,6 +2897,12 @@ MMU_MapPage (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32MMUFlags = 0; MMU_PT_INFO **ppsPTInfoList; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0); @@ -2942,6 +3011,12 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap, IMG_UINT32 uCount, i; IMG_DEV_PHYADDR DevPAddr; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + PVR_ASSERT (pMMUHeap != IMG_NULL); #if defined(PDUMP) @@ -2991,6 +3066,12 @@ MMU_MapPages (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32VAdvance; IMG_UINT32 ui32PAdvance; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + PVR_ASSERT (pMMUHeap != IMG_NULL); PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, size=0x%x", @@ -3058,6 +3139,12 @@ MMU_MapShadow (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32VAdvance; IMG_UINT32 ui32PAdvance; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + #if !defined (PDUMP) PVR_UNREFERENCED_PARAMETER(hUniqueTag); #endif @@ -3147,6 +3234,12 @@ MMU_UnmapPages (MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PTIndex; IMG_UINT32 *pui32Tmp; + if(OSGetCurrentProcessIDKM() != 1 && ui32BridgeLockPID != OSGetCurrentProcessIDKM()) + { + PVR_DPF((PVR_DBG_ERROR, "ERROR!!: MMU code used by pid %u but bridge lock from pid %u", OSGetCurrentProcessIDKM(), ui32BridgeLockPID)); + PVR_ASSERT(0); + } + #if !defined (PDUMP) PVR_UNREFERENCED_PARAMETER(hUniqueTag); #endif |