143cbaf06SRoberto Vargas /* 2*4c700c15SGovindraj Raja * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. 343cbaf06SRoberto Vargas * 443cbaf06SRoberto Vargas * SPDX-License-Identifier: BSD-3-Clause 543cbaf06SRoberto Vargas */ 643cbaf06SRoberto Vargas 743cbaf06SRoberto Vargas #include <assert.h> 809d40e0eSAntonio Nino Diaz 9bd9344f6SAntonio Nino Diaz #include <common/debug.h> 1009d40e0eSAntonio Nino Diaz #include <lib/utils.h> 11bd9344f6SAntonio Nino Diaz #include <lib/xlat_tables/xlat_tables_compat.h> 1243cbaf06SRoberto Vargas 1343cbaf06SRoberto Vargas /* 1443cbaf06SRoberto Vargas * All the regions defined in mem_region_t must have the following properties 1543cbaf06SRoberto Vargas * 1643cbaf06SRoberto Vargas * - Any contiguous regions must be merged into a single entry. 1743cbaf06SRoberto Vargas * - The number of bytes of each region must be greater than zero. 1843cbaf06SRoberto Vargas * - The calculation of the highest address within the region (base + nbytes-1) 1943cbaf06SRoberto Vargas * doesn't produce an overflow. 2043cbaf06SRoberto Vargas * 2143cbaf06SRoberto Vargas * These conditions must be fulfilled by the caller and they aren't checked 2243cbaf06SRoberto Vargas * at runtime. 2343cbaf06SRoberto Vargas */ 2443cbaf06SRoberto Vargas 2543cbaf06SRoberto Vargas /* 2643cbaf06SRoberto Vargas * zero_normalmem all the regions defined in tbl. 2743cbaf06SRoberto Vargas * It assumes that MMU is enabled and the memory is Normal memory. 2843cbaf06SRoberto Vargas * tbl must be a valid pointer to a memory mem_region_t array, 2943cbaf06SRoberto Vargas * nregions is the size of the array. 3043cbaf06SRoberto Vargas */ 3143cbaf06SRoberto Vargas void clear_mem_regions(mem_region_t *tbl, size_t nregions) 3243cbaf06SRoberto Vargas { 3343cbaf06SRoberto Vargas size_t i; 3443cbaf06SRoberto Vargas 35466bb285SZelalem assert(tbl != NULL); 36633fa4cdSjohpow01 assert(nregions > 0U); 3743cbaf06SRoberto Vargas 3843cbaf06SRoberto Vargas for (i = 0; i < nregions; i++) { 3943cbaf06SRoberto Vargas assert(tbl->nbytes > 0); 4043cbaf06SRoberto Vargas assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); 4143cbaf06SRoberto Vargas zero_normalmem((void *) (tbl->base), tbl->nbytes); 4243cbaf06SRoberto Vargas tbl++; 4343cbaf06SRoberto Vargas } 4443cbaf06SRoberto Vargas } 4543cbaf06SRoberto Vargas 46638b034cSRoberto Vargas #if defined(PLAT_XLAT_TABLES_DYNAMIC) 47638b034cSRoberto Vargas /* 48638b034cSRoberto Vargas * zero_normalmem all the regions defined in regions. 49638b034cSRoberto Vargas * It assumes that MMU is enabled and the memory is Normal memory. 50638b034cSRoberto Vargas * regions must be a valid pointer to a memory mem_region_t array, 51638b034cSRoberto Vargas * nregions is the size of the array. va is the virtual address 52638b034cSRoberto Vargas * where we want to map the physical pages that are going to 53638b034cSRoberto Vargas * be cleared, and chunk is the amount of memory mapped and 54638b034cSRoberto Vargas * cleared in every iteration. 55638b034cSRoberto Vargas */ 56c96f297fSRoberto Vargas void clear_map_dyn_mem_regions(struct mem_region *regions, 57638b034cSRoberto Vargas size_t nregions, 58638b034cSRoberto Vargas uintptr_t va, 59638b034cSRoberto Vargas size_t chunk) 60638b034cSRoberto Vargas { 61638b034cSRoberto Vargas uintptr_t begin; 62638b034cSRoberto Vargas int r; 63638b034cSRoberto Vargas size_t size; 643a1b7b10SAntonio Nino Diaz const unsigned int attr = MT_MEMORY | MT_RW | MT_NS; 65638b034cSRoberto Vargas 66638b034cSRoberto Vargas assert(regions != NULL); 67633fa4cdSjohpow01 assert(nregions != 0U); 68633fa4cdSjohpow01 assert(chunk != 0U); 69638b034cSRoberto Vargas 70633fa4cdSjohpow01 for (unsigned int i = 0U; i < nregions; i++) { 71633fa4cdSjohpow01 begin = regions[i].base; 72633fa4cdSjohpow01 size = regions[i].nbytes; 73633fa4cdSjohpow01 if (((begin & (chunk-1U)) != 0U) || 74633fa4cdSjohpow01 ((size & (chunk-1U)) != 0U)) { 75638b034cSRoberto Vargas INFO("PSCI: Not correctly aligned region\n"); 76638b034cSRoberto Vargas panic(); 77638b034cSRoberto Vargas } 78638b034cSRoberto Vargas 79633fa4cdSjohpow01 while (size > 0U) { 80638b034cSRoberto Vargas r = mmap_add_dynamic_region(begin, va, chunk, attr); 81638b034cSRoberto Vargas if (r != 0) { 82633fa4cdSjohpow01 INFO("PSCI: %s failed with %d\n", 83633fa4cdSjohpow01 "mmap_add_dynamic_region", r); 84638b034cSRoberto Vargas panic(); 85638b034cSRoberto Vargas } 86638b034cSRoberto Vargas 87638b034cSRoberto Vargas zero_normalmem((void *)va, chunk); 88638b034cSRoberto Vargas 89638b034cSRoberto Vargas r = mmap_remove_dynamic_region(va, chunk); 90638b034cSRoberto Vargas if (r != 0) { 91633fa4cdSjohpow01 INFO("PSCI: %s failed with %d\n", 92633fa4cdSjohpow01 "mmap_remove_dynamic_region", r); 93638b034cSRoberto Vargas panic(); 94638b034cSRoberto Vargas } 95638b034cSRoberto Vargas 96638b034cSRoberto Vargas begin += chunk; 97638b034cSRoberto Vargas size -= chunk; 98638b034cSRoberto Vargas } 99638b034cSRoberto Vargas } 100638b034cSRoberto Vargas } 101638b034cSRoberto Vargas #endif 102638b034cSRoberto Vargas 10343cbaf06SRoberto Vargas /* 10443cbaf06SRoberto Vargas * This function checks that a region (addr + nbytes-1) of memory is totally 10543cbaf06SRoberto Vargas * covered by one of the regions defined in tbl. 10643cbaf06SRoberto Vargas * tbl must be a valid pointer to a memory mem_region_t array, nregions 10743cbaf06SRoberto Vargas * is the size of the array and the region described by addr and nbytes must 10843cbaf06SRoberto Vargas * not generate an overflow. 10943cbaf06SRoberto Vargas * Returns: 11043cbaf06SRoberto Vargas * -1 means that the region is not covered by any of the regions 11143cbaf06SRoberto Vargas * described in tbl. 11243cbaf06SRoberto Vargas * 0 the region (addr + nbytes-1) is covered by one of the regions described 11343cbaf06SRoberto Vargas * in tbl 11443cbaf06SRoberto Vargas */ 11543cbaf06SRoberto Vargas int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, 11643cbaf06SRoberto Vargas uintptr_t addr, size_t nbytes) 11743cbaf06SRoberto Vargas { 11843cbaf06SRoberto Vargas uintptr_t region_start, region_end, start, end; 11943cbaf06SRoberto Vargas size_t i; 12043cbaf06SRoberto Vargas 121466bb285SZelalem assert(tbl != NULL); 122633fa4cdSjohpow01 assert(nbytes != 0U); 12343cbaf06SRoberto Vargas assert(!check_uptr_overflow(addr, nbytes-1)); 12443cbaf06SRoberto Vargas 12543cbaf06SRoberto Vargas region_start = addr; 126633fa4cdSjohpow01 region_end = addr + (nbytes - 1U); 127633fa4cdSjohpow01 for (i = 0U; i < nregions; i++) { 12843cbaf06SRoberto Vargas assert(tbl->nbytes > 0); 12943cbaf06SRoberto Vargas assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); 13043cbaf06SRoberto Vargas start = tbl->base; 13143cbaf06SRoberto Vargas end = start + (tbl->nbytes - 1); 132633fa4cdSjohpow01 if ((region_start >= start) && (region_end <= end)) { 13343cbaf06SRoberto Vargas return 0; 134633fa4cdSjohpow01 } 13543cbaf06SRoberto Vargas tbl++; 13643cbaf06SRoberto Vargas } 13743cbaf06SRoberto Vargas 13843cbaf06SRoberto Vargas return -1; 13943cbaf06SRoberto Vargas } 140