Merge pull request #319 from vwadekar/tegra-video-mem-aperture-v3

Reserve a Video Memory aperture in DRAM memory
This commit is contained in:
danh-arm 2015-06-18 14:58:33 +01:00
commit 09aa0392b3
6 changed files with 227 additions and 0 deletions

View File

@ -28,11 +28,23 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <memctrl.h>
#include <string.h>
#include <tegra_def.h>
#include <xlat_tables.h>
extern void zeromem16(void *mem, unsigned int length);
#define TEGRA_GPU_RESET_REG_OFFSET 0x28c
#define GPU_RESET_BIT (1 << 24)
/* Video Memory base and size (live values) */
static uintptr_t video_mem_base;
static uint64_t video_mem_size;
/*
* Init SMMU.
@ -71,6 +83,10 @@ void tegra_memctrl_setup(void)
tegra_mc_write_32(MC_SMMU_CONFIG_0,
MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
/* video memory carveout */
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, video_mem_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
}
/*
@ -90,3 +106,66 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
}
/*
* Program the Video Memory carveout region
*
* phys_base = physical base of aperture
* size_in_bytes = size of aperture in bytes
*/
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
uintptr_t vmem_end_new = phys_base + size_in_bytes;
uint32_t regval;
/*
* The GPU is the user of the Video Memory region. In order to
* transition to the new memory region smoothly, we program the
* new base/size ONLY if the GPU is in reset mode.
*/
regval = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
if ((regval & GPU_RESET_BIT) == 0) {
ERROR("GPU not in reset! Video Memory setup failed\n");
return;
}
/*
* Setup the Memory controller to restrict CPU accesses to the Video
* Memory region
*/
INFO("Configuring Video Memory Carveout\n");
/*
* Configure Memory Controller directly for the first time.
*/
if (video_mem_base == 0)
goto done;
/*
* Clear the old regions now being exposed. The following cases
* can occur -
*
* 1. clear whole old region (no overlap with new region)
* 2. clear old sub-region below new base
* 3. clear old sub-region above new end
*/
INFO("Cleaning previous Video Memory Carveout\n");
disable_mmu_el3();
if (phys_base > vmem_end_old || video_mem_base > vmem_end_new)
zeromem16((void *)video_mem_base, video_mem_size << 20);
else if (video_mem_base < phys_base)
zeromem16((void *)video_mem_base, phys_base - video_mem_base);
else if (vmem_end_old > vmem_end_new)
zeromem16((void *)vmem_end_new, vmem_end_old - vmem_end_new);
enable_mmu_el3(0);
done:
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, phys_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
/* store new values */
video_mem_base = phys_base;
video_mem_size = size_in_bytes >> 20;
}

View File

@ -37,6 +37,7 @@
#include <cortex_a57.h>
#include <cortex_a53.h>
#include <debug.h>
#include <errno.h>
#include <memctrl.h>
#include <mmio.h>
#include <platform.h>
@ -230,3 +231,32 @@ void bl31_plat_arch_setup(void)
/* enable the MMU */
enable_mmu_el3(0);
}
/*******************************************************************************
* Check if the given NS DRAM range is valid
******************************************************************************/
int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
{
uint64_t end = base + size_in_bytes - 1;
/*
* Check if the NS DRAM address is valid
*/
if ((base < TEGRA_DRAM_BASE) || (end > TEGRA_DRAM_END) ||
(base >= end)) {
ERROR("NS address is out-of-bounds!\n");
return -EFAULT;
}
/*
* TZDRAM aperture contains the BL31 and BL32 images, so we need
* to check if the NS DRAM range overlaps the TZDRAM aperture.
*/
if ((base < TZDRAM_END) && (end > tegra_bl31_phys_base)) {
ERROR("NS address overlaps TZDRAM!\n");
return -ENOTSUP;
}
/* valid NS address */
return 0;
}

View File

@ -59,4 +59,5 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \
${COMMON_DIR}/tegra_bl31_setup.c \
${COMMON_DIR}/tegra_gic.c \
${COMMON_DIR}/tegra_pm.c \
${COMMON_DIR}/tegra_sip_calls.c \
${COMMON_DIR}/tegra_topology.c

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <context_mgmt.h>
#include <debug.h>
#include <errno.h>
#include <memctrl.h>
#include <runtime_svc.h>
#include <tegra_private.h>
#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
/*******************************************************************************
* This function is responsible for handling all SiP calls from the NS world
******************************************************************************/
uint64_t tegra_sip_handler(uint32_t smc_fid,
uint64_t x1,
uint64_t x2,
uint64_t x3,
uint64_t x4,
void *cookie,
void *handle,
uint64_t flags)
{
uint32_t ns;
int err;
/* Determine which security state this SMC originated from */
ns = is_caller_non_secure(flags);
if (!ns)
SMC_RET1(handle, SMC_UNK);
switch (smc_fid) {
case TEGRA_SIP_NEW_VIDEOMEM_REGION:
/*
* Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
* or falls outside of the valid DRAM range
*/
err = bl31_check_ns_address(x1, x2);
if (err)
SMC_RET1(handle, err);
/*
* Check if Video Memory is aligned to 1MB.
*/
if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) {
ERROR("Unaligned Video Memory base address!\n");
SMC_RET1(handle, -ENOTSUP);
}
/* new video memory carveout settings */
tegra_memctrl_videomem_setup(x1, x2);
SMC_RET1(handle, 0);
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
}
SMC_RET1(handle, SMC_UNK);
}
/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
tegra_sip_fast,
OEN_SIP_START,
OEN_SIP_END,
SMC_TYPE_FAST,
NULL,
tegra_sip_handler
);

View File

@ -64,6 +64,10 @@
#define MC_SECURITY_CFG0_0 0x70
#define MC_SECURITY_CFG1_0 0x74
/* Video Memory carveout configuration registers */
#define MC_VIDEO_PROTECT_BASE 0x648
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
static inline uint32_t tegra_mc_read_32(uint32_t off)
{
return mmio_read_32(TEGRA_MC_BASE + off);
@ -76,5 +80,6 @@ static inline void tegra_mc_write_32(uint32_t off, uint32_t val)
void tegra_memctrl_setup(void);
void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes);
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes);
#endif /* __MEMCTRL_H__ */

View File

@ -34,6 +34,12 @@
#include <xlat_tables.h>
#include <platform_def.h>
/*******************************************************************************
* Tegra DRAM memory base address
******************************************************************************/
#define TEGRA_DRAM_BASE 0x80000000
#define TEGRA_DRAM_END 0x27FFFFFFF
typedef struct plat_params_from_bl2 {
uint64_t tzdram_size;
uintptr_t bl32_params;
@ -66,5 +72,6 @@ int tegra_prepare_cpu_on_finish(unsigned long mpidr);
/* Declarations for tegra_bl31_setup.c */
plat_params_from_bl2_t *bl31_get_plat_params(void);
int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes);
#endif /* __TEGRA_PRIVATE_H__ */