diff options
author | Loren Huang <b02279@freescale.com> | 2014-01-09 17:38:37 +0800 |
---|---|---|
committer | Richard Liu <r66033@freescale.com> | 2014-05-15 15:07:09 +0800 |
commit | eb955578de7088c054a9a3ace150e788b27cada6 (patch) | |
tree | 5a2beb77bfb7503bc3734044631afba6f2416f54 | |
parent | 36a4377215ccb3bc30a9f906e65db920ebce8632 (diff) |
ENGR00294354 gpu:Using vitural memory cause AXI bus error
There are two possible reasons to cause AXI bus error
1.Allocate Tile status buffer from virtual memory. It seems gc2000
and gc880 doesn't support tile status buffer from virtual memory.
2.Stream buffer using very beginning gpu mmu address. In this condition,
a faked non gpu mmu address maybe generated and fill into gpu which cause
AXI bus error.
[DATE]09-01-2014
Signed-off-by: Loren Huang <b02279@freescale.com>
Acked-by: Shawn Guo
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c | 5 | ||||
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h | 6 | ||||
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c | 120 | ||||
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c | 3 | ||||
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h | 9 | ||||
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h | 1 |
6 files changed, 139 insertions, 5 deletions
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c index 88535488b916..b75e7f64030e 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c @@ -933,6 +933,7 @@ gckKERNEL_Dispatch( #if !USE_NEW_LINUX_SIGNAL gctSIGNAL signal; #endif + gceSURF_TYPE type; gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x", Kernel, FromUser, Interface); @@ -1169,6 +1170,8 @@ gckKERNEL_Dispatch( break; case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY: + type = Interface->u.AllocateLinearVideoMemory.type; + /* Allocate memory. */ gcmkONERROR( _AllocateMemory(Kernel, @@ -1181,6 +1184,7 @@ gckKERNEL_Dispatch( if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) { bytes = node->VidMem.bytes; + node->VidMem.type = type; gcmkONERROR( gckKERNEL_AddProcessDB(Kernel, @@ -1192,6 +1196,7 @@ gckKERNEL_Dispatch( else { bytes = node->Virtual.bytes; + node->Virtual.type = type; if(node->Virtual.contiguous) { diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h index 6126bae3201d..d7ff9cf16372 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h @@ -734,6 +734,9 @@ typedef union _gcuVIDMEM_NODE #if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG gctPOINTER kernelVirtual; #endif + + /* Surface type. */ + gceSURF_TYPE type; } VidMem; @@ -790,6 +793,9 @@ typedef union _gcuVIDMEM_NODE /* */ gcsVIDMEM_NODE_SHARED_INFO sharedInfo; + + /* Surface type. */ + gceSURF_TYPE type; } Virtual; } diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c index e4ca49725dce..456ec246241e 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c @@ -46,6 +46,9 @@ gceMMU_TYPE; # define gcdMMU_CLEAR_VALUE 0x00000ABC #endif +/* VIV: Start GPU address for gcvSURF_VERTEX. */ +#define gcdVERTEX_START (128 << 10) + typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR; typedef struct _gcsMMU_STLB @@ -973,6 +976,88 @@ _Destroy( return gcvSTATUS_OK; } +/******************************************************************************* +** _AdjstIndex +** +** Adjust the index from which we search for a usable node to make sure +** index allocated is greater than Start. +*/ +gceSTATUS +_AdjustIndex( + IN gckMMU Mmu, + IN gctUINT32 Index, + IN gctUINT32 PageCount, + IN gctUINT32 Start, + OUT gctUINT32 * IndexAdjusted + ) +{ + gceSTATUS status; + gctUINT32 index = Index; + gctUINT32_PTR map = Mmu->pageTableLogical; + + gcmkHEADER(); + + for (; index < Mmu->pageTableEntries;) + { + gctUINT32 result = 0; + gctUINT32 nodeSize = 0; + + if (index >= Start) + { + break; + } + + switch (gcmENTRY_TYPE(map[index])) + { + case gcvMMU_SINGLE: + nodeSize = 1; + break; + + case gcvMMU_FREE: + nodeSize = map[index] >> 8; + break; + + default: + gcmkFATAL("MMU table correcupted at index %u!", index); + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + } + + if (nodeSize > PageCount) + { + result = index + (nodeSize - PageCount); + + if (result >= Start) + { + break; + } + } + + switch (gcmENTRY_TYPE(map[index])) + { + case gcvMMU_SINGLE: + index = map[index] >> 8; + break; + + case gcvMMU_FREE: + index = map[index + 1]; + break; + + default: + gcmkFATAL("MMU table correcupted at index %u!", index); + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + } + } + + *IndexAdjusted = index; + + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + +OnError: + gcmkFOOTER(); + return status; +} + gceSTATUS gckMMU_Construct( IN gckKERNEL Kernel, @@ -1136,6 +1221,7 @@ gceSTATUS _AllocatePages( IN gckMMU Mmu, IN gctSIZE_T PageCount, + IN gceSURF_TYPE Type, OUT gctPOINTER * PageTable, OUT gctUINT32 * Address ) @@ -1170,8 +1256,21 @@ _AllocatePages( /* Cast pointer to page table. */ for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;) { + index = Mmu->heapList; + + if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX)) + { + gcmkONERROR(_AdjustIndex( + Mmu, + index, + PageCount, + gcdVERTEX_START / gcmSIZEOF(gctUINT32), + &index + )); + } + /* Walk the heap list. */ - for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);) + for (; !gotIt && (index < Mmu->pageTableEntries);) { /* Check the node type. */ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index]))) @@ -1423,6 +1522,19 @@ gckMMU_AllocatePages( OUT gctUINT32 * Address ) { + return gckMMU_AllocatePagesEx( + Mmu, PageCount, gcvSURF_UNKNOWN, PageTable, Address); +} + +gceSTATUS +gckMMU_AllocatePagesEx( + IN gckMMU Mmu, + IN gctSIZE_T PageCount, + IN gceSURF_TYPE Type, + OUT gctPOINTER * PageTable, + OUT gctUINT32 * Address + ) +{ #if gcdMIRROR_PAGETABLE gceSTATUS status; gctPOINTER pageTable; @@ -1440,7 +1552,7 @@ gckMMU_AllocatePages( { if (Mmu == mirrorPageTable->mmus[i]) { - gcmkONERROR(_AllocatePages(Mmu, PageCount, PageTable, Address)); + gcmkONERROR(_AllocatePages(Mmu, PageCount, Type, PageTable, Address)); allocated = gcvTRUE; } } @@ -1452,7 +1564,7 @@ gckMMU_AllocatePages( if (Mmu != mmu) { - gcmkONERROR(_AllocatePages(mmu, PageCount, &pageTable, &address)); + gcmkONERROR(_AllocatePages(mmu, PageCount, Type, &pageTable, &address)); gcmkASSERT(address == *Address); } } @@ -1478,7 +1590,7 @@ OnError: return status; #else - return _AllocatePages(Mmu, PageCount, PageTable, Address); + return _AllocatePages(Mmu, PageCount, Type, PageTable, Address); #endif } diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c index 3b5dd82cbad0..3d861bece9c4 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c @@ -1814,8 +1814,9 @@ gckVIDMEM_Lock( { /* Allocate pages inside the MMU. */ gcmkONERROR( - gckMMU_AllocatePages(Kernel->mmu, + gckMMU_AllocatePagesEx(Kernel->mmu, Node->Virtual.pageCount, + Node->Virtual.type, &Node->Virtual.pageTables[Kernel->core], &Node->Virtual.addresses[Kernel->core])); } diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h index 7312cc24d598..63d5dad3a75a 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h @@ -2562,6 +2562,15 @@ gckMMU_AllocatePages( OUT gctUINT32 * Address ); +gceSTATUS +gckMMU_AllocatePagesEx( + IN gckMMU Mmu, + IN gctSIZE_T PageCount, + IN gceSURF_TYPE Type, + OUT gctPOINTER * PageTable, + OUT gctUINT32 * Address + ); + /* Remove a page table from the MMU. */ gceSTATUS gckMMU_FreePages( diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h index b2ffac335e22..522253779182 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h @@ -166,6 +166,7 @@ typedef enum _gceFEATURE gcvFEATURE_LINEAR_RENDER_TARGET, gcvFEATURE_BUG_FIXES8, gcvFEATURE_HALTI2, + gcvFEATURE_MMU, } gceFEATURE; |