summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2016-12-21 14:50:18 -0800
committerVarun Wadekar <vwadekar@nvidia.com>2017-05-01 15:33:31 -0700
commit9d42d23a2cb1394d0c9cf396dda7a362908da020 (patch)
treeb2570e5a40b963550ceecca9b697505586acbae8
parente9cb01d96e2615d65885f22731b1ebec0a53fd85 (diff)
Tegra: memctrl_v2: zero out NS Video memory carveout region
The video memory carveout has to be re-sized depending on the Video content. This requires the NS world to send us new base/size values. Before setting up the new region, we must zero out the previous memory region, so that the video frames are not leaked to the outside world. This patch adds the logic to zero out the previous memory carveout region. Change-Id: I471167ef7747154440df5c1a5e015fbeb69d9043 Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
-rw-r--r--plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c160
-rw-r--r--plat/nvidia/tegra/include/t186/tegra_def.h46
2 files changed, 168 insertions, 38 deletions
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index 41a4ede8..87c7ed03 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -40,7 +40,8 @@
#include <string.h>
#include <tegra_def.h>
#include <tegra_platform.h>
-#include <xlat_tables.h>
+#include <utils.h>
+#include <xlat_tables_v2.h>
#define TEGRA_GPU_RESET_REG_OFFSET 0x30
#define GPU_RESET_BIT (1 << 0)
@@ -450,7 +451,7 @@ void tegra_memctrl_restore_settings(void)
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size_mb);
/*
- * MCE propogates the VideoMem configuration values across the
+ * MCE propagates the VideoMem configuration values across the
* CCPLEX.
*/
mce_update_gsc_videomem();
@@ -490,7 +491,7 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
tegra_mc_read_32(MC_SECURITY_CFG1_0));
/*
- * MCE propogates the security configuration values across the
+ * MCE propagates the security configuration values across the
* CCPLEX.
*/
mce_update_gsc_tzdram();
@@ -506,25 +507,28 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
uint32_t index;
uint32_t total_128kb_blocks = size_in_bytes >> 17;
- uint32_t residual_4kb_blocks = (size_in_bytes & 0x1FFFF) >> 12;
+ uint32_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12;
uint32_t val;
+ INFO("Configuring TrustZone SRAM Memory Carveout\n");
+
/*
* Reset the access configuration registers to restrict access
* to the TZRAM aperture
*/
- for (index = MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0;
- index <= MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5;
- index += 4)
+ for (index = MC_TZRAM_CLIENT_ACCESS_CFG0;
+ index < ((uint32_t)MC_TZRAM_CARVEOUT_CFG + (uint32_t)MC_GSC_CONFIG_REGS_SIZE);
+ index += 4U) {
tegra_mc_write_32(index, 0);
+ }
/*
* Set the TZRAM base. TZRAM base must be 4k aligned, at least.
*/
- assert(!(phys_base & 0xFFF));
+ assert((phys_base & (uint64_t)0xFFF) == 0U);
tegra_mc_write_32(MC_TZRAM_BASE_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_TZRAM_BASE_HI,
- (uint32_t)(phys_base >> 32) & TZRAM_BASE_HI_MASK);
+ (uint32_t)(phys_base >> 32) & MC_GSC_BASE_HI_MASK);
/*
* Set the TZRAM size
@@ -533,7 +537,7 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
* blocks)
*
*/
- val = (residual_4kb_blocks << TZRAM_SIZE_RANGE_4KB_SHIFT) |
+ val = (residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) |
total_128kb_blocks;
tegra_mc_write_32(MC_TZRAM_SIZE, val);
@@ -543,17 +547,96 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
* at all.
*/
val = tegra_mc_read_32(MC_TZRAM_CARVEOUT_CFG);
- val &= ~TZRAM_ENABLE_TZ_LOCK_BIT;
- val |= TZRAM_LOCK_CFG_SETTINGS_BIT;
+ val &= ~MC_GSC_ENABLE_TZ_LOCK_BIT;
+ val |= MC_GSC_LOCK_CFG_SETTINGS_BIT;
tegra_mc_write_32(MC_TZRAM_CARVEOUT_CFG, val);
/*
- * MCE propogates the security configuration values across the
+ * MCE propagates the security configuration values across the
* CCPLEX.
*/
mce_update_gsc_tzram();
}
+static void tegra_lock_videomem_nonoverlap(uint64_t phys_base,
+ uint64_t size_in_bytes)
+{
+ uint32_t index;
+ uint64_t total_128kb_blocks = size_in_bytes >> 17;
+ uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12;
+ uint64_t val;
+
+ /*
+ * Reset the access configuration registers to restrict access to
+ * old Videomem aperture
+ */
+ for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0;
+ index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE);
+ index += 4U) {
+ tegra_mc_write_32(index, 0);
+ }
+
+ /*
+ * Set the base. It must be 4k aligned, at least.
+ */
+ assert((phys_base & (uint64_t)0xFFF) == 0U);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI,
+ (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK);
+
+ /*
+ * Set the aperture size
+ *
+ * total size = (number of 128KB blocks) + (number of remaining 4KB
+ * blocks)
+ *
+ */
+ val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) |
+ total_128kb_blocks);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val);
+
+ /*
+ * Lock the configuration settings by enabling TZ-only lock and
+ * locking the configuration against any future changes from NS
+ * world.
+ */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG,
+ (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT);
+
+ /*
+ * MCE propagates the GSC configuration values across the
+ * CCPLEX.
+ */
+}
+
+static void tegra_unlock_videomem_nonoverlap(void)
+{
+ /* Clear the base */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0);
+
+ /* Clear the size */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0);
+}
+
+static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
+ unsigned long long non_overlap_area_size)
+{
+ /*
+ * Map the NS memory first, clean it and then unmap it.
+ */
+ mmap_add_dynamic_region(non_overlap_area_start, /* PA */
+ non_overlap_area_start, /* VA */
+ non_overlap_area_size, /* size */
+ MT_NS | MT_RW | MT_EXECUTE_NEVER); /* attrs */
+
+ zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size);
+ flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
+
+ mmap_remove_dynamic_region(non_overlap_area_start,
+ non_overlap_area_size);
+}
+
/*
* Program the Video Memory carveout region
*
@@ -562,7 +645,10 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_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_mb << 20);
+ uintptr_t vmem_end_new = phys_base + size_in_bytes;
uint32_t regval;
+ unsigned long long non_overlap_area_size;
/*
* The GPU is the user of the Video Memory region. In order to
@@ -570,7 +656,7 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
* 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) {
+ if ((regval & GPU_RESET_BIT) == 0U) {
ERROR("GPU not in reset! Video Memory setup failed\n");
return;
}
@@ -581,17 +667,61 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
*/
INFO("Configuring Video Memory Carveout\n");
+ /*
+ * Configure Memory Controller directly for the first time.
+ */
+ if (video_mem_base == 0U)
+ goto done;
+
+ /*
+ * Lock the non overlapping memory being cleared so that other masters
+ * do not accidently write to it. The memory would be unlocked once
+ * the non overlapping region is cleared and the new memory
+ * settings take effect.
+ */
+ tegra_lock_videomem_nonoverlap(video_mem_base,
+ video_mem_size_mb << 20);
+
+ /*
+ * 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");
+
+ if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
+ tegra_clear_videomem(video_mem_base,
+ (uint64_t)video_mem_size_mb << 20);
+ } else {
+ if (video_mem_base < phys_base) {
+ non_overlap_area_size = phys_base - video_mem_base;
+ tegra_clear_videomem(video_mem_base, non_overlap_area_size);
+ }
+ if (vmem_end_old > vmem_end_new) {
+ non_overlap_area_size = vmem_end_old - vmem_end_new;
+ tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
+ }
+ }
+
+done:
+ /* program the Videomem aperture */
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
(uint32_t)(phys_base >> 32));
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
+ /* unlock the previous locked nonoverlapping aperture */
+ tegra_unlock_videomem_nonoverlap();
+
/* store new values */
video_mem_base = phys_base;
video_mem_size_mb = size_in_bytes >> 20;
/*
- * MCE propogates the VideoMem configuration values across the
+ * MCE propagates the VideoMem configuration values across the
* CCPLEX.
*/
mce_update_gsc_videomem();
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 6693cb3a..8d7ab6ea 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -157,6 +157,16 @@
#define TEGRA_MC_STREAMID_BASE 0x02C00000
#define TEGRA_MC_BASE 0x02C10000
+/* General Security Carveout register macros */
+#define MC_GSC_CONFIG_REGS_SIZE 0x40UL
+#define MC_GSC_LOCK_CFG_SETTINGS_BIT (1UL << 1)
+#define MC_GSC_ENABLE_TZ_LOCK_BIT (1UL << 0)
+#define MC_GSC_SIZE_RANGE_4KB_SHIFT 27UL
+#define MC_GSC_BASE_LO_SHIFT 12UL
+#define MC_GSC_BASE_LO_MASK 0xFFFFFUL
+#define MC_GSC_BASE_HI_SHIFT 0UL
+#define MC_GSC_BASE_HI_MASK 3UL
+
/* TZDRAM carveout configuration registers */
#define MC_SECURITY_CFG0_0 0x70
#define MC_SECURITY_CFG1_0 0x74
@@ -165,34 +175,24 @@
/* Video Memory carveout configuration registers */
#define MC_VIDEO_PROTECT_BASE_HI 0x978
#define MC_VIDEO_PROTECT_BASE_LO 0x648
-#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
+#define MC_VIDEO_PROTECT_SIZE_MB 0x64C
+
+/*
+ * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the
+ * non-overlapping Video memory region
+ */
+#define MC_VIDEO_PROTECT_CLEAR_CFG 0x25A0
+#define MC_VIDEO_PROTECT_CLEAR_BASE_LO 0x25A4
+#define MC_VIDEO_PROTECT_CLEAR_BASE_HI 0x25A8
+#define MC_VIDEO_PROTECT_CLEAR_SIZE 0x25AC
+#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 0x25B0
/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */
+#define MC_TZRAM_CARVEOUT_CFG 0x2190
#define MC_TZRAM_BASE_LO 0x2194
-#define TZRAM_BASE_LO_SHIFT 12
-#define TZRAM_BASE_LO_MASK 0xFFFFF
#define MC_TZRAM_BASE_HI 0x2198
-#define TZRAM_BASE_HI_SHIFT 0
-#define TZRAM_BASE_HI_MASK 3
#define MC_TZRAM_SIZE 0x219C
-#define TZRAM_SIZE_RANGE_4KB_SHIFT 27
-
-#define MC_TZRAM_CARVEOUT_CFG 0x2190
-#define TZRAM_LOCK_CFG_SETTINGS_BIT (1 << 1)
-#define TZRAM_ENABLE_TZ_LOCK_BIT (1 << 0)
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0 0x21A0
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG1 0x21A4
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG2 0x21A8
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG3 0x21AC
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG4 0x21B0
-#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG5 0x21B4
-
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS0 0x21B8
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS1 0x21BC
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS2 0x21C0
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS3 0x21C4
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS4 0x21C8
-#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5 0x21CC
+#define MC_TZRAM_CLIENT_ACCESS_CFG0 0x21A0
/*******************************************************************************
* Tegra UART Controller constants