Skip to content

Commit 0980f6d

Browse files
committed
Add simple memory regions mgmt tests
1 parent e844de2 commit 0980f6d

2 files changed

Lines changed: 356 additions & 0 deletions

File tree

tests/kernel/memory_management/physical_memory/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,23 @@ target_include_directories(test_pmallocator PRIVATE
1616
target_link_libraries(test_pmallocator PRIVATE unity)
1717

1818
add_test(NAME pmallocator_tests COMMAND test_pmallocator)
19+
20+
add_executable(test_hal_memory_regions
21+
test_hal_memory_regions.c
22+
${PROJECT_SOURCE_DIR}/src/kernel/hal/arch/riscv/memory_region.c
23+
${PROJECT_SOURCE_DIR}/src/lib/stdbigos/buffer.c
24+
${PROJECT_SOURCE_DIR}/src/lib/stdbigos/bitutils.c
25+
)
26+
27+
target_compile_features(test_hal_memory_regions PUBLIC c_std_23)
28+
target_compile_options(test_hal_memory_regions PRIVATE -Wall -Wextra)
29+
30+
target_include_directories(test_hal_memory_regions PRIVATE
31+
${PROJECT_SOURCE_DIR}/include
32+
${PROJECT_SOURCE_DIR}/external/include
33+
${PROJECT_SOURCE_DIR}/src/kernel
34+
)
35+
36+
target_link_libraries(test_hal_memory_regions PRIVATE unity)
37+
38+
add_test(NAME hal_memory_regions_tests COMMAND test_hal_memory_regions)
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
#include <dt/dt.h>
2+
#include "hal/include/memory_regions.h"
3+
#include <unity.h>
4+
5+
#include <string.h>
6+
7+
static bool g_hal_initialized = true;
8+
static int g_fake_dtb;
9+
10+
// ======== iHAL stubs ========
11+
bool ihal_is_init(void) {
12+
return g_hal_initialized;
13+
}
14+
15+
error_t ihal_get_dtb(void** dtbOUT) {
16+
if (dtbOUT == NULL)
17+
return ERR_BAD_ARG;
18+
*dtbOUT = &g_fake_dtb;
19+
return ERR_NONE;
20+
}
21+
22+
// ======== DT stubs ========
23+
// Node ids used by this test topology:
24+
// root(1) -> n10(non-memory) -> n20(memory) -> n30(memory)
25+
// reserved-memory root(50) -> n60(reserved child)
26+
27+
enum {
28+
NODE_ROOT = 1,
29+
NODE_NON_MEMORY = 10,
30+
NODE_MEMORY_A = 20,
31+
NODE_MEMORY_B = 30,
32+
NODE_RESERVED_ROOT = 50,
33+
NODE_RESERVED_CHILD = 60,
34+
};
35+
36+
enum {
37+
PROP_DEVICE_TYPE_MEMORY_A = 100,
38+
PROP_DEVICE_TYPE_MEMORY_B = 101,
39+
PROP_REG_MEMORY_A = 200,
40+
PROP_REG_MEMORY_B = 201,
41+
PROP_REG_RESERVED_CHILD = 202,
42+
};
43+
44+
static const u8 s_memory_word[] = {'m', 'e', 'm', 'o', 'r', 'y'};
45+
46+
// address_cells=1, size_cells=1 => each entry is 8 bytes (u32 addr + u32 size), big-endian.
47+
static const u8 s_reg_memory_a[] = {
48+
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, // [0x1000, 0x2000]
49+
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, // [0x4000, 0x1000]
50+
};
51+
52+
static const u8 s_reg_memory_b[] = {
53+
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, // [0x8000, 0x1000]
54+
};
55+
56+
static const u8 s_reg_reserved_child[] = {
57+
0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x00, // [0xA000, 0x2000]
58+
};
59+
60+
error_t dt_init(const void* fdt, fdt_t* obj) {
61+
if (fdt == NULL || obj == NULL)
62+
return ERR_BAD_ARG;
63+
64+
memset(obj, 0, sizeof(*obj));
65+
obj->root_node = NODE_ROOT;
66+
return ERR_NONE;
67+
}
68+
69+
void dt_reset([[maybe_unused]] fdt_t* obj) {
70+
}
71+
72+
error_t dt_get_node_in_subtree_by_path(const fdt_t* fdt, dt_node_t node, const char* node_path, dt_node_t* nodeOUT) {
73+
(void)fdt;
74+
(void)node;
75+
(void)node_path;
76+
(void)nodeOUT;
77+
return ERR_NOT_FOUND;
78+
}
79+
80+
error_t dt_get_node_by_path(const fdt_t* fdt, const char* node_path, dt_node_t* nodeOUT) {
81+
if (fdt == NULL || node_path == NULL || nodeOUT == NULL)
82+
return ERR_BAD_ARG;
83+
84+
if (strcmp(node_path, "/reserved-memory") == 0) {
85+
*nodeOUT = NODE_RESERVED_ROOT;
86+
return ERR_NONE;
87+
}
88+
89+
return ERR_NOT_FOUND;
90+
}
91+
92+
error_t dt_get_node_child(const fdt_t* fdt, dt_node_t node, dt_node_t* nodeOUT) {
93+
if (fdt == NULL || nodeOUT == NULL)
94+
return ERR_BAD_ARG;
95+
96+
if (node == NODE_ROOT) {
97+
*nodeOUT = NODE_NON_MEMORY;
98+
return ERR_NONE;
99+
}
100+
101+
if (node == NODE_RESERVED_ROOT) {
102+
*nodeOUT = NODE_RESERVED_CHILD;
103+
return ERR_NONE;
104+
}
105+
106+
return ERR_NOT_FOUND;
107+
}
108+
109+
error_t dt_get_node_sibling(const fdt_t* fdt, dt_node_t node, dt_node_t* nodeOUT) {
110+
if (fdt == NULL || nodeOUT == NULL)
111+
return ERR_BAD_ARG;
112+
113+
if (node == NODE_NON_MEMORY) {
114+
*nodeOUT = NODE_MEMORY_A;
115+
return ERR_NONE;
116+
}
117+
118+
if (node == NODE_MEMORY_A) {
119+
*nodeOUT = NODE_MEMORY_B;
120+
return ERR_NONE;
121+
}
122+
123+
return ERR_NOT_FOUND;
124+
}
125+
126+
error_t dt_get_node_name(const fdt_t* fdt, dt_node_t node, buffer_t* bufOUT) {
127+
(void)fdt;
128+
(void)node;
129+
(void)bufOUT;
130+
return ERR_NOT_FOUND;
131+
}
132+
133+
error_t dt_get_node_name_ptr(const fdt_t* fdt, dt_node_t node, const char** ptrOUT) {
134+
(void)fdt;
135+
(void)node;
136+
(void)ptrOUT;
137+
return ERR_NOT_FOUND;
138+
}
139+
140+
error_t dt_get_prop_by_name(const fdt_t* fdt, dt_node_t node, const char* prop_name, dt_prop_t* propOUT) {
141+
if (fdt == NULL || prop_name == NULL || propOUT == NULL)
142+
return ERR_BAD_ARG;
143+
144+
if (strcmp(prop_name, "device_type") == 0) {
145+
if (node == NODE_MEMORY_A) {
146+
*propOUT = PROP_DEVICE_TYPE_MEMORY_A;
147+
return ERR_NONE;
148+
}
149+
if (node == NODE_MEMORY_B) {
150+
*propOUT = PROP_DEVICE_TYPE_MEMORY_B;
151+
return ERR_NONE;
152+
}
153+
return ERR_NOT_FOUND;
154+
}
155+
156+
if (strcmp(prop_name, "reg") == 0) {
157+
if (node == NODE_MEMORY_A) {
158+
*propOUT = PROP_REG_MEMORY_A;
159+
return ERR_NONE;
160+
}
161+
if (node == NODE_MEMORY_B) {
162+
*propOUT = PROP_REG_MEMORY_B;
163+
return ERR_NONE;
164+
}
165+
if (node == NODE_RESERVED_CHILD) {
166+
*propOUT = PROP_REG_RESERVED_CHILD;
167+
return ERR_NONE;
168+
}
169+
return ERR_NOT_FOUND;
170+
}
171+
172+
return ERR_NOT_FOUND;
173+
}
174+
175+
error_t dt_get_first_prop(const fdt_t* fdt, dt_node_t node, dt_prop_t* propOUT) {
176+
(void)fdt;
177+
(void)node;
178+
(void)propOUT;
179+
return ERR_NOT_FOUND;
180+
}
181+
182+
error_t dt_get_next_prop(const fdt_t* fdt, dt_prop_t prop, dt_prop_t* propOUT) {
183+
(void)fdt;
184+
(void)prop;
185+
(void)propOUT;
186+
return ERR_NOT_FOUND;
187+
}
188+
189+
error_t dt_get_prop_name(const fdt_t* fdt, dt_prop_t prop, buffer_t* bufOUT) {
190+
(void)fdt;
191+
(void)prop;
192+
(void)bufOUT;
193+
return ERR_NOT_FOUND;
194+
}
195+
196+
error_t dt_get_prop_name_ptr(const fdt_t* fdt, dt_prop_t prop, const char** ptrOUT) {
197+
(void)fdt;
198+
(void)prop;
199+
(void)ptrOUT;
200+
return ERR_NOT_FOUND;
201+
}
202+
203+
error_t dt_get_prop_buffer(const fdt_t* fdt, dt_prop_t prop, buffer_t* bufOUT) {
204+
if (fdt == NULL || bufOUT == NULL)
205+
return ERR_BAD_ARG;
206+
207+
switch (prop) {
208+
case PROP_DEVICE_TYPE_MEMORY_A:
209+
case PROP_DEVICE_TYPE_MEMORY_B:
210+
*bufOUT = make_buffer((void*)s_memory_word, sizeof(s_memory_word));
211+
return ERR_NONE;
212+
case PROP_REG_MEMORY_A:
213+
*bufOUT = make_buffer((void*)s_reg_memory_a, sizeof(s_reg_memory_a));
214+
return ERR_NONE;
215+
case PROP_REG_MEMORY_B:
216+
*bufOUT = make_buffer((void*)s_reg_memory_b, sizeof(s_reg_memory_b));
217+
return ERR_NONE;
218+
case PROP_REG_RESERVED_CHILD:
219+
*bufOUT = make_buffer((void*)s_reg_reserved_child, sizeof(s_reg_reserved_child));
220+
return ERR_NONE;
221+
default:
222+
return ERR_NOT_FOUND;
223+
}
224+
}
225+
226+
error_t dt_get_rsv_mem_entry(const fdt_t* fdt, u32 index, fdt_rsv_entry* entryOUT) {
227+
if (fdt == NULL || entryOUT == NULL)
228+
return ERR_BAD_ARG;
229+
230+
if (index == 0) {
231+
entryOUT->address = 0x9000;
232+
entryOUT->size = 0x1000;
233+
return ERR_NONE;
234+
}
235+
236+
return ERR_OUT_OF_BOUNDS;
237+
}
238+
239+
error_t dt_get_reg_cell_counts(const fdt_t* fdt, dt_node_t node, u32* address_cellsOUT, u32* size_cellsOUT) {
240+
if (fdt == NULL || address_cellsOUT == NULL || size_cellsOUT == NULL)
241+
return ERR_BAD_ARG;
242+
243+
if (node == NODE_ROOT || node == NODE_RESERVED_ROOT) {
244+
*address_cellsOUT = 1;
245+
*size_cellsOUT = 1;
246+
return ERR_NONE;
247+
}
248+
249+
return ERR_NOT_FOUND;
250+
}
251+
252+
// ======== tests ========
253+
void setUp(void) {
254+
g_hal_initialized = true;
255+
}
256+
257+
void tearDown(void) {
258+
}
259+
260+
static void test_memory_iterator_returns_not_initialized_when_hal_not_ready(void) {
261+
g_hal_initialized = false;
262+
263+
hal_memory_iterator_t iter = {0};
264+
error_t err = hal_get_memory_regions_iterator(&iter);
265+
TEST_ASSERT_EQUAL(ERR_NOT_INITIALIZED, err);
266+
}
267+
268+
static void test_memory_iterator_enumerates_all_memory_regions(void) {
269+
hal_memory_iterator_t iter = {0};
270+
error_t err = hal_get_memory_regions_iterator(&iter);
271+
TEST_ASSERT_EQUAL(ERR_NONE, err);
272+
273+
physical_memory_region_t r = {0};
274+
275+
err = hal_get_next_memory_region(&iter, &r);
276+
TEST_ASSERT_EQUAL(ERR_NONE, err);
277+
TEST_ASSERT_EQUAL_HEX64(0x1000, (uintptr_t)r.addr);
278+
TEST_ASSERT_EQUAL_HEX64(0x2000, r.size);
279+
280+
err = hal_get_next_memory_region(&iter, &r);
281+
TEST_ASSERT_EQUAL(ERR_NONE, err);
282+
TEST_ASSERT_EQUAL_HEX64(0x4000, (uintptr_t)r.addr);
283+
TEST_ASSERT_EQUAL_HEX64(0x1000, r.size);
284+
285+
err = hal_get_next_memory_region(&iter, &r);
286+
TEST_ASSERT_EQUAL(ERR_NONE, err);
287+
TEST_ASSERT_EQUAL_HEX64(0x8000, (uintptr_t)r.addr);
288+
TEST_ASSERT_EQUAL_HEX64(0x1000, r.size);
289+
290+
err = hal_get_next_memory_region(&iter, &r);
291+
TEST_ASSERT_EQUAL(ERR_NOT_FOUND, err);
292+
}
293+
294+
static void test_reserved_iterator_enumerates_memreserve_then_reserved_memory_node(void) {
295+
hal_reserved_memory_iterator_t iter = {0};
296+
error_t err = hal_get_reserved_regions_iterator(&iter);
297+
TEST_ASSERT_EQUAL(ERR_NONE, err);
298+
299+
memory_area_t area = {0};
300+
301+
err = hal_get_next_reserved_region(&iter, &area);
302+
TEST_ASSERT_EQUAL(ERR_NONE, err);
303+
TEST_ASSERT_EQUAL_HEX64(0x9000, area.addr);
304+
TEST_ASSERT_EQUAL_HEX64(0x1000, area.size);
305+
306+
err = hal_get_next_reserved_region(&iter, &area);
307+
TEST_ASSERT_EQUAL(ERR_NONE, err);
308+
TEST_ASSERT_EQUAL_HEX64(0xA000, area.addr);
309+
TEST_ASSERT_EQUAL_HEX64(0x2000, area.size);
310+
311+
err = hal_get_next_reserved_region(&iter, &area);
312+
TEST_ASSERT_EQUAL(ERR_NOT_FOUND, err);
313+
}
314+
315+
static void test_public_api_null_args_return_bad_arg(void) {
316+
hal_memory_iterator_t mem_iter = {0};
317+
hal_reserved_memory_iterator_t res_iter = {0};
318+
physical_memory_region_t pmr = {0};
319+
memory_area_t area = {0};
320+
321+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_memory_regions_iterator(NULL));
322+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_reserved_regions_iterator(NULL));
323+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_next_memory_region(NULL, &pmr));
324+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_next_memory_region(&mem_iter, NULL));
325+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_next_reserved_region(NULL, &area));
326+
TEST_ASSERT_EQUAL(ERR_BAD_ARG, hal_get_next_reserved_region(&res_iter, NULL));
327+
}
328+
329+
int main(void) {
330+
UNITY_BEGIN();
331+
RUN_TEST(test_memory_iterator_returns_not_initialized_when_hal_not_ready);
332+
RUN_TEST(test_memory_iterator_enumerates_all_memory_regions);
333+
RUN_TEST(test_reserved_iterator_enumerates_memreserve_then_reserved_memory_node);
334+
RUN_TEST(test_public_api_null_args_return_bad_arg);
335+
return UNITY_END();
336+
}

0 commit comments

Comments
 (0)