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