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