blob: fec086b8c622dddfa847dfc60bd2132f51a1f52f [file] [log] [blame]
Roberto Vargasc5907702017-08-03 08:56:38 +01001/*
Zelaleme8dadb12020-02-05 14:12:39 -06002 * Copyright (c) 2017-2020, 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
Zelaleme8dadb12020-02-05 14:12:39 -060035 assert(tbl != NULL);
johpow01d4cb8532020-07-30 17:11:03 -050036 assert(nregions > 0U);
Roberto Vargasc5907702017-08-03 08:56:38 +010037
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);
johpow01d4cb8532020-07-30 17:11:03 -050067 assert(nregions != 0U);
68 assert(chunk != 0U);
Roberto Vargas550eb082018-01-05 16:00:05 +000069
johpow01d4cb8532020-07-30 17:11:03 -050070 for (unsigned int i = 0U; i < nregions; i++) {
71 begin = regions[i].base;
72 size = regions[i].nbytes;
73 if (((begin & (chunk-1U)) != 0U) ||
74 ((size & (chunk-1U)) != 0U)) {
Roberto Vargas550eb082018-01-05 16:00:05 +000075 INFO("PSCI: Not correctly aligned region\n");
76 panic();
77 }
78
johpow01d4cb8532020-07-30 17:11:03 -050079 while (size > 0U) {
Roberto Vargas550eb082018-01-05 16:00:05 +000080 r = mmap_add_dynamic_region(begin, va, chunk, attr);
81 if (r != 0) {
johpow01d4cb8532020-07-30 17:11:03 -050082 INFO("PSCI: %s failed with %d\n",
83 "mmap_add_dynamic_region", r);
Roberto Vargas550eb082018-01-05 16:00:05 +000084 panic();
85 }
86
johpow01d4cb8532020-07-30 17:11:03 -050087 zero_normalmem((void *)va, chunk);
Roberto Vargas550eb082018-01-05 16:00:05 +000088
89 r = mmap_remove_dynamic_region(va, chunk);
90 if (r != 0) {
johpow01d4cb8532020-07-30 17:11:03 -050091 INFO("PSCI: %s failed with %d\n",
92 "mmap_remove_dynamic_region", r);
Roberto Vargas550eb082018-01-05 16:00:05 +000093 panic();
94 }
95
96 begin += chunk;
97 size -= chunk;
98 }
99 }
100}
101#endif
102
Roberto Vargasc5907702017-08-03 08:56:38 +0100103/*
104 * This function checks that a region (addr + nbytes-1) of memory is totally
105 * covered by one of the regions defined in tbl.
106 * tbl must be a valid pointer to a memory mem_region_t array, nregions
107 * is the size of the array and the region described by addr and nbytes must
108 * not generate an overflow.
109 * Returns:
110 * -1 means that the region is not covered by any of the regions
111 * described in tbl.
112 * 0 the region (addr + nbytes-1) is covered by one of the regions described
113 * in tbl
114 */
115int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
116 uintptr_t addr, size_t nbytes)
117{
118 uintptr_t region_start, region_end, start, end;
119 size_t i;
120
Zelaleme8dadb12020-02-05 14:12:39 -0600121 assert(tbl != NULL);
johpow01d4cb8532020-07-30 17:11:03 -0500122 assert(nbytes != 0U);
Roberto Vargasc5907702017-08-03 08:56:38 +0100123 assert(!check_uptr_overflow(addr, nbytes-1));
124
125 region_start = addr;
johpow01d4cb8532020-07-30 17:11:03 -0500126 region_end = addr + (nbytes - 1U);
127 for (i = 0U; i < nregions; i++) {
Roberto Vargasc5907702017-08-03 08:56:38 +0100128 assert(tbl->nbytes > 0);
129 assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
130 start = tbl->base;
131 end = start + (tbl->nbytes - 1);
johpow01d4cb8532020-07-30 17:11:03 -0500132 if ((region_start >= start) && (region_end <= end)) {
Roberto Vargasc5907702017-08-03 08:56:38 +0100133 return 0;
johpow01d4cb8532020-07-30 17:11:03 -0500134 }
Roberto Vargasc5907702017-08-03 08:56:38 +0100135 tbl++;
136 }
137
138 return -1;
139}