diff options
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c')
-rw-r--r-- | drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c new file mode 100644 index 000000000000..7b677e43a543 --- /dev/null +++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c @@ -0,0 +1,348 @@ +/**************************************************************************** +* +* The MIT License (MIT) +* +* Copyright (c) 2014 - 2018 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 - 2018 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.h" + +#define _GC_OBJ_ZONE gcvZONE_KERNEL + +/* +* Responsibility of TA (trust application). +* 1) Start FE. +* When non secure driver asks for start FE. TA enable MMU and start FE. +* TA always execute MMU enable processes because it has no idea whether +* GPU has been power off. +* +* 2) Setup page table +* When non secure driver asks for set up GPU address to physical address +* mapping, TA check the attribute of physical address and attribute of +* GPU address to make sure they are match. Then it change page table. +* +*/ + +gcTA_MMU SharedMmu = gcvNULL; + +/******************************************************************************* +** +** gcTA_Construct +** +** Construct a new gcTA object. +*/ +int +gcTA_Construct( + IN gctaOS Os, + IN gceCORE Core, + OUT gcTA *TA + ) +{ + gceSTATUS status; + gctPOINTER pointer; + gcTA ta = gcvNULL; + + gcmkHEADER(); + gcmkVERIFY_ARGUMENT(TA != gcvNULL); + + /* Construct a gcTA object. */ + gcmkONERROR(gctaOS_Allocate(sizeof(struct _gcTA), &pointer)); + + gctaOS_ZeroMemory(pointer, sizeof(struct _gcTA)); + + ta = (gcTA)pointer; + + ta->os = Os; + ta->core = Core; + + gcmkONERROR(gctaHARDWARE_Construct(ta, &ta->hardware)); + + if (gctaHARDWARE_IsFeatureAvailable(ta->hardware, gcvFEATURE_SECURITY)) + { + if (SharedMmu == gcvNULL) + { + gcmkONERROR(gctaMMU_Construct(ta, &ta->mmu)); + + /* Record shared MMU. */ + SharedMmu = ta->mmu; + ta->destoryMmu = gcvTRUE; + } + else + { + ta->mmu = SharedMmu; + ta->destoryMmu = gcvFALSE; + } + + gcmkONERROR(gctaHARDWARE_PrepareFunctions(ta->hardware)); + } + + *TA = ta; + + gcmkFOOTER_NO(); + return 0; + +OnError: + if (ta) + { + if (ta->mmu && ta->destoryMmu) + { + gcmkVERIFY_OK(gctaMMU_Destory(ta->mmu)); + } + + if (ta->hardware) + { + gcmkVERIFY_OK(gctaHARDWARE_Destroy(ta->hardware)); + } + + gcmkVERIFY_OK(gctaOS_Free(ta)); + } + gcmkFOOTER(); + return status; +} + +/******************************************************************************* +** +** gcTA_Construct +** +** Destroy a gcTA object. +*/ +int +gcTA_Destroy( + IN gcTA TA + ) +{ + if (TA->mmu && TA->destoryMmu) + { + gcmkVERIFY_OK(gctaMMU_Destory(TA->mmu)); + } + + if (TA->hardware) + { + gcmkVERIFY_OK(gctaHARDWARE_Destroy(TA->hardware)); + } + + gcmkVERIFY_OK(gctaOS_Free(TA)); + + /* Destroy. */ + return 0; +} + + +/* +* Map a scatter gather list into gpu address space. +* +*/ +gceSTATUS +gcTA_MapMemory( + IN gcTA TA, + IN gctUINT32 *PhysicalArray, + IN gctPHYS_ADDR_T Physical, + IN gctUINT32 PageCount, + OUT gctUINT32 *GPUAddress + ) +{ + gceSTATUS status; + gcTA_MMU mmu; + gctUINT32 pageCount = PageCount; + gctUINT32 i; + gctUINT32 gpuAddress = *GPUAddress; + gctBOOL mtlbSecure = gcvFALSE; + gctBOOL physicalSecure = gcvFALSE; + + mmu = TA->mmu; + + /* Fill in page table. */ + for (i = 0; i < pageCount; i++) + { + gctUINT32 physical; + gctUINT32_PTR entry; + + if (PhysicalArray) + { + physical = PhysicalArray[i]; + } + else + { + physical = (gctUINT32)Physical + 4096 * i; + } + + gcmkONERROR(gctaMMU_GetPageEntry(mmu, gpuAddress, gcvNULL, &entry, &mtlbSecure)); + + status = gctaOS_IsPhysicalSecure(TA->os, physical, &physicalSecure); + + if (gcmIS_SUCCESS(status) && physicalSecure != mtlbSecure) + { + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED); + } + + gctaMMU_SetPage(mmu, physical, entry); + + gpuAddress += 4096; + } + + return gcvSTATUS_OK; + +OnError: + return status; +} + +gceSTATUS +gcTA_UnmapMemory( + IN gcTA TA, + IN gctUINT32 GPUAddress, + IN gctUINT32 PageCount + ) +{ + gceSTATUS status; + + gcmkONERROR(gctaMMU_FreePages(TA->mmu, GPUAddress, PageCount)); + + return gcvSTATUS_OK; + +OnError: + return status; +} + +gceSTATUS +gcTA_StartCommand( + IN gcTA TA, + IN gctUINT32 Address, + IN gctUINT32 Bytes + ) +{ + gctaHARDWARE_Execute(TA, Address, Bytes); + return gcvSTATUS_OK; +} + +int +gcTA_Dispatch( + IN gcTA TA, + IN gcsTA_INTERFACE * Interface + ) +{ + int command = Interface->command; + + gceSTATUS status = gcvSTATUS_OK; + + switch (command) + { + case KERNEL_START_COMMAND: + /* Enable MMU every time FE starts. + ** Because if normal world stop GPU and power off GPU, MMU states is reset. + */ + gcmkONERROR(gctaHARDWARE_SetMMU(TA->hardware, TA->mmu->mtlbLogical)); + + gcmkONERROR(gcTA_StartCommand( + TA, + Interface->u.StartCommand.address, + Interface->u.StartCommand.bytes + )); + break; + + case KERNEL_MAP_MEMORY: + gcmkONERROR(gcTA_MapMemory( + TA, + Interface->u.MapMemory.physicals, + Interface->u.MapMemory.physical, + Interface->u.MapMemory.pageCount, + &Interface->u.MapMemory.gpuAddress + )); + + break; + + case KERNEL_UNMAP_MEMORY: + status = gcTA_UnmapMemory( + TA, + Interface->u.UnmapMemory.gpuAddress, + Interface->u.UnmapMemory.pageCount + ); + break; + + case KERNEL_DUMP_MMU_EXCEPTION: + status = gctaHARDWARE_DumpMMUException(TA->hardware); + break; + + case KERNEL_HANDLE_MMU_EXCEPTION: + status = gctaHARDWARE_HandleMMUException( + TA->hardware, + Interface->u.HandleMMUException.mmuStatus, + Interface->u.HandleMMUException.physical, + Interface->u.HandleMMUException.gpuAddress + ); + break; + + case KERNEL_READ_MMU_EXCEPTION: + status = gctaHARDWARE_ReadMMUException( + TA->hardware, + &Interface->u.ReadMMUException.mmuStatus, + &Interface->u.ReadMMUException.mmuException + ); + break; + + default: + gcmkASSERT(0); + + status = gcvSTATUS_INVALID_ARGUMENT; + break; + } + +OnError: + Interface->result = status; + + return 0; +} + + + |