blob: a5c3c61700033d8a81118b29beff55a95f96adcf [file] [log] [blame]
Roberto Vargasc5907702017-08-03 08:56:38 +01001/*
Roberto Vargas550eb082018-01-05 16:00:05 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Roberto Vargasc5907702017-08-03 08:56:38 +01003 *
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 */
28void 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
Roberto Vargas550eb082018-01-05 16:00:05 +000043#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 */
Roberto Vargas85664f52018-02-12 12:36:17 +000053void clear_map_dyn_mem_regions(struct mem_region *regions,
Roberto Vargas550eb082018-01-05 16:00:05 +000054 size_t nregions,
55 uintptr_t va,
56 size_t chunk)
57{
58 uintptr_t begin;
59 int r;
60 size_t size;
Antonio Nino Diaz8643a812018-06-21 14:39:16 +010061 const unsigned int attr = MT_MEMORY | MT_RW | MT_NS;
Roberto Vargas550eb082018-01-05 16:00:05 +000062
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
Roberto Vargasc5907702017-08-03 08:56:38 +010096/*
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 */
108int 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}