diff options
author | Anup Patel <apatel@ventanamicro.com> | 2024-09-23 10:00:51 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2024-10-25 23:00:07 +0530 |
commit | 81d79913a0c23d7acc38ade7e8d8e3d48a388a3f (patch) | |
tree | c8798d746b8bcf0b79b332c2052b5caaf2b184a2 | |
parent | 65d4e9be95294c04a9a6b1be9215e9d571aba479 (diff) | |
download | opensbi-81d79913a0c23d7acc38ade7e8d8e3d48a388a3f.zip opensbi-81d79913a0c23d7acc38ade7e8d8e3d48a388a3f.tar.gz opensbi-81d79913a0c23d7acc38ade7e8d8e3d48a388a3f.tar.bz2 |
lib: sbi: Introduce domain data
Different parts of OpenSBI require their own per-domain data so
introduce domain data (or sbi_domain_data) which can be registered
by any part of OpenSBI. Using the domain data, the domain framework
will create a data pointer for every domain which can be used to
maintain some per-domain state.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com>
-rw-r--r-- | include/sbi/sbi_domain.h | 3 | ||||
-rw-r--r-- | include/sbi/sbi_domain_data.h | 93 | ||||
-rw-r--r-- | lib/sbi/objects.mk | 1 | ||||
-rw-r--r-- | lib/sbi/sbi_domain.c | 11 | ||||
-rw-r--r-- | lib/sbi/sbi_domain_data.c | 138 |
5 files changed, 246 insertions, 0 deletions
diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h index fc34982..cf09344 100644 --- a/include/sbi/sbi_domain.h +++ b/include/sbi/sbi_domain.h @@ -15,6 +15,7 @@ #include <sbi/sbi_types.h> #include <sbi/sbi_hartmask.h> #include <sbi/sbi_domain_context.h> +#include <sbi/sbi_domain_data.h> struct sbi_scratch; @@ -163,6 +164,8 @@ struct sbi_domain_memregion { struct sbi_domain { /** Node in linked list of domains */ struct sbi_dlist node; + /** Internal state of per-domain data */ + struct sbi_domain_data_priv data_priv; /** Logical index of this domain */ u32 index; /** HARTs assigned to this domain */ diff --git a/include/sbi/sbi_domain_data.h b/include/sbi/sbi_domain_data.h new file mode 100644 index 0000000..7eeafdc --- /dev/null +++ b/include/sbi/sbi_domain_data.h @@ -0,0 +1,93 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#ifndef __SBI_DOMAIN_DATA_H__ +#define __SBI_DOMAIN_DATA_H__ + +#include <sbi/sbi_types.h> +#include <sbi/sbi_list.h> + +struct sbi_domain; + +/** Maximum domain data per-domain */ +#define SBI_DOMAIN_MAX_DATA_PTRS 32 + +/** Representation of per-domain data */ +struct sbi_domain_data_priv { + /** Array of domain data pointers indexed by domain data identifier */ + void *idx_to_data_ptr[SBI_DOMAIN_MAX_DATA_PTRS]; +}; + +/** Representation of a domain data */ +struct sbi_domain_data { + /** + * Head is used for maintaining data list + * + * Note: initialized by domain framework + */ + struct sbi_dlist head; + /** + * Identifier which used to locate per-domain data + * + * Note: initialized by domain framework + */ + unsigned long data_idx; + /** Size of per-domain data */ + unsigned long data_size; + /** Optional callback to setup domain data */ + int (*data_setup)(struct sbi_domain *dom, + struct sbi_domain_data *data, void *data_ptr); + /** Optional callback to cleanup domain data */ + void (*data_cleanup)(struct sbi_domain *dom, + struct sbi_domain_data *data, void *data_ptr); +}; + +/** + * Get per-domain data pointer for a given domain + * @param dom pointer to domain + * @param data pointer to domain data + * + * @return per-domain data pointer + */ +void *sbi_domain_data_ptr(struct sbi_domain *dom, struct sbi_domain_data *data); + +/** + * Setup all domain data for a domain + * @param dom pointer to domain + * + * @return 0 on success and negative error code on failure + * + * Note: This function is used internally within domain framework. + */ +int sbi_domain_setup_data(struct sbi_domain *dom); + +/** + * Cleanup all domain data for a domain + * @param dom pointer to domain + * + * Note: This function is used internally within domain framework. + */ +void sbi_domain_cleanup_data(struct sbi_domain *dom); + +/** + * Register a domain data + * @param hndl pointer to domain data + * + * @return 0 on success and negative error code on failure + * + * Note: This function must be used only in cold boot path. + */ +int sbi_domain_register_data(struct sbi_domain_data *data); + +/** + * Unregister a domain data + * @param hndl pointer to domain data + * + * Note: This function must be used only in cold boot path. + */ +void sbi_domain_unregister_data(struct sbi_domain_data *data); + +#endif diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk index 535aa70..0b114bb 100644 --- a/lib/sbi/objects.mk +++ b/lib/sbi/objects.mk @@ -65,6 +65,7 @@ libsbi-objs-y += sbi_bitmap.o libsbi-objs-y += sbi_bitops.o libsbi-objs-y += sbi_console.o libsbi-objs-y += sbi_domain_context.o +libsbi-objs-y += sbi_domain_data.o libsbi-objs-y += sbi_domain.o libsbi-objs-y += sbi_emulate_csr.o libsbi-objs-y += sbi_fifo.o diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c index a1db131..30eb88f 100644 --- a/lib/sbi/sbi_domain.c +++ b/lib/sbi/sbi_domain.c @@ -586,6 +586,15 @@ int sbi_domain_register(struct sbi_domain *dom, } } + /* Setup data for the discovered domain */ + rc = sbi_domain_setup_data(dom); + if (rc) { + sbi_printf("%s: domain data setup failed for %s (error %d)\n", + __func__, dom->name, rc); + sbi_list_del(&dom->node); + return rc; + } + return 0; } @@ -752,6 +761,8 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid) struct sbi_domain_memregion *root_memregs; const struct sbi_platform *plat = sbi_platform_ptr(scratch); + SBI_INIT_LIST_HEAD(&domain_list); + if (scratch->fw_rw_offset == 0 || (scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) { sbi_printf("%s: fw_rw_offset is not a power of 2 (0x%lx)\n", diff --git a/lib/sbi/sbi_domain_data.c b/lib/sbi/sbi_domain_data.c new file mode 100644 index 0000000..04f0edf --- /dev/null +++ b/lib/sbi/sbi_domain_data.c @@ -0,0 +1,138 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include <sbi/sbi_bitmap.h> +#include <sbi/sbi_domain.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_heap.h> + +static SBI_LIST_HEAD(data_list); +static DECLARE_BITMAP(data_idx_bmap, SBI_DOMAIN_MAX_DATA_PTRS); + +void *sbi_domain_data_ptr(struct sbi_domain *dom, struct sbi_domain_data *data) +{ + if (dom && data && data->data_idx < SBI_DOMAIN_MAX_DATA_PTRS) + return dom->data_priv.idx_to_data_ptr[data->data_idx]; + + return NULL; +} + +static int domain_setup_data_one(struct sbi_domain *dom, + struct sbi_domain_data *data) +{ + struct sbi_domain_data_priv *priv = &dom->data_priv; + void *data_ptr; + int rc; + + if (priv->idx_to_data_ptr[data->data_idx]) + return SBI_EALREADY; + + data_ptr = sbi_zalloc(data->data_size); + if (!data_ptr) { + sbi_domain_cleanup_data(dom); + return SBI_ENOMEM; + } + + if (data->data_setup) { + rc = data->data_setup(dom, data, data_ptr); + if (rc) { + sbi_free(data_ptr); + return rc; + } + } + + priv->idx_to_data_ptr[data->data_idx] = data_ptr; + return 0; +} + +static void domain_cleanup_data_one(struct sbi_domain *dom, + struct sbi_domain_data *data) +{ + struct sbi_domain_data_priv *priv = &dom->data_priv; + void *data_ptr; + + data_ptr = priv->idx_to_data_ptr[data->data_idx]; + if (!data_ptr) + return; + + if (data->data_cleanup) + data->data_cleanup(dom, data, data_ptr); + + sbi_free(data_ptr); + priv->idx_to_data_ptr[data->data_idx] = NULL; +} + +int sbi_domain_setup_data(struct sbi_domain *dom) +{ + struct sbi_domain_data *data; + int rc; + + if (!dom) + return SBI_EINVAL; + + sbi_list_for_each_entry(data, &data_list, head) { + rc = domain_setup_data_one(dom, data); + if (rc) { + sbi_domain_cleanup_data(dom); + return rc; + } + } + + return 0; +} + +void sbi_domain_cleanup_data(struct sbi_domain *dom) +{ + struct sbi_domain_data *data; + + if (!dom) + return; + + sbi_list_for_each_entry(data, &data_list, head) + domain_cleanup_data_one(dom, data); +} + +int sbi_domain_register_data(struct sbi_domain_data *data) +{ + struct sbi_domain *dom; + u32 data_idx; + int rc; + + if (!data || !data->data_size) + return SBI_EINVAL; + + for (data_idx = 0; data_idx < SBI_DOMAIN_MAX_DATA_PTRS; data_idx++) { + if (!bitmap_test(data_idx_bmap, data_idx)) + break; + } + if (SBI_DOMAIN_MAX_DATA_PTRS <= data_idx) + return SBI_ENOSPC; + bitmap_set(data_idx_bmap, data_idx, 1); + + data->data_idx = data_idx; + sbi_list_add_tail(&data->head, &data_list); + + sbi_domain_for_each(dom) { + rc = domain_setup_data_one(dom, data); + if (rc) { + sbi_domain_unregister_data(data); + return rc; + } + } + + return 0; +} + +void sbi_domain_unregister_data(struct sbi_domain_data *data) +{ + struct sbi_domain *dom; + + sbi_domain_for_each(dom) + domain_cleanup_data_one(dom, data); + + sbi_list_del(&data->head); + bitmap_clear(data_idx_bmap, data->data_idx, 1); +} |