1 /*
2  * Copyright (c) 2021 Carlo Caione, <ccaione@baylibre.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public API for Shared Multi-Heap framework
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_MULTI_HEAP_MANAGER_SMH_H_
13 #define ZEPHYR_INCLUDE_MULTI_HEAP_MANAGER_SMH_H_
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @brief Heap Management
21  * @defgroup heaps Heap Management
22  * @ingroup os_services
23  * @{
24  * @}
25  */
26 
27 /**
28  * @brief Shared Multi-Heap (SMH) interface
29  * @defgroup shared_multi_heap Shared multi-heap interface
30  * @ingroup heaps
31  * @{
32  *
33  * The shared multi-heap manager uses the multi-heap allocator to manage a set
34  * of memory regions with different capabilities / attributes (cacheable,
35  * non-cacheable, etc...).
36  *
37  * All the different regions can be added at run-time to the shared multi-heap
38  * pool providing an opaque "attribute" value (an integer or enum value) that
39  * can be used by drivers or applications to request memory with certain
40  * capabilities.
41  *
42  * This framework is commonly used as follow:
43  *
44  *  - At boot time some platform code initialize the shared multi-heap
45  *    framework using @ref shared_multi_heap_pool_init and add the memory
46  *    regions to the pool with @ref shared_multi_heap_add, possibly gathering
47  *    the needed information for the regions from the DT.
48  *
49  *  - Each memory region encoded in a @ref shared_multi_heap_region structure.
50  *    This structure is also carrying an opaque and user-defined integer value
51  *    that is used to define the region capabilities (for example:
52  *    cacheability, cpu affinity, etc...)
53  *
54  *  - When a driver or application needs some dynamic memory with a certain
55  *    capability, it can use @ref shared_multi_heap_alloc (or the aligned
56  *    version) to request the memory by using the opaque parameter to select
57  *    the correct set of attributes for the needed memory. The framework will
58  *    take care of selecting the correct heap (thus memory region) to carve
59  *    memory from, based on the opaque parameter and the runtime state of the
60  *    heaps (available memory, heap state, etc...)
61  */
62 
63 /**
64  * @brief SMH region attributes enumeration type.
65  *
66  * Enumeration type for some common memory region attributes.
67  *
68  */
69 enum shared_multi_heap_attr {
70 	/** cacheable */
71 	SMH_REG_ATTR_CACHEABLE,
72 
73 	/** non-cacheable */
74 	SMH_REG_ATTR_NON_CACHEABLE,
75 
76 	/** external Memory */
77 	SMH_REG_ATTR_EXTERNAL,
78 
79 	/** must be the last item */
80 	SMH_REG_ATTR_NUM,
81 };
82 
83 /** Maximum number of standard attributes. */
84 #define MAX_SHARED_MULTI_HEAP_ATTR SMH_REG_ATTR_NUM
85 
86 /**
87  * @brief SMH region struct
88  *
89  * This struct is carrying information about the memory region to be added in
90  * the multi-heap pool.
91  */
92 struct shared_multi_heap_region {
93 	/** Memory heap attribute */
94 	uint32_t attr;
95 
96 	/** Memory heap starting virtual address */
97 	uintptr_t addr;
98 
99 	/** Memory heap size in bytes */
100 	size_t size;
101 };
102 
103 /**
104  * @brief Init the pool
105  *
106  * This must be the first function to be called to initialize the shared
107  * multi-heap pool. All the individual heaps must be added later with @ref
108  * shared_multi_heap_add.
109  *
110  * @note As for the generic multi-heap allocator the expectation is that this
111  * function will be called at soc- or board-level.
112  *
113  * @retval 0		on success.
114  * @retval -EALREADY	when the pool was already inited.
115  * @retval other	errno codes
116  */
117 int shared_multi_heap_pool_init(void);
118 
119 /**
120  * @brief Allocate memory from the memory shared multi-heap pool
121  *
122  * Allocates a block of memory of the specified size in bytes and with a
123  * specified capability / attribute. The opaque attribute parameter is used
124  * by the backend to select the correct heap to allocate memory from.
125  *
126  * @param attr		capability / attribute requested for the memory block.
127  * @param bytes		requested size of the allocation in bytes.
128  *
129  * @retval ptr		a valid pointer to heap memory.
130  * @retval err		NULL if no memory is available.
131  */
132 void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes);
133 
134 /**
135  * @brief Allocate aligned memory from the memory shared multi-heap pool
136  *
137  * Allocates a block of memory of the specified size in bytes and with a
138  * specified capability / attribute. Takes an additional parameter specifying a
139  * power of two alignment in bytes.
140  *
141  * @param attr		capability / attribute requested for the memory block.
142  * @param align		power of two alignment for the returned pointer, in bytes.
143  * @param bytes		requested size of the allocation in bytes.
144  *
145  * @retval ptr		a valid pointer to heap memory.
146  * @retval err		NULL if no memory is available.
147  */
148 void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr,
149 				      size_t align, size_t bytes);
150 
151 /**
152  * @brief Free memory from the shared multi-heap pool
153  *
154  * Used to free the passed block of memory that must be the return value of a
155  * previously call to @ref shared_multi_heap_alloc or @ref
156  * shared_multi_heap_aligned_alloc.
157  *
158  * @param block		block to free, must be a pointer to a block allocated
159  *			by shared_multi_heap_alloc or
160  *			shared_multi_heap_aligned_alloc.
161  */
162 void shared_multi_heap_free(void *block);
163 
164 /**
165  * @brief Add an heap region to the shared multi-heap pool
166  *
167  * This adds a shared multi-heap region to the multi-heap pool.
168  *
169  * @param user_data	pointer to any data for the heap.
170  * @param region	pointer to the memory region to be added.
171  *
172  * @retval 0		on success.
173  * @retval -EINVAL	when the region attribute is out-of-bound.
174  * @retval -ENOMEM	when there are no more heaps available.
175  * @retval other	errno codes
176  */
177 int shared_multi_heap_add(struct shared_multi_heap_region *region, void *user_data);
178 
179 /**
180  * @}
181  */
182 
183 #ifdef __cplusplus
184 }
185 #endif
186 
187 #endif /* ZEPHYR_INCLUDE_MULTI_HEAP_MANAGER_SMH_H_ */
188