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