123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /*
- * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <common/debug.h>
- #include <lib/utils.h>
- #include <lib/xlat_tables/xlat_tables_compat.h>
- /*
- * All the regions defined in mem_region_t must have the following properties
- *
- * - Any contiguous regions must be merged into a single entry.
- * - The number of bytes of each region must be greater than zero.
- * - The calculation of the highest address within the region (base + nbytes-1)
- * doesn't produce an overflow.
- *
- * These conditions must be fulfilled by the caller and they aren't checked
- * at runtime.
- */
- /*
- * zero_normalmem all the regions defined in tbl.
- * It assumes that MMU is enabled and the memory is Normal memory.
- * tbl must be a valid pointer to a memory mem_region_t array,
- * nregions is the size of the array.
- */
- void clear_mem_regions(mem_region_t *tbl, size_t nregions)
- {
- size_t i;
- assert(tbl != NULL);
- assert(nregions > 0U);
- for (i = 0; i < nregions; i++) {
- assert(tbl->nbytes > 0);
- assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
- zero_normalmem((void *) (tbl->base), tbl->nbytes);
- tbl++;
- }
- }
- #if defined(PLAT_XLAT_TABLES_DYNAMIC)
- /*
- * zero_normalmem all the regions defined in regions.
- * It assumes that MMU is enabled and the memory is Normal memory.
- * regions must be a valid pointer to a memory mem_region_t array,
- * nregions is the size of the array. va is the virtual address
- * where we want to map the physical pages that are going to
- * be cleared, and chunk is the amount of memory mapped and
- * cleared in every iteration.
- */
- void clear_map_dyn_mem_regions(struct mem_region *regions,
- size_t nregions,
- uintptr_t va,
- size_t chunk)
- {
- uintptr_t begin;
- int r;
- size_t size;
- const unsigned int attr = MT_MEMORY | MT_RW | MT_NS;
- assert(regions != NULL);
- assert(nregions != 0U);
- assert(chunk != 0U);
- for (unsigned int i = 0U; i < nregions; i++) {
- begin = regions[i].base;
- size = regions[i].nbytes;
- if (((begin & (chunk-1U)) != 0U) ||
- ((size & (chunk-1U)) != 0U)) {
- INFO("PSCI: Not correctly aligned region\n");
- panic();
- }
- while (size > 0U) {
- r = mmap_add_dynamic_region(begin, va, chunk, attr);
- if (r != 0) {
- INFO("PSCI: %s failed with %d\n",
- "mmap_add_dynamic_region", r);
- panic();
- }
- zero_normalmem((void *)va, chunk);
- r = mmap_remove_dynamic_region(va, chunk);
- if (r != 0) {
- INFO("PSCI: %s failed with %d\n",
- "mmap_remove_dynamic_region", r);
- panic();
- }
- begin += chunk;
- size -= chunk;
- }
- }
- }
- #endif
- /*
- * This function checks that a region (addr + nbytes-1) of memory is totally
- * covered by one of the regions defined in tbl.
- * tbl must be a valid pointer to a memory mem_region_t array, nregions
- * is the size of the array and the region described by addr and nbytes must
- * not generate an overflow.
- * Returns:
- * -1 means that the region is not covered by any of the regions
- * described in tbl.
- * 0 the region (addr + nbytes-1) is covered by one of the regions described
- * in tbl
- */
- int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
- uintptr_t addr, size_t nbytes)
- {
- uintptr_t region_start, region_end, start, end;
- size_t i;
- assert(tbl != NULL);
- assert(nbytes != 0U);
- assert(!check_uptr_overflow(addr, nbytes-1));
- region_start = addr;
- region_end = addr + (nbytes - 1U);
- for (i = 0U; i < nregions; i++) {
- assert(tbl->nbytes > 0);
- assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
- start = tbl->base;
- end = start + (tbl->nbytes - 1);
- if ((region_start >= start) && (region_end <= end)) {
- return 0;
- }
- tbl++;
- }
- return -1;
- }
|