OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Anup Patel <apatel@ventanamicro.com>
To: opensbi@lists.infradead.org
Subject: [PATCH 02/17] lib: sbi: Introduce simple heap allocator
Date: Tue, 25 Apr 2023 18:02:15 +0530	[thread overview]
Message-ID: <20230425123230.3943447-3-apatel@ventanamicro.com> (raw)
In-Reply-To: <20230425123230.3943447-1-apatel@ventanamicro.com>

We provide simple heap allocator to manage the heap space provided
by OpenSBI firmware and platform.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 include/sbi/sbi_heap.h |  44 +++++++++
 lib/sbi/objects.mk     |   1 +
 lib/sbi/sbi_heap.c     | 204 +++++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_init.c     |  15 +++
 4 files changed, 264 insertions(+)
 create mode 100644 include/sbi/sbi_heap.h
 create mode 100644 lib/sbi/sbi_heap.c

diff --git a/include/sbi/sbi_heap.h b/include/sbi/sbi_heap.h
new file mode 100644
index 0000000..88d176e
--- /dev/null
+++ b/include/sbi/sbi_heap.h
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ *   Anup Patel<apatel@ventanamicro.com>
+ */
+
+#ifndef __SBI_HEAP_H__
+#define __SBI_HEAP_H__
+
+#include <sbi/sbi_types.h>
+
+struct sbi_scratch;
+
+/** Allocate from heap area */
+void *sbi_malloc(size_t size);
+
+/** Zero allocate from heap area */
+void *sbi_zalloc(size_t size);
+
+/** Allocate array from heap area */
+static inline void *sbi_calloc(size_t nitems, size_t size)
+{
+	return sbi_zalloc(nitems * size);
+}
+
+/** Free-up to heap area */
+void sbi_free(void *ptr);
+
+/** Amount (in bytes) of free space in the heap area */
+unsigned long sbi_heap_free_space(void);
+
+/** Amount (in bytes) of used space in the heap area */
+unsigned long sbi_heap_used_space(void);
+
+/** Amount (in bytes) of reserved space in the heap area */
+unsigned long sbi_heap_reserved_space(void);
+
+/** Initialize heap area */
+int sbi_heap_init(struct sbi_scratch *scratch);
+
+#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 7d691c6..c699187 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -59,6 +59,7 @@ libsbi-objs-y += sbi_domain.o
 libsbi-objs-y += sbi_emulate_csr.o
 libsbi-objs-y += sbi_fifo.o
 libsbi-objs-y += sbi_hart.o
+libsbi-objs-y += sbi_heap.o
 libsbi-objs-y += sbi_math.o
 libsbi-objs-y += sbi_hfence.o
 libsbi-objs-y += sbi_hsm.o
