Skip to contentSkip to conversation

lib: sbi: Heap improvements for SMMTT

PATCH New Gregor Haas 2 participants 6 messages Aug 9, 2024

lore
Share & tools
lore
#0 lore raw

v4 cover lib: sbi: Heap improvements for SMMTT

This patch series includes two changes to the SBI heap implementation, primarily to enable future work on the SMMTT implementation. First, it enables allocations from multiple independent heaps on separate memory regions. Then, it adds a simple implementation for sbi_memalign for use in allocating aligned memory.

See the individual commit messages in this series for more technical details.

v4:
- Rename sbi_memalign{_from} -> sbi_aligned_alloc{_from}
- Miscellaneous code format changes

v3:
- Add missing Signed-off-by lines
- Rename struct heap_control -> struct sbi_heap_control
- Make various functions static inline in sbi_heap.h
- Fix previously incorrect sbi_memalign() implementation

Gregor Haas (3):
lib: sbi: Support multiple heaps
lib: sbi: Allocate from beginning of heap blocks
lib: sbi: Implement aligned memory allocators

 include/sbi/sbi_heap.h |  66 +++++++++++--
 lib/sbi/sbi_heap.c     | 204 +++++++++++++++++++++++++++++------------
 2 files changed, 204 insertions(+), 66 deletions(-)
Signature · 1 line
2.45.2
#1 lore raw

PATCH v4 1/3 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.

---
 include/sbi/sbi_heap.h |  57 +++++++++++++++++--
 lib/sbi/sbi_heap.c     | 122 +++++++++++++++++++++++------------------
 2 files changed, 119 insertions(+), 60 deletions(-)
include/sbi/sbi_heap.h +51 -6
index 16755ec..9a67090 100644
@@ -12,16 +12,32 @@
 
 #include <sbi/sbi_types.h>
 
+/* Opaque declaration of heap control struct */
+struct sbi_heap_control;
+
+/* Global heap control structure */
+extern struct sbi_heap_control global_hpctrl;
+
 /* Alignment of heap base address and size */
 #define HEAP_BASE_ALIGN			1024
 
 struct sbi_scratch;
 
 /** Allocate from heap area */
-void *sbi_malloc(size_t size);
+void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size);
+
+static inline void *sbi_malloc(size_t size)
+{
+	return sbi_malloc_from(&global_hpctrl, size);
+}
 
 /** Zero allocate from heap area */
-void *sbi_zalloc(size_t size);
+void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size);
+
+static inline void *sbi_zalloc(size_t size)
+{
+	return sbi_zalloc_from(&global_hpctrl, size);
+}
 
 /** Allocate array from heap area */
 static inline void *sbi_calloc(size_t nitems, size_t size)
@@ -29,19 +45,48 @@ static inline void *sbi_calloc(size_t nitems, size_t size)
 	return sbi_zalloc(nitems * size);
 }
 
+static inline void *sbi_calloc_from(struct sbi_heap_control *hpctrl,
+				    size_t nitems, size_t size)
+{
+	return sbi_zalloc_from(hpctrl, nitems * size);
+}
+
 /** Free-up to heap area */
-void sbi_free(void *ptr);
+void sbi_free_from(struct sbi_heap_control *hpctrl, void *ptr);
+
+static inline void sbi_free(void *ptr)
+{
+	return sbi_free_from(&global_hpctrl, ptr);
+}
 
 /** Amount (in bytes) of free space in the heap area */
-unsigned long sbi_heap_free_space(void);
+unsigned long sbi_heap_free_space_from(struct sbi_heap_control *hpctrl);
+
+static inline unsigned long sbi_heap_free_space(void)
+{
+	return sbi_heap_free_space_from(&global_hpctrl);
+}
 
 /** Amount (in bytes) of used space in the heap area */
-unsigned long sbi_heap_used_space(void);
+unsigned long sbi_heap_used_space_from(struct sbi_heap_control *hpctrl);
+
+static inline unsigned long sbi_heap_used_space(void)
+{
+	return sbi_heap_used_space_from(&global_hpctrl);
+}
 
 /** Amount (in bytes) of reserved space in the heap area */
-unsigned long sbi_heap_reserved_space(void);
+unsigned long sbi_heap_reserved_space_from(struct sbi_heap_control *hpctrl);
+
+static inline unsigned long sbi_heap_reserved_space(void)
+{
+	return sbi_heap_reserved_space_from(&global_hpctrl);
+}
 
 /** Initialize heap area */
 int sbi_heap_init(struct sbi_scratch *scratch);
