1 /* 2 * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <common/debug.h> 10 #include <lib/utils.h> 11 #include <lib/xlat_tables/xlat_tables_compat.h> 12 13 /* 14 * All the regions defined in mem_region_t must have the following properties 15 * 16 * - Any contiguous regions must be merged into a single entry. 17 * - The number of bytes of each region must be greater than zero. 18 * - The calculation of the highest address within the region (base + nbytes-1) 19 * doesn't produce an overflow. 20 * 21 * These conditions must be fulfilled by the caller and they aren't checked 22 * at runtime. 23 */ 24 25 /* 26 * zero_normalmem all the regions defined in tbl. 27 * It assumes that MMU is enabled and the memory is Normal memory. 28 * tbl must be a valid pointer to a memory mem_region_t array, 29 * nregions is the size of the array. 30 */ 31 void clear_mem_regions(mem_region_t *tbl, size_t nregions) 32 { 33 size_t i; 34 35 assert(tbl != NULL); 36 assert(nregions > 0U); 37 38 for (i = 0; i < nregions; i++) { 39 assert(tbl->nbytes > 0); 40 assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); 41 zero_normalmem((void *) (tbl->base), tbl->nbytes); 42 tbl++; 43 } 44 } 45 46 #if defined(PLAT_XLAT_TABLES_DYNAMIC) 47 /* 48 * zero_normalmem all the regions defined in regions. 49 * It assumes that MMU is enabled and the memory is Normal memory. 50 * regions must be a valid pointer to a memory mem_region_t array, 51 * nregions is the size of the array. va is the virtual address 52 * where we want to map the physical pages that are going to 53 * be cleared, and chunk is the amount of memory mapped and 54 * cleared in every iteration. 55 */ 56 void clear_map_dyn_mem_regions(struct mem_region *regions, 57 size_t nregions, 58 uintptr_t va, 59 size_t chunk) 60 { 61 uintptr_t begin; 62 int r; 63 size_t size; 64 const unsigned int attr = MT_MEMORY | MT_RW | MT_NS; 65 66 assert(regions != NULL); 67 assert(nregions != 0U); 68 assert(chunk != 0U); 69 70 for (unsigned int i = 0U; i < nregions; i++) { 71 begin = regions[i].base; 72 size = regions[i].nbytes; 73 if (((begin & (chunk-1U)) != 0U) || 74 ((size & (chunk-1U)) != 0U)) { 75 INFO("PSCI: Not correctly aligned region\n"); 76 panic(); 77 } 78 79 while (size > 0U) { 80 r = mmap_add_dynamic_region(begin, va, chunk, attr); 81 if (r != 0) { 82 INFO("PSCI: %s failed with %d\n", 83 "mmap_add_dynamic_region", r); 84 panic(); 85 } 86 87 zero_normalmem((void *)va, chunk); 88 89 r = mmap_remove_dynamic_region(va, chunk); 90 if (r != 0) { 91 INFO("PSCI: %s failed with %d\n", 92 "mmap_remove_dynamic_region", r); 93 panic(); 94 } 95 96 begin += chunk; 97 size -= chunk; 98 } 99 } 100 } 101 #endif 102 103 /* 104 * This function checks that a region (addr + nbytes-1) of memory is totally 105 * covered by one of the regions defined in tbl. 106 * tbl must be a valid pointer to a memory mem_region_t array, nregions 107 * is the size of the array and the region described by addr and nbytes must 108 * not generate an overflow. 109 * Returns: 110 * -1 means that the region is not covered by any of the regions 111 * described in tbl. 112 * 0 the region (addr + nbytes-1) is covered by one of the regions described 113 * in tbl 114 */ 115 int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, 116 uintptr_t addr, size_t nbytes) 117 { 118 uintptr_t region_start, region_end, start, end; 119 size_t i; 120 121 assert(tbl != NULL); 122 assert(nbytes != 0U); 123 assert(!check_uptr_overflow(addr, nbytes-1)); 124 125 region_start = addr; 126 region_end = addr + (nbytes - 1U); 127 for (i = 0U; i < nregions; i++) { 128 assert(tbl->nbytes > 0); 129 assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); 130 start = tbl->base; 131 end = start + (tbl->nbytes - 1); 132 if ((region_start >= start) && (region_end <= end)) { 133 return 0; 134 } 135 tbl++; 136 } 137 138 return -1; 139 } 140