diff --git a/lib/sbi/sbi_heap.c b/lib/sbi/sbi_heap.c
new file mode 100644
index 0000000..82aa1ec
--- /dev/null
+++ b/lib/sbi/sbi_heap.c
@@ -0,0 +1,204 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ *   Anup Patel<apatel@ventanamicro.com>
+ */
+
+#include <sbi/riscv_locks.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_list.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_string.h>
+
+#define HEAP_BASE_ALIGN			1024
+#define HEAP_ALLOC_ALIGN		64
+#define HEAP_HOUSEKEEPING_FACTOR	16
+
+struct heap_node {
+	struct sbi_dlist head;
+	unsigned long addr;
+	unsigned long size;
+};
+
+struct heap_control {
+	spinlock_t lock;
+	unsigned long base;
+	unsigned long size;
+	unsigned long hkbase;
+	unsigned long hksize;
+	struct sbi_dlist free_node_list;
+	struct sbi_dlist free_space_list;
+	struct sbi_dlist used_space_list;
+};
+
+static struct heap_control hpctrl;
+
+void *sbi_malloc(size_t size)
+{
+	void *ret = NULL;
+	struct heap_node *n, *np;
+
+	if (!size)
+		return NULL;
+
+	size += HEAP_ALLOC_ALIGN - 1;
+	size &= ~((unsigned long)HEAP_ALLOC_ALIGN - 1);
+
+	spin_lock(&hpctrl.lock);
+
+	np = NULL;
+	sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) {
+		if (size <= n->size) {
+			np = n;
+			break;
+		}
+	}
+	if (np) {
+		if ((size < np->size) &&
+		    !sbi_list_empty(&hpctrl.free_node_list)) {
+			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->size = size;
+			np->size -= size;
+			sbi_list_add_tail(&n->head, &hpctrl.used_space_list);
+			ret = (void *)n->addr;
+		} else if (size == np->size) {
+			sbi_list_del(&np->head);
+			sbi_list_add_tail(&np->head, &hpctrl.used_space_list);
+			ret = (void *)np->addr;
+		}
+	}
+
+	spin_unlock(&hpctrl.lock);
+
+	return ret;
+}
+
+void *sbi_zalloc(size_t size)
+{
+	void *ret = sbi_malloc(size);
+
+	if (ret)
+		sbi_memset(ret, 0, size);
+	return ret;
+}
+
+void sbi_free(void *ptr)
+{
+	struct heap_node *n, *np;
+
+	if (!ptr)
+		return;
+
+	spin_lock(&hpctrl.lock);
+
+	np = NULL;
+	sbi_list_for_each_entry(n, &hpctrl.used_space_list, head) {
+		if ((n->addr <= (unsigned long)ptr) &&
+		    ((unsigned long)ptr < (n->addr + n->size))) {
+			np = n;
+			break;
+		}
+	}
+	if (!np) {
+		spin_unlock(&hpctrl.lock);
+		return;
+	}
+
+	sbi_list_del(&np->head);
+
+	sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) {
+		if ((np->addr + np->size) == n->addr) {
+			n->addr = np->addr;
+			n->size += np->size;
+			sbi_list_add_tail(&np->head, &hpctrl.free_node_list);
+			np = NULL;
+			break;
+		} else if (np->addr == (n->addr + n->size)) {
+			n->size += np->size;
+			sbi_list_add_tail(&np->head, &hpctrl.free_node_list);
+			np = NULL;
+			break;
+		} else if ((n->addr + n->size) < np->addr) {
+			sbi_list_add(&np->head, &n->head);
+			np = NULL;
+			break;
+		}
+	}
+	if (np)
+		sbi_list_add_tail(&np->head, &hpctrl.free_space_list);
+
+	spin_unlock(&hpctrl.lock);
+}
+
+unsigned long sbi_heap_free_space(void)
+{
+	struct heap_node *n;
+	unsigned long ret = 0;
+
+	spin_lock(&hpctrl.lock);
+	sbi_list_for_each_entry(n, &hpctrl.free_space_list, head)
+		ret += n->size;
+	spin_unlock(&hpctrl.lock);
+
+	return ret;
+}
+
+unsigned long sbi_heap_used_space(void)
+{
+	return hpctrl.size - hpctrl.hksize - sbi_heap_free_space();
+}
+
+unsigned long sbi_heap_reserved_space(void)
+{
+	return hpctrl.hksize;
+}
+
+int sbi_heap_init(struct sbi_scratch *scratch)
+{
+	unsigned long i;
+	struct heap_node *n;
+
+	/* Sanity checks on heap offset and size */
+	if (!scratch->fw_heap_size ||
+	    (scratch->fw_heap_size & (HEAP_BASE_ALIGN - 1)) ||
+	    (scratch->fw_heap_offset < scratch->fw_rw_offset) ||
+	    (scratch->fw_size < (scratch->fw_heap_offset + scratch->fw_heap_size)) ||
+	    (scratch->fw_heap_offset & (HEAP_BASE_ALIGN - 1)))
+		return SBI_EINVAL;
+
+	/* Initialize heap control */
+	SPIN_LOCK_INIT(hpctrl.lock);
+	hpctrl.base = scratch->fw_start + scratch->fw_heap_offset;
+	hpctrl.size = scratch->fw_heap_size;
+	hpctrl.hkbase = hpctrl.base;
+	hpctrl.hksize = hpctrl.size / HEAP_HOUSEKEEPING_FACTOR;
+	hpctrl.hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1);
+	SBI_INIT_LIST_HEAD(&hpctrl.free_node_list);
+	SBI_INIT_LIST_HEAD(&hpctrl.free_space_list);
+	SBI_INIT_LIST_HEAD(&hpctrl.used_space_list);
+
+	/* Prepare free node list */
+	for (i = 0; i < (hpctrl.hksize / sizeof(*n)); i++) {
+		n = (struct heap_node *)(hpctrl.hkbase + (sizeof(*n) * i));
+		SBI_INIT_LIST_HEAD(&n->head);
+		n->addr = n->size = 0;
+		sbi_list_add_tail(&n->head, &hpctrl.free_node_list);
+	}
+
+	/* Prepare free space list */
+	n = sbi_list_first_entry(&hpctrl.free_node_list,
+				 struct heap_node, head);
+	sbi_list_del(&n->head);
+	n->addr = hpctrl.hkbase + hpctrl.hksize;
+	n->size = hpctrl.size - hpctrl.hksize;
+	sbi_list_add_tail(&n->head, &hpctrl.free_space_list);
+
+	return 0;
+}
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 5db8e7f..f09a7ac 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -17,6 +17,7 @@
 #include <sbi/sbi_ecall.h>
 #include <sbi/sbi_hart.h>
 #include <sbi/sbi_hartmask.h>
+#include <sbi/sbi_heap.h>
 #include <sbi/sbi_hsm.h>
 #include <sbi/sbi_ipi.h>
 #include <sbi/sbi_irqchip.h>
