Skip to content

Commit 7e97061

Browse files
committed
lib: sbi: Support multiple heaps
The upcoming SMMTT implementation will require some larger contiguous memory regions for the memory tracking tables. We plan to specify the memory region for these tables as a reserved-memory node in the device tree, and then dynamically allocate individual tables out of this region. These changes to the SBI heap allocator will allow us to explicitly create and allocate from a dedicated heap tied to the table memory region.
1 parent 0a66754 commit 7e97061

File tree

2 files changed

+113
-51
lines changed

2 files changed

+113
-51
lines changed

include/sbi/sbi_heap.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,54 @@
1212

1313
#include <sbi/sbi_types.h>
1414

15+
/* Opaque declaration of heap control struct */
16+
struct heap_control;
17+
1518
/* Alignment of heap base address and size */
1619
#define HEAP_BASE_ALIGN 1024
1720

1821
struct sbi_scratch;
1922

2023
/** Allocate from heap area */
2124
void *sbi_malloc(size_t size);
25+
void *sbi_malloc_from(struct heap_control *hpctrl, size_t size);
2226

2327
/** Zero allocate from heap area */
2428
void *sbi_zalloc(size_t size);
29+
void *sbi_zalloc_from(struct heap_control *hpctrl, size_t size);
2530

2631
/** Allocate array from heap area */
2732
static inline void *sbi_calloc(size_t nitems, size_t size)
2833
{
2934
return sbi_zalloc(nitems * size);
3035
}
3136

37+
static inline void *sbi_calloc_from(struct heap_control *hpctrl,
38+
size_t nitems, size_t size)
39+
{
40+
return sbi_zalloc_from(hpctrl, nitems * size);
41+
}
42+
3243
/** Free-up to heap area */
3344
void sbi_free(void *ptr);
45+
void sbi_free_from(struct heap_control *hpctrl, void *ptr);
3446

3547
/** Amount (in bytes) of free space in the heap area */
3648
unsigned long sbi_heap_free_space(void);
49+
unsigned long sbi_heap_free_space_from(struct heap_control *hpctrl);
3750

3851
/** Amount (in bytes) of used space in the heap area */
3952
unsigned long sbi_heap_used_space(void);
53+
unsigned long sbi_heap_used_space_from(struct heap_control *hpctrl);
4054

4155
/** Amount (in bytes) of reserved space in the heap area */
4256
unsigned long sbi_heap_reserved_space(void);
57+
unsigned long sbi_heap_reserved_space_from(struct heap_control *hpctrl);
4358

4459
/** Initialize heap area */
4560
int sbi_heap_init(struct sbi_scratch *scratch);
61+
int sbi_heap_init_new(struct heap_control *hpctrl, unsigned long base,
62+
unsigned long size);
63+
int sbi_heap_alloc_new(struct heap_control **hpctrl);
4664

4765
#endif

lib/sbi/sbi_heap.c

Lines changed: 95 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ struct heap_control {
3535
struct sbi_dlist used_space_list;
3636
};
3737

38-
static struct heap_control hpctrl;
38+
static struct heap_control global_hpctrl;
3939

