summaryrefslogtreecommitdiff
path: root/plat/nvidia/tegra
diff options
context:
space:
mode:
authorVikram Kanigiri <vikram.kanigiri@arm.com>2015-09-10 14:12:36 +0100
committerAchin Gupta <achin.gupta@arm.com>2015-09-14 22:09:40 +0100
commite3616819a9802ae84e9ed23092e26968bc1f25ae (patch)
treee9b9258472bc3d0f87862d062b0ed468eb3c1f09 /plat/nvidia/tegra
parent54dc71e7ec9f2a069907e8c0c24b5c8f8cc5f66a (diff)
Tegra: Perform cache maintenance on video carveout memory
Currently, the non-overlapping video memory carveout region is cleared after disabling the MMU at EL3. If at any exception level the carveout region is being marked as cacheable, this zeroing of memory will not have an affect on the cached lines. Hence, we first invalidate the dirty lines and update the memory and invalidate again so that both caches and memory is zeroed out. Change-Id: If3b2d139ab7227f6799c0911d59e079849dc86aa
Diffstat (limited to 'plat/nvidia/tegra')
-rw-r--r--plat/nvidia/tegra/common/drivers/memctrl/memctrl.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c
index 0d8e370f..40d1bab0 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c
@@ -107,6 +107,23 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
}
+static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
+ unsigned long long non_overlap_area_size)
+{
+ /*
+ * Perform cache maintenance to ensure that the non-overlapping area is
+ * zeroed out. The first invalidation of this range ensures that
+ * possible evictions of dirty cache lines do not interfere with the
+ * 'zeromem16' operation. Other CPUs could speculatively prefetch the
+ * main memory contents of this area between the first invalidation and
+ * the 'zeromem16' operation. The second invalidation ensures that any
+ * such cache lines are removed as well.
+ */
+ inv_dcache_range(non_overlap_area_start, non_overlap_area_size);
+ zeromem16((void *)non_overlap_area_start, non_overlap_area_size);
+ inv_dcache_range(non_overlap_area_start, non_overlap_area_size);
+}
+
/*
* Program the Video Memory carveout region
*
@@ -118,7 +135,7 @@ 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;
- uint64_t size;
+ unsigned long long non_overlap_area_size;
/*
* The GPU is the user of the Video Memory region. In order to
@@ -155,15 +172,15 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
disable_mmu_el3();
if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
- zeromem16((void *)video_mem_base, video_mem_size << 20);
+ tegra_clear_videomem(video_mem_base, video_mem_size << 20);
} else {
if (video_mem_base < phys_base) {
- size = phys_base - video_mem_base;
- zeromem16((void *)video_mem_base, size);
+ 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) {
- size = vmem_end_old - vmem_end_new;
- zeromem16((void *)vmem_end_new, size);
+ non_overlap_area_size = vmem_end_old - vmem_end_new;
+ tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
}
}
enable_mmu_el3(0);