1 /*
2 * Copyright (c) 2023 Carlo Caione <ccaione@baylibre.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/mem_mgmt/mem_attr_heap.h>
10 #include <zephyr/dt-bindings/memory-attr/memory-attr-sw.h>
11
12 #define ADDR_MEM_CACHE DT_REG_ADDR(DT_NODELABEL(mem_cache))
13 #define ADDR_MEM_CACHE_SW DT_REG_ADDR(DT_NODELABEL(mem_cache_sw))
14 #define ADDR_MEM_NON_CACHE_SW DT_REG_ADDR(DT_NODELABEL(mem_noncache_sw))
15 #define ADDR_MEM_DMA_SW DT_REG_ADDR(DT_NODELABEL(mem_dma_sw))
16 #define ADDR_MEM_CACHE_BIG_SW DT_REG_ADDR(DT_NODELABEL(mem_cache_sw_big))
17 #define ADDR_MEM_CACHE_DMA_SW DT_REG_ADDR(DT_NODELABEL(mem_cache_cache_dma_multi))
18
ZTEST(mem_attr_heap,test_mem_attr_heap)19 ZTEST(mem_attr_heap, test_mem_attr_heap)
20 {
21 const struct mem_attr_region_t *region;
22 void *block, *old_block;
23 int ret;
24
25 /*
26 * Init the pool.
27 */
28 ret = mem_attr_heap_pool_init();
29 zassert_equal(0, ret, "Failed initialization");
30
31 /*
32 * Any subsequent initialization should fail.
33 */
34 ret = mem_attr_heap_pool_init();
35 zassert_equal(-EALREADY, ret, "Second init should be failing");
36
37 /*
38 * Allocate 0x100 bytes of cacheable memory.
39 */
40 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);
41 zassert_not_null(block, "Failed to allocate memory");
42
43 /*
44 * Check that the just allocated memory was allocated from the correct
45 * memory region.
46 */
47 region = mem_attr_heap_get_region(block);
48 zassert_equal(region->dt_addr, ADDR_MEM_CACHE_SW,
49 "Memory allocated from the wrong region");
50
51 /*
52 * Allocate 0x100 bytes of non-cacheable memory.
53 */
54 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100);
55 zassert_not_null(block, "Failed to allocate memory");
56
57 /*
58 * Check that the just allocated memory was allocated from the correct
59 * memory region.
60 */
61 region = mem_attr_heap_get_region(block);
62 zassert_equal(region->dt_addr, ADDR_MEM_NON_CACHE_SW,
63 "Memory allocated from the wrong region");
64
65 /*
66 * Allocate 0x100 bytes of DMA memory.
67 */
68 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_DMA, 0x100);
69 zassert_not_null(block, "Failed to allocate memory");
70
71 /*
72 * Check that the just allocated memory was allocated from the correct
73 * memory region.
74 */
75 region = mem_attr_heap_get_region(block);
76 zassert_equal(region->dt_addr, ADDR_MEM_DMA_SW,
77 "Memory allocated from the wrong region");
78
79 /*
80 * Allocate 0x100 bytes of cacheable and DMA memory.
81 */
82 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA, 0x100);
83 zassert_not_null(block, "Failed to allocate memory");
84
85 /*
86 * Check that the just allocated memory was allocated from the correct
87 * memory region (CACHE + DMA and not just CACHE or just DMA).
88 */
89 region = mem_attr_heap_get_region(block);
90 zassert_equal(region->dt_addr, ADDR_MEM_CACHE_DMA_SW,
91 "Memory allocated from the wrong region");
92
93 /*
94 * Allocate memory with a non-existing attribute.
95 */
96 block = mem_attr_heap_alloc(DT_MEM_SW(DT_MEM_SW_ATTR_UNKNOWN), 0x100);
97 zassert_is_null(block, "Memory allocated with non-existing attribute");
98
99 /*
100 * Allocate memory too big to fit into the first cacheable memory
101 * region. It should be allocated from the second bigger memory region.
102 */
103 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x1500);
104 zassert_not_null(block, "Failed to allocate memory");
105
106 /*
107 * Check that the just allocated memory was allocated from the correct
108 * (bigger) cacheable memory region
109 */
110 region = mem_attr_heap_get_region(block);
111 zassert_equal(region->dt_addr, ADDR_MEM_CACHE_BIG_SW,
112 "Memory allocated from the wrong region");
113
114 /*
115 * Try to allocate a buffer too big.
116 */
117 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x4000);
118 zassert_is_null(block, "Buffer too big for regions correctly allocated");
119
120 /*
121 * Check if the memory is correctly released and can be reused
122 */
123 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);
124 old_block = block;
125 mem_attr_heap_free(block);
126 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);
127 zassert_equal_ptr(old_block, block, "Memory not correctly released");
128
129 /*
130 * Check if the memory is correctly aligned when requested
131 */
132 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100);
133 zassert_true(((uintptr_t) block % 32 != 0), "");
134 mem_attr_heap_free(block);
135 block = mem_attr_heap_aligned_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100, 32);
136 zassert_true(((uintptr_t) block % 32 == 0), "");
137
138 /*
139 * Try with a different alignment
140 */
141 block = mem_attr_heap_aligned_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100, 64);
142 zassert_true(((uintptr_t) block % 64 == 0), "");
143 }
144
145 ZTEST_SUITE(mem_attr_heap, NULL, NULL, NULL, NULL, NULL);
146