diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c index 0d8e370f57f43f6bcbccaaa59546032e7e3b0585..40d1bab067335711c6680e1d0723abf8e888ef98 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);