40-
void *sbi_malloc(size_t size)
40+
void *sbi_malloc_from(struct heap_control *hpctrl, size_t size)
4141
{
4242
void *ret = NULL;
4343
struct heap_node *n, *np;
@@ -48,81 +48,91 @@ void *sbi_malloc(size_t size)
4848
size += HEAP_ALLOC_ALIGN - 1;
4949
size &= ~((unsigned long)HEAP_ALLOC_ALIGN - 1);
5050

51-
spin_lock(&hpctrl.lock);
51+
spin_lock(&hpctrl->lock);
5252

5353
np = NULL;
54-
sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) {
54+
sbi_list_for_each_entry(n, &hpctrl->free_space_list, head) {
5555
if (size <= n->size) {
5656
np = n;
5757
break;
5858
}
5959
}
6060
if (np) {
6161
if ((size < np->size) &&
62-
!sbi_list_empty(&hpctrl.free_node_list)) {
63-
n = sbi_list_first_entry(&hpctrl.free_node_list,
62+
!sbi_list_empty(&hpctrl->free_node_list)) {
63+
n = sbi_list_first_entry(&hpctrl->free_node_list,
6464
struct heap_node, head);
6565
sbi_list_del(&n->head);
6666
n->addr = np->addr + np->size - size;
6767
n->size = size;
6868
np->size -= size;
69-
sbi_list_add_tail(&n->head, &hpctrl.used_space_list);
69+
sbi_list_add_tail(&n->head, &hpctrl->used_space_list);
7070
ret = (void *)n->addr;
7171
} else if (size == np->size) {
7272
sbi_list_del(&np->head);
73-
sbi_list_add_tail(&np->head, &hpctrl.used_space_list);
73+
sbi_list_add_tail(&np->head, &hpctrl->used_space_list);
7474
ret = (void *)np->addr;
7575
}
7676
}
7777

78-
spin_unlock(&hpctrl.lock);
78+
spin_unlock(&hpctrl->lock);
7979

8080
return ret;
8181
}
8282

83-
void *sbi_zalloc(size_t size)
83+
void *sbi_malloc(size_t size)
8484
{
85-
void *ret = sbi_malloc(size);
85+
return sbi_malloc_from(&global_hpctrl, size);
86+
}
87+
88+
void *sbi_zalloc_from(struct heap_control *hpctrl, size_t size)
89+
{
90+
void *ret = sbi_malloc_from(hpctrl, size);
8691

8792
if (ret)
8893
sbi_memset(ret, 0, size);
8994
return ret;
9095
}
9196

92-
void sbi_free(void *ptr)
97+
void *sbi_zalloc(size_t size)
98+
{
99+
return sbi_malloc_from(&global_hpctrl, size);
100+
}
101+
102+
void sbi_free_from(struct heap_control *hpctrl, void *ptr)
93103
{
94104
struct heap_node *n, *np;
95105

96106
if (!ptr)
97107
return;
98108

99-
spin_lock(&hpctrl.lock);
109+
spin_lock(&hpctrl->lock);
100110

101111
np = NULL;
102-
sbi_list_for_each_entry(n, &hpctrl.used_space_list, head) {
112+
sbi_list_for_each_entry(n, &hpctrl->used_space_list, head) {
103113
if ((n->addr <= (unsigned long)ptr) &&
104114
((unsigned long)ptr < (n->addr + n->size))) {
105115
np = n;
106116
break;
107117
}
108118
}
109119
if (!np) {
110-
spin_unlock(&hpctrl.lock);
120+
spin_unlock(&hpctrl->lock);
111121
return;
112122
}
113123

114124
sbi_list_del(&np->head);
115125

116-
sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) {
126+
sbi_list_for_each_entry(n, &hpctrl->free_space_list, head) {
117127
if ((np->addr + np->size) == n->addr) {
118128
n->addr = np->addr;
119129
n->size += np->size;
120-
sbi_list_add_tail(&np->head, &hpctrl.free_node_list);
130+
sbi_list_add_tail(&np->head, &hpctrl->free_node_list);
121131
np = NULL;
122132
break;
123133
} else if (np->addr == (n->addr + n->size)) {
124134
n->size += np->size;
125-
sbi_list_add_tail(&np->head, &hpctrl.free_node_list);
135+
sbi_list_add_tail(&np->head, &hpctrl->free_node_list);
126136
np = NULL;
127137
break;
128138
} else if ((n->addr + n->size) < np->addr) {
@@ -132,73 +142,107 @@ void sbi_free(void *ptr)
132142
}
133143
}
134144
if (np)
135-
sbi_list_add_tail(&np->head, &hpctrl.free_space_list);
145+
sbi_list_add_tail(&np->head, &hpctrl->free_space_list);
136146

137-
spin_unlock(&hpctrl.lock);
147+
spin_unlock(&hpctrl->lock);
138148
}
139149

140-
unsigned long sbi_heap_free_space(void)
150+
void sbi_free(void *ptr)
151+
{
152+
return sbi_free_from(&global_hpctrl, ptr);
153+
}
154+
155+
unsigned long sbi_heap_free_space_from(struct heap_control *hpctrl)
141156
{
142157
struct heap_node *n;
143158
unsigned long ret = 0;
144159

145-
spin_lock(&hpctrl.lock);
146-
sbi_list_for_each_entry(n, &hpctrl.free_space_list, head)
160+
spin_lock(&hpctrl->lock);
161+
sbi_list_for_each_entry(n, &hpctrl->free_space_list, head)
147162
ret += n->size;
148-
spin_unlock(&hpctrl.lock);
163+
spin_unlock(&hpctrl->lock);
149164

150165
return ret;
151166
}
152167

168+
unsigned long sbi_heap_free_space(void)
169+
{
170+
return sbi_heap_free_space_from(&global_hpctrl);
171+
}
172+
173+
unsigned long sbi_heap_used_space_from(struct heap_control *hpctrl)
174+
{
175+
return hpctrl->size - hpctrl->hksize - sbi_heap_free_space();
176+
}
177+
153178
unsigned long sbi_heap_used_space(void)
154179
{
155-
return hpctrl.size - hpctrl.hksize - sbi_heap_free_space();
180+
return sbi_heap_free_space_from(&global_hpctrl);
181+
}
182+
183+
unsigned long sbi_heap_reserved_space_from(struct heap_control *hpctrl)
184+
{
185+
return hpctrl->hksize;
156186
}
157187

158188
unsigned long sbi_heap_reserved_space(void)
159189
{
160-
return hpctrl.hksize;
190+
return sbi_heap_free_space_from(&global_hpctrl);
161191
}
162192

163-
int sbi_heap_init(struct sbi_scratch *scratch)
193+
int sbi_heap_init_new(struct heap_control *hpctrl, unsigned long base,
194+
unsigned long size)
164195
{
165196
unsigned long i;
166197
struct heap_node *n;
167198

168-
/* Sanity checks on heap offset and size */
169-
if (!scratch->fw_heap_size ||
170-
(scratch->fw_heap_size & (HEAP_BASE_ALIGN - 1)) ||
171-
(scratch->fw_heap_offset < scratch->fw_rw_offset) ||
172-
(scratch->fw_size < (scratch->fw_heap_offset + scratch->fw_heap_size)) ||
173-
(scratch->fw_heap_offset & (HEAP_BASE_ALIGN - 1)))
174-
return SBI_EINVAL;
175-
176199
/* Initialize heap control */
177-
SPIN_LOCK_INIT(hpctrl.lock);
178-
hpctrl.base = scratch->fw_start + scratch->fw_heap_offset;
179-
hpctrl.size = scratch->fw_heap_size;
180-
hpctrl.hkbase = hpctrl.base;
181-
hpctrl.hksize = hpctrl.size / HEAP_HOUSEKEEPING_FACTOR;
182-
hpctrl.hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1);
183-
SBI_INIT_LIST_HEAD(&hpctrl.free_node_list);
184-
SBI_INIT_LIST_HEAD(&hpctrl.free_space_list);
185-
SBI_INIT_LIST_HEAD(&hpctrl.used_space_list);
200+
SPIN_LOCK_INIT(hpctrl->lock);
201+
hpctrl->base = base;
202+
hpctrl->size = size;
203+
hpctrl->hkbase = hpctrl->base;
204+
hpctrl->hksize = hpctrl->size / HEAP_HOUSEKEEPING_FACTOR;
205+
hpctrl->hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1);
206+
SBI_INIT_LIST_HEAD(&hpctrl->free_node_list);
207+
SBI_INIT_LIST_HEAD(&hpctrl->free_space_list);
208+
SBI_INIT_LIST_HEAD(&hpctrl->used_space_list);
186209

187210
/* Prepare free node list */
188-
for (i = 0; i < (hpctrl.hksize / sizeof(*n)); i++) {
189-
n = (struct heap_node *)(hpctrl.hkbase + (sizeof(*n) * i));
211+
for (i = 0; i < (hpctrl->hksize / sizeof(*n)); i++) {
212+
n = (struct heap_node *)(hpctrl->hkbase + (sizeof(*n) * i));
190213
SBI_INIT_LIST_HEAD(&n->head);
191214
n->addr = n->size = 0;
192-
sbi_list_add_tail(&n->head, &hpctrl.free_node_list);
215+
sbi_list_add_tail(&n->head, &hpctrl->free_node_list);
193216
}
194217

195218
/* Prepare free space list */
196-
n = sbi_list_first_entry(&hpctrl.free_node_list,
219+
n = sbi_list_first_entry(&hpctrl->free_node_list,
197220
struct heap_node, head);
198221
sbi_list_del(&n->head);
199-
n->addr = hpctrl.hkbase + hpctrl.hksize;
200-
n->size = hpctrl.size - hpctrl.hksize;
201-
sbi_list_add_tail(&n->head, &hpctrl.free_space_list);
222+
n->addr = hpctrl->hkbase + hpctrl->hksize;
223+
n->size = hpctrl->size - hpctrl->hksize;
224+
sbi_list_add_tail(&n->head, &hpctrl->free_space_list);
202225

203226
return 0;
204227
}
228+
229+
int sbi_heap_init(struct sbi_scratch *scratch)
230+
{
231+
/* Sanity checks on heap offset and size */
232+
if (!scratch->fw_heap_size ||
233+
(scratch->fw_heap_size & (HEAP_BASE_ALIGN - 1)) ||
234+
(scratch->fw_heap_offset < scratch->fw_rw_offset) ||
235+
(scratch->fw_size < (scratch->fw_heap_offset + scratch->fw_heap_size)) ||
236+
(scratch->fw_heap_offset & (HEAP_BASE_ALIGN - 1)))
237+
return SBI_EINVAL;
238+
239+
return sbi_heap_init_from(&global_hpctrl,
240+
scratch->fw_start + scratch->fw_heap_offset,
241+
scratch->fw_heap_size);
242+
}
243+
244+
int sbi_heap_alloc_new(struct heap_control **hpctrl)
245+
{
246+
*hpctrl = sbi_calloc(1, sizeof(struct heap_control));
247+
return 0;
248+
}

0 commit comments

Comments
 (0)