MGS-4530-1 add 6.2.4.p4 gpu driver for L4.19

add mxc config to include drivers/mxc/gpu-viv

Signed-off-by: Xianzhong <xianzhong.li@nxp.com>
This commit is contained in:
Xianzhong 2019-01-29 00:53:08 +08:00 committed by Dong Aisheng
parent 4f8c3ce4ee
commit 30638182fd
98 changed files with 225075 additions and 0 deletions

View File

@ -228,4 +228,5 @@ source "drivers/interconnect/Kconfig"
source "drivers/counter/Kconfig"
source "drivers/mxc/Kconfig"
endmenu

View File

@ -186,3 +186,4 @@ obj-$(CONFIG_SIOX) += siox/
obj-$(CONFIG_GNSS) += gnss/
obj-$(CONFIG_INTERCONNECT) += interconnect/
obj-$(CONFIG_COUNTER) += counter/
obj-y += mxc/

11
drivers/mxc/Kconfig Normal file
View File

@ -0,0 +1,11 @@
# drivers/mxc/Kconfig
if ARCH_MXC
menu "MXC support drivers"
source "drivers/mxc/gpu-viv/Kconfig"
endmenu
endif

1
drivers/mxc/Makefile Normal file
View File

@ -0,0 +1 @@
obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/

326
drivers/mxc/gpu-viv/Kbuild Normal file
View File

@ -0,0 +1,326 @@
##############################################################################
#
# 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.
#
##############################################################################
#
# Linux build file for kernel HAL driver.
#
AQROOT := $(srctree)/drivers/mxc/gpu-viv
include $(AQROOT)/config
soc_vendor := $(firstword $(subst -, ,$(SOC_PLATFORM)))
soc_board := $(lastword $(subst -, ,$(SOC_PLATFORM)))
KERNEL_DIR ?= $(TOOL_DIR)/kernel
OS_KERNEL_DIR := hal/os/linux/kernel
ARCH_KERNEL_DIR := hal/kernel/arch
ARCH_VG_KERNEL_DIR := hal/kernel/archvg
HAL_KERNEL_DIR := hal/kernel
TA_DIR := hal/security_v1
HOST := $(shell hostname)
# Include platform config if exists.
-include $(AQROOT)/$(OS_KERNEL_DIR)/platform/$(soc_vendor)/gc_hal_kernel_platform_$(soc_board).config
MODULE_NAME ?= galcore
CUSTOMER_ALLOCATOR_OBJS ?=
ALLOCATOR_ARRAY_H_LOCATION ?= $(OS_KERNEL_DIR)/allocator/default/
EXTRA_CFLAGS += -Werror
OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_allocator.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_user_memory.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dma.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_gfp.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_reserved_mem.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
$(OS_KERNEL_DIR)/platform/$(soc_vendor)/gc_hal_kernel_platform_$(soc_board).o
ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
OBJS += $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dmabuf.o
endif
ifneq ($(CONFIG_IOMMU_SUPPORT),)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_iommu.o
endif
ifneq ($(CONFIG_DRM),)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_drm.o
endif
OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_async_command.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_power.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_security_v1.o
OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
$(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
ifeq ($(VIVANTE_ENABLE_3D), 1)
OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_recorder.o
endif
ifneq ($(CONFIG_ARM64),)
ifeq ($(CONFIG_ANDROID),)
VIVANTE_ENABLE_VG=0
endif
endif
ifeq ($(VIVANTE_ENABLE_VG), 1)
OBJS +=\
$(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
$(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
$(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
endif
ifneq ($(CONFIG_SYNC),)
EXTRA_CFLAGS += -Idrivers/staging/android
EXTRA_CFLAGS += -DgcdLINUX_SYNC_FILE=1
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
else
ifneq ($(CONFIG_SYNC_FILE),)
EXTRA_CFLAGS += -DgcdLINUX_SYNC_FILE=1
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
endif
endif
ifeq ($(SECURITY), 1)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_security.o
endif
ifneq ($(CUSTOMER_ALLOCATOR_OBJS),)
OBJS += $(CUSTOMER_ALLOCATOR_OBJS)
endif
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel_emulator.o \
$(TA_DIR)/gc_hal_ta.o \
$(TA_DIR)/gc_hal_ta_hardware.o \
$(TA_DIR)/gc_hal_ta_mmu.o \
$(TA_DIR)/os/emulator/gc_hal_ta_emulator.o
ifeq ($(KERNELRELEASE), )
.PHONY: all clean install
# Define targets.
all:
@$(MAKE) V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
clean:
@rm -rf $(OBJS)
@rm -rf modules.order Module.symvers .tmp_versions
@find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
install: all
@mkdir -p $(SDK_DIR)/drivers
@cp $(MODULE_NAME).ko $(SDK_DIR)/drivers
else
EXTRA_CFLAGS += -DLINUX -DDRIVER
ifeq ($(FLAREON),1)
EXTRA_CFLAGS += -DFLAREON
endif
ifeq ($(DEBUG), 1)
EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
else
EXTRA_CFLAGS += -DDBG=0
endif
ifeq ($(NO_DMA_COHERENT), 1)
EXTRA_CFLAGS += -DNO_DMA_COHERENT
endif
ifeq ($(CONFIG_DOVE_GPU), 1)
EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
endif
ifneq ($(USE_PLATFORM_DRIVER), 0)
EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
else
EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
endif
EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
else
EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
endif
ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
else
EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
endif
ifeq ($(USE_LINUX_PCIE), 1)
EXTRA_CFLAGS += -DUSE_LINUX_PCIE=1
else
EXTRA_CFLAGS += -DUSE_LINUX_PCIE=0
endif
ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
else
EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
endif
ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
else
EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
endif
ifeq ($(VIVANTE_ENABLE_3D),0)
EXTRA_CFLAGS += -DgcdENABLE_3D=0
else
EXTRA_CFLAGS += -DgcdENABLE_3D=1
endif
ifeq ($(VIVANTE_ENABLE_2D),0)
EXTRA_CFLAGS += -DgcdENABLE_2D=0
else
EXTRA_CFLAGS += -DgcdENABLE_2D=1
endif
ifeq ($(VIVANTE_ENABLE_VG),0)
EXTRA_CFLAGS += -DgcdENABLE_VG=0
else
EXTRA_CFLAGS += -DgcdENABLE_VG=1
endif
ifeq ($(USE_BANK_ALIGNMENT), 1)
EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
ifneq ($(BANK_BIT_START), 0)
ifneq ($(BANK_BIT_END), 0)
EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
endif
endif
ifneq ($(BANK_CHANNEL_BIT), 0)
EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
endif
endif
ifeq ($(FPGA_BUILD), 1)
EXTRA_CFLAGS += -DgcdFPGA_BUILD=1
else
EXTRA_CFLAGS += -DgcdFPGA_BUILD=0
endif
ifeq ($(SECURITY), 1)
EXTRA_CFLAGS += -DgcdSECURITY=1
endif
ifneq ($(CONFIG_DRM), )
ifneq ($(CONFIG_ANDROID),)
EXTRA_CFLAGS += -DgcdENABLE_DRM=$(VIVANTE_ENABLE_DRM)
else
EXTRA_CFLAGS += -DgcdENABLE_DRM=0
endif
else
EXTRA_CFLAGS += -DgcdENABLE_DRM=0
endif
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/arch
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
EXTRA_CFLAGS += -I$(AQROOT)/$(ALLOCATOR_ARRAY_H_LOCATION)
EXTRA_CFLAGS += -I$(AQROOT)/hal/security_v1/
ifneq ($(CONFIG_ARM), )
EXTRA_CFLAGS += -Iarch/arm/mm
endif
ifeq ($(VIVANTE_ENABLE_VG), 1)
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/archvg
endif
EXTRA_CFLAGS += -DHOST=\"$(HOST)\"
EXTRA_CFLAGS += -DgcdENABLE_TRUST_APPLICATION=1
obj-$(CONFIG_MXC_GPU_VIV) = $(MODULE_NAME).o
$(MODULE_NAME)-objs = $(OBJS)
endif

View File

@ -0,0 +1,10 @@
menu "MXC Vivante GPU support"
config MXC_GPU_VIV
tristate "MXC Vivante GPU support"
default y
---help---
Say Y to get the GPU driver support.
endmenu

View File

@ -0,0 +1,72 @@
##############################################################################
#
# 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.
#
##############################################################################
ARCH_TYPE ?= arm
SDK_DIR ?= $(AQROOT)/build/sdk
VIVANTE_ENABLE_3D ?= 1
VIVANTE_ENABLE_2D ?= 1
VIVANTE_ENABLE_VG ?= 1
VIVANTE_ENABLE_DRM ?= 1
NO_DMA_COHERENT ?= 0
USE_PLATFORM_DRIVER ?= 1
ENABLE_GPU_CLOCK_BY_DRIVER ?= 0
FORCE_ALL_VIDEO_MEMORY_CACHED ?= 0
CACHE_FUNCTION_UNIMPLEMENTED ?= 0
USE_BANK_ALIGNMENT ?= 1
BANK_BIT_START ?= 13
BANK_BIT_END ?= 15
BANK_CHANNEL_BIT ?= 12
SECURITY ?= 0
SOC_PLATFORM ?= freescale-imx

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_context_h_
#define __gc_hal_kernel_context_h_
#include "gc_hal_kernel_buffer.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Maps state locations within the context buffer. */
typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
typedef struct _gcsSTATE_MAP
{
/* Index of the state in the context buffer. */
gctUINT index;
/* State mask. */
gctUINT32 mask;
}
gcsSTATE_MAP;
/* Context buffer. */
typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
typedef struct _gcsCONTEXT
{
/* For debugging: the number of context buffer in the order of creation. */
gctUINT num;
/* Pointer to gckEVENT object. */
gckEVENT eventObj;
/* Context busy signal. */
gctSIGNAL signal;
/* Physical address of the context buffer. */
gctPHYS_ADDR physical;
/* Logical address of the context buffer. */
gctUINT32_PTR logical;
/* Hardware address of the context buffer. */
gctUINT32 address;
/* Pointer to the LINK commands. */
gctPOINTER link2D;
gctPOINTER link3D;
/* Next context buffer. */
gcsCONTEXT_PTR next;
}
gcsCONTEXT;
typedef struct _gcsRECORD_ARRAY_MAP * gcsRECORD_ARRAY_MAP_PTR;
struct _gcsRECORD_ARRAY_MAP
{
/* User pointer key. */
gctUINT64 key;
/* Kernel memory buffer. */
gcsSTATE_DELTA_RECORD_PTR kData;
/* Next map. */
gcsRECORD_ARRAY_MAP_PTR next;
};
#define USE_SW_RESET 1
/* gckCONTEXT structure that hold the current context. */
struct _gckCONTEXT
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckHARDWARE hardware;
/* Command buffer alignment. */
gctUINT32 alignment;
gctUINT32 reservedHead;
/* Context buffer metrics. */
gctSIZE_T maxState;
gctUINT32 numStates;
gctUINT32 totalSize;
gctUINT32 bufferSize;
gctUINT32 linkIndex2D;
gctUINT32 linkIndex3D;
gctUINT32 linkIndexXD;
gctUINT32 entryOffset3D;
gctUINT32 entryOffsetXDFrom2D;
gctUINT32 entryOffsetXDFrom3D;
/* State mapping. */
gcsSTATE_MAP_PTR map;
/* List of context buffers. */
gcsCONTEXT_PTR buffer;
/* Requested pipe select for context. */
gcePIPE_SELECT entryPipe;
gcePIPE_SELECT exitPipe;
/* Variables used for building state buffer. */
gctUINT32 lastAddress;
gctSIZE_T lastSize;
gctUINT32 lastIndex;
gctBOOL lastFixed;
gctUINT32 pipeSelectBytes;
/* Hint array. */
#if gcdSECURE_USER
gctBOOL_PTR hint;
#endif
gcsPROFILER_COUNTERS_PART1 latestProfiler_part1;
gcsPROFILER_COUNTERS_PART1 histroyProfiler_part1;
gcsPROFILER_COUNTERS_PART1 preProfiler_part1;
gcsPROFILER_COUNTERS_PART2 latestProfiler_part2;
gcsPROFILER_COUNTERS_PART2 histroyProfiler_part2;
gcsPROFILER_COUNTERS_PART2 preProfiler_part2;
};
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_context_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,376 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_h_
#define __gc_hal_kernel_hardware_h_
#if gcdENABLE_VG
#include "gc_hal_kernel_hardware_vg.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
gcvHARDWARE_FUNCTION_MMU,
gcvHARDWARE_FUNCTION_FLUSH,
/* BLT engine command sequence. */
gcvHARDWARE_FUNCTION_BLT_EVENT,
gcvHARDWARE_FUNCTION_DUMMY_DRAW,
gcvHARDWARE_FUNCTION_NUM,
}
gceHARDWARE_FUNCTION;
typedef struct _gcsHARWARE_FUNCTION
{
/* Entry of the function. */
gctUINT32 address;
/* CPU address of the function. */
gctUINT8_PTR logical;
/* Bytes of the function. */
gctUINT32 bytes;
/* Hardware address of END in this function. */
gctUINT32 endAddress;
/* Logical of END in this function. */
gctUINT8_PTR endLogical;
}
gcsHARDWARE_FUNCTION;
typedef struct _gcsSTATETIMER
{
gctUINT64 start;
gctUINT64 recent;
/* Elapse of each power state. */
gctUINT64 elapse[4];
}
gcsSTATETIMER;
typedef struct _gcsHARDWARE_SIGNATURE
{
/* Chip model. */
gceCHIPMODEL chipModel;
/* Revision value.*/
gctUINT32 chipRevision;
/* Supported feature fields. */
gctUINT32 chipFeatures;
/* Supported minor feature fields. */
gctUINT32 chipMinorFeatures;
/* Supported minor feature 1 fields. */
gctUINT32 chipMinorFeatures1;
/* Supported minor feature 2 fields. */
gctUINT32 chipMinorFeatures2;
}
gcsHARDWARE_SIGNATURE;
typedef struct _gcsMMU_TABLE_ARRAY_ENTRY
{
gctUINT32 low;
gctUINT32 high;
}
gcsMMU_TABLE_ARRAY_ENTRY;
typedef struct _gcsHARDWARE_PAGETABLE_ARRAY
{
/* Number of entries in page table array. */
gctUINT num;
/* Size in bytes of array. */
gctSIZE_T size;
/* Physical address of array. */
gctPHYS_ADDR_T address;
/* Memory descriptor. */
gctPHYS_ADDR physical;
/* Logical address of array. */
gctPOINTER logical;
}
gcsHARDWARE_PAGETABLE_ARRAY;
/* gckHARDWARE object. */
struct _gckHARDWARE
{
/* Object. */
gcsOBJECT object;
/* Pointer to gctKERNEL object. */
gckKERNEL kernel;
/* Pointer to gctOS object. */
gckOS os;
/* Core */
gceCORE core;
/* Chip characteristics. */
gcsHAL_QUERY_CHIP_IDENTITY identity;
gcsHAL_QUERY_CHIP_OPTIONS options;
gctUINT32 powerBaseAddress;
gctBOOL extraEventStates;
/* Big endian */
gctBOOL bigEndian;
/* Base address. */
gctUINT32 baseAddress;
/* Chip status */
gctPOINTER powerMutex;
gctUINT32 powerProcess;
gctUINT32 powerThread;
gceCHIPPOWERSTATE chipPowerState;
gctUINT32 lastWaitLink;
gctUINT32 lastEnd;
gctBOOL clockState;
gctBOOL powerState;
gctPOINTER globalSemaphore;
gctUINT32 mmuVersion;
/* Type */
gceHARDWARE_TYPE type;
#if gcdPOWEROFF_TIMEOUT
gctUINT32 powerOffTime;
gctUINT32 powerOffTimeout;
gctPOINTER powerOffTimer;
#endif
#if gcdENABLE_FSCALE_VAL_ADJUST
gctUINT32 powerOnFscaleVal;
#endif
gctPOINTER pageTableDirty[gcvENGINE_GPU_ENGINE_COUNT];
#if gcdLINK_QUEUE_SIZE
struct _gckQUEUE linkQueue;
#endif
gctBOOL stallFEPrefetch;
gctUINT32 minFscaleValue;
gctUINT waitCount;
gctUINT32 mcClk;
gctUINT32 shClk;
gctPOINTER pendingEvent;
/* Function used by gckHARDWARE. */
gctPHYS_ADDR mmuFuncPhysical;
gctPOINTER mmuFuncLogical;
gctSIZE_T mmuFuncBytes;
gctPHYS_ADDR auxFuncPhysical;
gctPHYS_ADDR auxPhysHandle;
gctPOINTER auxFuncLogical;
gctUINT32 auxFuncAddress;
gctSIZE_T auxFuncBytes;
gcsHARDWARE_FUNCTION functions[gcvHARDWARE_FUNCTION_NUM];
gcsSTATETIMER powerStateTimer;
gctUINT32 executeCount;
gctUINT32 lastExecuteAddress;
/* Head for hardware list in gckMMU. */
gcsLISTHEAD mmuHead;
gctPOINTER featureDatabase;
gctBOOL hasAsyncFe;
gctBOOL hasL2Cache;
gcsHARDWARE_SIGNATURE signature;
gctUINT32 maxOutstandingReads;
gcsHARDWARE_PAGETABLE_ARRAY pagetableArray;
gctUINT64 contextID;
};
typedef struct _gcsFEDescriptor
{
gctUINT32 start;
gctUINT32 end;
}
gcsFEDescriptor;
typedef struct _gcsFE * gckFE;
typedef struct _gcsFE
{
gckOS os;
/* Number of free descriptors. */
gctPOINTER freeDscriptors;
}
gcsFE;
gceSTATUS
gckFE_Initialize(
IN gckHARDWARE Hardware,
OUT gckFE FE
);
gceSTATUS
gckFE_ReserveSlot(
IN gckHARDWARE Hardware,
IN gckFE FE,
OUT gctBOOL * Available
);
void
gckFE_UpdateAvaiable(
IN gckHARDWARE Hardware,
OUT gckFE FE
);
void
gckFE_Execute(
IN gckHARDWARE Hardware,
IN gckFE FE,
IN gcsFEDescriptor * Desc
);
gceSTATUS
gckHARDWARE_GetBaseAddress(
IN gckHARDWARE Hardware,
OUT gctUINT32_PTR BaseAddress
);
gceSTATUS
gckHARDWARE_NeedBaseAddress(
IN gckHARDWARE Hardware,
IN gctUINT32 State,
OUT gctBOOL_PTR NeedBase
);
gceSTATUS
gckHARDWARE_GetFrameInfo(
IN gckHARDWARE Hardware,
OUT gcsHAL_FRAME_INFO * FrameInfo
);
gceSTATUS
gckHARDWARE_DumpGpuProfile(
IN gckHARDWARE Hardware
);
gceSTATUS
gckHARDWARE_HandleFault(
IN gckHARDWARE Hardware
);
gceSTATUS
gckHARDWARE_ExecuteFunctions(
IN gckHARDWARE Hardware,
IN gceHARDWARE_FUNCTION Function
);
gceSTATUS
gckHARDWARE_DummyDraw(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN gceDUMMY_DRAW_TYPE DummyDrawType,
IN OUT gctUINT32 * Bytes
);
gceSTATUS
gckHARDWARE_EnterQueryClock(
IN gckHARDWARE Hardware,
OUT gctUINT64 *McStart,
OUT gctUINT64 *ShStart
);
gceSTATUS
gckHARDWARE_ExitQueryClock(
IN gckHARDWARE Hardware,
IN gctUINT64 McStart,
IN gctUINT64 ShStart,
OUT gctUINT32 *McClk,
OUT gctUINT32 *ShClk
);
gceSTATUS
gckHARDWARE_QueryFrequency(
IN gckHARDWARE Hardware
);
#define gcmkWRITE_MEMORY(logical, data) \
do { \
gcmkVERIFY_OK(gckOS_WriteMemory(os, logical, data)); \
logical++; \
}\
while (0) ; \
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_hardware_h_ */

View File

@ -0,0 +1,728 @@
/****************************************************************************
*
* 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.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_context.h"
/*
* -----------------------
* HARDWARE STATE RECORDER
* -----------------------
*
* State mirror buffer is used to 'mirror' hardware states since hardware
* states can't be dumpped. It is a context buffer which stores 'global'
* context.
*
* For each commit, state recorder
* 1) Records context buffer (if there is) and command buffers in this commit.
* 2) Parse those buffers to estimate the state changed.
* 3) Stores result to a mirror buffer.
*
* == Commit 0 ====================================================================
*
* Context Buffer 0
*
* Command Buffer 0
*
* Mirror Buffer 0 <- Context Buffer 0 + Command Buffer 0
*
* == Commit 1 ====================================================================
*
* Command Buffer 1
*
* Mirror Buffer 1 <- Command buffer 1 + Mirror Buffer 0
*
* == Commit 2 ====================================================================
*
* Context Buffer 2 (optional)
*
* Command Buffer 2
*
* Mirror Buffer 2 <- Command buffer 2 + Context Buffer 2 + Mirror Buffer 1
*
* == Commit N ====================================================================
*
* For Commit N, these buffers are needed to reproduce hardware's behavior in
* this commit.
*
* Mirror Buffer [N - 1] : State Mirror accumlated by past commits,
* which is used to restore hardware state.
* Context Buffer [N] :
* Command Buffer [N] : Command buffer executed by hardware in this commit.
*
* If sequence of states programming matters, hardware's behavior can't be reproduced,
* but the state values stored in mirror buffer are assuring.
*/
/* Queue size. */
#define gcdNUM_RECORDS 6
typedef struct _gcsPARSER_HANDLER * gckPARSER_HANDLER;
typedef void
(*HandlerFunction)(
IN gckPARSER_HANDLER Handler,
IN gctUINT32 Addr,
IN gctUINT32 Data
);
typedef struct _gcsPARSER_HANDLER
{
gctUINT32 type;
gctUINT32 cmd;
gctPOINTER private;
HandlerFunction function;
}
gcsPARSER_HANDLER;
typedef struct _gcsPARSER * gckPARSER;
typedef struct _gcsPARSER
{
gctUINT8_PTR currentCmdBufferAddr;
/* Current command. */
gctUINT32 lo;
gctUINT32 hi;
gctUINT8 cmdOpcode;
gctUINT16 cmdAddr;
gctUINT32 cmdSize;
gctUINT32 cmdRectCount;
gctUINT8 skip;
gctUINT32 skipCount;
gctBOOL allow;
gctBOOL stop;
/* Callback used by parser to handle a command. */
gckPARSER_HANDLER commandHandler;
}
gcsPARSER;
typedef struct _gcsMIRROR
{
gctUINT32_PTR logical[gcdNUM_RECORDS];
gctUINT32 bytes;
gcsSTATE_MAP_PTR map;
gctSIZE_T maxState;
}
gcsMIRROR;
typedef struct _gcsDELTA
{
gctUINT64 commitStamp;
gctUINT32_PTR command;
gctUINT32 commandBytes;
gctUINT32_PTR context;
gctUINT32 contextBytes;
}
gcsDELTA;
typedef struct _gcsRECORDER
{
gckOS os;
gcsMIRROR mirror;
gcsDELTA deltas[gcdNUM_RECORDS];
/* Index of current record. */
gctUINT index;
/* Number of records. */
gctUINT num;
/* Plugin used by gckPARSER. */
gcsPARSER_HANDLER recorderHandler;
gckPARSER parser;
}
gcsRECORDER;
/******************************************************************************\
***************************** Command Buffer Parser ****************************
\******************************************************************************/
/*
** Command buffer parser checks command buffer in FE's view to make sure there
** is no format error.
**
** Parser provide a callback mechnisam, so plug-in can be added to implement
** other functions.
*/
static void
_HandleLoadState(
IN OUT gckPARSER Parser
)
{
gctUINT i;
gctUINT32_PTR data = (gctUINT32_PTR)Parser->currentCmdBufferAddr;
gctUINT32 cmdAddr = Parser->cmdAddr;
if (Parser->commandHandler == gcvNULL
|| Parser->commandHandler->cmd != 0x01
)
{
/* No handler for this command. */
return;
}
for (i = 0; i < Parser->cmdSize; i++)
{
Parser->commandHandler->function(Parser->commandHandler, cmdAddr, *data);
/* Advance to next state. */
cmdAddr++;
data++;
}
}
static void
_GetCommand(
IN OUT gckPARSER Parser
)
{
gctUINT32 * buffer = (gctUINT32 *)Parser->currentCmdBufferAddr;
gctUINT16 cmdRectCount;
gctUINT16 cmdDataCount;
Parser->hi = buffer[0];
Parser->lo = buffer[1];
Parser->cmdOpcode = (((((gctUINT32) (Parser->hi)) >> (0 ? 31:27)) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) );
Parser->cmdRectCount = 1;
switch (Parser->cmdOpcode)
{
case 0x01:
/* Extract count. */
Parser->cmdSize = (((((gctUINT32) (Parser->hi)) >> (0 ? 25:16)) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1)))))) );
if (Parser->cmdSize == 0)
{
/* 0 means 1024. */
Parser->cmdSize = 1024;
}
Parser->skip = (Parser->cmdSize & 0x1) ? 0 : 1;
/* Extract address. */
Parser->cmdAddr = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) );
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 4;
Parser->skipCount = Parser->cmdSize + Parser->skip;
break;
case 0x05:
Parser->cmdSize = 4;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x06:
Parser->cmdSize = 5;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x0C:
Parser->cmdSize = 3;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x09:
Parser->cmdSize = 2;
Parser->cmdAddr = 0x0F16;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x04:
Parser->cmdSize = 1;
Parser->cmdAddr = 0x0F06;
cmdRectCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
cmdDataCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 26:16)) & ((gctUINT32) ((((1 ? 26:16) - (0 ? 26:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:16) - (0 ? 26:16) + 1)))))) );
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2)
+ cmdRectCount * 2
+ gcmALIGN(cmdDataCount, 2);
Parser->cmdRectCount = cmdRectCount;
break;
case 0x03:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x02:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x07:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x08:
/* Commands after LINK isn't executed, skip them. */
Parser->stop = gcvTRUE;
break;
default:
/* Unknown command is a risk. */
Parser->allow = gcvFALSE;
break;
}
}
static void
_ParseCommand(
IN OUT gckPARSER Parser
)
{
switch(Parser->cmdOpcode)
{
case 0x01:
_HandleLoadState(Parser);
break;
case 0x05:
case 0x06:
case 0x0C:
break;
case 0x04:
break;
default:
break;
}
/* Advance to next command. */
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr
+ (Parser->skipCount << 2);
}
gceSTATUS
gckPARSER_Parse(
IN gckPARSER Parser,
IN gctUINT8_PTR Buffer,
IN gctUINT32 Bytes
)
{
gckPARSER parser = Parser;
gctUINT8_PTR end = (gctUINT8_PTR)Buffer + Bytes;
/* Initialize parser. */
parser->currentCmdBufferAddr = (gctUINT8_PTR)Buffer;
parser->skip = 0;
parser->allow = gcvTRUE;
parser->stop = gcvFALSE;
/* Go through command buffer until reaching the end
** or meeting an error. */
do
{
_GetCommand(parser);
_ParseCommand(parser);
}
while ((parser->currentCmdBufferAddr < end)
&& (parser->allow == gcvTRUE)
&& (parser->stop == gcvFALSE)
);
if (parser->allow == gcvFALSE)
{
/* Error detected. */
return gcvSTATUS_NOT_SUPPORTED;
}
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckPARSER_RegisterCommandHandler
**
** Register a command handler which will be called when parser get a command.
**
*/
gceSTATUS
gckPARSER_RegisterCommandHandler(
IN gckPARSER Parser,
IN gckPARSER_HANDLER Handler
)
{
Parser->commandHandler = Handler;
return gcvSTATUS_OK;
}
gceSTATUS
gckPARSER_Construct(
IN gckOS Os,
IN gckPARSER_HANDLER Handler,
OUT gckPARSER * Parser
)
{
gceSTATUS status;
gckPARSER pointer;
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsPARSER), (gctPOINTER *)&pointer));
/* Put it here temp, should have a more general plug-in mechnisam. */
pointer->commandHandler = Handler;
*Parser = pointer;
return gcvSTATUS_OK;
OnError:
return status;
}
void
gckPARSER_Destroy(
IN gckOS Os,
IN gckPARSER Parser
)
{
gcmkOS_SAFE_FREE(Os, Parser);
}
/******************************************************************************\
**************************** Hardware States Recorder **************************
\******************************************************************************/
static void
_RecodeState(
IN gckPARSER_HANDLER Handler,
IN gctUINT32 Addr,
IN gctUINT32 Data
)
{
gcmkVERIFY_OK(gckRECORDER_UpdateMirror(Handler->private, Addr, Data));
}
static gctUINT
_Previous(
IN gctUINT Index
)
{
if (Index == 0)
{
return gcdNUM_RECORDS - 1;
}
return Index - 1;
}
static gctUINT
_Next(
IN gctUINT Index
)
{
return (Index + 1) % gcdNUM_RECORDS;
}
gceSTATUS
gckRECORDER_Construct(
IN gckOS Os,
IN gckHARDWARE Hardware,
OUT gckRECORDER * Recorder
)
{
gceSTATUS status;
gckCONTEXT context = gcvNULL;
gckRECORDER recorder = gcvNULL;
gctSIZE_T mapSize;
gctUINT i;
gctBOOL virtualCommandBuffer = Hardware->kernel->virtualCommandBuffer;
/* MMU is not ready now. */
Hardware->kernel->virtualCommandBuffer = gcvFALSE;
gcmkONERROR(gckCONTEXT_Construct(Os, Hardware, 0, &context));
/* Restore. */
Hardware->kernel->virtualCommandBuffer = virtualCommandBuffer;
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsRECORDER), (gctPOINTER *)&recorder));
gckOS_ZeroMemory(recorder, gcmSIZEOF(gcsRECORDER));
/* Copy state map. */
recorder->mirror.maxState = context->maxState;
mapSize = context->maxState * gcmSIZEOF(gcsSTATE_MAP);
gcmkONERROR(gckOS_Allocate(Os, mapSize, (gctPOINTER *)&recorder->mirror.map));
gckOS_MemCopy(recorder->mirror.map, context->map, mapSize);
/* Copy context buffer. */
recorder->mirror.bytes = context->totalSize;
for (i = 0; i < gcdNUM_RECORDS; i++)
{
gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->mirror.logical[i]));
gckOS_MemCopy(recorder->mirror.logical[i], context->buffer->logical, context->totalSize);
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
gcmkONERROR(gckOS_Allocate(Os, gcdCMD_BUFFER_SIZE, (gctPOINTER *)&recorder->deltas[i].command));
gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->deltas[i].context));
}
recorder->index = 0;
recorder->num = 0;
/* Initialize Parser plugin. */
recorder->recorderHandler.cmd = 0x01;
recorder->recorderHandler.private = recorder;
recorder->recorderHandler.function = _RecodeState;
gcmkONERROR(gckPARSER_Construct(Os, &recorder->recorderHandler, &recorder->parser));
recorder->os = Os;
*Recorder = recorder;
gckCONTEXT_Destroy(context);
return gcvSTATUS_OK;
OnError:
if (context)
{
gckCONTEXT_Destroy(context);
}
if (recorder)
{
gckRECORDER_Destory(Os, recorder);
}
return status;
}
gceSTATUS
gckRECORDER_Destory(
IN gckOS Os,
IN gckRECORDER Recorder
)
{
gctUINT i;
if (Recorder->mirror.map)
{
gcmkOS_SAFE_FREE(Os, Recorder->mirror.map);
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
if (Recorder->mirror.logical[i])
{
gcmkOS_SAFE_FREE(Os, Recorder->mirror.logical[i]);
}
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
if (Recorder->deltas[i].command)
{
gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].command);
}
if (Recorder->deltas[i].context)
{
gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].context);
}
}
if (Recorder->parser)
{
gckPARSER_Destroy(Os, Recorder->parser);
}
gcmkOS_SAFE_FREE(Os, Recorder);
return gcvSTATUS_OK;
}
gceSTATUS
gckRECORDER_UpdateMirror(
IN gckRECORDER Recorder,
IN gctUINT32 State,
IN gctUINT32 Data
)
{
gctUINT32 index;
gcsSTATE_MAP_PTR map = Recorder->mirror.map;
gctUINT32_PTR buffer = Recorder->mirror.logical[Recorder->index];
if (State >= Recorder->mirror.maxState)
{
/* Ignore them just like HW does. */
return gcvSTATUS_OK;
}
index = map[State].index;
if (index)
{
buffer[index] = Data;
}
return gcvSTATUS_OK;
}
void
gckRECORDER_AdvanceIndex(
IN gckRECORDER Recorder,
IN gctUINT64 CommitStamp
)
{
/* Get next record. */
gctUINT next = (Recorder->index + 1) % gcdNUM_RECORDS;
/* Record stamp of this commit. */
Recorder->deltas[Recorder->index].commitStamp = CommitStamp;
/* Mirror of next record is mirror of this record and delta in next record. */
gckOS_MemCopy(Recorder->mirror.logical[next],
Recorder->mirror.logical[Recorder->index], Recorder->mirror.bytes);
/* Advance to next record. */
Recorder->index = next;
Recorder->num = gcmMIN(Recorder->num + 1, gcdNUM_RECORDS - 1);
/* Reset delta. */
Recorder->deltas[Recorder->index].commandBytes = 0;
Recorder->deltas[Recorder->index].contextBytes = 0;
}
void
gckRECORDER_Record(
IN gckRECORDER Recorder,
IN gctUINT8_PTR CommandBuffer,
IN gctUINT32 CommandBytes,
IN gctUINT8_PTR ContextBuffer,
IN gctUINT32 ContextBytes
)
{
gcsDELTA * delta = &Recorder->deltas[Recorder->index];
if (CommandBytes != 0xFFFFFFFF)
{
gckPARSER_Parse(Recorder->parser, CommandBuffer, CommandBytes);
gckOS_MemCopy(delta->command, CommandBuffer, CommandBytes);
delta->commandBytes = CommandBytes;
}
if (ContextBytes != 0xFFFFFFFF)
{
gckPARSER_Parse(Recorder->parser, ContextBuffer, ContextBytes);
gckOS_MemCopy(delta->context, ContextBuffer, ContextBytes);
delta->contextBytes = ContextBytes;
}
}
void
gckRECORDER_Dump(
IN gckRECORDER Recorder
)
{
gctUINT last = Recorder->index;
gctUINT previous;
gctUINT i;
gcsMIRROR *mirror = &Recorder->mirror;
gcsDELTA *delta;
gckOS os = Recorder->os;
for (i = 0; i < Recorder->num; i++)
{
last = _Previous(last);
}
for (i = 0; i < Recorder->num; i++)
{
delta = &Recorder->deltas[last];
/* Dump record */
gcmkPRINT("#[commit %llu]", delta->commitStamp);
if (delta->commitStamp)
{
previous = _Previous(last);
gcmkPRINT("#[mirror]");
gckOS_DumpBuffer(os, mirror->logical[previous], mirror->bytes, gcvDUMP_BUFFER_CONTEXT, gcvTRUE);
gcmkPRINT("@[kernel.execute]");
}
if (delta->contextBytes)
{
gckOS_DumpBuffer(os, delta->context, delta->contextBytes, gcvDUMP_BUFFER_CONTEXT, gcvTRUE);
gcmkPRINT("@[kernel.execute]");
}
gckOS_DumpBuffer(os, delta->command, delta->commandBytes, gcvDUMP_BUFFER_USER, gcvTRUE);
gcmkPRINT("@[kernel.execute]");
last = _Next(last);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,353 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_command_vg_h_
#define __gc_hal_kernel_hardware_command_vg_h_
/******************************************************************************\
******************* Task and Interrupt Management Structures. ******************
\******************************************************************************/
/* Task storage header. */
typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
typedef struct _gcsTASK_STORAGE
{
/* Next allocated storage buffer. */
gcsTASK_STORAGE_PTR next;
}
gcsTASK_STORAGE;
/* Task container header. */
typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
typedef struct _gcsTASK_CONTAINER
{
/* The number of tasks left to be processed in the container. */
gctINT referenceCount;
/* Size of the buffer. */
gctUINT size;
/* Link to the previous and the next allocated containers. */
gcsTASK_CONTAINER_PTR allocPrev;
gcsTASK_CONTAINER_PTR allocNext;
/* Link to the previous and the next containers in the free list. */
gcsTASK_CONTAINER_PTR freePrev;
gcsTASK_CONTAINER_PTR freeNext;
}
gcsTASK_CONTAINER;
/* Kernel space task master table entry. */
typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
typedef struct _gcsBLOCK_TASK_ENTRY
{
/* Pointer to the current task container for the block. */
gcsTASK_CONTAINER_PTR container;
/* Pointer to the current task data within the container. */
gcsTASK_HEADER_PTR task;
/* Pointer to the last link task within the container. */
gcsTASK_LINK_PTR link;
/* Number of interrupts allocated for this block. */
gctUINT interruptCount;
/* The index of the current interrupt. */
gctUINT interruptIndex;
/* Interrupt semaphore. */
gctSEMAPHORE interruptSemaphore;
/* Interrupt value array. */
gctINT32 interruptArray[32];
}
gcsBLOCK_TASK_ENTRY;
/******************************************************************************\
********************* Command Queue Management Structures. *********************
\******************************************************************************/
/* Command queue kernel element pointer. */
typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
/* Command queue object handler function type. */
typedef gceSTATUS (* gctOBJECT_HANDLER) (
gckVGKERNEL Kernel,
gcsKERNEL_CMDQUEUE_PTR Entry
);
/* Command queue kernel element. */
typedef struct _gcsKERNEL_CMDQUEUE
{
/* The number of buffers in the queue. */
gcsCMDBUFFER_PTR commandBuffer;
/* Pointer to the object handler function. */
gctOBJECT_HANDLER handler;
}
gcsKERNEL_CMDQUEUE;
/* Command queue header. */
typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
typedef struct _gcsKERNEL_QUEUE_HEADER
{
/* The size of the buffer in bytes. */
gctUINT size;
/* The number of pending entries to be processed. */
volatile gctUINT pending;
/* The current command queue entry. */
gcsKERNEL_CMDQUEUE_PTR currentEntry;
/* Next buffer. */
gcsKERNEL_QUEUE_HEADER_PTR next;
}
gcsKERNEL_QUEUE_HEADER;
/******************************************************************************\
******************************* gckVGCOMMAND Object *******************************
\******************************************************************************/
/* gckVGCOMMAND object. */
struct _gckVGCOMMAND
{
/***************************************************************************
** Object data and pointers.
*/
gcsOBJECT object;
gckVGKERNEL kernel;
gckOS os;
gckVGHARDWARE hardware;
/* Features. */
gctBOOL fe20;
gctBOOL vg20;
gctBOOL vg21;
/***************************************************************************
** Enable command queue dumping.
*/
gctBOOL enableDumping;
/***************************************************************************
** Bus Error interrupt.
*/
gctINT32 busErrorInt;
/***************************************************************************
** Command buffer information.
*/
gcsCOMMAND_BUFFER_INFO info;
/***************************************************************************
** Synchronization objects.
*/
gctPOINTER queueMutex;
gctPOINTER taskMutex;
gctPOINTER commitMutex;
/***************************************************************************
** Task management.
*/
/* The head of the storage buffer linked list. */
gcsTASK_STORAGE_PTR taskStorage;
/* Allocation size. */
gctUINT taskStorageGranularity;
gctUINT taskStorageUsable;
/* The free container list. */
gcsTASK_CONTAINER_PTR taskFreeHead;
gcsTASK_CONTAINER_PTR taskFreeTail;
/* Task table */
gcsBLOCK_TASK_ENTRY taskTable[gcvBLOCK_COUNT];
/***************************************************************************
** Command queue.
*/
/* Pointer to the allocated queue memory. */
gcsKERNEL_QUEUE_HEADER_PTR queue;
/* Pointer to the current available queue from which new queue entries
will be allocated. */
gcsKERNEL_QUEUE_HEADER_PTR queueHead;
/* If different from queueHead, points to the command queue which is
currently being executed by the hardware. */
gcsKERNEL_QUEUE_HEADER_PTR queueTail;
/* Points to the queue to merge the tail with when the tail is processed. */
gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
/* Queue overflow counter. */
gctUINT queueOverflow;
/***************************************************************************
** Context.
*/
/* Context counter used for unique ID. */
gctUINT64 contextCounter;
/* Current context ID. */
gctUINT64 currentContext;
/* Command queue power semaphore. */
gctPOINTER powerSemaphore;
gctINT32 powerStallInt;
gcsCMDBUFFER_PTR powerStallBuffer;
gctSIGNAL powerStallSignal;
};
/******************************************************************************\
************************ gckVGCOMMAND Object Internal API. ***********************
\******************************************************************************/
/* Initialize architecture dependent command buffer information. */
gceSTATUS
gckVGCOMMAND_InitializeInfo(
IN gckVGCOMMAND Command
);
/* Form a STATE command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_StateCommand(
IN gckVGCOMMAND Command,
IN gctUINT32 Pipe,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN gctUINT32 Count,
IN OUT gctUINT32 * Bytes
);
/* Form a RESTART command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_RestartCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a FETCH command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_FetchCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a CALL command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_CallCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a RETURN command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_ReturnCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN OUT gctUINT32 * Bytes
);
/* Form an EVENT command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_EventCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gceBLOCK Block,
IN gctINT32 InterruptId,
IN OUT gctUINT32 * Bytes
);
/* Form an END command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_EndCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctINT32 InterruptId,
IN OUT gctUINT32 * Bytes
);
#endif /* __gc_hal_kernel_hardware_command_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_vg_h_
#define __gc_hal_kernel_hardware_vg_h_
/* gckHARDWARE object. */
struct _gckVGHARDWARE
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckKERNEL object. */
gckVGKERNEL kernel;
/* Pointer to gckOS object. */
gckOS os;
/* Chip characteristics. */
gceCHIPMODEL chipModel;
gctUINT32 chipRevision;
gctUINT32 productID;
gctUINT32 ecoID;
gctUINT32 customerID;
gctUINT32 chipFeatures;
gctUINT32 chipMinorFeatures;
gctUINT32 chipMinorFeatures2;
/* Features. */
gctBOOL fe20;
gctBOOL vg20;
gctBOOL vg21;
gctBOOL fc;
/* Event mask. */
gctUINT32 eventMask;
gctBOOL clockState;
gctBOOL powerState;
gctPOINTER powerMutex;
gctUINT32 powerProcess;
gctUINT32 powerThread;
gceCHIPPOWERSTATE chipPowerState;
gceCHIPPOWERSTATE chipPowerStateGlobal;
gctPOINTER pageTableDirty;
#if gcdPOWEROFF_TIMEOUT
gctUINT32 powerOffTime;
gctUINT32 powerOffTimeout;
gctPOINTER powerOffTimer;
#endif
gcsHAL_QUERY_CHIP_OPTIONS options;
gctPOINTER featureDatabase;
};
#endif /* __gc_hal_kernel_hardware_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,477 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#include "gc_hal_kernel_context.h"
#define _GC_OBJ_ZONE gcvZONE_ASYNC_COMMAND
static gceSTATUS
_HandlePatchList(
IN gckASYNC_COMMAND Command,
IN gcoCMDBUF CommandBuffer,
IN gctBOOL NeedCopy
)
{
gceSTATUS status;
gcsPATCH_LIST * uList;
gcsPATCH_LIST * previous;
gcsPATCH_LIST * kList;
gcmkHEADER_ARG(
"Command=0x%x CommandBuffer=0x%x NeedCopy=%d",
Command, CommandBuffer, NeedCopy
);
uList = gcmUINT64_TO_PTR(CommandBuffer->patchHead);
while (uList)
{
gctUINT i;
kList = gcvNULL;
previous = uList;
gcmkONERROR(gckKERNEL_OpenUserData(
Command->kernel,
NeedCopy,
Command->kList,
uList,
gcmSIZEOF(gcsPATCH_LIST),
(gctPOINTER *)&kList
));
for (i = 0; i < kList->count; i++)
{
gcsPATCH * patch = &kList->patch[i];
/* Touch video memory node. */
gcmkVERIFY_OK(gckVIDMEM_SetCommitStamp(Command->kernel, gcvENGINE_BLT, patch->handle, Command->commitStamp));
}
uList = kList->next;
gcmkVERIFY_OK(gckKERNEL_CloseUserData(
Command->kernel,
NeedCopy,
gcvFALSE,
previous,
gcmSIZEOF(gcsPATCH_LIST),
(gctPOINTER *)&kList
));
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (kList)
{
gcmkVERIFY_OK(gckKERNEL_CloseUserData(
Command->kernel,
NeedCopy,
gcvFALSE,
previous,
gcmSIZEOF(gcsPATCH_LIST),
(gctPOINTER *)&kList
));
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckASYNC_COMMAND_Construct(
IN gckKERNEL Kernel,
OUT gckASYNC_COMMAND * Command
)
{
gceSTATUS status;
gckASYNC_COMMAND command;
gckOS os = Kernel->os;
gcmkHEADER();
/* Allocate gckASYNC_COMMAND object. */
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsASYNC_COMMAND), (gctPOINTER *)&command));
gckOS_ZeroMemory(command, gcmSIZEOF(gcsASYNC_COMMAND));
/* Mutex to protect gckFE. */
gcmkONERROR(gckOS_CreateMutex(os, &command->mutex));
/* Initialize gckFE. */
gckFE_Initialize(Kernel->hardware, &command->fe);
/* Initialize gckASYNC_COMMAND object. */
command->os = os;
command->kernel = Kernel;
command->hardware = Kernel->hardware;
gcmkVERIFY_OK(gckHARDWARE_QueryCommandBuffer(
Kernel->hardware,
gcvENGINE_BLT,
gcvNULL,
gcvNULL,
&command->reservedTail
));
gcmkONERROR(gckFENCE_Create(
os, Kernel, &command->fence
));
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsPATCH_LIST), &command->kList));
/* Commit stamp start from 1. */
command->commitStamp = 1;
*Command = command;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Rollback. */
gckASYNC_COMMAND_Destroy(command);
gcmkFOOTER();
return status;
}
gceSTATUS
gckASYNC_COMMAND_Destroy(
IN gckASYNC_COMMAND Command
)
{
gcmkHEADER();
if (Command)
{
if (Command->mutex)
{
gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutex));
}
if (Command->fence)
{
gcmkVERIFY_OK(gckFENCE_Destory(Command->os, Command->fence));
}
if (Command->kList)
{
gcmkOS_SAFE_FREE(Command->os, Command->kList);
}
if (Command->fe.freeDscriptors)
{
gcmkOS_SAFE_FREE(Command->os, Command->fe.freeDscriptors);
}
gcmkOS_SAFE_FREE(Command->os, Command);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckASYNC_COMMAND_Commit(
IN gckASYNC_COMMAND Command,
IN gcoCMDBUF CommandBuffer,
IN gcsQUEUE_PTR EventQueue
)
{
gceSTATUS status;
gctBOOL available = gcvFALSE;
gctBOOL acquired = gcvFALSE;
gcoCMDBUF commandBufferObject = gcvNULL;
struct _gcoCMDBUF _commandBufferObject;
gctUINT8_PTR commandBufferLogical;
gctUINT8_PTR commandBufferTail;
gctUINT commandBufferSize;
gctUINT32 commandBufferAddress;
gcsFEDescriptor descriptor;
gctUINT32 skipFlushBytes;
gctUINT32 fenceBytes;
gctBOOL needCopy;
gctUINT32 oldValue;
gctUINT32 flushBytes;
gcmkHEADER();
gckOS_QueryNeedCopy(Command->os, 0, &needCopy);
gcmkVERIFY_OK(_HandlePatchList(Command, CommandBuffer, needCopy));
/* Open user passed gcoCMDBUF object. */
gcmkONERROR(gckKERNEL_OpenUserData(
Command->kernel,
needCopy,
&_commandBufferObject,
CommandBuffer,
gcmSIZEOF(struct _gcoCMDBUF),
(gctPOINTER *)&commandBufferObject
));
gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
gckHARDWARE_FlushAsyncMMU(Command->hardware, gcvNULL, &flushBytes);
gcmkONERROR(gckOS_AtomicExchange(Command->os,
Command->hardware->pageTableDirty[gcvENGINE_BLT],
0,
&oldValue));
if (oldValue)
{
commandBufferLogical
= (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
+ commandBufferObject->startOffset;
gckHARDWARE_FlushAsyncMMU(Command->hardware, commandBufferLogical, &flushBytes);
skipFlushBytes = 0;
}
else
{
skipFlushBytes = flushBytes;
}
/* Compute the command buffer entry and the size. */
commandBufferLogical
= (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
+ commandBufferObject->startOffset
+ skipFlushBytes;
commandBufferSize
= commandBufferObject->offset
+ Command->reservedTail
- commandBufferObject->startOffset
- skipFlushBytes;
commandBufferTail
= commandBufferLogical
+ commandBufferSize
- Command->reservedTail;
/* Get the hardware address. */
if (Command->kernel && Command->kernel->virtualCommandBuffer)
{
gckKERNEL kernel = Command->kernel;
gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer
= gcmNAME_TO_PTR(commandBufferObject->physical);
if (virtualCommandBuffer == gcvNULL)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gcmkONERROR(gckKERNEL_GetGPUAddress(
Command->kernel,
commandBufferLogical,
gcvTRUE,
virtualCommandBuffer,
&commandBufferAddress
));
}
else
{
gcmkONERROR(gckHARDWARE_ConvertLogical(
Command->hardware,
commandBufferLogical,
gcvTRUE,
&commandBufferAddress
));
}
gcmkONERROR(gckHARDWARE_Fence(
Command->hardware,
gcvENGINE_BLT,
commandBufferTail,
Command->fence->address,
Command->commitStamp,
&fenceBytes
));
descriptor.start = commandBufferAddress;
descriptor.end = commandBufferAddress + commandBufferSize;
gcmkDUMPCOMMAND(
Command->os,
commandBufferLogical,
commandBufferSize,
gcvDUMP_BUFFER_USER,
gcvFALSE
);
gckOS_AcquireMutex(Command->os, Command->mutex, gcvINFINITE);
acquired = gcvTRUE;
/* Acquire a slot. */
for(;;)
{
gcmkONERROR(gckFE_ReserveSlot(Command->hardware, &Command->fe, &available));
if (available)
{
break;
}
else
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE, "No available slot, have to wait");
gckOS_Delay(Command->os, 1);
}
}
/* Send descriptor. */
gckFE_Execute(Command->hardware, &Command->fe, &descriptor);
Command->commitStamp++;
gckOS_ReleaseMutex(Command->os, Command->mutex);
acquired = gcvFALSE;
gcmkVERIFY_OK(gckKERNEL_CloseUserData(
Command->kernel,
needCopy,
gcvFALSE,
CommandBuffer,
gcmSIZEOF(struct _gcoCMDBUF),
(gctPOINTER *)&commandBufferObject
));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (acquired)
{
gckOS_ReleaseMutex(Command->os, Command->mutex);
}
if (commandBufferObject)
{
gcmkVERIFY_OK(gckKERNEL_CloseUserData(
Command->kernel,
needCopy,
gcvFALSE,
CommandBuffer,
gcmSIZEOF(struct _gcoCMDBUF),
(gctPOINTER *)&commandBufferObject
));
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckASYNC_COMMAND_EnterCommit(
IN gckASYNC_COMMAND Command
)
{
return gckOS_AcquireMutex(Command->os, Command->mutex, gcvINFINITE);
}
gceSTATUS
gckASYNC_COMMAND_ExitCommit(
IN gckASYNC_COMMAND Command
)
{
return gckOS_ReleaseMutex(Command->os, Command->mutex);
}
gceSTATUS
gckASYNC_COMMAND_Execute(
IN gckASYNC_COMMAND Command,
IN gctUINT32 Start,
IN gctUINT32 End
)
{
gceSTATUS status;
gcsFEDescriptor descriptor;
gctBOOL available;
descriptor.start = Start;
descriptor.end = End;
/* Acquire a slot. */
for(;;)
{
gcmkONERROR(gckFE_ReserveSlot(Command->hardware, &Command->fe, &available));
if (available)
{
break;
}
else
{
gckOS_Delay(Command->os, 1);
}
}
/* Send descriptor. */
gckFE_Execute(Command->hardware, &Command->fe, &descriptor);
return gcvSTATUS_OK;
OnError:
return status;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,892 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
/**
** @file
** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
** based memory allocation. An arena-based memory heap allocates data quickly
** from specified arenas and reduces memory fragmentation.
**
*/
#include "gc_hal_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_HEAP
/*******************************************************************************
***** Structures ***************************************************************
*******************************************************************************/
#define gcdIN_USE ((gcskNODE_PTR)gcvMAXUINTPTR_T)
typedef struct _gcskNODE * gcskNODE_PTR;
typedef struct _gcskNODE
{
/* Number of byets in node. */
gctSIZE_T bytes;
/* Pointer to next free node, or gcvNULL to mark the node as freed, or
** gcdIN_USE to mark the node as used. */
gcskNODE_PTR next;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
/* Time stamp of allocation. */
gctUINT64 timeStamp;
#endif
}
gcskNODE;
typedef struct _gcskHEAP * gcskHEAP_PTR;
typedef struct _gcskHEAP
{
/* Linked list. */
gcskHEAP_PTR next;
gcskHEAP_PTR prev;
/* Heap size. */
gctSIZE_T size;
/* Free list. */
gcskNODE_PTR freeList;
}
gcskHEAP;
struct _gckHEAP
{
/* Object. */
gcsOBJECT object;
/* Pointer to a gckOS object. */
gckOS os;
/* Locking mutex. */
gctPOINTER mutex;
/* Allocation parameters. */
gctSIZE_T allocationSize;
/* Heap list. */
gcskHEAP_PTR heap;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gctUINT64 timeStamp;
#endif
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Profile information. */
gctUINT32 allocCount;
gctUINT64 allocBytes;
gctUINT64 allocBytesMax;
gctUINT64 allocBytesTotal;
gctUINT32 heapCount;
gctUINT32 heapCountMax;
gctUINT64 heapMemory;
gctUINT64 heapMemoryMax;
#endif
};
/*******************************************************************************
***** Static Support Functions *************************************************
*******************************************************************************/
#if gcmIS_DEBUG(gcdDEBUG_CODE)
static gctSIZE_T
_DumpHeap(
IN gcskHEAP_PTR Heap
)
{
gctPOINTER p;
gctSIZE_T leaked = 0;
/* Start at first node. */
for (p = Heap + 1;;)
{
/* Convert the pointer. */
gcskNODE_PTR node = (gcskNODE_PTR) p;
/* Check if this is a used node. */
if (node->next == gcdIN_USE)
{
/* Print the leaking node. */
gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
"Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
"(%08X %c%c%c%c)",
node, node->bytes, node->timeStamp,
((gctUINT32_PTR) (node + 1))[0],
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
/* Add leaking byte count. */
leaked += node->bytes;
}
/* Test for end of heap. */
if (node->bytes == 0)
{
break;
}
else
{
/* Move to next node. */
p = (gctUINT8_PTR) node + node->bytes;
}
}
/* Return the number of leaked bytes. */
return leaked;
}
#endif
static gceSTATUS
_CompactKernelHeap(
IN gckHEAP Heap
)
{
gcskHEAP_PTR heap, next;
gctPOINTER p;
gcskHEAP_PTR freeList = gcvNULL;
gcmkHEADER_ARG("Heap=0x%x", Heap);
/* Walk all the heaps. */
for (heap = Heap->heap; heap != gcvNULL; heap = next)
{
gcskNODE_PTR lastFree = gcvNULL;
/* Zero out the free list. */
heap->freeList = gcvNULL;
/* Start at the first node. */
for (p = (gctUINT8_PTR) (heap + 1);;)
{
/* Convert the pointer. */
gcskNODE_PTR node = (gcskNODE_PTR) p;
gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
/* Test if this node not used. */
if (node->next != gcdIN_USE)
{
/* Test if this is the end of the heap. */
if (node->bytes == 0)
{
break;
}
/* Test of this is the first free node. */
else if (lastFree == gcvNULL)
{
/* Initialzie the free list. */
heap->freeList = node;
lastFree = node;
}
else
{
/* Test if this free node is contiguous with the previous
** free node. */
if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
{
/* Just increase the size of the previous free node. */
lastFree->bytes += node->bytes;
}
else
{
/* Add to linked list. */
lastFree->next = node;
lastFree = node;
}
}
}
/* Move to next node. */
p = (gctUINT8_PTR) node + node->bytes;
}
/* Mark the end of the chain. */
if (lastFree != gcvNULL)
{
lastFree->next = gcvNULL;
}
/* Get next heap. */
next = heap->next;
/* Check if the entire heap is free. */
if ((heap->freeList != gcvNULL)
&& (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
)
{
/* Remove the heap from the linked list. */
if (heap->prev == gcvNULL)
{
Heap->heap = next;
}
else
{
heap->prev->next = next;
}
if (heap->next != gcvNULL)
{
heap->next->prev = heap->prev;
}
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profiling. */
Heap->heapCount -= 1;
Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
#endif
/* Add this heap to the list of heaps that need to be freed. */
heap->next = freeList;
freeList = heap;
}
}
if (freeList != gcvNULL)
{
/* Release the mutex, remove any chance for a dead lock. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Free all heaps in the free list. */
for (heap = freeList; heap != gcvNULL; heap = next)
{
/* Get pointer to the next heap. */
next = heap->next;
/* Free the heap. */
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
"Freeing heap 0x%x (%lu bytes)",
heap, heap->size + gcmSIZEOF(gcskHEAP));
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
}
/* Acquire the mutex again. */
gcmkVERIFY_OK(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
}
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/*******************************************************************************
***** gckHEAP API Code *********************************************************
*******************************************************************************/
/*******************************************************************************
**
** gckHEAP_Construct
**
** Construct a new gckHEAP object.
**
** INPUT:
**
** gckOS Os
** Pointer to a gckOS object.
**
** gctSIZE_T AllocationSize
** Minimum size per arena.
**
** OUTPUT:
**
** gckHEAP * Heap
** Pointer to a variable that will hold the pointer to the gckHEAP
** object.
*/
gceSTATUS
gckHEAP_Construct(
IN gckOS Os,
IN gctSIZE_T AllocationSize,
OUT gckHEAP * Heap
)
{
gceSTATUS status;
gckHEAP heap = gcvNULL;
gctPOINTER pointer = gcvNULL;
gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
/* Allocate the gckHEAP object. */
gcmkONERROR(gckOS_AllocateMemory(Os,
gcmSIZEOF(struct _gckHEAP),
&pointer));
heap = pointer;
/* Initialize the gckHEAP object. */
heap->object.type = gcvOBJ_HEAP;
heap->os = Os;
heap->allocationSize = AllocationSize;
heap->heap = gcvNULL;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
heap->timeStamp = 0;
#endif
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Zero the counters. */
heap->allocCount = 0;
heap->allocBytes = 0;
heap->allocBytesMax = 0;
heap->allocBytesTotal = 0;
heap->heapCount = 0;
heap->heapCountMax = 0;
heap->heapMemory = 0;
heap->heapMemoryMax = 0;
#endif
/* Create the mutex. */
gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
/* Return the pointer to the gckHEAP object. */
*Heap = heap;
/* Success. */
gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
return gcvSTATUS_OK;
OnError:
/* Roll back. */
if (heap != gcvNULL)
{
/* Free the heap structure. */
gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
}
/* Return the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckHEAP_Destroy
**
** Destroy a gckHEAP object.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckHEAP_Destroy(
IN gckHEAP Heap
)
{
gcskHEAP_PTR heap;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gctSIZE_T leaked = 0;
#endif
gcmkHEADER_ARG("Heap=0x%x", Heap);
for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
{
/* Unlink heap from linked list. */
Heap->heap = heap->next;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
/* Check for leaked memory. */
leaked += _DumpHeap(heap);
#endif
/* Free the heap. */
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
}
/* Free the mutex. */
gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
/* Free the heap structure. */
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
/* Success. */
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gcmkFOOTER_ARG("leaked=%lu", leaked);
#else
gcmkFOOTER_NO();
#endif
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckHEAP_Allocate
**
** Allocate data from the heap.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object.
**
** IN gctSIZE_T Bytes
** Number of byte to allocate.
**
** OUTPUT:
**
** gctPOINTER * Memory
** Pointer to a variable that will hold the address of the allocated
** memory.
*/
gceSTATUS
gckHEAP_Allocate(
IN gckHEAP Heap,
IN gctSIZE_T Bytes,
OUT gctPOINTER * Memory
)
{
gctBOOL acquired = gcvFALSE;
gcskHEAP_PTR heap;
gceSTATUS status;
gctSIZE_T bytes;
gcskNODE_PTR node, used, prevFree = gcvNULL;
gctPOINTER memory = gcvNULL;
gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Bytes > 0);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
/* Determine number of bytes required for a node. */
bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
acquired = gcvTRUE;
/* Check if this allocation is bigger than the default allocation size. */
if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
{
/* Adjust allocation size. */
Heap->allocationSize = bytes * 2;
}
else if (Heap->heap != gcvNULL)
{
gctINT i;
/* 2 retries, since we might need to compact. */
for (i = 0; i < 2; ++i)
{
/* Walk all the heaps. */
for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
{
/* Check if this heap has enough bytes to hold the request. */
if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
{
prevFree = gcvNULL;
/* Walk the chain of free nodes. */
for (node = heap->freeList;
node != gcvNULL;
node = node->next
)
{
gcmkASSERT(node->next != gcdIN_USE);
/* Check if this free node has enough bytes. */
if (node->bytes >= bytes)
{
/* Use the node. */
goto UseNode;
}
/* Save current free node for linked list management. */
prevFree = node;
}
}
}
if (i == 0)
{
/* Compact the heap. */
gcmkVERIFY_OK(_CompactKernelHeap(Heap));
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"===== KERNEL HEAP =====");
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of allocations : %12u",
Heap->allocCount);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of bytes allocated : %12llu",
Heap->allocBytes);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum allocation size : %12llu",
Heap->allocBytesMax);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Total number of bytes allocated : %12llu",
Heap->allocBytesTotal);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of heaps : %12u",
Heap->heapCount);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Heap memory in bytes : %12llu",
Heap->heapMemory);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum number of heaps : %12u",
Heap->heapCountMax);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum heap memory in bytes : %12llu",
Heap->heapMemoryMax);
#endif
}
}
}
/* Release the mutex. */
gcmkONERROR(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
acquired = gcvFALSE;
/* Allocate a new heap. */
gcmkONERROR(
gckOS_AllocateMemory(Heap->os,
Heap->allocationSize,
&memory));
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
"Allocated heap 0x%x (%lu bytes)",
memory, Heap->allocationSize);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
acquired = gcvTRUE;
/* Use the allocated memory as the heap. */
heap = (gcskHEAP_PTR) memory;
/* Insert this heap to the head of the chain. */
heap->next = Heap->heap;
heap->prev = gcvNULL;
heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
if (heap->next != gcvNULL)
{
heap->next->prev = heap;
}
Heap->heap = heap;
/* Mark the end of the heap. */
node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ Heap->allocationSize
- gcmSIZEOF(gcskNODE)
);
node->bytes = 0;
node->next = gcvNULL;
/* Create a free list. */
node = (gcskNODE_PTR) (heap + 1);
heap->freeList = node;
/* Initialize the free list. */
node->bytes = heap->size - gcmSIZEOF(gcskNODE);
node->next = gcvNULL;
/* No previous free. */
prevFree = gcvNULL;
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profiling. */
Heap->heapCount += 1;
Heap->heapMemory += Heap->allocationSize;
if (Heap->heapCount > Heap->heapCountMax)
{
Heap->heapCountMax = Heap->heapCount;
}
if (Heap->heapMemory > Heap->heapMemoryMax)
{
Heap->heapMemoryMax = Heap->heapMemory;
}
#endif
UseNode:
/* Verify some stuff. */
gcmkASSERT(heap != gcvNULL);
gcmkASSERT(node != gcvNULL);
gcmkASSERT(node->bytes >= bytes);
if (heap->prev != gcvNULL)
{
/* Unlink the heap from the linked list. */
heap->prev->next = heap->next;
if (heap->next != gcvNULL)
{
heap->next->prev = heap->prev;
}
/* Move the heap to the front of the list. */
heap->next = Heap->heap;
heap->prev = gcvNULL;
Heap->heap = heap;
heap->next->prev = heap;
}
/* Check if there is enough free space left after usage for another free
** node. */
if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
{
/* Allocated used space from the back of the free list. */
used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
/* Adjust the number of free bytes. */
node->bytes -= bytes;
gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
}
else
{
/* Remove this free list from the chain. */
if (prevFree == gcvNULL)
{
heap->freeList = node->next;
}
else
{
prevFree->next = node->next;
}
/* Consume the entire free node. */
used = (gcskNODE_PTR) node;
bytes = node->bytes;
}
/* Mark node as used. */
used->bytes = bytes;
used->next = gcdIN_USE;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
used->timeStamp = ++Heap->timeStamp;
#endif
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profile counters. */
Heap->allocCount += 1;
Heap->allocBytes += bytes;
Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
Heap->allocBytesTotal += bytes;
#endif
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Return pointer to memory. */
*Memory = used + 1;
/* Success. */
gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
return gcvSTATUS_OK;
OnError:
if (acquired)
{
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
}
if (memory != gcvNULL)
{
/* Free the heap memory. */
gckOS_FreeMemory(Heap->os, memory);
}
/* Return the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckHEAP_Free
**
** Free allocated memory from the heap.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object.
**
** IN gctPOINTER Memory
** Pointer to memory to free.
**
** OUTPUT:
**
** NOTHING.
*/
gceSTATUS
gckHEAP_Free(
IN gckHEAP Heap,
IN gctPOINTER Memory
)
{
gcskNODE_PTR node;
gceSTATUS status;
gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
/* Pointer to structure. */
node = (gcskNODE_PTR) Memory - 1;
/* Mark the node as freed. */
node->next = gcvNULL;
#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profile counters. */
Heap->allocBytes -= node->bytes;
#endif
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
#if VIVANTE_PROFILER
gceSTATUS
gckHEAP_ProfileStart(
IN gckHEAP Heap
)
{
gcmkHEADER_ARG("Heap=0x%x", Heap);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
/* Zero the counters. */
Heap->allocCount = 0;
Heap->allocBytes = 0;
Heap->allocBytesMax = 0;
Heap->allocBytesTotal = 0;
Heap->heapCount = 0;
Heap->heapCountMax = 0;
Heap->heapMemory = 0;
Heap->heapMemoryMax = 0;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckHEAP_ProfileEnd(
IN gckHEAP Heap,
IN gctCONST_STRING Title
)
{
gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Title != gcvNULL);
gcmkPRINT("");
gcmkPRINT("=====[ HEAP - %s ]=====", Title);
gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
gcmkPRINT("==============================================");
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif /* VIVANTE_PROFILER */
/*******************************************************************************
***** Test Code ****************************************************************
*******************************************************************************/

View File

@ -0,0 +1,911 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#if gcdENABLE_VG
/******************************************************************************\
*********************** Support Functions and Definitions **********************
\******************************************************************************/
/* Interruot statistics will be accumulated if not zero. */
#define gcmENABLE_INTERRUPT_STATISTICS 0
#define _GC_OBJ_ZONE gcvZONE_INTERRUPT
/* Object structure. */
struct _gckVGINTERRUPT
{
/* Object. */
gcsOBJECT object;
/* gckVGKERNEL pointer. */
gckVGKERNEL kernel;
/* gckOS pointer. */
gckOS os;
/* Interrupt handlers. */
gctINTERRUPT_HANDLER handlers[32];
/* Main interrupt handler thread. */
gctTHREAD handler;
gctBOOL terminate;
/* Interrupt FIFO. */
gctSEMAPHORE fifoValid;
gctUINT32 fifo[256];
gctUINT fifoItems;
gctUINT8 head;
gctUINT8 tail;
/* Interrupt statistics. */
#if gcmENABLE_INTERRUPT_STATISTICS
gctUINT maxFifoItems;
gctUINT fifoOverflow;
gctUINT maxSimultaneous;
gctUINT multipleCount;
#endif
};
/*******************************************************************************
**
** _ProcessInterrupt
**
** The interrupt processor.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#if gcmENABLE_INTERRUPT_STATISTICS
static void
_ProcessInterrupt(
gckVGINTERRUPT Interrupt,
gctUINT_PTR TriggeredCount
)
#else
static void
_ProcessInterrupt(
gckVGINTERRUPT Interrupt
)
#endif
{
gceSTATUS status;
gctUINT32 triggered;
gctUINT i;
/* Advance to the next entry. */
Interrupt->tail += 1;
Interrupt->fifoItems -= 1;
/* Get the interrupt value. */
triggered = Interrupt->fifo[Interrupt->tail];
gcmkASSERT(triggered != 0);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: triggered=0x%08X\n",
__FUNCTION__,
triggered
);
/* Walk through all possible interrupts. */
for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
{
/* Test if interrupt happened. */
if ((triggered & 1) == 1)
{
#if gcmENABLE_INTERRUPT_STATISTICS
if (TriggeredCount != gcvNULL)
{
(* TriggeredCount) += 1;
}
#endif
/* Make sure we have valid handler. */
if (Interrupt->handlers[i] == gcvNULL)
{
gcmkTRACE(
gcvLEVEL_ERROR,
"%s: Interrupt %d isn't registered.\n",
__FUNCTION__, i
);
}
else
{
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: interrupt=%d\n",
__FUNCTION__,
i
);
/* Call the handler. */
status = Interrupt->handlers[i] (Interrupt->kernel);
if (gcmkIS_ERROR(status))
{
/* Failed to signal the semaphore. */
gcmkTRACE(
gcvLEVEL_ERROR,
"%s: Error %d incrementing the semaphore #%d.\n",
__FUNCTION__, status, i
);
}
}
}
/* Next interrupt. */
triggered >>= 1;
/* No more interrupts to handle? */
if (triggered == 0)
{
break;
}
}
}
/*******************************************************************************
**
** _MainInterruptHandler
**
** The main interrupt thread serves the interrupt FIFO and calls registered
** handlers for the interrupts that occured. The handlers are called in the
** sequence interrupts occured with the exception when multiple interrupts
** occured at the same time. In that case the handler calls are "sorted" by
** the interrupt number therefore giving the interrupts with lower numbers
** higher priority.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
_MainInterruptHandler(
gctTHREADFUNCPARAMETER ThreadParameter
)
{
gceSTATUS status;
gckVGINTERRUPT interrupt;
#if gcmENABLE_INTERRUPT_STATISTICS
gctUINT count;
#endif
/* Cast the object. */
interrupt = (gckVGINTERRUPT) ThreadParameter;
/* Enter the loop. */
while (gcvTRUE)
{
/* Wait for an interrupt. */
status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
/* Error? */
if (gcmkIS_ERROR(status))
{
break;
}
/* System termination request? */
if (status == gcvSTATUS_TERMINATE)
{
break;
}
/* Driver is shutting down? */
if (interrupt->terminate)
{
break;
}
#if gcmENABLE_INTERRUPT_STATISTICS
/* Reset triggered count. */
count = 0;
/* Process the interrupt. */
_ProcessInterrupt(interrupt, &count);
/* Update conters. */
if (count > interrupt->maxSimultaneous)
{
interrupt->maxSimultaneous = count;
}
if (count > 1)
{
interrupt->multipleCount += 1;
}
#else
/* Process the interrupt. */
_ProcessInterrupt(interrupt);
#endif
}
return 0;
}
/*******************************************************************************
**
** _StartInterruptHandler / _StopInterruptHandler
**
** Main interrupt handler routine control.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
static gceSTATUS
_StartInterruptHandler(
gckVGINTERRUPT Interrupt
)
{
gceSTATUS status, last;
do
{
/* Objects must not be already created. */
gcmkASSERT(Interrupt->fifoValid == gcvNULL);
gcmkASSERT(Interrupt->handler == gcvNULL);
/* Reset the termination request. */
Interrupt->terminate = gcvFALSE;
#if !gcdENABLE_INFINITE_SPEED_HW
/* Construct the fifo semaphore. */
gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
Interrupt->os, &Interrupt->fifoValid
));
/* Start the interrupt handler thread. */
gcmkERR_BREAK(gckOS_StartThread(
Interrupt->os,
_MainInterruptHandler,
Interrupt,
&Interrupt->handler
));
#endif
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (Interrupt->fifoValid != gcvNULL)
{
gcmkCHECK_STATUS(gckOS_DestroySemaphore(
Interrupt->os, Interrupt->fifoValid
));
Interrupt->fifoValid = gcvNULL;
}
/* Return the status. */
return status;
}
static gceSTATUS
_StopInterruptHandler(
gckVGINTERRUPT Interrupt
)
{
gceSTATUS status;
do
{
/* Does the thread exist? */
if (Interrupt->handler == gcvNULL)
{
/* The semaphore must be NULL as well. */
gcmkASSERT(Interrupt->fifoValid == gcvNULL);
/* Success. */
status = gcvSTATUS_OK;
break;
}
/* The semaphore must exist as well. */
gcmkASSERT(Interrupt->fifoValid != gcvNULL);
/* Set the termination request. */
Interrupt->terminate = gcvTRUE;
/* Unlock the thread. */
gcmkERR_BREAK(gckOS_IncrementSemaphore(
Interrupt->os, Interrupt->fifoValid
));
/* Wait until the thread quits. */
gcmkERR_BREAK(gckOS_StopThread(
Interrupt->os,
Interrupt->handler
));
/* Destroy the semaphore. */
gcmkERR_BREAK(gckOS_DestroySemaphore(
Interrupt->os, Interrupt->fifoValid
));
/* Reset handles. */
Interrupt->handler = gcvNULL;
Interrupt->fifoValid = gcvNULL;
}
while (gcvFALSE);
/* Return the status. */
return status;
}
/******************************************************************************\
***************************** Interrupt Object API *****************************
\******************************************************************************/
/*******************************************************************************
**
** gckVGINTERRUPT_Construct
**
** Construct an interrupt object.
**
** INPUT:
**
** Kernel
** Pointer to the gckVGKERNEL object.
**
** OUTPUT:
**
** Interrupt
** Pointer to the new gckVGINTERRUPT object.
*/
gceSTATUS
gckVGINTERRUPT_Construct(
IN gckVGKERNEL Kernel,
OUT gckVGINTERRUPT * Interrupt
)
{
gceSTATUS status;
gckVGINTERRUPT interrupt = gcvNULL;
gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
/* Verify argeuments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
do
{
/* Allocate the gckVGINTERRUPT structure. */
gcmkERR_BREAK(gckOS_Allocate(
Kernel->os,
gcmSIZEOF(struct _gckVGINTERRUPT),
(gctPOINTER *) &interrupt
));
/* Reset the object data. */
gcmkVERIFY_OK(gckOS_ZeroMemory(
interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
));
/* Initialize the object. */
interrupt->object.type = gcvOBJ_INTERRUPT;
/* Initialize the object pointers. */
interrupt->kernel = Kernel;
interrupt->os = Kernel->os;
/* Initialize the current FIFO position. */
interrupt->head = (gctUINT8)~0;
interrupt->tail = (gctUINT8)~0;
/* Start the thread. */
gcmkERR_BREAK(_StartInterruptHandler(interrupt));
/* Return interrupt object. */
*Interrupt = interrupt;
gcmkFOOTER_ARG("*Interrup=0x%x", *Interrupt);
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (interrupt != gcvNULL)
{
/* Free the gckVGINTERRUPT structure. */
gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
}
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Destroy
**
** Destroy an interrupt object.
**
** INPUT:
**
** Interrupt
** Pointer to the gckVGINTERRUPT object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Destroy(
IN gckVGINTERRUPT Interrupt
)
{
gceSTATUS status;
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
do
{
/* Stop the interrupt thread. */
gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
/* Mark the object as unknown. */
Interrupt->object.type = gcvOBJ_UNKNOWN;
/* Free the gckVGINTERRUPT structure. */
gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_DumpState
**
** Print the current state of the interrupt manager.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#if gcvDEBUG
gceSTATUS
gckVGINTERRUPT_DumpState(
IN gckVGINTERRUPT Interrupt
)
{
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
/* Print the header. */
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: INTERRUPT OBJECT STATUS\n",
__FUNCTION__
);
/* Print statistics. */
#if gcmENABLE_INTERRUPT_STATISTICS
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Maximum number of FIFO items accumulated at a single time: %d\n",
Interrupt->maxFifoItems
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Interrupt FIFO overflow happened times: %d\n",
Interrupt->fifoOverflow
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Maximum number of interrupts simultaneously generated: %d\n",
Interrupt->maxSimultaneous
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Number of times when there were multiple interrupts generated: %d\n",
Interrupt->multipleCount
);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" The current number of entries in the FIFO: %d\n",
Interrupt->fifoItems
);
/* Print the FIFO contents. */
if (Interrupt->fifoItems != 0)
{
gctUINT8 index;
gctUINT8 last;
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" FIFO current contents:\n"
);
/* Get the current pointers. */
index = Interrupt->tail;
last = Interrupt->head;
while (index != last)
{
/* Advance to the next entry. */
index += 1;
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" %d: 0x%08X\n",
index, Interrupt->fifo[index]
);
}
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
#endif
/*******************************************************************************
**
** gckVGINTERRUPT_Enable
**
** Enable the specified interrupt.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** Id
** Pointer to the variable that holds the interrupt number to be
** registered in range 0..31.
** If the value is less then 0, gckVGINTERRUPT_Enable will attempt
** to find an unused interrupt. If such interrupt is found, the number
** will be assigned to the variable if the functuion call succeedes.
**
** Handler
** Pointer to the handler to register for the interrupt.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Enable(
IN gckVGINTERRUPT Interrupt,
IN OUT gctINT32_PTR Id,
IN gctINTERRUPT_HANDLER Handler
)
{
gceSTATUS status;
gctINT32 i;
gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
gcmkVERIFY_ARGUMENT(Id != gcvNULL);
gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
do
{
/* See if we need to allocate an ID. */
if (*Id < 0)
{
/* Find the first unused interrupt handler. */
for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
{
if (Interrupt->handlers[i] == gcvNULL)
{
break;
}
}
/* No unused innterrupts? */
if (i == gcmCOUNTOF(Interrupt->handlers))
{
status = gcvSTATUS_OUT_OF_RESOURCES;
break;
}
/* Update the interrupt ID. */
*Id = i;
}
/* Make sure the ID is in range. */
else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
{
status = gcvSTATUS_INVALID_ARGUMENT;
break;
}
/* Set interrupt handler. */
Interrupt->handlers[*Id] = Handler;
/* Success. */
status = gcvSTATUS_OK;
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Disable
**
** Disable the specified interrupt.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** Id
** Interrupt number to be disabled in range 0..31.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Disable(
IN gckVGINTERRUPT Interrupt,
IN gctINT32 Id
)
{
gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
/* Reset interrupt handler. */
Interrupt->handlers[Id] = gcvNULL;
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Enque
**
** Read the interrupt status register and put the value in the interrupt FIFO.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#ifndef __QNXNTO__
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt
)
#else
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt,
OUT gckOS *Os,
OUT gctSEMAPHORE *Semaphore
)
#endif
{
gceSTATUS status;
gctUINT32 triggered;
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
#ifdef __QNXNTO__
*Os = gcvNULL;
*Semaphore = gcvNULL;
#endif
do
{
/* Read interrupt status register. */
gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
Interrupt->kernel->hardware, &triggered
));
/* Mask out TS overflow interrupt */
triggered &= 0xfffffffe;
/* No interrupts to process? */
if (triggered == 0)
{
status = gcvSTATUS_NOT_OUR_INTERRUPT;
break;
}
/* FIFO overflow? */
if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
{
#if gcmENABLE_INTERRUPT_STATISTICS
Interrupt->fifoOverflow += 1;
#endif
/* OR the interrupt with the last value in the FIFO. */
Interrupt->fifo[Interrupt->head] |= triggered;
/* Success (kind of). */
status = gcvSTATUS_OK;
}
else
{
/* Advance to the next entry. */
Interrupt->head += 1;
Interrupt->fifoItems += 1;
#if gcmENABLE_INTERRUPT_STATISTICS
if (Interrupt->fifoItems > Interrupt->maxFifoItems)
{
Interrupt->maxFifoItems = Interrupt->fifoItems;
}
#endif
/* Set the new value. */
Interrupt->fifo[Interrupt->head] = triggered;
#ifndef __QNXNTO__
/* Increment the FIFO semaphore. */
gcmkERR_BREAK(gckOS_IncrementSemaphore(
Interrupt->os, Interrupt->fifoValid
));
#else
*Os = Interrupt->os;
*Semaphore = Interrupt->fifoValid;
#endif
/* Windows kills our threads prematurely when the application
exists. Verify here that the thread is still alive. */
status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
/* Has the thread been prematurely terminated? */
if (status != gcvSTATUS_OK)
{
/* Process all accumulated interrupts. */
while (Interrupt->head != Interrupt->tail)
{
#if gcmENABLE_INTERRUPT_STATISTICS
/* Process the interrupt. */
_ProcessInterrupt(Interrupt, gcvNULL);
#else
/* Process the interrupt. */
_ProcessInterrupt(Interrupt);
#endif
}
/* Set success. */
status = gcvSTATUS_OK;
}
}
}
while (gcvFALSE);
gcmkFOOTER();
/* Return status. */
return status;
}
#endif /* gcdENABLE_VG */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,556 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#if gcdENABLE_VG
#define _GC_OBJ_ZONE gcvZONE_MMU
/*******************************************************************************
**
** gckVGMMU_Construct
**
** Construct a new gckVGMMU object.
**
** INPUT:
**
** gckVGKERNEL Kernel
** Pointer to an gckVGKERNEL object.
**
** gctSIZE_T MmuSize
** Number of bytes for the page table.
**
** OUTPUT:
**
** gckVGMMU * Mmu
** Pointer to a variable that receives the gckVGMMU object pointer.
*/
gceSTATUS gckVGMMU_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT32 MmuSize,
OUT gckVGMMU * Mmu
)
{
gckOS os;
gckVGHARDWARE hardware;
gceSTATUS status;
gckVGMMU mmu;
gctUINT32 * pageTable;
gctUINT32 i;
gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(MmuSize > 0);
gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
/* Extract the gckOS object pointer. */
os = Kernel->os;
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
/* Extract the gckVGHARDWARE object pointer. */
hardware = Kernel->hardware;
gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
/* Allocate memory for the gckVGMMU object. */
status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
if (status < 0)
{
/* Error. */
gcmkFATAL(
"%s(%d): could not allocate gckVGMMU object.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Initialize the gckVGMMU object. */
mmu->object.type = gcvOBJ_MMU;
mmu->os = os;
mmu->hardware = hardware;
/* Create the mutex. */
status = gckOS_CreateMutex(os, &mmu->mutex);
if (status < 0)
{
/* Roll back. */
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
gcmkFOOTER();
/* Error. */
return status;
}
/* Allocate the page table. */
mmu->pageTableSize = (gctUINT32)MmuSize;
status = gckOS_AllocateContiguous(os,
gcvFALSE,
&mmu->pageTableSize,
&mmu->pageTablePhysical,
&mmu->pageTableLogical);
if (status < 0)
{
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
/* Error. */
gcmkFATAL(
"%s(%d): could not allocate page table.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Compute number of entries in page table. */
mmu->entryCount = (gctUINT32)mmu->pageTableSize / sizeof(gctUINT32);
mmu->entry = 0;
/* Mark the entire page table as available. */
pageTable = (gctUINT32 *) mmu->pageTableLogical;
for (i = 0; i < mmu->entryCount; i++)
{
pageTable[i] = (gctUINT32)~0;
}
/* Set page table address. */
status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
if (status < 0)
{
/* Free the page table. */
gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os,
mmu->pageTablePhysical,
mmu->pageTableLogical,
mmu->pageTableSize));
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
/* Error. */
gcmkFATAL(
"%s(%d): could not program page table.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Return the gckVGMMU object pointer. */
*Mmu = mmu;
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): %u entries at %p.(0x%08X)\n",
__FUNCTION__, __LINE__,
mmu->entryCount,
mmu->pageTableLogical,
mmu->pageTablePhysical
);
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGMMU_Destroy
**
** Destroy a nAQMMU object.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGMMU_Destroy(
IN gckVGMMU Mmu
)
{
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
/* Free the page table. */
gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os,
Mmu->pageTablePhysical,
Mmu->pageTableLogical,
Mmu->pageTableSize));
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
/* Mark the gckVGMMU object as unknown. */
Mmu->object.type = gcvOBJ_UNKNOWN;
/* Free the gckVGMMU object. */
gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGMMU_AllocatePages
**
** Allocate pages inside the page table.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** gctSIZE_T PageCount
** Number of pages to allocate.
**
** OUTPUT:
**
** gctPOINTER * PageTable
** Pointer to a variable that receives the base address of the page
** table.
**
** gctUINT32 * Address
** Pointer to a variable that receives the hardware specific address.
*/
gceSTATUS gckVGMMU_AllocatePages(
IN gckVGMMU Mmu,
IN gctSIZE_T PageCount,
OUT gctPOINTER * PageTable,
OUT gctUINT32 * Address
)
{
gceSTATUS status;
gctUINT32 tail, index, i;
gctUINT32 * table;
gctBOOL allocated = gcvFALSE;
gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
Mmu, PageCount, PageTable, Address);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageCount > 0);
gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
gcmkVERIFY_ARGUMENT(Address != gcvNULL);
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
if (PageCount > Mmu->entryCount)
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): page table too small for %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
gcmkFOOTER_NO();
/* Not enough pages avaiable. */
return gcvSTATUS_OUT_OF_RESOURCES;
}
/* Grab the mutex. */
status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
if (status < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): could not acquire mutex.\n"
,__FUNCTION__, __LINE__
);
gcmkFOOTER();
/* Error. */
return status;
}
/* Compute the tail for this allocation. */
tail = Mmu->entryCount - (gctUINT32)PageCount;
/* Walk all entries until we find enough slots. */
for (index = Mmu->entry; index <= tail;)
{
/* Access page table. */
table = (gctUINT32 *) Mmu->pageTableLogical + index;
/* See if all slots are available. */
for (i = 0; i < PageCount; i++, table++)
{
if (*table != ~0)
{
/* Start from next slot. */
index += i + 1;
break;
}
}
if (i == PageCount)
{
/* Bail out if we have enough page entries. */
allocated = gcvTRUE;
break;
}
}
if (!allocated)
{
if (status >= 0)
{
/* Walk all entries until we find enough slots. */
for (index = 0; index <= tail;)
{
/* Access page table. */
table = (gctUINT32 *) Mmu->pageTableLogical + index;
/* See if all slots are available. */
for (i = 0; i < PageCount; i++, table++)
{
if (*table != ~0)
{
/* Start from next slot. */
index += i + 1;
break;
}
}
if (i == PageCount)
{
/* Bail out if we have enough page entries. */
allocated = gcvTRUE;
break;
}
}
}
}
if (!allocated && (status >= 0))
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): not enough free pages for %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
/* Not enough empty slots available. */
status = gcvSTATUS_OUT_OF_RESOURCES;
}
if (status >= 0)
{
/* Build virtual address. */
status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
index,
0,
Address);
if (status >= 0)
{
/* Update current entry into page table. */
Mmu->entry = index + (gctUINT32)PageCount;
/* Return pointer to page table. */
*PageTable = (gctUINT32 *) Mmu->pageTableLogical + index;
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
__FUNCTION__, __LINE__,
PageCount,
index,
*Address,
*PageTable
);
}
}
/* Release the mutex. */
gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckVGMMU_FreePages
**
** Free pages inside the page table.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** gctPOINTER PageTable
** Base address of the page table to free.
**
** gctSIZE_T PageCount
** Number of pages to free.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGMMU_FreePages(
IN gckVGMMU Mmu,
IN gctPOINTER PageTable,
IN gctSIZE_T PageCount
)
{
gctUINT32 * table;
gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
Mmu, PageTable, PageCount);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
gcmkVERIFY_ARGUMENT(PageCount > 0);
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): freeing %u pages at index %u @ %p.\n",
__FUNCTION__, __LINE__,
PageCount,
((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
PageTable
);
/* Convert pointer. */
table = (gctUINT32 *) PageTable;
/* Mark the page table entries as available. */
while (PageCount-- > 0)
{
*table++ = (gctUINT32)~0;
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
gceSTATUS
gckVGMMU_SetPage(
IN gckVGMMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
)
{
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
*PageEntry = PageAddress;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckVGMMU_Flush(
IN gckVGMMU Mmu
)
{
gckVGHARDWARE hardware;
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
hardware = Mmu->hardware;
gcmkVERIFY_OK(
gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif /* gcdENABLE_VG */

View File

@ -0,0 +1,381 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_POWER
/******************************************************************************\
************************ Dynamic Voltage Frequency Setting *********************
\******************************************************************************/
#if gcdDVFS
static gctUINT32
_GetLoadHistory(
IN gckDVFS Dvfs,
IN gctUINT32 Select,
IN gctUINT32 Index
)
{
return Dvfs->loads[Index];
}
static void
_IncreaseScale(
IN gckDVFS Dvfs,
IN gctUINT32 Load,
OUT gctUINT8 *Scale
)
{
if (Dvfs->currentScale < 32)
{
*Scale = Dvfs->currentScale + 8;
}
else
{
*Scale = Dvfs->currentScale + 8;
*Scale = gcmMIN(64, *Scale);
}
}
static void
_RecordFrequencyHistory(
gckDVFS Dvfs,
gctUINT32 Frequency
)
{
gctUINT32 i = 0;
struct _FrequencyHistory *history = Dvfs->frequencyHistory;
for (i = 0; i < 16; i++)
{
if (history->frequency == Frequency)
{
break;
}
if (history->frequency == 0)
{
history->frequency = Frequency;
break;
}
history++;
}
if (i < 16)
{
history->count++;
}
}
static gctUINT32
_GetFrequencyHistory(
gckDVFS Dvfs,
gctUINT32 Frequency
)
{
gctUINT32 i = 0;
struct _FrequencyHistory * history = Dvfs->frequencyHistory;
for (i = 0; i < 16; i++)
{
if (history->frequency == Frequency)
{
break;
}
history++;
}
if (i < 16)
{
return history->count;
}
return 0;
}
static void
_Policy(
IN gckDVFS Dvfs,
IN gctUINT32 Load,
OUT gctUINT8 *Scale
)
{
gctUINT8 load[4], nextLoad;
gctUINT8 scale;
/* Last 4 history. */
load[0] = (Load & 0xFF);
load[1] = (Load & 0xFF00) >> 8;
load[2] = (Load & 0xFF0000) >> 16;
load[3] = (Load & 0xFF000000) >> 24;
/* Determine target scale. */
if (load[0] > 54)
{
_IncreaseScale(Dvfs, Load, &scale);
}
else
{
nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
scale = Dvfs->currentScale * (nextLoad) / 54;
scale = gcmMAX(1, scale);
scale = gcmMIN(64, scale);
}
Dvfs->totalConfig++;
Dvfs->loads[(load[0]-1)/8]++;
*Scale = scale;
if (Dvfs->totalConfig % 100 == 0)
{
gcmkPRINT("=======================================================");
gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
8, 16, 24, 32, 40, 48, 56, 64);
gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
_GetLoadHistory(Dvfs,2, 0),
_GetLoadHistory(Dvfs,2, 1),
_GetLoadHistory(Dvfs,2, 2),
_GetLoadHistory(Dvfs,2, 3),
_GetLoadHistory(Dvfs,2, 4),
_GetLoadHistory(Dvfs,2, 5),
_GetLoadHistory(Dvfs,2, 6),
_GetLoadHistory(Dvfs,2, 7)
);
gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
58, 120, 240, 360, 480);
gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
_GetFrequencyHistory(Dvfs, 58),
_GetFrequencyHistory(Dvfs,120),
_GetFrequencyHistory(Dvfs,240),
_GetFrequencyHistory(Dvfs,360),
_GetFrequencyHistory(Dvfs,480)
);
}
}
static void
_TimerFunction(
gctPOINTER Data
)
{
gceSTATUS status;
gckDVFS dvfs = (gckDVFS) Data;
gckHARDWARE hardware = dvfs->hardware;
gctUINT32 value;
gctUINT32 frequency;
gctUINT8 scale;
gctUINT32 t1, t2, consumed;
gckOS_GetTicks(&t1);
gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
/* determine target sacle. */
_Policy(dvfs, value, &scale);
/* Set frequency and voltage. */
gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
/* Query real frequency. */
gcmkONERROR(
gckOS_QueryGPUFrequency(hardware->os,
hardware->core,
&frequency,
&dvfs->currentScale));
_RecordFrequencyHistory(dvfs, frequency);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
"Current frequency = %d",
frequency);
/* Set period. */
gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
OnError:
/* Determine next querying time. */
gckOS_GetTicks(&t2);
consumed = gcmMIN(((long)t2 - (long)t1), 5);
if (dvfs->stop == gcvFALSE)
{
gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
dvfs->timer,
dvfs->pollingTime - consumed));
}
return;
}
gceSTATUS
gckDVFS_Construct(
IN gckHARDWARE Hardware,
OUT gckDVFS * Dvfs
)
{
gceSTATUS status;
gctPOINTER pointer;
gckDVFS dvfs = gcvNULL;
gckOS os = Hardware->os;
gcmkHEADER_ARG("Hardware=0x%X", Hardware);
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
/* Allocate a gckDVFS manager. */
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
dvfs = pointer;
/* Initialization. */
dvfs->hardware = Hardware;
dvfs->pollingTime = gcdDVFS_POLLING_TIME;
dvfs->os = Hardware->os;
dvfs->currentScale = 64;
/* Create a polling timer. */
gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
/* Initialize frequency and voltage adjustment helper. */
gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
/* Return result. */
*Dvfs = dvfs;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Roll back. */
if (dvfs)
{
if (dvfs->timer)
{
gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
}
gcmkOS_SAFE_FREE(os, dvfs);
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckDVFS_Destroy(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
/* Deinitialize helper fuunction. */
gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
/* DestroyTimer. */
gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckDVFS_Start(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
gckHARDWARE_InitDVFS(Dvfs->hardware);
Dvfs->stop = gcvFALSE;
gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckDVFS_Stop(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
Dvfs->stop = gcvTRUE;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif

View File

@ -0,0 +1,63 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_precomp_h_
#define __gc_hal_kernel_precomp_h_
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel.h"
#endif /* __gc_hal_kernel_precomp_h_ */

View File

@ -0,0 +1,286 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
#if gcdSECURITY
/*
** Open a security service channel.
*/
gceSTATUS
gckKERNEL_SecurityOpen(
IN gckKERNEL Kernel,
IN gctUINT32 GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
return gcvSTATUS_OK;
OnError:
return status;
}
/*
** Close a security service channel
*/
gceSTATUS
gckKERNEL_SecurityClose(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
/*
** Security service interface.
*/
gceSTATUS
gckKERNEL_SecurityCallService(
IN gctUINT32 Channel,
IN OUT gcsTA_INTERFACE * Interface
)
{
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gckOS_CallSecurityService(Channel, Interface);
status = Interface->result;
gcmkONERROR(status);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityStartCommand(
IN gckKERNEL Kernel
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_START_COMMAND;
iface.u.StartCommand.gpu = Kernel->core;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityAllocateSecurityMemory(
IN gckKERNEL Kernel,
IN gctUINT32 Bytes,
OUT gctUINT32 * Handle
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
iface.u.AllocateSecurityMemory.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*Handle = iface.u.AllocateSecurityMemory.memory_handle;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityExecute(
IN gckKERNEL Kernel,
IN gctPOINTER Buffer,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
#if defined(LINUX)
gctPHYS_ADDR_T physical;
gctUINT32 address;
#endif
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_EXECUTE;
iface.u.Execute.command_buffer = (gctUINT32 *)Buffer;
iface.u.Execute.gpu = Kernel->core;
iface.u.Execute.command_buffer_length = Bytes;
#if defined(LINUX)
gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, Buffer, &physical));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Kernel->os, physical, &physical));
gcmkSAFECASTPHYSADDRT(address, physical);
iface.u.Execute.command_buffer = (gctUINT32 *)address;
#endif
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
/* Update queue tail pointer. */
gcmkONERROR(gckHARDWARE_UpdateQueueTail(
Kernel->hardware, 0, 0
));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityMapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 *PhysicalArray,
IN gctUINT32 PageCount,
OUT gctUINT32 * GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
#if defined(LINUX)
gctPHYS_ADDR_T physical;
gctUINT32 address;
#endif
gcmkHEADER();
iface.command = KERNEL_MAP_MEMORY;
#if defined(LINUX)
gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray, &physical));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Kernel->os, physical, &physical));
gcmkSAFECASTPHYSADDRT(address, physical);
iface.u.MapMemory.physicals = (gctUINT32 *)address;
#endif
iface.u.MapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*GPUAddress = iface.u.MapMemory.gpuAddress;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityUnmapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 GPUAddress,
IN gctUINT32 PageCount
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_UNMAP_MEMORY;
iface.u.UnmapMemory.gpuAddress = GPUAddress;
iface.u.UnmapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,320 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
#if gcdENABLE_TRUST_APPLICATION
/*
** Open a security service channel.
*/
gceSTATUS
gckKERNEL_SecurityOpen(
IN gckKERNEL Kernel,
IN gctUINT32 GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
return gcvSTATUS_OK;
OnError:
return status;
}
/*
** Close a security service channel
*/
gceSTATUS
gckKERNEL_SecurityClose(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
/*
** Security service interface.
*/
gceSTATUS
gckKERNEL_SecurityCallService(
IN gctUINT32 Channel,
IN OUT gcsTA_INTERFACE * Interface
)
{
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gckOS_CallSecurityService(Channel, Interface);
status = Interface->result;
gcmkONERROR(status);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityStartCommand(
IN gckKERNEL Kernel,
IN gctUINT32 Address,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_START_COMMAND;
iface.u.StartCommand.gpu = Kernel->core;
iface.u.StartCommand.address = Address;
iface.u.StartCommand.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityAllocateSecurityMemory(
IN gckKERNEL Kernel,
IN gctUINT32 Bytes,
OUT gctUINT32 * Handle
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
iface.u.AllocateSecurityMemory.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*Handle = iface.u.AllocateSecurityMemory.memory_handle;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityMapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 *PhysicalArray,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 PageCount,
OUT gctUINT32 * GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_MAP_MEMORY;
iface.u.MapMemory.physicals = PhysicalArray;
iface.u.MapMemory.physical = Physical;
iface.u.MapMemory.pageCount = PageCount;
iface.u.MapMemory.gpuAddress = *GPUAddress;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityDumpMMUException(
IN gckKERNEL Kernel
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_DUMP_MMU_EXCEPTION;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityUnmapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 GPUAddress,
IN gctUINT32 PageCount
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_UNMAP_MEMORY;
iface.u.UnmapMemory.gpuAddress = GPUAddress;
iface.u.UnmapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_ReadMMUException(
IN gckKERNEL Kernel,
IN gctUINT32_PTR MMUStatus,
IN gctUINT32_PTR MMUException
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_READ_MMU_EXCEPTION;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*MMUStatus = iface.u.ReadMMUException.mmuStatus;
*MMUException = iface.u.ReadMMUException.mmuException;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_HandleMMUException(
IN gckKERNEL Kernel,
IN gctUINT32 MMUStatus,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_HANDLE_MMU_EXCEPTION;
iface.u.HandleMMUException.mmuStatus = MMUStatus;
iface.u.HandleMMUException.physical = Physical;
iface.u.HandleMMUException.gpuAddress = GPUAddress;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,644 @@
/****************************************************************************
*
* 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_kernel_precomp.h"
#if gcdENABLE_VG
#define _GC_OBJ_ZONE gcvZONE_VG
/******************************************************************************\
******************************* gckKERNEL API Code ******************************
\******************************************************************************/
/*******************************************************************************
**
** gckKERNEL_Construct
**
** Construct a new gckKERNEL object.
**
** INPUT:
**
** gckOS Os
** Pointer to an gckOS object.
**
** IN gctPOINTER Context
** Pointer to a driver defined context.
**
** OUTPUT:
**
** gckKERNEL * Kernel
** Pointer to a variable that will hold the pointer to the gckKERNEL
** object.
*/
gceSTATUS gckVGKERNEL_Construct(
IN gckOS Os,
IN gctPOINTER Context,
IN gckKERNEL inKernel,
OUT gckVGKERNEL * Kernel
)
{
gceSTATUS status;
gckVGKERNEL kernel = gcvNULL;
gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
do
{
/* Allocate the gckKERNEL object. */
gcmkERR_BREAK(gckOS_Allocate(
Os,
sizeof(struct _gckVGKERNEL),
(gctPOINTER *) &kernel
));
/* Initialize the gckKERNEL object. */
kernel->object.type = gcvOBJ_KERNEL;
kernel->os = Os;
kernel->context = Context;
kernel->hardware = gcvNULL;
kernel->interrupt = gcvNULL;
kernel->command = gcvNULL;
kernel->mmu = gcvNULL;
kernel->kernel = inKernel;
/* Construct the gckVGHARDWARE object. */
gcmkERR_BREAK(gckVGHARDWARE_Construct(
Os, &kernel->hardware
));
/* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
kernel->hardware->kernel = kernel;
/* Construct the gckVGINTERRUPT object. */
gcmkERR_BREAK(gckVGINTERRUPT_Construct(
kernel, &kernel->interrupt
));
/* Construct the gckVGCOMMAND object. */
gcmkERR_BREAK(gckVGCOMMAND_Construct(
kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
));
/* Construct the gckVGMMU object. */
gcmkERR_BREAK(gckVGMMU_Construct(
kernel, gcmKB2BYTES(gcdGC355_VGMMU_MEMORY_SIZE_KB), &kernel->mmu
));
/* Return pointer to the gckKERNEL object. */
*Kernel = kernel;
gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (kernel != gcvNULL)
{
if (kernel->mmu != gcvNULL)
{
gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
}
if (kernel->command != gcvNULL)
{
gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
}
if (kernel->interrupt != gcvNULL)
{
gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
}
if (kernel->hardware != gcvNULL)
{
gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
}
gcmkVERIFY_OK(gckOS_Free(Os, kernel));
}
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckKERNEL_Destroy
**
** Destroy an gckKERNEL object.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGKERNEL_Destroy(
IN gckVGKERNEL Kernel
)
{
gceSTATUS status;
gcmkHEADER_ARG("Kernel=0x%x", Kernel);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
do
{
/* Destroy the gckVGMMU object. */
if (Kernel->mmu != gcvNULL)
{
gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
Kernel->mmu = gcvNULL;
}
/* Destroy the gckVGCOMMAND object. */
if (Kernel->command != gcvNULL)
{
gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
Kernel->command = gcvNULL;
}
/* Destroy the gckVGINTERRUPT object. */
if (Kernel->interrupt != gcvNULL)
{
gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
Kernel->interrupt = gcvNULL;
}
/* Destroy the gckVGHARDWARE object. */
if (Kernel->hardware != gcvNULL)
{
gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
Kernel->hardware = gcvNULL;
}
/* Mark the gckKERNEL object as unknown. */
Kernel->object.type = gcvOBJ_UNKNOWN;
/* Free the gckKERNEL object. */
gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
}
while (gcvFALSE);
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckKERNEL_Dispatch
**
** Dispatch a command received from the user HAL layer.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gcsHAL_INTERFACE * Interface
** Pointer to a gcsHAL_INTERFACE structure that defines the command to
** be dispatched.
**
** OUTPUT:
**
** gcsHAL_INTERFACE * Interface
** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
** returned.
*/
gceSTATUS gckVGKERNEL_Dispatch(
IN gckKERNEL Kernel,
IN gctBOOL FromUser,
IN OUT gcsHAL_INTERFACE * Interface
)
{
gceSTATUS status;
gcsHAL_INTERFACE * kernelInterface = Interface;
gctUINT32 processID;
gckKERNEL kernel = Kernel;
gctPHYS_ADDR physical = gcvNULL;
gctPOINTER logical = gcvNULL;
gctSIZE_T bytes = 0;
gctBOOL powerMutexAcquired = gcvFALSE;
gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gcmkONERROR(gckOS_GetProcessID(&processID));
/* Dispatch on command. */
switch (Interface->command)
{
case gcvHAL_QUERY_CHIP_IDENTITY:
/* Query chip identity. */
gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
Kernel->vg->hardware,
&kernelInterface->u.QueryChipIdentity.chipModel,
&kernelInterface->u.QueryChipIdentity.chipRevision,
&kernelInterface->u.QueryChipIdentity.productID,
&kernelInterface->u.QueryChipIdentity.ecoID,
&kernelInterface->u.QueryChipIdentity.customerID,
&kernelInterface->u.QueryChipIdentity.chipFeatures,
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
));
break;
case gcvHAL_QUERY_COMMAND_BUFFER:
/* Query command buffer information. */
gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
Kernel,
&kernelInterface->u.QueryCommandBuffer.information
));
break;
case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
/* Allocate non-paged memory. */
gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
Kernel->os,
gcvTRUE,
gcvALLOC_FLAG_CONTIGUOUS,
&bytes,
&physical,
&logical
));
kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
break;
case gcvHAL_FREE_NON_PAGED_MEMORY:
physical = gcmNAME_TO_PTR(kernelInterface->u.FreeNonPagedMemory.physical);
/* Unmap user logical out of physical memory first. */
gcmkERR_BREAK(gckOS_UnmapUserLogical(
Kernel->os,
physical,
(gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)));
/* Free non-paged memory. */
gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
Kernel->os,
(gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
physical,
gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
));
gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical);
break;
case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes;
/* Allocate contiguous memory. */
gcmkERR_BREAK(gckOS_AllocateContiguous(
Kernel->os,
gcvTRUE,
&bytes,
&physical,
&logical
));
kernelInterface->u.AllocateContiguousMemory.bytes = bytes;
kernelInterface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical);
kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
break;
case gcvHAL_FREE_CONTIGUOUS_MEMORY:
physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical);
/* Unmap user logical out of physical memory first. */
gcmkERR_BREAK(gckOS_UnmapUserLogical(
Kernel->os,
physical,
(gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes,
gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical)
));
/* Free contiguous memory. */
gcmkERR_BREAK(gckOS_FreeContiguous(
Kernel->os,
physical,
gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical),
(gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes
));
gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical);
break;
case gcvHAL_ALLOCATE_VIDEO_MEMORY:
gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
break;
case gcvHAL_MAP_MEMORY:
/* Map memory. */
gcmkERR_BREAK(gckKERNEL_MapMemory(
Kernel,
gcmINT2PTR(kernelInterface->u.MapMemory.physical),
(gctSIZE_T) kernelInterface->u.MapMemory.bytes,
&logical
));
kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
break;
case gcvHAL_UNMAP_MEMORY:
/* Unmap memory. */
gcmkERR_BREAK(gckKERNEL_UnmapMemory(
Kernel,
gcmINT2PTR(kernelInterface->u.MapMemory.physical),
(gctSIZE_T) kernelInterface->u.MapMemory.bytes,
gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical),
processID
));
break;
case gcvHAL_MAP_USER_MEMORY:
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
break;
case gcvHAL_UNMAP_USER_MEMORY:
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
break;
case gcvHAL_LOCK_VIDEO_MEMORY:
gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
break;
case gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY:
gcmkERR_BREAK(gckKERNEL_BottomHalfUnlockVideoMemory(Kernel, processID,
kernelInterface->u.BottomHalfUnlockVideoMemory.node));
break;
case gcvHAL_USER_SIGNAL:
#if !USE_NEW_LINUX_SIGNAL
/* Dispatch depends on the user signal subcommands. */
switch(Interface->u.UserSignal.command)
{
case gcvUSER_SIGNAL_CREATE:
/* Create a signal used in the user space. */
gcmkERR_BREAK(
gckOS_CreateUserSignal(Kernel->os,
Interface->u.UserSignal.manualReset,
&Interface->u.UserSignal.id));
gcmkVERIFY_OK(
gckKERNEL_AddProcessDB(Kernel,
processID, gcvDB_SIGNAL,
gcmINT2PTR(Interface->u.UserSignal.id),
gcvNULL,
0));
break;
case gcvUSER_SIGNAL_DESTROY:
gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
Kernel,
processID, gcvDB_SIGNAL,
gcmINT2PTR(Interface->u.UserSignal.id)));
/* Destroy the signal. */
gcmkERR_BREAK(
gckOS_DestroyUserSignal(Kernel->os,
Interface->u.UserSignal.id));
break;
case gcvUSER_SIGNAL_SIGNAL:
/* Signal the signal. */
gcmkERR_BREAK(
gckOS_SignalUserSignal(Kernel->os,
Interface->u.UserSignal.id,
Interface->u.UserSignal.state));
break;
case gcvUSER_SIGNAL_WAIT:
/* Wait on the signal. */
status = gckOS_WaitUserSignal(Kernel->os,
Interface->u.UserSignal.id,
Interface->u.UserSignal.wait);
break;
default:
/* Invalid user signal command. */
gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
}
#endif
break;
case gcvHAL_COMMIT:
/* Commit a command and context buffer. */
gcmkERR_BREAK(gckVGCOMMAND_Commit(
Kernel->vg->command,
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
kernelInterface->u.VGCommit.entryCount,
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
));
break;
case gcvHAL_GET_BASE_ADDRESS:
/* Get base address. */
gcmkONERROR(
gckOS_GetBaseAddress(Kernel->os,
&Interface->u.GetBaseAddress.baseAddress));
break;
case gcvHAL_EVENT_COMMIT:
gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
break;
case gcvHAL_READ_REGISTER:
#if gcdREGISTER_ACCESS_FROM_USER
{
gceCHIPPOWERSTATE power;
gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE));
powerMutexAcquired = gcvTRUE;
gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware,
&power));
if (power == gcvPOWER_ON)
{
/* Read a register. */
gcmkONERROR(gckOS_ReadRegisterEx(
Kernel->os,
Kernel->core,
Interface->u.ReadRegisterData.address,
&Interface->u.ReadRegisterData.data));
}
else
{
/* Chip is in power-state. */
Interface->u.ReadRegisterData.data = 0;
status = gcvSTATUS_CHIP_NOT_READY;
}
gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
powerMutexAcquired = gcvFALSE;
}
#else
/* No access from user land to read registers. */
Interface->u.ReadRegisterData.data = 0;
status = gcvSTATUS_NOT_SUPPORTED;
#endif
break;
case gcvHAL_WRITE_REGISTER:
#if gcdREGISTER_ACCESS_FROM_USER
{
gceCHIPPOWERSTATE power;
gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE));
powerMutexAcquired = gcvTRUE;
gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware,
&power));
if (power == gcvPOWER_ON)
{
/* Write a register. */
gcmkONERROR(
gckOS_WriteRegisterEx(Kernel->os,
Kernel->core,
Interface->u.WriteRegisterData.address,
Interface->u.WriteRegisterData.data));
}
else
{
/* Chip is in power-state. */
Interface->u.WriteRegisterData.data = 0;
status = gcvSTATUS_CHIP_NOT_READY;
}
gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
powerMutexAcquired = gcvFALSE;
}
#else
/* No access from user land to write registers. */
status = gcvSTATUS_NOT_SUPPORTED;
#endif
break;
default:
/* Invalid command, try gckKERNEL_Dispatch */
status = gckKERNEL_Dispatch(Kernel, gcvNULL, gcvTRUE, Interface);
}
OnError:
/* Save status. */
kernelInterface->status = status;
if (powerMutexAcquired == gcvTRUE)
{
gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
}
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckKERNEL_QueryCommandBuffer
**
** Query command buffer attributes.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckVGHARDWARE object.
**
** OUTPUT:
**
** gcsCOMMAND_BUFFER_INFO_PTR Information
** Pointer to the information structure to receive buffer attributes.
*/
gceSTATUS
gckKERNEL_QueryCommandBuffer(
IN gckKERNEL Kernel,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
)
{
gceSTATUS status;
gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
Kernel, Information);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
/* Get the information. */
status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
gcmkFOOTER();
/* Return status. */
return status;
}
#endif /* gcdENABLE_VG */

View File

@ -0,0 +1,119 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_vg_h_
#define __gc_hal_kernel_vg_h_
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel_hardware.h"
/******************************************************************************\
********************************** Structures **********************************
\******************************************************************************/
/* gckKERNEL object. */
struct _gckVGKERNEL
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckVGHARDWARE hardware;
/* Pointer to gckINTERRUPT object. */
gckVGINTERRUPT interrupt;
/* Pointer to gckCOMMAND object. */
gckVGCOMMAND command;
/* Pointer to context. */
gctPOINTER context;
/* Pointer to gckMMU object. */
gckVGMMU mmu;
gckKERNEL kernel;
};
/* gckMMU object. */
struct _gckVGMMU
{
/* The object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckVGHARDWARE hardware;
/* The page table mutex. */
gctPOINTER mutex;
/* Page table information. */
gctSIZE_T pageTableSize;
gctPHYS_ADDR pageTablePhysical;
gctPOINTER pageTableLogical;
/* Allocation index. */
gctUINT32 entryCount;
gctUINT32 entry;
};
#endif /* __gc_hal_kernel_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,302 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_driver_vg_h_
#define __gc_hal_driver_vg_h_
#include "gc_hal_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
******************************* I/O Control Codes ******************************
\******************************************************************************/
#define gcvHAL_CLASS "galcore"
#define IOCTL_GCHAL_INTERFACE 30000
/******************************************************************************\
********************* Command buffer information structure. ********************
\******************************************************************************/
typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
typedef struct _gcsCOMMAND_BUFFER_INFO
{
/* FE command buffer interrupt ID. */
gctINT32 feBufferInt;
/* TS overflow interrupt ID. */
gctINT32 tsOverflowInt;
/* Alignment and mask for the buffer address. */
gctUINT addressMask;
gctUINT32 addressAlignment;
/* Alignment for each command. */
gctUINT32 commandAlignment;
/* Number of bytes required by the STATE command. */
gctUINT32 stateCommandSize;
/* Number of bytes required by the RESTART command. */
gctUINT32 restartCommandSize;
/* Number of bytes required by the FETCH command. */
gctUINT32 fetchCommandSize;
/* Number of bytes required by the CALL command. */
gctUINT32 callCommandSize;
/* Number of bytes required by the RETURN command. */
gctUINT32 returnCommandSize;
/* Number of bytes required by the EVENT command. */
gctUINT32 eventCommandSize;
/* Number of bytes required by the END command. */
gctUINT32 endCommandSize;
/* Number of bytes reserved at the tail of a static command buffer. */
gctUINT32 staticTailSize;
/* Number of bytes reserved at the tail of a dynamic command buffer. */
gctUINT32 dynamicTailSize;
}
gcsCOMMAND_BUFFER_INFO;
/******************************************************************************\
******************************** Task Structures *******************************
\******************************************************************************/
typedef enum _gceTASK
{
gcvTASK_LINK,
gcvTASK_CLUSTER,
gcvTASK_INCREMENT,
gcvTASK_DECREMENT,
gcvTASK_SIGNAL,
gcvTASK_LOCKDOWN,
gcvTASK_UNLOCK_VIDEO_MEMORY,
gcvTASK_FREE_VIDEO_MEMORY,
gcvTASK_FREE_CONTIGUOUS_MEMORY,
gcvTASK_UNMAP_USER_MEMORY
}
gceTASK;
typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
typedef struct _gcsTASK_HEADER
{
/* Task ID. */
IN gceTASK id;
}
gcsTASK_HEADER;
typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
typedef struct _gcsTASK_LINK
{
/* Task ID (gcvTASK_LINK). */
IN gceTASK id;
/* Pointer to the next task container. */
IN gctPOINTER cotainer;
/* Pointer to the next task from the next task container. */
IN gcsTASK_HEADER_PTR task;
}
gcsTASK_LINK;
typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
typedef struct _gcsTASK_CLUSTER
{
/* Task ID (gcvTASK_CLUSTER). */
IN gceTASK id;
/* Number of tasks in the cluster. */
IN gctUINT taskCount;
}
gcsTASK_CLUSTER;
typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
typedef struct _gcsTASK_INCREMENT
{
/* Task ID (gcvTASK_INCREMENT). */
IN gceTASK id;
/* Address of the variable to increment. */
IN gctUINT32 address;
}
gcsTASK_INCREMENT;
typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
typedef struct _gcsTASK_DECREMENT
{
/* Task ID (gcvTASK_DECREMENT). */
IN gceTASK id;
/* Address of the variable to decrement. */
IN gctUINT32 address;
}
gcsTASK_DECREMENT;
typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
typedef struct _gcsTASK_SIGNAL
{
/* Task ID (gcvTASK_SIGNAL). */
IN gceTASK id;
/* Process owning the signal. */
IN gctHANDLE process;
/* Signal handle to signal. */
IN gctSIGNAL signal;
#if defined(__QNXNTO__)
IN gctINT32 coid;
IN gctINT32 rcvid;
#endif
}
gcsTASK_SIGNAL;
typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
typedef struct _gcsTASK_LOCKDOWN
{
/* Task ID (gcvTASK_LOCKDOWN). */
IN gceTASK id;
/* Address of the user space counter. */
IN gctUINT32 userCounter;
/* Address of the kernel space counter. */
IN gctUINT32 kernelCounter;
/* Process owning the signal. */
IN gctHANDLE process;
/* Signal handle to signal. */
IN gctSIGNAL signal;
}
gcsTASK_LOCKDOWN;
typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
{
/* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
IN gceTASK id;
/* Allocated video memory. */
IN gctUINT64 node;
}
gcsTASK_UNLOCK_VIDEO_MEMORY;
typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
typedef struct _gcsTASK_FREE_VIDEO_MEMORY
{
/* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
IN gceTASK id;
/* Allocated video memory. */
IN gctUINT32 node;
}
gcsTASK_FREE_VIDEO_MEMORY;
typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
{
/* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
IN gceTASK id;
/* Number of bytes allocated. */
IN gctSIZE_T bytes;
/* Physical address of allocation. */
IN gctPHYS_ADDR physical;
/* Logical address of allocation. */
IN gctPOINTER logical;
}
gcsTASK_FREE_CONTIGUOUS_MEMORY;
typedef struct _gcsTASK_UNMAP_USER_MEMORY * gcsTASK_UNMAP_USER_MEMORY_PTR;
typedef struct _gcsTASK_UNMAP_USER_MEMORY
{
/* Task ID (gcvTASK_UNMAP_USER_MEMORY). */
IN gceTASK id;
/* Base address of user memory to unmap. */
IN gctPOINTER memory;
/* Size of user memory in bytes to unmap. */
IN gctSIZE_T size;
/* Info record returned by gcvHAL_MAP_USER_MEMORY. */
IN gctPOINTER info;
/* Physical address of mapped memory as returned by
gcvHAL_MAP_USER_MEMORY. */
IN gctUINT32 address;
}
gcsTASK_UNMAP_USER_MEMORY;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_driver_h_ */

View File

@ -0,0 +1,200 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __VIVNATE_DRM_H__
#define __VIVNATE_DRM_H__
#if !defined(__KERNEL__)
#include <drm.h>
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/* creation flag bits. */
#define DRM_VIV_GEM_CONTIGUOUS (1u << 0)
#define DRM_VIV_GEM_CACHED (1u << 1)
#define DRM_VIV_GEM_SECURE (1u << 2)
#define DRM_VIV_GEM_CMA_LIMIT (1u << 3)
#define DRM_VIV_GEM_VIRTUAL_POOL (1u << 4)
struct drm_viv_gem_create {
__u64 size;
__u32 flags;
__u32 handle;
};
struct drm_viv_gem_lock {
__u32 handle;
__u32 cacheable;
__u64 logical;
};
struct drm_viv_gem_unlock {
__u32 handle;
};
#define DRM_VIV_GEM_CLEAN_CACHE 0x01
#define DRM_VIV_GEM_INVALIDATE_CACHE 0x02
#define DRM_VIV_GEM_FLUSH_CACHE 0x03
#define DRM_VIV_GEM_MEMORY_BARRIER 0x04
struct drm_viv_gem_cache {
__u32 handle;
__u32 op;
__u64 logical;
__u64 bytes;
};
#define DRM_VIV_GEM_PARAM_POOL 0x00
#define DRM_VIV_GEM_PARAM_SIZE 0x01
struct drm_viv_gem_query {
__u32 handle;
__u32 param;
__u64 value;
};
struct drm_viv_gem_timestamp {
__u32 handle;
/* inc count, 0 for query current. */
__u32 inc;
/* output inc'ed timestamp. */
__u64 timestamp;
};
/* basic tiling mode. */
#define DRM_VIV_GEM_TILING_LINEAR 0x01
#define DRM_VIV_GEM_TILING_TILED 0x02
#define DRM_VIV_GEM_TILING_SUPERTILED 0x04
#define DRM_VIV_GEM_TILING_MINORTILED 0x08
/* tiling mode modifiers. */
#define DRM_VIV_GEM_TILING_SPLIT 0x10
#define DRM_VIV_GEM_TILING_X_MAJOR 0x20
#define DRM_VIV_GEM_TILING_Y_MAJOR 0x40
#define DRM_VIV_GEM_TILING_SWAP 0x80
/* ts mode. */
#define DRM_VIV_GEM_TS_NONE 0x00
#define DRM_VIV_GEM_TS_DISABLED 0x01
#define DRM_VIV_GEM_TS_NORMAL 0x02
#define DRM_VIV_GEM_TS_COMPRESSED 0x03
struct drm_viv_gem_set_tiling {
__u32 handle;
__u32 tiling_mode;
__u32 ts_mode;
__u64 clear_value;
};
struct drm_viv_gem_get_tiling {
__u32 handle;
__u32 tiling_mode;
__u32 ts_mode;
__u64 clear_value;
};
struct drm_viv_gem_attach_aux {
__u32 handle;
__u32 ts_handle;
};
struct drm_viv_gem_ref_node {
__u32 handle;
/* output. */
__u32 node;
__u32 ts_node;
};
#define DRM_VIV_GEM_CREATE 0x00
#define DRM_VIV_GEM_LOCK 0x01
#define DRM_VIV_GEM_UNLOCK 0x02
#define DRM_VIV_GEM_CACHE 0x03
#define DRM_VIV_GEM_QUERY 0x04
#define DRM_VIV_GEM_TIMESTAMP 0x05
#define DRM_VIV_GEM_SET_TILING 0x06
#define DRM_VIV_GEM_GET_TILING 0x07
#define DRM_VIV_GEM_ATTACH_AUX 0x08
#define DRM_VIV_GEM_REF_NODE 0x09
#define DRM_VIV_NUM_IOCTLS 0x0A
#define DRM_IOCTL_VIV_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CREATE, struct drm_viv_gem_create)
#define DRM_IOCTL_VIV_GEM_LOCK DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_LOCK, struct drm_viv_gem_lock)
#define DRM_IOCTL_VIV_GEM_UNLOCK DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_UNLOCK, struct drm_viv_gem_unlock)
#define DRM_IOCTL_VIV_GEM_CACHE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CACHE, struct drm_viv_gem_cache)
#define DRM_IOCTL_VIV_GEM_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_QUERY, struct drm_viv_gem_query)
#define DRM_IOCTL_VIV_GEM_TIMESTAMP DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_TIMESTAMP, struct drm_viv_gem_timestamp)
#define DRM_IOCTL_VIV_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_SET_TILING, struct drm_viv_gem_set_tiling)
#define DRM_IOCTL_VIV_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_GET_TILING, struct drm_viv_gem_get_tiling)
#define DRM_IOCTL_VIV_GEM_ATTACH_AUX DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_ATTACH_AUX, struct drm_viv_gem_attach_aux)
#define DRM_IOCTL_VIV_GEM_REF_NODE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_REF_NODE, struct drm_viv_gem_ref_node)
#if defined(__cplusplus)
}
#endif
#endif /* __VIVNATE_DRM_H__ */

View File

@ -0,0 +1,125 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_dump_h_
#define __gc_hal_dump_h_
#ifdef __cplusplus
extern "C" {
#endif
/*
** FILE LAYOUT:
**
** gcsDUMP_FILE structure
**
** gcsDUMP_DATA frame
** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
** gctUINT8 data[length]
*/
#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
typedef struct _gcsDUMP_FILE
{
gctUINT32 signature; /* File signature */
gctSIZE_T length; /* Length of file */
gctUINT32 frames; /* Number of frames in file */
}
gcsDUMP_FILE;
typedef enum _gceDUMP_TAG
{
gcvTAG_SURFACE = gcmCC('s','u','r','f'),
gcvTAG_FRAME = gcmCC('f','r','m',' '),
gcvTAG_COMMAND = gcmCC('c','m','d',' '),
gcvTAG_INDEX = gcmCC('i','n','d','x'),
gcvTAG_STREAM = gcmCC('s','t','r','m'),
gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
gcvTAG_DEPTH = gcmCC('z','b','u','f'),
gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
gcvTAG_DELETE = gcmCC('d','e','l',' '),
gcvTAG_BUFOBJ = gcmCC('b','u','f','o'),
}
gceDUMP_TAG;
typedef struct _gcsDUMP_SURFACE
{
gceDUMP_TAG type; /* Type of record. */
gctUINT32 address; /* Address of the surface. */
gctINT16 width; /* Width of surface. */
gctINT16 height; /* Height of surface. */
gceSURF_FORMAT format; /* Surface pixel format. */
gctSIZE_T length; /* Number of bytes inside the surface. */
}
gcsDUMP_SURFACE;
typedef struct _gcsDUMP_DATA
{
gceDUMP_TAG type; /* Type of record. */
gctSIZE_T length; /* Number of bytes of data. */
gctUINT32 address; /* Address for the data. */
}
gcsDUMP_DATA;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_dump_h_ */

View File

@ -0,0 +1,589 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_eglplatform_h_
#define __gc_hal_eglplatform_h_
#include "gc_hal_types.h"
#include "gc_hal_base.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#ifndef WIN32_LEAN_AND_MEAN
/* #define WIN32_LEAN_AND_MEAN 1 */
#endif
#include <windows.h>
typedef HDC HALNativeDisplayType;
typedef HWND HALNativeWindowType;
typedef HBITMAP HALNativePixmapType;
typedef struct __BITFIELDINFO
{
BITMAPINFO bmi;
RGBQUAD bmiColors[2];
}
BITFIELDINFO;
#elif /* defined(__APPLE__) || */ defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
#elif defined(WL_EGL_PLATFORM) || defined(EGL_API_WL) /* Wayland */
#elif defined(__GBM__) /* GBM */
#elif defined(__ANDROID__) || defined(ANDROID)
#elif defined(MIR_EGL_PLATFORM) /* Mir */
#elif defined(__QNXNTO__)
#elif defined(__unix__) || defined(__APPLE__)
#if defined(EGL_API_DFB)
#elif defined(EGL_API_FB)
#elif defined(EGL_API_NULLWS)
#else
/* X11 (tetative). */
#endif
#else
#error "Platform not recognized"
#endif
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#include "gc_hal_eglplatform_type.h"
/*******************************************************************************
** Display. ********************************************************************
*/
gceSTATUS
gcoOS_GetDisplay(
OUT HALNativeDisplayType * Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_GetDisplayByIndex(
IN gctINT DisplayIndex,
OUT HALNativeDisplayType * Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_GetDisplayInfo(
IN HALNativeDisplayType Display,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctSIZE_T * Physical,
OUT gctINT * Stride,
OUT gctINT * BitsPerPixel
);
gceSTATUS
gcoOS_GetDisplayInfoEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctUINT DisplayInfoSize,
OUT halDISPLAY_INFO * DisplayInfo
);
gceSTATUS
gcoOS_GetDisplayVirtual(
IN HALNativeDisplayType Display,
OUT gctINT * Width,
OUT gctINT * Height
);
gceSTATUS
gcoOS_GetDisplayBackbuffer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctPOINTER * context,
OUT gcoSURF * surface,
OUT gctUINT * Offset,
OUT gctINT * X,
OUT gctINT * Y
);
gceSTATUS
gcoOS_SetDisplayVirtual(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_SetDisplayVirtualEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER Context,
IN gcoSURF Surface,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_CancelDisplayBackbuffer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER Context,
IN gcoSURF Surface,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_SetSwapInterval(
IN HALNativeDisplayType Display,
IN gctINT Interval
);
gceSTATUS
gcoOS_SetSwapIntervalEx(
IN HALNativeDisplayType Display,
IN gctINT Interval,
IN gctPOINTER localDisplay);
gceSTATUS
gcoOS_GetSwapInterval(
IN HALNativeDisplayType Display,
IN gctINT_PTR Min,
IN gctINT_PTR Max
);
gceSTATUS
gcoOS_DisplayBufferRegions(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT NumRects,
IN gctINT_PTR Rects
);
gceSTATUS
gcoOS_DestroyDisplay(
IN HALNativeDisplayType Display
);
gceSTATUS
gcoOS_InitLocalDisplayInfo(
IN HALNativeDisplayType Display,
IN OUT gctPOINTER * localDisplay
);
gceSTATUS
gcoOS_DeinitLocalDisplayInfo(
IN HALNativeDisplayType Display,
IN OUT gctPOINTER * localDisplay
);
gceSTATUS
gcoOS_GetDisplayInfoEx2(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER localDisplay,
IN gctUINT DisplayInfoSize,
OUT halDISPLAY_INFO * DisplayInfo
);
gceSTATUS
gcoOS_GetDisplayBackbufferEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER localDisplay,
OUT gctPOINTER * context,
OUT gcoSURF * surface,
OUT gctUINT * Offset,
OUT gctINT * X,
OUT gctINT * Y
);
gceSTATUS
gcoOS_IsValidDisplay(
IN HALNativeDisplayType Display
);
gceSTATUS
gcoOS_GetNativeVisualId(
IN HALNativeDisplayType Display,
OUT gctINT* nativeVisualId
);
gctBOOL
gcoOS_SynchronousFlip(
IN HALNativeDisplayType Display
);
/*******************************************************************************
** Windows. ********************************************************************
*/
gceSTATUS
gcoOS_CreateWindow(
IN HALNativeDisplayType Display,
IN gctINT X,
IN gctINT Y,
IN gctINT Width,
IN gctINT Height,
OUT HALNativeWindowType * Window
);
gceSTATUS
gcoOS_GetWindowInfo(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctINT * X,
OUT gctINT * Y,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctUINT * Offset
);
gceSTATUS
gcoOS_DestroyWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_DrawImage(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits
);
gceSTATUS
gcoOS_GetImage(
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
OUT gctINT * BitsPerPixel,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_GetWindowInfoEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctINT * X,
OUT gctINT * Y,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctUINT * Offset,
OUT gceSURF_FORMAT * Format,
OUT gceSURF_TYPE * Type
);
gceSTATUS
gcoOS_DrawImageEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits,
IN gceSURF_FORMAT Format
);
/*
* Possiable types:
* gcvSURF_BITMAP
* gcvSURF_RENDER_TARGET
* gcvSURF_RENDER_TARGET_NO_COMPRESSION
* gcvSURF_RENDER_TARGET_NO_TILE_STATUS
*/
gceSTATUS
gcoOS_SetWindowFormat(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gceSURF_TYPE Type,
IN gceSURF_FORMAT Format
);
/*******************************************************************************
** Pixmaps. ********************************************************************
*/
gceSTATUS
gcoOS_CreatePixmap(
IN HALNativeDisplayType Display,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
OUT HALNativePixmapType * Pixmap
);
gceSTATUS
gcoOS_GetPixmapInfo(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctINT * Stride,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_DrawPixmap(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits
);
gceSTATUS
gcoOS_DestroyPixmap(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap
);
gceSTATUS
gcoOS_GetPixmapInfoEx(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctINT * Stride,
OUT gctPOINTER * Bits,
OUT gceSURF_FORMAT * Format
);
gceSTATUS
gcoOS_CopyPixmapBits(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
IN gctUINT DstWidth,
IN gctUINT DstHeight,
IN gctINT DstStride,
IN gceSURF_FORMAT DstFormat,
OUT gctPOINTER DstBits
);
/*******************************************************************************
** OS relative. ****************************************************************
*/
gceSTATUS
gcoOS_LoadEGLLibrary(
OUT gctHANDLE * Handle
);
gceSTATUS
gcoOS_FreeEGLLibrary(
IN gctHANDLE Handle
);
gceSTATUS
gcoOS_ShowWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_HideWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_SetWindowTitle(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctCONST_STRING Title
);
gceSTATUS
gcoOS_CapturePointer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_GetEvent(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT halEvent * Event
);
gceSTATUS
gcoOS_CreateClientBuffer(
IN gctINT Width,
IN gctINT Height,
IN gctINT Format,
IN gctINT Type,
OUT gctPOINTER * ClientBuffer
);
gceSTATUS
gcoOS_GetClientBufferInfo(
IN gctPOINTER ClientBuffer,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * Stride,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_DestroyClientBuffer(
IN gctPOINTER ClientBuffer
);
gceSTATUS
gcoOS_DestroyContext(
IN gctPOINTER Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_CreateContext(
IN gctPOINTER LocalDisplay,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_MakeCurrent(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType DrawDrawable,
IN HALNativeWindowType ReadDrawable,
IN gctPOINTER Context,
IN gcoSURF ResolveTarget
);
gceSTATUS
gcoOS_CreateDrawable(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable
);
gceSTATUS
gcoOS_DestroyDrawable(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable
);
gceSTATUS
gcoOS_SwapBuffers(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable,
IN gcoSURF RenderTarget,
IN gcoSURF ResolveTarget,
IN gctPOINTER ResolveBits,
OUT gctUINT *Width,
OUT gctUINT *Height
);
gceSTATUS
gcoOS_ResizeWindow(
IN gctPOINTER localDisplay,
IN HALNativeWindowType Drawable,
IN gctUINT Width,
IN gctUINT Height
);
gceSTATUS
gcoOS_RSForSwap(
IN gctPOINTER localDisplay,
IN HALNativeWindowType Drawable,
IN gctPOINTER resolve
);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_eglplatform_h_ */

View File

@ -0,0 +1,326 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_eglplatform_type_h_
#define __gc_hal_eglplatform_type_h_
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
** Events. *********************************************************************
*/
typedef enum _halEventType
{
/* Keyboard event. */
HAL_KEYBOARD,
/* Mouse move event. */
HAL_POINTER,
/* Mouse button event. */
HAL_BUTTON,
/* Application close event. */
HAL_CLOSE,
/* Application window has been updated. */
HAL_WINDOW_UPDATE
}
halEventType;
/* Scancodes for keyboard. */
typedef enum _halKeys
{
HAL_UNKNOWN = -1,
HAL_BACKSPACE = 0x08,
HAL_TAB,
HAL_ENTER = 0x0D,
HAL_ESCAPE = 0x1B,
HAL_SPACE = 0x20,
HAL_SINGLEQUOTE = 0x27,
HAL_PAD_ASTERISK = 0x2A,
HAL_COMMA = 0x2C,
HAL_HYPHEN,
HAL_PERIOD,
HAL_SLASH,
HAL_0,
HAL_1,
HAL_2,
HAL_3,
HAL_4,
HAL_5,
HAL_6,
HAL_7,
HAL_8,
HAL_9,
HAL_SEMICOLON = 0x3B,
HAL_EQUAL = 0x3D,
HAL_A = 0x41,
HAL_B,
HAL_C,
HAL_D,
HAL_E,
HAL_F,
HAL_G,
HAL_H,
HAL_I,
HAL_J,
HAL_K,
HAL_L,
HAL_M,
HAL_N,
HAL_O,
HAL_P,
HAL_Q,
HAL_R,
HAL_S,
HAL_T,
HAL_U,
HAL_V,
HAL_W,
HAL_X,
HAL_Y,
HAL_Z,
HAL_LBRACKET,
HAL_BACKSLASH,
HAL_RBRACKET,
HAL_BACKQUOTE = 0x60,
HAL_F1 = 0x80,
HAL_F2,
HAL_F3,
HAL_F4,
HAL_F5,
HAL_F6,
HAL_F7,
HAL_F8,
HAL_F9,
HAL_F10,
HAL_F11,
HAL_F12,
HAL_LCTRL,
HAL_RCTRL,
HAL_LSHIFT,
HAL_RSHIFT,
HAL_LALT,
HAL_RALT,
HAL_CAPSLOCK,
HAL_NUMLOCK,
HAL_SCROLLLOCK,
HAL_PAD_0,
HAL_PAD_1,
HAL_PAD_2,
HAL_PAD_3,
HAL_PAD_4,
HAL_PAD_5,
HAL_PAD_6,
HAL_PAD_7,
HAL_PAD_8,
HAL_PAD_9,
HAL_PAD_HYPHEN,
HAL_PAD_PLUS,
HAL_PAD_SLASH,
HAL_PAD_PERIOD,
HAL_PAD_ENTER,
HAL_SYSRQ,
HAL_PRNTSCRN,
HAL_BREAK,
HAL_UP,
HAL_LEFT,
HAL_RIGHT,
HAL_DOWN,
HAL_HOME,
HAL_END,
HAL_PGUP,
HAL_PGDN,
HAL_INSERT,
HAL_DELETE,
HAL_LWINDOW,
HAL_RWINDOW,
HAL_MENU,
HAL_POWER,
HAL_SLEEP,
HAL_WAKE
}
halKeys;
/* Structure that defined keyboard mapping. */
typedef struct _halKeyMap
{
/* Normal key. */
halKeys normal;
/* Extended key. */
halKeys extended;
}
halKeyMap;
/* Event structure. */
typedef struct _halEvent
{
/* Event type. */
halEventType type;
/* Event data union. */
union _halEventData
{
/* Event data for keyboard. */
struct _halKeyboard
{
/* Scancode. */
halKeys scancode;
/* ASCII characte of the key pressed. */
char key;
/* Flag whether the key was pressed (1) or released (0). */
char pressed;
}
keyboard;
/* Event data for pointer. */
struct _halPointer
{
/* Current pointer coordinate. */
int x;
int y;
}
pointer;
/* Event data for mouse buttons. */
struct _halButton
{
/* Left button state. */
int left;
/* Middle button state. */
int middle;
/* Right button state. */
int right;
/* Current pointer coordinate. */
int x;
int y;
}
button;
}
data;
}
halEvent;
/* VFK_DISPLAY_INFO structure defining information returned by
vdkGetDisplayInfoEx. */
typedef struct _halDISPLAY_INFO
{
/* The size of the display in pixels. */
int width;
int height;
/* The stride of the dispay. -1 is returned if the stride is not known
** for the specified display.*/
int stride;
/* The color depth of the display in bits per pixel. */
int bitsPerPixel;
/* The logical pointer to the display memory buffer. NULL is returned
** if the pointer is not known for the specified display. */
void * logical;
/* The physical address of the display memory buffer. ~0 is returned
** if the address is not known for the specified display. */
unsigned long physical;
/* Can be wraped as surface. */
int wrapFB;
/* FB_MULTI_BUFFER support */
int multiBuffer;
int backBufferY;
/* Tiled buffer / tile status support. */
int tiledBuffer;
int tileStatus;
int compression;
/* The color info of the display. */
unsigned int alphaLength;
unsigned int alphaOffset;
unsigned int redLength;
unsigned int redOffset;
unsigned int greenLength;
unsigned int greenOffset;
unsigned int blueLength;
unsigned int blueOffset;
/* Display flip support. */
int flip;
}
halDISPLAY_INFO;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_eglplatform_type_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_buffer_h_
#define __gc_hal_kernel_buffer_h_
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
************************ Command Buffer and Event Objects **********************
\******************************************************************************/
/* The number of context buffers per user. */
#define gcdCONTEXT_BUFFER_COUNT 2
#define gcdRENDER_FENCE_LENGTH (6 * gcmSIZEOF(gctUINT32))
#define gcdBLT_FENCE_LENGTH (10 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_FLUSHCACHE_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_XFB_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_HW_FENCE_32BIT (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_HW_FENCE_64BIT (6 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_PROBE_LENGTH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_XFB_LENGH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_PROBE_LENGH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
/* State delta record. */
typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
typedef struct _gcsSTATE_DELTA_RECORD
{
/* State address. */
gctUINT address;
/* State mask. */
gctUINT32 mask;
/* State data. */
gctUINT32 data;
}
gcsSTATE_DELTA_RECORD;
/* State delta. */
typedef struct _gcsSTATE_DELTA
{
/* For debugging: the number of delta in the order of creation. */
gctUINT num;
/* Main state delta ID. Every time state delta structure gets reinitialized,
main ID is incremented. If main state ID overflows, all map entry IDs get
reinitialized to make sure there is no potential erroneous match after
the overflow.*/
gctUINT id;
/* Vertex element count for the delta buffer. */
gctUINT elementCount;
/* Number of states currently stored in the record array. */
gctUINT recordCount;
/* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
gctUINT64 recordArray;
gctUINT recordSize;
/* Map entry ID is used for map entry validation. If map entry ID does not
match the main state delta ID, the entry and the corresponding state are
considered not in use. */
gctUINT64 mapEntryID;
gctUINT mapEntryIDSize;
/* If the map entry ID matches the main state delta ID, index points to
the state record in the record array. */
gctUINT64 mapEntryIndex;
}
gcsSTATE_DELTA;
#define gcdPATCH_LIST_SIZE 1024
/* Command buffer patch record. */
typedef struct _gcsPATCH
{
/* Handle of a video memory node. */
gctUINT32 handle;
/* Flag */
gctUINT32 flag;
}
gcsPATCH;
/* List of patches for the command buffer. */
typedef struct _gcsPATCH_LIST
{
/* Array of patch records. */
struct _gcsPATCH patch[gcdPATCH_LIST_SIZE];
/* Number of patches in the array. */
gctUINT count;
/* Next item in the list. */
struct _gcsPATCH_LIST *next;
}
gcsPATCH_LIST;
#define FENCE_NODE_LIST_INIT_COUNT 100
typedef struct _gcsFENCE_APPEND_NODE
{
gcsSURF_NODE_PTR node;
gceFENCE_TYPE type;
}gcsFENCE_APPEND_NODE;
typedef gcsFENCE_APPEND_NODE * gcsFENCE_APPEND_NODE_PTR;
typedef struct _gcsFENCE_LIST * gcsFENCE_LIST_PTR;
typedef struct _gcsFENCE_LIST
{
/* Resource that need get fence, but command used this resource not generated */
gcsFENCE_APPEND_NODE_PTR pendingList;
gctUINT pendingCount;
gctUINT pendingAllocCount;
/* Resoure that already generated command in this command buffer but not get fence */
gcsFENCE_APPEND_NODE_PTR onIssueList;
gctUINT onIssueCount;
gctUINT onIssueAllocCount;
}
gcsFENCE_LIST;
/* Command buffer object. */
struct _gcoCMDBUF
{
/* The object. */
gcsOBJECT object;
/* Commit count. */
gctUINT64 commitCount;
/* Command buffer entry and exit pipes. */
gcePIPE_SELECT entryPipe;
gcePIPE_SELECT exitPipe;
/* Feature usage flags. */
gctBOOL using2D;
gctBOOL using3D;
/* Size of reserved tail for each commit. */
gctUINT32 reservedTail;
/* Physical address of command buffer. Just a name. */
gctUINT32 physical;
/* Logical address of command buffer. */
gctUINT64 logical;
/* Number of bytes in command buffer. */
gctUINT32 bytes;
/* Start offset into the command buffer. */
gctUINT32 startOffset;
/* Current offset into the command buffer. */
gctUINT32 offset;
/* Number of free bytes in command buffer. */
gctUINT32 free;
/* Location of the last reserved area. */
gctUINT64 lastReserve;
gctUINT32 lastOffset;
#if gcdSECURE_USER
/* Hint array for the current command buffer. */
gctUINT hintArraySize;
gctUINT64 hintArray;
gctUINT64 hintArrayTail;
#endif
/* Last load state command location and hardware address. */
gctUINT64 lastLoadStatePtr;
gctUINT32 lastLoadStateAddress;
gctUINT32 lastLoadStateCount;
/* List of patches. */
gctUINT64 patchHead;
/* Link to next gcoCMDBUF object in one commit. */
gctUINT64 nextCMDBUF;
/*
* Put pointer type member after this line.
*/
/* Completion signal. */
gctSIGNAL signal;
/* Link to the siblings. */
gcoCMDBUF prev;
gcoCMDBUF next;
/* Mirror command buffer(s). */
gcoCMDBUF *mirrors;
gctUINT32 mirrorCount;
};
typedef struct _gcsQUEUE
{
/* Pointer to next gcsQUEUE structure in gcsQUEUE. */
gctUINT64 next;
/* Event information. */
gcsHAL_INTERFACE iface;
}
gcsQUEUE;
/* Event queue. */
struct _gcoQUEUE
{
/* The object. */
gcsOBJECT object;
/* Pointer to current event queue. */
gcsQUEUE_PTR head;
gcsQUEUE_PTR tail;
/* chunks of the records. */
gctPOINTER chunks;
/* List of free records. */
gcsQUEUE_PTR freeList;
#define gcdIN_QUEUE_RECORD_LIMIT 16
/* Number of records currently in queue */
gctUINT32 recordCount;
/* Max size of pending unlock node in vidmem pool not committed */
gctUINT maxUnlockBytes;
gceENGINE engine;
};
struct _gcsTEMPCMDBUF
{
gctUINT32 currentByteSize;
gctPOINTER buffer;
gctBOOL inUse;
};
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_buffer_h_ */

View File

@ -0,0 +1,566 @@
/****************************************************************************
*
* 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 file for the local memory management.
*/
#ifndef __gc_hal_mem_h_
#define __gc_hal_mem_h_
#if (gcdENABLE_3D || gcdENABLE_VG)
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
** Usage:
The macros to declare MemPool type and functions are
gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
The data structures for MemPool are
typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
The MemPool constructor and destructor functions are
gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
FS: for Fixed-Size data structures
VS: for Variable-size data structures
AFS: for Array of Fixed-Size data structures
// Example 1: For a fixed-size data structure, struct gcsNode.
// It is used locally in a file, so the functions are static without prefix.
// At top level, declear allocate and free functions.
// The first argument is the data type.
// The second armument is the short name used in the fuctions.
gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
// The previous macro creates two inline functions,
// _AllocateNode and _FreeNode.
// In function or struct
gcsMEM_FS_MEM_POOL nodeMemPool;
// In function,
struct gcsNode * node;
gceSTATUS status;
// Before using the memory pool, initialize it.
// The second argument is the gcoOS object.
// The third argument is the number of data structures to allocate for each chunk.
status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
...
// Allocate a node.
status = _AllocateNode(nodeMemPool, &node);
...
// Free a node.
_FreeNode(nodeMemPool, node);
// After using the memory pool, free it.
gcfMEM_FreeFSMemPool(&nodeMemPool);
// Example 2: For array of fixed-size data structures, struct gcsNode.
// It is used in several files, so the functions are extern with prefix.
// At top level, declear allocate and free functions.
// The first argument is the data type, and the second one is the short name
// used in the fuctions.
gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
// The previous macro creates two inline functions,
// gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
// In function or struct
gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
// In function,
struct gcsNode * nodeArray;
gceSTATUS status;
// Before using the array memory pool, initialize it.
// The second argument is the gcoOS object, the third is the number of data
// structures to allocate for each chunk.
status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
...
// Allocate a node array of size 100.
status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
...
// Free a node array.
gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
// After using the array memory pool, free it.
gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
*******************************************************************************/
/*******************************************************************************
** To switch back to use gcoOS_Allocate and gcoOS_Free, add
** #define USE_LOCAL_MEMORY_POOL 0
** before including this file.
*******************************************************************************/
#ifndef USE_LOCAL_MEMORY_POOL
/*
USE_LOCAL_MEMORY_POOL
This define enables the local memory management to improve performance.
*/
#define USE_LOCAL_MEMORY_POOL 1
#endif
/*******************************************************************************
** Memory Pool Data Structures
*******************************************************************************/
#if USE_LOCAL_MEMORY_POOL
typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
#else
typedef gcoOS gcsMEM_FS_MEM_POOL;
typedef gcoOS gcsMEM_VS_MEM_POOL;
typedef gcoOS gcsMEM_AFS_MEM_POOL;
#endif
/*******************************************************************************
** Memory Pool Macros
*******************************************************************************/
#if USE_LOCAL_MEMORY_POOL
#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName##List(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * FirstPointer, \
Type * LastPointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status;\
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
}
#else
#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcoOS_Allocate(MemPool, \
gcmSIZEOF(Type), \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
gcmSIZEOF(Type), \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
status = gcoOS_Allocate(MemPool, \
Size, \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
Size, \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
status = gcoOS_Allocate(MemPool, \
Count * gcmSIZEOF(Type), \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
Count * gcmSIZEOF(Type), \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#endif
/*******************************************************************************
** Memory Pool Data Functions
*******************************************************************************/
gceSTATUS
gcfMEM_InitFSMemPool(
IN gcsMEM_FS_MEM_POOL * MemPool,
IN gcoOS OS,
IN gctUINT NodeCount,
IN gctUINT NodeSize
);
gceSTATUS
gcfMEM_FreeFSMemPool(
IN gcsMEM_FS_MEM_POOL * MemPool
);
gceSTATUS
gcfMEM_FSMemPoolGetANode(
IN gcsMEM_FS_MEM_POOL MemPool,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_FSMemPoolFreeANode(
IN gcsMEM_FS_MEM_POOL MemPool,
IN gctPOINTER Node
);
gceSTATUS
gcfMEM_FSMemPoolFreeAList(
IN gcsMEM_FS_MEM_POOL MemPool,
IN gctPOINTER FirstNode,
IN gctPOINTER LastNode
);
gceSTATUS
gcfMEM_InitVSMemPool(
IN gcsMEM_VS_MEM_POOL * MemPool,
IN gcoOS OS,
IN gctUINT BlockSize,
IN gctBOOL RecycleFreeNode
);
gceSTATUS
gcfMEM_FreeVSMemPool(
IN gcsMEM_VS_MEM_POOL * MemPool
);
gceSTATUS
gcfMEM_VSMemPoolGetANode(
IN gcsMEM_VS_MEM_POOL MemPool,
IN gctUINT Size,
IN gctUINT Alignment,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_VSMemPoolFreeANode(
IN gcsMEM_VS_MEM_POOL MemPool,
IN gctPOINTER Node
);
gceSTATUS
gcfMEM_InitAFSMemPool(
IN gcsMEM_AFS_MEM_POOL *MemPool,
IN gcoOS OS,
IN gctUINT NodeCount,
IN gctUINT NodeSize
);
gceSTATUS
gcfMEM_FreeAFSMemPool(
IN gcsMEM_AFS_MEM_POOL *MemPool
);
gceSTATUS
gcfMEM_AFSMemPoolGetANode(
IN gcsMEM_AFS_MEM_POOL MemPool,
IN gctUINT Count,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_AFSMemPoolFreeANode(
IN gcsMEM_AFS_MEM_POOL MemPool,
IN gctPOINTER Node
);
#ifdef __cplusplus
}
#endif
#endif /* (gcdENABLE_3D || gcdENABLE_VG) */
#endif /* __gc_hal_mem_h_ */

View File

@ -0,0 +1,121 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_metadata_h_
#define __gc_hal_kernel_metadata_h_
#ifdef __cplusplus
extern "C" {
#endif
/* Macro to combine four characters into a Character Code. */
#define __FOURCC(a, b, c, d) \
((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define VIV_VIDMEM_METADATA_MAGIC __FOURCC('v', 'i', 'v', 'm')
/* Compressed format now was defined same as dec400d, should be general. */
typedef enum _VIV_COMPRESS_FMT
{
_VIV_CFMT_ARGB8 = 0,
_VIV_CFMT_XRGB8,
_VIV_CFMT_AYUV,
_VIV_CFMT_UYVY,
_VIV_CFMT_YUY2,
_VIV_CFMT_YUV_ONLY,
_VIV_CFMT_UV_MIX,
_VIV_CFMT_ARGB4,
_VIV_CFMT_XRGB4,
_VIV_CFMT_A1R5G5B5,
_VIV_CFMT_X1R5G5B5,
_VIV_CFMT_R5G6B5,
_VIV_CFMT_Z24S8,
_VIV_CFMT_Z24,
_VIV_CFMT_Z16,
_VIV_CFMT_A2R10G10B10,
_VIV_CFMT_BAYER,
_VIV_CFMT_SIGNED_BAYER,
_VIV_CFMT_VAA16,
_VIV_CFMT_S8,
_VIV_CFMT_MAX,
} _VIV_COMPRESS_FMT;
/* Metadata for cross-device fd share with additional (ts) info. */
typedef struct _VIV_VIDMEM_METADATA
{
uint32_t magic;
int32_t ts_fd;
void * ts_dma_buf;
#ifdef gcdANDROID
dma_addr_t ts_address;
#endif
uint32_t fc_enabled;
uint32_t fc_value;
uint32_t fc_value_upper;
uint32_t compressed;
uint32_t compress_format;
} _VIV_VIDMEM_METADATA;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_metadata_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,279 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_rename_h_
#define __gc_hal_rename_h_
#if defined(_HAL2D_APPENDIX)
#define _HAL2D_RENAME_2(api, appendix) api ## appendix
#define _HAL2D_RENAME_1(api, appendix) _HAL2D_RENAME_2(api, appendix)
#define gcmHAL2D(api) _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
#define gckOS_Construct gcmHAL2D(gckOS_Construct)
#define gckOS_Destroy gcmHAL2D(gckOS_Destroy)
#define gckOS_QueryVideoMemory gcmHAL2D(gckOS_QueryVideoMemory)
#define gckOS_Allocate gcmHAL2D(gckOS_Allocate)
#define gckOS_Free gcmHAL2D(gckOS_Free)
#define gckOS_AllocateMemory gcmHAL2D(gckOS_AllocateMemory)
#define gckOS_FreeMemory gcmHAL2D(gckOS_FreeMemory)
#define gckOS_AllocatePagedMemory gcmHAL2D(gckOS_AllocatePagedMemory)
#define gckOS_AllocatePagedMemoryEx gcmHAL2D(gckOS_AllocatePagedMemoryEx)
#define gckOS_LockPages gcmHAL2D(gckOS_LockPages)
#define gckOS_MapPages gcmHAL2D(gckOS_MapPages)
#define gckOS_UnlockPages gcmHAL2D(gckOS_UnlockPages)
#define gckOS_FreePagedMemory gcmHAL2D(gckOS_FreePagedMemory)
#define gckOS_AllocateNonPagedMemory gcmHAL2D(gckOS_AllocateNonPagedMemory)
#define gckOS_FreeNonPagedMemory gcmHAL2D(gckOS_FreeNonPagedMemory)
#define gckOS_AllocateContiguous gcmHAL2D(gckOS_AllocateContiguous)
#define gckOS_FreeContiguous gcmHAL2D(gckOS_FreeContiguous)
#define gckOS_GetPageSize gcmHAL2D(gckOS_GetPageSize)
#define gckOS_GetPhysicalAddress gcmHAL2D(gckOS_GetPhysicalAddress)
#define gckOS_UserLogicalToPhysical gcmHAL2D(gckOS_UserLogicalToPhysical)
#define gckOS_GetPhysicalAddressProcess gcmHAL2D(gckOS_GetPhysicalAddressProcess)
#define gckOS_MapPhysical gcmHAL2D(gckOS_MapPhysical)
#define gckOS_UnmapPhysical gcmHAL2D(gckOS_UnmapPhysical)
#define gckOS_ReadRegister gcmHAL2D(gckOS_ReadRegister)
#define gckOS_WriteRegister gcmHAL2D(gckOS_WriteRegister)
#define gckOS_WriteMemory gcmHAL2D(gckOS_WriteMemory)
#define gckOS_MapMemory gcmHAL2D(gckOS_MapMemory)
#define gckOS_UnmapMemory gcmHAL2D(gckOS_UnmapMemory)
#define gckOS_UnmapMemoryEx gcmHAL2D(gckOS_UnmapMemoryEx)
#define gckOS_CreateMutex gcmHAL2D(gckOS_CreateMutex)
#define gckOS_DeleteMutex gcmHAL2D(gckOS_DeleteMutex)
#define gckOS_AcquireMutex gcmHAL2D(gckOS_AcquireMutex)
#define gckOS_ReleaseMutex gcmHAL2D(gckOS_ReleaseMutex)
#define gckOS_AtomicExchange gcmHAL2D(gckOS_AtomicExchange)
#define gckOS_AtomicExchangePtr gcmHAL2D(gckOS_AtomicExchangePtr)
#define gckOS_AtomConstruct gcmHAL2D(gckOS_AtomConstruct)
#define gckOS_AtomDestroy gcmHAL2D(gckOS_AtomDestroy)
#define gckOS_AtomGet gcmHAL2D(gckOS_AtomGet)
#define gckOS_AtomIncrement gcmHAL2D(gckOS_AtomIncrement)
#define gckOS_AtomDecrement gcmHAL2D(gckOS_AtomDecrement)
#define gckOS_Delay gcmHAL2D(gckOS_Delay)
#define gckOS_GetTime gcmHAL2D(gckOS_GetTime)
#define gckOS_MemoryBarrier gcmHAL2D(gckOS_MemoryBarrier)
#define gckOS_MapUserPointer gcmHAL2D(gckOS_MapUserPointer)
#define gckOS_UnmapUserPointer gcmHAL2D(gckOS_UnmapUserPointer)
#define gckOS_QueryNeedCopy gcmHAL2D(gckOS_QueryNeedCopy)
#define gckOS_CopyFromUserData gcmHAL2D(gckOS_CopyFromUserData)
#define gckOS_CopyToUserData gcmHAL2D(gckOS_CopyToUserData)
#define gckOS_SuspendInterrupt gcmHAL2D(gckOS_SuspendInterrupt)
#define gckOS_ResumeInterrupt gcmHAL2D(gckOS_ResumeInterrupt)
#define gckOS_GetBaseAddress gcmHAL2D(gckOS_GetBaseAddress)
#define gckOS_MemCopy gcmHAL2D(gckOS_MemCopy)
#define gckOS_ZeroMemory gcmHAL2D(gckOS_ZeroMemory)
#define gckOS_DeviceControl gcmHAL2D(gckOS_DeviceControl)
#define gckOS_GetProcessID gcmHAL2D(gckOS_GetProcessID)
#define gckOS_GetThreadID gcmHAL2D(gckOS_GetThreadID)
#define gckOS_CreateSignal gcmHAL2D(gckOS_CreateSignal)
#define gckOS_DestroySignal gcmHAL2D(gckOS_DestroySignal)
#define gckOS_Signal gcmHAL2D(gckOS_Signal)
#define gckOS_WaitSignal gcmHAL2D(gckOS_WaitSignal)
#define gckOS_MapSignal gcmHAL2D(gckOS_MapSignal)
#define gckOS_MapUserMemory gcmHAL2D(gckOS_MapUserMemory)
#define gckOS_UnmapUserMemory gcmHAL2D(gckOS_UnmapUserMemory)
#define gckOS_CreateUserSignal gcmHAL2D(gckOS_CreateUserSignal)
#define gckOS_DestroyUserSignal gcmHAL2D(gckOS_DestroyUserSignal)
#define gckOS_WaitUserSignal gcmHAL2D(gckOS_WaitUserSignal)
#define gckOS_SignalUserSignal gcmHAL2D(gckOS_SignalUserSignal)
#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
#define gckOS_CacheClean gcmHAL2D(gckOS_CacheClean)
#define gckOS_CacheFlush gcmHAL2D(gckOS_CacheFlush)
#define gckOS_SetDebugLevel gcmHAL2D(gckOS_SetDebugLevel)
#define gckOS_SetDebugZone gcmHAL2D(gckOS_SetDebugZone)
#define gckOS_SetDebugLevelZone gcmHAL2D(gckOS_SetDebugLevelZone)
#define gckOS_SetDebugZones gcmHAL2D(gckOS_SetDebugZones)
#define gckOS_SetDebugFile gcmHAL2D(gckOS_SetDebugFile)
#define gckOS_Broadcast gcmHAL2D(gckOS_Broadcast)
#define gckOS_SetGPUPower gcmHAL2D(gckOS_SetGPUPower)
#define gckOS_CreateSemaphore gcmHAL2D(gckOS_CreateSemaphore)
#define gckOS_DestroySemaphore gcmHAL2D(gckOS_DestroySemaphore)
#define gckOS_AcquireSemaphore gcmHAL2D(gckOS_AcquireSemaphore)
#define gckOS_ReleaseSemaphore gcmHAL2D(gckOS_ReleaseSemaphore)
#define gckHEAP_Construct gcmHAL2D(gckHEAP_Construct)
#define gckHEAP_Destroy gcmHAL2D(gckHEAP_Destroy)
#define gckHEAP_Allocate gcmHAL2D(gckHEAP_Allocate)
#define gckHEAP_Free gcmHAL2D(gckHEAP_Free)
#define gckHEAP_ProfileStart gcmHAL2D(gckHEAP_ProfileStart)
#define gckHEAP_ProfileEnd gcmHAL2D(gckHEAP_ProfileEnd)
#define gckHEAP_Test gcmHAL2D(gckHEAP_Test)
#define gckVIDMEM_Construct gcmHAL2D(gckVIDMEM_Construct)
#define gckVIDMEM_Destroy gcmHAL2D(gckVIDMEM_Destroy)
#define gckVIDMEM_Allocate gcmHAL2D(gckVIDMEM_Allocate)
#define gckVIDMEM_AllocateLinear gcmHAL2D(gckVIDMEM_AllocateLinear)
#define gckVIDMEM_Free gcmHAL2D(gckVIDMEM_Free)
#define gckVIDMEM_Lock gcmHAL2D(gckVIDMEM_Lock)
#define gckVIDMEM_Unlock gcmHAL2D(gckVIDMEM_Unlock)
#define gckVIDMEM_ConstructVirtual gcmHAL2D(gckVIDMEM_ConstructVirtual)
#define gckVIDMEM_DestroyVirtual gcmHAL2D(gckVIDMEM_DestroyVirtual)
#define gckKERNEL_Construct gcmHAL2D(gckKERNEL_Construct)
#define gckKERNEL_Destroy gcmHAL2D(gckKERNEL_Destroy)
#define gckKERNEL_Dispatch gcmHAL2D(gckKERNEL_Dispatch)
#define gckKERNEL_QueryVideoMemory gcmHAL2D(gckKERNEL_QueryVideoMemory)
#define gckKERNEL_GetVideoMemoryPool gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
#define gckKERNEL_MapVideoMemory gcmHAL2D(gckKERNEL_MapVideoMemory)
#define gckKERNEL_UnmapVideoMemory gcmHAL2D(gckKERNEL_UnmapVideoMemory)
#define gckKERNEL_MapMemory gcmHAL2D(gckKERNEL_MapMemory)
#define gckKERNEL_UnmapMemory gcmHAL2D(gckKERNEL_UnmapMemory)
#define gckKERNEL_Notify gcmHAL2D(gckKERNEL_Notify)
#define gckKERNEL_QuerySettings gcmHAL2D(gckKERNEL_QuerySettings)
#define gckKERNEL_Recovery gcmHAL2D(gckKERNEL_Recovery)
#define gckKERNEL_OpenUserData gcmHAL2D(gckKERNEL_OpenUserData)
#define gckKERNEL_CloseUserData gcmHAL2D(gckKERNEL_CloseUserData)
#define gckHARDWARE_Construct gcmHAL2D(gckHARDWARE_Construct)
#define gckHARDWARE_Destroy gcmHAL2D(gckHARDWARE_Destroy)
#define gckHARDWARE_QuerySystemMemory gcmHAL2D(gckHARDWARE_QuerySystemMemory)
#define gckHARDWARE_BuildVirtualAddress gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
#define gckHARDWARE_QueryCommandBuffer gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
#define gckHARDWARE_WaitLink gcmHAL2D(gckHARDWARE_WaitLink)
#define gckHARDWARE_Execute gcmHAL2D(gckHARDWARE_Execute)
#define gckHARDWARE_End gcmHAL2D(gckHARDWARE_End)
#define gckHARDWARE_Nop gcmHAL2D(gckHARDWARE_Nop)
#define gckHARDWARE_PipeSelect gcmHAL2D(gckHARDWARE_PipeSelect)
#define gckHARDWARE_Link gcmHAL2D(gckHARDWARE_Link)
#define gckHARDWARE_Event gcmHAL2D(gckHARDWARE_Event)
#define gckHARDWARE_QueryMemory gcmHAL2D(gckHARDWARE_QueryMemory)
#define gckHARDWARE_QueryChipIdentity gcmHAL2D(gckHARDWARE_QueryChipIdentity)
#define gckHARDWARE_QueryChipSpecs gcmHAL2D(gckHARDWARE_QueryChipSpecs)
#define gckHARDWARE_QueryShaderCaps gcmHAL2D(gckHARDWARE_QueryShaderCaps)
#define gckHARDWARE_ConvertFormat gcmHAL2D(gckHARDWARE_ConvertFormat)
#define gckHARDWARE_SplitMemory gcmHAL2D(gckHARDWARE_SplitMemory)
#define gckHARDWARE_AlignToTile gcmHAL2D(gckHARDWARE_AlignToTile)
#define gckHARDWARE_UpdateQueueTail gcmHAL2D(gckHARDWARE_UpdateQueueTail)
#define gckHARDWARE_ConvertLogical gcmHAL2D(gckHARDWARE_ConvertLogical)
#define gckHARDWARE_Interrupt gcmHAL2D(gckHARDWARE_Interrupt)
#define gckHARDWARE_SetMMU gcmHAL2D(gckHARDWARE_SetMMU)
#define gckHARDWARE_FlushMMU gcmHAL2D(gckHARDWARE_FlushMMU)
#define gckHARDWARE_GetIdle gcmHAL2D(gckHARDWARE_GetIdle)
#define gckHARDWARE_Flush gcmHAL2D(gckHARDWARE_Flush)
#define gckHARDWARE_SetFastClear gcmHAL2D(gckHARDWARE_SetFastClear)
#define gckHARDWARE_ReadInterrupt gcmHAL2D(gckHARDWARE_ReadInterrupt)
#define gckHARDWARE_SetPowerManagementState gcmHAL2D(gckHARDWARE_SetPowerManagementState)
#define gckHARDWARE_QueryPowerManagementState gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
#define gckHARDWARE_ProfileEngine2D gcmHAL2D(gckHARDWARE_ProfileEngine2D)
#define gckHARDWARE_InitializeHardware gcmHAL2D(gckHARDWARE_InitializeHardware)
#define gckHARDWARE_Reset gcmHAL2D(gckHARDWARE_Reset)
#define gckINTERRUPT_Construct gcmHAL2D(gckINTERRUPT_Construct)
#define gckINTERRUPT_Destroy gcmHAL2D(gckINTERRUPT_Destroy)
#define gckINTERRUPT_SetHandler gcmHAL2D(gckINTERRUPT_SetHandler)
#define gckINTERRUPT_Notify gcmHAL2D(gckINTERRUPT_Notify)
#define gckEVENT_Construct gcmHAL2D(gckEVENT_Construct)
#define gckEVENT_Destroy gcmHAL2D(gckEVENT_Destroy)
#define gckEVENT_AddList gcmHAL2D(gckEVENT_AddList)
#define gckEVENT_FreeNonPagedMemory gcmHAL2D(gckEVENT_FreeNonPagedMemory)
#define gckEVENT_FreeContiguousMemory gcmHAL2D(gckEVENT_FreeContiguousMemory)
#define gckEVENT_FreeVideoMemory gcmHAL2D(gckEVENT_FreeVideoMemory)
#define gckEVENT_Signal gcmHAL2D(gckEVENT_Signal)
#define gckEVENT_Unlock gcmHAL2D(gckEVENT_Unlock)
#define gckEVENT_Submit gcmHAL2D(gckEVENT_Submit)
#define gckEVENT_Commit gcmHAL2D(gckEVENT_Commit)
#define gckEVENT_Notify gcmHAL2D(gckEVENT_Notify)
#define gckEVENT_Interrupt gcmHAL2D(gckEVENT_Interrupt)
#define gckCOMMAND_Construct gcmHAL2D(gckCOMMAND_Construct)
#define gckCOMMAND_Destroy gcmHAL2D(gckCOMMAND_Destroy)
#define gckCOMMAND_EnterCommit gcmHAL2D(gckCOMMAND_EnterCommit)
#define gckCOMMAND_ExitCommit gcmHAL2D(gckCOMMAND_ExitCommit)
#define gckCOMMAND_Start gcmHAL2D(gckCOMMAND_Start)
#define gckCOMMAND_Stop gcmHAL2D(gckCOMMAND_Stop)
#define gckCOMMAND_Commit gcmHAL2D(gckCOMMAND_Commit)
#define gckCOMMAND_Reserve gcmHAL2D(gckCOMMAND_Reserve)
#define gckCOMMAND_Execute gcmHAL2D(gckCOMMAND_Execute)
#define gckCOMMAND_Stall gcmHAL2D(gckCOMMAND_Stall)
#define gckCOMMAND_Attach gcmHAL2D(gckCOMMAND_Attach)
#define gckCOMMAND_Detach gcmHAL2D(gckCOMMAND_Detach)
#define gckMMU_Construct gcmHAL2D(gckMMU_Construct)
#define gckMMU_Destroy gcmHAL2D(gckMMU_Destroy)
#define gckMMU_AllocatePages gcmHAL2D(gckMMU_AllocatePages)
#define gckMMU_FreePages gcmHAL2D(gckMMU_FreePages)
#define gckMMU_Test gcmHAL2D(gckMMU_Test)
#define gckHARDWARE_QueryProfileRegisters gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
#define FindMdlMap gcmHAL2D(FindMdlMap)
#define OnProcessExit gcmHAL2D(OnProcessExit)
#define gckGALDEVICE_Destroy gcmHAL2D(gckGALDEVICE_Destroy)
#define gckOS_Print gcmHAL2D(gckOS_Print)
#define gckGALDEVICE_FreeMemory gcmHAL2D(gckGALDEVICE_FreeMemory)
#define gckGALDEVICE_AllocateMemory gcmHAL2D(gckGALDEVICE_AllocateMemory)
#define gckOS_DebugBreak gcmHAL2D(gckOS_DebugBreak)
#define gckGALDEVICE_Release_ISR gcmHAL2D(gckGALDEVICE_Release_ISR)
#define gckOS_Verify gcmHAL2D(gckOS_Verify)
#define gckCOMMAND_Release gcmHAL2D(gckCOMMAND_Release)
#define gckGALDEVICE_Stop gcmHAL2D(gckGALDEVICE_Stop)
#define gckGALDEVICE_Construct gcmHAL2D(gckGALDEVICE_Construct)
#define gckOS_DebugFatal gcmHAL2D(gckOS_DebugFatal)
#define gckOS_DebugTrace gcmHAL2D(gckOS_DebugTrace)
#define gckHARDWARE_GetBaseAddress gcmHAL2D(gckHARDWARE_GetBaseAddress)
#define gckGALDEVICE_Setup_ISR gcmHAL2D(gckGALDEVICE_Setup_ISR)
#define gckKERNEL_AttachProcess gcmHAL2D(gckKERNEL_AttachProcess)
#define gckKERNEL_AttachProcessEx gcmHAL2D(gckKERNEL_AttachProcessEx)
#define gckGALDEVICE_Start_Thread gcmHAL2D(gckGALDEVICE_Start_Thread)
#define gckHARDWARE_QueryIdle gcmHAL2D(gckHARDWARE_QueryIdle)
#define gckGALDEVICE_Start gcmHAL2D(gckGALDEVICE_Start)
#define gckOS_GetKernelLogical gcmHAL2D(gckOS_GetKernelLogical)
#define gckOS_DebugTraceZone gcmHAL2D(gckOS_DebugTraceZone)
#define gckGALDEVICE_Stop_Thread gcmHAL2D(gckGALDEVICE_Stop_Thread)
#define gckHARDWARE_NeedBaseAddress gcmHAL2D(gckHARDWARE_NeedBaseAddress)
#endif
#endif /* __gc_hal_rename_h_ */

View File

@ -0,0 +1,69 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_resource_h_
#define __gc_hal_resource_h_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_resource_h_ */

View File

@ -0,0 +1,186 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _GC_HAL_SECURITY_INTERFACE_H_
#define _GC_HAL_SECURITY_INTERFACE_H_
/*!
@brief Command codes between kernel module and TrustZone
@discussion
Critical services must be done in TrustZone to avoid sensitive content leak. Most of kernel module is kept in non-Secure os to minimize
code in TrustZone.
*/
typedef enum kernel_packet_command {
KERNEL_START_COMMAND,
KERNEL_SUBMIT,
KERNEL_MAP_MEMORY, /* */
KERNEL_UNMAP_MEMORY,
KERNEL_ALLOCATE_SECRUE_MEMORY, /*! Security memory management. */
KERNEL_FREE_SECURE_MEMORY,
KERNEL_EXECUTE, /* Execute a command buffer. */
KERNEL_DUMP_MMU_EXCEPTION,
KERNEL_HANDLE_MMU_EXCEPTION,
KERNEL_READ_MMU_EXCEPTION,
} kernel_packet_command_t;
struct kernel_start_command {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT32 address;
gctUINT32 bytes;
};
/*!
@brief gckCOMMAND Object requests TrustZone to submit command buffer.
@discussion
Code in trustzone will check content of command buffer after copying command buffer to TrustZone.
*/
struct kernel_submit {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT8 kernel_command; /*! Whether it is a kernel command. */
gctUINT32 command_buffer_handle; /*! Handle to command buffer. */
gctUINT32 offset; /* Offset in command buffer. */
gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
gctUINT32 command_buffer_length; /*! Length of command buffer. */
};
/*!
@brief gckVIDMEM Object requests TrustZone to allocate security memory.
@discussion
Allocate a buffer from security GPU memory.
*/
struct kernel_allocate_security_memory {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT32 bytes; /*! Requested bytes. */
gctUINT32 memory_handle; /*! Handle of allocated memory. */
};
/*!
@brief gckVIDMEM Object requests TrustZone to allocate security memory.
@discussion
Free a video memory buffer from security GPU memory.
*/
struct kernel_free_security_memory {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT32 memory_handle; /*! Handle of allocated memory. */
};
struct kernel_execute {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT8 kernel_command; /*! Whether it is a kernel command. */
gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
gctUINT32 command_buffer_length; /*! Length of command buffer. */
};
typedef struct kernel_map_scatter_gather {
gctUINT32 bytes;
gctUINT32 physical;
struct kernel_map_scatter_gather *next;
}
kernel_map_scatter_gather_t;
struct kernel_map_memory {
kernel_packet_command_t command;
kernel_map_scatter_gather_t *scatter;
gctUINT32 *physicals;
gctPHYS_ADDR_T physical; /*! Contiguous physical address range. */
gctUINT32 pageCount;
gctUINT32 gpuAddress;
};
struct kernel_unmap_memory {
gctUINT32 gpuAddress;
gctUINT32 pageCount;
};
struct kernel_read_mmu_exception {
gctUINT32 mmuStatus;
gctUINT32 mmuException;
};
struct kernel_handle_mmu_exception {
gctUINT32 mmuStatus;
gctPHYS_ADDR_T physical;
gctUINT32 gpuAddress;
};
typedef struct _gcsTA_INTERFACE {
kernel_packet_command_t command;
union {
struct kernel_submit Submit;
struct kernel_start_command StartCommand;
struct kernel_allocate_security_memory AllocateSecurityMemory;
struct kernel_execute Execute;
struct kernel_map_memory MapMemory;
struct kernel_unmap_memory UnmapMemory;
struct kernel_read_mmu_exception ReadMMUException;
struct kernel_handle_mmu_exception HandleMMUException;
} u;
gceSTATUS result;
} gcsTA_INTERFACE;
enum {
gcvTA_COMMAND_INIT,
gcvTA_COMMAND_DISPATCH,
gcvTA_CALLBACK_ALLOC_SECURE_MEM,
gcvTA_CALLBACK_FREE_SECURE_MEM,
};
#endif

View File

@ -0,0 +1,135 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_statistics_h_
#define __gc_hal_statistics_h_
#define VIV_STAT_ENABLE_STATISTICS 0
/* Toal number of frames for which the frame time is accounted. We have storage
to keep frame times for last this many frames.
*/
#define VIV_STAT_FRAME_BUFFER_SIZE 30
/*
Total number of frames sampled for a mode. This means
# of frames for HZ Current : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
# of frames for HZ Switched : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+
--------------------------------------------------------
: (2 * VIV_STAT_EARLY_Z_SAMPLE_FRAMES) frames needed
IMPORTANT: This total must be smaller than VIV_STAT_FRAME_BUFFER_SIZE
*/
#define VIV_STAT_EARLY_Z_SAMPLE_FRAMES 7
#define VIV_STAT_EARLY_Z_LATENCY_FRAMES 2
/* Multiplication factor for previous Hz off mode. Make it more than 1.0 to advertise HZ on.*/
#define VIV_STAT_EARLY_Z_FACTOR (1.05f)
/* Defines the statistical data keys monitored by the statistics module */
typedef enum _gceSTATISTICS
{
gcvFRAME_FPS = 1,
}
gceSTATISTICS;
/* HAL statistics information. */
typedef struct _gcsSTATISTICS_EARLYZ
{
gctUINT switchBackCount;
gctUINT nextCheckPoint;
gctBOOL disabled;
}
gcsSTATISTICS_EARLYZ;
/* HAL statistics information. */
typedef struct _gcsSTATISTICS
{
gctUINT64 frameTime[VIV_STAT_FRAME_BUFFER_SIZE];
gctUINT64 previousFrameTime;
gctUINT frame;
gcsSTATISTICS_EARLYZ earlyZ;
}
gcsSTATISTICS;
/* Add a frame based data into current statistics. */
void
gcfSTATISTICS_AddData(
IN gceSTATISTICS Key,
IN gctUINT Value
);
/* Marks the frame end and triggers statistical calculations and decisions.*/
void
gcfSTATISTICS_MarkFrameEnd (
void
);
/* Sets whether the dynmaic HZ is disabled or not .*/
void
gcfSTATISTICS_DisableDynamicEarlyZ (
IN gctBOOL Disabled
);
#endif /*__gc_hal_statistics_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_version_h_
#define __gc_hal_version_h_
#define gcvVERSION_MAJOR 6
#define gcvVERSION_MINOR 2
#define gcvVERSION_PATCH 4
#define gcvVERSION_BUILD 190076
#define gcvVERSION_STRING "6.2.4.p4.190076"
#endif /* __gc_hal_version_h_ */

View File

@ -0,0 +1,918 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_vg_h_
#define __gc_hal_vg_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "gc_hal_rename.h"
#include "gc_hal_types.h"
#include "gc_hal_enum.h"
#include "gc_hal_base.h"
#if gcdENABLE_VG
/* Thread routine type. */
#if defined(LINUX)
typedef gctINT gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE
#elif defined(WIN32)
typedef gctUINT gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE __stdcall
#elif defined(__QNXNTO__)
typedef void * gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE
#endif
typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
gctTHREADFUNCPARAMETER ThreadParameter
);
#if defined(gcvDEBUG)
# undef gcvDEBUG
#endif
#define gcdFORCE_DEBUG 0
#define gcdFORCE_MESSAGES 0
#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
# define gcvDEBUG 1
#else
# define gcvDEBUG 0
#endif
#define _gcmERROR_RETURN(prefix, func) \
status = func; \
if (gcmIS_ERROR(status)) \
{ \
prefix##PRINT_VERSION(); \
prefix##TRACE(gcvLEVEL_ERROR, \
#prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
return status; \
} \
do { } while (gcvFALSE)
#define gcmERROR_RETURN(func) _gcmERROR_RETURN(gcm, func)
#define gcmLOG_LOCATION()
#define gcmkIS_ERROR(status) (status < 0)
#define gcmALIGNDOWN(n, align) \
(\
(n) & ~((align) - 1) \
)
#define gcmIS_VALID_INDEX(Index, Array) \
(((gctUINT) (Index)) < gcmCOUNTOF(Array))
#define gcmIS_NAN(x) \
(\
((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
)
#define gcmLERP(v1, v2, w) \
((v1) * (w) + (v2) * (1.0f - (w)))
#define gcmINTERSECT(Start1, Start2, Length) \
(gcmABS((Start1) - (Start2)) < (Length))
/*******************************************************************************
**
** gcmERR_GOTO
**
** Prints a message and terminates the current loop on error.
**
** ASSUMPTIONS:
**
** 'status' variable of gceSTATUS type must be defined.
**
** ARGUMENTS:
**
** Function
** Function to evaluate.
*/
#define gcmERR_GOTO(Function) \
status = Function; \
if (gcmIS_ERROR(status)) \
{ \
gcmTRACE(\
gcvLEVEL_ERROR, \
"gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
status, __LINE__, __FUNCTION__ \
); \
goto ErrorHandler; \
}
#if gcvDEBUG || gcdFORCE_MESSAGES
# define gcmVERIFY_BOOLEAN(Expression) \
gcmASSERT(\
((Expression) == gcvFALSE ) || \
((Expression) == gcvTRUE ) \
)
#else
# define gcmVERIFY_BOOLEAN(Expression)
#endif
/*******************************************************************************
**
** gcmVERIFYFIELDFIT
**
** Verify whether the value fits in the field.
**
** ARGUMENTS:
**
** data Data value.
** reg Name of register.
** field Name of field within register.
** value Value for field.
*/
#define gcmVERIFYFIELDFIT(reg, field, value) \
gcmASSERT(\
(value) <= gcmFIELDMAX(reg, field) \
)
/*******************************************************************************
**
** gcmFIELDMAX
**
** Get field maximum value.
**
** ARGUMENTS:
**
** reg Name of register.
** field Name of field within register.
*/
#define gcmFIELDMAX(reg, field) \
(\
(gctUINT32) \
(\
(__gcmGETSIZE(reg##_##field) == 32) \
? ~0U \
: (~(~0U << __gcmGETSIZE(reg##_##field))) \
) \
)
/* ANSI C does not have the 'f' functions, define replacements here. */
#define gcmSINF(x) ((gctFLOAT) sin(x))
#define gcmCOSF(x) ((gctFLOAT) cos(x))
#define gcmASINF(x) ((gctFLOAT) asin(x))
#define gcmACOSF(x) ((gctFLOAT) acos(x))
#define gcmSQRTF(x) ((gctFLOAT) sqrt(x))
#define gcmFABSF(x) ((gctFLOAT) fabs(x))
#define gcmFMODF(x, y) ((gctFLOAT) fmod((x), (y)))
#define gcmCEILF(x) ((gctFLOAT) ceil(x))
#define gcmFLOORF(x) ((gctFLOAT) floor(x))
/* Fixed point constants. */
#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
/* Integer constants. */
#define gcvMAX_POS_INT ((gctINT) 0x7FFFFFFF)
#define gcvMAX_NEG_INT ((gctINT) 0x80000000)
/* Float constants. */
#define gcvMAX_POS_FLOAT ((gctFLOAT) 3.4028235e+038)
#define gcvMAX_NEG_FLOAT ((gctFLOAT) -3.4028235e+038)
/******************************************************************************\
***************************** Miscellaneous Macro ******************************
\******************************************************************************/
#define gcmKB2BYTES(Kilobyte) \
(\
(Kilobyte) << 10 \
)
#define gcmMB2BYTES(Megabyte) \
(\
(Megabyte) << 20 \
)
#define gcmMAT(Matrix, Row, Column) \
(\
(Matrix) [(Row) * 3 + (Column)] \
)
#define gcmMAKE2CHAR(Char1, Char2) \
(\
((gctUINT16) (gctUINT8) (Char1) << 0) | \
((gctUINT16) (gctUINT8) (Char2) << 8) \
)
#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
(\
((gctUINT32)(gctUINT8) (Char1) << 0) | \
((gctUINT32)(gctUINT8) (Char2) << 8) | \
((gctUINT32)(gctUINT8) (Char3) << 16) | \
((gctUINT32)(gctUINT8) (Char4) << 24) \
)
/* some platforms need to fix the physical address for HW to access*/
#define gcmFIXADDRESS(address) \
(\
(address)\
)
#define gcmkFIXADDRESS(address) \
(\
(address)\
)
/******************************************************************************\
****************************** Kernel Debug Macro ******************************
\******************************************************************************/
/* Return the kernel logical pointer for the given physical one. */
gceSTATUS
gckOS_GetKernelLogical(
IN gckOS Os,
IN gctUINT32 Address,
OUT gctPOINTER * KernelPointer
);
/* Return the kernel logical pointer for the given physical one. */
gceSTATUS
gckOS_GetKernelLogicalEx(
IN gckOS Os,
IN gceCORE Core,
IN gctUINT32 Address,
OUT gctPOINTER * KernelPointer
);
/*----------------------------------------------------------------------------*/
/*----------------------------- Semaphore Object -----------------------------*/
/* Increment the value of a semaphore. */
gceSTATUS
gckOS_IncrementSemaphore(
IN gckOS Os,
IN gctSEMAPHORE Semaphore
);
/* Decrement the value of a semaphore (waiting might occur). */
gceSTATUS
gckOS_DecrementSemaphore(
IN gckOS Os,
IN gctSEMAPHORE Semaphore
);
/*----------------------------------------------------------------------------*/
/*------------------------------- Thread Object ------------------------------*/
/* Start a thread. */
gceSTATUS
gckOS_StartThread(
IN gckOS Os,
IN gctTHREADFUNC ThreadFunction,
IN gctPOINTER ThreadParameter,
OUT gctTHREAD * Thread
);
/* Stop a thread. */
gceSTATUS
gckOS_StopThread(
IN gckOS Os,
IN gctTHREAD Thread
);
/* Verify whether the thread is still running. */
gceSTATUS
gckOS_VerifyThread(
IN gckOS Os,
IN gctTHREAD Thread
);
/* Construct a new gckVGKERNEL object. */
gceSTATUS
gckVGKERNEL_Construct(
IN gckOS Os,
IN gctPOINTER Context,
IN gckKERNEL inKernel,
OUT gckVGKERNEL * Kernel
);
/* Destroy an gckVGKERNEL object. */
gceSTATUS
gckVGKERNEL_Destroy(
IN gckVGKERNEL Kernel
);
/* Unmap memory. */
gceSTATUS
gckKERNEL_UnmapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID
);
/* Dispatch a user-level command. */
gceSTATUS
gckVGKERNEL_Dispatch(
IN gckKERNEL Kernel,
IN gctBOOL FromUser,
IN OUT struct _gcsHAL_INTERFACE * Interface
);
/* Query command buffer requirements. */
gceSTATUS
gckKERNEL_QueryCommandBuffer(
IN gckKERNEL Kernel,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
);
/******************************************************************************\
******************************* gckVGHARDWARE Object ******************************
\******************************************************************************/
/* Construct a new gckVGHARDWARE object. */
gceSTATUS
gckVGHARDWARE_Construct(
IN gckOS Os,
OUT gckVGHARDWARE * Hardware
);
/* Destroy an gckVGHARDWARE object. */
gceSTATUS
gckVGHARDWARE_Destroy(
IN gckVGHARDWARE Hardware
);
/* Query system memory requirements. */
gceSTATUS
gckVGHARDWARE_QuerySystemMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * SystemSize,
OUT gctUINT32 * SystemBaseAddress
);
/* Build virtual address. */
gceSTATUS
gckVGHARDWARE_BuildVirtualAddress(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Index,
IN gctUINT32 Offset,
OUT gctUINT32 * Address
);
/* Kickstart the command processor. */
gceSTATUS
gckVGHARDWARE_Execute(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Count
);
/* Query the available memory. */
gceSTATUS
gckVGHARDWARE_QueryMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * InternalSize,
OUT gctUINT32 * InternalBaseAddress,
OUT gctUINT32 * InternalAlignment,
OUT gctSIZE_T * ExternalSize,
OUT gctUINT32 * ExternalBaseAddress,
OUT gctUINT32 * ExternalAlignment,
OUT gctUINT32 * HorizontalTileSize,
OUT gctUINT32 * VerticalTileSize
);
/* Query the identity of the hardware. */
gceSTATUS
gckVGHARDWARE_QueryChipIdentity(
IN gckVGHARDWARE Hardware,
OUT gceCHIPMODEL* ChipModel,
OUT gctUINT32* ChipRevision,
OUT gctUINT32* ProductID,
OUT gctUINT32* EcoID,
OUT gctUINT32* CustomerID,
OUT gctUINT32* ChipFeatures,
OUT gctUINT32* ChipMinorFeatures,
OUT gctUINT32* ChipMinorFeatures1
);
/* Convert an API format. */
gceSTATUS
gckVGHARDWARE_ConvertFormat(
IN gckVGHARDWARE Hardware,
IN gceSURF_FORMAT Format,
OUT gctUINT32 * BitsPerPixel,
OUT gctUINT32 * BytesPerTile
);
/* Split a harwdare specific address into API stuff. */
gceSTATUS
gckVGHARDWARE_SplitMemory(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
OUT gcePOOL * Pool,
OUT gctUINT32 * Offset
);
/* Align size to tile boundary. */
gceSTATUS
gckVGHARDWARE_AlignToTile(
IN gckVGHARDWARE Hardware,
IN gceSURF_TYPE Type,
IN OUT gctUINT32_PTR Width,
IN OUT gctUINT32_PTR Height
);
/* Convert logical address to hardware specific address. */
gceSTATUS
gckVGHARDWARE_ConvertLogical(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctBOOL InUserSpace,
OUT gctUINT32 * Address
);
/* Program MMU. */
gceSTATUS
gckVGHARDWARE_SetMMU(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical
);
/* Flush the MMU. */
gceSTATUS
gckVGHARDWARE_FlushMMU(
IN gckVGHARDWARE Hardware
);
/* Get idle register. */
gceSTATUS
gckVGHARDWARE_GetIdle(
IN gckVGHARDWARE Hardware,
OUT gctUINT32 * Data
);
/* Flush the caches. */
gceSTATUS
gckVGHARDWARE_Flush(
IN gckVGHARDWARE Hardware,
IN gceKERNEL_FLUSH Flush,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
);
/* Enable/disable fast clear. */
gceSTATUS
gckVGHARDWARE_SetFastClear(
IN gckVGHARDWARE Hardware,
IN gctINT Enable
);
gceSTATUS
gckVGHARDWARE_ReadInterrupt(
IN gckVGHARDWARE Hardware,
OUT gctUINT32_PTR IDs
);
/* Power management. */
gceSTATUS
gckVGHARDWARE_SetPowerManagementState(
IN gckVGHARDWARE Hardware,
IN gceCHIPPOWERSTATE State
);
gceSTATUS
gckVGHARDWARE_QueryPowerManagementState(
IN gckVGHARDWARE Hardware,
OUT gceCHIPPOWERSTATE* State
);
gceSTATUS
gckVGHARDWARE_SetPowerManagement(
IN gckVGHARDWARE Hardware,
IN gctBOOL PowerManagement
);
gceSTATUS
gckVGHARDWARE_SetPowerOffTimeout(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Timeout
);
gceSTATUS
gckVGHARDWARE_QueryPowerOffTimeout(
IN gckVGHARDWARE Hardware,
OUT gctUINT32* Timeout
);
gceSTATUS
gckVGHARDWARE_QueryIdle(
IN gckVGHARDWARE Hardware,
OUT gctBOOL_PTR IsIdle
);
/******************************************************************************\
*************************** Command Buffer Structures **************************
\******************************************************************************/
/* Vacant command buffer marker. */
#define gcvVACANT_BUFFER ((gcsCOMPLETION_SIGNAL_PTR) ((gctSIZE_T)1))
/* Command buffer header. */
typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
typedef struct _gcsCMDBUFFER
{
/* Pointer to the completion signal. */
gcsCOMPLETION_SIGNAL_PTR completion;
/* The user sets this to the node of the container buffer whitin which
this particular command buffer resides. The kernel sets this to the
node of the internally allocated buffer. */
gcuVIDMEM_NODE_PTR node;
/* Command buffer hardware address. */
gctUINT32 address;
/* The offset of the buffer from the beginning of the header. */
gctUINT32 bufferOffset;
/* Size of the area allocated for the data portion of this particular
command buffer (headers and tail reserves are excluded). */
gctUINT32 size;
/* Offset into the buffer [0..size]; reflects exactly how much data has
been put into the command buffer. */
gctUINT offset;
/* The number of command units in the buffer for the hardware to
execute. */
gctUINT32 dataCount;
/* MANAGED BY : user HAL (gcoBUFFER object).
USED BY : user HAL (gcoBUFFER object).
Points to the immediate next allocated command buffer. */
gcsCMDBUFFER_PTR nextAllocated;
/* MANAGED BY : user layers (HAL and drivers).
USED BY : kernel HAL (gcoBUFFER object).
Points to the next subbuffer if any. A family of subbuffers are chained
together and are meant to be executed inseparably as a unit. Meaning
that context switching cannot occur while a chain of subbuffers is being
executed. */
gcsCMDBUFFER_PTR nextSubBuffer;
}
gcsCMDBUFFER;
/* Command queue element. */
typedef struct _gcsVGCMDQUEUE
{
/* Pointer to the command buffer header. */
gcsCMDBUFFER_PTR commandBuffer;
/* Dynamic vs. static command buffer state. */
gctBOOL dynamic;
}
gcsVGCMDQUEUE;
/* Context map entry. */
typedef struct _gcsVGCONTEXT_MAP
{
/* State index. */
gctUINT32 index;
/* New state value. */
gctUINT32 data;
/* Points to the next entry in the mod list. */
gcsVGCONTEXT_MAP_PTR next;
}
gcsVGCONTEXT_MAP;
/* gcsVGCONTEXT structure that holds the current context. */
typedef struct _gcsVGCONTEXT
{
/* Context ID. */
gctUINT64 id;
/* State caching ebable flag. */
gctBOOL stateCachingEnabled;
/* Current pipe. */
gctUINT32 currentPipe;
/* State map/mod buffer. */
gctUINT32 mapFirst;
gctUINT32 mapLast;
gcsVGCONTEXT_MAP_PTR mapContainer;
gcsVGCONTEXT_MAP_PTR mapPrev;
gcsVGCONTEXT_MAP_PTR mapCurr;
gcsVGCONTEXT_MAP_PTR firstPrevMap;
gcsVGCONTEXT_MAP_PTR firstCurrMap;
/* Main context buffer. */
gcsCMDBUFFER_PTR header;
gctUINT32_PTR buffer;
/* Completion signal. */
gctHANDLE process;
gctSIGNAL signal;
#if defined(__QNXNTO__)
gctSIGNAL userSignal;
gctINT32 coid;
gctINT32 rcvid;
#endif
}
gcsVGCONTEXT;
/* User space task header. */
typedef struct _gcsTASK * gcsTASK_PTR;
typedef struct _gcsTASK
{
/* Pointer to the next task for the same interrupt in user space. */
gcsTASK_PTR next;
/* Size of the task data that immediately follows the structure. */
gctUINT size;
/* Task data starts here. */
/* ... */
}
gcsTASK;
/* User space task master table entry. */
typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
typedef struct _gcsTASK_MASTER_ENTRY
{
/* Pointers to the head and to the tail of the task chain. */
gcsTASK_PTR head;
gcsTASK_PTR tail;
}
gcsTASK_MASTER_ENTRY;
/* User space task master table entry. */
typedef struct _gcsTASK_MASTER_TABLE
{
/* Table with one entry per block. */
gcsTASK_MASTER_ENTRY table[gcvBLOCK_COUNT];
/* The total number of tasks sckeduled. */
gctUINT count;
/* The total size of event data in bytes. */
gctUINT size;
#if defined(__QNXNTO__)
gctINT32 coid;
gctINT32 rcvid;
#endif
}
gcsTASK_MASTER_TABLE;
/******************************************************************************\
***************************** gckVGINTERRUPT Object ******************************
\******************************************************************************/
typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
IN gckVGKERNEL Kernel
);
gceSTATUS
gckVGINTERRUPT_Construct(
IN gckVGKERNEL Kernel,
OUT gckVGINTERRUPT * Interrupt
);
gceSTATUS
gckVGINTERRUPT_Destroy(
IN gckVGINTERRUPT Interrupt
);
gceSTATUS
gckVGINTERRUPT_Enable(
IN gckVGINTERRUPT Interrupt,
IN OUT gctINT32_PTR Id,
IN gctINTERRUPT_HANDLER Handler
);
gceSTATUS
gckVGINTERRUPT_Disable(
IN gckVGINTERRUPT Interrupt,
IN gctINT32 Id
);
#ifndef __QNXNTO__
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt
);
#else
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt,
OUT gckOS *Os,
OUT gctSEMAPHORE *Semaphore
);
#endif
gceSTATUS
gckVGINTERRUPT_DumpState(
IN gckVGINTERRUPT Interrupt
);
/******************************************************************************\
******************************* gckVGCOMMAND Object *******************************
\******************************************************************************/
typedef struct _gckVGCOMMAND * gckVGCOMMAND;
/* Construct a new gckVGCOMMAND object. */
gceSTATUS
gckVGCOMMAND_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT TaskGranularity,
IN gctUINT QueueSize,
OUT gckVGCOMMAND * Command
);
/* Destroy an gckVGCOMMAND object. */
gceSTATUS
gckVGCOMMAND_Destroy(
IN gckVGCOMMAND Command
);
/* Query command buffer attributes. */
gceSTATUS
gckVGCOMMAND_QueryCommandBuffer(
IN gckVGCOMMAND Command,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
);
/* Allocate a command queue. */
gceSTATUS
gckVGCOMMAND_Allocate(
IN gckVGCOMMAND Command,
IN gctSIZE_T Size,
OUT gcsCMDBUFFER_PTR * CommandBuffer,
OUT gctPOINTER * Data
);
/* Release memory held by the command queue. */
gceSTATUS
gckVGCOMMAND_Free(
IN gckVGCOMMAND Command,
IN gcsCMDBUFFER_PTR CommandBuffer
);
/* Schedule the command queue for execution. */
gceSTATUS
gckVGCOMMAND_Execute(
IN gckVGCOMMAND Command,
IN gcsCMDBUFFER_PTR CommandBuffer
);
/* Commit a buffer to the command queue. */
gceSTATUS
gckVGCOMMAND_Commit(
IN gckVGCOMMAND Command,
IN gcsVGCONTEXT_PTR Context,
IN gcsVGCMDQUEUE_PTR Queue,
IN gctUINT EntryCount,
IN gcsTASK_MASTER_TABLE_PTR TaskTable
);
/******************************************************************************\
********************************* gckVGMMU Object ********************************
\******************************************************************************/
typedef struct _gckVGMMU * gckVGMMU;
/* Construct a new gckVGMMU object. */
gceSTATUS
gckVGMMU_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT32 MmuSize,
OUT gckVGMMU * Mmu
);
/* Destroy an gckVGMMU object. */
gceSTATUS
gckVGMMU_Destroy(
IN gckVGMMU Mmu
);
/* Allocate pages inside the MMU. */
gceSTATUS
gckVGMMU_AllocatePages(
IN gckVGMMU Mmu,
IN gctSIZE_T PageCount,
OUT gctPOINTER * PageTable,
OUT gctUINT32 * Address
);
/* Remove a page table from the MMU. */
gceSTATUS
gckVGMMU_FreePages(
IN gckVGMMU Mmu,
IN gctPOINTER PageTable,
IN gctSIZE_T PageCount
);
/* Set the MMU page with info. */
gceSTATUS
gckVGMMU_SetPage(
IN gckVGMMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
);
/* Flush MMU */
gceSTATUS
gckVGMMU_Flush(
IN gckVGMMU Mmu
);
#endif /* gcdENABLE_VG */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __gc_hal_h_ */

View File

@ -0,0 +1,119 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_array_h_
#define __gc_hal_kernel_allocator_array_h_
extern gceSTATUS
_GFPAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#ifdef CONFIG_DMA_SHARED_BUFFER
extern gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifndef NO_DMA_COHERENT
extern gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
/* Default allocator entry. */
gcsALLOCATOR_DESC allocatorArray[] =
{
/* GFP allocator. */
gcmkDEFINE_ALLOCATOR_DESC("gfp", _GFPAlloctorInit),
/* User memory importer. */
gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
#ifdef CONFIG_DMA_SHARED_BUFFER
/* Dmabuf allocator. */
gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
#endif
#ifndef NO_DMA_COHERENT
gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
#endif
gcmkDEFINE_ALLOCATOR_DESC("reserved-mem", _ReservedMemoryAllocatorInit),
};
#endif

View File

@ -0,0 +1,604 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)
#include <linux/dma-direct.h>
#endif
#include <linux/slab.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsDMA_PRIV * gcsDMA_PRIV_PTR;
typedef struct _gcsDMA_PRIV {
atomic_t usage;
}
gcsDMA_PRIV;
struct mdl_dma_priv {
gctPOINTER kvaddr;
dma_addr_t dmaHandle;
};
/*
* Debugfs support.
*/
static int gc_dma_usage_show(struct seq_file* m, void* data)
{
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
gcsDMA_PRIV_PTR priv = Allocator->privateData;
long long usage = (long long)atomic_read(&priv->usage);
seq_printf(m, "type n pages bytes\n");
seq_printf(m, "normal %10llu %12llu\n", usage, usage * PAGE_SIZE);
return 0;
}
static gcsINFO InfoList[] =
{
{"dmausage", gc_dma_usage_show},
};
static void
_DebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList),
Allocator
));
}
static void
_DebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_DmaAlloc(
IN gckALLOCATOR Allocator,
INOUT PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flags
)
{
gceSTATUS status;
u32 gfp = GFP_KERNEL | gcdNOWARN;
gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
struct mdl_dma_priv *mdlPriv=gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER_ARG("Mdl=%p NumPages=0x%zx Flags=0x%x", Mdl, NumPages, Flags);
gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_dma_priv), (gctPOINTER *)&mdlPriv));
mdlPriv->kvaddr = gcvNULL;
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
if (Flags & gcvALLOC_FLAG_4GB_ADDR)
{
gfp |= __GFP_DMA32;
}
#endif
mdlPriv->kvaddr
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64
= dma_alloc_coherent(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp);
#else
= dma_alloc_writecombine(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp);
#endif
#ifdef CONFLICT_BETWEEN_BASE_AND_PHYS
if ((os->device->baseAddress & 0x80000000) != (mdlPriv->dmaHandle & 0x80000000))
{
mdlPriv->dmaHandle = (mdlPriv->dmaHandle & ~0x80000000)
| (os->device->baseAddress & 0x80000000);
}
#endif
if (mdlPriv->kvaddr == gcvNULL)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
Mdl->priv = mdlPriv;
Mdl->dmaHandle = mdlPriv->dmaHandle;
/* Statistic. */
atomic_add(NumPages, &allocatorPriv->usage);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (mdlPriv)
{
gckOS_Free(os, mdlPriv);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_DmaGetSGT(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct page ** pages = gcvNULL;
struct page * page = gcvNULL;
struct sg_table *sgt = NULL;
struct mdl_dma_priv *mdlPriv = (struct mdl_dma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gctSIZE_T offset = Offset & ~PAGE_MASK; /* Offset to the first page */
gctINT skipPages = Offset >> PAGE_SHIFT; /* skipped pages */
gctINT numPages = (PAGE_ALIGN(Offset + Bytes) >> PAGE_SHIFT) - skipPages;
gctINT i;
gcmkASSERT(Offset + Bytes <= Mdl->numPages << PAGE_SHIFT);
sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL | gcdNOWARN);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
pages = kmalloc(sizeof(struct page*) * numPages, GFP_KERNEL | gcdNOWARN);
if (!pages)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
#if !defined(phys_to_page)
page = virt_to_page(mdlPriv->kvaddr);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
page = phys_to_page(mdlPriv->dmaHandle);
#else
page = phys_to_page(dma_to_phys(&Allocator->os->device->platform->device->dev, mdlPriv->dmaHandle));
#endif
for (i = 0; i < numPages; ++i)
{
pages[i] = nth_page(page, i + skipPages);
}
if (sg_alloc_table_from_pages(sgt, pages, numPages, offset, Bytes, GFP_KERNEL) < 0)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
*SGT = (gctPOINTER)sgt;
OnError:
if (pages)
{
kfree(pages);
}
if (gcmIS_ERROR(status) && sgt)
{
kfree(sgt);
}
return status;
#else
return gcvSTATUS_NOT_SUPPORTED;
#endif
}
static void
_DmaFree(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64
dma_free_coherent(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
#else
dma_free_writecombine(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
#endif
gckOS_Free(os, mdlPriv);
/* Statistic. */
atomic_sub(Mdl->numPages, &allocatorPriv->usage);
}
static gceSTATUS
_DmaMmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
struct mdl_dma_priv *mdlPriv = (struct mdl_dma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
/* map kernel memory to user space.. */
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC
if (remap_pfn_range(
vma,
vma->vm_start,
(mdlPriv->dmaHandle >> PAGE_SHIFT) + skipPages,
numPages << PAGE_SHIFT,
pgprot_writecombine(vma->vm_page_prot)) < 0)
#else
/* map kernel memory to user space.. */
if (dma_mmap_writecombine(gcvNULL,
vma,
(gctINT8_PTR)mdlPriv->kvaddr + (skipPages << PAGE_SHIFT),
mdlPriv->dmaHandle + (skipPages << PAGE_SHIFT),
numPages << PAGE_SHIFT) < 0)
#endif
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): dma_mmap_attrs error",
__FUNCTION__, __LINE__
);
status = gcvSTATUS_OUT_OF_MEMORY;
}
gcmkFOOTER();
return status;
}
static void
_DmaUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): vm_munmap failed",
__FUNCTION__, __LINE__
);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): do_munmap failed",
__FUNCTION__, __LINE__
);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
_DmaMapUser(
gckALLOCATOR Allocator,
PLINUX_MDL Mdl,
PLINUX_MDL_MAP MdlMap,
gctBOOL Cacheable
)
{
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(_DmaMmap(Allocator, Mdl, Cacheable, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical;
MdlMap->cacheable = gcvFALSE;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
_DmaUnmapUser(Allocator, Mdl, userLogical, Mdl->numPages * PAGE_SIZE);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_DmaMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
)
{
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
*Logical =mdlPriv->kvaddr;
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
)
{
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
*Physical = mdlPriv->dmaHandle + Offset;
return gcvSTATUS_OK;
}
static void
_DmaAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_DebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator operations. */
gcsALLOCATOR_OPERATIONS DmaAllocatorOperations = {
.Alloc = _DmaAlloc,
.Free = _DmaFree,
.Mmap = _DmaMmap,
.MapUser = _DmaMapUser,
.UnmapUser = _DmaUnmapUser,
.MapKernel = _DmaMapKernel,
.UnmapKernel = _DmaUnmapKernel,
.Cache = _DmaCache,
.Physical = _DmaPhysical,
.GetSGT = _DmaGetSGT,
};
/* Default allocator entry. */
gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
gcsDMA_PRIV_PTR priv = gcvNULL;
gcmkONERROR(gckALLOCATOR_Construct(Os, &DmaAllocatorOperations, &allocator));
priv = kzalloc(gcmSIZEOF(gcsDMA_PRIV), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
atomic_set(&priv->usage, 0);
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _DmaAllocatorDestructor;
_DebugfsInit(allocator, Parent);
/*
* DMA allocator is only used for NonPaged memory
* when NO_DMA_COHERENT is not defined.
*/
allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
| gcvALLOC_FLAG_4GB_ADDR
#endif
;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,546 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/dma-buf.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
/* Descriptor of a dma_buf imported. */
typedef struct _gcsDMABUF
{
struct dma_buf * dmabuf;
struct dma_buf_attachment * attachment;
struct sg_table * sgt;
unsigned long * pagearray;
int npages;
int pid;
struct list_head list;
}
gcsDMABUF;
struct allocator_priv
{
struct mutex lock;
struct list_head buf_list;
};
/*
* Debugfs support.
*/
static int dma_buf_info_show(struct seq_file* m, void* data)
{
int ret;
gcsDMABUF *buf_desc;
struct dma_buf_attachment *attach_obj;
int count = 0;
size_t size = 0;
int npages = 0;
const char *exp_name;
gcsINFO_NODE *node = m->private;
gckALLOCATOR allocator = node->device;
struct allocator_priv *priv = allocator->privateData;
ret = mutex_lock_interruptible(&priv->lock);
if (ret)
return ret;
seq_puts(m, "Attached dma-buf objects:\n");
seq_puts(m, " pid fd pages size exporter attached-devices\n");
list_for_each_entry(buf_desc, &priv->buf_list, list) {
struct dma_buf *buf_obj = buf_desc->dmabuf;
ret = mutex_lock_interruptible(&buf_obj->lock);
if (ret) {
seq_puts(m,
"ERROR locking buffer object: skipping\n");
continue;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
exp_name = buf_obj->exp_name;
#else
exp_name = "unknown";
#endif
seq_printf(m, "%6d %p %8d %8zu %10s",
buf_desc->pid,
buf_desc->dmabuf,
buf_desc->npages,
buf_obj->size,
exp_name);
list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
seq_printf(m, " %s", dev_name(attach_obj->dev));
}
seq_puts(m, "\n");
count++;
size += buf_obj->size;
npages += buf_desc->npages;
mutex_unlock(&buf_obj->lock);
}
seq_printf(m, "\nTotal %d objects, %d pages, %zu bytes\n", count, npages, size);
mutex_unlock(&priv->lock);
return 0;
}
static gcsINFO _InfoList[] =
{
{"bufinfo", dma_buf_info_show},
};
static void
_DebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma_buf"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
_InfoList,
gcmCOUNTOF(_InfoList),
Allocator
));
}
static void
_DebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
_InfoList,
gcmCOUNTOF(_InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_DmabufAttach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
gceSTATUS status;
gckOS os = Allocator->os;
struct dma_buf *dmabuf = Desc->dmaBuf.dmabuf;
struct sg_table *sgt = NULL;
struct dma_buf_attachment *attachment = NULL;
int npages = 0;
unsigned long *pagearray = NULL;
int i, j, k = 0;
struct scatterlist *s;
struct allocator_priv *priv = Allocator->privateData;
gcsDMABUF *buf_desc = NULL;
gcmkHEADER();
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
if (!dmabuf)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
get_dma_buf(dmabuf);
attachment = dma_buf_attach(dmabuf, &os->device->platform->device->dev);
if (!attachment)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
/* Prepare page array. */
/* Get number of pages. */
for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
{
npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE;
}
/* Allocate page array. */
gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray));
/* Fill page array. */
for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
{
for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++)
{
pagearray[k++] = sg_dma_address(s) + j * PAGE_SIZE;
}
}
/* Prepare descriptor. */
gcmkONERROR(gckOS_Allocate(os, sizeof(gcsDMABUF), (gctPOINTER *)&buf_desc));
buf_desc->dmabuf = dmabuf;
buf_desc->pagearray = pagearray;
buf_desc->attachment = attachment;
buf_desc->sgt = sgt;
/* Record in buffer list to support debugfs. */
buf_desc->npages = npages;
buf_desc->pid = _GetProcessID();
mutex_lock(&priv->lock);
list_add(&buf_desc->list, &priv->buf_list);
mutex_unlock(&priv->lock);
/* Record page number. */
Mdl->numPages = npages;
Mdl->priv = buf_desc;
Mdl->contiguous = (sgt->nents == 1) ? gcvTRUE : gcvFALSE;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (pagearray)
{
gcmkOS_SAFE_FREE(os, pagearray);
}
if (sgt)
{
dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL);
}
gcmkFOOTER();
return status;
}
static void
_DmabufFree(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gckOS os = Allocator->os;
struct allocator_priv *priv = Allocator->privateData;
mutex_lock(&priv->lock);
list_del(&buf_desc->list);
mutex_unlock(&priv->lock);
dma_buf_unmap_attachment(buf_desc->attachment, buf_desc->sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(buf_desc->dmabuf, buf_desc->attachment);
dma_buf_put(buf_desc->dmabuf);
gckOS_Free(os, buf_desc->pagearray);
gckOS_Free(os, buf_desc);
}
static void
_DmabufUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctINT8_PTR userLogical = MdlMap->vmaAddr;
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
userLogical -= buf_desc->sgt->sgl->offset;
vm_munmap((unsigned long)userLogical, Mdl->numPages << PAGE_SHIFT);
}
static gceSTATUS
_DmabufMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctINT8_PTR userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
userLogical = (gctINT8_PTR)vm_mmap(buf_desc->dmabuf->file,
0L,
Mdl->numPages << PAGE_SHIFT,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
if (IS_ERR(userLogical))
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
userLogical += buf_desc->sgt->sgl->offset;
/* To make sure the mapping is created. */
if (access_ok(VERIFY_READ, userLogical, 4))
{
uint32_t mem;
get_user(mem, (uint32_t *)userLogical);
(void)mem;
}
MdlMap->vmaAddr = (gctPOINTER)userLogical;
MdlMap->cacheable = Cacheable;
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
_DmabufUnmapUser(Allocator, Mdl, MdlMap, Mdl->numPages << PAGE_SHIFT);
}
return status;
}
static gceSTATUS
_DmabufMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_DmabufUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_DmabufCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
)
{
gcsDMABUF *buf_desc = Mdl->priv;
struct sg_table *sgt = buf_desc->sgt;
enum dma_data_direction dir;
switch (Operation)
{
case gcvCACHE_CLEAN:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir);
break;
case gcvCACHE_FLUSH:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir);
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, sgt->sgl, sgt->nents, dir);
break;
case gcvCACHE_INVALIDATE:
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, sgt->sgl, sgt->nents, dir);
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_DmabufPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctUINT32 offsetInPage = Offset & ~PAGE_MASK;
gctUINT32 index = Offset / PAGE_SIZE;
*Physical = buf_desc->pagearray[index] + offsetInPage;
return gcvSTATUS_OK;
}
/* Default allocator operations. */
static gcsALLOCATOR_OPERATIONS DmabufAllocatorOperations =
{
.Attach = _DmabufAttach,
.Free = _DmabufFree,
.MapUser = _DmabufMapUser,
.UnmapUser = _DmabufUnmapUser,
.MapKernel = _DmabufMapKernel,
.UnmapKernel = _DmabufUnmapKernel,
.Cache = _DmabufCache,
.Physical = _DmabufPhysical,
};
static void
_DmabufAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_DebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator entry. */
gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
struct allocator_priv *priv = NULL;
priv = kmalloc(sizeof (struct allocator_priv), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
mutex_init(&priv->lock);
INIT_LIST_HEAD(&priv->buf_list);
gcmkONERROR(
gckALLOCATOR_Construct(Os, &DmabufAllocatorOperations, &allocator));
allocator->capability = gcvALLOC_FLAG_DMABUF
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
;
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _DmabufAllocatorDestructor;
_DebugfsInit(allocator, Parent);
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (priv)
{
kfree(priv);
}
return status;
}

View File

@ -0,0 +1,511 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/ioport.h>
#define _GC_OBJ_ZONE gcvZONE_OS
/*
* reserved_mem is for contiguous pool, internal pool and external pool, etc.
*/
/* mdl private. */
struct reserved_mem
{
unsigned long start;
unsigned long size;
char name[32];
int release;
/* Link together. */
struct list_head link;
};
/* allocator info. */
struct reserved_mem_alloc
{
/* Record allocated reserved memory regions. */
struct list_head region;
struct mutex lock;
};
static int reserved_mem_show(struct seq_file* m, void* data)
{
struct list_head *pos;
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
struct reserved_mem_alloc *alloc = Allocator->privateData;
list_for_each(pos, &alloc->region)
{
struct reserved_mem * res= list_entry(pos, struct reserved_mem, link);
seq_printf(m, "0x%08lx-0x%08lx : %s\n",
res->start, res->start + res->size -1, res->name);
}
return 0;
}
static gcsINFO info_list[] =
{
{"reserved-mem", reserved_mem_show},
};
static void
reserved_mem_debugfs_init(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "reserved-mem"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
info_list,
gcmCOUNTOF(info_list),
Allocator
));
}
static void
reserved_mem_debugfs_cleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
info_list,
gcmCOUNTOF(info_list)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
reserved_mem_attach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
struct reserved_mem_alloc *alloc = Allocator->privateData;
struct reserved_mem *res;
struct resource *region = NULL;
res = kzalloc(sizeof(struct reserved_mem), GFP_KERNEL | gcdNOWARN);
if (!res)
return gcvSTATUS_OUT_OF_MEMORY;
res->start = Desc->reservedMem.start;
res->size = Desc->reservedMem.size;
strncpy(res->name, Desc->reservedMem.name, sizeof(res->name)-1);
res->release = 1;
if (!Desc->reservedMem.requested)
{
region = request_mem_region(res->start, res->size, res->name);
if (!region)
{
printk("request mem %s(0x%lx - 0x%lx) failed\n",
res->name, res->start, res->start + res->size - 1);
kfree(res);
return gcvSTATUS_OUT_OF_RESOURCES;
}
res->release = 1;
}
mutex_lock(&alloc->lock);
list_add(&res->link, &alloc->region);
mutex_unlock(&alloc->lock);
Mdl->priv = res;
return gcvSTATUS_OK;
}
static void
reserved_mem_detach(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
struct reserved_mem_alloc *alloc = Allocator->privateData;
struct reserved_mem *res = Mdl->priv;
/* unlink from region list. */
mutex_lock(&alloc->lock);
list_del_init(&res->link);
mutex_unlock(&alloc->lock);
if (res->release)
{
release_mem_region(res->start, res->size);
}
kfree(res);
}
static gceSTATUS
reserved_mem_mmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
struct reserved_mem *res = (struct reserved_mem*)Mdl->priv;
unsigned long pfn;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
pfn = (res->start >> PAGE_SHIFT) + skipPages;
/* Make this mapping non-cached. */
vma->vm_flags |= gcdVM_FLAGS;
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
pfn, numPages << PAGE_SHIFT, vma->vm_page_prot) < 0)
{
gcmkTRACE(
gcvLEVEL_ERROR,
"%s(%d): remap_pfn_range error.",
__FUNCTION__, __LINE__
);
status = gcvSTATUS_OUT_OF_MEMORY;
}
gcmkFOOTER();
return status;
}
static void
reserved_mem_unmap_user(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
if (unlikely(!current->mm))
return;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr, (unsigned long)Size) < 0)
{
printk("%s: vm_munmap failed\n", __func__);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr, (unsigned long)Size) < 0)
{
printk("%s: do_munmap failed\n", __func__);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
reserved_mem_map_user(
gckALLOCATOR Allocator,
PLINUX_MDL Mdl,
PLINUX_MDL_MAP MdlMap,
gctBOOL Cacheable
)
{
struct reserved_mem *res = (struct reserved_mem*)Mdl->priv;
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(NULL, 0L, res->size,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, 0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(NULL, 0L, res->size,
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(reserved_mem_mmap(Allocator, Mdl, gcvFALSE, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical;
MdlMap->cacheable = gcvFALSE;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
reserved_mem_unmap_user(Allocator, Mdl, userLogical, res->size);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
reserved_mem_map_kernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
)
{
struct reserved_mem *res = Mdl->priv;
void *vaddr;
/* Should never run here now. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)
vaddr = memremap(res->start, res->size, MEMREMAP_WC);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
vaddr = memremap(res->start, res->size, MEMREMAP_WT);
#else
vaddr = ioremap_nocache(res->start, res->size);
#endif
if (!vaddr)
{
return gcvSTATUS_OUT_OF_MEMORY;
}
*Logical = vaddr;
return gcvSTATUS_OK;;
}
static gceSTATUS
reserved_mem_unmap_kernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
memunmap((void *)Logical);
#else
iounmap((void *)Logical);
#endif
return gcvSTATUS_OK;
}
static gceSTATUS
reserved_mem_cache_op(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
)
{
/* Always WC or UC, safe to use mb. */
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
reserved_mem_get_physical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct reserved_mem *res = Mdl->priv;
*Physical = res->start + Offset;
return gcvSTATUS_OK;
}
static void
reserved_mem_dtor(
gcsALLOCATOR *Allocator
)
{
reserved_mem_debugfs_cleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* GFP allocator operations. */
static gcsALLOCATOR_OPERATIONS reserved_mem_ops = {
.Alloc = NULL,
.Attach = reserved_mem_attach,
.Free = reserved_mem_detach,
.Mmap = reserved_mem_mmap,
.MapUser = reserved_mem_map_user,
.UnmapUser = reserved_mem_unmap_user,
.MapKernel = reserved_mem_map_kernel,
.UnmapKernel = reserved_mem_unmap_kernel,
.Cache = reserved_mem_cache_op,
.Physical = reserved_mem_get_physical,
};
/* GFP allocator entry. */
gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
struct reserved_mem_alloc *alloc = NULL;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &reserved_mem_ops, &allocator));
alloc = kzalloc(sizeof(*alloc), GFP_KERNEL | gcdNOWARN);
if (!alloc)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
INIT_LIST_HEAD(&alloc->region);
mutex_init(&alloc->lock);
/* Register private data. */
allocator->privateData = alloc;
allocator->destructor = reserved_mem_dtor;
reserved_mem_debugfs_init(allocator, Parent);
allocator->capability = gcvALLOC_FLAG_LINUX_RESERVED_MEM;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,854 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#define _GC_OBJ_ZONE gcvZONE_ALLOCATOR
enum um_desc_type
{
UM_PHYSICAL_MAP,
UM_PAGE_MAP,
UM_PFN_MAP,
};
#if LINUX_VERSION_CODE < KERNEL_VERSION (2,6,24)
struct sg_table
{
struct scatterlist *sgl;
unsigned int nents;
unsigned int orig_nents;
};
#endif
/* Descriptor of a user memory imported. */
struct um_desc
{
int type;
union
{
/* UM_PHYSICAL_MAP. */
unsigned long physical;
/* UM_PAGE_MAP. */
struct
{
struct page **pages;
struct sg_table sgt;
};
/* UM_PFN_MAP. */
struct
{
unsigned long *pfns;
int *refs;
};
};
/* contiguous chunks, does not include padding pages. */
int chunk_count;
unsigned long vm_flags;
unsigned long user_vaddr;
size_t size;
unsigned long offset;
size_t pageCount;
size_t extraPage;
};
static int import_physical_map(struct um_desc *um, unsigned long phys)
{
um->type = UM_PHYSICAL_MAP;
um->physical = phys & PAGE_MASK;
um->chunk_count = 1;
return 0;
}
static int import_page_map(struct um_desc *um,
unsigned long addr, size_t page_count, size_t size)
{
int i;
int result;
struct page **pages;
pages = kzalloc(page_count * sizeof(void *), GFP_KERNEL | gcdNOWARN);
if (!pages)
return -ENOMEM;
down_read(&current->mm->mmap_sem);
result = get_user_pages(
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
current,
current->mm,
#endif
addr & PAGE_MASK,
page_count,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
FOLL_WRITE,
#else
1,
0,
#endif
pages,
NULL);
up_read(&current->mm->mmap_sem);
if (result < page_count)
{
for (i = 0; i < result; i++)
{
if (pages[i])
{
put_page(pages[i]);
}
}
kfree(pages);
return -ENODEV;
}
um->chunk_count = 1;
for (i = 1; i < page_count; i++)
{
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
{
++um->chunk_count;
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
result = sg_alloc_table_from_pages(&um->sgt, pages, page_count,
addr & ~PAGE_MASK, size, GFP_KERNEL | gcdNOWARN);
#else
result = alloc_sg_list_from_pages(&um->sgt.sgl, pages, page_count,
addr & ~PAGE_MASK, size, &um->sgt.nents);
um->sgt.orig_nents = um->sgt.nents;
#endif
if (unlikely(result < 0))
{
printk("[galcore]: %s: sg_alloc_table_from_pages failed\n", __FUNCTION__);
goto error;
}
result = dma_map_sg(galcore_device, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
if (unlikely(result != um->sgt.nents))
{
printk("[galcore]: %s: dma_map_sg failed\n", __FUNCTION__);
goto error;
}
um->type = UM_PAGE_MAP;
um->pages = pages;
return 0;
error:
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
sg_free_table(&um->sgt);
#else
kfree(um->sgt.sgl);
#endif
if (pages)
{
kfree(pages);
}
return result;
}
static int import_pfn_map(struct um_desc *um,
unsigned long addr, size_t pfn_count)
{
int i;
struct vm_area_struct *vma;
unsigned long *pfns;
int *refs;
if (!current->mm)
return -ENOTTY;
down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, addr);
up_read(&current->mm->mmap_sem);
if (!vma)
return -ENOTTY;
pfns = kzalloc(pfn_count * sizeof(unsigned long), GFP_KERNEL | gcdNOWARN);
if (!pfns)
return -ENOMEM;
refs = kzalloc(pfn_count * sizeof(int), GFP_KERNEL | gcdNOWARN);
if (!refs)
{
kfree(pfns);
return -ENOMEM;
}
for (i = 0; i < pfn_count; i++)
{
spinlock_t *ptl;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pgd = pgd_offset(current->mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto err;
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || pud_bad(*pud))
goto err;
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto err;
pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
if (!pte)
{
spin_unlock(ptl);
goto err;
}
if (!pte_present(*pte))
{
pte_unmap_unlock(pte, ptl);
goto err;
}
pfns[i] = pte_pfn(*pte);
pte_unmap_unlock(pte, ptl);
/* Advance to next. */
addr += PAGE_SIZE;
}
for (i = 0; i < pfn_count; i++)
{
if (pfn_valid(pfns[i]))
{
struct page *page = pfn_to_page(pfns[i]);
refs[i] = get_page_unless_zero(page);
}
}
um->chunk_count = 1;
for (i = 1; i < pfn_count; i++)
{
if (pfns[i] != pfns[i - 1] + 1)
{
++um->chunk_count;
}
}
um->type = UM_PFN_MAP;
um->pfns = pfns;
um->refs = refs;
return 0;
err:
if (pfns)
kfree(pfns);
if (refs)
kfree(refs);
return -ENOTTY;
}
static gceSTATUS
_Import(
IN gckOS Os,
IN gctPOINTER Memory,
IN gctUINT32 Physical,
IN gctSIZE_T Size,
IN struct um_desc * UserMemory
)
{
gceSTATUS status = gcvSTATUS_OK;
unsigned long vm_flags = 0;
struct vm_area_struct *vma = NULL;
unsigned long start, end, memory;
int result = 0;
gctSIZE_T extraPage;
gctSIZE_T pageCount, i;
gcmkHEADER_ARG("Os=0x%p Memory=%p Physical=0x%x Size=%lu", Os, Memory, Physical, Size);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
gcmkVERIFY_ARGUMENT(Size > 0);
memory = (unsigned long)Memory;
/* Get the number of required pages. */
end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
start = memory >> PAGE_SHIFT;
pageCount = end - start;
/* Allocate extra page to avoid cache overflow */
#if gcdENABLE_2D
extraPage = 2;
#else
extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, _GC_OBJ_ZONE,
"%s(%d): pageCount: %d. extraPage: %d",
__FUNCTION__, __LINE__,
pageCount, extraPage
);
/* Overflow. */
if ((memory + Size) < memory)
{
gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
return gcvSTATUS_INVALID_ARGUMENT;
}
if (memory)
{
unsigned long vaddr = memory;
for (i = 0; i < pageCount; i++)
{
u32 data;
get_user(data, (u32 *)vaddr);
put_user(data, (u32 *)vaddr);
vaddr += PAGE_SIZE;
/* Fix QM crash with test_buffers */
if (vaddr > memory + Size - 4)
{
vaddr = memory + Size - 4;
}
}
vma = find_vma(current->mm, memory);
if (!vma)
{
/* No such memory, or across vmas. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
#ifdef CONFIG_ARM
/* coherent cache in case vivt or vipt-aliasing cache. */
__cpuc_flush_user_range(memory, memory + Size, vma->vm_flags);
#endif
vm_flags = vma->vm_flags;
vaddr = vma->vm_end;
while (vaddr < memory + Size)
{
vma = find_vma(current->mm, vaddr);
if (!vma)
{
/* No such memory. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if ((vma->vm_flags & VM_PFNMAP) != (vm_flags & VM_PFNMAP))
{
/* Can not support different map type: both PFN and PAGE detected. */
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
vaddr = vma->vm_end;
}
}
if (Physical != gcvINVALID_PHYSICAL_ADDRESS)
{
result = import_physical_map(UserMemory, Physical);
}
else
{
if (vm_flags & VM_PFNMAP)
{
result = import_pfn_map(UserMemory, memory, pageCount);
}
else
{
result = import_page_map(UserMemory, memory, pageCount, Size);
}
}
if (result == -EINVAL)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
else if (result == -ENOMEM)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
else if (result < 0)
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
if(Os->device->platform->flagBits & gcvPLATFORM_FLAG_LIMIT_4G_ADDRESS )
{
gctPHYS_ADDR_T addr;
if (Physical != gcvINVALID_PHYSICAL_ADDRESS)
{
if(Physical >0xFFFFFFFFu || Physical + Size > 0xFFFFFFFFu )
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
else if (vm_flags & VM_PFNMAP)
{
for(i = 0; i < pageCount; i++)
{
addr = UserMemory->pfns[i] << PAGE_SHIFT;
if( addr > 0xFFFFFFFFu)
{
kfree(UserMemory->pfns);
UserMemory->pfns = gcvNULL;
kfree(UserMemory->refs) ;
UserMemory->refs = gcvNULL;
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
}
else
{
for (i = 0; i< pageCount; i++)
{
addr = page_to_phys(UserMemory->pages[i]);
if(addr > 0xFFFFFFFFu )
{
kfree(UserMemory->pages);
UserMemory->pages = gcvNULL;
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
}
}
UserMemory->vm_flags = vm_flags;
UserMemory->user_vaddr = (unsigned long)Memory;
UserMemory->size = Size;
UserMemory->offset = (Physical != gcvINVALID_PHYSICAL_ADDRESS)
? (Physical & ~PAGE_MASK)
: (memory & ~PAGE_MASK);
UserMemory->pageCount = pageCount;
UserMemory->extraPage = extraPage;
if (extraPage && UserMemory->type == UM_PAGE_MAP)
{
/*Add the padding pages */
UserMemory->chunk_count++;
}
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
static gceSTATUS
_UserMemoryAttach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
gceSTATUS status;
struct um_desc * userMemory = gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER();
/* Handle is meangless for this importer. */
gcmkVERIFY_ARGUMENT(Desc != gcvNULL);
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct um_desc), (gctPOINTER *)&userMemory));
gckOS_ZeroMemory(userMemory, gcmSIZEOF(struct um_desc));
gcmkONERROR(_Import(os, Desc->userMem.memory, Desc->userMem.physical, Desc->userMem.size, userMemory));
Mdl->priv = userMemory;
Mdl->numPages = userMemory->pageCount + userMemory->extraPage;
Mdl->contiguous = (userMemory->chunk_count == 1);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (userMemory != gcvNULL)
{
gckOS_Free(os,(gctPOINTER)userMemory);
}
gcmkFOOTER();
return status;
}
static void release_physical_map(struct um_desc *um)
{
}
static void release_page_map(struct um_desc *um)
{
int i;
dma_unmap_sg(galcore_device, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
sg_free_table(&um->sgt);
#else
kfree(um->sgt.sgl);
#endif
for (i = 0; i < um->pageCount; i++)
{
if (!PageReserved(um->pages[i]))
{
SetPageDirty(um->pages[i]);
}
put_page(um->pages[i]);
}
kfree(um->pages);
}
static void release_pfn_map(struct um_desc *um)
{
int i;
for (i = 0; i < um->pageCount; i++)
{
if (pfn_valid(um->pfns[i]))
{
struct page *page = pfn_to_page(um->pfns[i]);
if (!PageReserved(page))
{
SetPageDirty(page);
}
if (um->refs[i])
{
put_page(page);
}
}
}
kfree(um->pfns);
kfree(um->refs);
}
static void
_UserMemoryFree(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct um_desc *userMemory = Mdl->priv;
gcmkHEADER();
if (userMemory)
{
switch (userMemory->type)
{
case UM_PHYSICAL_MAP:
release_physical_map(userMemory);
break;
case UM_PAGE_MAP:
release_page_map(userMemory);
break;
case UM_PFN_MAP:
release_pfn_map(userMemory);
break;
}
gcmkOS_SAFE_FREE(os, userMemory);
}
gcmkFOOTER_NO();
}
static gceSTATUS
_UserMemoryMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
struct um_desc *userMemory = Mdl->priv;
MdlMap->vmaAddr = (gctPOINTER)userMemory->user_vaddr;
MdlMap->cacheable = gcvTRUE;
return gcvSTATUS_OK;
}
static void
_UserMemoryUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
return;
}
static gceSTATUS
_UserMemoryMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_UserMemoryUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_UserMemoryCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
)
{
struct um_desc *um = Mdl->priv;
enum dma_data_direction dir;
if (um->type != UM_PAGE_MAP)
{
_MemoryBarrier();
return gcvSTATUS_OK;
}
#ifdef CONFIG_ARM
/* coherent cache in case vivt or vipt-aliasing cache. */
__cpuc_flush_user_range(um->user_vaddr,
um->user_vaddr + um->size, um->vm_flags);
#endif
switch (Operation)
{
case gcvCACHE_CLEAN:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
case gcvCACHE_FLUSH:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
case gcvCACHE_INVALIDATE:
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_UserMemoryPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
gckOS os = Allocator->os;
struct um_desc *userMemory = Mdl->priv;
unsigned long offset = Offset + userMemory->offset;
gctUINT32 offsetInPage = offset & ~PAGE_MASK;
gctUINT32 index = offset / PAGE_SIZE;
if (index >= userMemory->pageCount)
{
if (index < userMemory->pageCount + userMemory->extraPage)
{
*Physical = page_to_phys(os->paddingPage);
}
else
{
return gcvSTATUS_INVALID_ARGUMENT;
}
}
else
{
switch (userMemory->type)
{
case UM_PHYSICAL_MAP:
*Physical = userMemory->physical + index * PAGE_SIZE;
break;
case UM_PAGE_MAP:
*Physical = page_to_phys(userMemory->pages[index]);
break;
case UM_PFN_MAP:
*Physical = userMemory->pfns[index] << PAGE_SHIFT;
break;
}
}
*Physical += offsetInPage;
return gcvSTATUS_OK;
}
static void
_UserMemoryAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* User memory allocator (importer) operations. */
static gcsALLOCATOR_OPERATIONS UserMemoryAllocatorOperations =
{
.Attach = _UserMemoryAttach,
.Free = _UserMemoryFree,
.MapUser = _UserMemoryMapUser,
.UnmapUser = _UserMemoryUnmapUser,
.MapKernel = _UserMemoryMapKernel,
.UnmapKernel = _UserMemoryUnmapKernel,
.Cache = _UserMemoryCache,
.Physical = _UserMemoryPhysical,
};
/* Default allocator entry. */
gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &UserMemoryAllocatorOperations, &allocator));
allocator->destructor = _UserMemoryAllocatorDestructor;
allocator->capability = gcvALLOC_FLAG_USERMEMORY;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
return status;
}

View File

@ -0,0 +1,131 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_array_h_
#define __gc_hal_kernel_allocator_array_h_
extern gceSTATUS
_GFPAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#if LINUX_CMA_FSL
extern gceSTATUS
_CMAFSLAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifdef CONFIG_DMA_SHARED_BUFFER
extern gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifndef NO_DMA_COHERENT
extern gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
gcsALLOCATOR_DESC allocatorArray[] =
{
/* GFP allocator. */
gcmkDEFINE_ALLOCATOR_DESC("gfp", _GFPAlloctorInit),
#if LINUX_CMA_FSL
gcmkDEFINE_ALLOCATOR_DESC("cmafsl", _CMAFSLAlloctorInit),
#endif
/* User memory importer. */
gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
#ifdef CONFIG_DMA_SHARED_BUFFER
/* Dmabuf allocator. */
gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
#endif
#ifndef NO_DMA_COHERENT
gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
#endif
gcmkDEFINE_ALLOCATOR_DESC("reserved-mem", _ReservedMemoryAllocatorInit),
};
#endif

View File

@ -0,0 +1,603 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsCMA_PRIV * gcsCMA_PRIV_PTR;
typedef struct _gcsCMA_PRIV {
atomic_t cmasize;
gctBOOL cmaLimitRequest;
}
gcsCMA_PRIV;
struct mdl_cma_priv {
gctPOINTER kvaddr;
dma_addr_t physical;
};
static int gc_cma_usage_show(struct seq_file* m, void* data)
{
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
gcsCMA_PRIV_PTR priv = Allocator->privateData;
long long size = (long long)atomic_read(&priv->cmasize);
seq_printf(m, "type n pages bytes\n");
seq_printf(m, "cma %10llu %12llu\n", size, size * PAGE_SIZE);
return 0;
}
static gcsINFO InfoList[] =
{
{"cmausage", gc_cma_usage_show},
};
static void
_CMAAllocatorDebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "cma"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList),
Allocator
));
}
static void
_CMAAllocatorDebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_CMAFSLAlloc(
IN gckALLOCATOR Allocator,
INOUT PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flags
)
{
gceSTATUS status;
u32 gfp = GFP_KERNEL | gcdNOWARN;
gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
struct mdl_cma_priv *mdl_priv=gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER_ARG("Mdl=%p NumPages=0x%zx", Mdl, NumPages);
if (os->allocatorLimitMarker && !(Flags & gcvALLOC_FLAG_CMA_PREEMPT))
{
if (Flags & gcvALLOC_FLAG_CMA_LIMIT)
{
priv->cmaLimitRequest = gcvTRUE;
}
else if (priv->cmaLimitRequest == gcvTRUE)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
}
gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_cma_priv), (gctPOINTER *)&mdl_priv));
mdl_priv->kvaddr = gcvNULL;
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
if (Flags & gcvALLOC_FLAG_4GB_ADDR)
{
gfp |= __GFP_DMA32;
}
#endif
mdl_priv->kvaddr = dma_alloc_writecombine(&os->device->platform->device->dev,
NumPages * PAGE_SIZE,
&mdl_priv->physical,
gfp);
if (mdl_priv->kvaddr == gcvNULL)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
Mdl->priv = mdl_priv;
Mdl->dmaHandle = mdl_priv->physical;
atomic_add(NumPages, &priv->cmasize);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (mdl_priv)
{
gckOS_Free(os, mdl_priv);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_CMAFSLGetSGT(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct page ** pages = gcvNULL;
struct page * page = gcvNULL;
struct sg_table *sgt = NULL;
struct mdl_cma_priv *mdl_priv = (struct mdl_cma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gctSIZE_T offset = Offset & ~PAGE_MASK; /* Offset to the first page */
gctINT skipPages = Offset >> PAGE_SHIFT; /* skipped pages */
gctINT numPages = (PAGE_ALIGN(Offset + Bytes) >> PAGE_SHIFT) - skipPages;
gctINT i;
gcmkASSERT(Offset + Bytes <= Mdl->numPages << PAGE_SHIFT);
sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL | gcdNOWARN);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
pages = kmalloc(sizeof(struct page*) * numPages, GFP_KERNEL | gcdNOWARN);
if (!pages)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
#if !defined(phys_to_page)
page = virt_to_page(mdlPriv->kvaddr);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
page = phys_to_page(mdlPriv->physical);
#else
page = phys_to_page(dma_to_phys(&Allocator->os->device->platform->device->dev, mdl_priv->physical));
#endif
for (i = 0; i < numPages; ++i)
{
pages[i] = nth_page(page, i + skipPages);
}
if (sg_alloc_table_from_pages(sgt, pages, numPages, offset, Bytes, GFP_KERNEL) < 0)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
*SGT = (gctPOINTER)sgt;
OnError:
if (pages)
{
kfree(pages);
}
if (gcmIS_ERROR(status) && sgt)
{
kfree(sgt);
}
return status;
#else
return gcvSTATUS_NOT_SUPPORTED;
#endif
}
static void
_CMAFSLFree(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct mdl_cma_priv *mdlPriv=(struct mdl_cma_priv *)Mdl->priv;
gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
dma_free_writecombine(&os->device->platform->device->dev,
Mdl->numPages * PAGE_SIZE,
mdlPriv->kvaddr,
mdlPriv->physical);
gckOS_Free(os, mdlPriv);
atomic_sub(Mdl->numPages, &priv->cmasize);
}
static gceSTATUS
_CMAFSLMmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
gckOS os = Allocator->os;
struct mdl_cma_priv *mdlPriv = (struct mdl_cma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
/* Now map all the vmalloc pages to this user address. */
if (Mdl->contiguous)
{
/* map kernel memory to user space.. */
if (dma_mmap_writecombine(&os->device->platform->device->dev,
vma,
(gctINT8_PTR)mdlPriv->kvaddr + (skipPages << PAGE_SHIFT),
mdlPriv->physical + (skipPages << PAGE_SHIFT),
numPages << PAGE_SHIFT) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): dma_mmap_attrs error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
}
else
{
gcmkFATAL("%s(%d): unexpected noncontiguous mdl\n");
gcmkONERROR(gcvSTATUS_HEAP_CORRUPTED);
}
OnError:
gcmkFOOTER();
return status;
}
static void
_CMAFSLUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): vm_munmap failed",
__FUNCTION__, __LINE__
);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): do_munmap failed",
__FUNCTION__, __LINE__
);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
_CMAFSLMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(_CMAFSLMmap(Allocator, Mdl, Cacheable, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical;
MdlMap->cacheable = Cacheable;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
_CMAFSLUnmapUser(Allocator, Mdl, userLogical, Mdl->numPages * PAGE_SIZE);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_CMAMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
)
{
struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
*Logical =mdl_priv->kvaddr;
return gcvSTATUS_OK;
}
static gceSTATUS
_CMAUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
return gcvSTATUS_OK;
}
static gceSTATUS
_CMACache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
)
{
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_CMAPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
*Physical = mdl_priv->physical + Offset;
return gcvSTATUS_OK;
}
static void
_CMAAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_CMAAllocatorDebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator operations. */
static gcsALLOCATOR_OPERATIONS CMAFSLAllocatorOperations =
{
.Alloc = _CMAFSLAlloc,
.Free = _CMAFSLFree,
.Mmap = _CMAFSLMmap,
.MapUser = _CMAFSLMapUser,
.UnmapUser = _CMAFSLUnmapUser,
.MapKernel = _CMAMapKernel,
.UnmapKernel = _CMAUnmapKernel,
.Cache = _CMACache,
.Physical = _CMAPhysical,
.GetSGT = _CMAFSLGetSGT,
};
/* Default allocator entry. */
gceSTATUS
_CMAFSLAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
gcsCMA_PRIV_PTR priv = gcvNULL;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &CMAFSLAllocatorOperations, &allocator));
priv = kzalloc(gcmSIZEOF(gcsCMA_PRIV), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
atomic_set(&priv->cmasize, 0);
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _CMAAllocatorDestructor;
_CMAAllocatorDebugfsInit(allocator, Parent);
allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
| gcvALLOC_FLAG_4GB_ADDR
#endif
;
#if defined(CONFIG_ARM64)
Os->allocatorLimitMarker = (Os->device->baseAddress + totalram_pages * PAGE_SIZE) > 0x100000000;
#else
Os->allocatorLimitMarker = gcvFALSE;
#endif
priv->cmaLimitRequest = gcvFALSE;
if (Os->allocatorLimitMarker)
{
allocator->capability |= gcvALLOC_FLAG_CMA_LIMIT;
}
allocator->capability |= gcvALLOC_FLAG_CMA_PREEMPT;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,260 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
#include <linux/anon_inodes.h>
#endif
#include <linux/file.h>
#include "gc_hal_kernel_allocator_array.h"
#include "gc_hal_kernel_platform.h"
#define _GC_OBJ_ZONE gcvZONE_OS
/******************************************************************************\
******************************** Debugfs Support *******************************
\******************************************************************************/
static gceSTATUS
_AllocatorDebugfsInit(
IN gckOS Os
)
{
gceSTATUS status;
gckGALDEVICE device = Os->device;
gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
gcmkONERROR(gckDEBUGFS_DIR_Init(dir, device->debugfsDir.root, "allocators"));
return gcvSTATUS_OK;
OnError:
return status;
}
static void
_AllocatorDebugfsCleanup(
IN gckOS Os
)
{
gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
gckDEBUGFS_DIR_Deinit(dir);
}
/***************************************************************************\
************************ Allocator management *******************************
\***************************************************************************/
gceSTATUS
gckOS_ImportAllocators(
gckOS Os
)
{
gceSTATUS status;
gctUINT i;
gckALLOCATOR allocator;
_AllocatorDebugfsInit(Os);
INIT_LIST_HEAD(&Os->allocatorList);
for (i = 0; i < gcmCOUNTOF(allocatorArray); i++)
{
if (allocatorArray[i].construct)
{
/* Construct allocator. */
status = allocatorArray[i].construct(Os, &Os->allocatorDebugfsDir, &allocator);
if (gcmIS_ERROR(status))
{
gcmkPRINT("["DEVICE_NAME"]: Can't construct allocator(%s)",
allocatorArray[i].name);
continue;
}
allocator->name = allocatorArray[i].name;
list_add_tail(&allocator->link, &Os->allocatorList);
}
}
#if gcdDEBUG
list_for_each_entry(allocator, &Os->allocatorList, link)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d) Allocator: %s",
__FUNCTION__, __LINE__,
allocator->name
);
}
#endif
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_FreeAllocators(
gckOS Os
)
{
gckALLOCATOR allocator;
gckALLOCATOR temp;
list_for_each_entry_safe(allocator, temp, &Os->allocatorList, link)
{
list_del(&allocator->link);
/* Destroy allocator. */
allocator->destructor(allocator);
}
_AllocatorDebugfsCleanup(Os);
return gcvSTATUS_OK;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION (3,6,0) \
|| (!defined (ARCH_HAS_SG_CHAIN) && !defined (CONFIG_ARCH_HAS_SG_CHAIN))
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
static inline void sg_set_page(struct scatterlist *sg, struct page *page,
unsigned int len, unsigned int offset)
{
sg->page = page;
sg->offset = offset;
sg->length = len;
}
static inline void sg_mark_end(struct scatterlist *sg)
{
(void)sg;
}
# endif
int
alloc_sg_list_from_pages(
struct scatterlist **sgl,
struct page **pages,
unsigned int n_pages,
unsigned long offset,
unsigned long size,
unsigned int *nents
)
{
unsigned int chunks;
unsigned int i;
unsigned int cur_page;
struct scatterlist *s;
chunks = 1;
for (i = 1; i < n_pages; ++i)
{
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
{
++chunks;
}
}
s = kzalloc(sizeof(struct scatterlist) * chunks, GFP_KERNEL);
if (unlikely(!s))
{
return -ENOMEM;
}
*sgl = s;
*nents = chunks;
cur_page = 0;
for (i = 0; i < chunks; i++, s++)
{
unsigned long chunk_size;
unsigned int j;
for (j = cur_page + 1; j < n_pages; j++)
{
if (page_to_pfn(pages[j]) != page_to_pfn(pages[j - 1]) + 1)
{
break;
}
}
chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset;
sg_set_page(s, pages[cur_page], min(size, chunk_size), offset);
size -= chunk_size;
offset = 0;
cur_page = j;
}
sg_mark_end(s - 1);
return 0;
}
#endif

View File

@ -0,0 +1,572 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_h_
#define __gc_hal_kernel_allocator_h_
#include "gc_hal_kernel_linux.h"
#include <linux/slab.h>
#include <linux/mm_types.h>
typedef struct _gcsALLOCATOR * gckALLOCATOR;
typedef union _gcsATTACH_DESC * gcsATTACH_DESC_PTR;
typedef struct _gcsALLOCATOR_OPERATIONS
{
/**************************************************************************
**
** Alloc
**
** Allocte memory, request size is page aligned.
**
** INPUT:
**
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_Mdl
** Pointer to Mdl whichs stores information
** about allocated memory.
**
** gctSIZE_T NumPages
** Number of pages need to allocate.
**
** gctUINT32 Flag
** Allocation option.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS
(*Alloc)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flag
);
/**************************************************************************
**
** Free
**
** Free memory.
**
** INPUT:
**
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Mdl which stores information.
**
** OUTPUT:
**
** Nothing.
**
*/
void
(*Free)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
);
/**************************************************************************
**
** Mmap
**
** Map a page range of the memory to user space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl.
**
** gctSIZE_T skipPages
** Number of page to be skipped from beginning of this memory.
**
** gctSIZE_T numPages
** Number of pages to be mapped from skipPages.
**
** INOUT:
**
** struct vm_area_struct *vma
** Pointer to VMM memory area.
**
*/
gceSTATUS
(*Mmap)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
);
/**************************************************************************
**
** MapUser
**
** Map memory to user space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl.
**
** gctBOOL Cacheable
** Whether this mapping is cacheable.
**
** OUTPUT:
**
** gctPOINTER * UserLogical
** Pointer to user logical address.
**
** Nothing.
**
*/
gceSTATUS
(*MapUser)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
);
/**************************************************************************
**
** UnmapUser
**
** Unmap address from user address space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctPOINTER Logical
** Address to be unmap
**
** gctUINT32 Size
** Size of address space
**
** OUTPUT:
**
** Nothing.
**
*/
void
(*UnmapUser)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
);
/**************************************************************************
**
** MapKernel
**
** Map memory to kernel space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** OUTPUT:
** gctPOINTER * Logical
** Mapped kernel address.
*/
gceSTATUS
(*MapKernel)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
OUT gctPOINTER *Logical
);
/**************************************************************************
**
** UnmapKernel
**
** Unmap memory from kernel space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctPOINTER Logical
** Mapped kernel address.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS
(*UnmapKernel)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
);
/**************************************************************************
**
** Cache
**
** Maintain cache coherency.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctSIZE_T Offset
** Offset to this memory block
**
** gctPOINTER Logical
** Logical address, could be user address or kernel address
**
** gctUINT32 Bytes
** Size of memory region.
**
** gceCACHEOPERATION Opertaion
** Cache operation.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS (*Cache)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctUINT32 Bytes,
IN gceCACHEOPERATION Operation
);
/**************************************************************************
**
** Physical
**
** Get physical address from a offset in memory region.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctUINT32 Offset
** Offset in this memory region.
**
** OUTPUT:
** gctUINT32_PTR Physical
** Physical address.
**
*/
gceSTATUS (*Physical)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
);
/**************************************************************************
**
** Attach
**
** Import memory allocated by an external allocator.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctUINT32 Handle
** Handle of the memory.
**
** OUTPUT:
** None.
**
*/
gceSTATUS (*Attach)(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
OUT PLINUX_MDL Mdl
);
/**************************************************************************
**
** GetSGT
**
** Get scatter-gather table from a range of the memory.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctUINT32 Handle
** Handle of the memory.
**
** gctSIZE_T Offset
** Offset to the beginning of this mdl.
**
** gctSIZE_T Bytes
** Total bytes form Offset.
**
** OUTPUT:
** gctPOINTER *SGT
** scatter-gather table
**
*/
gceSTATUS (*GetSGT)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
);
}
gcsALLOCATOR_OPERATIONS;
typedef struct _gcsALLOCATOR
{
/* Pointer to gckOS Object. */
gckOS os;
/* Name. */
gctSTRING name;
/* Operations. */
gcsALLOCATOR_OPERATIONS * ops;
/* Capability of this allocator. */
gctUINT32 capability;
/* Debugfs entry of this allocator. */
gcsDEBUGFS_DIR debugfsDir;
/* Private data used by customer allocator. */
void * privateData;
/* Allocator destructor. */
void (*destructor)(struct _gcsALLOCATOR *);
struct list_head link;
}
gcsALLOCATOR;
typedef struct _gcsALLOCATOR_DESC
{
/* Name of a allocator. */
char * name;
/* Entry function to construct a allocator. */
gceSTATUS (*construct)(gckOS, gcsDEBUGFS_DIR *, gckALLOCATOR *);
}
gcsALLOCATOR_DESC;
typedef union _gcsATTACH_DESC
{
/* gcvALLOC_FLAG_DMABUF */
struct
{
gctPOINTER dmabuf;
}
dmaBuf;
/* gcvALLOC_FLAG_USERMEMORY */
struct
{
gctPOINTER memory;
gctPHYS_ADDR_T physical;
gctSIZE_T size;
}
userMem;
/* gcvALLOC_FLAG_EXTERNAL_MEMORY */
struct
{
gcsEXTERNAL_MEMORY_INFO info;
}
externalMem;
/* Reserved memory. */
struct
{
unsigned long start;
unsigned long size;
const char * name;
int requested;
}
reservedMem;
}
gcsATTACH_DESC;
/*
* Helpers
*/
/* Fill a gcsALLOCATOR_DESC structure. */
#define gcmkDEFINE_ALLOCATOR_DESC(Name, Construct) \
{ \
.name = Name, \
.construct = Construct, \
}
/* Construct a allocator. */
static inline gceSTATUS
gckALLOCATOR_Construct(
IN gckOS Os,
IN gcsALLOCATOR_OPERATIONS * Operations,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
gcmkASSERT(Allocator != gcvNULL);
gcmkASSERT
( Operations
&& (Operations->Alloc || Operations->Attach)
&& (Operations->Free)
&& Operations->MapUser
&& Operations->UnmapUser
&& Operations->MapKernel
&& Operations->UnmapKernel
&& Operations->Cache
&& Operations->Physical
);
allocator = kzalloc(sizeof(gcsALLOCATOR), GFP_KERNEL | gcdNOWARN);
if (unlikely(!allocator))
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
/* Record os. */
allocator->os = Os;
/* Set operations. */
allocator->ops = Operations;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
return status;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION (3,6,0) \
|| (!defined (ARCH_HAS_SG_CHAIN) && !defined (CONFIG_ARCH_HAS_SG_CHAIN))
int
alloc_sg_list_from_pages(
struct scatterlist **sgl,
struct page **pages,
unsigned int n_pages,
unsigned long offset,
unsigned long size,
unsigned int *nents
);
#endif
/*
How to implement customer allocator
Build in customer alloctor
It is recommanded that customer allocator is implmented in independent
source file(s) which is specified by CUSOMTER_ALLOCATOR_OBJS in Kbuld.
Register gcsALLOCATOR
For each customer specified allocator, a desciption entry must be added
to allocatorArray defined in gc_hal_kernel_allocator_array.h.
An entry in allocatorArray is a gcsALLOCATOR_DESC structure which describes
name and constructor of a gckALLOCATOR object.
Implement gcsALLOCATOR_DESC.init()
In gcsALLOCATOR_DESC.init(), gckALLOCATOR_Construct should be called
to create a gckALLOCATOR object, customer specified private data can
be put in gcsALLOCATOR.privateData.
Implement gcsALLOCATOR_OPERATIONS
When call gckALLOCATOR_Construct to create a gckALLOCATOR object, a
gcsALLOCATOR_OPERATIONS structure must be provided whose all members
implemented.
*/
#endif

View File

@ -0,0 +1,151 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_debug_h_
#define __gc_hal_kernel_debug_h_
#include <gc_hal_kernel_linux.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#include <stdarg.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
#include <linux/nmi.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
****************************** OS-dependent Macros *****************************
\******************************************************************************/
typedef va_list gctARGUMENTS;
#define gcmkARGUMENTS_START(Arguments, Pointer) \
va_start(Arguments, Pointer)
#define gcmkARGUMENTS_END(Arguments) \
va_end(Arguments)
#define gcmkARGUMENTS_ARG(Arguments, Type) \
va_arg(Arguments, Type)
#define gcmkDECLARE_MUTEX(__mutex__) \
DEFINE_MUTEX(__mutex__); \
#define gcmkMUTEX_LOCK(__mutex__) \
mutex_lock(&__mutex__);
#define gcmkMUTEX_UNLOCK(__mutex__) \
mutex_unlock(&__mutex__);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
# define gcmkGETPROCESSID() \
task_tgid_vnr(current)
#else
# define gcmkGETPROCESSID() \
current->tgid
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
# define gcmkGETTHREADID() \
task_pid_vnr(current)
#else
# define gcmkGETTHREADID() \
current->pid
#endif
#define gcmkOUTPUT_STRING(String) \
if (gckDEBUGFS_IsEnabled()) \
{ \
while (-ERESTARTSYS == gckDEBUGFS_Print(String)); \
} \
else \
{ \
printk(String); \
}
#define gcmkSPRINTF(Destination, Size, Message, Value) \
snprintf(Destination, Size, Message, Value)
#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
snprintf(Destination, Size, Message, Value1, Value2)
#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
snprintf(Destination, Size, Message, Value1, Value2, Value3)
#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
#define gcmkSTRCATSAFE(Destination, Size, String) \
strncat(Destination, String, (Size) - 1)
#define gcmkMEMCPY(Destination, Source, Size) \
memcpy(Destination, Source, Size)
#define gcmkSTRLEN(String) \
strlen(String)
/* If not zero, forces data alignment in the variable argument list
by its individual size. */
#define gcdALIGNBYSIZE 1
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_debug_h_ */

View File

@ -0,0 +1,965 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef MODULE
#include <linux/module.h>
#endif
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/completion.h>
#include <linux/seq_file.h>
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_debug.h"
/*
Prequsite:
1) Debugfs feature must be enabled in the kernel.
1.a) You can enable this, in the compilation of the uImage, all you have to do is, In the "make menuconfig" part,
you have to enable the debugfs in the kernel hacking part of the menu.
HOW TO USE:
1) insert the driver with the following option logFileSize, Ex: insmod galcore.ko ...... logFileSize=10240
This gives a circular buffer of 10 MB
2)Usually after inserting the driver, the debug file system is mounted under /sys/kernel/debug/
2.a)If the debugfs is not mounted, you must do "mount -t debugfs none /sys/kernel/debug"
3) To read what is being printed in the debugfs file system:
Ex : cat /sys/kernel/debug/gc/galcore_trace
4)To write into the debug file system from user side :
Ex: echo "hello" > cat /sys/kernel/debug/gc/galcore_trace
5)To write into debugfs from kernel side, Use the function called gckDEBUGFS_Print
How to Get Video Memory Usage:
1) Select a process whose video memory usage can be dump, no need to reset it until <pid> is needed to be change.
echo <pid> > /sys/kernel/debug/gc/vidmem
2) Get video memory usage.
cat /sys/kernel/debug/gc/vidmem
USECASE Kernel Dump:
1) Go to /hal/inc/gc_hal_options.h, and enable the following flags:
- # define gcdDUMP 1
- # define gcdDUMP_IN_KERNEL 1
- # define gcdDUMP_COMMAND 1
2) Go to /hal/kernel/gc_hal_kernel_command.c and disable the following flag
-#define gcdSIMPLE_COMMAND_DUMP 0
3) Compile the driver
4) insmod it with the logFileSize option
5) Run an application
6) You can get the dump by cat /sys/kernel/debug/gpu/galcore_trace
*/
/**/
typedef va_list gctDBGARGS ;
#define gcmkARGS_START(argument, pointer) va_start(argument, pointer)
#define gcmkARGS_END(argument) va_end(argument)
#define gcmkDEBUGFS_PRINT(ArgumentSize, Message) \
{ \
gctDBGARGS __arguments__; \
gcmkARGS_START(__arguments__, Message); \
_debugfs_res = _DebugFSPrint(ArgumentSize, Message, &__arguments__);\
gcmkARGS_END(__arguments__); \
}
static DEFINE_SPINLOCK(traceLock);
/* Debug File System Node Struct. */
struct _gcsDEBUGFS_Node
{
/*wait queues for read and write operations*/
#if defined(DECLARE_WAIT_QUEUE_HEAD)
wait_queue_head_t read_q , write_q ;
#else
struct wait_queue *read_q , *write_q ;
#endif
struct dentry *parent ; /*parent directory*/
struct dentry *filen ; /*filename*/
struct semaphore sem ; /* mutual exclusion semaphore */
char *data ; /* The circular buffer data */
int size ; /* Size of the buffer pointed to by 'data' */
int refcount ; /* Files that have this buffer open */
int read_point ; /* Offset in circ. buffer of oldest data */
int write_point ; /* Offset in circ. buffer of newest data */
int offset ; /* Byte number of read_point in the stream */
struct _gcsDEBUGFS_Node *next ;
caddr_t temp;
int tempSize;
};
/* amount of data in the queue */
#define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
(node)->write_point - (node)->read_point : \
(node)->size - (node)->read_point + (node)->write_point)
/* byte number of the last byte in the queue */
#define gcmkNODE_FIRST_EMPTY_BYTE(node) ((node)->offset + gcmkNODE_QLEN(node))
/*Synchronization primitives*/
#define gcmkNODE_READQ(node) (&((node)->read_q))
#define gcmkNODE_WRITEQ(node) (&((node)->write_q))
#define gcmkNODE_SEM(node) (&((node)->sem))
/*Utilities*/
#define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
/*Debug File System Struct*/
typedef struct _gcsDEBUGFS_
{
gcsDEBUGFS_Node* linkedlist ;
gcsDEBUGFS_Node* currentNode ;
int isInited ;
} gcsDEBUGFS_ ;
/*debug file system*/
static gcsDEBUGFS_ gc_dbgfs ;
static int gc_debugfs_open(struct inode *inode, struct file *file)
{
gcsINFO_NODE *node = inode->i_private;
return single_open(file, node->info->show, node);
}
static ssize_t
gc_debugfs_write(
struct file *file,
const char __user *buf,
size_t count,
loff_t *pos
)
{
struct seq_file *s = file->private_data;
gcsINFO_NODE *node = s->private;
gcsINFO *info = node->info;
if (info->write)
{
info->write(buf, count, node);
}
return count;
}
static const struct file_operations gc_debugfs_operations = {
.owner = THIS_MODULE,
.open = gc_debugfs_open,
.write = gc_debugfs_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
gceSTATUS
gckDEBUGFS_DIR_Init(
IN gckDEBUGFS_DIR Dir,
IN struct dentry *root,
IN gctCONST_STRING Name
)
{
Dir->root = debugfs_create_dir(Name, root);
if (!Dir->root)
{
return gcvSTATUS_NOT_SUPPORTED;
}
INIT_LIST_HEAD(&Dir->nodeList);
return gcvSTATUS_OK;
}
gceSTATUS
gckDEBUGFS_DIR_CreateFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count,
IN gctPOINTER Data
)
{
int i;
gcsINFO_NODE * node;
gceSTATUS status;
for (i = 0; i < count; i++)
{
umode_t mode = 0;
/* Create a node. */
node = (gcsINFO_NODE *)kzalloc(sizeof(gcsINFO_NODE), GFP_KERNEL);
node->info = &List[i];
node->device = Data;
mode |= List[i].show ? S_IRUGO : 0;
mode |= List[i].write ? S_IWUSR : 0;
node->entry = debugfs_create_file(
List[i].name, mode, Dir->root, node, &gc_debugfs_operations);
if (!node->entry)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
list_add(&(node->head), &(Dir->nodeList));
}
return gcvSTATUS_OK;
OnError:
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(Dir, List, count));
return status;
}
gceSTATUS
gckDEBUGFS_DIR_RemoveFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count
)
{
int i;
gcsINFO_NODE * node;
gcsINFO_NODE * temp;
for (i = 0; i < count; i++)
{
list_for_each_entry_safe(node, temp, &Dir->nodeList, head)
{
if (node->info == &List[i])
{
debugfs_remove(node->entry);
list_del(&node->head);
kfree(node);
}
}
}
return gcvSTATUS_OK;
}
void
gckDEBUGFS_DIR_Deinit(
IN gckDEBUGFS_DIR Dir
)
{
if (Dir->root != NULL)
{
debugfs_remove(Dir->root);
Dir->root = NULL;
}
}
/*******************************************************************************
**
** READ & WRITE FUNCTIONS (START)
**
*******************************************************************************/
/*******************************************************************************
**
** _ReadFromNode
**
** 1) reading bytes out of a circular buffer with wraparound.
** 2)returns caddr_t, pointer to data read, which the caller must free.
** 3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
** be the number of bytes actually returned
**
*******************************************************************************/
static caddr_t
_ReadFromNode (
gcsDEBUGFS_Node* Node ,
size_t *Length ,
loff_t *Offset
)
{
caddr_t retval ;
int bytes_copied = 0 , n , start_point , remaining ;
/* find the smaller of the total bytes we have available and what
* the user is asking for */
*Length = gcmkMIN ( *Length , gcmkNODE_QLEN(Node) ) ;
remaining = * Length ;
/* Get start point. */
start_point = Node->read_point;
/* allocate memory to return */
if (remaining > Node->tempSize)
{
kfree(Node->temp);
if ( ( retval = kmalloc ( sizeof (char ) * remaining , GFP_ATOMIC ) ) == NULL )
return NULL;
Node->temp = retval;
Node->tempSize = remaining;
}
else
{
retval = Node->temp;
}
/* copy the (possibly noncontiguous) data to our buffer */
while ( remaining )
{
n = gcmkMIN ( remaining , Node->size - start_point ) ;
memcpy ( retval + bytes_copied , Node->data + start_point , n ) ;
bytes_copied += n ;
remaining -= n ;
start_point = ( start_point + n ) % Node->size ;
}
/* advance user's file pointer */
Node->read_point = (Node->read_point + * Length) % Node->size ;
return retval ;
}
/*******************************************************************************
**
** _WriteToNode
**
** 1) writes to a circular buffer with wraparound.
** 2)in case of an overflow, it overwrites the oldest unread data.
**
*********************************************************************************/
static void
_WriteToNode (
gcsDEBUGFS_Node* Node ,
caddr_t Buf ,
int Length
)
{
int bytes_copied = 0 ;
int overflow = 0 ;
int n ;
if ( Length + gcmkNODE_QLEN ( Node ) >= ( Node->size - 1 ) )
{
overflow = 1 ;
}
while ( Length )
{
/* how many contiguous bytes are available from the write point to
* the end of the circular buffer? */
n = gcmkMIN ( Length , Node->size - Node->write_point ) ;
memcpy ( Node->data + Node->write_point , Buf + bytes_copied , n ) ;
bytes_copied += n ;
Length -= n ;
Node->write_point = ( Node->write_point + n ) % Node->size ;
}
/* if there is an overflow, reset the read point to read whatever is
* the oldest data that we have, that has not yet been
* overwritten. */
if ( overflow )
{
Node->read_point = ( Node->write_point + 1 ) % Node->size ;
}
}
/*******************************************************************************
**
** PRINTING UTILITY (START)
**
*******************************************************************************/
/*******************************************************************************
**
** _GetArgumentSize
**
**
*******************************************************************************/
static gctINT
_GetArgumentSize (
IN gctCONST_STRING Message
)
{
gctINT i , count ;
for ( i = 0 , count = 0 ; Message[i] ; i += 1 )
{
if ( Message[i] == '%' )
{
count += 1 ;
}
}
return count * sizeof (unsigned int ) ;
}
/*******************************************************************************
**
** _AppendString
**
**
*******************************************************************************/
static ssize_t
_AppendString (
IN gcsDEBUGFS_Node* Node,
IN gctCONST_STRING String,
IN int Length
)
{
int n;
unsigned long flags;
/* if the message is longer than the buffer, just take the beginning
* of it, in hopes that the reader (if any) will have time to read
* before we wrap around and obliterate it */
n = gcmkMIN ( Length , Node->size - 1 );
spin_lock_irqsave(&traceLock, flags);
/* now copy it into the circular buffer and free our temp copy */
_WriteToNode ( Node , (caddr_t)String , n ) ;
spin_unlock_irqrestore(&traceLock, flags);
return n ;
}
/*******************************************************************************
**
** _DebugFSPrint
**
**
*******************************************************************************/
static ssize_t
_DebugFSPrint (
IN unsigned int ArgumentSize ,
IN const char* Message ,
IN gctDBGARGS * Arguments
)
{
char buffer[MAX_LINE_SIZE] ;
int len ;
ssize_t res = 0;
if ( gc_dbgfs.currentNode )
{
len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) Arguments ) ;
buffer[len] = '\0' ;
/* Add end-of-line if missing. */
if ( buffer[len - 1] != '\n' )
{
buffer[len ++] = '\n' ;
buffer[len] = '\0' ;
}
res = _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
}
return res;
}
/*******************************************************************************
**
** LINUX SYSTEM FUNCTIONS (START)
**
*******************************************************************************/
static int
_DebugFSOpen (
struct inode* inode,
struct file* filp
)
{
filp->private_data = inode->i_private;
return 0;
}
/*******************************************************************************
**
** _DebugFSRead
**
*******************************************************************************/
static ssize_t
_DebugFSRead (
struct file *file,
char __user * buffer,
size_t length,
loff_t * offset
)
{
int retval;
caddr_t data_to_return;
unsigned long flags;
gcsDEBUGFS_Node* node = file->private_data;
if (node == NULL)
{
printk ( "debugfs_read: record not found\n" );
return - EIO ;
}
spin_lock_irqsave(&traceLock, flags);
/* wait until there's data available (unless we do nonblocking reads) */
while (!gcmkNODE_QLEN(node))
{
spin_unlock_irqrestore(&traceLock, flags);
if (file->f_flags & O_NONBLOCK)
{
return - EAGAIN ;
}
if (wait_event_interruptible((*(gcmkNODE_READQ(node))) , (*offset < gcmkNODE_FIRST_EMPTY_BYTE(node))))
{
return - ERESTARTSYS ; /* signal: tell the fs layer to handle it */
}
spin_lock_irqsave(&traceLock, flags);
}
data_to_return = _ReadFromNode(node , &length , offset);
spin_unlock_irqrestore(&traceLock, flags);
if (data_to_return == NULL)
{
retval = 0;
goto unlock;
}
if (copy_to_user(buffer, data_to_return, length) > 0)
{
retval = - EFAULT;
}
else
{
retval = length;
}
unlock:
wake_up_interruptible(gcmkNODE_WRITEQ(node));
return retval ;
}
/*******************************************************************************
**
**_DebugFSWrite
**
*******************************************************************************/
static ssize_t
_DebugFSWrite (
struct file *file ,
const char __user * buffer ,
size_t length ,
loff_t * offset
)
{
caddr_t message = NULL ;
int n ;
gcsDEBUGFS_Node* node = file->private_data;
/* get the metadata about this log */
if (node == NULL)
{
return - EIO ;
}
if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
{
return - ERESTARTSYS ;
}
/* if the message is longer than the buffer, just take the beginning
* of it, in hopes that the reader (if any) will have time to read
* before we wrap around and obliterate it */
n = gcmkMIN ( length , node->size - 1 ) ;
/* make sure we have the memory for it */
if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
{
up ( gcmkNODE_SEM ( node ) ) ;
return - ENOMEM ;
}
/* copy into our temp buffer */
if ( copy_from_user ( message , buffer , n ) > 0 )
{
up ( gcmkNODE_SEM ( node ) ) ;
kfree ( message ) ;
return - EFAULT ;
}
/* now copy it into the circular buffer and free our temp copy */
_WriteToNode ( node , message , n ) ;
kfree ( message ) ;
up ( gcmkNODE_SEM ( node ) ) ;
/* wake up any readers that might be waiting for the data. we call
* schedule in the vague hope that a reader will run before the
* writer's next write, to avoid losing data. */
wake_up_interruptible ( gcmkNODE_READQ ( node ) ) ;
return n ;
}
/*******************************************************************************
**
** File Operations Table
**
*******************************************************************************/
static const struct file_operations debugfs_operations = {
.owner = THIS_MODULE ,
.open = _DebugFSOpen ,
.read = _DebugFSRead ,
.write = _DebugFSWrite ,
} ;
/*******************************************************************************
**
** INTERFACE FUNCTIONS (START)
**
*******************************************************************************/
/*******************************************************************************
**
** gckDEBUGFS_IsEnabled
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
gctINT
gckDEBUGFS_IsEnabled ( void )
{
return gc_dbgfs.isInited ;
}
/*******************************************************************************
**
** gckDEBUGFS_Initialize
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
gctINT
gckDEBUGFS_Initialize ( void )
{
if ( ! gc_dbgfs.isInited )
{
gc_dbgfs.linkedlist = gcvNULL ;
gc_dbgfs.currentNode = gcvNULL ;
gc_dbgfs.isInited = 1 ;
}
return gc_dbgfs.isInited ;
}
/*******************************************************************************
**
** gckDEBUGFS_Terminate
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
gctINT
gckDEBUGFS_Terminate ( void )
{
gcsDEBUGFS_Node * next = gcvNULL ;
gcsDEBUGFS_Node * temp = gcvNULL ;
if ( gc_dbgfs.isInited )
{
temp = gc_dbgfs.linkedlist ;
while ( temp != gcvNULL )
{
next = temp->next ;
gckDEBUGFS_FreeNode ( temp ) ;
kfree ( temp ) ;
temp = next ;
}
gc_dbgfs.isInited = 0 ;
}
return 0 ;
}
/*******************************************************************************
**
** gckDEBUGFS_CreateNode
**
**
** INPUT:
**
** OUTPUT:
**
** gckDEBUGFS_FreeNode * Device
** Pointer to a variable receiving the gcsDEBUGFS_Node object pointer on
** success.
*********************************************************************************/
gctINT
gckDEBUGFS_CreateNode (
IN gctPOINTER Device,
IN gctINT SizeInKB ,
IN struct dentry * Root ,
IN gctCONST_STRING NodeName ,
OUT gcsDEBUGFS_Node **Node
)
{
gcsDEBUGFS_Node*node ;
/* allocate space for our metadata and initialize it */
if ( ( node = kmalloc ( sizeof (gcsDEBUGFS_Node ) , GFP_KERNEL ) ) == NULL )
goto struct_malloc_failed ;
/*Zero it out*/
memset ( node , 0 , sizeof (gcsDEBUGFS_Node ) ) ;
/*Init the sync primitives*/
#if defined(DECLARE_WAIT_QUEUE_HEAD)
init_waitqueue_head ( gcmkNODE_READQ ( node ) ) ;
#else
init_waitqueue ( gcmkNODE_READQ ( node ) ) ;
#endif
#if defined(DECLARE_WAIT_QUEUE_HEAD)
init_waitqueue_head ( gcmkNODE_WRITEQ ( node ) ) ;
#else
init_waitqueue ( gcmkNODE_WRITEQ ( node ) ) ;
#endif
sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
/*End the sync primitives*/
/*creating the debug file system*/
node->parent = Root;
if (SizeInKB)
{
/* figure out how much of a buffer this should be and allocate the buffer */
node->size = 1024 * SizeInKB ;
if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
goto data_malloc_failed ;
node->tempSize = 0;
node->temp = NULL;
/*creating the file*/
node->filen = debugfs_create_file(NodeName, S_IRUGO|S_IWUSR, node->parent, node,
&debugfs_operations);
}
/* add it to our linked list */
node->next = gc_dbgfs.linkedlist ;
gc_dbgfs.linkedlist = node ;
/* pass the struct back */
*Node = node ;
return 0 ;
data_malloc_failed:
kfree ( node ) ;
struct_malloc_failed:
return - ENOMEM ;
}
/*******************************************************************************
**
** gckDEBUGFS_FreeNode
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
void
gckDEBUGFS_FreeNode (
IN gcsDEBUGFS_Node * Node
)
{
gcsDEBUGFS_Node **ptr ;
if ( Node == NULL )
{
printk ( "null passed to free_vinfo\n" ) ;
return ;
}
down ( gcmkNODE_SEM ( Node ) ) ;
/*free data*/
vfree ( Node->data ) ;
kfree(Node->temp);
/*Close Debug fs*/
if ( Node->filen )
{
debugfs_remove ( Node->filen ) ;
}
/* now delete the node from the linked list */
ptr = & ( gc_dbgfs.linkedlist ) ;
while ( *ptr != Node )
{
if ( ! *ptr )
{
printk ( "corrupt info list!\n" ) ;
break ;
}
else
ptr = & ( ( **ptr ).next ) ;
}
*ptr = Node->next ;
up ( gcmkNODE_SEM ( Node ) ) ;
}
/*******************************************************************************
**
** gckDEBUGFS_SetCurrentNode
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
void
gckDEBUGFS_SetCurrentNode (
IN gcsDEBUGFS_Node * Node
)
{
gc_dbgfs.currentNode = Node ;
}
/*******************************************************************************
**
** gckDEBUGFS_GetCurrentNode
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
void
gckDEBUGFS_GetCurrentNode (
OUT gcsDEBUGFS_Node ** Node
)
{
*Node = gc_dbgfs.currentNode ;
}
/*******************************************************************************
**
** gckDEBUGFS_Print
**
**
** INPUT:
**
** OUTPUT:
**
*******************************************************************************/
ssize_t
gckDEBUGFS_Print (
IN gctCONST_STRING Message ,
...
)
{
ssize_t _debugfs_res = 0;
gcmkDEBUGFS_PRINT ( _GetArgumentSize ( Message ) , Message ) ;
return _debugfs_res;
}

View File

@ -0,0 +1,170 @@
/****************************************************************************
*
* 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 <stdarg.h>
#ifndef __gc_hal_kernel_debugfs_h_
#define __gc_hal_kernel_debugfs_h_
#define MAX_LINE_SIZE 768 /* Max bytes for a line of debug info */
typedef struct _gcsDEBUGFS_Node gcsDEBUGFS_Node;
typedef struct _gcsDEBUGFS_DIR *gckDEBUGFS_DIR;
typedef struct _gcsDEBUGFS_DIR
{
struct dentry * root;
struct list_head nodeList;
}
gcsDEBUGFS_DIR;
typedef struct _gcsINFO
{
const char * name;
int (*show)(struct seq_file*, void*);
int (*write)(const char __user *buf, size_t count, void*);
}
gcsINFO;
typedef struct _gcsINFO_NODE
{
gcsINFO * info;
gctPOINTER device;
struct dentry * entry;
struct list_head head;
}
gcsINFO_NODE;
gceSTATUS
gckDEBUGFS_DIR_Init(
IN gckDEBUGFS_DIR Dir,
IN struct dentry *root,
IN gctCONST_STRING Name
);
gceSTATUS
gckDEBUGFS_DIR_CreateFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count,
IN gctPOINTER Data
);
gceSTATUS
gckDEBUGFS_DIR_RemoveFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count
);
void
gckDEBUGFS_DIR_Deinit(
IN gckDEBUGFS_DIR Dir
);
/*******************************************************************************
**
** System Related
**
*******************************************************************************/
gctINT gckDEBUGFS_IsEnabled(void);
gctINT gckDEBUGFS_Initialize(void);
gctINT gckDEBUGFS_Terminate(void);
/*******************************************************************************
**
** Node Related
**
*******************************************************************************/
gctINT
gckDEBUGFS_CreateNode(
IN gctPOINTER Device,
IN gctINT SizeInKB,
IN struct dentry * Root,
IN gctCONST_STRING NodeName,
OUT gcsDEBUGFS_Node **Node
);
void gckDEBUGFS_FreeNode(
IN gcsDEBUGFS_Node * Node
);
void gckDEBUGFS_SetCurrentNode(
IN gcsDEBUGFS_Node * Node
);
void gckDEBUGFS_GetCurrentNode(
OUT gcsDEBUGFS_Node ** Node
);
ssize_t gckDEBUGFS_Print(
IN gctCONST_STRING Message,
...
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,273 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_device_h_
#define __gc_hal_kernel_device_h_
#include "gc_hal_kernel_debugfs.h"
#include "gc_hal_ta.h"
typedef struct _gcsDEVICE_CONSTRUCT_ARGS
{
gctBOOL recovery;
gctUINT stuckDump;
gctUINT gpu3DMinClock;
gctBOOL contiguousRequested;
gcsPLATFORM* platform;
gctBOOL mmu;
gctBOOL registerMemMapped;
gctPOINTER registerMemAddress;
#if gcdDEC_ENABLE_AHB
gctUINT32 registerMemBaseDEC300;
gctSIZE_T registerMemSizeDEC300;
#endif
gctINT irqs[gcvCORE_COUNT];
gctUINT registerBases[gcvCORE_COUNT];
gctUINT registerSizes[gcvCORE_COUNT];
gctBOOL powerManagement;
gctBOOL gpuProfiler;
gctUINT chipIDs[gcvCORE_COUNT];
}
gcsDEVICE_CONSTRUCT_ARGS;
/******************************************************************************\
************************** gckGALDEVICE Structure ******************************
\******************************************************************************/
typedef struct _gckGALDEVICE
{
/* Objects. */
gckOS os;
gckKERNEL kernels[gcdMAX_GPU_COUNT];
gcsPLATFORM* platform;
/* Attributes. */
gctSIZE_T internalSize;
gctPHYS_ADDR internalPhysical;
gctUINT32 internalPhysicalName;
gctPOINTER internalLogical;
gckVIDMEM internalVidMem;
gctUINT32 externalBase;
gctSIZE_T externalSize;
gctPHYS_ADDR externalPhysical;
gctUINT32 externalPhysicalName;
gctPOINTER externalLogical;
gckVIDMEM externalVidMem;
gctPHYS_ADDR_T contiguousBase;
gctSIZE_T contiguousSize;
gckVIDMEM contiguousVidMem;
gctPOINTER contiguousLogical;
gctPHYS_ADDR contiguousPhysical;
gctUINT32 contiguousPhysicalName;
gctSIZE_T systemMemorySize;
gctUINT32 systemMemoryBaseAddress;
gctPOINTER registerBases[gcdMAX_GPU_COUNT];
gctSIZE_T registerSizes[gcdMAX_GPU_COUNT];
gctUINT32 baseAddress;
gctUINT32 physBase;
gctUINT32 physSize;
/* By request_mem_region. */
gctUINT32 requestedRegisterMemBases[gcdMAX_GPU_COUNT];
gctSIZE_T requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
/* By request_mem_region. */
gctUINT32 requestedContiguousBase;
gctSIZE_T requestedContiguousSize;
/* IRQ management. */
gctINT irqLines[gcdMAX_GPU_COUNT];
gctBOOL isrInitializeds[gcdMAX_GPU_COUNT];
/* Thread management. */
struct task_struct *threadCtxts[gcdMAX_GPU_COUNT];
struct semaphore semas[gcdMAX_GPU_COUNT];
gctBOOL threadInitializeds[gcdMAX_GPU_COUNT];
gctBOOL killThread;
/* Signal management. */
gctINT signal;
/* States before suspend. */
gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
/* Device Debug File System Entry in kernel. */
struct _gcsDEBUGFS_Node * dbgNode;
gcsDEBUGFS_DIR debugfsDir;
gckDEVICE device;
gcsDEVICE_CONSTRUCT_ARGS args;
/* gctsOs object for trust application. */
gctaOS taos;
#if gcdENABLE_DRM
void* drm;
#endif
}
* gckGALDEVICE;
typedef struct _gcsHAL_PRIVATE_DATA
{
gckGALDEVICE device;
/*
* 'fput' schedules actual work in '__fput' in a different thread.
* So the process opens the device may not be the same as the one that
* closes it.
*/
gctUINT32 pidOpen;
gctBOOL isLocked;
}
gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
gceSTATUS gckGALDEVICE_Setup_ISR(
IN gceCORE Core
);
gceSTATUS gckGALDEVICE_Setup_ISR_VG(
IN gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Release_ISR(
IN gceCORE Core
);
gceSTATUS gckGALDEVICE_Release_ISR_VG(
IN gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Start_Threads(
IN gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Stop_Threads(
gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Start(
IN gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Stop(
gckGALDEVICE Device
);
gceSTATUS gckGALDEVICE_Construct(
IN gctINT IrqLine,
IN gctUINT32 RegisterMemBase,
IN gctSIZE_T RegisterMemSize,
IN gctINT IrqLine2D,
IN gctUINT32 RegisterMemBase2D,
IN gctSIZE_T RegisterMemSize2D,
IN gctINT IrqLineVG,
IN gctUINT32 RegisterMemBaseVG,
IN gctSIZE_T RegisterMemSizeVG,
IN gctUINT32 ContiguousBase,
IN gctSIZE_T ContiguousSize,
IN gctUINT32 ExternalBase,
IN gctSIZE_T ExternalSize,
IN gctSIZE_T BankSize,
IN gctINT FastClear,
IN gctINT Compression,
IN gctUINT32 PhysBaseAddr,
IN gctUINT32 PhysSize,
IN gctINT Signal,
IN gctUINT LogFileSize,
IN gctINT PowerManagement,
IN gctINT GpuProfiler,
IN gcsDEVICE_CONSTRUCT_ARGS * Args,
OUT gckGALDEVICE *Device
);
gceSTATUS gckGALDEVICE_Destroy(
IN gckGALDEVICE Device
);
static gcmINLINE gckKERNEL
_GetValidKernel(
gckGALDEVICE Device
)
{
if (Device->kernels[gcvCORE_MAJOR])
{
return Device->kernels[gcvCORE_MAJOR];
}
else
if (Device->kernels[gcvCORE_2D])
{
return Device->kernels[gcvCORE_2D];
}
else
if (Device->kernels[gcvCORE_VG])
{
return Device->kernels[gcvCORE_VG];
}
else
{
gcmkASSERT(gcvFALSE);
return gcvNULL;
}
}
#endif /* __gc_hal_kernel_device_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,856 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#if gcdENABLE_DRM
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <linux/dma-buf.h>
#include "gc_hal_kernel_linux.h"
#include "gc_hal_drm.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
/******************************************************************************\
******************************* gckKERNEL DRM Code ******************************
\******************************************************************************/
struct viv_gem_object {
struct drm_gem_object base;
uint32_t node_handle;
gckVIDMEM_NODE node_object;
gctBOOL cacheable;
};
struct dma_buf *viv_gem_prime_export(struct drm_device *drm,
struct drm_gem_object *gem_obj,
int flags)
{
struct viv_gem_object *viv_obj = container_of(gem_obj, struct viv_gem_object, base);
struct dma_buf *dmabuf = gcvNULL;
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
if (gal_dev)
{
gckKERNEL kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkVERIFY_OK(gckVIDMEM_NODE_Export(kernel, viv_obj->node_handle, flags,
(gctPOINTER*)&dmabuf, gcvNULL));
}
return dmabuf;
}
struct drm_gem_object *viv_gem_prime_import(struct drm_device *drm,
struct dma_buf *dmabuf)
{
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev;
gckKERNEL kernel;
gctUINT32 processID;
gckVIDMEM_NODE nodeObject;
gceSTATUS status = gcvSTATUS_OK;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_WRAP_USER_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.WrapUserMemory.desc.flag = gcvALLOC_FLAG_DMABUF;
iface.u.WrapUserMemory.desc.handle = -1;
iface.u.WrapUserMemory.desc.dmabuf = gcmPTR_TO_UINT64(dmabuf);
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Lookup(kernel, processID, iface.u.WrapUserMemory.node, &nodeObject));
/* ioctl output */
gem_obj = kzalloc(sizeof(struct viv_gem_object), GFP_KERNEL);
drm_gem_private_object_init(drm, gem_obj, dmabuf->size);
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_handle = iface.u.WrapUserMemory.node;
viv_obj->node_object = nodeObject;
OnError:
return gem_obj;
}
void viv_gem_free_object(struct drm_gem_object *gem_obj)
{
struct viv_gem_object *viv_obj = container_of(gem_obj, struct viv_gem_object, base);
struct drm_device *drm = gem_obj->dev;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_RELEASE_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.ReleaseVideoMemory.node = viv_obj->node_handle;
gcmkVERIFY_OK(gckDEVICE_Dispatch(gal_dev->device, &iface));
drm_gem_object_release(gem_obj);
kfree(gem_obj);
}
static int viv_ioctl_gem_create(struct drm_device *drm, void *data,
struct drm_file *file)
{
int ret = 0;
struct drm_viv_gem_create *args = (struct drm_viv_gem_create*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev;
gckKERNEL kernel;
gctUINT32 processID;
gckVIDMEM_NODE nodeObject;
gctUINT32 flags = gcvALLOC_FLAG_DMABUF_EXPORTABLE;
gceSTATUS status = gcvSTATUS_OK;
gcePOOL pool = gcvPOOL_DEFAULT;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if (args->flags & DRM_VIV_GEM_CONTIGUOUS)
{
flags |= gcvALLOC_FLAG_CONTIGUOUS;
}
if (args->flags & DRM_VIV_GEM_CACHED)
{
flags |= gcvALLOC_FLAG_CACHEABLE;
}
if (args->flags & DRM_VIV_GEM_SECURE)
{
flags |= gcvALLOC_FLAG_SECURITY;
}
if (args->flags & DRM_VIV_GEM_CMA_LIMIT)
{
flags |= gcvALLOC_FLAG_CMA_LIMIT;
}
if (args->flags & DRM_VIV_GEM_VIRTUAL_POOL) {
flags &= ~(gcvALLOC_FLAG_CMA_LIMIT | gcvALLOC_FLAG_CONTIGUOUS);
pool = gcvPOOL_VIRTUAL;
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.AllocateLinearVideoMemory.bytes = PAGE_ALIGN(args->size);
iface.u.AllocateLinearVideoMemory.alignment = 256;
iface.u.AllocateLinearVideoMemory.type = gcvSURF_RENDER_TARGET; /* should be general */
iface.u.AllocateLinearVideoMemory.flag = flags;
iface.u.AllocateLinearVideoMemory.pool = pool;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Lookup(kernel, processID, iface.u.AllocateLinearVideoMemory.node, &nodeObject));
/* ioctl output */
gem_obj = kzalloc(sizeof(struct viv_gem_object), GFP_KERNEL);
drm_gem_private_object_init(drm, gem_obj, iface.u.AllocateLinearVideoMemory.bytes);
ret = drm_gem_handle_create(file, gem_obj, &args->handle);
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_handle = iface.u.AllocateLinearVideoMemory.node;
viv_obj->node_object = nodeObject;
viv_obj->cacheable = flags & gcvALLOC_FLAG_CACHEABLE;
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(gem_obj);
OnError:
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_lock(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_lock *args = (struct drm_viv_gem_lock*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_LOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.LockVideoMemory.node = viv_obj->node_handle;
iface.u.LockVideoMemory.cacheable = args->cacheable;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
args->logical = iface.u.LockVideoMemory.memory;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_unlock(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_unlock *args = (struct drm_viv_gem_unlock*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.UnlockVideoMemory.node = (gctUINT64)viv_obj->node_handle;
iface.u.UnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.BottomHalfUnlockVideoMemory.node = (gctUINT64)viv_obj->node_handle;
iface.u.BottomHalfUnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_cache(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_cache *args = (struct drm_viv_gem_cache*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gceCACHEOPERATION cache_op = 0;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
switch (args->op)
{
case DRM_VIV_GEM_CLEAN_CACHE:
cache_op = gcvCACHE_CLEAN;
break;
case DRM_VIV_GEM_INVALIDATE_CACHE:
cache_op = gcvCACHE_INVALIDATE;
break;
case DRM_VIV_GEM_FLUSH_CACHE:
cache_op = gcvCACHE_FLUSH;
break;
case DRM_VIV_GEM_MEMORY_BARRIER:
cache_op = gcvCACHE_MEMORY_BARRIER;
break;
default:
break;
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_CACHE;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.Cache.node = viv_obj->node_handle;
iface.u.Cache.operation = cache_op;
iface.u.Cache.logical = args->logical;
iface.u.Cache.bytes = args->bytes;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_query(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_query *args = (struct drm_viv_gem_query*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
switch (args->param)
{
case DRM_VIV_GEM_PARAM_POOL:
args->value = (__u64)viv_obj->node_object->pool;
break;
case DRM_VIV_GEM_PARAM_SIZE:
args->value = (__u64)gem_obj->size;
break;
default:
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_timestamp(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_timestamp *args = (struct drm_viv_gem_timestamp *)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_object->timeStamp += args->inc;
args->timestamp = viv_obj->node_object->timeStamp;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_set_tiling(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_set_tiling *args = (struct drm_viv_gem_set_tiling*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_object->tilingMode = args->tiling_mode;
viv_obj->node_object->tsMode = args->ts_mode;
viv_obj->node_object->clearValue = args->clear_value;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_get_tiling(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_get_tiling *args = (struct drm_viv_gem_get_tiling*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
args->tiling_mode = viv_obj->node_object->tilingMode;
args->ts_mode = viv_obj->node_object->tsMode;
args->clear_value = viv_obj->node_object->clearValue;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_attach_aux(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_attach_aux *args = (struct drm_viv_gem_attach_aux*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
struct drm_gem_object *gem_ts_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gckVIDMEM_NODE nodeObj = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
nodeObj = viv_obj->node_object;
/* do not support re-attach */
if (nodeObj->tsNode)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
if (args->ts_handle)
{
struct viv_gem_object *viv_ts_obj;
gckKERNEL kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcsHAL_INTERFACE iface;
gctBOOL is2BitPerTile = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_TILE_STATUS_2BITS);
gctBOOL isCompressionDEC400 = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_COMPRESSION_DEC400);
gctPOINTER entry = gcvNULL;
gctUINT32 tileStatusFiller = (isCompressionDEC400 || ((kernel->hardware->identity.chipModel == gcv500) && (kernel->hardware->identity.chipRevision > 2)))
? 0xFFFFFFFF
: is2BitPerTile ? 0x55555555 : 0x11111111;
gem_ts_obj = drm_gem_object_lookup(file, args->ts_handle);
if (!gem_ts_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_ts_obj = container_of(gem_ts_obj, struct viv_gem_object, base);
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, viv_ts_obj->node_object));
nodeObj->tsNode = viv_ts_obj->node_object;
/* Fill tile status node with tileStatusFiller value first time to avoid GPU hang. */
/* Lock tile status node. */
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_LOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.LockVideoMemory.node = viv_ts_obj->node_handle;
iface.u.LockVideoMemory.cacheable = viv_ts_obj->cacheable;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
/* Fill tile status node with tileStatusFiller. */
gcmkONERROR(gckVIDMEM_NODE_LockCPU(kernel, viv_ts_obj->node_handle, &entry));
memset(entry , tileStatusFiller , (__u64)gem_ts_obj->size);
gcmkONERROR(gckVIDMEM_NODE_UnlockCPU(kernel, viv_ts_obj->node_handle, entry));
/* UnLock tile status node. */
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.UnlockVideoMemory.node = (gctUINT64)viv_ts_obj->node_handle;
iface.u.UnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.BottomHalfUnlockVideoMemory.node = (gctUINT64)viv_ts_obj->node_handle;
iface.u.BottomHalfUnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
}
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
if (gem_ts_obj)
{
drm_gem_object_unreference_unlocked(gem_ts_obj);
}
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_ref_node(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_ref_node *args = (struct drm_viv_gem_ref_node*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gckKERNEL kernel = gcvNULL;
gctUINT32 processID;
gckVIDMEM_NODE nodeObj;
gctUINT32 nodeHandle = 0, tsNodeHandle = 0;
gctBOOL refered = gcvFALSE;
int ret = 0;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
nodeObj = viv_obj->node_object;
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Allocate(kernel, nodeObj, &nodeHandle));
gcmkONERROR(
gckKERNEL_AddProcessDB(kernel,
processID, gcvDB_VIDEO_MEMORY,
gcmINT2PTR(nodeHandle),
gcvNULL,
0));
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, nodeObj));
refered = gcvTRUE;
if (nodeObj->tsNode)
{
gcmkONERROR(gckVIDMEM_HANDLE_Allocate(kernel, nodeObj->tsNode, &tsNodeHandle));
gcmkONERROR(
gckKERNEL_AddProcessDB(kernel,
processID, gcvDB_VIDEO_MEMORY,
gcmINT2PTR(tsNodeHandle),
gcvNULL,
0));
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, nodeObj->tsNode));
}
args->node = nodeHandle;
args->ts_node = tsNodeHandle;
OnError:
if (gcmIS_ERROR(status) && kernel)
{
gctUINT32 processID;
gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
if (tsNodeHandle)
{
gckVIDMEM_HANDLE_Dereference(kernel, processID, tsNodeHandle);
}
if (nodeHandle)
{
gckVIDMEM_HANDLE_Dereference(kernel, processID, nodeHandle);
}
if (refered)
{
gcmkONERROR(gckVIDMEM_NODE_Dereference(kernel, nodeObj));
}
args->node = 0;
args->ts_node = 0;
ret = -ENOTTY;
}
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return ret;
}
static const struct drm_ioctl_desc viv_ioctls[] =
{
DRM_IOCTL_DEF_DRV(VIV_GEM_CREATE, viv_ioctl_gem_create, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_LOCK, viv_ioctl_gem_lock, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_UNLOCK, viv_ioctl_gem_unlock, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_CACHE, viv_ioctl_gem_cache, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_QUERY, viv_ioctl_gem_query, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_TIMESTAMP, viv_ioctl_gem_timestamp, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_SET_TILING, viv_ioctl_gem_set_tiling, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_GET_TILING, viv_ioctl_gem_get_tiling, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_ATTACH_AUX, viv_ioctl_gem_attach_aux, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_REF_NODE, viv_ioctl_gem_ref_node, DRM_AUTH | DRM_RENDER_ALLOW),
};
int viv_drm_open(struct drm_device *drm, struct drm_file *file)
{
gctINT i;
gctUINT32 pid = _GetProcessID();
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
gceSTATUS status = gcvSTATUS_OK;
for (i = 0; i < gcdMAX_GPU_COUNT; ++i)
{
if (gal_dev->kernels[i])
{
gcmkONERROR(gckKERNEL_AttachProcessEx(gal_dev->kernels[i], gcvTRUE, pid));
}
}
file->driver_priv = gcmINT2PTR(pid);
OnError:
return gcmIS_ERROR(status) ? -ENODEV : 0;
}
void viv_drm_postclose(struct drm_device *drm, struct drm_file *file)
{
gctINT i;
gctUINT32 pid = gcmPTR2SIZE(file->driver_priv);
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
for (i = 0; i < gcdMAX_GPU_COUNT; ++i)
{
if (gal_dev->kernels[i])
{
gcmkVERIFY_OK(gckKERNEL_AttachProcessEx(gal_dev->kernels[i], gcvFALSE, pid));
}
}
}
static const struct file_operations viv_drm_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
};
static struct drm_driver viv_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,
.open = viv_drm_open,
.postclose = viv_drm_postclose,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
.gem_free_object_unlocked = viv_gem_free_object,
#else
.gem_free_object = viv_gem_free_object,
#endif
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = viv_gem_prime_export,
.gem_prime_import = viv_gem_prime_import,
.ioctls = viv_ioctls,
.num_ioctls = DRM_VIV_NUM_IOCTLS,
.fops = &viv_drm_fops,
.name = "vivante",
.desc = "vivante DRM",
.date = "20170808",
.major = 1,
.minor = 0,
};
int viv_drm_probe(struct device *dev)
{
int ret = 0;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
struct drm_device *drm = gcvNULL;
gal_dev = (gckGALDEVICE)dev_get_drvdata(dev);
if (!gal_dev)
{
ret = -ENODEV;
gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
}
drm = drm_dev_alloc(&viv_drm_driver, dev);
if (IS_ERR(drm))
{
ret = PTR_ERR(drm);
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
drm->dev_private = (void*)gal_dev;
ret = drm_dev_register(drm, 0);
if (ret)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gal_dev->drm = (void*)drm;
OnError:
if (gcmIS_ERROR(status))
{
if (drm)
{
drm_dev_unref(drm);
}
printk(KERN_ERR "galcore: Failed to setup drm device.\n");
}
return ret;
}
int viv_drm_remove(struct device *dev)
{
gckGALDEVICE gal_dev = (gckGALDEVICE)dev_get_drvdata(dev);
if (gal_dev)
{
struct drm_device *drm = (struct drm_device*)gal_dev->drm;
drm_dev_unregister(drm);
drm_dev_unref(drm);
}
return 0;
}
#endif

View File

@ -0,0 +1,250 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_device.h"
#include <linux/iommu.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsIOMMU
{
struct iommu_domain * domain;
struct device * device;
}
gcsIOMMU;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
static int
_IOMMU_Fault_Handler(
struct iommu_domain * Domain,
struct device * Dev,
unsigned long DomainAddress,
int flags,
void * args
)
#else
static int
_IOMMU_Fault_Handler(
struct iommu_domain * Domain,
struct device * Dev,
unsigned long DomainAddress,
int flags
)
#endif
{
return 0;
}
static int
_FlatMapping(
IN gckIOMMU Iommu
)
{
gceSTATUS status;
gctUINT32 physical;
for (physical = 0; physical < 0x80000000; physical += PAGE_SIZE)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"Map %x => %x bytes = %d",
physical, physical, PAGE_SIZE
);
gcmkONERROR(gckIOMMU_Map(Iommu, physical, physical, PAGE_SIZE));
}
return gcvSTATUS_OK;
OnError:
return status;
}
void
gckIOMMU_Destory(
IN gckOS Os,
IN gckIOMMU Iommu
)
{
gcmkHEADER();
if (Iommu->domain && Iommu->device)
{
iommu_attach_device(Iommu->domain, Iommu->device);
}
if (Iommu->domain)
{
iommu_domain_free(Iommu->domain);
}
if (Iommu)
{
gcmkOS_SAFE_FREE(Os, Iommu);
}
gcmkFOOTER_NO();
}
gceSTATUS
gckIOMMU_Construct(
IN gckOS Os,
OUT gckIOMMU * Iommu
)
{
gceSTATUS status;
gckIOMMU iommu = gcvNULL;
struct device *dev;
int ret;
gcmkHEADER();
dev = &Os->device->platform->device->dev;
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));
gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));
iommu->domain = iommu_domain_alloc(&platform_bus_type);
if (!iommu->domain)
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);
#else
iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler);
#endif
ret = iommu_attach_device(iommu->domain, dev);
if (ret)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail %d", ret);
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
iommu->device = dev;
_FlatMapping(iommu);
*Iommu = iommu;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gckIOMMU_Destory(Os, iommu);
gcmkFOOTER();
return status;
}
gceSTATUS
gckIOMMU_Map(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Physical,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
int ret;
gcmkHEADER_ARG("DomainAddress=%#X, Physical=%#X, Bytes=%d",
DomainAddress, Physical, Bytes);
ret = iommu_map(Iommu->domain, DomainAddress, Physical, Bytes, 0);
if (ret)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckIOMMU_Unmap(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Bytes
)
{
gcmkHEADER();
iommu_unmap(Iommu->domain, DomainAddress, Bytes);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}

View File

@ -0,0 +1,510 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
/******************************************************************************\
******************************* gckKERNEL API Code ******************************
\******************************************************************************/
/*******************************************************************************
**
** gckKERNEL_QueryVideoMemory
**
** Query the amount of video memory.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** OUTPUT:
**
** gcsHAL_INTERFACE * Interface
** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
** the memory information.
*/
gceSTATUS
gckKERNEL_QueryVideoMemory(
IN gckKERNEL Kernel,
OUT gcsHAL_INTERFACE * Interface
)
{
gckGALDEVICE device;
gcmkHEADER_ARG("Kernel=%p", Kernel);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interface != NULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Get internal memory size and physical address. */
Interface->u.QueryVideoMemory.internalSize = device->internalSize;
Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysicalName;
/* Get external memory size and physical address. */
Interface->u.QueryVideoMemory.externalSize = device->externalSize;
Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysicalName;
/* Get contiguous memory size and physical address. */
Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysicalName;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckKERNEL_GetVideoMemoryPool
**
** Get the gckVIDMEM object belonging to the specified pool.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gcePOOL Pool
** Pool to query gckVIDMEM object for.
**
** OUTPUT:
**
** gckVIDMEM * VideoMemory
** Pointer to a variable that will hold the pointer to the gckVIDMEM
** object belonging to the requested pool.
*/
gceSTATUS
gckKERNEL_GetVideoMemoryPool(
IN gckKERNEL Kernel,
IN gcePOOL Pool,
OUT gckVIDMEM * VideoMemory
)
{
gckGALDEVICE device;
gckVIDMEM videoMemory;
gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Dispatch on pool. */
switch (Pool)
{
case gcvPOOL_LOCAL_INTERNAL:
/* Internal memory. */
videoMemory = device->internalVidMem;
break;
case gcvPOOL_LOCAL_EXTERNAL:
/* External memory. */
videoMemory = device->externalVidMem;
break;
case gcvPOOL_SYSTEM:
/* System memory. */
videoMemory = device->contiguousVidMem;
break;
default:
/* Unknown pool. */
videoMemory = NULL;
}
/* Return pointer to the gckVIDMEM object. */
*VideoMemory = videoMemory;
/* Return status. */
gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckKERNEL_MapMemory
**
** Map video memory into the current process space.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctPHYS_ADDR Physical
** Physical address of video memory to map.
**
** gctSIZE_T Bytes
** Number of bytes to map.
**
** OUTPUT:
**
** gctPOINTER * Logical
** Pointer to a variable that will hold the base address of the mapped
** memory region.
*/
gceSTATUS
gckKERNEL_MapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
OUT gctPOINTER * Logical
)
{
gckKERNEL kernel = Kernel;
gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
}
/*******************************************************************************
**
** gckKERNEL_UnmapMemory
**
** Unmap video memory from the current process space.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctPHYS_ADDR Physical
** Physical address of video memory to map.
**
** gctSIZE_T Bytes
** Number of bytes to map.
**
** gctPOINTER Logical
** Base address of the mapped memory region.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckKERNEL_UnmapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID
)
{
gckKERNEL kernel = Kernel;
gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
return gckOS_UnmapMemoryEx(Kernel->os, physical, Bytes, Logical, ProcessID);
}
/*******************************************************************************
**
** gckKERNEL_MapVideoMemory
**
** Get the logical address for a hardware specific memory address for the
** current process.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctBOOL InUserSpace
** gcvTRUE to map the memory into the user space.
**
** gctUINT32 Address
** Hardware specific memory address.
**
** OUTPUT:
**
** gctPOINTER * Logical
** Pointer to a variable that will hold the logical address of the
** specified memory address.
*/
gceSTATUS
gckKERNEL_MapVideoMemoryEx(
IN gckKERNEL Kernel,
IN gceCORE Core,
IN gctBOOL InUserSpace,
IN gctUINT32 Address,
IN gcePOOL Pool,
OUT gctPOINTER * Logical
)
{
gckGALDEVICE device = gcvNULL;
gctUINT32 offset = 0;
gctUINT32 base = 0;
gctSIZE_T bytes = 0;
gctPHYS_ADDR physical = gcvNULL;
gceSTATUS status;
gctPOINTER logical = gcvNULL;
#if gcdENABLE_VG
gcePOOL pool = gcvPOOL_UNKNOWN;
#endif
gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
Kernel, InUserSpace, Address);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Logical != NULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
#if gcdENABLE_VG
if (Core == gcvCORE_VG)
{
/* Split the memory address into a pool type and offset. */
gcmkONERROR(
gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset));
}
else
#endif
{
offset = Address;
}
/* Dispatch on pool. */
switch (Pool)
{
case gcvPOOL_LOCAL_INTERNAL:
/* Internal memory. */
logical = device->internalLogical;
/* Impossible to use per device logical for all user processes. */
BUG_ON("Incorrect path");
break;
case gcvPOOL_LOCAL_EXTERNAL:
physical = device->externalPhysical;
bytes = device->externalSize;
#if gcdENABLE_VG
if (Core == gcvCORE_VG)
{
gcmkVERIFY_OK(
gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
device->externalVidMem->baseAddress,
&pool,
&base));
}
else
#endif
{
base = Kernel->externalBaseAddress;
}
break;
case gcvPOOL_SYSTEM:
/* System memory. */
physical = device->contiguousPhysical;
bytes = device->contiguousSize;
#if gcdENABLE_VG
if (Core == gcvCORE_VG)
{
gcmkVERIFY_OK(
gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
device->contiguousVidMem->baseAddress,
&pool,
&base));
}
else
#endif
{
base = Kernel->contiguousBaseAddress;
}
break;
default:
/* Invalid memory pool. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gcmkONERROR(gckOS_MapMemory(Kernel->os, physical, bytes, &logical));
/* GPU address offset */
offset -= base;
/* Build logical address of specified address. */
*Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
/* Success. */
gcmkFOOTER_ARG("*Logical=%p", *Logical);
return gcvSTATUS_OK;
OnError:
/* Retunn the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckKERNEL_MapVideoMemory
**
** Get the logical address for a hardware specific memory address for the
** current process.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctBOOL InUserSpace
** gcvTRUE to map the memory into the user space.
**
** gctUINT32 Address
** Hardware specific memory address.
**
** OUTPUT:
**
** gctPOINTER * Logical
** Pointer to a variable that will hold the logical address of the
** specified memory address.
*/
gceSTATUS
gckKERNEL_MapVideoMemory(
IN gckKERNEL Kernel,
IN gctBOOL InUserSpace,
IN gctUINT32 Address,
OUT gctPOINTER * Logical
)
{
return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, gcvPOOL_SYSTEM, Logical);
}
/*******************************************************************************
**
** gckKERNEL_Notify
**
** This function iscalled by clients to notify the gckKERNRL object of an event.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gceNOTIFY Notification
** Notification event.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckKERNEL_Notify(
IN gckKERNEL Kernel,
IN gceNOTIFY Notification,
IN gctBOOL Data
)
{
gceSTATUS status;
/* Dispatch on notifcation. */
switch (Notification)
{
case gcvNOTIFY_INTERRUPT:
/* Process the interrupt. */
#if COMMAND_PROCESSOR_VERSION > 1
status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
#else
status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
#endif
break;
default:
status = gcvSTATUS_OK;
break;
}
/* Success. */
return status;
}
gceSTATUS
gckKERNEL_QuerySettings(
IN gckKERNEL Kernel,
OUT gcsKERNEL_SETTINGS * Settings
)
{
gckGALDEVICE device;
gcmkHEADER_ARG("Kernel=%p", Kernel);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Fill in signal. */
Settings->signal = device->signal;
/* Success. */
gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
return gcvSTATUS_OK;
}

View File

@ -0,0 +1,411 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_linux_h_
#define __gc_hal_kernel_linux_h_
#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/kthread.h>
#include <linux/idr.h>
#ifdef MODVERSIONS
# include <linux/modversions.h>
#endif
#include <asm/io.h>
#include <asm/uaccess.h>
#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
#include <linux/clk.h>
#endif
#define NTSTRSAFE_NO_CCH_FUNCTIONS
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_platform.h"
#include "gc_hal_kernel_device.h"
#include "gc_hal_kernel_os.h"
#include "gc_hal_kernel_debugfs.h"
#include "gc_hal_ta.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
#else
#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
#endif
#ifndef DEVICE_NAME
# define DEVICE_NAME "galcore"
#endif
#ifndef CLASS_NAME
# define CLASS_NAME "graphics_class"
#endif
#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
#else
#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
#endif
/* Protection bit when mapping memroy to user sapce */
#define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
#define gcdSUPPRESS_OOM_MESSAGE 1
#if gcdSUPPRESS_OOM_MESSAGE
#define gcdNOWARN __GFP_NOWARN
#else
#define gcdNOWARN 0
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 1, 0)
#ifdef gcdIRQ_SHARED
# define gcdIRQF_FLAG (IRQF_SHARED)
# else
# define gcdIRQF_FLAG (0)
# endif
#else
#ifdef gcdIRQ_SHARED
# define gcdIRQF_FLAG (IRQF_DISABLED | IRQF_SHARED)
# else
# define gcdIRQF_FLAG (IRQF_DISABLED)
# endif
#endif
/* gcdLINUX_SYNC_FILE and CONFIG_SYNC_FILE. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
# define dma_fence fence
# define dma_fence_array fence_array
# define dma_fence_ops fence_ops
# define dma_fence_default_wait fence_default_wait
# define dma_fence_signal(f) fence_signal(f)
# define dma_fence_signal_locked(f) fence_signal_locked(f)
# define dma_fence_get(f) fence_get(f)
# define dma_fence_put(f) fence_put(f)
# define dma_fence_is_array(f) fence_is_array(f)
# define dma_fence_is_signaled(f) fence_is_signaled(f)
# define to_dma_fence_array(f) to_fence_array(f)
# define dma_fence_wait_timeout(f, n, t) fence_wait_timeout((f), (n), (t))
# define dma_fence_init(f, o, l, t, s) fence_init((f), (o), (l), (t), (s))
# define dma_fence_context_alloc(s) fence_context_alloc(s)
#endif
extern struct device *galcore_device;
/******************************************************************************\
********************************** Structures **********************************
\******************************************************************************/
typedef struct _gcsIOMMU * gckIOMMU;
typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
typedef struct _gcsUSER_MAPPING
{
/* Pointer to next mapping structure. */
gcsUSER_MAPPING_PTR next;
/* Physical address of this mapping. */
gctUINT32 physical;
/* Logical address of this mapping. */
gctPOINTER logical;
/* Number of bytes of this mapping. */
gctSIZE_T bytes;
/* Starting address of this mapping. */
gctINT8_PTR start;
/* Ending address of this mapping. */
gctINT8_PTR end;
}
gcsUSER_MAPPING;
typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
typedef struct _gcsINTEGER_DB
{
struct idr idr;
spinlock_t lock;
gctINT curr;
}
gcsINTEGER_DB;
struct _gckOS
{
/* Object. */
gcsOBJECT object;
/* Pointer to device */
gckGALDEVICE device;
/* Memory management */
struct mutex mdlMutex;
struct list_head mdlHead;
/* Kernel process ID. */
gctUINT32 kernelProcessID;
/* Signal management. */
/* Lock. */
spinlock_t signalLock;
/* signal id database. */
gcsINTEGER_DB signalDB;
gcsUSER_MAPPING_PTR userMap;
/* workqueue for os timer. */
struct workqueue_struct * workqueue;
/* Allocate extra page to avoid cache overflow */
struct page* paddingPage;
/* Detect unfreed allocation. */
atomic_t allocateCount;
struct list_head allocatorList;
gcsDEBUGFS_DIR allocatorDebugfsDir;
gctBOOL allocatorLimitMarker;
/* Lock for register access check. */
spinlock_t registerAccessLock;
/* External power states. */
gctBOOL powerStates[gcdMAX_GPU_COUNT];
/* External clock states. */
gctBOOL clockStates[gcdMAX_GPU_COUNT];
/* IOMMU. */
gckIOMMU iommu;
};
typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
typedef struct _gcsSIGNAL
{
/* Kernel sync primitive. */
volatile unsigned int done;
spinlock_t lock;
wait_queue_head_t wait;
/* Manual reset flag. */
gctBOOL manualReset;
/* The reference counter. */
atomic_t ref;
/* The owner of the signal. */
gctHANDLE process;
/* ID. */
gctUINT32 id;
#if gcdLINUX_SYNC_FILE
#ifndef CONFIG_SYNC_FILE
/* Parent timeline. */
struct sync_timeline * timeline;
# else
struct dma_fence *fence;
# endif
#endif
}
gcsSIGNAL;
typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
typedef struct _gcsOSTIMER
{
struct delayed_work work;
gctTIMERFUNCTION function;
gctPOINTER data;
} gcsOSTIMER;
gceSTATUS
gckOS_ImportAllocators(
gckOS Os
);
gceSTATUS
gckOS_FreeAllocators(
gckOS Os
);
/* Reserved memory. */
gceSTATUS
gckOS_RequestReservedMemory(
gckOS Os,
unsigned long Start,
unsigned long Size,
const char * Name,
gctBOOL Requested,
void ** MemoryHandle
);
void
gckOS_ReleaseReservedMemory(
gckOS Os,
void * MemoryHandle
);
gceSTATUS
_ConvertLogical2Physical(
IN gckOS Os,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID,
IN PLINUX_MDL Mdl,
OUT gctPHYS_ADDR_T * Physical
);
gctBOOL
_QuerySignal(
IN gckOS Os,
IN gctSIGNAL Signal
);
static inline gctINT
_GetProcessID(
void
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
return task_tgid_vnr(current);
#else
return current->tgid;
#endif
}
static inline void
_MemoryBarrier(
void
)
{
#if defined(CONFIG_ARM) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
dsb();
#else
mb();
#endif
}
static inline void
_Barrier(
void
)
{
barrier();
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
static inline int
is_vmalloc_addr(
void *Addr
)
{
unsigned long addr = (unsigned long)Addr;
return addr >= VMALLOC_START && addr < VMALLOC_END;
}
#endif
#ifdef CONFIG_IOMMU_SUPPORT
void
gckIOMMU_Destory(
IN gckOS Os,
IN gckIOMMU Iommu
);
gceSTATUS
gckIOMMU_Construct(
IN gckOS Os,
OUT gckIOMMU * Iommu
);
gceSTATUS
gckIOMMU_Map(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Physical,
IN gctUINT32 Bytes
);
gceSTATUS
gckIOMMU_Unmap(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Bytes
);
#endif
#endif /* __gc_hal_kernel_linux_h_ */

View File

@ -0,0 +1,66 @@
/****************************************************************************
*
* 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_kernel_linux.h"
gctINT
gckMATH_ModuloInt(
IN gctINT X,
IN gctINT Y
)
{
if(Y ==0) {return 0;}
else {return X % Y;}
}

View File

@ -0,0 +1,89 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _gc_hal_kernel_mutex_h_
#define _gc_hal_kernel_mutex_h_
#include "gc_hal.h"
#include <linux/mutex.h>
/* Create a new mutex. */
#define gckOS_CreateMutex(Os, Mutex) \
({ \
gceSTATUS _status; \
gcmkHEADER_ARG("Os=0x%X", Os); \
\
/* Validate the arguments. */ \
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); \
gcmkVERIFY_ARGUMENT(Mutex != gcvNULL); \
\
/* Allocate the mutex structure. */ \
_status = gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex); \
\
if (gcmIS_SUCCESS(_status)) \
{ \
/* Initialize the mutex. */ \
mutex_init(*(struct mutex **)Mutex); \
} \
\
/* Return status. */ \
gcmkFOOTER_ARG("*Mutex=0x%X", *(struct mutex **)Mutex); \
_status; \
})
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_os_h_
#define __gc_hal_kernel_os_h_
typedef struct _LINUX_MDL LINUX_MDL, *PLINUX_MDL;
typedef struct _LINUX_MDL_MAP LINUX_MDL_MAP, *PLINUX_MDL_MAP;
struct _LINUX_MDL_MAP
{
gctINT pid;
/* map references. */
gctUINT32 count;
struct vm_area_struct * vma;
gctPOINTER vmaAddr;
gctBOOL cacheable;
struct list_head link;
};
struct _LINUX_MDL
{
gckOS os;
atomic_t refs;
/* Kernel address. */
char * addr;
/* Size and covered page count. */
size_t bytes;
gctINT numPages;
gctBOOL contiguous;
dma_addr_t dmaHandle;
gctBOOL cacheable;
struct mutex mapsMutex;
struct list_head mapsHead;
/* Pointer to allocator which allocates memory for this mdl. */
void * allocator;
/* Private data used by allocator. */
void * priv;
uint gid;
struct list_head link;
};
extern PLINUX_MDL_MAP
FindMdlMap(
IN PLINUX_MDL Mdl,
IN gctINT PID
);
typedef struct _DRIVER_ARGS
{
gctUINT64 InputBuffer;
gctUINT64 InputBufferSize;
gctUINT64 OutputBuffer;
gctUINT64 OutputBufferSize;
}
DRIVER_ARGS;
#endif /* __gc_hal_kernel_os_h_ */

View File

@ -0,0 +1,307 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _gc_hal_kernel_platform_h_
#define _gc_hal_kernel_platform_h_
#include <linux/mm.h>
#include <linux/platform_device.h>
#if USE_LINUX_PCIE
#include <linux/pci.h>
#endif
typedef struct _gcsMODULE_PARAMETERS
{
gctINT irqLine;
gctUINT registerMemBase;
gctUINT registerMemSize;
gctINT irqLine2D;
gctUINT registerMemBase2D;
gctUINT registerMemSize2D;
gctINT irqLineVG;
gctUINT registerMemBaseVG;
gctUINT registerMemSizeVG;
gctUINT contiguousSize;
gctUINT contiguousBase;
gctUINT contiguousRequested;
gctUINT externalSize;
gctUINT externalBase;
gctUINT bankSize;
gctINT fastClear;
gceCOMPRESSION_OPTION compression;
gctINT powerManagement;
gctINT gpuProfiler;
gctINT signal;
gctUINT baseAddress;
gctUINT physSize;
gctUINT logFileSize;
gctUINT recovery;
gctUINT stuckDump;
gctUINT showArgs;
gctUINT gpu3DMinClock;
gctBOOL registerMemMapped;
gctPOINTER registerMemAddress;
gctINT irqs[gcvCORE_COUNT];
gctUINT registerBases[gcvCORE_COUNT];
gctUINT registerSizes[gcvCORE_COUNT];
gctUINT chipIDs[gcvCORE_COUNT];
}
gcsMODULE_PARAMETERS;
typedef struct soc_platform gcsPLATFORM;
typedef struct soc_platform_ops
{
/*******************************************************************************
**
** adjustParam
**
** Override content of arguments, if a argument is not changed here, it will
** keep as default value or value set by insmod command line.
*/
gceSTATUS
(*adjustParam)(
IN gcsPLATFORM * Platform,
OUT gcsMODULE_PARAMETERS *Args
);
/*******************************************************************************
**
** getPower
**
** Prepare power and clock operation.
*/
gceSTATUS
(*getPower)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** putPower
**
** Finish power and clock operation.
*/
gceSTATUS
(*putPower)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** setPower
**
** Set power state of specified GPU.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to config.
**
** gceBOOL Enable
** Enable or disable power.
*/
gceSTATUS
(*setPower)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU,
IN gctBOOL Enable
);
/*******************************************************************************
**
** setClock
**
** Set clock state of specified GPU.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to config.
**
** gceBOOL Enable
** Enable or disable clock.
*/
gceSTATUS
(*setClock)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU,
IN gctBOOL Enable
);
/*******************************************************************************
**
** reset
**
** Reset GPU outside.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to reset.
*/
gceSTATUS
(*reset)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU
);
/*******************************************************************************
**
** getGPUPhysical
**
** Convert CPU physical address to GPU physical address if they are
** different.
*/
gceSTATUS
(*getGPUPhysical)(
IN gcsPLATFORM * Platform,
IN gctPHYS_ADDR_T CPUPhysical,
OUT gctPHYS_ADDR_T * GPUPhysical
);
/*******************************************************************************
**
** getCPUPhysical
**
** Convert GPU physical address to CPU physical address if they are
** different.
*/
gceSTATUS
(*getCPUPhysical)(
IN gcsPLATFORM * Platform,
IN gctUINT32 GPUPhysical,
OUT gctPHYS_ADDR_T * CPUPhysical
);
/*******************************************************************************
**
** adjustProt
**
** Override Prot flag when mapping paged memory to userspace.
*/
gceSTATUS
(*adjustProt)(
IN struct vm_area_struct * vma
);
/*******************************************************************************
**
** shrinkMemory
**
** Do something to collect memory, eg, act as oom killer.
*/
gceSTATUS
(*shrinkMemory)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** cache
**
** Cache operation.
*/
gceSTATUS
(*cache)(
IN gcsPLATFORM * Platform,
IN gctUINT32 ProcessID,
IN gctPHYS_ADDR Handle,
IN gctUINT32 Physical,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
);
/*******************************************************************************
**
** getPolicyID
**
** Get policyID for a specified surface type.
*/
gceSTATUS
(*getPolicyID)(
IN gcsPLATFORM * Platform,
IN gceSURF_TYPE Type,
OUT gctUINT32_PTR PolicyID,
OUT gctUINT32_PTR AXIConfig
);
}
gcsPLATFORM_OPERATIONS;
struct soc_platform
{
#if USE_LINUX_PCIE
struct pci_dev* device;
struct pci_driver* driver;
#else
struct platform_device* device;
struct platform_driver* driver;
#endif
const char *name;
gcsPLATFORM_OPERATIONS* ops;
/* PLATFORM specific flags */
gctUINT32 flagBits;
};
#if USE_LINUX_PCIE
int soc_platform_init(struct pci_driver *pdrv, gcsPLATFORM **platform);
#else
int soc_platform_init(struct platform_driver *pdrv, gcsPLATFORM **platform);
#endif
int soc_platform_terminate(gcsPLATFORM *platform);
#endif

View File

@ -0,0 +1,426 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include <linux/slab.h>
#include "tee_client_api.h"
#define _GC_OBJ_ZONE gcvZONE_OS
#define GPU3D_UUID { 0xcc9f80ea, 0xa836, 0x11e3, { 0x9b, 0x07, 0x78, 0x2b, 0xcb, 0x5c, 0xf3, 0xe3 } }
static const TEEC_UUID gpu3d_uuid = GPU3D_UUID;
TEEC_Context teecContext;
typedef struct _gcsSecurityChannel
{
gckOS os;
TEEC_Session session;
int * virtual;
TEEC_SharedMemory inputBuffer;
gctUINT32 bytes;
gctPOINTER mutex;
}
gcsSecurityChannel;
TEEC_SharedMemory *
gpu3d_allocate_secure_mem(
gckOS Os,
unsigned int size
)
{
TEEC_Result result;
TEEC_Context *context = &teecContext;
TEEC_SharedMemory *shm = NULL;
void *handle = NULL;
gctPHYS_ADDR_T phyAddr;
gceSTATUS status;
gctSIZE_T bytes = size;
shm = kmalloc(sizeof(TEEC_SharedMemory), GFP_KERNEL);
if (NULL == shm)
{
return NULL;
}
memset(shm, 0, sizeof(TEEC_SharedMemory));
status = gckOS_AllocatePagedMemoryEx(
Os,
gcvALLOC_FLAG_SECURITY,
bytes,
gcvNULL,
(gctPHYS_ADDR *)&handle);
if (gcmIS_ERROR(status))
{
kfree(shm);
return NULL;
}
status = gckOS_PhysicalToPhysicalAddress(
Os,
handle,
0,
&phyAddr);
if (gcmIS_ERROR(status))
{
kfree(shm);
return NULL;
}
/* record the handle into shm->user_data */
shm->userdata = handle;
/* [b] Bulk input buffer. */
shm->size = size;
shm->flags = TEEC_MEM_INPUT;
/* Use TEE Client API to register the underlying memory buffer. */
shm->phyAddr = (void *)(gctUINT32)phyAddr;
result = TEEC_RegisterSharedMemory(
context,
shm);
if (result != TEEC_SUCCESS)
{
gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
kfree(shm);
return NULL;
}
return shm;
}
void gpu3d_release_secure_mem(
gckOS Os,
void *shm_handle
)
{
TEEC_SharedMemory *shm = shm_handle;
void * handle;
if (!shm)
{
return;
}
handle = shm->userdata;
TEEC_ReleaseSharedMemory(shm);
gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
kfree(shm);
return;
}
static TEEC_Result gpu3d_session_callback(
TEEC_Session* session,
uint32_t commandID,
TEEC_Operation* operation,
void* userdata
)
{
gcsSecurityChannel *channel = userdata;
if (channel == gcvNULL)
{
return TEEC_ERROR_BAD_PARAMETERS;
}
switch (commandID)
{
case gcvTA_CALLBACK_ALLOC_SECURE_MEM:
{
uint32_t size = operation->params[0].value.a;
TEEC_SharedMemory *shm = NULL;
shm = gpu3d_allocate_secure_mem(channel->os, size);
if (shm == NULL)
{
return TEEC_ERROR_OUT_OF_MEMORY;
}
/* use the value to save the pointer in client side */
operation->params[0].value.a = (uint32_t)shm;
operation->params[0].value.b = (uint32_t)shm->phyAddr;
break;
}
case gcvTA_CALLBACK_FREE_SECURE_MEM:
{
TEEC_SharedMemory *shm = (TEEC_SharedMemory *)operation->params[0].value.a;
gpu3d_release_secure_mem(channel->os, shm);
break;
}
default:
break;
}
return TEEC_SUCCESS;
}
gceSTATUS
gckOS_OpenSecurityChannel(
IN gckOS Os,
IN gceCORE GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
TEEC_Result result;
static bool initialized = gcvFALSE;
gcsSecurityChannel *channel = gcvNULL;
TEEC_Operation operation = {0};
/* Connect to TEE. */
if (initialized == gcvFALSE)
{
result = TEEC_InitializeContext(NULL, &teecContext);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_CHIP_NOT_READY);
}
initialized = gcvTRUE;
}
/* Construct channel. */
gcmkONERROR(
gckOS_Allocate(Os, gcmSIZEOF(*channel), (gctPOINTER *)&channel));
gckOS_ZeroMemory(channel, gcmSIZEOF(gcsSecurityChannel));
channel->os = Os;
gcmkONERROR(gckOS_CreateMutex(Os, &channel->mutex));
/* Allocate shared memory for passing gcTA_INTERFACE. */
channel->bytes = gcmSIZEOF(gcsTA_INTERFACE);
channel->virtual = kmalloc(channel->bytes, GFP_KERNEL | __GFP_NOWARN);
if (!channel->virtual)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
channel->inputBuffer.size = channel->bytes;
channel->inputBuffer.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
channel->inputBuffer.phyAddr = (void *)virt_to_phys(channel->virtual);
result = TEEC_RegisterSharedMemory(&teecContext, &channel->inputBuffer);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_VALUE_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
operation.params[0].value.a = GPU;
/* Open session with TEE application. */
result = TEEC_OpenSession(
&teecContext,
&channel->session,
&gpu3d_uuid,
TEEC_LOGIN_USER,
NULL,
&operation,
NULL);
/* Prepare callback. */
TEEC_RegisterCallback(&channel->session, gpu3d_session_callback, channel);
*Channel = (gctUINT32)channel;
return gcvSTATUS_OK;
OnError:
if (channel)
{
if (channel->virtual)
{
}
if (channel->mutex)
{
gcmkVERIFY_OK(gckOS_DeleteMutex(Os, channel->mutex));
}
gcmkVERIFY_OK(gckOS_Free(Os, channel));
}
return status;
}
gceSTATUS
gckOS_CloseSecurityChannel(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_CallSecurityService(
IN gctUINT32 Channel,
IN gcsTA_INTERFACE *Interface
)
{
gceSTATUS status;
TEEC_Result result;
gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
TEEC_Operation operation = {0};
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
gckOS_AcquireMutex(channel->os, channel->mutex, gcvINFINITE);
gckOS_MemCopy(channel->virtual, Interface, channel->bytes);
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_PARTIAL_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
/* Note: we use the updated size in the MemRef output by the encryption. */
operation.params[0].memref.parent = &channel->inputBuffer;
operation.params[0].memref.offset = 0;
operation.params[0].memref.size = sizeof(gcsTA_INTERFACE);
operation.started = true;
/* Start the commit command within the TEE application. */
result = TEEC_InvokeCommand(
&channel->session,
gcvTA_COMMAND_DISPATCH,
&operation,
NULL);
gckOS_MemCopy(Interface, channel->virtual, channel->bytes);
gckOS_ReleaseMutex(channel->os, channel->mutex);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckOS_InitSecurityChannel(
IN gctUINT32 Channel
)
{
gceSTATUS status;
TEEC_Result result;
gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
TEEC_Operation operation = {0};
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_PARTIAL_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
/* Note: we use the updated size in the MemRef output by the encryption. */
operation.params[0].memref.parent = &channel->inputBuffer;
operation.params[0].memref.offset = 0;
operation.params[0].memref.size = gcmSIZEOF(gcsTA_INTERFACE);
operation.started = true;
/* Start the commit command within the TEE application. */
result = TEEC_InvokeCommand(
&channel->session,
gcvTA_COMMAND_INIT,
&operation,
NULL);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}

View File

@ -0,0 +1,116 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#define _GC_OBJ_ZONE gcvZONE_OS
#if gcdENABLE_TRUST_APPLICATION
gceSTATUS
gckOS_OpenSecurityChannel(
IN gckOS Os,
IN gceCORE Core,
OUT gctUINT32 *Channel
)
{
*Channel = Core + 1;
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_InitSecurityChannel(
OUT gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_CloseSecurityChannel(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
extern gceSTATUS
TAEmulator (
gceCORE,
void *
);
gceSTATUS
gckOS_CallSecurityService(
IN gctUINT32 Channel,
IN gcsTA_INTERFACE *Interface
)
{
gceCORE core;
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
core = (gceCORE)(Channel - 1);
TAEmulator(core, Interface);
status = Interface->result;
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,378 @@
/****************************************************************************
*
* 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.h>
#include <gc_hal_base.h>
#if gcdLINUX_SYNC_FILE
#include <linux/kernel.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "gc_hal_kernel_sync.h"
#include "gc_hal_kernel_linux.h"
#ifndef CONFIG_SYNC_FILE
static struct sync_pt * viv_sync_pt_dup(struct sync_pt *sync_pt)
{
gceSTATUS status;
struct viv_sync_pt *pt;
struct viv_sync_pt *src;
struct viv_sync_timeline *obj;
src = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
/* Create the new sync_pt. */
pt = (struct viv_sync_pt *)
sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
pt->stamp = src->stamp;
/* Reference signal. */
status = gckOS_MapSignal(obj->os,
src->signal,
gcvNULL /* (gctHANDLE) _GetProcessID() */,
&pt->signal);
if (gcmIS_ERROR(status)) {
sync_pt_free((struct sync_pt *)pt);
return NULL;
}
return (struct sync_pt *)pt;
}
static int viv_sync_pt_has_signaled(struct sync_pt *sync_pt)
{
gceSTATUS status;
struct viv_sync_pt *pt;
struct viv_sync_timeline *obj;
pt = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
status = _QuerySignal(obj->os, pt->signal);
if (gcmIS_ERROR(status)) {
/* Error. */
return -1;
}
return (int) status;
}
static int viv_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
{
int ret;
struct viv_sync_pt *pt1 = (struct viv_sync_pt *)a;
struct viv_sync_pt *pt2 = (struct viv_sync_pt *)b;
ret = (pt1->stamp < pt2->stamp) ? -1
: (pt1->stamp == pt2->stamp) ? 0
: 1;
return ret;
}
static void viv_sync_pt_free(struct sync_pt *sync_pt)
{
struct viv_sync_pt *pt;
struct viv_sync_timeline *obj;
pt = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
gckOS_DestroySignal(obj->os, pt->signal);
}
static void viv_timeline_value_str(struct sync_timeline *timeline,
char *str, int size)
{
struct viv_sync_timeline *obj;
obj = (struct viv_sync_timeline *)timeline;
snprintf(str, size, "stamp_%llu", obj->stamp);
}
static void viv_pt_value_str(struct sync_pt *sync_pt, char *str, int size)
{
struct viv_sync_pt *pt;
pt = (struct viv_sync_pt *)sync_pt;
snprintf(str, size, "signal_%lu@stamp_%llu",
(unsigned long)pt->signal, pt->stamp);
}
static struct sync_timeline_ops viv_timeline_ops =
{
.driver_name = "viv_gpu_sync",
.dup = viv_sync_pt_dup,
.has_signaled = viv_sync_pt_has_signaled,
.compare = viv_sync_pt_compare,
.free_pt = viv_sync_pt_free,
.timeline_value_str = viv_timeline_value_str,
.pt_value_str = viv_pt_value_str,
};
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS os)
{
struct viv_sync_timeline * obj;
obj = (struct viv_sync_timeline *)
sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
obj->os = os;
obj->stamp = 0;
return obj;
}
struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
gctSIGNAL Signal)
{
gceSTATUS status;
struct viv_sync_pt *pt;
pt = (struct viv_sync_pt *)
sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
pt->stamp = obj->stamp++;
/* Dup signal. */
status = gckOS_MapSignal(obj->os,
Signal,
gcvNULL /* (gctHANDLE) _GetProcessID() */,
&pt->signal);
if (gcmIS_ERROR(status)) {
sync_pt_free((struct sync_pt *)pt);
return NULL;
}
return (struct sync_pt *)pt;
}
#else
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os)
{
struct viv_sync_timeline *timeline;
timeline = kmalloc(sizeof(struct viv_sync_timeline),
gcdNOWARN | GFP_KERNEL);
if (!timeline)
return NULL;
strncpy(timeline->name, name, sizeof(timeline->name) - 1);
timeline->context = dma_fence_context_alloc(1);
atomic64_set(&timeline->seqno, 0);
timeline->os = Os;
return timeline;
}
void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline)
{
kfree(timeline);
}
static const char * viv_fence_get_driver_name(struct dma_fence *fence)
{
return "viv_gpu_sync";
}
static const char * viv_fence_get_timeline_name(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
return f->parent->name;
}
/* Same as fence_signaled. */
static inline bool __viv_fence_signaled(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
gceSTATUS status;
status = _QuerySignal(timeline->os, f->signal);
return (status == gcvSTATUS_TRUE) ? true : false;
}
static bool viv_fence_enable_signaling(struct dma_fence *fence)
{
/* fence is locked already. */
return !__viv_fence_signaled(fence);
}
static bool viv_fence_signaled(struct dma_fence *fence)
{
/* fence could be locked, could be not. */
return __viv_fence_signaled(fence);
}
static void viv_fence_release(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
if (f->signal)
gckOS_DestroySignal(timeline->os, f->signal);
kfree(fence);
}
static struct dma_fence_ops viv_fence_ops =
{
.get_driver_name = viv_fence_get_driver_name,
.get_timeline_name = viv_fence_get_timeline_name,
.enable_signaling = viv_fence_enable_signaling,
.signaled = viv_fence_signaled,
.wait = dma_fence_default_wait,
.release = viv_fence_release,
};
struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal)
{
gceSTATUS status;
struct viv_fence *fence;
struct dma_fence *old_fence = NULL;
unsigned seqno;
fence = kzalloc(sizeof(struct viv_fence), gcdNOWARN | GFP_KERNEL);
if (!fence)
return NULL;
/* Reference signal in fence. */
status = gckOS_MapSignal(timeline->os, (gctSIGNAL)(uintptr_t)signal->id,
NULL, &fence->signal);
if (gcmIS_ERROR(status)) {
kfree(fence);
return NULL;
}
spin_lock_init(&fence->lock);
fence->parent = timeline;
seqno = (unsigned)atomic64_inc_return(&timeline->seqno);
dma_fence_init((struct dma_fence *)fence, &viv_fence_ops,
&fence->lock, timeline->context, seqno);
/*
* Reference fence in signal.
* Be aware of recursive reference!!
*/
spin_lock(&signal->lock);
if (signal->fence) {
old_fence = signal->fence;
signal->fence = NULL;
}
if (!signal->done) {
signal->fence = (struct dma_fence*)fence;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,68)
dma_fence_get((struct dma_fence*)fence);
#endif
}
spin_unlock(&signal->lock);
if (old_fence)
dma_fence_put(old_fence);
if (!signal->fence) {
/* Fence already signaled. */
gckOS_DestroySignal(timeline->os, fence->signal);
fence->signal = NULL;
dma_fence_signal_locked((struct dma_fence*)fence);
dma_fence_put((struct dma_fence*)fence);
fence = NULL;
}
return (struct dma_fence*)fence;
}
#endif
#endif

View File

@ -0,0 +1,151 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_sync_h_
#define __gc_hal_kernel_sync_h_
#include <linux/types.h>
#ifndef CONFIG_SYNC_FILE
/* sync.h is in drivers/staging/android/ for now. */
#include <sync.h>
#include <gc_hal.h>
#include <gc_hal_base.h>
struct viv_sync_timeline
{
/* Parent object. */
struct sync_timeline obj;
/* Timestamp when sync_pt is created. */
gctUINT64 stamp;
/* Pointer to os struct. */
gckOS os;
};
struct viv_sync_pt
{
/* Parent object. */
struct sync_pt pt;
/* Reference signal. */
gctSIGNAL signal;
/* Timestamp when sync_pt is created. */
gctUINT64 stamp;
};
/* Create viv_sync_timeline object. */
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
/* Create viv_sync_pt object. */
struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
gctSIGNAL signal);
#else
#include <linux/sync_file.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
# include <linux/fence.h>
# include <linux/fence-array.h>
#else
# include <linux/dma-fence.h>
# include <linux/dma-fence-array.h>
#endif
#include <gc_hal.h>
#include <gc_hal_base.h>
#include "gc_hal_kernel_linux.h"
struct viv_sync_timeline
{
char name[64];
/* Parent object. */
u64 context;
/* Timestamp when sync_pt is created. */
atomic64_t seqno;
/* Pointer to os struct. */
gckOS os;
};
struct viv_fence
{
/* must be the first. */
struct dma_fence base;
spinlock_t lock;
struct viv_sync_timeline *parent;
/* link with signal. */
gctSIGNAL signal;
};
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline);
struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal);
#endif
#endif /* __gc_hal_kernel_sync_h_ */

View File

@ -0,0 +1,146 @@
/****************************************************************************
*
* 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_kernel_linux.h"
#include "gc_hal_kernel_platform.h"
gceSTATUS
_AdjustParam(
IN gcsPLATFORM *Platform,
OUT gcsMODULE_PARAMETERS *Args
)
{
#if USE_LINUX_PCIE
struct pci_dev *pdev = Platform->device;
unsigned char irqline = pdev->irq;
if ((Args->irqLine2D != -1) && (Args->irqLine2D != irqline))
{
Args->irqLine2D = irqline;
}
if ((Args->irqLine != -1) && (Args->irqLine != irqline))
{
Args->irqLine = irqline;
}
#endif
return gcvSTATUS_OK;
}
static struct soc_platform_ops default_ops =
{
.adjustParam = _AdjustParam,
};
static struct soc_platform default_platform =
{
.name = __FILE__,
.ops = &default_ops,
};
#if USE_LINUX_PCIE
int soc_platform_init(struct pci_driver *pdrv,
struct soc_platform **platform)
{
*platform = &default_platform;
return 0;
}
int soc_platform_terminate(struct soc_platform *platform)
{
return 0;
}
#else
static struct platform_device *default_dev;
int soc_platform_init(struct platform_driver *pdrv,
struct soc_platform **platform)
{
int ret;
default_dev = platform_device_alloc(pdrv->driver.name, -1);
if (!default_dev) {
printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
return -ENOMEM;
}
/* Add device */
ret = platform_device_add(default_dev);
if (ret) {
printk(KERN_ERR "galcore: platform_device_add failed.\n");
goto put_dev;
}
*platform = &default_platform;
return 0;
put_dev:
platform_device_put(default_dev);
return ret;
}
int soc_platform_terminate(struct soc_platform *platform)
{
if (default_dev) {
platform_device_unregister(default_dev);
default_dev = NULL;
}
return 0;
}
#endif

View File

@ -0,0 +1,29 @@
EXTRA_CFLAGS += -DgcdDEFAULT_CONTIGUOUS_SIZE=~0U
EXTRA_CFLAGS += -DgcdFSL_CONTIGUOUS_SIZE=134217728
ifneq ($(CONFIG_ANDROID),)
# build for android
EXTRA_CFLAGS += -DgcdANDROID
endif
EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2
ifeq ($(CONFIG_SYNC)$(CONFIG_SYNC_FILE),)
$(warn CONFIG_SYNC or CONFIG_SYNC_FILE is not set in kernel config)
$(warn Android native fence sync requires CONFIG_SYNC or CONFIG_SYNC_FILE)
endif
ifneq ($(CONFIG_ARCH_FSL_IMX8QM),)
EXTRA_CFLAGS += -DIMX8_SCU_CONTROL=1 -DIMX8_PHYS_BASE=0x80000000 -DIMX8_PHYS_SIZE=0x80000000
endif
EXTRA_CFLAGS += -DLINUX_CMA_FSL=1
ALLOCATOR_ARRAY_H_LOCATION := $(OS_KERNEL_DIR)/allocator/freescale
CUSTOMER_ALLOCATOR_OBJS := $(ALLOCATOR_ARRAY_H_LOCATION)/gc_hal_kernel_allocator_cma.o
EXTRA_CFLAGS += -DCLASS_NAME=\"gpu_class\"
EXTRA_CFLAGS += -DgcdGPU_2D_TIMEOUT=20000
EXTRA_CFLAGS += -DNO_DMA_COHERENT=1
EXTRA_CFLAGS += -DgcdSYS_FREE_MEMORY_LIMIT=51200

View File

@ -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;
}

View File

@ -0,0 +1,373 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _GC_HAL_TA_H_
#define _GC_HAL_TA_H_
#include "gc_hal_types.h"
#include "gc_hal_security_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _gctaOS * gctaOS;
typedef struct _gcTA * gcTA;
typedef struct _gcTA_HARDWARE * gcTA_HARDWARE;
typedef struct _gcTA_MMU * gcTA_MMU;
/*
Trust Application is a object needed to be created as a context in trust zone.
One client for a core.
*/
typedef struct _gcTA {
/* gctaOS object */
gctaOS os;
gceCORE core;
gcTA_MMU mmu;
gcTA_HARDWARE hardware;
gctBOOL destoryMmu;
} gcsTA;
typedef struct _gcTA_MMU
{
gctaOS os;
gctSIZE_T mtlbBytes;
gctPOINTER mtlbLogical;
gctPHYS_ADDR mtlbPhysical;
gctPOINTER stlbs;
gctPOINTER safePageLogical;
gctPHYS_ADDR safePagePhysical;
gctPOINTER nonSecureSafePageLogical;
gctPHYS_ADDR nonSecureSafePagePhysical;
gctPOINTER mutex;
}
gcsTA_MMU;
gceSTATUS HALDECL
TAEmulator(
gceCORE Core,
void * Interface
);
int
gcTA_Construct(
IN gctaOS Os,
IN gceCORE Core,
OUT gcTA *TA
);
int
gcTA_Destroy(
IN gcTA TA
);
int
gcTA_Dispatch(
IN gcTA TA,
IN OUT gcsTA_INTERFACE * Interface
);
/*************************************
* Porting layer
*/
gceSTATUS
gctaOS_ConstructOS(
IN gckOS Os,
OUT gctaOS *TAos
);
gceSTATUS
gctaOS_DestroyOS(
IN gctaOS Os
);
gceSTATUS
gctaOS_Allocate(
IN gctUINT32 Bytes,
OUT gctPOINTER *Pointer
);
gceSTATUS
gctaOS_Free(
IN gctPOINTER Pointer
);
gceSTATUS
gctaOS_AllocateSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T *Bytes,
OUT gctPOINTER *Logical,
OUT gctPOINTER *Physical
);
gceSTATUS
gctaOS_FreeSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
OUT gctPOINTER Physical
);
gceSTATUS
gctaOS_AllocateNonSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T *Bytes,
OUT gctPOINTER *Logical,
OUT gctPOINTER *Physical
);
gceSTATUS
gctaOS_FreeNonSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
OUT gctPOINTER Physical
);
gceSTATUS
gctaOS_GetPhysicalAddress(
IN gctaOS Os,
IN gctPOINTER Logical,
OUT gctPHYS_ADDR_T * Physical
);
gceSTATUS gctaOS_WriteRegister(
IN gctaOS Os, IN gceCORE Core,
IN gctUINT32 Address,
IN gctUINT32 Data
);
gceSTATUS gctaOS_ReadRegister(
IN gctaOS Os, IN gceCORE Core,
IN gctUINT32 Address,
IN gctUINT32 *Data
);
gceSTATUS
gctaOS_MemCopy(
IN gctUINT8_PTR Dest,
IN gctUINT8_PTR Src,
IN gctUINT32 Bytes
);
gceSTATUS
gctaOS_ZeroMemory(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
);
void
gctaOS_CacheFlush(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
);
void
gctaOS_CacheClean(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
);
void
gctaOS_CacheInvalidate(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
);
gceSTATUS
gctaOS_IsPhysicalSecure(
IN gctaOS Os,
IN gctUINT32 Physical,
OUT gctBOOL *Secure
);
gceSTATUS
gctaOS_Delay(
IN gctaOS Os,
IN gctUINT32 Delay
);
gceSTATUS
gctaOS_SetGPUPower(
IN gctaOS Os,
IN gctUINT32 Core,
IN gctBOOL Clock,
IN gctBOOL Power
);
/*
** gctaHARDWARE
*/
gceSTATUS
gctaHARDWARE_Construct(
IN gcTA TA,
OUT gcTA_HARDWARE * Hardware
);
gceSTATUS
gctaHARDWARE_Destroy(
IN gcTA_HARDWARE Hardware
);
gceSTATUS
gctaHARDWARE_Execute(
IN gcTA TA,
IN gctUINT32 Address,
IN gctUINT32 Bytes
);
gceSTATUS
gctaHARDWARE_End(
IN gcTA_HARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctUINT32 * Bytes
);
gceSTATUS
gctaHARDWARE_SetMMU(
IN gcTA_HARDWARE Hardware,
IN gctPOINTER Logical
);
gceSTATUS
gctaHARDWARE_IsFeatureAvailable(
IN gcTA_HARDWARE Hardware,
IN gceFEATURE Feature
);
gceSTATUS
gctaHARDWARE_PrepareFunctions(
IN gcTA_HARDWARE Hardware
);
gceSTATUS
gctaHARDWARE_DumpMMUException(
IN gcTA_HARDWARE Hardware
);
gceSTATUS
gctaHARDWARE_HandleMMUException(
IN gcTA_HARDWARE Hardware,
IN gctUINT32 MMUStatus,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 GPUAddress
);
gceSTATUS
gctaHARDWARE_ReadMMUException(
IN gcTA_HARDWARE Hardware,
OUT gctUINT32_PTR MMUStatus,
OUT gctUINT32_PTR MMUException
);
gceSTATUS
gctaMMU_Construct(
IN gcTA TA,
OUT gcTA_MMU *Mmu
);
gceSTATUS
gctaMMU_Destory(
IN gcTA_MMU Mmu
);
gceSTATUS
gctaMMU_SetPage(
IN gcTA_MMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
);
gceSTATUS
gctaMMU_GetPageEntry(
IN gcTA_MMU Mmu,
IN gctUINT32 Address,
OUT gctUINT32_PTR MtlbEntry,
OUT gctUINT32_PTR *PageTable,
OUT gctBOOL * Secure
);
void
gctaMMU_DumpPagetableEntry(
IN gcTA_MMU Mmu,
IN gctUINT32 Address
);
gceSTATUS
gctaMMU_FreePages(
IN gcTA_MMU Mmu,
IN gctUINT32 Address,
IN gctUINT32 PageCount
);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _GC_HAL_TA_HARDWARE_H_
#define _GC_HAL_TA_HARDWARE_H_
#include "gc_hal_types.h"
#include "gc_hal_security_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _gcsMMU_TABLE_ARRAY_ENTRY
{
gctUINT32 low;
gctUINT32 high;
}
gcsMMU_TABLE_ARRAY_ENTRY;
typedef struct _gcsHARDWARE_PAGETABLE_ARRAY
{
/* Number of entries in page table array. */
gctUINT num;
/* Size in bytes of array. */
gctSIZE_T size;
/* Physical address of array. */
gctPHYS_ADDR_T address;
/* Memory descriptor. */
gctPOINTER physical;
/* Logical address of array. */
gctPOINTER logical;
}
gcsHARDWARE_PAGETABLE_ARRAY;
typedef struct _gcsHARWARE_FUNCTION
{
/* Entry of the function. */
gctUINT32 address;
/* CPU address of the function. */
gctUINT8_PTR logical;
/* Bytes of the function. */
gctUINT32 bytes;
/* Hardware address of END in this function. */
gctUINT32 endAddress;
/* Logical of END in this function. */
gctUINT8_PTR endLogical;
}
gcsHARDWARE_FUNCTION;
typedef struct _gcTA_HARDWARE
{
gctaOS os;
gcTA ta;
gctUINT32 chipModel;
gctUINT32 chipRevision;
gctUINT32 productID;
gctUINT32 ecoID;
gctUINT32 customerID;
gctPOINTER featureDatabase;
gcsHARDWARE_PAGETABLE_ARRAY pagetableArray;
/* Function used by gctaHARDWARE. */
gctPHYS_ADDR functionPhysical;
gctPOINTER functionLogical;
gctUINT32 functionAddress;
gctSIZE_T functionBytes;
gcsHARDWARE_FUNCTION functions[1];
}
gcsTA_HARDWARE;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,586 @@
/****************************************************************************
*
* 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 2
/*******************************************************************************
************************************ Define ************************************
********************************************************************************/
#define gcdMMU_MTLB_SHIFT 22
#define gcdMMU_STLB_4K_SHIFT 12
#define gcdMMU_STLB_64K_SHIFT 16
#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
/* Page offset definitions. */
#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
#define gcdMMU_OFFSET_16K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
#define gcdMMU_OFFSET_16K_MASK ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
#define gcdMMU_MTLB_PRESENT 0x00000001
#define gcdMMU_MTLB_EXCEPTION 0x00000002
#define gcdMMU_MTLB_4K_PAGE 0x00000000
#define gcdMMU_STLB_PRESENT 0x00000001
#define gcdMMU_STLB_EXCEPTION 0x00000002
#define gcdMMU_STLB_SECURITY (1 << 4)
#define gcdMMU_STLB_4K_PAGE 0x00000000
#define gcdUSE_MMU_EXCEPTION 1
#define gcdMMU_SECURE_AREA_START ((gcdMMU_MTLB_ENTRY_NUM - gcdMMU_SECURE_AREA_SIZE) << gcdMMU_MTLB_SHIFT)
typedef enum _gceMMU_TYPE
{
gcvMMU_USED = (0 << 4),
gcvMMU_SINGLE = (1 << 4),
gcvMMU_FREE = (2 << 4),
}
gceMMU_TYPE;
typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
typedef struct _gcsMMU_STLB
{
gctPHYS_ADDR physical;
gctUINT32_PTR logical;
gctSIZE_T size;
gctPHYS_ADDR_T physBase;
gctSIZE_T pageCount;
gctUINT32 mtlbIndex;
gctUINT32 mtlbEntryNum;
gcsMMU_STLB_PTR next;
} gcsMMU_STLB;
#define gcmENTRY_TYPE(x) (x & 0xF0)
/*
* We need flat mapping ta command buffer.
*/
/*
* Helper
*/
gctUINT32
_MtlbOffset(
gctUINT32 Address
)
{
return (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
}
gctUINT32
_StlbOffset(
gctUINT32 Address
)
{
return (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
}
static gctUINT32
_SetPage(gctUINT32 PageAddress)
{
return PageAddress
/* writable */
| (1 << 2)
/* Ignore exception */
| (0 << 1)
/* Present */
| (1 << 0);
}
static void
_WritePageEntry(
IN gctUINT32_PTR PageEntry,
IN gctUINT32 EntryValue
)
{
*PageEntry = EntryValue;
gctaOS_CacheClean((gctUINT8_PTR)PageEntry, gcmSIZEOF(gctUINT32));
}
static gceSTATUS
_FillPageTable(
IN gctUINT32_PTR PageTable,
IN gctUINT32 PageCount,
IN gctUINT32 EntryValue
)
{
gctUINT i;
for (i = 0; i < PageCount; i++)
{
_WritePageEntry(PageTable + i, EntryValue);
}
return gcvSTATUS_OK;
}
static gceSTATUS
_AllocateStlb(
IN gctaOS Os,
OUT gcsMMU_STLB_PTR *Stlb
)
{
gceSTATUS status;
gcsMMU_STLB_PTR stlb;
gctPOINTER pointer = gcvNULL;
/* Allocate slave TLB record. */
gcmkONERROR(gctaOS_Allocate(gcmSIZEOF(gcsMMU_STLB), &pointer));
stlb = pointer;
stlb->size = gcdMMU_STLB_4K_SIZE;
/* Allocate slave TLB entries. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
Os,
&stlb->size,
(gctPOINTER *)&stlb->logical,
&stlb->physical
));
gcmkONERROR(gctaOS_GetPhysicalAddress(Os, stlb->logical, &stlb->physBase));
#if gcdUSE_MMU_EXCEPTION
_FillPageTable(stlb->logical, (gctUINT32)stlb->size / 4, gcdMMU_STLB_EXCEPTION);
#else
gctaOS_ZeroMemory(stlb->logical, (gctUINT32)stlb->size);
#endif
*Stlb = stlb;
return gcvSTATUS_OK;
OnError:
if(pointer != gcvNULL)
gcmkVERIFY_OK(gctaOS_Free(pointer));
return status;
}
gceSTATUS
gctaMMU_Construct(
IN gcTA TA,
OUT gcTA_MMU *Mmu
)
{
gceSTATUS status;
gctSIZE_T bytes = 4096;
gcTA_MMU mmu = gcvNULL;
gcmkONERROR(gctaOS_Allocate(
gcmSIZEOF(gcsTA_MMU),
(gctPOINTER *)&mmu
));
mmu->mtlbLogical = gcvNULL;
mmu->stlbs = gcvNULL;
mmu->safePageLogical = gcvNULL;
mmu->nonSecureSafePageLogical = gcvNULL;
mmu->os = TA->os;
/* MTLB bytes. */
mmu->mtlbBytes = gcdMMU_MTLB_SIZE;
/* Allocate MTLB. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
TA->os,
&mmu->mtlbBytes,
&mmu->mtlbLogical,
&mmu->mtlbPhysical
));
#if gcdUSE_MMU_EXCEPTION
_FillPageTable(mmu->mtlbLogical, (gctUINT32)mmu->mtlbBytes / 4, gcdMMU_STLB_EXCEPTION);
#else
gctaOS_ZeroMemory(mmu->mtlbLogical, (gctUINT32)mmu->mtlbBytes);
#endif
/* Allocate a array to store stlbs. */
gcmkONERROR(gctaOS_Allocate((gctUINT32)mmu->mtlbBytes, &mmu->stlbs));
gctaOS_ZeroMemory((gctUINT8_PTR)mmu->stlbs, (gctUINT32)mmu->mtlbBytes);
/* Allocate security safe page. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
TA->os,
&bytes,
&mmu->safePageLogical,
&mmu->safePagePhysical
));
gctaOS_ZeroMemory((gctUINT8_PTR)mmu->safePageLogical, (gctUINT32)bytes);
/* Allocate non security safe page. */
gcmkONERROR(gctaOS_AllocateSecurityMemory(
TA->os,
&bytes,
&mmu->nonSecureSafePageLogical,
&mmu->nonSecureSafePagePhysical
));
gctaOS_ZeroMemory((gctUINT8_PTR)mmu->nonSecureSafePageLogical, (gctUINT32)bytes);
/* gcmkONERROR(gctaOS_CreateMutex(TA->os, &mmu->mutex)); */
*Mmu = mmu;
return gcvSTATUS_OK;
OnError:
if (mmu)
{
if (mmu->safePageLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
TA->os,
4096,
mmu->safePageLogical,
mmu->safePagePhysical
));
}
if (mmu->nonSecureSafePageLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
TA->os,
4096,
mmu->nonSecureSafePageLogical,
mmu->nonSecureSafePagePhysical
));
}
if (mmu->mtlbLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
TA->os,
4096,
mmu->mtlbLogical,
mmu->mtlbPhysical
));
}
if (mmu->stlbs)
{
gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)mmu->stlbs));
}
gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)mmu));
}
return status;
}
gceSTATUS
gctaMMU_Destory(
IN gcTA_MMU Mmu
)
{
gctaOS os = Mmu->os;
if (Mmu->safePageLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
os,
4096,
Mmu->safePageLogical,
Mmu->safePagePhysical
));
}
if (Mmu->nonSecureSafePageLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
os,
4096,
Mmu->nonSecureSafePageLogical,
Mmu->nonSecureSafePagePhysical
));
}
if (Mmu->mtlbLogical)
{
gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
os,
4096,
Mmu->mtlbLogical,
Mmu->mtlbPhysical
));
}
if (Mmu->stlbs)
{
gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)Mmu->stlbs));
}
gcmkVERIFY_OK(gctaOS_Free(Mmu));
return gcvSTATUS_OK;
}
gceSTATUS
gctaMMU_GetPageEntry(
IN gcTA_MMU Mmu,
IN gctUINT32 Address,
OUT gctUINT32_PTR MtlbEntry,
OUT gctUINT32_PTR *PageTable,
OUT gctBOOL * Secure
)
{
gceSTATUS status;
struct _gcsMMU_STLB *stlb;
struct _gcsMMU_STLB **stlbs = (struct _gcsMMU_STLB **)Mmu->stlbs;
gctUINT32 offset = _MtlbOffset(Address);
gctUINT32 mtlbEntry;
gctBOOL secure = Address > gcdMMU_SECURE_AREA_START;
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
stlb = stlbs[offset];
if (stlb == gcvNULL)
{
gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
mtlbEntry = (gctUINT32)(stlb->physBase & 0xFFFFFFFF)
| gcdMMU_MTLB_4K_PAGE
| gcdMMU_MTLB_PRESENT
;
if (secure)
{
/* Secure MTLB. */
mtlbEntry |= (1 << 4);
}
/* Insert Slave TLB address to Master TLB entry.*/
_WritePageEntry((gctUINT32_PTR)Mmu->mtlbLogical + offset, mtlbEntry);
/* Record stlb. */
stlbs[offset] = stlb;
if (MtlbEntry)
{
/* Return entry value of new mtlb entry. */
*MtlbEntry = mtlbEntry;
}
}
*PageTable = &stlb->logical[_StlbOffset(Address)];
if (Secure)
{
*Secure = secure;
}
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gctaMMU_SetPage(
IN gcTA_MMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
)
{
/* gctBOOL secure; */
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
_WritePageEntry(PageEntry, _SetPage(PageAddress));
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gctaMMU_FreePages(
IN gcTA_MMU Mmu,
IN gctUINT32 Address,
IN gctUINT32 PageCount
)
{
gceSTATUS status;
gctUINT32 i;
gctUINT32_PTR entry;
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Fill in page table. */
for (i = 0; i < PageCount; i++)
{
gcmkONERROR(gctaMMU_GetPageEntry(Mmu, Address, gcvNULL, &entry, gcvNULL));
#if gcdUSE_MMU_EXCEPTION
*entry = gcdMMU_STLB_EXCEPTION;
#else
*entry = 0;
#endif
Address += 4096;
}
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gctaMMU_Enable(
IN gcTA_MMU Mmu,
IN gcTA TA
)
{
gceSTATUS status;
gctPHYS_ADDR_T address;
gctPHYS_ADDR_T safeAddress;
gcmkONERROR(gctaOS_GetPhysicalAddress(Mmu->os, Mmu->mtlbLogical, &address));
gctaOS_GetPhysicalAddress(Mmu->os, Mmu->safePageLogical, &safeAddress);
return gcvSTATUS_OK;
OnError:
return status;
}
void
gctaMMU_DumpPagetableEntry(
IN gcTA_MMU Mmu,
IN gctUINT32 Address
)
{
gctUINT32 entry;
gctUINT32 mtlb = _MtlbOffset(Address);
gctUINT32_PTR mtlbLogical = Mmu->mtlbLogical;
gctUINT32_PTR stlbLogical;
gcsMMU_STLB_PTR stlb;
struct _gcsMMU_STLB **stlbs = (struct _gcsMMU_STLB **)Mmu->stlbs;
gctUINT32 stlbOffset = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
gctUINT32 offsetInPage = Address & gcdMMU_OFFSET_4K_MASK;
stlb = stlbs[mtlb];
gcmkPRINT(" MTLB entry = %d\n", mtlb);
gcmkPRINT(" STLB entry = %d\n", stlbOffset);
gcmkPRINT(" Offset = 0x%08X (%d)\n", offsetInPage, offsetInPage);
if (stlb == gcvNULL)
{
/* Dmp mtlb entry. */
entry = mtlbLogical[mtlb];
gcmkPRINT(" mtlb entry [%d] = %x", mtlb, entry);
}
else
{
stlbLogical = stlb->logical;
gcmkPRINT(" stlb entry = 0x%08X", stlbLogical[stlbOffset]);
}
}

View File

@ -0,0 +1,324 @@
/****************************************************************************
*
* 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_base.h"
#include "gc_hal.h"
#include "gc_hal_ta.h"
#include "gc_hal_kernel_mutex.h"
#define _GC_OBJ_ZONE gcvZONE_OS
gcTA globalTA[16] = { gcvNULL, gcvNULL, gcvNULL, gcvNULL,gcvNULL, gcvNULL, gcvNULL, gcvNULL };
gctaOS globalTAos;
struct _gctaOS {
void *os;
gctPOINTER dispatchMutex;
};
gceSTATUS HALDECL
TAEmulator(
gceCORE Core,
void * Interface
)
{
gckOS_AcquireMutex(globalTAos->os, globalTAos->dispatchMutex, gcvINFINITE);
gcTA_Dispatch(globalTA[Core], Interface);
gckOS_ReleaseMutex(globalTAos->os, globalTAos->dispatchMutex);
return gcvSTATUS_OK;
}
gceSTATUS
gctaOS_ConstructOS(
IN gckOS Os,
OUT gctaOS *TAos
)
{
gctaOS os;
gctPOINTER pointer = gcvNULL;
gceSTATUS status;
gcmkONERROR(gckOS_AllocateMemory(Os, gcmSIZEOF(struct _gctaOS), &pointer));
os = (gctaOS)pointer;
os->os = Os;
gcmkONERROR(gckOS_CreateMutex(Os, &os->dispatchMutex));
*TAos = globalTAos = os;
return gcvSTATUS_OK;
OnError:
if (pointer != gcvNULL)
{
gcmkVERIFY_OK(gckOS_FreeMemory(Os, pointer));
}
return status;
}
gceSTATUS
gctaOS_DestroyOS(
IN gctaOS Os
)
{
gckOS os = Os->os;
gcmkVERIFY_OK(gckOS_DeleteMutex(os, Os->dispatchMutex));
gcmkVERIFY_OK(gckOS_FreeMemory(os, Os));
return gcvSTATUS_OK;
}
gceSTATUS
gctaOS_AllocateSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T *Bytes,
OUT gctPOINTER *Logical,
OUT gctPOINTER *Physical
)
{
gceSTATUS status;
gcmkONERROR(gckOS_AllocateNonPagedMemory(Os->os, gcvFALSE, gcvALLOC_FLAG_CONTIGUOUS, Bytes, (gctPHYS_ADDR *)Physical, Logical));
return gcvSTATUS_OK;
OnError:
return status;
}
gceSTATUS
gctaOS_FreeSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
OUT gctPOINTER Physical
)
{
gckOS_FreeNonPagedMemory(Os->os, Bytes, (gctPHYS_ADDR)Physical, Logical);
return gcvSTATUS_OK;
}
gceSTATUS
gctaOS_AllocateNonSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T *Bytes,
OUT gctPOINTER *Logical,
OUT gctPOINTER *Physical
)
{
gceSTATUS status;
gcmkONERROR(gckOS_AllocateNonPagedMemory(Os->os, gcvFALSE, gcvALLOC_FLAG_CONTIGUOUS, Bytes, (gctPHYS_ADDR *)Physical, Logical));
return gcvSTATUS_OK;
OnError:
return status;
}
gceSTATUS
gctaOS_FreeNonSecurityMemory(
IN gctaOS Os,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
OUT gctPOINTER Physical
)
{
gckOS_FreeNonPagedMemory(Os->os, Bytes, (gctPHYS_ADDR)Physical, Logical);
return gcvSTATUS_OK;
}
gceSTATUS
gctaOS_Allocate(
IN gctUINT32 Bytes,
OUT gctPOINTER *Pointer
)
{
return gckOS_AllocateMemory(globalTAos->os, Bytes, Pointer);
}
gceSTATUS
gctaOS_Free(
IN gctPOINTER Pointer
)
{
return gckOS_FreeMemory(globalTAos->os, Pointer);
}
gceSTATUS
gctaOS_GetPhysicalAddress(
IN gctaOS Os,
IN gctPOINTER Logical,
OUT gctPHYS_ADDR_T * Physical
)
{
gctPHYS_ADDR_T physical;
gceSTATUS status;
gcmkONERROR(gckOS_GetPhysicalAddress(Os->os, Logical, &physical));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os->os, physical, &physical));
*Physical = physical;
return gcvSTATUS_OK;
OnError:
return status;
}
gceSTATUS gctaOS_WriteRegister(
IN gctaOS Os, IN gceCORE Core,
IN gctUINT32 Address,
IN gctUINT32 Data
)
{
return gckOS_WriteRegisterEx(Os->os, Core, Address, Data);
}
gceSTATUS gctaOS_ReadRegister(
IN gctaOS Os, IN gceCORE Core,
IN gctUINT32 Address,
IN gctUINT32 *Data
)
{
return gckOS_ReadRegisterEx(Os->os, Core, Address, Data);
}
gceSTATUS
gctaOS_MemCopy(
IN gctUINT8_PTR Dest,
IN gctUINT8_PTR Src,
IN gctUINT32 Bytes
)
{
gckOS_MemCopy(Dest, Src, Bytes);
return gcvSTATUS_OK;
}
gceSTATUS
gctaOS_ZeroMemory(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
)
{
gckOS_ZeroMemory(Dest, Bytes);
return gcvSTATUS_OK;
}
void
gctaOS_CacheFlush(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
)
{
}
void
gctaOS_CacheClean(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
)
{
}
void
gctaOS_CacheInvalidate(
IN gctUINT8_PTR Dest,
IN gctUINT32 Bytes
)
{
}
gceSTATUS
gctaOS_IsPhysicalSecure(
IN gctaOS Os,
IN gctUINT32 Physical,
OUT gctBOOL *Secure
)
{
return gcvSTATUS_NOT_SUPPORTED;
}
gceSTATUS
gctaOS_Delay(
IN gctaOS Os,
IN gctUINT32 Delay
)
{
return gckOS_Delay(Os->os, Delay);
}
gceSTATUS
gctaOS_SetGPUPower(
IN gctaOS Os,
IN gctUINT32 Core,
IN gctBOOL Clock,
IN gctBOOL Power
)
{
return gckOS_SetGPUPower(Os->os, Core, Power, Clock);
}