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