+int sbi_heap_init_new(struct sbi_heap_control *hpctrl, unsigned long base,
+		       unsigned long size);
+int sbi_heap_alloc_new(struct sbi_heap_control **hpctrl);
 
 #endif
lib/sbi/sbi_heap.c +68 -54

236 lines not on this page · raw message

Signature · 1 line
2.45.2
#2 lore raw

PATCH v4 2/3 lib: sbi: Allocate from beginning of heap blocks

In reply to Gregor Haas

In the next commit, we'll add a new sbi_memalign() function. In order to allocate aligned memory, we'll sometimes need to allocate from the middle of a heap block, effectively splitting it in two. Allocating from the beginning of a heap block in the nonaligned case more closely matches this behavior, reducing the complexity of understanding the heap implementation.

---
 lib/sbi/sbi_heap.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
lib/sbi/sbi_heap.c +2 -1
index e43d77c..cc4893d 100644
@@ -63,8 +63,9 @@ void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size)
 			n = sbi_list_first_entry(&hpctrl->free_node_list,
 						 struct heap_node, head);
 			sbi_list_del(&n->head);
-			n->addr = np->addr + np->size - size;
+			n->addr = np->addr;
 			n->size = size;
+			np->addr += size;
 			np->size -= size;
 			sbi_list_add_tail(&n->head, &hpctrl->used_space_list);
 			ret = (void *)n->addr;
Signature · 1 line
2.45.2
#3 lore raw

PATCH v4 3/3 lib: sbi: Implement aligned memory allocators

In reply to Gregor Haas

This change adds a simple implementation of sbi_aligned_alloc(), for future use in allocating aligned memory for SMMTT tables.

---
 include/sbi/sbi_heap.h |  9 +++++
 lib/sbi/sbi_heap.c     | 75 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 78 insertions(+), 6 deletions(-)
include/sbi/sbi_heap.h +9 -0
index 9a67090..a4b3f0c 100644
@@ -31,6 +31,15 @@ static inline void *sbi_malloc(size_t size)
 	return sbi_malloc_from(&global_hpctrl, size);
 }
 
+/** Allocate aligned from heap area */
+void *sbi_aligned_alloc_from(struct sbi_heap_control *hpctrl,
+			     size_t alignment,size_t size);
+
+static inline void *sbi_aligned_alloc(size_t alignment, size_t size)
+{
+	return sbi_aligned_alloc_from(&global_hpctrl, alignment, size);
+}
+
 /** Zero allocate from heap area */
 void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size);
 
lib/sbi/sbi_heap.c +69 -6

107 lines not on this page · raw message

Signature · 1 line
2.45.2
#4 lore raw

PATCH v4 3/3 lib: sbi: Implement aligned memory allocators

Quoted 5 lines · On Fri, Aug 9, 2024 at 8:46?AM Gregor Haas <[email protected]> wrote:

This change adds a simple implementation of sbi_aligned_alloc(), for future use in allocating aligned memory for SMMTT tables.

LGTM.

Regards,
Anup

Quoted 141 lines
---
 include/sbi/sbi_heap.h |  9 +++++
 lib/sbi/sbi_heap.c     | 75 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 78 insertions(+), 6 deletions(-)
include/sbi/sbi_heap.h +9 -0
index 9a67090..a4b3f0c 100644
@@ -31,6 +31,15 @@ static inline void *sbi_malloc(size_t size)
        return sbi_malloc_from(&global_hpctrl, size);
 }
 
+/** Allocate aligned from heap area */
+void *sbi_aligned_alloc_from(struct sbi_heap_control *hpctrl,
+                            size_t alignment,size_t size);
+
+static inline void *sbi_aligned_alloc(size_t alignment, size_t size)
+{
+       return sbi_aligned_alloc_from(&global_hpctrl, alignment, size);
+}
+
 /** Zero allocate from heap area */
 void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size);
 
