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 > 0); 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 > 0 && chunk > 0); 68 69 for ( ; nregions--; regions++) { 70 begin = regions->base; 71 size = regions->nbytes; 72 if ((begin & (chunk-1)) != 0 || (size & (chunk-1)) != 0) { 73 INFO("PSCI: Not correctly aligned region\n"); 74 panic(); 75 } 76 77 while (size > 0) { 78 r = mmap_add_dynamic_region(begin, va, chunk, attr); 79 if (r != 0) { 80 INFO("PSCI: mmap_add_dynamic_region failed with %d\n", r); 81 panic(); 82 } 83 84 zero_normalmem((void *) va, chunk); 85 86 r = mmap_remove_dynamic_region(va, chunk); 87 if (r != 0) { 88 INFO("PSCI: mmap_remove_dynamic_region failed with %d\n", r); 89 panic(); 90 } 91 92 begin += chunk; 93 size -= chunk; 94 } 95 } 96 } 97 #endif 98 99 /* 100 * This function checks that a region (addr + nbytes-1) of memory is totally 101 * covered by one of the regions defined in tbl. 102 * tbl must be a valid pointer to a memory mem_region_t array, nregions 103 * is the size of the array and the region described by addr and nbytes must 104 * not generate an overflow. 105 * Returns: 106 * -1 means that the region is not covered by any of the regions 107 * described in tbl. 108 * 0 the region (addr + nbytes-1) is covered by one of the regions described 109 * in tbl 110 */ 111 int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, 112 uintptr_t addr, size_t nbytes) 113 { 114 uintptr_t region_start, region_end, start, end; 115 size_t i; 116 117 assert(tbl != NULL); 118 assert(nbytes > 0); 119 assert(!check_uptr_overflow(addr, nbytes-1)); 120 121 region_start = addr; 122 region_end = addr + (nbytes - 1); 123 for (i = 0; i < nregions; i++) { 124 assert(tbl->nbytes > 0); 125 assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); 126 start = tbl->base; 127 end = start + (tbl->nbytes - 1); 128 if (region_start >= start && region_end <= end) 129 return 0; 130 tbl++; 131 } 132 133 return -1; 134 } 135