summaryrefslogtreecommitdiff
path: root/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c')
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c178
1 files changed, 102 insertions, 76 deletions
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 0c71e28e868c..43c9297f6c3d 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
@@ -97,6 +97,43 @@ static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
static gctPOINTER mirrorPageTableMutex = gcvNULL;
#endif
+static void
+_WritePageEntry(
+ IN gctUINT32_PTR PageEntry,
+ IN gctUINT32 EntryValue
+ )
+{
+ static gctUINT16 data = 0xff00;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ *PageEntry = gcmSWAB32(EntryValue);
+ }
+ else
+ {
+ *PageEntry = EntryValue;
+ }
+}
+
+static gctUINT32
+_ReadPageEntry(
+ IN gctUINT32_PTR PageEntry
+ )
+{
+ static gctUINT16 data = 0xff00;
+ gctUINT32 entryValue;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ entryValue = *PageEntry;
+ return gcmSWAB32(entryValue);
+ }
+ else
+ {
+ return *PageEntry;
+ }
+}
+
static gceSTATUS
_FillPageTable(
IN gctUINT32_PTR PageTable,
@@ -108,7 +145,7 @@ _FillPageTable(
for (i = 0; i < PageCount; i++)
{
- PageTable[i] = EntryValue;
+ _WritePageEntry(PageTable + i, EntryValue);
}
return gcvSTATUS_OK;
@@ -132,16 +169,16 @@ _Link(
gctUINT32_PTR pageTable = Mmu->pageTableLogical;
/* Dispatch on node type. */
- switch (gcmENTRY_TYPE(pageTable[Index]))
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[Index])))
{
case gcvMMU_SINGLE:
/* Set single index. */
- pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
+ _WritePageEntry(&pageTable[Index], (Next << 8) | gcvMMU_SINGLE);
break;
case gcvMMU_FREE:
/* Set index. */
- pageTable[Index + 1] = Next;
+ _WritePageEntry(&pageTable[Index + 1], Next);
break;
default:
@@ -167,13 +204,13 @@ _AddFree(
if (Count == 1)
{
/* Initialize a single page node. */
- pageTable[Node] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+ _WritePageEntry(pageTable + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
}
else
{
/* Initialize the node. */
- pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
- pageTable[Node + 1] = ~0U;
+ _WritePageEntry(pageTable + Node + 0, (Count << 8) | gcvMMU_FREE);
+ _WritePageEntry(pageTable + Node + 1, ~0U);
}
/* Append the node. */
@@ -196,7 +233,7 @@ _Collect(
for (i = 0; i < Mmu->pageTableEntries; ++i)
{
/* Dispatch based on type of page. */
- switch (gcmENTRY_TYPE(pageTable[i]))
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[i])))
{
case gcvMMU_USED:
/* Used page, so close any open node. */
@@ -229,10 +266,10 @@ _Collect(
}
/* Advance the count. */
- count += pageTable[i] >> 8;
+ count += _ReadPageEntry(&pageTable[i]) >> 8;
/* Advance the index into the page table. */
- i += (pageTable[i] >> 8) - 1;
+ i += (_ReadPageEntry(&pageTable[i]) >> 8) - 1;
break;
default:
@@ -341,19 +378,20 @@ _FillFlatMapping(
gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
}
- *(Mmu->mtlbLogical + mStart)
- = stlb->physBase
- /* 64KB page size */
- | (1 << 2)
- /* Ignore exception */
- | (0 << 1)
- /* Present */
- | (1 << 0);
+ _WritePageEntry(Mmu->mtlbLogical + mStart,
+ stlb->physBase
+ /* 64KB page size */
+ | (1 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0)
+ );
#if gcdMMU_TABLE_DUMP
gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
__FUNCTION__, __LINE__,
mStart,
- *(Mmu->mtlbLogical + mStart));
+ _ReadPageEntry(Mmu->mtlbLogical + mStart));
#endif
stlb->mtlbIndex = mStart;
@@ -368,12 +406,12 @@ _FillFlatMapping(
while (sStart <= last)
{
gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
- *(stlb->logical + sStart) = _SetPage(start);
+ _WritePageEntry(stlb->logical + sStart, _SetPage(start));
#if gcdMMU_TABLE_DUMP
gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
__FUNCTION__, __LINE__,
sStart,
- *(stlb->logical + sStart));
+ _ReadPageEntry(stlb->logical + sStart));
#endif
/* next page. */
start += gcdMMU_PAGE_64K_SIZE;
@@ -428,7 +466,7 @@ OnError:
if (pre->mtlbEntryNum != 0)
{
gcmkASSERT(pre->mtlbEntryNum == 1);
- *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
}
gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
@@ -493,8 +531,8 @@ _SetupDynamicSpace(
/* Initilization. */
pageTable = Mmu->pageTableLogical;
- pageTable[0] = (Mmu->pageTableEntries << 8) | gcvMMU_FREE;
- pageTable[1] = ~0U;
+ _WritePageEntry(pageTable, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
+ _WritePageEntry(pageTable + 1, ~0U);
Mmu->heapList = 0;
Mmu->freeNodes = gcvFALSE;
@@ -509,18 +547,20 @@ _SetupDynamicSpace(
/* Map to Master TLB. */
for (; i < gcdMMU_MTLB_ENTRY_NUM; i++)
{
- Mmu->mtlbLogical[i] = physical
- /* 4KB page size */
- | (0 << 2)
- /* Ignore exception */
- | (0 << 1)
- /* Present */
- | (1 << 0);
+ _WritePageEntry(Mmu->mtlbLogical + i,
+ physical
+ /* 4KB page size */
+ | (0 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0)
+ );
#if gcdMMU_TABLE_DUMP
gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
__FUNCTION__, __LINE__,
i,
- *(Mmu->mtlbLogical + i));
+ _ReadPageEntry(Mmu->mtlbLogical + i));
#endif
physical += gcdMMU_STLB_4K_SIZE;
}
@@ -645,18 +685,11 @@ _Construct(
pageTable = mmu->pageTableLogical;
#if gcdMMU_CLEAR_VALUE
- {
- gctUINT32 i;
-
- for (i = 0; i < mmu->pageTableEntries; ++i)
- {
- pageTable[i] = gcdMMU_CLEAR_VALUE;
- }
- }
+ _FillPageTable(pageTable, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
#endif
- pageTable[0] = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
- pageTable[1] = ~0U;
+ _WritePageEntry(pageTable, (mmu->pageTableEntries << 8) | gcvMMU_FREE);
+ _WritePageEntry(pageTable + 1, ~0U);
mmu->heapList = 0;
mmu->freeNodes = gcvFALSE;
@@ -797,7 +830,7 @@ _Destroy(
if (pre->mtlbEntryNum != 0)
{
gcmkASSERT(pre->mtlbEntryNum == 1);
- *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
#if gcdMMU_TABLE_DUMP
gckOS_Print("%s(%d): clean MTLB[%d]\n",
__FUNCTION__, __LINE__,
@@ -1044,7 +1077,7 @@ _AllocatePages(
for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
{
/* Check the node type. */
- switch (gcmENTRY_TYPE(pageTable[index]))
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
{
case gcvMMU_SINGLE:
/* Single odes are valid if we only need 1 page. */
@@ -1056,13 +1089,13 @@ _AllocatePages(
{
/* Move to next node. */
previous = index;
- index = pageTable[index] >> 8;
+ index = _ReadPageEntry(&pageTable[index]) >> 8;
}
break;
case gcvMMU_FREE:
/* Test if the node has enough space. */
- if (PageCount <= (pageTable[index] >> 8))
+ if (PageCount <= (_ReadPageEntry(&pageTable[index]) >> 8))
{
gotIt = gcvTRUE;
}
@@ -1070,7 +1103,7 @@ _AllocatePages(
{
/* Move to next node. */
previous = index;
- index = pageTable[index + 1];
+ index = _ReadPageEntry(&pageTable[index + 1]);
}
break;
@@ -1099,36 +1132,36 @@ _AllocatePages(
}
}
- switch (gcmENTRY_TYPE(pageTable[index]))
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
{
case gcvMMU_SINGLE:
/* Unlink single node from free list. */
gcmkONERROR(
- _Link(Mmu, previous, pageTable[index] >> 8));
+ _Link(Mmu, previous, _ReadPageEntry(&pageTable[index]) >> 8));
break;
case gcvMMU_FREE:
/* Check how many pages will be left. */
- left = (pageTable[index] >> 8) - PageCount;
+ left = (_ReadPageEntry(&pageTable[index]) >> 8) - PageCount;
switch (left)
{
case 0:
/* The entire node is consumed, just unlink it. */
gcmkONERROR(
- _Link(Mmu, previous, pageTable[index + 1]));
+ _Link(Mmu, previous, _ReadPageEntry(&pageTable[index + 1])));
break;
case 1:
/* One page will remain. Convert the node to a single node and
** advance the index. */
- pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
+ _WritePageEntry(&pageTable[index], (_ReadPageEntry(&pageTable[index + 1]) << 8) | gcvMMU_SINGLE);
index ++;
break;
default:
/* Enough pages remain for a new node. However, we will just adjust
** the size of the current node and advance the index. */
- pageTable[index] = (left << 8) | gcvMMU_FREE;
+ _WritePageEntry(&pageTable[index], (left << 8) | gcvMMU_FREE);
index += left;
break;
}
@@ -1232,35 +1265,32 @@ _FreePages(
#if gcdMMU_CLEAR_VALUE
if (Mmu->hardware->mmuVersion == 0)
{
- gctUINT32 i;
-
- for (i = 0; i < PageCount; ++i)
- {
- pageTable[i] = gcdMMU_CLEAR_VALUE;
- }
+ _FillPageTable(pageTable, PageCount, gcdMMU_CLEAR_VALUE);
}
#endif
if (PageCount == 1)
{
/* Single page node. */
- pageTable[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE
+ _WritePageEntry(pageTable,
+ (~((1U<<8)-1)) | gcvMMU_SINGLE
#if gcdUSE_MMU_EXCEPTION
- /* Enable exception */
- | (1 << 1)
+ /* Enable exception */
+ | 1 << 1
#endif
- ;
+ );
}
else
{
/* Mark the node as free. */
- pageTable[0] = (PageCount << 8) | gcvMMU_FREE
+ _WritePageEntry(pageTable,
+ (PageCount << 8) | gcvMMU_FREE
#if gcdUSE_MMU_EXCEPTION
- /* Enable exception */
- | (1 << 1)
+ /* Enable exception */
+ | 1 << 1
#endif
- ;
- pageTable[1] = ~0U;
+ );
+ _WritePageEntry(pageTable + 1, ~0U);
#if gcdUSE_MMU_EXCEPTION
/* Enable exception */
@@ -1509,12 +1539,8 @@ gckMMU_SetPage(
data = _SetPage(PageAddress);
}
- if (Mmu->hardware->bigEndian)
- {
- data = gcmSWAB32(data);
- }
+ _WritePageEntry(PageEntry, data);
- *PageEntry = data;
#if gcdMIRROR_PAGETABLE
for (i = 0; i < mirrorPageTable->reference; i++)
{
@@ -1526,11 +1552,11 @@ gckMMU_SetPage(
if (mmu->hardware->mmuVersion == 0)
{
- *pageEntry = PageAddress;
+ _WritePageEntry(pageEntry, PageAddress);
}
else
{
- *pageEntry = _SetPage(PageAddress);
+ _WritePageEntry(pageEntry, _SetPage(PageAddress));
}
}
@@ -1734,7 +1760,7 @@ gckMMU_DumpPageTableEntry(
* gcdMMU_STLB_4K_ENTRY_NUM
+ stlb;
- gcmkPRINT(" Page table entry = 0x%08X", pageTable[index]);
+ gcmkPRINT(" Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
}
gcmkFOOTER_NO();