mirror of
https://github.com/revyos/thead-kernel.git
synced 2026-06-21 09:12:26 +02:00
1070 lines
27 KiB
C
1070 lines
27 KiB
C
/****************************************************************************
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2014 - 2021 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 - 2021 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 "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"
|
|
#include <linux/printk.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)
|
|
{
|
|
pr_warn("[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,
|
|
0x00010900
|
|
);
|
|
|
|
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;
|
|
}
|
|
|