blob: 27e9f2f7590beee90f8b9983baad8722af2ecf61 [file] [log] [blame]
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2020 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2020 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "shared/gc_hal_types.h"
#include "gc_hal_base.h"
#include "gc_hal_security_interface.h"
#include "gc_hal_ta.h"
#include "gc_hal_ta_hardware.h"
#include "gc_hal.h"
#include "gc_feature_database.h"
#define _GC_OBJ_ZONE 1
#define SRC_MAX 8
#define RECT_ADDR_OFFSET 3
#define INVALID_ADDRESS ~0U
/******************************************************************************\
********************************* Support Code *********************************
\******************************************************************************/
static gceSTATUS
_IdentifyHardwareByDatabase(
IN gcTA_HARDWARE Hardware
)
{
gceSTATUS status;
gctUINT32 chipIdentity;
gcsFEATURE_DATABASE *database;
gctaOS os = Hardware->os;
gcmkHEADER();
/***************************************************************************
** Get chip ID and revision.
*/
/* Read chip identity register. */
gcmkONERROR(gctaOS_ReadRegister(os, Hardware->ta->core, 0x00018, &chipIdentity));
/* Special case for older graphic cores. */
if (((((gctUINT32) (chipIdentity)) >> (0 ?
31:24) & ((gctUINT32) ((((1 ?
31:24) - (0 ?
31:24) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:24) - (0 ?
31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ?
31:24) - (0 ?
31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
{
Hardware->chipModel = gcv500;
Hardware->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
}
else
{
/* Read chip identity register. */
gcmkONERROR(
gctaOS_ReadRegister(os, Hardware->ta->core,
0x00020,
(gctUINT32_PTR) &Hardware->chipModel));
if (((Hardware->chipModel & 0xFF00) == 0x0400)
&& (Hardware->chipModel != 0x0420)
&& (Hardware->chipModel != 0x0428))
{
Hardware->chipModel = (gceCHIPMODEL) (Hardware->chipModel & 0x0400);
}
/* Read CHIP_REV register. */
gcmkONERROR(
gctaOS_ReadRegister(os, Hardware->ta->core,
0x00024,
&Hardware->chipRevision));
if ((Hardware->chipModel == gcv300)
&& (Hardware->chipRevision == 0x2201)
)
{
gctUINT32 chipDate;
gctUINT32 chipTime;
/* Read date and time registers. */
gcmkONERROR(
gctaOS_ReadRegister(os, Hardware->ta->core,
0x00028,
&chipDate));
gcmkONERROR(
gctaOS_ReadRegister(os, Hardware->ta->core,
0x0002C,
&chipTime));
if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
{
/* This IP has an ECO; put the correct revision in it. */
Hardware->chipRevision = 0x1051;
}
}
gcmkONERROR(
gctaOS_ReadRegister(os, Hardware->ta->core,
0x000A8,
&Hardware->productID));
}
gcmkVERIFY_OK(gctaOS_ReadRegister(
os, Hardware->ta->core,
0x000E8
,
&Hardware->ecoID
));
gcmkVERIFY_OK(gctaOS_ReadRegister(
os, Hardware->ta->core,
0x00030
,
&Hardware->customerID
));
/***************************************************************************
** Get chip features.
*/
database =
Hardware->featureDatabase =
gcQueryFeatureDB(
Hardware->chipModel,
Hardware->chipRevision,
Hardware->productID,
Hardware->ecoID,
Hardware->customerID
);
if (database == gcvNULL)
{
gcmkPRINT("[galcore]: Feature database is not found,"
"chipModel=0x%0x, chipRevision=0x%x, productID=0x%x, ecoID=0x%x, customerID=0x%x",
Hardware->chipModel,
Hardware->chipRevision,
Hardware->productID,
Hardware->ecoID,
Hardware->customerID);
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gctaHARDWARE_SetMMUStates(
IN gcTA_HARDWARE Hardware,
IN gctPOINTER MtlbAddress,
IN gceMMU_MODE Mode,
IN gctPOINTER SafeAddress,
IN gctPOINTER Logical,
IN OUT gctUINT32 * Bytes
)
{
gceSTATUS status;
gctUINT32 config;
gctUINT32 extMtlb;
gctPHYS_ADDR_T physical;
gctUINT32_PTR buffer;
gctUINT32 reserveBytes = 2 * 4;
gcsMMU_TABLE_ARRAY_ENTRY * entry;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
entry = (gcsMMU_TABLE_ARRAY_ENTRY *) Hardware->pagetableArray.logical;
/* Convert logical address into physical address. */
gcmkONERROR(
gctaOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &physical));
config = (gctUINT32)(physical & 0xFFFFFFFF);
extMtlb = (gctUINT32)(physical >> 32);
/* more than 40bit physical address */
if (extMtlb & 0xFFFFFF00)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
switch (Mode)
{
case gcvMMU_MODE_1K:
if (config & 0x3FF)
{
gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
}
config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
break;
case gcvMMU_MODE_4K:
if (config & 0xFFF)
{
gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
}
config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
break;
default:
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if (Logical != gcvNULL)
{
buffer = Logical;
/* Setup page table array entry. */
entry->low = config;
entry->high = extMtlb;
/* Setup command buffer to load index 0 of page table array. */
*buffer++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x006B) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
*buffer++
= (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) &((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
16:16) - (0 ?
16:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
16:16) - (0 ?
16:16) + 1))))))) << (0 ?
16:16))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
16:16) - (0 ?
16:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))));
}
if (Bytes != gcvNULL)
{
*Bytes = reserveBytes;
}
/* Return the status. */
gcmkFOOTER_NO();
return status;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gctaHARDWARE_End(
IN gcTA_HARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctUINT32 * Bytes
)
{
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
Hardware, Logical, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
if (Logical != gcvNULL)
{
if (*Bytes < 8)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append END. */
logical[0] =
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
/* Record the count of execution which is finised by this END. */
logical[1] =
0;
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
}
if (Bytes != gcvNULL)
{
/* Return number of bytes required by the END command. */
*Bytes = 8;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gctaHARDWARE_Construct(
IN gcTA TA,
OUT gcTA_HARDWARE * Hardware
)
{
gceSTATUS status;
gcTA_HARDWARE hardware = gcvNULL;
gctaOS os = TA->os;
gcmkONERROR(gctaOS_Allocate(
gcmSIZEOF(gcsTA_HARDWARE),
(gctPOINTER *)&hardware
));
gctaOS_ZeroMemory((gctUINT8_PTR)hardware, gcmSIZEOF(gcsTA_HARDWARE));
hardware->ta = TA;
hardware->os = os;
hardware->pagetableArray.size = 4096;
hardware->functionBytes = 4096;
/* Power on GPU. */
gctaOS_SetGPUPower(os, TA->core, gcvTRUE, gcvTRUE);
/*************************************/
/******** Get chip information ******/
/*************************************/
gctaOS_WriteRegister(
hardware->ta->os, hardware->ta->core,
0x00000,
0x00000900
);
gcmkONERROR(_IdentifyHardwareByDatabase(hardware));
*Hardware = hardware;
return gcvSTATUS_OK;
OnError:
if (hardware)
{
gctaOS_Free(hardware);
}
return status;
}
gceSTATUS
gctaHARDWARE_Destroy(
IN gcTA_HARDWARE Hardware
)
{
if (Hardware->pagetableArray.logical)
{
gctaOS_FreeSecurityMemory(
Hardware->ta->os,
Hardware->pagetableArray.size,
Hardware->pagetableArray.logical,
(gctUINT32_PTR)Hardware->pagetableArray.physical
);
}
if (Hardware->functionLogical)
{
gctaOS_FreeSecurityMemory(
Hardware->ta->os,
Hardware->functionBytes,
Hardware->functionLogical,
(gctUINT32_PTR)Hardware->functionPhysical
);
}
gctaOS_Free(Hardware);
return gcvSTATUS_OK;
}
gceSTATUS
gctaHARDWARE_Execute(
IN gcTA TA,
IN gctUINT32 Address,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
gctUINT32 address = Address, control;
gcmkHEADER_ARG("Address=0x%x Bytes=%lu",
Address, Bytes);
/* Enable all events. */
gcmkONERROR(
gctaOS_WriteRegister(TA->os, TA->core, 0x00014, ~0U));
/* Write address register. */
gcmkONERROR(
gctaOS_WriteRegister(TA->os, TA->core, 0x00654, address));
/* Build control register. */
control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
16:16) - (0 ?
16:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
16:16) - (0 ?
16:16) + 1))))))) << (0 ?
16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
16:16) - (0 ?
16:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
/* Write control register. */
gcmkONERROR(
gctaOS_WriteRegister(TA->os, TA->core, 0x003A4, control));
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"Started command buffer @ 0x%08x",
address);
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gctaHARDWARE_MmuEnable(
IN gcTA_HARDWARE Hardware
)
{
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x0018C,
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) ((gctUINT32) (1 ) & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))));
return gcvSTATUS_OK;
}
/*
* In trust zone, we prepare page table array table and configure base address of
* it to hardware.
*/
gceSTATUS
gctaHARDWARE_SetMMU(
IN gcTA_HARDWARE Hardware,
IN gctPOINTER Logical
)
{
gcsMMU_TABLE_ARRAY_ENTRY *entry;
gcsHARDWARE_FUNCTION *function = &Hardware->functions[0];
gctUINT32 delay = 1;
gctUINT32 timer = 0;
gctUINT32 idle;
gctPHYS_ADDR_T mtlbPhysical;
gctPHYS_ADDR_T secureSafeAddress;
gctPHYS_ADDR_T nonSecureSafeAddress;
gctaOS_GetPhysicalAddress(Hardware->ta->os, Logical, &mtlbPhysical);
gctaOS_GetPhysicalAddress(Hardware->ta->os, Hardware->ta->mmu->safePageLogical, &secureSafeAddress);
gctaOS_GetPhysicalAddress(Hardware->ta->os, Hardware->ta->mmu->nonSecureSafePageLogical, &nonSecureSafeAddress);
/* not support more than 40bit physical address */
if ((secureSafeAddress & 0xFFFFFF0000000000ULL) ||
(nonSecureSafeAddress & 0xFFFFFF0000000000ULL))
{
return (gcvSTATUS_NOT_SUPPORTED);
}
/* Fill entry 0 of page table array. */
entry = (gcsMMU_TABLE_ARRAY_ENTRY *)Hardware->pagetableArray.logical;
entry->low = (gctUINT32)(mtlbPhysical & 0xFFFFFFFF);
entry->high = (gctUINT32)(mtlbPhysical >> 32)
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
8:8) - (0 ?
8:8) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
8:8) - (0 ?
8:8) + 1))))))) << (0 ?
8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
8:8) - (0 ?
8:8) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
;
/* Set page table base. */
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x0038C,
(gctUINT32)(Hardware->pagetableArray.address & 0xFFFFFFFF)
);
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x00390,
(gctUINT32)((Hardware->pagetableArray.address >> 32) & 0xFFFFFFFF)
);
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x00394
,
1
);
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x0039C,
(gctUINT32)(secureSafeAddress & 0xFFFFFFFF)
);
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x00398,
(gctUINT32)(nonSecureSafeAddress & 0xFFFFFFFF)
);
gctaOS_WriteRegister(
Hardware->ta->os, Hardware->ta->core,
0x003A0,
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
23:16) - (0 ?
23:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
23:16) - (0 ?
23:16) + 1))))))) << (0 ?
23:16))) | (((gctUINT32) ((gctUINT32) ((gctUINT32)((secureSafeAddress >> 32) & 0xFFFFFFFF)) & ((gctUINT32) ((((1 ?
23:16) - (0 ?
23:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:31) - (0 ?
31:31) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:31) - (0 ?
31:31) + 1))))))) << (0 ?
31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
31:31) - (0 ?
31:31) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
7:0) - (0 ?
7:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
7:0) - (0 ?
7:0) + 1))))))) << (0 ?
7:0))) | (((gctUINT32) ((gctUINT32) ((gctUINT32)((secureSafeAddress >> 32) & 0xFFFFFFFF)) & ((gctUINT32) ((((1 ?
7:0) - (0 ?
7:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:15) - (0 ?
15:15) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:15) - (0 ?
15:15) + 1))))))) << (0 ?
15:15))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
15:15) - (0 ?
15:15) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15)))
);
/* Execute prepared command sequence. */
gctaHARDWARE_Execute(
Hardware->ta,
function->address,
function->bytes
);
/* Wait until MMU configure finishes. */
do
{
gctaOS_Delay(Hardware->os, delay);
gctaOS_ReadRegister(
Hardware->ta->os, Hardware->ta->core,
0x00004,
&idle);
timer += delay;
delay *= 2;
}
while (!(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ));
/* Enable MMU. */
gctaOS_WriteRegister(
Hardware->os, Hardware->ta->core,
0x00388,
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
);
return gcvSTATUS_OK;
}
gceSTATUS
gctaHARDWARE_PrepareFunctions(
IN gcTA_HARDWARE Hardware
)
{
gceSTATUS status;
gcsHARDWARE_FUNCTION * function;
gctUINT32 mmuBytes;
gctUINT32 endBytes = 8;
gctUINT8_PTR logical;
gctPHYS_ADDR_T physical;
gcmkHEADER();
/* Allocate page table array. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
Hardware->ta->os,
&Hardware->pagetableArray.size,
&Hardware->pagetableArray.logical,
&Hardware->pagetableArray.physical
));
gcmkONERROR(gctaOS_GetPhysicalAddress(
Hardware->ta->os,
Hardware->pagetableArray.logical,
&Hardware->pagetableArray.address
));
/* Allocate GPU functions. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
Hardware->ta->os,
&Hardware->functionBytes,
&Hardware->functionLogical,
&Hardware->functionPhysical
));
gcmkONERROR(gctaOS_GetPhysicalAddress(
Hardware->ta->os,
Hardware->functionLogical,
&physical
));
gcmkSAFECASTPHYSADDRT(Hardware->functionAddress, physical);
function = &Hardware->functions[0];
function->logical = Hardware->functionLogical;
function->address = Hardware->functionAddress;
logical = function->logical;
gcmkONERROR(gctaHARDWARE_SetMMUStates(
Hardware,
Hardware->ta->mmu->mtlbLogical,
gcvMMU_MODE_4K,
Hardware->ta->mmu->safePageLogical,
logical,
&mmuBytes
));
logical += 8;
gcmkONERROR(gctaHARDWARE_End(
Hardware,
logical,
&endBytes
));
function->bytes = mmuBytes + endBytes;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gctaHARDWARE_IsFeatureAvailable(
IN gcTA_HARDWARE Hardware,
IN gceFEATURE Feature
)
{
gctBOOL available;
gcsFEATURE_DATABASE *database = Hardware->featureDatabase;
switch (Feature)
{
case gcvFEATURE_SECURITY:
available = database->SECURITY;
break;
default:
gcmkFATAL("Invalid feature has been requested.");
available = gcvFALSE;
}
return available;
}
gceSTATUS
gctaHARDWARE_DumpMMUException(
IN gcTA_HARDWARE Hardware
)
{
gctUINT32 mmu = 0;
gctUINT32 mmuStatus = 0;
gctUINT32 address = 0;
gctUINT32 i = 0;
gctUINT32 mmuStatusRegAddress;
gctUINT32 mmuExceptionAddress;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
mmuStatusRegAddress = 0x00384;
mmuExceptionAddress = 0x00380;
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkPRINT("ChipModel=0x%x ChipRevision=0x%x:\n",
Hardware->chipModel,
Hardware->chipRevision);
gcmkPRINT("**************************\n");
gcmkPRINT("*** MMU ERROR DUMP ***\n");
gcmkPRINT("**************************\n");
gcmkVERIFY_OK(gctaOS_ReadRegister(
Hardware->os, Hardware->ta->core,
mmuStatusRegAddress
,
&mmuStatus
));
gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
for (i = 0; i < 4; i += 1)
{
mmu = mmuStatus & 0xF;
mmuStatus >>= 4;
if (mmu == 0)
{
continue;
}
switch (mmu)
{
case 1:
gcmkPRINT(" MMU%d: slave not present\n", i);
break;
case 2:
gcmkPRINT(" MMU%d: page not present\n", i);
break;
case 3:
gcmkPRINT(" MMU%d: write violation\n", i);
break;
case 4:
gcmkPRINT(" MMU%d: out of bound", i);
break;
case 5:
gcmkPRINT(" MMU%d: read security violation", i);
break;
case 6:
gcmkPRINT(" MMU%d: write security violation", i);
break;
default:
gcmkPRINT(" MMU%d: unknown state\n", i);
}
gcmkVERIFY_OK(gctaOS_ReadRegister(
Hardware->os, Hardware->ta->core,
mmuExceptionAddress + i * 4
,
&address
));
gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
gctaMMU_DumpPagetableEntry(Hardware->ta->mmu, address);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gctaHARDWARE_ReadMMUException(
IN gcTA_HARDWARE Hardware,
OUT gctUINT32_PTR MMUStatus,
OUT gctUINT32_PTR MMUException
)
{
gctUINT32 mmuStatusRegAddress;
gctUINT32 mmuExceptionAddress;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
mmuStatusRegAddress = 0x00384;
mmuExceptionAddress = 0x00380;
gcmkVERIFY_OK(gctaOS_ReadRegister(
Hardware->os, Hardware->ta->core,
mmuStatusRegAddress
,
MMUStatus
));
gcmkVERIFY_OK(gctaOS_ReadRegister(
Hardware->os, Hardware->ta->core,
mmuExceptionAddress
,
MMUException
));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gctaHARDWARE_HandleMMUException(
IN gcTA_HARDWARE Hardware,
IN gctUINT32 MMUStatus,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 GPUAddress
)
{
gctUINT32 mmu = 0;
gctUINT32 mmuStatus = 0;
gctUINT32 mtlbEntry = 0;
gctUINT32_PTR stlbEntry;
gctBOOL secure;
gctUINT32 mmuStatusRegAddress;
gctUINT32 mmuExceptionAddress;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
mmuStatusRegAddress = 0x00384;
mmuExceptionAddress = 0x00380;
gcmkVERIFY_OK(gctaOS_ReadRegister(
Hardware->os, Hardware->ta->core,
mmuStatusRegAddress
,
&mmuStatus
));
mmu = mmuStatus & 0xF;
/* Setup page table. */
gctaMMU_GetPageEntry(
Hardware->ta->mmu,
GPUAddress,
&mtlbEntry,
&stlbEntry,
&secure
);
gctaMMU_SetPage(
Hardware->ta->mmu,
(gctUINT32)Physical,
stlbEntry
);
switch (mmu)
{
case 1:
gcmkASSERT(mtlbEntry != 0);
gctaOS_WriteRegister(
Hardware->os, Hardware->ta->core,
mmuExceptionAddress
,
mtlbEntry
);
break;
case 2:
gctaOS_WriteRegister(
Hardware->os, Hardware->ta->core,
mmuExceptionAddress
,
*stlbEntry
);
break;
default:
gcmkASSERT(0);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}