lib/sbi/sbi_heap.c +69 -7
index cc4893d..6d08e44 100644
@@ -37,27 +37,67 @@ struct sbi_heap_control {
 
 struct sbi_heap_control global_hpctrl;
 
-void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size)
+static void *alloc_with_align(struct sbi_heap_control *hpctrl,
+                             size_t align, size_t size)
 {
        void *ret = NULL;
-       struct heap_node *n, *np;
+       struct heap_node *n, *np, *rem;
+       unsigned long lowest_aligned;
+       size_t pad;
 
        if (!size)
                return NULL;
 
-       size += HEAP_ALLOC_ALIGN - 1;
-       size &= ~((unsigned long)HEAP_ALLOC_ALIGN - 1);
+       size += align - 1;
+       size &= ~((unsigned long)align - 1);
 
        spin_lock(&hpctrl->lock);
 
        np = NULL;
        sbi_list_for_each_entry(n, &hpctrl->free_space_list, head) {
-               if (size <= n->size) {
+               lowest_aligned = ROUNDUP(n->addr, align);
+               pad = lowest_aligned - n->addr;
+
+               if (size + pad <= n->size) {
                        np = n;
                        break;
                }
        }
-       if (np) {
+       if (!np)
+               goto out;
+
+       if (pad) {
+               if (sbi_list_empty(&hpctrl->free_node_list)) {
+                       goto out;
+               }
+
+               n = sbi_list_first_entry(&hpctrl->free_node_list,
+                                        struct heap_node, head);
+               sbi_list_del(&n->head);
+
+               if ((size + pad < np->size) &&
+                   !sbi_list_empty(&hpctrl->free_node_list)) {
+                       rem = sbi_list_first_entry(&hpctrl->free_node_list,
+                                                  struct heap_node, head);
+                       sbi_list_del(&rem->head);
+                       rem->addr = np->addr + (size + pad);
+                       rem->size = np->size - (size + pad);
+                       sbi_list_add_tail(&rem->head,
+                                         &hpctrl->free_space_list);
+               } else if (size + pad != np->size) {
+                       /* Can't allocate, return n */
+                       sbi_list_add(&n->head, &hpctrl->free_node_list);
+                       ret = NULL;
+                       goto out;
+               }
+
+               n->addr = lowest_aligned;
+               n->size = size;
+               sbi_list_add_tail(&n->head, &hpctrl->used_space_list);
+
+               np->size = pad;
+               ret = (void *)n->addr;
+       } else {
                if ((size < np->size) &&
                    !sbi_list_empty(&hpctrl->free_node_list)) {
                        n = sbi_list_first_entry(&hpctrl->free_node_list,
@@ -76,11 +116,34 @@ void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size)
                }
        }
 
+out:
        spin_unlock(&hpctrl->lock);
 
        return ret;
 }
 
+void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size)
+{
+       return alloc_with_align(hpctrl, HEAP_ALLOC_ALIGN, size);
+}
+
+void *sbi_aligned_alloc_from(struct sbi_heap_control *hpctrl,
+                            size_t alignment, size_t size)
+{
+       if (alignment < HEAP_ALLOC_ALIGN)
+               alignment = HEAP_ALLOC_ALIGN;
+
+       /* Make sure alignment is power of two */
+       if ((alignment & (alignment - 1)) != 0)
+               return NULL;
+
+       /* Make sure size is multiple of alignment */
+       if (size % alignment != 0)
+               return NULL;
+
+       return alloc_with_align(hpctrl, alignment, size);
+}
+
 void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size)
 {
        void *ret = sbi_malloc_from(hpctrl, size);
--

2.45.2

Applied
#5 lore raw

v4 cover lib: sbi: Heap improvements for SMMTT

In reply to Gregor Haas
Quoted 18 lines · On Fri, Aug 9, 2024 at 8:46?AM Gregor Haas <[email protected]> wrote:

This patch series includes two changes to the SBI heap implementation, primarily to enable future work on the SMMTT implementation. First, it enables allocations from multiple independent heaps on separate memory regions. Then, it adds a simple implementation for sbi_memalign for use in allocating aligned memory.

See the individual commit messages in this series for more technical details.

v4:
- Rename sbi_memalign{_from} -> sbi_aligned_alloc{_from}
- Miscellaneous code format changes

v3:
- Add missing Signed-off-by lines
- Rename struct heap_control -> struct sbi_heap_control
- Make various functions static inline in sbi_heap.h
- Fix previously incorrect sbi_memalign() implementation

Quoted 4 lines

Gregor Haas (3):
lib: sbi: Support multiple heaps
lib: sbi: Allocate from beginning of heap blocks
lib: sbi: Implement aligned memory allocators

Applied this series to the riscv/opensbi repo.

Thanks,
Anup

Quoted 8 lines
 include/sbi/sbi_heap.h |  66 +++++++++++--
 lib/sbi/sbi_heap.c     | 204 +++++++++++++++++++++++++++++------------
 2 files changed, 204 insertions(+), 66 deletions(-)

--
2.45.2