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