diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/opensbi/lib/sbi/sbi_scratch.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/opensbi/lib/sbi/sbi_scratch.c')
-rw-r--r-- | roms/opensbi/lib/sbi/sbi_scratch.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/roms/opensbi/lib/sbi/sbi_scratch.c b/roms/opensbi/lib/sbi/sbi_scratch.c new file mode 100644 index 000000000..96bae5be4 --- /dev/null +++ b/roms/opensbi/lib/sbi/sbi_scratch.c @@ -0,0 +1,99 @@ + /* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <sbi/riscv_locks.h> +#include <sbi/sbi_hart.h> +#include <sbi/sbi_hartmask.h> +#include <sbi/sbi_platform.h> +#include <sbi/sbi_scratch.h> +#include <sbi/sbi_string.h> + +u32 last_hartid_having_scratch = SBI_HARTMASK_MAX_BITS; +struct sbi_scratch *hartid_to_scratch_table[SBI_HARTMASK_MAX_BITS] = { 0 }; + +static spinlock_t extra_lock = SPIN_LOCK_INITIALIZER; +static unsigned long extra_offset = SBI_SCRATCH_EXTRA_SPACE_OFFSET; + +typedef struct sbi_scratch *(*hartid2scratch)(ulong hartid, ulong hartindex); + +int sbi_scratch_init(struct sbi_scratch *scratch) +{ + u32 i; + const struct sbi_platform *plat = sbi_platform_ptr(scratch); + + for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) { + if (sbi_platform_hart_invalid(plat, i)) + continue; + hartid_to_scratch_table[i] = + ((hartid2scratch)scratch->hartid_to_scratch)(i, + sbi_platform_hart_index(plat, i)); + if (hartid_to_scratch_table[i]) + last_hartid_having_scratch = i; + } + + return 0; +} + +unsigned long sbi_scratch_alloc_offset(unsigned long size, const char *owner) +{ + u32 i; + void *ptr; + unsigned long ret = 0; + struct sbi_scratch *rscratch; + + /* + * We have a simple brain-dead allocator which never expects + * anything to be free-ed hence it keeps incrementing the + * next allocation offset until it runs-out of space. + * + * In future, we will have more sophisticated allocator which + * will allow us to re-claim free-ed space. + */ + + if (!size) + return 0; + + if (size & (__SIZEOF_POINTER__ - 1)) + size = (size & ~(__SIZEOF_POINTER__ - 1)) + __SIZEOF_POINTER__; + + spin_lock(&extra_lock); + + if (SBI_SCRATCH_SIZE < (extra_offset + size)) + goto done; + + ret = extra_offset; + extra_offset += size; + +done: + spin_unlock(&extra_lock); + + if (ret) { + for (i = 0; i < sbi_scratch_last_hartid(); i++) { + rscratch = sbi_hartid_to_scratch(i); + if (!rscratch) + continue; + ptr = sbi_scratch_offset_ptr(rscratch, ret); + sbi_memset(ptr, 0, size); + } + } + + return ret; +} + +void sbi_scratch_free_offset(unsigned long offset) +{ + if ((offset < SBI_SCRATCH_EXTRA_SPACE_OFFSET) || + (SBI_SCRATCH_SIZE <= offset)) + return; + + /* + * We don't actually free-up because it's a simple + * brain-dead allocator. + */ +} |