@@ -118,6 +119,15 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
 	sbi_printf("Firmware Size             : %d KB\n",
 		   (u32)(scratch->fw_size / 1024));
 	sbi_printf("Firmware RW Offset        : 0x%lx\n", scratch->fw_rw_offset);
+	sbi_printf("Firmware RW Size          : %d KB\n",
+		   (u32)((scratch->fw_size - scratch->fw_rw_offset) / 1024));
+	sbi_printf("Firmware Heap Offset      : 0x%lx\n", scratch->fw_heap_offset);
+	sbi_printf("Firmware Heap Size        : "
+		   "%d KB (total), %d KB (reserved), %d KB (used), %d KB (free)\n",
+		   (u32)(scratch->fw_heap_size / 1024),
+		   (u32)(sbi_heap_reserved_space() / 1024),
+		   (u32)(sbi_heap_used_space() / 1024),
+		   (u32)(sbi_heap_free_space() / 1024));
 
 	/* SBI details */
 	sbi_printf("Runtime SBI Version       : %d.%d\n",
@@ -258,6 +268,11 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 		sbi_hart_hang();
 
 	/* Note: This has to be second thing in coldboot init sequence */
+	rc = sbi_heap_init(scratch);
+	if (rc)
+		sbi_hart_hang();
+
+	/* Note: This has to be thing thing in coldboot init sequence */
 	rc = sbi_domain_init(scratch, hartid);
 	if (rc)
 		sbi_hart_hang();
-- 
2.34.1



  parent reply	other threads:[~2023-04-25 12:32 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-25 12:32 [PATCH 00/17] Introduce and use simple heap allocator Anup Patel
2023-04-25 12:32 ` [PATCH 01/17] platform: Allow platforms to specify heap size Anup Patel
2023-05-31 11:17   ` Andrew Jones
2023-04-25 12:32 ` Anup Patel [this message]
2023-05-31 12:11   ` [PATCH 02/17] lib: sbi: Introduce simple heap allocator Andrew Jones
2023-06-04 10:17     ` Anup Patel
2023-04-25 12:32 ` [PATCH 03/17] lib: sbi: Print scratch size and usage at boot time Anup Patel
2023-05-31 12:20   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 04/17] lib: sbi_pmu: Use heap for per-HART PMU state Anup Patel
2023-05-31 12:32   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 05/17] lib: sbi: Use heap for root domain creation Anup Patel
2023-05-31 12:34   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 06/17] lib: sbi: Use scratch space to save per-HART domain pointer Anup Patel
2023-05-31 12:39   ` Andrew Jones
2023-06-04 10:38     ` Anup Patel
2023-04-25 12:32 ` [PATCH 07/17] lib: utils/gpio: Use heap in SiFive and StartFive GPIO drivers Anup Patel
2023-05-31 12:42   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 08/17] lib: utils/i2c: Use heap in DesignWare and SiFive I2C drivers Anup Patel
2023-05-31 12:42   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 09/17] lib: utils/ipi: Use heap in ACLINT MSWI driver Anup Patel
2023-05-31 12:43   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 10/17] lib: utils/irqchip: Use heap in PLIC, APLIC and IMSIC drivers Anup Patel
2023-05-31 12:46   ` Andrew Jones
2023-06-04 11:43     ` Anup Patel
2023-04-25 12:32 ` [PATCH 11/17] lib: utils/timer: Use heap in ACLINT MTIMER driver Anup Patel
2023-05-31 12:50   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 12/17] lib: utils/fdt: Use heap in FDT domain parsing Anup Patel
2023-05-31 13:02   ` Andrew Jones
2023-06-05  4:00     ` Anup Patel
2023-04-25 12:32 ` [PATCH 13/17] lib: utils/ipi: Use scratch space to save per-HART MSWI pointer Anup Patel
2023-05-31 13:03   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 14/17] lib: utils/timer: Use scratch space to save per-HART MTIMER pointer Anup Patel
2023-05-31 13:06   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 15/17] lib: utils/irqchip: Use scratch space to save per-HART PLIC pointer Anup Patel
2023-05-31 13:12   ` Andrew Jones
2023-06-05  5:31     ` Anup Patel
2023-06-05  5:43   ` Jessica Clarke
2023-06-05  6:51     ` Anup Patel
2023-06-05  6:57       ` Jessica Clarke
2023-06-05 11:23         ` Anup Patel
2023-04-25 12:32 ` [PATCH 16/17] lib: utils/irqchip: Don't check hartid in imsic_update_hartid_table() Anup Patel
2023-05-31 13:14   ` Andrew Jones
2023-04-25 12:32 ` [PATCH 17/17] lib: utils/irqchip: Use scratch space to save per-HART IMSIC pointer Anup Patel
2023-05-31 13:34   ` Andrew Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230425123230.3943447-3-apatel@ventanamicro.com \
    --to=apatel@ventanamicro.com \
    --cc=opensbi@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox