[PATCH v6] lib: sbi: Set the scratch allocation to alignment to cacheline size.

Raj Vishwanathan raj.vishwanathan at gmail.com
Wed Apr 23 22:08:38 PDT 2025


Samuel

Thank you for the code review.  Would you like me send an updated
patch?  I am confused by "These are trivial issues, so:"

Raj


On Wed, Apr 23, 2025 at 6:17 PM Samuel Holland
<samuel.holland at sifive.com> wrote:
>
> Hi Raj,
>
> On 2025-04-23 5:50 PM, Raj Vishwanathan wrote:
> > We 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 <Raj.Vishwanathan at gmail.com>
> > --
> > Changes in V6:
> >       Add assert for assert_member_offset for cbom_block_size
> >       Update the subject line
> > Changes in V5:
> >       Formatting issues
> > Changes in V4:
> >       Pickup the cacheline size from the dts file
> > Changes in V3:
> >     Remove platform specific references to 64 Bytes.
> > Changes in V2:
> >     Added a new configuration to get the alignment size.
> > Change in V1:
> >     Original Patch
> > ---
> >  include/sbi/sbi_platform.h         |  5 +++++
> >  include/sbi_utils/fdt/fdt_helper.h |  2 ++
> >  lib/sbi/sbi_scratch.c              | 26 ++++++++++++++++++++++++--
> >  lib/utils/fdt/fdt_helper.c         | 24 ++++++++++++++++++++++++
> >  platform/generic/platform.c        |  9 +++++++++
> >  5 files changed, 64 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
> > index 82840ae..08ece32 100644
> > --- a/include/sbi/sbi_platform.h
> > +++ b/include/sbi/sbi_platform.h
> > @@ -39,6 +39,8 @@
> >  #define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__)
> >  /** Offset of hart_index2id in struct sbi_platform */
> >  #define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x60 + (__SIZEOF_POINTER__ * 2))
> > +/** Offset of cbom_block_size in struct sbi_platform */
> > +#define SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET (0x60 + (__SIZEOF_POINTER__ * 3))
> >
> >  #define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT           (1UL << 12)
> >
> > @@ -190,6 +192,8 @@ struct sbi_platform {
> >        *     hart_index2id[<abc>] = <abc>
> >        */
> >       const u32 *hart_index2id;
> > +     /** Allocation alignment for Scratch */
> > +     unsigned long cbom_block_size;
> >  };
> >
> >  /**
> > @@ -207,6 +211,7 @@ assert_member_offset(struct sbi_platform, reserved, SBI_PLATFORM_RESERVED_OFFSET
> >  assert_member_offset(struct sbi_platform, platform_ops_addr, SBI_PLATFORM_OPS_OFFSET);
> >  assert_member_offset(struct sbi_platform, firmware_context, SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET);
> >  assert_member_offset(struct sbi_platform, hart_index2id, SBI_PLATFORM_HART_INDEX2ID_OFFSET);
> > +assert_member_offset(struct sbi_platform, cbom_block_size, SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET);
> >
> >  /** Get pointer to sbi_platform for sbi_scratch pointer */
> >  #define sbi_platform_ptr(__s) \
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 5875880..04c850c 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -50,6 +50,8 @@ int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid);
> >
> >  int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid);
> >
> > +int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long  *cbom_block_size);
> > +
> >  int fdt_parse_timebase_frequency(const void *fdt, unsigned long *freq);
> >
> >  int fdt_parse_isa_extensions(const void *fdt, unsigned int hartid,
> > diff --git a/lib/sbi/sbi_scratch.c b/lib/sbi/sbi_scratch.c
> > index 8c7eeaf..916f283 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;
> >
> > +static unsigned long sbi_get_scratch_alloc_align(void)
> > +{
> > +     const struct sbi_platform *plat;
> > +     /*
> > +      * Get the alignment size. We will return DEFAULT_SCRATCH_ALLOC_ALIGNMENT
> > +      * or riscv,cbom_block_size
> > +      */
> > +     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;
>
> This variable is unconditionally assigned below, so it doesn't need to be
> initialized here.
>
> >
> >       /*
> >        * 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 79e59dd..b2d91fd 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;
> > diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> > index f3072be..2b1b949 100644
> > --- a/platform/generic/platform.c
> > +++ b/platform/generic/platform.c
> > @@ -147,6 +147,9 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
> >       const void *fdt = (void *)arg1;
> >       u32 hartid, hart_count = 0;
> >       int rc, root_offset, cpus_offset, cpu_offset, len;
> > +     unsigned long cbom_block_size = 0;
> > +     unsigned long tmp = 0;
> > +
> >
>
> Extra blank line here. These are trivial issues, so:
>
> Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
>
> >       root_offset = fdt_path_offset(fdt, "/");
> >       if (root_offset < 0)
> > @@ -174,11 +177,17 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
> >                       continue;
> >
> >               generic_hart_index2id[hart_count++] = hartid;
> > +
> > +             rc = fdt_parse_cbom_block_size(fdt, cpu_offset, &tmp);
> > +             if (rc)
> > +                     continue;
> > +             cbom_block_size = MAX(tmp, cbom_block_size);
> >       }
> >
> >       platform.hart_count = hart_count;
> >       platform.heap_size = fw_platform_get_heap_size(fdt, hart_count);
> >       platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
> > +     platform.cbom_block_size = cbom_block_size;
> >
> >       fw_platform_coldboot_harts_init(fdt);
> >
>



More information about the opensbi mailing list