Commit 3fbec436 authored by Manish Pandey's avatar Manish Pandey Committed by TrustedFirmware Code Review
Browse files

Merge changes from topic "tegra-memctrlv2-vpr-resize-bugfix" into integration

* changes:
  Tegra: sanity check NS address and size before use
  Tegra: memctrl_v2: fixup sequence to resize video memory
parents b667b369 685e5609
...@@ -280,56 +280,32 @@ static void tegra_clear_videomem(uintptr_t non_overlap_area_start, ...@@ -280,56 +280,32 @@ static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
{ {
int ret; int ret;
INFO("Cleaning previous Video Memory Carveout\n");
/* /*
* Map the NS memory first, clean it and then unmap it. * Map the NS memory first, clean it and then unmap it.
*/ */
ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
non_overlap_area_start, /* VA */ non_overlap_area_start, /* VA */
non_overlap_area_size, /* size */ non_overlap_area_size, /* size */
MT_NS | MT_RW | MT_EXECUTE_NEVER | MT_DEVICE | MT_RW | MT_NS); /* attrs */
MT_NON_CACHEABLE); /* attrs */
assert(ret == 0); assert(ret == 0);
zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size); zeromem((void *)non_overlap_area_start, non_overlap_area_size);
flush_dcache_range(non_overlap_area_start, non_overlap_area_size); flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
(void)mmap_remove_dynamic_region(non_overlap_area_start, ret = mmap_remove_dynamic_region(non_overlap_area_start,
non_overlap_area_size); non_overlap_area_size);
assert(ret == 0);
} }
/* static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base,
* Program the Video Memory carveout region unsigned long size_in_bytes)
*
* 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_mb << 20); uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20);
uintptr_t vmem_end_new = phys_base + size_in_bytes; uintptr_t vmem_end_new = phys_base + size_in_bytes;
unsigned long long non_overlap_area_size; unsigned long long non_overlap_area_size;
/*
* 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 == 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 * Clear the old regions now being exposed. The following cases
* can occur - * can occur -
...@@ -338,8 +314,6 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) ...@@ -338,8 +314,6 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
* 2. clear old sub-region below new base * 2. clear old sub-region below new base
* 3. clear old sub-region above new end * 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)) { if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
tegra_clear_videomem(video_mem_base, tegra_clear_videomem(video_mem_base,
video_mem_size_mb << 20U); video_mem_size_mb << 20U);
...@@ -353,26 +327,55 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) ...@@ -353,26 +327,55 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
tegra_clear_videomem(vmem_end_new, non_overlap_area_size); tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
} }
} }
}
/*
* 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)
{
/*
* Setup the Memory controller to restrict CPU accesses to the Video
* Memory region
*/
INFO("Configuring Video Memory Carveout\n");
if (video_mem_base != 0U) {
/*
* 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);
}
done:
/* program the Videomem aperture */ /* 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_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
(uint32_t)(phys_base >> 32)); (uint32_t)(phys_base >> 32));
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); 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 propagates the VideoMem configuration values across the * MCE propagates the VideoMem configuration values across the
* CCPLEX. * CCPLEX.
*/ */
mce_update_gsc_videomem(); (void)mce_update_gsc_videomem();
/* Clear the non-overlapping memory */
if (video_mem_base != 0U) {
tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes);
tegra_unlock_videomem_nonoverlap();
}
/* store new values */
video_mem_base = phys_base;
video_mem_size_mb = (uint64_t)size_in_bytes >> 20;
} }
/* /*
......
...@@ -367,7 +367,15 @@ void bl31_plat_arch_setup(void) ...@@ -367,7 +367,15 @@ void bl31_plat_arch_setup(void)
int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes) int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
{ {
uint64_t end = base + size_in_bytes - U(1); uint64_t end = base + size_in_bytes - U(1);
int32_t ret = 0;
/*
* Sanity check the input values
*/
if ((base == 0U) || (size_in_bytes == 0U)) {
ERROR("NS address 0x%llx (%lld bytes) is invalid\n",
base, size_in_bytes);
return -EINVAL;
}
/* /*
* Check if the NS DRAM address is valid * Check if the NS DRAM address is valid
...@@ -376,7 +384,7 @@ int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes) ...@@ -376,7 +384,7 @@ int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
(end > TEGRA_DRAM_END)) { (end > TEGRA_DRAM_END)) {
ERROR("NS address 0x%llx is out-of-bounds!\n", base); ERROR("NS address 0x%llx is out-of-bounds!\n", base);
ret = -EFAULT; return -EFAULT;
} }
/* /*
...@@ -385,9 +393,9 @@ int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes) ...@@ -385,9 +393,9 @@ int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
*/ */
if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) { if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) {
ERROR("NS address 0x%llx overlaps TZDRAM!\n", base); ERROR("NS address 0x%llx overlaps TZDRAM!\n", base);
ret = -ENOTSUP; return -ENOTSUP;
} }
/* valid NS address */ /* valid NS address */
return ret; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment