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