diff options
| author | Raj Vishwanathan <[email protected]> | 2025-04-23 15:50:45 -0700 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2025-04-24 09:23:47 +0530 |
| commit | 99aabc6b8431a2bcf2b28a2423952e529de9fbc5 (patch) | |
| tree | 98113aa1ca54567d010931e7f9f3799ca208e435 /lib | |
| parent | 4d0128ec58e109faed3f6357f982a0079361075a (diff) | |
lib: sbi: Set the scratch allocation to alignment to cacheline size
Set the scratch allocation alignment to cacheline size specified by
riscv,cbom-block-size in the DTS file to avoid two atomic variables
from the same cache line causing livelock on some platforms. If the
cacheline is not specified, we set it a default value.
Signed-off-by: Raj Vishwanathan <[email protected]>
Reviewed-by: Anup Patel <[email protected]>
Reviewed-by: Samuel Holland <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Anup Patel <[email protected]>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sbi/sbi_scratch.c | 26 | ||||
| -rw-r--r-- | lib/utils/fdt/fdt_helper.c | 24 |
2 files changed, 48 insertions, 2 deletions
diff --git a/lib/sbi/sbi_scratch.c b/lib/sbi/sbi_scratch.c index 8c7eeaf8..bb14a1a2 100644 --- a/lib/sbi/sbi_scratch.c +++ b/lib/sbi/sbi_scratch.c @@ -14,6 +14,8 @@ #include <sbi/sbi_scratch.h> #include <sbi/sbi_string.h> +#define DEFAULT_SCRATCH_ALLOC_ALIGN __SIZEOF_POINTER__ + u32 sbi_scratch_hart_count; u32 hartindex_to_hartid_table[SBI_HARTMASK_MAX_BITS] = { [0 ... SBI_HARTMASK_MAX_BITS-1] = -1U }; struct sbi_scratch *hartindex_to_scratch_table[SBI_HARTMASK_MAX_BITS]; @@ -21,6 +23,19 @@ struct sbi_scratch *hartindex_to_scratch_table[SBI_HARTMASK_MAX_BITS]; static spinlock_t extra_lock = SPIN_LOCK_INITIALIZER; static unsigned long extra_offset = SBI_SCRATCH_EXTRA_SPACE_OFFSET; +/* + * Get the alignment size. + * Return DEFAULT_SCRATCH_ALLOC_ALIGNMENT or riscv,cbom_block_size + */ +static unsigned long sbi_get_scratch_alloc_align(void) +{ + const struct sbi_platform *plat = sbi_platform_thishart_ptr(); + + if (!plat || !plat->cbom_block_size) + return DEFAULT_SCRATCH_ALLOC_ALIGN; + return plat->cbom_block_size; +} + u32 sbi_hartid_to_hartindex(u32 hartid) { sbi_for_each_hartindex(i) @@ -57,6 +72,7 @@ unsigned long sbi_scratch_alloc_offset(unsigned long size) void *ptr; unsigned long ret = 0; struct sbi_scratch *rscratch; + unsigned long scratch_alloc_align = 0; /* * We have a simple brain-dead allocator which never expects @@ -70,8 +86,14 @@ unsigned long sbi_scratch_alloc_offset(unsigned long size) if (!size) return 0; - size += __SIZEOF_POINTER__ - 1; - size &= ~((unsigned long)__SIZEOF_POINTER__ - 1); + scratch_alloc_align = sbi_get_scratch_alloc_align(); + + /* + * We let the allocation align to cacheline bytes to avoid livelock on + * certain platforms due to atomic variables from the same cache line. + */ + size += scratch_alloc_align - 1; + size &= ~(scratch_alloc_align - 1); spin_lock(&extra_lock); diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c index 79e59dd5..b2d91fdf 100644 --- a/lib/utils/fdt/fdt_helper.c +++ b/lib/utils/fdt/fdt_helper.c @@ -246,6 +246,30 @@ int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid) return 0; } +int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size) +{ + int len; + const void *prop; + const fdt32_t *val; + + if (!fdt || cpu_offset < 0) + return SBI_EINVAL; + + prop = fdt_getprop(fdt, cpu_offset, "device_type", &len); + if (!prop || !len) + return SBI_EINVAL; + if (strncmp (prop, "cpu", strlen ("cpu"))) + return SBI_EINVAL; + + val = fdt_getprop(fdt, cpu_offset, "riscv,cbom-block-size", &len); + if (!val || len < sizeof(fdt32_t)) + return SBI_EINVAL; + + if (cbom_block_size) + *cbom_block_size = fdt32_to_cpu(*val); + return 0; +} + int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid) { u32 hartid; |
