1
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
2
#include <string.h>
3
3
#include <linux/memblock.h>
4
+ #include <linux/sizes.h>
4
5
#include "basic_api.h"
5
6
6
7
#define EXPECTED_MEMBLOCK_REGIONS 128
@@ -25,8 +26,222 @@ static int memblock_initialization_check(void)
25
26
return 0 ;
26
27
}
27
28
29
+ /*
30
+ * A simple test that adds a memory block of a specified base address
31
+ * and size to the collection of available memory regions (memblock.memory).
32
+ * It checks if a new entry was created and if region counter and total memory
33
+ * were correctly updated.
34
+ */
35
+ static int memblock_add_simple_check (void )
36
+ {
37
+ struct memblock_region * rgn ;
38
+
39
+ rgn = & memblock .memory .regions [0 ];
40
+
41
+ struct region r = {
42
+ .base = SZ_1G ,
43
+ .size = SZ_4M
44
+ };
45
+
46
+ reset_memblock ();
47
+ memblock_add (r .base , r .size );
48
+
49
+ assert (rgn -> base == r .base );
50
+ assert (rgn -> size == r .size );
51
+
52
+ assert (memblock .memory .cnt == 1 );
53
+ assert (memblock .memory .total_size == r .size );
54
+
55
+ return 0 ;
56
+ }
57
+
58
+ /*
59
+ * A test that tries to add two memory blocks that don't overlap with one
60
+ * another. It checks if two correctly initialized entries were added to the
61
+ * collection of available memory regions (memblock.memory) and if this
62
+ * change was reflected in memblock.memory's total size and region counter.
63
+ */
64
+ static int memblock_add_disjoint_check (void )
65
+ {
66
+ struct memblock_region * rgn1 , * rgn2 ;
67
+
68
+ rgn1 = & memblock .memory .regions [0 ];
69
+ rgn2 = & memblock .memory .regions [1 ];
70
+
71
+ struct region r1 = {
72
+ .base = SZ_1G ,
73
+ .size = SZ_8K
74
+ };
75
+ struct region r2 = {
76
+ .base = SZ_1G + SZ_16K ,
77
+ .size = SZ_8K
78
+ };
79
+
80
+ reset_memblock ();
81
+ memblock_add (r1 .base , r1 .size );
82
+ memblock_add (r2 .base , r2 .size );
83
+
84
+ assert (rgn1 -> base == r1 .base );
85
+ assert (rgn1 -> size == r1 .size );
86
+
87
+ assert (rgn2 -> base == r2 .base );
88
+ assert (rgn2 -> size == r2 .size );
89
+
90
+ assert (memblock .memory .cnt == 2 );
91
+ assert (memblock .memory .total_size == r1 .size + r2 .size );
92
+
93
+ return 0 ;
94
+ }
95
+
96
+ /*
97
+ * A test that tries to add two memory blocks, where the second one overlaps
98
+ * with the beginning of the first entry (that is r1.base < r2.base + r2.size).
99
+ * After this, it checks if two entries are merged into one region that starts
100
+ * at r2.base and has size of two regions minus their intersection. It also
101
+ * verifies the reported total size of the available memory and region counter.
102
+ */
103
+ static int memblock_add_overlap_top_check (void )
104
+ {
105
+ struct memblock_region * rgn ;
106
+ phys_addr_t total_size ;
107
+
108
+ rgn = & memblock .memory .regions [0 ];
109
+
110
+ struct region r1 = {
111
+ .base = SZ_512M ,
112
+ .size = SZ_1G
113
+ };
114
+ struct region r2 = {
115
+ .base = SZ_256M ,
116
+ .size = SZ_512M
117
+ };
118
+
119
+ total_size = (r1 .base - r2 .base ) + r1 .size ;
120
+
121
+ reset_memblock ();
122
+ memblock_add (r1 .base , r1 .size );
123
+ memblock_add (r2 .base , r2 .size );
124
+
125
+ assert (rgn -> base == r2 .base );
126
+ assert (rgn -> size == total_size );
127
+
128
+ assert (memblock .memory .cnt == 1 );
129
+ assert (memblock .memory .total_size == total_size );
130
+
131
+ return 0 ;
132
+ }
133
+
134
+ /*
135
+ * A test that tries to add two memory blocks, where the second one overlaps
136
+ * with the end of the first entry (that is r2.base < r1.base + r1.size).
137
+ * After this, it checks if two entries are merged into one region that starts
138
+ * at r1.base and has size of two regions minus their intersection. It verifies
139
+ * that memblock can still see only one entry and has a correct total size of
140
+ * the available memory.
141
+ */
142
+ static int memblock_add_overlap_bottom_check (void )
143
+ {
144
+ struct memblock_region * rgn ;
145
+ phys_addr_t total_size ;
146
+
147
+ rgn = & memblock .memory .regions [0 ];
148
+
149
+ struct region r1 = {
150
+ .base = SZ_128M ,
151
+ .size = SZ_512M
152
+ };
153
+ struct region r2 = {
154
+ .base = SZ_256M ,
155
+ .size = SZ_1G
156
+ };
157
+
158
+ total_size = (r2 .base - r1 .base ) + r2 .size ;
159
+
160
+ reset_memblock ();
161
+ memblock_add (r1 .base , r1 .size );
162
+ memblock_add (r2 .base , r2 .size );
163
+
164
+ assert (rgn -> base == r1 .base );
165
+ assert (rgn -> size == total_size );
166
+
167
+ assert (memblock .memory .cnt == 1 );
168
+ assert (memblock .memory .total_size == total_size );
169
+
170
+ return 0 ;
171
+ }
172
+
173
+ /*
174
+ * A test that tries to add two memory blocks, where the second one is
175
+ * within the range of the first entry (that is r1.base < r2.base &&
176
+ * r2.base + r2.size < r1.base + r1.size). It checks if two entries are merged
177
+ * into one region that stays the same. The counter and total size of available
178
+ * memory are expected to not be updated.
179
+ */
180
+ static int memblock_add_within_check (void )
181
+ {
182
+ struct memblock_region * rgn ;
183
+
184
+ rgn = & memblock .memory .regions [0 ];
185
+
186
+ struct region r1 = {
187
+ .base = SZ_8M ,
188
+ .size = SZ_32M
189
+ };
190
+ struct region r2 = {
191
+ .base = SZ_16M ,
192
+ .size = SZ_1M
193
+ };
194
+
195
+ reset_memblock ();
196
+ memblock_add (r1 .base , r1 .size );
197
+ memblock_add (r2 .base , r2 .size );
198
+
199
+ assert (rgn -> base == r1 .base );
200
+ assert (rgn -> size == r1 .size );
201
+
202
+ assert (memblock .memory .cnt == 1 );
203
+ assert (memblock .memory .total_size == r1 .size );
204
+
205
+ return 0 ;
206
+ }
207
+
208
+ /*
209
+ * A simple test that tries to add the same memory block twice. The counter
210
+ * and total size of available memory are expected to not be updated.
211
+ */
212
+ static int memblock_add_twice_check (void )
213
+ {
214
+ struct region r = {
215
+ .base = SZ_16K ,
216
+ .size = SZ_2M
217
+ };
218
+
219
+ reset_memblock ();
220
+
221
+ memblock_add (r .base , r .size );
222
+ memblock_add (r .base , r .size );
223
+
224
+ assert (memblock .memory .cnt == 1 );
225
+ assert (memblock .memory .total_size == r .size );
226
+
227
+ return 0 ;
228
+ }
229
+
230
+ static int memblock_add_checks (void )
231
+ {
232
+ memblock_add_simple_check ();
233
+ memblock_add_disjoint_check ();
234
+ memblock_add_overlap_top_check ();
235
+ memblock_add_overlap_bottom_check ();
236
+ memblock_add_within_check ();
237
+ memblock_add_twice_check ();
238
+
239
+ return 0 ;
240
+ }
241
+
28
242
int memblock_basic_checks (void )
29
243
{
30
244
memblock_initialization_check ();
245
+ memblock_add_checks ();
31
246
return 0 ;
32
247
}
0 commit comments