summaryrefslogtreecommitdiff
path: root/plat/nvidia/tegra
diff options
context:
space:
mode:
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);