From atishp at atishpatra.org  Mon Aug  2 12:38:10 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 2 Aug 2021 12:38:10 -0700
Subject: [PATCH 1/5] lib: utils/timer: Allow separate base addresses for
 MTIME and MTIMECMP
In-Reply-To: <20210724122503.2486624-2-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-2-anup.patel@wdc.com>
Message-ID: <CAOnJCU+uGRKRXnwN6CM=n9Mh6w-T5eV9Uynh8E3bPyfT62H5Cg@mail.gmail.com>

On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> We extend the ACLINT library to support separate base addresses
> for MTIME and MTIMECMP registers.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  include/sbi_utils/timer/aclint_mtimer.h | 19 ++++--
>  lib/utils/timer/aclint_mtimer.c         | 77 +++++++++++++++++++------
>  lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
>  platform/fpga/ariane/platform.c         |  8 ++-
>  platform/fpga/openpiton/platform.c      | 13 ++++-
>  platform/kendryte/k210/platform.c       |  8 ++-
>  platform/nuclei/ux600/platform.c        |  8 ++-
>  platform/template/platform.c            |  8 ++-
>  8 files changed, 116 insertions(+), 41 deletions(-)
>
> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> index 62aa086..54eb238 100644
> --- a/include/sbi_utils/timer/aclint_mtimer.h
> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> @@ -12,16 +12,25 @@
>
>  #include <sbi/sbi_types.h>
>
> -#define ACLINT_MTIMER_ALIGN            0x1000
> -#define ACLINT_MTIMER_SIZE             0x8000
> -#define ACLINT_MTIMER_MAX_HARTS        4095
> +#define ACLINT_MTIME_ALIGN                     0x8
> +#define ACLINT_MTIMECMP_ALIGN                  0x8
> +#define ACLINT_MTIMER_MAX_HARTS                4095

duplicate definition

> +
> +#define ACLINT_DEFAULT_MTIME_OFFSET    0x7ff8
> +#define ACLINT_DEFAULT_MTIME_SIZE      0x8
> +#define ACLINT_DEFAULT_MTIMECMP_OFFSET 0x0000
> +#define ACLINT_DEFAULT_MTIMECMP_SIZE   0x7ff8
> +#define ACLINT_DEFAULT_MTIMER_SIZE     0x8000
> +#define ACLINT_DEFAULT_MTIMER_ALIGN    0x1000
>
>  #define CLINT_MTIMER_OFFSET            0x4000
>
>  struct aclint_mtimer_data {
>         /* Public details */
> -       unsigned long addr;
> -       unsigned long size;
> +       unsigned long mtime_addr;
> +       unsigned long mtime_size;
> +       unsigned long mtimecmp_addr;
> +       unsigned long mtimecmp_size;
>         u32 first_hartid;
>         u32 hart_count;
>         bool has_64bit_mmio;
> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> index 41b0290..ebc9300 100644
> --- a/lib/utils/timer/aclint_mtimer.c
> +++ b/lib/utils/timer/aclint_mtimer.c
> @@ -10,6 +10,7 @@
>  #include <sbi/riscv_asm.h>
>  #include <sbi/riscv_atomic.h>
>  #include <sbi/riscv_io.h>
> +#include <sbi/sbi_bitops.h>
>  #include <sbi/sbi_domain.h>
>  #include <sbi/sbi_error.h>
>  #include <sbi/sbi_hartmask.h>
> @@ -17,9 +18,6 @@
>  #include <sbi/sbi_timer.h>
>  #include <sbi_utils/timer/aclint_mtimer.h>
>
> -#define MTIMER_CMP_OFF         0x0000
> -#define MTIMER_VAL_OFF         0x7ff8
> -
>  static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS];
>
>  #if __riscv_xlen != 32
> @@ -56,7 +54,7 @@ static void mtimer_time_wr32(bool timecmp, u64 value, volatile u64 *addr)
>  static u64 mtimer_value(void)
>  {
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[current_hartid()];
> -       u64 *time_val = ((void *)mt->addr) + MTIMER_VAL_OFF;
> +       u64 *time_val = (void *)mt->mtime_addr;
>
>         /* Read MTIMER Time Value */
>         return mt->time_rd(time_val) + mt->time_delta;
> @@ -66,7 +64,7 @@ static void mtimer_event_stop(void)
>  {
>         u32 target_hart = current_hartid();
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
>
>         /* Clear MTIMER Time Compare */
>         mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]);
> @@ -76,7 +74,7 @@ static void mtimer_event_start(u64 next_event)
>  {
>         u32 target_hart = current_hartid();
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
>
>         /* Program MTIMER Time Compare */
>         mt->time_wr(true, next_event - mt->time_delta,
> @@ -111,8 +109,8 @@ int aclint_mtimer_warm_init(void)
>          */
>         if (mt->time_delta_reference) {
>                 reference = mt->time_delta_reference;
> -               mt_time_val = (void *)mt->addr + MTIMER_VAL_OFF;
> -               ref_time_val = (void *)reference->addr + MTIMER_VAL_OFF;
> +               mt_time_val = (void *)mt->mtime_addr;
> +               ref_time_val = (void *)reference->mtime_addr;
>                 if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
>                         v1 = mt->time_rd(mt_time_val);
>                         mv = reference->time_rd(ref_time_val);
> @@ -122,24 +120,53 @@ int aclint_mtimer_warm_init(void)
>         }
>
>         /* Clear Time Compare */
> -       mt_time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       mt_time_cmp = (void *)mt->mtimecmp_addr;
>         mt->time_wr(true, -1ULL,
>                     &mt_time_cmp[target_hart - mt->first_hartid]);
>
>         return 0;
>  }
>
> +static int aclint_mtimer_add_regions(unsigned long addr, unsigned long size)
> +{
> +       int rc;
> +       unsigned long pos, end, rsize;
> +       struct sbi_domain_memregion reg;
> +
> +       pos = addr;
> +       end = addr + size;
> +       while (pos < end) {
> +               rsize = pos & (ACLINT_DEFAULT_MTIMER_ALIGN - 1);
> +               if (rsize)
> +                       rsize = 1UL << __ffs(pos);
> +               else
> +                       rsize = ((end - pos) < ACLINT_DEFAULT_MTIMER_ALIGN) ?
> +                               (end - pos) : ACLINT_DEFAULT_MTIMER_ALIGN;
> +
> +               sbi_domain_memregion_init(pos, rsize,
> +                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> +               rc = sbi_domain_root_add_memregion(&reg);
> +               if (rc)
> +                       return rc;
> +               pos += rsize;
> +       }
> +
> +       return 0;
> +}
> +
>  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>                             struct aclint_mtimer_data *reference)
>  {
>         u32 i;
>         int rc;
> -       unsigned long pos, region_size;
> -       struct sbi_domain_memregion reg;
>
>         /* Sanity checks */
> -       if (!mt || (mt->addr & (ACLINT_MTIMER_ALIGN - 1)) ||
> -           (mt->size < ACLINT_MTIMER_SIZE) ||
> +       if (!mt || !mt->mtime_size ||
> +           (mt->hart_count && !mt->mtimecmp_size) ||
> +           (mt->mtime_addr & (ACLINT_MTIME_ALIGN - 1)) ||
> +           (mt->mtime_size & (ACLINT_MTIME_ALIGN - 1)) ||
> +           (mt->mtimecmp_addr & (ACLINT_MTIMECMP_ALIGN - 1)) ||
> +           (mt->mtimecmp_size & (ACLINT_MTIMECMP_ALIGN - 1)) ||
>             (mt->first_hartid >= SBI_HARTMASK_MAX_BITS) ||
>             (mt->hart_count > ACLINT_MTIMER_MAX_HARTS))
>                 return SBI_EINVAL;
> @@ -164,12 +191,24 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>                 mtimer_hartid2data[mt->first_hartid + i] = mt;
>
>         /* Add MTIMER regions to the root domain */
> -       for (pos = 0; pos < mt->size; pos += ACLINT_MTIMER_ALIGN) {
> -               region_size = ((mt->size - pos) < ACLINT_MTIMER_ALIGN) ?
> -                             (mt->size - pos) : ACLINT_MTIMER_ALIGN;
> -               sbi_domain_memregion_init(mt->addr + pos, region_size,
> -                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> -               rc = sbi_domain_root_add_memregion(&reg);
> +       if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) {
> +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> +                                       mt->mtime_size + mt->mtimecmp_size);
> +               if (rc)
> +                       return rc;
> +       } else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) {
> +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> +                                       mt->mtime_size + mt->mtimecmp_size);
> +               if (rc)
> +                       return rc;
> +       } else {
> +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> +                                               mt->mtime_size);
> +               if (rc)
> +                       return rc;
> +
> +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> +                                               mt->mtimecmp_size);
>                 if (rc)
>                         return rc;
>         }
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 4907428..3f830ad 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
>         int rc;
> -       unsigned long offset;
> +       unsigned long offset, addr, size;
>         struct aclint_mtimer_data *mt, *mtmaster = NULL;
>
>         if (MTIMER_MAX_NR <= mtimer_count)
> @@ -31,19 +31,23 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>         if (0 < mtimer_count)
>                 mtmaster = &mtimer[0];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &mt->addr, &mt->size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
>                                    &mt->first_hartid, &mt->hart_count);
>         if (rc)
>                 return rc;
>         mt->has_64bit_mmio = true;
>
> +       mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> +       mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> +       mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
> +       mt->mtime_size = size - mt->mtimecmp_size;
> +
>         if (match->data) {
>                 /* Adjust MTIMER address and size for CLINT device */
>                 offset = *((unsigned long *)match->data);
> -               mt->addr += offset;
> -               if ((mt->size - offset) < ACLINT_MTIMER_SIZE)
> -                       return SBI_EINVAL;
> -               mt->size -= offset;
> +               mt->mtime_addr += offset;
> +               mt->mtimecmp_addr += offset;
> +               mt->mtime_size -= offset;
>                 /* Parse additional CLINT properties */
>                 if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
>                         mt->has_64bit_mmio = false;
> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
> index 0b47aa0..58a46c0 100644
> --- a/platform/fpga/ariane/platform.c
> +++ b/platform/fpga/ariane/platform.c
> @@ -44,8 +44,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = ARIANE_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = ARIANE_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = ARIANE_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index 57ec21b..bcfe7eb 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -49,8 +49,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> @@ -82,7 +86,10 @@ static int openpiton_early_init(bool cold_boot)
>         rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0");
>         if (!rc) {
>                 mswi.addr = clint_addr;
> -               mtimer.addr = clint_addr + CLINT_MTIMER_OFFSET;
> +               mtimer.mtime_addr = clint_addr + CLINT_MTIMER_OFFSET +
> +                                   ACLINT_DEFAULT_MTIME_OFFSET;
> +               mtimer.mtimecmp_addr = clint_addr + CLINT_MTIMER_OFFSET +
> +                                   ACLINT_DEFAULT_MTIMECMP_OFFSET;
>         }
>
>         return 0;
> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
> index 55c4b1e..ee4c223 100644
> --- a/platform/kendryte/k210/platform.c
> +++ b/platform/kendryte/k210/platform.c
> @@ -42,8 +42,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = K210_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = K210_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = K210_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
> index 22ca4c9..ab0becc 100644
> --- a/platform/nuclei/ux600/platform.c
> +++ b/platform/nuclei/ux600/platform.c
> @@ -74,8 +74,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = UX600_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = UX600_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = UX600_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/template/platform.c b/platform/template/platform.c
> index 3f09d98..4528822 100644
> --- a/platform/template/platform.c
> +++ b/platform/template/platform.c
> @@ -43,8 +43,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = PLATFORM_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = PLATFORM_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug  2 12:40:35 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 2 Aug 2021 12:40:35 -0700
Subject: [PATCH 2/5] lib: utils: Extend fdt_get_node_addr_size() for
 multiple register sets
In-Reply-To: <20210724122503.2486624-3-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-3-anup.patel@wdc.com>
Message-ID: <CAOnJCUL-g2HDPSzbvL3an6iwUK4mp944JOhUY7EWH1JqXyXKNg@mail.gmail.com>

On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> We add "set" parameter to fdt_get_node_addr_size() API so that
> calling function can specify index of desired register set. This
> will allow fdt_get_node_addr_size() to handle DT nodes with
> multiple register sets.
>

IMHO, index would be a better name for the parameter.

> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  include/sbi_utils/fdt/fdt_helper.h      |  3 ++-
>  lib/utils/fdt/fdt_helper.c              | 31 ++++++++++++++++++-------
>  lib/utils/gpio/fdt_gpio_sifive.c        |  2 +-
>  lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
>  4 files changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 55b9382..0445e36 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -43,7 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
>                                 const char *prop, const char *cells_prop,
>                                 int index, struct fdt_phandle_args *out_args);
>
> -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> +int fdt_get_node_addr_size(void *fdt, int node, int set,
> +                          unsigned long *addr,
>                            unsigned long *size);
>
>  int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index a970c0f..a992911 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -157,7 +157,8 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
>         return 0;
>  }
>
> -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> +int fdt_get_node_addr_size(void *fdt, int node, int set,
> +                          unsigned long *addr,
>                            unsigned long *size)
>  {
>         int parent, len, i, rc;
> @@ -165,6 +166,9 @@ int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
>         const fdt32_t *prop_addr, *prop_size;
>         uint64_t temp = 0;
>
> +       if (!fdt || node < 0 || set < 0)
> +               return SBI_EINVAL;
> +
>         parent = fdt_parent_offset(fdt, node);
>         if (parent < 0)
>                 return parent;
> @@ -179,6 +183,11 @@ int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
>         prop_addr = fdt_getprop(fdt, node, "reg", &len);
>         if (!prop_addr)
>                 return SBI_ENODEV;
> +
> +       if ((len / sizeof(u32)) <= (set * (cell_addr + cell_size)))
> +               return SBI_EINVAL;
> +
> +       prop_addr = prop_addr + (set * (cell_addr + cell_size));
>         prop_size = prop_addr + cell_addr;
>
>         if (addr) {
> @@ -271,7 +280,8 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -309,7 +319,8 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -343,7 +354,8 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -381,7 +393,8 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -441,7 +454,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
>         if (nodeoffset < 0 || !plic || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         plic->addr = reg_addr;
> @@ -482,7 +496,8 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>             !out_first_hartid || !out_hart_count)
>                 return SBI_EINVAL;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         *out_addr = reg_addr;
> @@ -544,7 +559,7 @@ int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
>         if (nodeoffset < 0)
>                 return nodeoffset;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, addr, NULL);
>         if (rc < 0 || !addr)
>                 return SBI_ENODEV;
>
> diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
> index abc9d72..bbddd58 100644
> --- a/lib/utils/gpio/fdt_gpio_sifive.c
> +++ b/lib/utils/gpio/fdt_gpio_sifive.c
> @@ -76,7 +76,7 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
>                 return SBI_ENOSPC;
>         chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoff, &chip->addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &chip->addr, NULL);
>         if (rc)
>                 return rc;
>
> diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
> index f98f03d..b0b7dbb 100644
> --- a/lib/utils/reset/fdt_reset_sifive_test.c
> +++ b/lib/utils/reset/fdt_reset_sifive_test.c
> @@ -18,7 +18,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
>         int rc;
>         unsigned long addr;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
>         if (rc)
>                 return rc;
>
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Other than that, looks good.

Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug  2 12:44:48 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 2 Aug 2021 12:44:48 -0700
Subject: [PATCH 3/5] lib: utils/fdt: Extend fdt_parse_aclint_node()
 function
In-Reply-To: <20210724122503.2486624-4-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-4-anup.patel@wdc.com>
Message-ID: <CAOnJCU+wmGBOsTjoKS8mpBX9mznMg+g5rze8L2=KBkPgqwZPfw@mail.gmail.com>

On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> The fdt_parse_aclint_node() is used to parse DT node for SiFive
> CLINT, ACLINT MTIMER, and ACLINT MSWI devices.
>
> The ACLINT MTIMER has undergone following changes:
> 1) MTIMER DT node now requires separate addresses in for MTIME
>    register and MTIMECMPx registers in the reg DT property.
> 2) MTIMER DT node might have no interrupts-extended DT property
>    when the MTIMER device has no associated HARTs (i.e. the
>    MTIMER device has no MTIMECMPx registers)
>
> This patch extends fdt_parse_aclint_node() to handle above
> mentioned changes in ACLINT MTIMER DT bindings.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  include/sbi_utils/fdt/fdt_helper.h |  3 +-
>  lib/utils/fdt/fdt_helper.c         | 50 ++++++++++++++++++------------
>  lib/utils/ipi/fdt_ipi_mswi.c       |  3 +-
>  lib/utils/timer/fdt_timer_mtimer.c | 23 +++++++++-----
>  4 files changed, 49 insertions(+), 30 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 0445e36..d49b123 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -73,7 +73,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
>  int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
>
>  int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
> -                         unsigned long *out_addr, unsigned long *out_size,
> +                         unsigned long *out_addr1, unsigned long *out_size1,
> +                         unsigned long *out_addr2, unsigned long *out_size2,
>                           u32 *out_first_hartid, u32 *out_hart_count);
>
>  int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index a992911..12e694c 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -482,38 +482,50 @@ int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat)
>  }
>
>  int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
> -                         unsigned long *out_addr, unsigned long *out_size,
> +                         unsigned long *out_addr1, unsigned long *out_size1,
> +                         unsigned long *out_addr2, unsigned long *out_size2,
>                           u32 *out_first_hartid, u32 *out_hart_count)
>  {
>         const fdt32_t *val;
>         unsigned long reg_addr, reg_size;
>         int i, rc, count, cpu_offset, cpu_intc_offset;
> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid;
> +       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
>
>         if (nodeoffset < 0 || !fdt ||
> -           !out_addr || !out_size ||
> +           !out_addr1 || !out_size1 ||
>             !out_first_hartid || !out_hart_count)
>                 return SBI_EINVAL;
>
>         rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
>                                     &reg_addr, &reg_size);
> -       if (rc < 0 || !reg_addr || !reg_size)
> +       if (rc < 0 || !reg_size)
>                 return SBI_ENODEV;
> -       *out_addr = reg_addr;
> -       *out_size = reg_size;
> +       *out_addr1 = reg_addr;
> +       *out_size1 = reg_size;
> +
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 1,
> +                                   &reg_addr, &reg_size);
> +       if (rc < 0 || !reg_size)
> +               reg_addr = reg_size = 0;
> +       if (out_addr2)
> +               *out_addr2 = reg_addr;
> +       if (out_size2)
> +               *out_size2 = reg_size;
> +
> +       *out_first_hartid = 0;
> +       *out_hart_count = 0;
>
>         val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count);
>         if (!val || count < sizeof(fdt32_t))
> -               return SBI_ENODEV;
> +               return 0;
>         count = count / sizeof(fdt32_t);
>
>         first_hartid = -1U;
> -       last_hartid = 0;
> -       *out_hart_count = 0;
> -       for (i = 0; i < count; i += 2) {
> -               phandle = fdt32_to_cpu(val[i]);
> -               hwirq = fdt32_to_cpu(val[i + 1]);
> +       hart_count = last_hartid = 0;
> +       for (i = 0; i < (count / 2); i++) {
> +               phandle = fdt32_to_cpu(val[2 * i]);
> +               hwirq = fdt32_to_cpu(val[(2 * i) + 1]);
>
>                 cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
>                 if (cpu_intc_offset < 0)
> @@ -535,17 +547,15 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>                                 first_hartid = hartid;
>                         if (hartid > last_hartid)
>                                 last_hartid = hartid;
> -                       (*out_hart_count)++;
> +                       hart_count++;
>                 }
>         }
>
> -       if ((last_hartid < first_hartid) || first_hartid == -1U)
> -               return SBI_ENODEV;
> -
> -       *out_first_hartid = first_hartid;
> -       count = last_hartid - first_hartid + 1;
> -       if (*out_hart_count < count)
> -               *out_hart_count = count;
> +       if ((last_hartid >= first_hartid) && first_hartid != -1U) {
> +               *out_first_hartid = first_hartid;
> +               count = last_hartid - first_hartid + 1;
> +               *out_hart_count = (hart_count < count) ? hart_count : count;
> +       }
>
>         return 0;
>  }
> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
> index f119f9c..1f0fda7 100644
> --- a/lib/utils/ipi/fdt_ipi_mswi.c
> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
> @@ -28,7 +28,8 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
>                 return SBI_ENOSPC;
>         ms = &mswi[mswi_count];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, false, &ms->addr, &ms->size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, false,
> +                                  &ms->addr, &ms->size, NULL, NULL,
>                                    &ms->first_hartid, &ms->hart_count);
>         if (rc)
>                 return rc;
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 3f830ad..b08ed38 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
>         int rc;
> -       unsigned long offset, addr, size;
> +       unsigned long offset, addr[2], size[2];
>         struct aclint_mtimer_data *mt, *mtmaster = NULL;
>
>         if (MTIMER_MAX_NR <= mtimer_count)
> @@ -31,18 +31,19 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>         if (0 < mtimer_count)
>                 mtmaster = &mtimer[0];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> +                                  &addr[0], &size[0], &addr[1], &size[1],
>                                    &mt->first_hartid, &mt->hart_count);
>         if (rc)
>                 return rc;
>         mt->has_64bit_mmio = true;
>
> -       mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> -       mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> -       mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
> -       mt->mtime_size = size - mt->mtimecmp_size;
> -
> -       if (match->data) {
> +       if (match->data) { /* SiFive CLINT */
> +               /* Set CLINT addresses */
> +               mt->mtimecmp_addr = addr[0] + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> +               mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> +               mt->mtime_addr = addr[0] + ACLINT_DEFAULT_MTIME_OFFSET;
> +               mt->mtime_size = size[0] - mt->mtimecmp_size;
>                 /* Adjust MTIMER address and size for CLINT device */
>                 offset = *((unsigned long *)match->data);
>                 mt->mtime_addr += offset;
> @@ -51,6 +52,12 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                 /* Parse additional CLINT properties */
>                 if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
>                         mt->has_64bit_mmio = false;
> +       } else { /* RISC-V ACLINT MTIMER */
> +               /* Set ACLINT MTIMER addresses */
> +               mt->mtime_addr = addr[0];
> +               mt->mtime_size = size[0];
> +               mt->mtimecmp_addr = addr[1];
> +               mt->mtimecmp_size = size[1];
>         }
>
>         rc = aclint_mtimer_cold_init(mt, mtmaster);
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug  2 12:49:25 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 2 Aug 2021 12:49:25 -0700
Subject: [PATCH 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting only
 32-bit MMIO
In-Reply-To: <20210724122503.2486624-5-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-5-anup.patel@wdc.com>
Message-ID: <CAOnJCUJovbgfLGuCQtYbRBDWsM0o8SXqjFkb3gCbsSzW7SSQzg@mail.gmail.com>

On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> We can have ACLINT MTIMER devices which only support 32-bit MMIO
> accesses on RV64 system so this patch adds a boolean DT property
> "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.
>

Where is this property documented ? I couldn't find it in your v3
aclint patch [1].
Did I miss something?

I also think "mtimer,32bit-mmio" may be a better choice than
"mtimer,no-64bit-mmio"

[1]https://github.com/avpatel/linux/commits/riscv_aclint_v3
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  lib/utils/timer/fdt_timer_mtimer.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index b08ed38..15a36ed 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                 mt->mtime_size = size[0];
>                 mt->mtimecmp_addr = addr[1];
>                 mt->mtimecmp_size = size[1];
> +               /* Parse additional ACLINT MTIMER properties */
> +               if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> +                       mt->has_64bit_mmio = false;
>         }
>
>         rc = aclint_mtimer_cold_init(mt, mtmaster);
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi



-- 
Regards,
Atish


From bmeng.cn at gmail.com  Wed Aug  4 23:29:30 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Thu, 5 Aug 2021 14:29:30 +0800
Subject: [PATCH 1/5] lib: utils/timer: Allow separate base addresses for
 MTIME and MTIMECMP
In-Reply-To: <20210724122503.2486624-2-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-2-anup.patel@wdc.com>
Message-ID: <CAEUhbmWPQU-xhzS6USZoj6FSw0ut--rvD=uY3ORpkuNd7KoWAw@mail.gmail.com>

On Sat, Jul 24, 2021 at 8:26 PM Anup Patel <anup.patel at wdc.com> wrote:
>
> We extend the ACLINT library to support separate base addresses
> for MTIME and MTIMECMP registers.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  include/sbi_utils/timer/aclint_mtimer.h | 19 ++++--
>  lib/utils/timer/aclint_mtimer.c         | 77 +++++++++++++++++++------
>  lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
>  platform/fpga/ariane/platform.c         |  8 ++-
>  platform/fpga/openpiton/platform.c      | 13 ++++-
>  platform/kendryte/k210/platform.c       |  8 ++-
>  platform/nuclei/ux600/platform.c        |  8 ++-
>  platform/template/platform.c            |  8 ++-
>  8 files changed, 116 insertions(+), 41 deletions(-)
>
> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> index 62aa086..54eb238 100644
> --- a/include/sbi_utils/timer/aclint_mtimer.h
> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> @@ -12,16 +12,25 @@
>
>  #include <sbi/sbi_types.h>
>
> -#define ACLINT_MTIMER_ALIGN            0x1000
> -#define ACLINT_MTIMER_SIZE             0x8000
> -#define ACLINT_MTIMER_MAX_HARTS        4095
> +#define ACLINT_MTIME_ALIGN                     0x8
> +#define ACLINT_MTIMECMP_ALIGN                  0x8
> +#define ACLINT_MTIMER_MAX_HARTS                4095
> +
> +#define ACLINT_DEFAULT_MTIME_OFFSET    0x7ff8
> +#define ACLINT_DEFAULT_MTIME_SIZE      0x8
> +#define ACLINT_DEFAULT_MTIMECMP_OFFSET 0x0000
> +#define ACLINT_DEFAULT_MTIMECMP_SIZE   0x7ff8
> +#define ACLINT_DEFAULT_MTIMER_SIZE     0x8000
> +#define ACLINT_DEFAULT_MTIMER_ALIGN    0x1000

It is confusing to have some macros be defined as MTIME while some
others with MTIMER. Can we keep them consistent?

>
>  #define CLINT_MTIMER_OFFSET            0x4000
>
>  struct aclint_mtimer_data {
>         /* Public details */
> -       unsigned long addr;
> -       unsigned long size;
> +       unsigned long mtime_addr;
> +       unsigned long mtime_size;
> +       unsigned long mtimecmp_addr;
> +       unsigned long mtimecmp_size;
>         u32 first_hartid;
>         u32 hart_count;
>         bool has_64bit_mmio;

[snip]

Regards,
Bin


From bmeng.cn at gmail.com  Thu Aug  5 00:41:13 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Thu,  5 Aug 2021 15:41:13 +0800
Subject: [PATCH] lib/utils: fdt: Change addr and size to uint64_t
Message-ID: <20210805074113.5626-1-bmeng.cn@gmail.com>

The maximum address and size encoded in DT are 64-bit numbers, so we
should use uint64_t for 'addr' and 'size' in fdt_get_node_addr_size().

Signed-off-by: Bin Meng <bmeng.cn at gmail.com>
---

 include/sbi_utils/fdt/fdt_helper.h      |  6 +++---
 lib/utils/fdt/fdt_helper.c              | 19 +++++++++----------
 lib/utils/gpio/fdt_gpio_sifive.c        |  4 +++-
 lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
 platform/fpga/openpiton/platform.c      |  2 +-
 5 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 55b9382..32aebb4 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -43,8 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
 				const char *prop, const char *cells_prop,
 				int index, struct fdt_phandle_args *out_args);
 
-int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
-			   unsigned long *size);
+int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr,
+			   uint64_t *size);
 
 int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
 
@@ -75,7 +75,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
 			  unsigned long *out_addr, unsigned long *out_size,
 			  u32 *out_first_hartid, u32 *out_hart_count);
 
-int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
+int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
 			  const char *compatible);
 
 #endif /* __FDT_HELPER_H__ */
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index a970c0f..a27f5ba 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -120,7 +120,7 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
 }
 
 static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
-				 unsigned long *addr)
+				 uint64_t *addr)
 {
 	int i, rlen;
 	int cell_addr, cell_size;
@@ -157,8 +157,7 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
 	return 0;
 }
 
-int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
-			   unsigned long *size)
+int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
 {
 	int parent, len, i, rc;
 	int cell_addr, cell_size;
@@ -266,7 +265,7 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
 {
 	int len, rc;
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
@@ -304,7 +303,7 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
 {
 	int len, rc;
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
@@ -338,7 +337,7 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
 {
 	int len, rc;
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
@@ -376,7 +375,7 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
 {
 	int len, rc;
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
@@ -436,7 +435,7 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
 {
 	int len, rc;
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 
 	if (nodeoffset < 0 || !plic || !fdt)
 		return SBI_ENODEV;
@@ -472,7 +471,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
 			  u32 *out_first_hartid, u32 *out_hart_count)
 {
 	const fdt32_t *val;
-	unsigned long reg_addr, reg_size;
+	uint64_t reg_addr, reg_size;
 	int i, rc, count, cpu_offset, cpu_intc_offset;
 	u32 phandle, hwirq, hartid, first_hartid, last_hartid;
 	u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
@@ -535,7 +534,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
 	return 0;
 }
 
-int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
+int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
 			  const char *compatible)
 {
 	int nodeoffset, rc;
diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
index abc9d72..00d3e14 100644
--- a/lib/utils/gpio/fdt_gpio_sifive.c
+++ b/lib/utils/gpio/fdt_gpio_sifive.c
@@ -71,15 +71,17 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
 {
 	int rc;
 	struct sifive_gpio_chip *chip;
+	uint64_t addr;
 
 	if (SIFIVE_GPIO_CHIP_MAX <= sifive_gpio_chip_count)
 		return SBI_ENOSPC;
 	chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
 
-	rc = fdt_get_node_addr_size(fdt, nodeoff, &chip->addr, NULL);
+	rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
 	if (rc)
 		return rc;
 
+	chip->addr = addr;
 	chip->chip.driver = &fdt_gpio_sifive;
 	chip->chip.id = phandle;
 	chip->chip.ngpio = SIFIVE_GPIO_PINS_DEF;
diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
index f98f03d..b0b59e7 100644
--- a/lib/utils/reset/fdt_reset_sifive_test.c
+++ b/lib/utils/reset/fdt_reset_sifive_test.c
@@ -16,7 +16,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
 				  const struct fdt_match *match)
 {
 	int rc;
-	unsigned long addr;
+	uint64_t addr;
 
 	rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
 	if (rc)
diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
index 57ec21b..6939b57 100644
--- a/platform/fpga/openpiton/platform.c
+++ b/platform/fpga/openpiton/platform.c
@@ -64,7 +64,7 @@ static int openpiton_early_init(bool cold_boot)
 	void *fdt;
 	struct platform_uart_data uart_data;
 	struct plic_data plic_data;
-	unsigned long clint_addr;
+	uint64_t clint_addr;
 	int rc;
 
 	if (!cold_boot)
-- 
2.25.1



From bmeng.cn at gmail.com  Thu Aug  5 01:39:55 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Thu, 5 Aug 2021 16:39:55 +0800
Subject: [PATCH v2] lib: sbi: Fix bug in strncmp function
In-Reply-To: <20210728161535.421-1-Dd_nirvana@sjtu.edu.cn>
References: <20210728161535.421-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <CAEUhbmVeLtGTbpbiO9we8vxmsV+HU1e-11kaS4VL_=XgOcBmvA@mail.gmail.com>

Hi Dong,

On Thu, Jul 29, 2021 at 12:23 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>
> No need to compare characters when the count turns to 0.
> Fix the issue in sbi_strncmp.
>
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> ---
>  lib/sbi/sbi_string.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/lib/sbi/sbi_string.c b/lib/sbi/sbi_string.c
> index 7805ba4..c87bce9 100644
> --- a/lib/sbi/sbi_string.c
> +++ b/lib/sbi/sbi_string.c
> @@ -33,6 +33,10 @@ int sbi_strncmp(const char *a, const char *b, size_t count)
>         for (; count > 0 && *a == *b && *a != '\0'; a++, b++, count--)
>                 ;
>
> +       /* No difference till the end */
> +       if (!count)
> +               return 0;
> +
>         return *a - *b;
>  }
>

Your original patch is also needed: "strncmp should return 0 when the
count is 0"

Regards,
Bin


From schwab at linux-m68k.org  Thu Aug  5 01:46:45 2021
From: schwab at linux-m68k.org (Andreas Schwab)
Date: Thu, 05 Aug 2021 10:46:45 +0200
Subject: [PATCH v2] lib: sbi: Fix bug in strncmp function
In-Reply-To: <CAEUhbmVeLtGTbpbiO9we8vxmsV+HU1e-11kaS4VL_=XgOcBmvA@mail.gmail.com>
 (Bin Meng's message of "Thu, 5 Aug 2021 16:39:55 +0800")
References: <20210728161535.421-1-Dd_nirvana@sjtu.edu.cn>
 <CAEUhbmVeLtGTbpbiO9we8vxmsV+HU1e-11kaS4VL_=XgOcBmvA@mail.gmail.com>
Message-ID: <87bl6cth1m.fsf@igel.home>

On Aug 05 2021, Bin Meng wrote:

> Hi Dong,
>
> On Thu, Jul 29, 2021 at 12:23 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>>
>> No need to compare characters when the count turns to 0.
>> Fix the issue in sbi_strncmp.
>>
>> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
>> ---
>>  lib/sbi/sbi_string.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/lib/sbi/sbi_string.c b/lib/sbi/sbi_string.c
>> index 7805ba4..c87bce9 100644
>> --- a/lib/sbi/sbi_string.c
>> +++ b/lib/sbi/sbi_string.c
>> @@ -33,6 +33,10 @@ int sbi_strncmp(const char *a, const char *b, size_t count)
>>         for (; count > 0 && *a == *b && *a != '\0'; a++, b++, count--)
>>                 ;
>>
>> +       /* No difference till the end */
>> +       if (!count)
>> +               return 0;
>> +
>>         return *a - *b;
>>  }
>>
>
> Your original patch is also needed: "strncmp should return 0 when the
> count is 0"

Which this patch duly implements.

Andreas.

-- 
Andreas Schwab, schwab at linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


From bmeng.cn at gmail.com  Thu Aug  5 02:18:46 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Thu, 5 Aug 2021 17:18:46 +0800
Subject: [PATCH v2] lib: sbi: Fix bug in strncmp function
In-Reply-To: <87bl6cth1m.fsf@igel.home>
References: <20210728161535.421-1-Dd_nirvana@sjtu.edu.cn>
 <CAEUhbmVeLtGTbpbiO9we8vxmsV+HU1e-11kaS4VL_=XgOcBmvA@mail.gmail.com>
 <87bl6cth1m.fsf@igel.home>
Message-ID: <CAEUhbmVy3HzUJgW1HvJoU3k8pnNRopfD4N4oCMrP5e8U2DAzXg@mail.gmail.com>

On Thu, Aug 5, 2021 at 4:46 PM Andreas Schwab <schwab at linux-m68k.org> wrote:
>
> On Aug 05 2021, Bin Meng wrote:
>
> > Hi Dong,
> >
> > On Thu, Jul 29, 2021 at 12:23 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
> >>
> >> No need to compare characters when the count turns to 0.
> >> Fix the issue in sbi_strncmp.
> >>
> >> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> >> ---
> >>  lib/sbi/sbi_string.c | 4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> diff --git a/lib/sbi/sbi_string.c b/lib/sbi/sbi_string.c
> >> index 7805ba4..c87bce9 100644
> >> --- a/lib/sbi/sbi_string.c
> >> +++ b/lib/sbi/sbi_string.c
> >> @@ -33,6 +33,10 @@ int sbi_strncmp(const char *a, const char *b, size_t count)
> >>         for (; count > 0 && *a == *b && *a != '\0'; a++, b++, count--)
> >>                 ;
> >>
> >> +       /* No difference till the end */
> >> +       if (!count)
> >> +               return 0;
> >> +
> >>         return *a - *b;
> >>  }
> >>
> >
> > Your original patch is also needed: "strncmp should return 0 when the
> > count is 0"
>
> Which this patch duly implements.

Ah, yes. Maybe we should update the comment to make it clear.

Anyway:
Reviewed-by: Bin Meng <bmeng.cn at gmail.com>


From anup at brainfault.org  Sat Aug  7 03:18:36 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 15:48:36 +0530
Subject: [PATCH v2] lib: sbi: Fix bug in strncmp function
In-Reply-To: <CAEUhbmVy3HzUJgW1HvJoU3k8pnNRopfD4N4oCMrP5e8U2DAzXg@mail.gmail.com>
References: <20210728161535.421-1-Dd_nirvana@sjtu.edu.cn>
 <CAEUhbmVeLtGTbpbiO9we8vxmsV+HU1e-11kaS4VL_=XgOcBmvA@mail.gmail.com>
 <87bl6cth1m.fsf@igel.home>
 <CAEUhbmVy3HzUJgW1HvJoU3k8pnNRopfD4N4oCMrP5e8U2DAzXg@mail.gmail.com>
Message-ID: <CAAhSdy1QQS6CqaD3ucFOWVn4n30fX8K+dHt_VmrJ8rEnx=09XA@mail.gmail.com>

On Thu, Aug 5, 2021 at 2:49 PM Bin Meng <bmeng.cn at gmail.com> wrote:
>
> On Thu, Aug 5, 2021 at 4:46 PM Andreas Schwab <schwab at linux-m68k.org> wrote:
> >
> > On Aug 05 2021, Bin Meng wrote:
> >
> > > Hi Dong,
> > >
> > > On Thu, Jul 29, 2021 at 12:23 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
> > >>
> > >> No need to compare characters when the count turns to 0.
> > >> Fix the issue in sbi_strncmp.
> > >>
> > >> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> > >> ---
> > >>  lib/sbi/sbi_string.c | 4 ++++
> > >>  1 file changed, 4 insertions(+)
> > >>
> > >> diff --git a/lib/sbi/sbi_string.c b/lib/sbi/sbi_string.c
> > >> index 7805ba4..c87bce9 100644
> > >> --- a/lib/sbi/sbi_string.c
> > >> +++ b/lib/sbi/sbi_string.c
> > >> @@ -33,6 +33,10 @@ int sbi_strncmp(const char *a, const char *b, size_t count)
> > >>         for (; count > 0 && *a == *b && *a != '\0'; a++, b++, count--)
> > >>                 ;
> > >>
> > >> +       /* No difference till the end */
> > >> +       if (!count)
> > >> +               return 0;
> > >> +
> > >>         return *a - *b;
> > >>  }
> > >>
> > >
> > > Your original patch is also needed: "strncmp should return 0 when the
> > > count is 0"
> >
> > Which this patch duly implements.
>
> Ah, yes. Maybe we should update the comment to make it clear.
>
> Anyway:
> Reviewed-by: Bin Meng <bmeng.cn at gmail.com>

Looks good to me.

Reviewed-by: Anup Patel <anup.patel at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Sat Aug  7 05:20:45 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 17:50:45 +0530
Subject: [PATCH] lib/utils: fdt: Change addr and size to uint64_t
In-Reply-To: <20210805074113.5626-1-bmeng.cn@gmail.com>
References: <20210805074113.5626-1-bmeng.cn@gmail.com>
Message-ID: <CAAhSdy10wEvh2EygGt7-Qsf8j7WM1sgWtmqdL8sPbN7UXh1MQQ@mail.gmail.com>

On Thu, Aug 5, 2021 at 1:11 PM Bin Meng <bmeng.cn at gmail.com> wrote:
>
> The maximum address and size encoded in DT are 64-bit numbers, so we
> should use uint64_t for 'addr' and 'size' in fdt_get_node_addr_size().
>
> Signed-off-by: Bin Meng <bmeng.cn at gmail.com>

We don't have MMU in M-mode so both RV32 and RV64 can only access
memory or devices within 0 to ULONG_MAX addresses. Based on this
rationale the addr and size parameters were kept "unsigned long". Using
"uint64_t" for addr and size is also fine because it makes things closer to
DT but on RV32 the addresses will still be truncated to 32-bit.

Overall, this looks good to me.

Reviewed-by: Anup Patel <anup.patel at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


> ---
>
>  include/sbi_utils/fdt/fdt_helper.h      |  6 +++---
>  lib/utils/fdt/fdt_helper.c              | 19 +++++++++----------
>  lib/utils/gpio/fdt_gpio_sifive.c        |  4 +++-
>  lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
>  platform/fpga/openpiton/platform.c      |  2 +-
>  5 files changed, 17 insertions(+), 16 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 55b9382..32aebb4 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -43,8 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
>                                 const char *prop, const char *cells_prop,
>                                 int index, struct fdt_phandle_args *out_args);
>
> -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> -                          unsigned long *size);
> +int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr,
> +                          uint64_t *size);
>
>  int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
>
> @@ -75,7 +75,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>                           unsigned long *out_addr, unsigned long *out_size,
>                           u32 *out_first_hartid, u32 *out_hart_count);
>
> -int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
> +int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
>                           const char *compatible);
>
>  #endif /* __FDT_HELPER_H__ */
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index a970c0f..a27f5ba 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -120,7 +120,7 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
>  }
>
>  static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
> -                                unsigned long *addr)
> +                                uint64_t *addr)
>  {
>         int i, rlen;
>         int cell_addr, cell_size;
> @@ -157,8 +157,7 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
>         return 0;
>  }
>
> -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> -                          unsigned long *size)
> +int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
>  {
>         int parent, len, i, rc;
>         int cell_addr, cell_size;
> @@ -266,7 +265,7 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
>  {
>         int len, rc;
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
> @@ -304,7 +303,7 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
>  {
>         int len, rc;
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
> @@ -338,7 +337,7 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
>  {
>         int len, rc;
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
> @@ -376,7 +375,7 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
>  {
>         int len, rc;
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
> @@ -436,7 +435,7 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
>  {
>         int len, rc;
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>
>         if (nodeoffset < 0 || !plic || !fdt)
>                 return SBI_ENODEV;
> @@ -472,7 +471,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>                           u32 *out_first_hartid, u32 *out_hart_count)
>  {
>         const fdt32_t *val;
> -       unsigned long reg_addr, reg_size;
> +       uint64_t reg_addr, reg_size;
>         int i, rc, count, cpu_offset, cpu_intc_offset;
>         u32 phandle, hwirq, hartid, first_hartid, last_hartid;
>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
> @@ -535,7 +534,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>         return 0;
>  }
>
> -int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
> +int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
>                           const char *compatible)
>  {
>         int nodeoffset, rc;
> diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
> index abc9d72..00d3e14 100644
> --- a/lib/utils/gpio/fdt_gpio_sifive.c
> +++ b/lib/utils/gpio/fdt_gpio_sifive.c
> @@ -71,15 +71,17 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
>  {
>         int rc;
>         struct sifive_gpio_chip *chip;
> +       uint64_t addr;
>
>         if (SIFIVE_GPIO_CHIP_MAX <= sifive_gpio_chip_count)
>                 return SBI_ENOSPC;
>         chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoff, &chip->addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
>         if (rc)
>                 return rc;
>
> +       chip->addr = addr;
>         chip->chip.driver = &fdt_gpio_sifive;
>         chip->chip.id = phandle;
>         chip->chip.ngpio = SIFIVE_GPIO_PINS_DEF;
> diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
> index f98f03d..b0b59e7 100644
> --- a/lib/utils/reset/fdt_reset_sifive_test.c
> +++ b/lib/utils/reset/fdt_reset_sifive_test.c
> @@ -16,7 +16,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
>         int rc;
> -       unsigned long addr;
> +       uint64_t addr;
>
>         rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
>         if (rc)
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index 57ec21b..6939b57 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -64,7 +64,7 @@ static int openpiton_early_init(bool cold_boot)
>         void *fdt;
>         struct platform_uart_data uart_data;
>         struct plic_data plic_data;
> -       unsigned long clint_addr;
> +       uint64_t clint_addr;
>         int rc;
>
>         if (!cold_boot)
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Sat Aug  7 05:28:17 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 17:58:17 +0530
Subject: [PATCH 1/5] lib: utils/timer: Allow separate base addresses for
 MTIME and MTIMECMP
In-Reply-To: <CAOnJCU+uGRKRXnwN6CM=n9Mh6w-T5eV9Uynh8E3bPyfT62H5Cg@mail.gmail.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-2-anup.patel@wdc.com>
 <CAOnJCU+uGRKRXnwN6CM=n9Mh6w-T5eV9Uynh8E3bPyfT62H5Cg@mail.gmail.com>
Message-ID: <CAAhSdy0F3dGjO5smf2y0Jw9HQfyXBCzKPhh123y50GngpR8v5A@mail.gmail.com>

On Tue, Aug 3, 2021 at 1:08 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We extend the ACLINT library to support separate base addresses
> > for MTIME and MTIMECMP registers.
> >
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  include/sbi_utils/timer/aclint_mtimer.h | 19 ++++--
> >  lib/utils/timer/aclint_mtimer.c         | 77 +++++++++++++++++++------
> >  lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
> >  platform/fpga/ariane/platform.c         |  8 ++-
> >  platform/fpga/openpiton/platform.c      | 13 ++++-
> >  platform/kendryte/k210/platform.c       |  8 ++-
> >  platform/nuclei/ux600/platform.c        |  8 ++-
> >  platform/template/platform.c            |  8 ++-
> >  8 files changed, 116 insertions(+), 41 deletions(-)
> >
> > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > index 62aa086..54eb238 100644
> > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > @@ -12,16 +12,25 @@
> >
> >  #include <sbi/sbi_types.h>
> >
> > -#define ACLINT_MTIMER_ALIGN            0x1000
> > -#define ACLINT_MTIMER_SIZE             0x8000
> > -#define ACLINT_MTIMER_MAX_HARTS        4095
> > +#define ACLINT_MTIME_ALIGN                     0x8
> > +#define ACLINT_MTIMECMP_ALIGN                  0x8
> > +#define ACLINT_MTIMER_MAX_HARTS                4095
>
> duplicate definition

Okay, will drop duplicate defines.

>
> > +
> > +#define ACLINT_DEFAULT_MTIME_OFFSET    0x7ff8
> > +#define ACLINT_DEFAULT_MTIME_SIZE      0x8
> > +#define ACLINT_DEFAULT_MTIMECMP_OFFSET 0x0000
> > +#define ACLINT_DEFAULT_MTIMECMP_SIZE   0x7ff8
> > +#define ACLINT_DEFAULT_MTIMER_SIZE     0x8000
> > +#define ACLINT_DEFAULT_MTIMER_ALIGN    0x1000
> >
> >  #define CLINT_MTIMER_OFFSET            0x4000
> >
> >  struct aclint_mtimer_data {
> >         /* Public details */
> > -       unsigned long addr;
> > -       unsigned long size;
> > +       unsigned long mtime_addr;
> > +       unsigned long mtime_size;
> > +       unsigned long mtimecmp_addr;
> > +       unsigned long mtimecmp_size;
> >         u32 first_hartid;
> >         u32 hart_count;
> >         bool has_64bit_mmio;
> > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > index 41b0290..ebc9300 100644
> > --- a/lib/utils/timer/aclint_mtimer.c
> > +++ b/lib/utils/timer/aclint_mtimer.c
> > @@ -10,6 +10,7 @@
> >  #include <sbi/riscv_asm.h>
> >  #include <sbi/riscv_atomic.h>
> >  #include <sbi/riscv_io.h>
> > +#include <sbi/sbi_bitops.h>
> >  #include <sbi/sbi_domain.h>
> >  #include <sbi/sbi_error.h>
> >  #include <sbi/sbi_hartmask.h>
> > @@ -17,9 +18,6 @@
> >  #include <sbi/sbi_timer.h>
> >  #include <sbi_utils/timer/aclint_mtimer.h>
> >
> > -#define MTIMER_CMP_OFF         0x0000
> > -#define MTIMER_VAL_OFF         0x7ff8
> > -
> >  static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS];
> >
> >  #if __riscv_xlen != 32
> > @@ -56,7 +54,7 @@ static void mtimer_time_wr32(bool timecmp, u64 value, volatile u64 *addr)
> >  static u64 mtimer_value(void)
> >  {
> >         struct aclint_mtimer_data *mt = mtimer_hartid2data[current_hartid()];
> > -       u64 *time_val = ((void *)mt->addr) + MTIMER_VAL_OFF;
> > +       u64 *time_val = (void *)mt->mtime_addr;
> >
> >         /* Read MTIMER Time Value */
> >         return mt->time_rd(time_val) + mt->time_delta;
> > @@ -66,7 +64,7 @@ static void mtimer_event_stop(void)
> >  {
> >         u32 target_hart = current_hartid();
> >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> > +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
> >
> >         /* Clear MTIMER Time Compare */
> >         mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]);
> > @@ -76,7 +74,7 @@ static void mtimer_event_start(u64 next_event)
> >  {
> >         u32 target_hart = current_hartid();
> >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> > +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
> >
> >         /* Program MTIMER Time Compare */
> >         mt->time_wr(true, next_event - mt->time_delta,
> > @@ -111,8 +109,8 @@ int aclint_mtimer_warm_init(void)
> >          */
> >         if (mt->time_delta_reference) {
> >                 reference = mt->time_delta_reference;
> > -               mt_time_val = (void *)mt->addr + MTIMER_VAL_OFF;
> > -               ref_time_val = (void *)reference->addr + MTIMER_VAL_OFF;
> > +               mt_time_val = (void *)mt->mtime_addr;
> > +               ref_time_val = (void *)reference->mtime_addr;
> >                 if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> >                         v1 = mt->time_rd(mt_time_val);
> >                         mv = reference->time_rd(ref_time_val);
> > @@ -122,24 +120,53 @@ int aclint_mtimer_warm_init(void)
> >         }
> >
> >         /* Clear Time Compare */
> > -       mt_time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> > +       mt_time_cmp = (void *)mt->mtimecmp_addr;
> >         mt->time_wr(true, -1ULL,
> >                     &mt_time_cmp[target_hart - mt->first_hartid]);
> >
> >         return 0;
> >  }
> >
> > +static int aclint_mtimer_add_regions(unsigned long addr, unsigned long size)
> > +{
> > +       int rc;
> > +       unsigned long pos, end, rsize;
> > +       struct sbi_domain_memregion reg;
> > +
> > +       pos = addr;
> > +       end = addr + size;
> > +       while (pos < end) {
> > +               rsize = pos & (ACLINT_DEFAULT_MTIMER_ALIGN - 1);
> > +               if (rsize)
> > +                       rsize = 1UL << __ffs(pos);
> > +               else
> > +                       rsize = ((end - pos) < ACLINT_DEFAULT_MTIMER_ALIGN) ?
> > +                               (end - pos) : ACLINT_DEFAULT_MTIMER_ALIGN;
> > +
> > +               sbi_domain_memregion_init(pos, rsize,
> > +                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> > +               rc = sbi_domain_root_add_memregion(&reg);
> > +               if (rc)
> > +                       return rc;
> > +               pos += rsize;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> >                             struct aclint_mtimer_data *reference)
> >  {
> >         u32 i;
> >         int rc;
> > -       unsigned long pos, region_size;
> > -       struct sbi_domain_memregion reg;
> >
> >         /* Sanity checks */
> > -       if (!mt || (mt->addr & (ACLINT_MTIMER_ALIGN - 1)) ||
> > -           (mt->size < ACLINT_MTIMER_SIZE) ||
> > +       if (!mt || !mt->mtime_size ||
> > +           (mt->hart_count && !mt->mtimecmp_size) ||
> > +           (mt->mtime_addr & (ACLINT_MTIME_ALIGN - 1)) ||
> > +           (mt->mtime_size & (ACLINT_MTIME_ALIGN - 1)) ||
> > +           (mt->mtimecmp_addr & (ACLINT_MTIMECMP_ALIGN - 1)) ||
> > +           (mt->mtimecmp_size & (ACLINT_MTIMECMP_ALIGN - 1)) ||
> >             (mt->first_hartid >= SBI_HARTMASK_MAX_BITS) ||
> >             (mt->hart_count > ACLINT_MTIMER_MAX_HARTS))
> >                 return SBI_EINVAL;
> > @@ -164,12 +191,24 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> >                 mtimer_hartid2data[mt->first_hartid + i] = mt;
> >
> >         /* Add MTIMER regions to the root domain */
> > -       for (pos = 0; pos < mt->size; pos += ACLINT_MTIMER_ALIGN) {
> > -               region_size = ((mt->size - pos) < ACLINT_MTIMER_ALIGN) ?
> > -                             (mt->size - pos) : ACLINT_MTIMER_ALIGN;
> > -               sbi_domain_memregion_init(mt->addr + pos, region_size,
> > -                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> > -               rc = sbi_domain_root_add_memregion(&reg);
> > +       if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) {
> > +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> > +                                       mt->mtime_size + mt->mtimecmp_size);
> > +               if (rc)
> > +                       return rc;
> > +       } else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) {
> > +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> > +                                       mt->mtime_size + mt->mtimecmp_size);
> > +               if (rc)
> > +                       return rc;
> > +       } else {
> > +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> > +                                               mt->mtime_size);
> > +               if (rc)
> > +                       return rc;
> > +
> > +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> > +                                               mt->mtimecmp_size);
> >                 if (rc)
> >                         return rc;
> >         }
> > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > index 4907428..3f830ad 100644
> > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > @@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >                                   const struct fdt_match *match)
> >  {
> >         int rc;
> > -       unsigned long offset;
> > +       unsigned long offset, addr, size;
> >         struct aclint_mtimer_data *mt, *mtmaster = NULL;
> >
> >         if (MTIMER_MAX_NR <= mtimer_count)
> > @@ -31,19 +31,23 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >         if (0 < mtimer_count)
> >                 mtmaster = &mtimer[0];
> >
> > -       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &mt->addr, &mt->size,
> > +       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
> >                                    &mt->first_hartid, &mt->hart_count);
> >         if (rc)
> >                 return rc;
> >         mt->has_64bit_mmio = true;
> >
> > +       mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> > +       mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> > +       mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
> > +       mt->mtime_size = size - mt->mtimecmp_size;
> > +
> >         if (match->data) {
> >                 /* Adjust MTIMER address and size for CLINT device */
> >                 offset = *((unsigned long *)match->data);
> > -               mt->addr += offset;
> > -               if ((mt->size - offset) < ACLINT_MTIMER_SIZE)
> > -                       return SBI_EINVAL;
> > -               mt->size -= offset;
> > +               mt->mtime_addr += offset;
> > +               mt->mtimecmp_addr += offset;
> > +               mt->mtime_size -= offset;
> >                 /* Parse additional CLINT properties */
> >                 if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
> >                         mt->has_64bit_mmio = false;
> > diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
> > index 0b47aa0..58a46c0 100644
> > --- a/platform/fpga/ariane/platform.c
> > +++ b/platform/fpga/ariane/platform.c
> > @@ -44,8 +44,12 @@ static struct aclint_mswi_data mswi = {
> >  };
> >
> >  static struct aclint_mtimer_data mtimer = {
> > -       .addr = ARIANE_ACLINT_MTIMER_ADDR,
> > -       .size = ACLINT_MTIMER_SIZE,
> > +       .mtime_addr = ARIANE_ACLINT_MTIMER_ADDR +
> > +                     ACLINT_DEFAULT_MTIME_OFFSET,
> > +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> > +       .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
> > +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> > +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >         .first_hartid = 0,
> >         .hart_count = ARIANE_HART_COUNT,
> >         .has_64bit_mmio = TRUE,
> > diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> > index 57ec21b..bcfe7eb 100644
> > --- a/platform/fpga/openpiton/platform.c
> > +++ b/platform/fpga/openpiton/platform.c
> > @@ -49,8 +49,12 @@ static struct aclint_mswi_data mswi = {
> >  };
> >
> >  static struct aclint_mtimer_data mtimer = {
> > -       .addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR,
> > -       .size = ACLINT_MTIMER_SIZE,
> > +       .mtime_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> > +                     ACLINT_DEFAULT_MTIME_OFFSET,
> > +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> > +       .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> > +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> > +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >         .first_hartid = 0,
> >         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
> >         .has_64bit_mmio = TRUE,
> > @@ -82,7 +86,10 @@ static int openpiton_early_init(bool cold_boot)
> >         rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0");
> >         if (!rc) {
> >                 mswi.addr = clint_addr;
> > -               mtimer.addr = clint_addr + CLINT_MTIMER_OFFSET;
> > +               mtimer.mtime_addr = clint_addr + CLINT_MTIMER_OFFSET +
> > +                                   ACLINT_DEFAULT_MTIME_OFFSET;
> > +               mtimer.mtimecmp_addr = clint_addr + CLINT_MTIMER_OFFSET +
> > +                                   ACLINT_DEFAULT_MTIMECMP_OFFSET;
> >         }
> >
> >         return 0;
> > diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
> > index 55c4b1e..ee4c223 100644
> > --- a/platform/kendryte/k210/platform.c
> > +++ b/platform/kendryte/k210/platform.c
> > @@ -42,8 +42,12 @@ static struct aclint_mswi_data mswi = {
> >  };
> >
> >  static struct aclint_mtimer_data mtimer = {
> > -       .addr = K210_ACLINT_MTIMER_ADDR,
> > -       .size = ACLINT_MTIMER_SIZE,
> > +       .mtime_addr = K210_ACLINT_MTIMER_ADDR +
> > +                     ACLINT_DEFAULT_MTIME_OFFSET,
> > +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> > +       .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
> > +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> > +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >         .first_hartid = 0,
> >         .hart_count = K210_HART_COUNT,
> >         .has_64bit_mmio = TRUE,
> > diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
> > index 22ca4c9..ab0becc 100644
> > --- a/platform/nuclei/ux600/platform.c
> > +++ b/platform/nuclei/ux600/platform.c
> > @@ -74,8 +74,12 @@ static struct aclint_mswi_data mswi = {
> >  };
> >
> >  static struct aclint_mtimer_data mtimer = {
> > -       .addr = UX600_ACLINT_MTIMER_ADDR,
> > -       .size = ACLINT_MTIMER_SIZE,
> > +       .mtime_addr = UX600_ACLINT_MTIMER_ADDR +
> > +                     ACLINT_DEFAULT_MTIME_OFFSET,
> > +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> > +       .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
> > +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> > +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >         .first_hartid = 0,
> >         .hart_count = UX600_HART_COUNT,
> >         .has_64bit_mmio = TRUE,
> > diff --git a/platform/template/platform.c b/platform/template/platform.c
> > index 3f09d98..4528822 100644
> > --- a/platform/template/platform.c
> > +++ b/platform/template/platform.c
> > @@ -43,8 +43,12 @@ static struct aclint_mswi_data mswi = {
> >  };
> >
> >  static struct aclint_mtimer_data mtimer = {
> > -       .addr = PLATFORM_ACLINT_MTIMER_ADDR,
> > -       .size = ACLINT_MTIMER_SIZE,
> > +       .mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> > +                     ACLINT_DEFAULT_MTIME_OFFSET,
> > +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> > +       .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> > +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> > +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >         .first_hartid = 0,
> >         .hart_count = PLATFORM_HART_COUNT,
> >         .has_64bit_mmio = TRUE,
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>
>
> --
> Regards,
> Atish


From anup at brainfault.org  Sat Aug  7 05:46:07 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 18:16:07 +0530
Subject: [PATCH 1/5] lib: utils/timer: Allow separate base addresses for
 MTIME and MTIMECMP
In-Reply-To: <CAEUhbmWPQU-xhzS6USZoj6FSw0ut--rvD=uY3ORpkuNd7KoWAw@mail.gmail.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-2-anup.patel@wdc.com>
 <CAEUhbmWPQU-xhzS6USZoj6FSw0ut--rvD=uY3ORpkuNd7KoWAw@mail.gmail.com>
Message-ID: <CAAhSdy3WdAgpRQBn7iJX7yKPLaARu7nB4u61XpwzN3=sj8GTxQ@mail.gmail.com>

On Thu, Aug 5, 2021 at 11:59 AM Bin Meng <bmeng.cn at gmail.com> wrote:
>
> On Sat, Jul 24, 2021 at 8:26 PM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We extend the ACLINT library to support separate base addresses
> > for MTIME and MTIMECMP registers.
> >
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  include/sbi_utils/timer/aclint_mtimer.h | 19 ++++--
> >  lib/utils/timer/aclint_mtimer.c         | 77 +++++++++++++++++++------
> >  lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
> >  platform/fpga/ariane/platform.c         |  8 ++-
> >  platform/fpga/openpiton/platform.c      | 13 ++++-
> >  platform/kendryte/k210/platform.c       |  8 ++-
> >  platform/nuclei/ux600/platform.c        |  8 ++-
> >  platform/template/platform.c            |  8 ++-
> >  8 files changed, 116 insertions(+), 41 deletions(-)
> >
> > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > index 62aa086..54eb238 100644
> > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > @@ -12,16 +12,25 @@
> >
> >  #include <sbi/sbi_types.h>
> >
> > -#define ACLINT_MTIMER_ALIGN            0x1000
> > -#define ACLINT_MTIMER_SIZE             0x8000
> > -#define ACLINT_MTIMER_MAX_HARTS        4095
> > +#define ACLINT_MTIME_ALIGN                     0x8
> > +#define ACLINT_MTIMECMP_ALIGN                  0x8
> > +#define ACLINT_MTIMER_MAX_HARTS                4095
> > +
> > +#define ACLINT_DEFAULT_MTIME_OFFSET    0x7ff8
> > +#define ACLINT_DEFAULT_MTIME_SIZE      0x8
> > +#define ACLINT_DEFAULT_MTIMECMP_OFFSET 0x0000
> > +#define ACLINT_DEFAULT_MTIMECMP_SIZE   0x7ff8
> > +#define ACLINT_DEFAULT_MTIMER_SIZE     0x8000
> > +#define ACLINT_DEFAULT_MTIMER_ALIGN    0x1000
>
> It is confusing to have some macros be defined as MTIME while some
> others with MTIMER. Can we keep them consistent?

Okay, let me try to simplify this.

Regards,
Anup

>
> >
> >  #define CLINT_MTIMER_OFFSET            0x4000
> >
> >  struct aclint_mtimer_data {
> >         /* Public details */
> > -       unsigned long addr;
> > -       unsigned long size;
> > +       unsigned long mtime_addr;
> > +       unsigned long mtime_size;
> > +       unsigned long mtimecmp_addr;
> > +       unsigned long mtimecmp_size;
> >         u32 first_hartid;
> >         u32 hart_count;
> >         bool has_64bit_mmio;
>
> [snip]
>
> Regards,
> Bin


From anup at brainfault.org  Sat Aug  7 05:47:33 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 18:17:33 +0530
Subject: [PATCH 2/5] lib: utils: Extend fdt_get_node_addr_size() for
 multiple register sets
In-Reply-To: <CAOnJCUL-g2HDPSzbvL3an6iwUK4mp944JOhUY7EWH1JqXyXKNg@mail.gmail.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-3-anup.patel@wdc.com>
 <CAOnJCUL-g2HDPSzbvL3an6iwUK4mp944JOhUY7EWH1JqXyXKNg@mail.gmail.com>
Message-ID: <CAAhSdy3Zrfrq7jJJzbXMV-=vVkLTzwg3=-jTjJP7bJS=2=7a5w@mail.gmail.com>

On Tue, Aug 3, 2021 at 1:10 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We add "set" parameter to fdt_get_node_addr_size() API so that
> > calling function can specify index of desired register set. This
> > will allow fdt_get_node_addr_size() to handle DT nodes with
> > multiple register sets.
> >
>
> IMHO, index would be a better name for the parameter.

Okay, I will use index as parameter name.

Regards,
Anup

>
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  include/sbi_utils/fdt/fdt_helper.h      |  3 ++-
> >  lib/utils/fdt/fdt_helper.c              | 31 ++++++++++++++++++-------
> >  lib/utils/gpio/fdt_gpio_sifive.c        |  2 +-
> >  lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
> >  4 files changed, 27 insertions(+), 11 deletions(-)
> >
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 55b9382..0445e36 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -43,7 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
> >                                 const char *prop, const char *cells_prop,
> >                                 int index, struct fdt_phandle_args *out_args);
> >
> > -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> > +int fdt_get_node_addr_size(void *fdt, int node, int set,
> > +                          unsigned long *addr,
> >                            unsigned long *size);
> >
> >  int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
> > diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> > index a970c0f..a992911 100644
> > --- a/lib/utils/fdt/fdt_helper.c
> > +++ b/lib/utils/fdt/fdt_helper.c
> > @@ -157,7 +157,8 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
> >         return 0;
> >  }
> >
> > -int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> > +int fdt_get_node_addr_size(void *fdt, int node, int set,
> > +                          unsigned long *addr,
> >                            unsigned long *size)
> >  {
> >         int parent, len, i, rc;
> > @@ -165,6 +166,9 @@ int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> >         const fdt32_t *prop_addr, *prop_size;
> >         uint64_t temp = 0;
> >
> > +       if (!fdt || node < 0 || set < 0)
> > +               return SBI_EINVAL;
> > +
> >         parent = fdt_parent_offset(fdt, node);
> >         if (parent < 0)
> >                 return parent;
> > @@ -179,6 +183,11 @@ int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
> >         prop_addr = fdt_getprop(fdt, node, "reg", &len);
> >         if (!prop_addr)
> >                 return SBI_ENODEV;
> > +
> > +       if ((len / sizeof(u32)) <= (set * (cell_addr + cell_size)))
> > +               return SBI_EINVAL;
> > +
> > +       prop_addr = prop_addr + (set * (cell_addr + cell_size));
> >         prop_size = prop_addr + cell_addr;
> >
> >         if (addr) {
> > @@ -271,7 +280,8 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
> >         if (nodeoffset < 0 || !uart || !fdt)
> >                 return SBI_ENODEV;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         uart->addr = reg_addr;
> > @@ -309,7 +319,8 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
> >         if (nodeoffset < 0 || !uart || !fdt)
> >                 return SBI_ENODEV;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         uart->addr = reg_addr;
> > @@ -343,7 +354,8 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
> >         if (nodeoffset < 0 || !uart || !fdt)
> >                 return SBI_ENODEV;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         uart->addr = reg_addr;
> > @@ -381,7 +393,8 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> >         if (nodeoffset < 0 || !uart || !fdt)
> >                 return SBI_ENODEV;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         uart->addr = reg_addr;
> > @@ -441,7 +454,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
> >         if (nodeoffset < 0 || !plic || !fdt)
> >                 return SBI_ENODEV;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         plic->addr = reg_addr;
> > @@ -482,7 +496,8 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
> >             !out_first_hartid || !out_hart_count)
> >                 return SBI_EINVAL;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> > +                                   &reg_addr, &reg_size);
> >         if (rc < 0 || !reg_addr || !reg_size)
> >                 return SBI_ENODEV;
> >         *out_addr = reg_addr;
> > @@ -544,7 +559,7 @@ int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
> >         if (nodeoffset < 0)
> >                 return nodeoffset;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoffset, addr, NULL);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, addr, NULL);
> >         if (rc < 0 || !addr)
> >                 return SBI_ENODEV;
> >
> > diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
> > index abc9d72..bbddd58 100644
> > --- a/lib/utils/gpio/fdt_gpio_sifive.c
> > +++ b/lib/utils/gpio/fdt_gpio_sifive.c
> > @@ -76,7 +76,7 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
> >                 return SBI_ENOSPC;
> >         chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoff, &chip->addr, NULL);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &chip->addr, NULL);
> >         if (rc)
> >                 return rc;
> >
> > diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
> > index f98f03d..b0b7dbb 100644
> > --- a/lib/utils/reset/fdt_reset_sifive_test.c
> > +++ b/lib/utils/reset/fdt_reset_sifive_test.c
> > @@ -18,7 +18,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
> >         int rc;
> >         unsigned long addr;
> >
> > -       rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
> > +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
> >         if (rc)
> >                 return rc;
> >
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
> Other than that, looks good.
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>
>
> --
> Regards,
> Atish


From anup at brainfault.org  Sat Aug  7 06:17:33 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 18:47:33 +0530
Subject: [PATCH 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting only
 32-bit MMIO
In-Reply-To: <CAOnJCUJovbgfLGuCQtYbRBDWsM0o8SXqjFkb3gCbsSzW7SSQzg@mail.gmail.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-5-anup.patel@wdc.com>
 <CAOnJCUJovbgfLGuCQtYbRBDWsM0o8SXqjFkb3gCbsSzW7SSQzg@mail.gmail.com>
Message-ID: <CAAhSdy2nzPuNXFvJPMUn_=wpp83SeUpZps8_AWCcHBEBqz2XTw@mail.gmail.com>

On Tue, Aug 3, 2021 at 1:19 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Jul 24, 2021 at 5:25 AM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We can have ACLINT MTIMER devices which only support 32-bit MMIO
> > accesses on RV64 system so this patch adds a boolean DT property
> > "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.
> >
>
> Where is this property documented ? I couldn't find it in your v3
> aclint patch [1].
> Did I miss something?

I have updated DT bindings in linux v3 series. Please check again.

>
> I also think "mtimer,32bit-mmio" may be a better choice than
> "mtimer,no-64bit-mmio"
>
> [1]https://github.com/avpatel/linux/commits/riscv_aclint_v3

Actually, "mtimer,no-64bit-mmio" is more appropriate because
all registers of MTIMER are 64-bits wide so by default RV64
systems should support 64-bit MMIO for MTIMER. In fact, most
existing RV64 systems do support 64-bit MMIO for MTIMER.

Regards,
Anup

> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  lib/utils/timer/fdt_timer_mtimer.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > index b08ed38..15a36ed 100644
> > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >                 mt->mtime_size = size[0];
> >                 mt->mtimecmp_addr = addr[1];
> >                 mt->mtimecmp_size = size[1];
> > +               /* Parse additional ACLINT MTIMER properties */
> > +               if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> > +                       mt->has_64bit_mmio = false;
> >         }
> >
> >         rc = aclint_mtimer_cold_init(mt, mtmaster);
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
>
> --
> Regards,
> Atish


From anup.patel at wdc.com  Sat Aug  7 06:33:17 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:17 +0530
Subject: [PATCH v2 0/5] ACLINT MTIMER improvements
Message-ID: <20210807133322.545675-1-anup.patel@wdc.com>

To support more flexibility in ACLINT MTIMER implementation, the ACLINT
specification now allows separate base address of MTIME and MTIMECMP
registers so that multiple MTIMER devices can share the same physical
MTIME register.

This series extends ACLINT support in OpenSBI to incorporate above changes
in ACLINT MTIMER definition. It can be found in the riscv_aclint_imp_v2
branch at:
https://github.com/avpatel/opensbi.git

Changes since v1:
 - Simplified defines in PATCH1
 - Renamed parameter of fdt_get_node_addr_size() in PATCH2
 - Rebased patch series on latest OpenSBI master

Anup Patel (5):
  lib: utils/timer: Allow separate base addresses for MTIME and MTIMECMP
  lib: utils: Extend fdt_get_node_addr_size() for multiple register sets
  lib: utils/fdt: Extend fdt_parse_aclint_node() function
  lib: utils/timer: Allow ACLINT MTIMER supporting only 32-bit MMIO
  lib: utils/timer: Simplify MTIMER synchronization

 include/sbi_utils/fdt/fdt_helper.h      |   7 +-
 include/sbi_utils/timer/aclint_mtimer.h |  23 +++-
 lib/utils/fdt/fdt_helper.c              |  81 +++++++++-----
 lib/utils/gpio/fdt_gpio_sifive.c        |   2 +-
 lib/utils/ipi/fdt_ipi_mswi.c            |   3 +-
 lib/utils/reset/fdt_reset_sifive_test.c |   2 +-
 lib/utils/timer/aclint_mtimer.c         | 141 ++++++++++++++++--------
 lib/utils/timer/fdt_timer_mtimer.c      |  67 +++++++++--
 platform/fpga/ariane/platform.c         |   8 +-
 platform/fpga/openpiton/platform.c      |  13 ++-
 platform/kendryte/k210/platform.c       |   8 +-
 platform/nuclei/ux600/platform.c        |   8 +-
 platform/template/platform.c            |   8 +-
 13 files changed, 264 insertions(+), 107 deletions(-)

-- 
2.25.1



From anup.patel at wdc.com  Sat Aug  7 06:33:22 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:22 +0530
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <20210807133322.545675-1-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
Message-ID: <20210807133322.545675-6-anup.patel@wdc.com>

We simplify MTIMER synchronization as follows:

1) Detect MTIMER devices with unique (or non-shared) MTIME
   register at boot-time
2) Select first MTIMER device with no associated HART as our
   reference MTIMER device
3) Only synchronize MTIMER devices with unique (or non-shared)
   MTIME register using reference MTIMER device
4) Directly update the MTIME register at time of synchronization
   because MTIME is a read/write register.

Signed-off-by: Anup Patel <anup.patel at wdc.com>
---
 include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
 lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
 lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
 3 files changed, 80 insertions(+), 33 deletions(-)

diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
index fdc46cd..a9fe445 100644
--- a/include/sbi_utils/timer/aclint_mtimer.h
+++ b/include/sbi_utils/timer/aclint_mtimer.h
@@ -31,14 +31,19 @@ struct aclint_mtimer_data {
 	u32 first_hartid;
 	u32 hart_count;
 	bool has_64bit_mmio;
+	bool has_shared_mtime;
 	/* Private details (initialized and used by ACLINT MTIMER library) */
 	struct aclint_mtimer_data *time_delta_reference;
 	unsigned long time_delta_computed;
-	u64 time_delta;
 	u64 (*time_rd)(volatile u64 *addr);
 	void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
 };
 
+void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
+
+void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
+				 struct aclint_mtimer_data *ref);
+
 int aclint_mtimer_warm_init(void);
 
 int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
index 0e4e846..d612b12 100644
--- a/lib/utils/timer/aclint_mtimer.c
+++ b/lib/utils/timer/aclint_mtimer.c
@@ -57,7 +57,7 @@ static u64 mtimer_value(void)
 	u64 *time_val = (void *)mt->mtime_addr;
 
 	/* Read MTIMER Time Value */
-	return mt->time_rd(time_val) + mt->time_delta;
+	return mt->time_rd(time_val);
 }
 
 static void mtimer_event_stop(void)
@@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
 	u64 *time_cmp = (void *)mt->mtimecmp_addr;
 
 	/* Program MTIMER Time Compare */
-	mt->time_wr(true, next_event - mt->time_delta,
+	mt->time_wr(true, next_event,
 		    &time_cmp[target_hart - mt->first_hartid]);
 }
 
@@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
 	.timer_event_stop = mtimer_event_stop
 };
 
+void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
+{
+	u64 v1, v2, mv, delta;
+	u64 *mt_time_val, *ref_time_val;
+	struct aclint_mtimer_data *reference;
+
+	/* Sync-up non-shared MTIME if reference is available */
+	if (mt->has_shared_mtime || !mt->time_delta_reference)
+		return;
+
+	reference = mt->time_delta_reference;
+	mt_time_val = (void *)mt->mtime_addr;
+	ref_time_val = (void *)reference->mtime_addr;
+	if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
+		v1 = mt->time_rd(mt_time_val);
+		mv = reference->time_rd(ref_time_val);
+		v2 = mt->time_rd(mt_time_val);
+		delta = mv - ((v1 / 2) + (v2 / 2));
+		mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
+			    mt_time_val);
+	}
+
+}
+
+void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
+				 struct aclint_mtimer_data *ref)
+{
+	if (!mt || !ref || mt == ref)
+		return;
+
+	mt->time_delta_reference = ref;
+	mt->time_delta_computed = 0;
+}
+
 int aclint_mtimer_warm_init(void)
 {
-	u64 v1, v2, mv;
+	u64 *mt_time_cmp;
 	u32 target_hart = current_hartid();
-	struct aclint_mtimer_data *reference;
-	u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
 	struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
 
 	if (!mt)
 		return SBI_ENODEV;
 
-	/*
-	 * Compute delta if reference available
-	 *
-	 * We deliberately compute time_delta in warm init so that time_delta
-	 * is computed on a HART which is going to use given MTIMER. We use
-	 * atomic flag timer_delta_computed to ensure that only one HART does
-	 * time_delta computation.
-	 */
-	if (mt->time_delta_reference) {
-		reference = mt->time_delta_reference;
-		mt_time_val = (void *)mt->mtime_addr;
-		ref_time_val = (void *)reference->mtime_addr;
-		if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
-			v1 = mt->time_rd(mt_time_val);
-			mv = reference->time_rd(ref_time_val);
-			v2 = mt->time_rd(mt_time_val);
-			mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
-		}
-	}
+	/* Sync-up MTIME register */
+	aclint_mtimer_sync(mt);
 
 	/* Clear Time Compare */
 	mt_time_cmp = (void *)mt->mtimecmp_addr;
@@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 		return SBI_EINVAL;
 
 	/* Initialize private data */
-	mt->time_delta_reference = reference;
-	mt->time_delta_computed = 0;
-	mt->time_delta = 0;
+	aclint_mtimer_set_reference(mt, reference);
 	mt->time_rd = mtimer_time_rd32;
 	mt->time_wr = mtimer_time_wr32;
 
diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
index 15a36ed..26b5a2a 100644
--- a/lib/utils/timer/fdt_timer_mtimer.c
+++ b/lib/utils/timer/fdt_timer_mtimer.c
@@ -17,19 +17,18 @@
 
 static unsigned long mtimer_count = 0;
 static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
+static struct aclint_mtimer_data *mt_reference = NULL;
 
 static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 				  const struct fdt_match *match)
 {
-	int rc;
+	int i, rc;
 	unsigned long offset, addr[2], size[2];
-	struct aclint_mtimer_data *mt, *mtmaster = NULL;
+	struct aclint_mtimer_data *mt;
 
 	if (MTIMER_MAX_NR <= mtimer_count)
 		return SBI_ENOSPC;
 	mt = &mtimer[mtimer_count];
-	if (0 < mtimer_count)
-		mtmaster = &mtimer[0];
 
 	rc = fdt_parse_aclint_node(fdt, nodeoff, true,
 				   &addr[0], &size[0], &addr[1], &size[1],
@@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 	if (rc)
 		return rc;
 	mt->has_64bit_mmio = true;
+	mt->has_shared_mtime = false;
 
 	if (match->data) { /* SiFive CLINT */
 		/* Set CLINT addresses */
@@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 			mt->has_64bit_mmio = false;
 	}
 
-	rc = aclint_mtimer_cold_init(mt, mtmaster);
+	/* Check if MTIMER device has shared MTIME address */
+	mt->has_shared_mtime = false;
+	for (i = 0; i < mtimer_count; i++) {
+		if (mtimer[i].mtime_addr == mt->mtime_addr) {
+			mt->has_shared_mtime = true;
+			break;
+		}
+	}
+
+	/* Initialize the MTIMER device */
+	rc = aclint_mtimer_cold_init(mt, mt_reference);
 	if (rc)
 		return rc;
 
+	/*
+	 * Select first MTIMER device with no associated HARTs as
+	 * our reference MTIMER device
+	 */
+	if (!mt->hart_count && !mt_reference) {
+		mt_reference = mt;
+		/*
+		 * Set reference for already propbed MTIMER devices
+		 * with non-shared MTIME
+		 */
+		for (i = 0; i < mtimer_count; i++)
+			if (!mtimer[i].has_shared_mtime)
+				aclint_mtimer_set_reference(&mtimer[i], mt);
+	}
+
+	/* Explicitly sync-up MTIMER devices not associated with any HARTs */
+	if (!mt->hart_count)
+		aclint_mtimer_sync(mt);
+
 	mtimer_count++;
 	return 0;
 }
-- 
2.25.1



From anup.patel at wdc.com  Sat Aug  7 06:33:18 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:18 +0530
Subject: [PATCH v2 1/5] lib: utils/timer: Allow separate base addresses for
 MTIME and MTIMECMP
In-Reply-To: <20210807133322.545675-1-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
Message-ID: <20210807133322.545675-2-anup.patel@wdc.com>

We extend the ACLINT library to support separate base addresses
for MTIME and MTIMECMP registers.

Signed-off-by: Anup Patel <anup.patel at wdc.com>
Reviewed-by: Atish Patra <atish.patra at wdc.com>
---
 include/sbi_utils/timer/aclint_mtimer.h | 16 +++--
 lib/utils/timer/aclint_mtimer.c         | 78 +++++++++++++++++++------
 lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
 platform/fpga/ariane/platform.c         |  8 ++-
 platform/fpga/openpiton/platform.c      | 13 ++++-
 platform/kendryte/k210/platform.c       |  8 ++-
 platform/nuclei/ux600/platform.c        |  8 ++-
 platform/template/platform.c            |  8 ++-
 8 files changed, 114 insertions(+), 41 deletions(-)

diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
index 62aa086..fdc46cd 100644
--- a/include/sbi_utils/timer/aclint_mtimer.h
+++ b/include/sbi_utils/timer/aclint_mtimer.h
@@ -12,16 +12,22 @@
 
 #include <sbi/sbi_types.h>
 
-#define ACLINT_MTIMER_ALIGN		0x1000
-#define ACLINT_MTIMER_SIZE		0x8000
-#define ACLINT_MTIMER_MAX_HARTS	4095
+#define ACLINT_MTIMER_ALIGN		0x8
+#define ACLINT_MTIMER_MAX_HARTS		4095
+
+#define ACLINT_DEFAULT_MTIME_OFFSET	0x7ff8
+#define ACLINT_DEFAULT_MTIME_SIZE	0x8
+#define ACLINT_DEFAULT_MTIMECMP_OFFSET	0x0000
+#define ACLINT_DEFAULT_MTIMECMP_SIZE	0x7ff8
 
 #define CLINT_MTIMER_OFFSET		0x4000
 
 struct aclint_mtimer_data {
 	/* Public details */
-	unsigned long addr;
-	unsigned long size;
+	unsigned long mtime_addr;
+	unsigned long mtime_size;
+	unsigned long mtimecmp_addr;
+	unsigned long mtimecmp_size;
 	u32 first_hartid;
 	u32 hart_count;
 	bool has_64bit_mmio;
diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
index 41b0290..0e4e846 100644
--- a/lib/utils/timer/aclint_mtimer.c
+++ b/lib/utils/timer/aclint_mtimer.c
@@ -10,6 +10,7 @@
 #include <sbi/riscv_asm.h>
 #include <sbi/riscv_atomic.h>
 #include <sbi/riscv_io.h>
+#include <sbi/sbi_bitops.h>
 #include <sbi/sbi_domain.h>
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_hartmask.h>
@@ -17,9 +18,6 @@
 #include <sbi/sbi_timer.h>
 #include <sbi_utils/timer/aclint_mtimer.h>
 
-#define MTIMER_CMP_OFF		0x0000
-#define MTIMER_VAL_OFF		0x7ff8
-
 static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS];
 
 #if __riscv_xlen != 32
@@ -56,7 +54,7 @@ static void mtimer_time_wr32(bool timecmp, u64 value, volatile u64 *addr)
 static u64 mtimer_value(void)
 {
 	struct aclint_mtimer_data *mt = mtimer_hartid2data[current_hartid()];
-	u64 *time_val = ((void *)mt->addr) + MTIMER_VAL_OFF;
+	u64 *time_val = (void *)mt->mtime_addr;
 
 	/* Read MTIMER Time Value */
 	return mt->time_rd(time_val) + mt->time_delta;
@@ -66,7 +64,7 @@ static void mtimer_event_stop(void)
 {
 	u32 target_hart = current_hartid();
 	struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
-	u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
+	u64 *time_cmp = (void *)mt->mtimecmp_addr;
 
 	/* Clear MTIMER Time Compare */
 	mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]);
@@ -76,7 +74,7 @@ static void mtimer_event_start(u64 next_event)
 {
 	u32 target_hart = current_hartid();
 	struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
-	u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
+	u64 *time_cmp = (void *)mt->mtimecmp_addr;
 
 	/* Program MTIMER Time Compare */
 	mt->time_wr(true, next_event - mt->time_delta,
@@ -111,8 +109,8 @@ int aclint_mtimer_warm_init(void)
 	 */
 	if (mt->time_delta_reference) {
 		reference = mt->time_delta_reference;
-		mt_time_val = (void *)mt->addr + MTIMER_VAL_OFF;
-		ref_time_val = (void *)reference->addr + MTIMER_VAL_OFF;
+		mt_time_val = (void *)mt->mtime_addr;
+		ref_time_val = (void *)reference->mtime_addr;
 		if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
 			v1 = mt->time_rd(mt_time_val);
 			mv = reference->time_rd(ref_time_val);
@@ -122,24 +120,54 @@ int aclint_mtimer_warm_init(void)
 	}
 
 	/* Clear Time Compare */
-	mt_time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
+	mt_time_cmp = (void *)mt->mtimecmp_addr;
 	mt->time_wr(true, -1ULL,
 		    &mt_time_cmp[target_hart - mt->first_hartid]);
 
 	return 0;
 }
 
+static int aclint_mtimer_add_regions(unsigned long addr, unsigned long size)
+{
+#define MTIMER_ADD_REGION_ALIGN		0x1000
+	int rc;
+	unsigned long pos, end, rsize;
+	struct sbi_domain_memregion reg;
+
+	pos = addr;
+	end = addr + size;
+	while (pos < end) {
+		rsize = pos & (MTIMER_ADD_REGION_ALIGN - 1);
+		if (rsize)
+			rsize = 1UL << __ffs(pos);
+		else
+			rsize = ((end - pos) < MTIMER_ADD_REGION_ALIGN) ?
+				(end - pos) : MTIMER_ADD_REGION_ALIGN;
+
+		sbi_domain_memregion_init(pos, rsize,
+					  SBI_DOMAIN_MEMREGION_MMIO, &reg);
+		rc = sbi_domain_root_add_memregion(&reg);
+		if (rc)
+			return rc;
+		pos += rsize;
+	}
+
+	return 0;
+}
+
 int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 			    struct aclint_mtimer_data *reference)
 {
 	u32 i;
 	int rc;
-	unsigned long pos, region_size;
-	struct sbi_domain_memregion reg;
 
 	/* Sanity checks */
-	if (!mt || (mt->addr & (ACLINT_MTIMER_ALIGN - 1)) ||
-	    (mt->size < ACLINT_MTIMER_SIZE) ||
+	if (!mt || !mt->mtime_size ||
+	    (mt->hart_count && !mt->mtimecmp_size) ||
+	    (mt->mtime_addr & (ACLINT_MTIMER_ALIGN - 1)) ||
+	    (mt->mtime_size & (ACLINT_MTIMER_ALIGN - 1)) ||
+	    (mt->mtimecmp_addr & (ACLINT_MTIMER_ALIGN - 1)) ||
+	    (mt->mtimecmp_size & (ACLINT_MTIMER_ALIGN - 1)) ||
 	    (mt->first_hartid >= SBI_HARTMASK_MAX_BITS) ||
 	    (mt->hart_count > ACLINT_MTIMER_MAX_HARTS))
 		return SBI_EINVAL;
@@ -164,12 +192,24 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 		mtimer_hartid2data[mt->first_hartid + i] = mt;
 
 	/* Add MTIMER regions to the root domain */
-	for (pos = 0; pos < mt->size; pos += ACLINT_MTIMER_ALIGN) {
-		region_size = ((mt->size - pos) < ACLINT_MTIMER_ALIGN) ?
-			      (mt->size - pos) : ACLINT_MTIMER_ALIGN;
-		sbi_domain_memregion_init(mt->addr + pos, region_size,
-					  SBI_DOMAIN_MEMREGION_MMIO, &reg);
-		rc = sbi_domain_root_add_memregion(&reg);
+	if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) {
+		rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
+					mt->mtime_size + mt->mtimecmp_size);
+		if (rc)
+			return rc;
+	} else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) {
+		rc = aclint_mtimer_add_regions(mt->mtime_addr,
+					mt->mtime_size + mt->mtimecmp_size);
+		if (rc)
+			return rc;
+	} else {
+		rc = aclint_mtimer_add_regions(mt->mtime_addr,
+						mt->mtime_size);
+		if (rc)
+			return rc;
+
+		rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
+						mt->mtimecmp_size);
 		if (rc)
 			return rc;
 	}
diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
index 4907428..3f830ad 100644
--- a/lib/utils/timer/fdt_timer_mtimer.c
+++ b/lib/utils/timer/fdt_timer_mtimer.c
@@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 				  const struct fdt_match *match)
 {
 	int rc;
-	unsigned long offset;
+	unsigned long offset, addr, size;
 	struct aclint_mtimer_data *mt, *mtmaster = NULL;
 
 	if (MTIMER_MAX_NR <= mtimer_count)
@@ -31,19 +31,23 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 	if (0 < mtimer_count)
 		mtmaster = &mtimer[0];
 
-	rc = fdt_parse_aclint_node(fdt, nodeoff, true, &mt->addr, &mt->size,
+	rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
 				   &mt->first_hartid, &mt->hart_count);
 	if (rc)
 		return rc;
 	mt->has_64bit_mmio = true;
 
+	mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
+	mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
+	mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
+	mt->mtime_size = size - mt->mtimecmp_size;
+
 	if (match->data) {
 		/* Adjust MTIMER address and size for CLINT device */
 		offset = *((unsigned long *)match->data);
-		mt->addr += offset;
-		if ((mt->size - offset) < ACLINT_MTIMER_SIZE)
-			return SBI_EINVAL;
-		mt->size -= offset;
+		mt->mtime_addr += offset;
+		mt->mtimecmp_addr += offset;
+		mt->mtime_size -= offset;
 		/* Parse additional CLINT properties */
 		if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
 			mt->has_64bit_mmio = false;
diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
index 0b47aa0..58a46c0 100644
--- a/platform/fpga/ariane/platform.c
+++ b/platform/fpga/ariane/platform.c
@@ -44,8 +44,12 @@ static struct aclint_mswi_data mswi = {
 };
 
 static struct aclint_mtimer_data mtimer = {
-	.addr = ARIANE_ACLINT_MTIMER_ADDR,
-	.size = ACLINT_MTIMER_SIZE,
+	.mtime_addr = ARIANE_ACLINT_MTIMER_ADDR +
+		      ACLINT_DEFAULT_MTIME_OFFSET,
+	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
+	.mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
+			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
+	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
 	.first_hartid = 0,
 	.hart_count = ARIANE_HART_COUNT,
 	.has_64bit_mmio = TRUE,
diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
index 6939b57..a9bfa99 100644
--- a/platform/fpga/openpiton/platform.c
+++ b/platform/fpga/openpiton/platform.c
@@ -49,8 +49,12 @@ static struct aclint_mswi_data mswi = {
 };
 
 static struct aclint_mtimer_data mtimer = {
-	.addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR,
-	.size = ACLINT_MTIMER_SIZE,
+	.mtime_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
+		      ACLINT_DEFAULT_MTIME_OFFSET,
+	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
+	.mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
+			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
+	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
 	.first_hartid = 0,
 	.hart_count = OPENPITON_DEFAULT_HART_COUNT,
 	.has_64bit_mmio = TRUE,
@@ -82,7 +86,10 @@ static int openpiton_early_init(bool cold_boot)
 	rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0");
 	if (!rc) {
 		mswi.addr = clint_addr;
-		mtimer.addr = clint_addr + CLINT_MTIMER_OFFSET;
+		mtimer.mtime_addr = clint_addr + CLINT_MTIMER_OFFSET +
+				    ACLINT_DEFAULT_MTIME_OFFSET;
+		mtimer.mtimecmp_addr = clint_addr + CLINT_MTIMER_OFFSET +
+				    ACLINT_DEFAULT_MTIMECMP_OFFSET;
 	}
 
 	return 0;
diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
index 55c4b1e..ee4c223 100644
--- a/platform/kendryte/k210/platform.c
+++ b/platform/kendryte/k210/platform.c
@@ -42,8 +42,12 @@ static struct aclint_mswi_data mswi = {
 };
 
 static struct aclint_mtimer_data mtimer = {
-	.addr = K210_ACLINT_MTIMER_ADDR,
-	.size = ACLINT_MTIMER_SIZE,
+	.mtime_addr = K210_ACLINT_MTIMER_ADDR +
+		      ACLINT_DEFAULT_MTIME_OFFSET,
+	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
+	.mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
+			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
+	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
 	.first_hartid = 0,
 	.hart_count = K210_HART_COUNT,
 	.has_64bit_mmio = TRUE,
diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
index 22ca4c9..ab0becc 100644
--- a/platform/nuclei/ux600/platform.c
+++ b/platform/nuclei/ux600/platform.c
@@ -74,8 +74,12 @@ static struct aclint_mswi_data mswi = {
 };
 
 static struct aclint_mtimer_data mtimer = {
-	.addr = UX600_ACLINT_MTIMER_ADDR,
-	.size = ACLINT_MTIMER_SIZE,
+	.mtime_addr = UX600_ACLINT_MTIMER_ADDR +
+		      ACLINT_DEFAULT_MTIME_OFFSET,
+	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
+	.mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
+			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
+	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
 	.first_hartid = 0,
 	.hart_count = UX600_HART_COUNT,
 	.has_64bit_mmio = TRUE,
diff --git a/platform/template/platform.c b/platform/template/platform.c
index 3f09d98..4528822 100644
--- a/platform/template/platform.c
+++ b/platform/template/platform.c
@@ -43,8 +43,12 @@ static struct aclint_mswi_data mswi = {
 };
 
 static struct aclint_mtimer_data mtimer = {
-	.addr = PLATFORM_ACLINT_MTIMER_ADDR,
-	.size = ACLINT_MTIMER_SIZE,
+	.mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR +
+		      ACLINT_DEFAULT_MTIME_OFFSET,
+	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
+	.mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
+			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
+	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
 	.first_hartid = 0,
 	.hart_count = PLATFORM_HART_COUNT,
 	.has_64bit_mmio = TRUE,
-- 
2.25.1



From anup.patel at wdc.com  Sat Aug  7 06:33:21 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:21 +0530
Subject: [PATCH v2 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting only
 32-bit MMIO
In-Reply-To: <20210807133322.545675-1-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
Message-ID: <20210807133322.545675-5-anup.patel@wdc.com>

We can have ACLINT MTIMER devices which only support 32-bit MMIO
accesses on RV64 system so this patch adds a boolean DT property
"mtimer,no-64bit-mmio" to detect this from MTIMER DT node.

Signed-off-by: Anup Patel <anup.patel at wdc.com>
---
 lib/utils/timer/fdt_timer_mtimer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
index b08ed38..15a36ed 100644
--- a/lib/utils/timer/fdt_timer_mtimer.c
+++ b/lib/utils/timer/fdt_timer_mtimer.c
@@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 		mt->mtime_size = size[0];
 		mt->mtimecmp_addr = addr[1];
 		mt->mtimecmp_size = size[1];
+		/* Parse additional ACLINT MTIMER properties */
+		if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
+			mt->has_64bit_mmio = false;
 	}
 
 	rc = aclint_mtimer_cold_init(mt, mtmaster);
-- 
2.25.1



From anup.patel at wdc.com  Sat Aug  7 06:33:19 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:19 +0530
Subject: [PATCH v2 2/5] lib: utils: Extend fdt_get_node_addr_size() for
 multiple register sets
In-Reply-To: <20210807133322.545675-1-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
Message-ID: <20210807133322.545675-3-anup.patel@wdc.com>

We add "index" parameter to fdt_get_node_addr_size() API so that
calling function can specify index of desired register set. This
will allow fdt_get_node_addr_size() to handle DT nodes with
multiple register sets.

Signed-off-by: Anup Patel <anup.patel at wdc.com>
Reviewed-by: Atish Patra <atish.patra at wdc.com>
---
 include/sbi_utils/fdt/fdt_helper.h      |  4 ++--
 lib/utils/fdt/fdt_helper.c              | 31 ++++++++++++++++++-------
 lib/utils/gpio/fdt_gpio_sifive.c        |  2 +-
 lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
 4 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 32aebb4..1a93e1c 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -43,8 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
 				const char *prop, const char *cells_prop,
 				int index, struct fdt_phandle_args *out_args);
 
-int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr,
-			   uint64_t *size);
+int fdt_get_node_addr_size(void *fdt, int node, int index,
+			   uint64_t *addr, uint64_t *size);
 
 int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
 
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index a27f5ba..b68544f 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -157,13 +157,17 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
 	return 0;
 }
 
-int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
+int fdt_get_node_addr_size(void *fdt, int node, int index,
+			   uint64_t *addr, uint64_t *size)
 {
 	int parent, len, i, rc;
 	int cell_addr, cell_size;
 	const fdt32_t *prop_addr, *prop_size;
 	uint64_t temp = 0;
 
+	if (!fdt || node < 0 || index < 0)
+		return SBI_EINVAL;
+
 	parent = fdt_parent_offset(fdt, node);
 	if (parent < 0)
 		return parent;
@@ -178,6 +182,11 @@ int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
 	prop_addr = fdt_getprop(fdt, node, "reg", &len);
 	if (!prop_addr)
 		return SBI_ENODEV;
+
+	if ((len / sizeof(u32)) <= (index * (cell_addr + cell_size)))
+		return SBI_EINVAL;
+
+	prop_addr = prop_addr + (index * (cell_addr + cell_size));
 	prop_size = prop_addr + cell_addr;
 
 	if (addr) {
@@ -270,7 +279,8 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	uart->addr = reg_addr;
@@ -308,7 +318,8 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	uart->addr = reg_addr;
@@ -342,7 +353,8 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	uart->addr = reg_addr;
@@ -380,7 +392,8 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
 	if (nodeoffset < 0 || !uart || !fdt)
 		return SBI_ENODEV;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	uart->addr = reg_addr;
@@ -440,7 +453,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
 	if (nodeoffset < 0 || !plic || !fdt)
 		return SBI_ENODEV;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	plic->addr = reg_addr;
@@ -481,7 +495,8 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
 	    !out_first_hartid || !out_hart_count)
 		return SBI_EINVAL;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
+				    &reg_addr, &reg_size);
 	if (rc < 0 || !reg_addr || !reg_size)
 		return SBI_ENODEV;
 	*out_addr = reg_addr;
@@ -543,7 +558,7 @@ int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
 	if (nodeoffset < 0)
 		return nodeoffset;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoffset, addr, NULL);
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, addr, NULL);
 	if (rc < 0 || !addr)
 		return SBI_ENODEV;
 
diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
index 00d3e14..677f0fa 100644
--- a/lib/utils/gpio/fdt_gpio_sifive.c
+++ b/lib/utils/gpio/fdt_gpio_sifive.c
@@ -77,7 +77,7 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
 		return SBI_ENOSPC;
 	chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
 
-	rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
+	rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
 	if (rc)
 		return rc;
 
diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
index b0b59e7..7e0eba3 100644
--- a/lib/utils/reset/fdt_reset_sifive_test.c
+++ b/lib/utils/reset/fdt_reset_sifive_test.c
@@ -18,7 +18,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
 	int rc;
 	uint64_t addr;
 
-	rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
+	rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
 	if (rc)
 		return rc;
 
-- 
2.25.1



From anup.patel at wdc.com  Sat Aug  7 06:33:20 2021
From: anup.patel at wdc.com (Anup Patel)
Date: Sat,  7 Aug 2021 19:03:20 +0530
Subject: [PATCH v2 3/5] lib: utils/fdt: Extend fdt_parse_aclint_node() function
In-Reply-To: <20210807133322.545675-1-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
Message-ID: <20210807133322.545675-4-anup.patel@wdc.com>

The fdt_parse_aclint_node() is used to parse DT node for SiFive
CLINT, ACLINT MTIMER, and ACLINT MSWI devices.

The ACLINT MTIMER has undergone following changes:
1) MTIMER DT node now requires separate addresses in for MTIME
   register and MTIMECMPx registers in the reg DT property.
2) MTIMER DT node might have no interrupts-extended DT property
   when the MTIMER device has no associated HARTs (i.e. the
   MTIMER device has no MTIMECMPx registers)

This patch extends fdt_parse_aclint_node() to handle above
mentioned changes in ACLINT MTIMER DT bindings.

Signed-off-by: Anup Patel <anup.patel at wdc.com>
Reviewed-by: Atish Patra <atish.patra at wdc.com>
---
 include/sbi_utils/fdt/fdt_helper.h |  3 +-
 lib/utils/fdt/fdt_helper.c         | 50 ++++++++++++++++++------------
 lib/utils/ipi/fdt_ipi_mswi.c       |  3 +-
 lib/utils/timer/fdt_timer_mtimer.c | 23 +++++++++-----
 4 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 1a93e1c..2246254 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -72,7 +72,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
 int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
 
 int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
-			  unsigned long *out_addr, unsigned long *out_size,
+			  unsigned long *out_addr1, unsigned long *out_size1,
+			  unsigned long *out_addr2, unsigned long *out_size2,
 			  u32 *out_first_hartid, u32 *out_hart_count);
 
 int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index b68544f..5628337 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -481,38 +481,50 @@ int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat)
 }
 
 int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
-			  unsigned long *out_addr, unsigned long *out_size,
+			  unsigned long *out_addr1, unsigned long *out_size1,
+			  unsigned long *out_addr2, unsigned long *out_size2,
 			  u32 *out_first_hartid, u32 *out_hart_count)
 {
 	const fdt32_t *val;
 	uint64_t reg_addr, reg_size;
 	int i, rc, count, cpu_offset, cpu_intc_offset;
-	u32 phandle, hwirq, hartid, first_hartid, last_hartid;
+	u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
 	u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
 
 	if (nodeoffset < 0 || !fdt ||
-	    !out_addr || !out_size ||
+	    !out_addr1 || !out_size1 ||
 	    !out_first_hartid || !out_hart_count)
 		return SBI_EINVAL;
 
 	rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
 				    &reg_addr, &reg_size);
-	if (rc < 0 || !reg_addr || !reg_size)
+	if (rc < 0 || !reg_size)
 		return SBI_ENODEV;
-	*out_addr = reg_addr;
-	*out_size = reg_size;
+	*out_addr1 = reg_addr;
+	*out_size1 = reg_size;
+
+	rc = fdt_get_node_addr_size(fdt, nodeoffset, 1,
+				    &reg_addr, &reg_size);
+	if (rc < 0 || !reg_size)
+		reg_addr = reg_size = 0;
+	if (out_addr2)
+		*out_addr2 = reg_addr;
+	if (out_size2)
+		*out_size2 = reg_size;
+
+	*out_first_hartid = 0;
+	*out_hart_count = 0;
 
 	val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count);
 	if (!val || count < sizeof(fdt32_t))
-		return SBI_ENODEV;
+		return 0;
 	count = count / sizeof(fdt32_t);
 
 	first_hartid = -1U;
-	last_hartid = 0;
-	*out_hart_count = 0;
-	for (i = 0; i < count; i += 2) {
-		phandle = fdt32_to_cpu(val[i]);
-		hwirq = fdt32_to_cpu(val[i + 1]);
+	hart_count = last_hartid = 0;
+	for (i = 0; i < (count / 2); i++) {
+		phandle = fdt32_to_cpu(val[2 * i]);
+		hwirq = fdt32_to_cpu(val[(2 * i) + 1]);
 
 		cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
 		if (cpu_intc_offset < 0)
@@ -534,17 +546,15 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
 				first_hartid = hartid;
 			if (hartid > last_hartid)
 				last_hartid = hartid;
-			(*out_hart_count)++;
+			hart_count++;
 		}
 	}
 
-	if ((last_hartid < first_hartid) || first_hartid == -1U)
-		return SBI_ENODEV;
-
-	*out_first_hartid = first_hartid;
-	count = last_hartid - first_hartid + 1;
-	if (*out_hart_count < count)
-		*out_hart_count = count;
+	if ((last_hartid >= first_hartid) && first_hartid != -1U) {
+		*out_first_hartid = first_hartid;
+		count = last_hartid - first_hartid + 1;
+		*out_hart_count = (hart_count < count) ? hart_count : count;
+	}
 
 	return 0;
 }
diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
index f119f9c..1f0fda7 100644
--- a/lib/utils/ipi/fdt_ipi_mswi.c
+++ b/lib/utils/ipi/fdt_ipi_mswi.c
@@ -28,7 +28,8 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
 		return SBI_ENOSPC;
 	ms = &mswi[mswi_count];
 
-	rc = fdt_parse_aclint_node(fdt, nodeoff, false, &ms->addr, &ms->size,
+	rc = fdt_parse_aclint_node(fdt, nodeoff, false,
+				   &ms->addr, &ms->size, NULL, NULL,
 				   &ms->first_hartid, &ms->hart_count);
 	if (rc)
 		return rc;
diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
index 3f830ad..b08ed38 100644
--- a/lib/utils/timer/fdt_timer_mtimer.c
+++ b/lib/utils/timer/fdt_timer_mtimer.c
@@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 				  const struct fdt_match *match)
 {
 	int rc;
-	unsigned long offset, addr, size;
+	unsigned long offset, addr[2], size[2];
 	struct aclint_mtimer_data *mt, *mtmaster = NULL;
 
 	if (MTIMER_MAX_NR <= mtimer_count)
@@ -31,18 +31,19 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 	if (0 < mtimer_count)
 		mtmaster = &mtimer[0];
 
-	rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
+	rc = fdt_parse_aclint_node(fdt, nodeoff, true,
+				   &addr[0], &size[0], &addr[1], &size[1],
 				   &mt->first_hartid, &mt->hart_count);
 	if (rc)
 		return rc;
 	mt->has_64bit_mmio = true;
 
-	mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
-	mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
-	mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
-	mt->mtime_size = size - mt->mtimecmp_size;
-
-	if (match->data) {
+	if (match->data) { /* SiFive CLINT */
+		/* Set CLINT addresses */
+		mt->mtimecmp_addr = addr[0] + ACLINT_DEFAULT_MTIMECMP_OFFSET;
+		mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
+		mt->mtime_addr = addr[0] + ACLINT_DEFAULT_MTIME_OFFSET;
+		mt->mtime_size = size[0] - mt->mtimecmp_size;
 		/* Adjust MTIMER address and size for CLINT device */
 		offset = *((unsigned long *)match->data);
 		mt->mtime_addr += offset;
@@ -51,6 +52,12 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 		/* Parse additional CLINT properties */
 		if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
 			mt->has_64bit_mmio = false;
+	} else { /* RISC-V ACLINT MTIMER */
+		/* Set ACLINT MTIMER addresses */
+		mt->mtime_addr = addr[0];
+		mt->mtime_size = size[0];
+		mt->mtimecmp_addr = addr[1];
+		mt->mtimecmp_size = size[1];
 	}
 
 	rc = aclint_mtimer_cold_init(mt, mtmaster);
-- 
2.25.1



From jrtc27 at jrtc27.com  Sat Aug  7 07:25:34 2021
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Sat, 7 Aug 2021 15:25:34 +0100
Subject: [PATCH 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting only
 32-bit MMIO
In-Reply-To: <20210724122503.2486624-5-anup.patel@wdc.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-5-anup.patel@wdc.com>
Message-ID: <AE608946-D528-4B6C-B01B-B53D39B55E23@jrtc27.com>

On 24 Jul 2021, at 13:25, Anup Patel <anup.patel at wdc.com> wrote:
> 
> We can have ACLINT MTIMER devices which only support 32-bit MMIO
> accesses on RV64 system so this patch adds a boolean DT property
> "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.

Can the ACLINT not just mandate 64-bit accesses must work? FreeBSD and
Linux aren?t going to want to support such broken implementations, and
I would hope at least the upcoming platform spec will mandate 64-bit
access, if not the ACLINT itself.

Jess

> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
> lib/utils/timer/fdt_timer_mtimer.c | 3 +++
> 1 file changed, 3 insertions(+)
> 
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index b08ed38..15a36ed 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> 		mt->mtime_size = size[0];
> 		mt->mtimecmp_addr = addr[1];
> 		mt->mtimecmp_size = size[1];
> +		/* Parse additional ACLINT MTIMER properties */
> +		if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> +			mt->has_64bit_mmio = false;
> 	}
> 
> 	rc = aclint_mtimer_cold_init(mt, mtmaster);
> -- 
> 2.25.1
> 
> 
> -- 
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi



From anup at brainfault.org  Sat Aug  7 08:26:56 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 7 Aug 2021 20:56:56 +0530
Subject: [PATCH 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting only
 32-bit MMIO
In-Reply-To: <AE608946-D528-4B6C-B01B-B53D39B55E23@jrtc27.com>
References: <20210724122503.2486624-1-anup.patel@wdc.com>
 <20210724122503.2486624-5-anup.patel@wdc.com>
 <AE608946-D528-4B6C-B01B-B53D39B55E23@jrtc27.com>
Message-ID: <CAAhSdy2Eb-TTTBnwTEvgzPrh+YwSJXGWCCheBQWiDOzo2CusqA@mail.gmail.com>

On Sat, Aug 7, 2021 at 7:55 PM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> On 24 Jul 2021, at 13:25, Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We can have ACLINT MTIMER devices which only support 32-bit MMIO
> > accesses on RV64 system so this patch adds a boolean DT property
> > "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.
>
> Can the ACLINT not just mandate 64-bit accesses must work? FreeBSD and
> Linux aren?t going to want to support such broken implementations, and
> I would hope at least the upcoming platform spec will mandate 64-bit
> access, if not the ACLINT itself.

This has been discussed on the AIA mailing lists.

The ACLINT spec can't mandate 64-bit MMIO access because there is
a cost associated in using wider bus between harts and ACLINT device
to support 64-bit MMIO accesses.

Andrew confirmed that the RISC-V privilege spec does not explicitly
state that 64-MMIO accesses are mandatory for MTIME and MTIMECMP
on RV64 systems.

Refer:
https://lists.riscv.org/g/tech-aia/message/114
https://lists.riscv.org/g/tech-aia/message/115
https://lists.riscv.org/g/tech-aia/message/117
https://lists.riscv.org/g/tech-aia/message/118
https://lists.riscv.org/g/tech-aia/message/119
https://lists.riscv.org/g/tech-aia/message/120


Regards,
Anup



>
> Jess
>
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> > lib/utils/timer/fdt_timer_mtimer.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > index b08ed38..15a36ed 100644
> > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >               mt->mtime_size = size[0];
> >               mt->mtimecmp_addr = addr[1];
> >               mt->mtimecmp_size = size[1];
> > +             /* Parse additional ACLINT MTIMER properties */
> > +             if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> > +                     mt->has_64bit_mmio = false;
> >       }
> >
> >       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>


From atishp at atishpatra.org  Wed Aug 11 09:28:42 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Wed, 11 Aug 2021 09:28:42 -0700
Subject: [PATCH v2 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting
 only 32-bit MMIO
In-Reply-To: <20210807133322.545675-5-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-5-anup.patel@wdc.com>
Message-ID: <CAOnJCUKht+Wjw05KO3FNVNS4ND8HLXWrc+i0pYCws2_ZnaupYw@mail.gmail.com>

On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> We can have ACLINT MTIMER devices which only support 32-bit MMIO
> accesses on RV64 system so this patch adds a boolean DT property
> "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  lib/utils/timer/fdt_timer_mtimer.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index b08ed38..15a36ed 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                 mt->mtime_size = size[0];
>                 mt->mtimecmp_addr = addr[1];
>                 mt->mtimecmp_size = size[1];
> +               /* Parse additional ACLINT MTIMER properties */
> +               if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> +                       mt->has_64bit_mmio = false;
>         }
>
>         rc = aclint_mtimer_cold_init(mt, mtmaster);
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Wed Aug 11 14:07:30 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Wed, 11 Aug 2021 14:07:30 -0700
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <20210807133322.545675-6-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
Message-ID: <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>

On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
>
> We simplify MTIMER synchronization as follows:
>
> 1) Detect MTIMER devices with unique (or non-shared) MTIME
>    register at boot-time
> 2) Select first MTIMER device with no associated HART as our
>    reference MTIMER device
> 3) Only synchronize MTIMER devices with unique (or non-shared)
>    MTIME register using reference MTIMER device
> 4) Directly update the MTIME register at time of synchronization
>    because MTIME is a read/write register.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> ---
>  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
>  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
>  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
>  3 files changed, 80 insertions(+), 33 deletions(-)
>
> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> index fdc46cd..a9fe445 100644
> --- a/include/sbi_utils/timer/aclint_mtimer.h
> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
>         u32 first_hartid;
>         u32 hart_count;
>         bool has_64bit_mmio;
> +       bool has_shared_mtime;
>         /* Private details (initialized and used by ACLINT MTIMER library) */
>         struct aclint_mtimer_data *time_delta_reference;
>         unsigned long time_delta_computed;
> -       u64 time_delta;
>         u64 (*time_rd)(volatile u64 *addr);
>         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
>  };
>
> +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> +
> +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> +                                struct aclint_mtimer_data *ref);
> +
>  int aclint_mtimer_warm_init(void);
>
>  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> index 0e4e846..d612b12 100644
> --- a/lib/utils/timer/aclint_mtimer.c
> +++ b/lib/utils/timer/aclint_mtimer.c
> @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
>         u64 *time_val = (void *)mt->mtime_addr;
>
>         /* Read MTIMER Time Value */
> -       return mt->time_rd(time_val) + mt->time_delta;
> +       return mt->time_rd(time_val);
>  }
>
>  static void mtimer_event_stop(void)
> @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
>         u64 *time_cmp = (void *)mt->mtimecmp_addr;
>
>         /* Program MTIMER Time Compare */
> -       mt->time_wr(true, next_event - mt->time_delta,
> +       mt->time_wr(true, next_event,
>                     &time_cmp[target_hart - mt->first_hartid]);
>  }
>
> @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
>         .timer_event_stop = mtimer_event_stop
>  };
>
> +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> +{
> +       u64 v1, v2, mv, delta;
> +       u64 *mt_time_val, *ref_time_val;
> +       struct aclint_mtimer_data *reference;
> +
> +       /* Sync-up non-shared MTIME if reference is available */
> +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> +               return;
> +
> +       reference = mt->time_delta_reference;
> +       mt_time_val = (void *)mt->mtime_addr;
> +       ref_time_val = (void *)reference->mtime_addr;
> +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> +               v1 = mt->time_rd(mt_time_val);
> +               mv = reference->time_rd(ref_time_val);
> +               v2 = mt->time_rd(mt_time_val);
> +               delta = mv - ((v1 / 2) + (v2 / 2));
> +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> +                           mt_time_val);
> +       }
> +
> +}
> +
> +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> +                                struct aclint_mtimer_data *ref)
> +{
> +       if (!mt || !ref || mt == ref)
> +               return;
> +
> +       mt->time_delta_reference = ref;
> +       mt->time_delta_computed = 0;
> +}
> +
>  int aclint_mtimer_warm_init(void)
>  {
> -       u64 v1, v2, mv;
> +       u64 *mt_time_cmp;
>         u32 target_hart = current_hartid();
> -       struct aclint_mtimer_data *reference;
> -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
>
>         if (!mt)
>                 return SBI_ENODEV;
>
> -       /*
> -        * Compute delta if reference available
> -        *
> -        * We deliberately compute time_delta in warm init so that time_delta
> -        * is computed on a HART which is going to use given MTIMER. We use
> -        * atomic flag timer_delta_computed to ensure that only one HART does
> -        * time_delta computation.
> -        */
> -       if (mt->time_delta_reference) {
> -               reference = mt->time_delta_reference;
> -               mt_time_val = (void *)mt->mtime_addr;
> -               ref_time_val = (void *)reference->mtime_addr;
> -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> -                       v1 = mt->time_rd(mt_time_val);
> -                       mv = reference->time_rd(ref_time_val);
> -                       v2 = mt->time_rd(mt_time_val);
> -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> -               }
> -       }
> +       /* Sync-up MTIME register */
> +       aclint_mtimer_sync(mt);
>
>         /* Clear Time Compare */
>         mt_time_cmp = (void *)mt->mtimecmp_addr;
> @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>                 return SBI_EINVAL;
>
>         /* Initialize private data */
> -       mt->time_delta_reference = reference;
> -       mt->time_delta_computed = 0;
> -       mt->time_delta = 0;
> +       aclint_mtimer_set_reference(mt, reference);
>         mt->time_rd = mtimer_time_rd32;
>         mt->time_wr = mtimer_time_wr32;
>
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 15a36ed..26b5a2a 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -17,19 +17,18 @@
>
>  static unsigned long mtimer_count = 0;
>  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> +static struct aclint_mtimer_data *mt_reference = NULL;
>
>  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
> -       int rc;
> +       int i, rc;
>         unsigned long offset, addr[2], size[2];
> -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> +       struct aclint_mtimer_data *mt;
>
>         if (MTIMER_MAX_NR <= mtimer_count)
>                 return SBI_ENOSPC;
>         mt = &mtimer[mtimer_count];
> -       if (0 < mtimer_count)
> -               mtmaster = &mtimer[0];
>
>         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
>                                    &addr[0], &size[0], &addr[1], &size[1],
> @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>         if (rc)
>                 return rc;
>         mt->has_64bit_mmio = true;
> +       mt->has_shared_mtime = false;
>
>         if (match->data) { /* SiFive CLINT */
>                 /* Set CLINT addresses */
> @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                         mt->has_64bit_mmio = false;
>         }
>
> -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> +       /* Check if MTIMER device has shared MTIME address */
> +       mt->has_shared_mtime = false;
> +       for (i = 0; i < mtimer_count; i++) {
> +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> +                       mt->has_shared_mtime = true;
> +                       break;
> +               }
> +       }
> +
> +       /* Initialize the MTIMER device */
> +       rc = aclint_mtimer_cold_init(mt, mt_reference);
>         if (rc)
>                 return rc;
>
> +       /*
> +        * Select first MTIMER device with no associated HARTs as
> +        * our reference MTIMER device
> +        */
> +       if (!mt->hart_count && !mt_reference) {
> +               mt_reference = mt;
> +               /*
> +                * Set reference for already propbed MTIMER devices
> +                * with non-shared MTIME
> +                */
> +               for (i = 0; i < mtimer_count; i++)
> +                       if (!mtimer[i].has_shared_mtime)
> +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> +       }
> +

Is there a reason this is done after cold_init ?

> +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> +       if (!mt->hart_count)
> +               aclint_mtimer_sync(mt);
> +
>         mtimer_count++;
>         return 0;
>  }
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


--
Regards,
Atish


From anup at brainfault.org  Wed Aug 11 21:18:52 2021
From: anup at brainfault.org (Anup Patel)
Date: Thu, 12 Aug 2021 09:48:52 +0530
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
 <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
Message-ID: <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>

On Thu, Aug 12, 2021 at 2:37 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We simplify MTIMER synchronization as follows:
> >
> > 1) Detect MTIMER devices with unique (or non-shared) MTIME
> >    register at boot-time
> > 2) Select first MTIMER device with no associated HART as our
> >    reference MTIMER device
> > 3) Only synchronize MTIMER devices with unique (or non-shared)
> >    MTIME register using reference MTIMER device
> > 4) Directly update the MTIME register at time of synchronization
> >    because MTIME is a read/write register.
> >
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
> >  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
> >  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
> >  3 files changed, 80 insertions(+), 33 deletions(-)
> >
> > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > index fdc46cd..a9fe445 100644
> > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
> >         u32 first_hartid;
> >         u32 hart_count;
> >         bool has_64bit_mmio;
> > +       bool has_shared_mtime;
> >         /* Private details (initialized and used by ACLINT MTIMER library) */
> >         struct aclint_mtimer_data *time_delta_reference;
> >         unsigned long time_delta_computed;
> > -       u64 time_delta;
> >         u64 (*time_rd)(volatile u64 *addr);
> >         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
> >  };
> >
> > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> > +
> > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > +                                struct aclint_mtimer_data *ref);
> > +
> >  int aclint_mtimer_warm_init(void);
> >
> >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > index 0e4e846..d612b12 100644
> > --- a/lib/utils/timer/aclint_mtimer.c
> > +++ b/lib/utils/timer/aclint_mtimer.c
> > @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
> >         u64 *time_val = (void *)mt->mtime_addr;
> >
> >         /* Read MTIMER Time Value */
> > -       return mt->time_rd(time_val) + mt->time_delta;
> > +       return mt->time_rd(time_val);
> >  }
> >
> >  static void mtimer_event_stop(void)
> > @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
> >         u64 *time_cmp = (void *)mt->mtimecmp_addr;
> >
> >         /* Program MTIMER Time Compare */
> > -       mt->time_wr(true, next_event - mt->time_delta,
> > +       mt->time_wr(true, next_event,
> >                     &time_cmp[target_hart - mt->first_hartid]);
> >  }
> >
> > @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
> >         .timer_event_stop = mtimer_event_stop
> >  };
> >
> > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> > +{
> > +       u64 v1, v2, mv, delta;
> > +       u64 *mt_time_val, *ref_time_val;
> > +       struct aclint_mtimer_data *reference;
> > +
> > +       /* Sync-up non-shared MTIME if reference is available */
> > +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> > +               return;
> > +
> > +       reference = mt->time_delta_reference;
> > +       mt_time_val = (void *)mt->mtime_addr;
> > +       ref_time_val = (void *)reference->mtime_addr;
> > +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > +               v1 = mt->time_rd(mt_time_val);
> > +               mv = reference->time_rd(ref_time_val);
> > +               v2 = mt->time_rd(mt_time_val);
> > +               delta = mv - ((v1 / 2) + (v2 / 2));
> > +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> > +                           mt_time_val);
> > +       }
> > +
> > +}
> > +
> > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > +                                struct aclint_mtimer_data *ref)
> > +{
> > +       if (!mt || !ref || mt == ref)
> > +               return;
> > +
> > +       mt->time_delta_reference = ref;
> > +       mt->time_delta_computed = 0;
> > +}
> > +
> >  int aclint_mtimer_warm_init(void)
> >  {
> > -       u64 v1, v2, mv;
> > +       u64 *mt_time_cmp;
> >         u32 target_hart = current_hartid();
> > -       struct aclint_mtimer_data *reference;
> > -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
> >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> >
> >         if (!mt)
> >                 return SBI_ENODEV;
> >
> > -       /*
> > -        * Compute delta if reference available
> > -        *
> > -        * We deliberately compute time_delta in warm init so that time_delta
> > -        * is computed on a HART which is going to use given MTIMER. We use
> > -        * atomic flag timer_delta_computed to ensure that only one HART does
> > -        * time_delta computation.
> > -        */
> > -       if (mt->time_delta_reference) {
> > -               reference = mt->time_delta_reference;
> > -               mt_time_val = (void *)mt->mtime_addr;
> > -               ref_time_val = (void *)reference->mtime_addr;
> > -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > -                       v1 = mt->time_rd(mt_time_val);
> > -                       mv = reference->time_rd(ref_time_val);
> > -                       v2 = mt->time_rd(mt_time_val);
> > -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> > -               }
> > -       }
> > +       /* Sync-up MTIME register */
> > +       aclint_mtimer_sync(mt);
> >
> >         /* Clear Time Compare */
> >         mt_time_cmp = (void *)mt->mtimecmp_addr;
> > @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> >                 return SBI_EINVAL;
> >
> >         /* Initialize private data */
> > -       mt->time_delta_reference = reference;
> > -       mt->time_delta_computed = 0;
> > -       mt->time_delta = 0;
> > +       aclint_mtimer_set_reference(mt, reference);
> >         mt->time_rd = mtimer_time_rd32;
> >         mt->time_wr = mtimer_time_wr32;
> >
> > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > index 15a36ed..26b5a2a 100644
> > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > @@ -17,19 +17,18 @@
> >
> >  static unsigned long mtimer_count = 0;
> >  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> > +static struct aclint_mtimer_data *mt_reference = NULL;
> >
> >  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >                                   const struct fdt_match *match)
> >  {
> > -       int rc;
> > +       int i, rc;
> >         unsigned long offset, addr[2], size[2];
> > -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> > +       struct aclint_mtimer_data *mt;
> >
> >         if (MTIMER_MAX_NR <= mtimer_count)
> >                 return SBI_ENOSPC;
> >         mt = &mtimer[mtimer_count];
> > -       if (0 < mtimer_count)
> > -               mtmaster = &mtimer[0];
> >
> >         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> >                                    &addr[0], &size[0], &addr[1], &size[1],
> > @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >         if (rc)
> >                 return rc;
> >         mt->has_64bit_mmio = true;
> > +       mt->has_shared_mtime = false;
> >
> >         if (match->data) { /* SiFive CLINT */
> >                 /* Set CLINT addresses */
> > @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >                         mt->has_64bit_mmio = false;
> >         }
> >
> > -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > +       /* Check if MTIMER device has shared MTIME address */
> > +       mt->has_shared_mtime = false;
> > +       for (i = 0; i < mtimer_count; i++) {
> > +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> > +                       mt->has_shared_mtime = true;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       /* Initialize the MTIMER device */
> > +       rc = aclint_mtimer_cold_init(mt, mt_reference);
> >         if (rc)
> >                 return rc;
> >
> > +       /*
> > +        * Select first MTIMER device with no associated HARTs as
> > +        * our reference MTIMER device
> > +        */
> > +       if (!mt->hart_count && !mt_reference) {
> > +               mt_reference = mt;
> > +               /*
> > +                * Set reference for already propbed MTIMER devices
> > +                * with non-shared MTIME
> > +                */
> > +               for (i = 0; i < mtimer_count; i++)
> > +                       if (!mtimer[i].has_shared_mtime)
> > +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> > +       }
> > +
>
> Is there a reason this is done after cold_init ?

We should select a MTIMER device as reference only after it is
successfully initialized by the cold_init(). This ensures that even the
reference MTIMER device has gone through all sanity checks.

Also, simply selecting the first successfully initialized MTIMER device is
also not appropriate because we don't know how MTIMER devices are
ordered in DT.

For now, the strategy is to select a successfully initialized MTIMER
device with hart_count = 0 as reference. In future, we might select
optional DT property to help us select the reference MTIMER device.

Regards,
Anup

>
> > +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> > +       if (!mt->hart_count)
> > +               aclint_mtimer_sync(mt);
> > +
> >         mtimer_count++;
> >         return 0;
> >  }
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
> --
> Regards,
> Atish


From atishp at atishpatra.org  Thu Aug 12 08:09:10 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Thu, 12 Aug 2021 08:09:10 -0700
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
 <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
 <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>
Message-ID: <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>

On Wed, Aug 11, 2021 at 9:19 PM Anup Patel <anup at brainfault.org> wrote:
>
> On Thu, Aug 12, 2021 at 2:37 AM Atish Patra <atishp at atishpatra.org> wrote:
> >
> > On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> > >
> > > We simplify MTIMER synchronization as follows:
> > >
> > > 1) Detect MTIMER devices with unique (or non-shared) MTIME
> > >    register at boot-time
> > > 2) Select first MTIMER device with no associated HART as our
> > >    reference MTIMER device
> > > 3) Only synchronize MTIMER devices with unique (or non-shared)
> > >    MTIME register using reference MTIMER device
> > > 4) Directly update the MTIME register at time of synchronization
> > >    because MTIME is a read/write register.
> > >
> > > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > > ---
> > >  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
> > >  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
> > >  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
> > >  3 files changed, 80 insertions(+), 33 deletions(-)
> > >
> > > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > > index fdc46cd..a9fe445 100644
> > > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > > @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
> > >         u32 first_hartid;
> > >         u32 hart_count;
> > >         bool has_64bit_mmio;
> > > +       bool has_shared_mtime;
> > >         /* Private details (initialized and used by ACLINT MTIMER library) */
> > >         struct aclint_mtimer_data *time_delta_reference;
> > >         unsigned long time_delta_computed;
> > > -       u64 time_delta;
> > >         u64 (*time_rd)(volatile u64 *addr);
> > >         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
> > >  };
> > >
> > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> > > +
> > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > +                                struct aclint_mtimer_data *ref);
> > > +
> > >  int aclint_mtimer_warm_init(void);
> > >
> > >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > > index 0e4e846..d612b12 100644
> > > --- a/lib/utils/timer/aclint_mtimer.c
> > > +++ b/lib/utils/timer/aclint_mtimer.c
> > > @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
> > >         u64 *time_val = (void *)mt->mtime_addr;
> > >
> > >         /* Read MTIMER Time Value */
> > > -       return mt->time_rd(time_val) + mt->time_delta;
> > > +       return mt->time_rd(time_val);
> > >  }
> > >
> > >  static void mtimer_event_stop(void)
> > > @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
> > >         u64 *time_cmp = (void *)mt->mtimecmp_addr;
> > >
> > >         /* Program MTIMER Time Compare */
> > > -       mt->time_wr(true, next_event - mt->time_delta,
> > > +       mt->time_wr(true, next_event,
> > >                     &time_cmp[target_hart - mt->first_hartid]);
> > >  }
> > >
> > > @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
> > >         .timer_event_stop = mtimer_event_stop
> > >  };
> > >
> > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> > > +{
> > > +       u64 v1, v2, mv, delta;
> > > +       u64 *mt_time_val, *ref_time_val;
> > > +       struct aclint_mtimer_data *reference;
> > > +
> > > +       /* Sync-up non-shared MTIME if reference is available */
> > > +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> > > +               return;
> > > +
> > > +       reference = mt->time_delta_reference;
> > > +       mt_time_val = (void *)mt->mtime_addr;
> > > +       ref_time_val = (void *)reference->mtime_addr;
> > > +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > +               v1 = mt->time_rd(mt_time_val);
> > > +               mv = reference->time_rd(ref_time_val);
> > > +               v2 = mt->time_rd(mt_time_val);
> > > +               delta = mv - ((v1 / 2) + (v2 / 2));
> > > +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> > > +                           mt_time_val);
> > > +       }
> > > +
> > > +}
> > > +
> > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > +                                struct aclint_mtimer_data *ref)
> > > +{
> > > +       if (!mt || !ref || mt == ref)
> > > +               return;
> > > +
> > > +       mt->time_delta_reference = ref;
> > > +       mt->time_delta_computed = 0;
> > > +}
> > > +
> > >  int aclint_mtimer_warm_init(void)
> > >  {
> > > -       u64 v1, v2, mv;
> > > +       u64 *mt_time_cmp;
> > >         u32 target_hart = current_hartid();
> > > -       struct aclint_mtimer_data *reference;
> > > -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
> > >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > >
> > >         if (!mt)
> > >                 return SBI_ENODEV;
> > >
> > > -       /*
> > > -        * Compute delta if reference available
> > > -        *
> > > -        * We deliberately compute time_delta in warm init so that time_delta
> > > -        * is computed on a HART which is going to use given MTIMER. We use
> > > -        * atomic flag timer_delta_computed to ensure that only one HART does
> > > -        * time_delta computation.
> > > -        */
> > > -       if (mt->time_delta_reference) {
> > > -               reference = mt->time_delta_reference;
> > > -               mt_time_val = (void *)mt->mtime_addr;
> > > -               ref_time_val = (void *)reference->mtime_addr;
> > > -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > -                       v1 = mt->time_rd(mt_time_val);
> > > -                       mv = reference->time_rd(ref_time_val);
> > > -                       v2 = mt->time_rd(mt_time_val);
> > > -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> > > -               }
> > > -       }
> > > +       /* Sync-up MTIME register */
> > > +       aclint_mtimer_sync(mt);
> > >
> > >         /* Clear Time Compare */
> > >         mt_time_cmp = (void *)mt->mtimecmp_addr;
> > > @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > >                 return SBI_EINVAL;
> > >
> > >         /* Initialize private data */
> > > -       mt->time_delta_reference = reference;
> > > -       mt->time_delta_computed = 0;
> > > -       mt->time_delta = 0;
> > > +       aclint_mtimer_set_reference(mt, reference);
> > >         mt->time_rd = mtimer_time_rd32;
> > >         mt->time_wr = mtimer_time_wr32;
> > >
> > > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > > index 15a36ed..26b5a2a 100644
> > > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > > @@ -17,19 +17,18 @@
> > >
> > >  static unsigned long mtimer_count = 0;
> > >  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> > > +static struct aclint_mtimer_data *mt_reference = NULL;
> > >
> > >  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > >                                   const struct fdt_match *match)
> > >  {
> > > -       int rc;
> > > +       int i, rc;
> > >         unsigned long offset, addr[2], size[2];
> > > -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> > > +       struct aclint_mtimer_data *mt;
> > >
> > >         if (MTIMER_MAX_NR <= mtimer_count)
> > >                 return SBI_ENOSPC;
> > >         mt = &mtimer[mtimer_count];
> > > -       if (0 < mtimer_count)
> > > -               mtmaster = &mtimer[0];
> > >
> > >         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> > >                                    &addr[0], &size[0], &addr[1], &size[1],
> > > @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > >         if (rc)
> > >                 return rc;
> > >         mt->has_64bit_mmio = true;
> > > +       mt->has_shared_mtime = false;
> > >
> > >         if (match->data) { /* SiFive CLINT */
> > >                 /* Set CLINT addresses */
> > > @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > >                         mt->has_64bit_mmio = false;
> > >         }
> > >
> > > -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > > +       /* Check if MTIMER device has shared MTIME address */
> > > +       mt->has_shared_mtime = false;
> > > +       for (i = 0; i < mtimer_count; i++) {
> > > +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> > > +                       mt->has_shared_mtime = true;
> > > +                       break;
> > > +               }
> > > +       }
> > > +
> > > +       /* Initialize the MTIMER device */
> > > +       rc = aclint_mtimer_cold_init(mt, mt_reference);
> > >         if (rc)
> > >                 return rc;
> > >
> > > +       /*
> > > +        * Select first MTIMER device with no associated HARTs as
> > > +        * our reference MTIMER device
> > > +        */
> > > +       if (!mt->hart_count && !mt_reference) {
> > > +               mt_reference = mt;
> > > +               /*
> > > +                * Set reference for already propbed MTIMER devices
> > > +                * with non-shared MTIME
> > > +                */
> > > +               for (i = 0; i < mtimer_count; i++)
> > > +                       if (!mtimer[i].has_shared_mtime)
> > > +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> > > +       }
> > > +
> >
> > Is there a reason this is done after cold_init ?
>
> We should select a MTIMER device as reference only after it is
> successfully initialized by the cold_init(). This ensures that even the
> reference MTIMER device has gone through all sanity checks.

Got it. Thanks.

>
> Also, simply selecting the first successfully initialized MTIMER device is
> also not appropriate because we don't know how MTIMER devices are
> ordered in DT.
>
> For now, the strategy is to select a successfully initialized MTIMER
> device with hart_count = 0 as reference. In future, we might select

Is this information documented somewhere ? The platform must have a
MTIMER device
with zero hart_count in order to get a reference.

Just for my understanding, when do we need multiple MTIMER devices
with zero hart count in multi-socket
scenarios ?

> optional DT property to help us select the reference MTIMER device.
>
> Regards,
> Anup
>
> >
> > > +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> > > +       if (!mt->hart_count)
> > > +               aclint_mtimer_sync(mt);
> > > +
> > >         mtimer_count++;
> > >         return 0;
> > >  }
> > > --
> > > 2.25.1
> > >
> > >
> > > --
> > > opensbi mailing list
> > > opensbi at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/opensbi
> >
> >
> > --
> > Regards,
> > Atish

Other than that, this patch looks good to me.

Reviewed-by: Atish Patra <atish.patra at wdc.com>


-- 
Regards,
Atish


From anup at brainfault.org  Thu Aug 12 09:54:37 2021
From: anup at brainfault.org (Anup Patel)
Date: Thu, 12 Aug 2021 22:24:37 +0530
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
 <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
 <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>
 <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>
Message-ID: <CAAhSdy1WgQ7fLTzrwyZ+S5oqw_yX0iHPd5c6FO0d=xosrN6m6g@mail.gmail.com>

On Thu, Aug 12, 2021 at 8:39 PM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Wed, Aug 11, 2021 at 9:19 PM Anup Patel <anup at brainfault.org> wrote:
> >
> > On Thu, Aug 12, 2021 at 2:37 AM Atish Patra <atishp at atishpatra.org> wrote:
> > >
> > > On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> > > >
> > > > We simplify MTIMER synchronization as follows:
> > > >
> > > > 1) Detect MTIMER devices with unique (or non-shared) MTIME
> > > >    register at boot-time
> > > > 2) Select first MTIMER device with no associated HART as our
> > > >    reference MTIMER device
> > > > 3) Only synchronize MTIMER devices with unique (or non-shared)
> > > >    MTIME register using reference MTIMER device
> > > > 4) Directly update the MTIME register at time of synchronization
> > > >    because MTIME is a read/write register.
> > > >
> > > > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > > > ---
> > > >  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
> > > >  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
> > > >  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
> > > >  3 files changed, 80 insertions(+), 33 deletions(-)
> > > >
> > > > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > > > index fdc46cd..a9fe445 100644
> > > > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > > > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > > > @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
> > > >         u32 first_hartid;
> > > >         u32 hart_count;
> > > >         bool has_64bit_mmio;
> > > > +       bool has_shared_mtime;
> > > >         /* Private details (initialized and used by ACLINT MTIMER library) */
> > > >         struct aclint_mtimer_data *time_delta_reference;
> > > >         unsigned long time_delta_computed;
> > > > -       u64 time_delta;
> > > >         u64 (*time_rd)(volatile u64 *addr);
> > > >         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
> > > >  };
> > > >
> > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> > > > +
> > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > +                                struct aclint_mtimer_data *ref);
> > > > +
> > > >  int aclint_mtimer_warm_init(void);
> > > >
> > > >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > > > index 0e4e846..d612b12 100644
> > > > --- a/lib/utils/timer/aclint_mtimer.c
> > > > +++ b/lib/utils/timer/aclint_mtimer.c
> > > > @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
> > > >         u64 *time_val = (void *)mt->mtime_addr;
> > > >
> > > >         /* Read MTIMER Time Value */
> > > > -       return mt->time_rd(time_val) + mt->time_delta;
> > > > +       return mt->time_rd(time_val);
> > > >  }
> > > >
> > > >  static void mtimer_event_stop(void)
> > > > @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
> > > >         u64 *time_cmp = (void *)mt->mtimecmp_addr;
> > > >
> > > >         /* Program MTIMER Time Compare */
> > > > -       mt->time_wr(true, next_event - mt->time_delta,
> > > > +       mt->time_wr(true, next_event,
> > > >                     &time_cmp[target_hart - mt->first_hartid]);
> > > >  }
> > > >
> > > > @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
> > > >         .timer_event_stop = mtimer_event_stop
> > > >  };
> > > >
> > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> > > > +{
> > > > +       u64 v1, v2, mv, delta;
> > > > +       u64 *mt_time_val, *ref_time_val;
> > > > +       struct aclint_mtimer_data *reference;
> > > > +
> > > > +       /* Sync-up non-shared MTIME if reference is available */
> > > > +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> > > > +               return;
> > > > +
> > > > +       reference = mt->time_delta_reference;
> > > > +       mt_time_val = (void *)mt->mtime_addr;
> > > > +       ref_time_val = (void *)reference->mtime_addr;
> > > > +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > +               v1 = mt->time_rd(mt_time_val);
> > > > +               mv = reference->time_rd(ref_time_val);
> > > > +               v2 = mt->time_rd(mt_time_val);
> > > > +               delta = mv - ((v1 / 2) + (v2 / 2));
> > > > +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> > > > +                           mt_time_val);
> > > > +       }
> > > > +
> > > > +}
> > > > +
> > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > +                                struct aclint_mtimer_data *ref)
> > > > +{
> > > > +       if (!mt || !ref || mt == ref)
> > > > +               return;
> > > > +
> > > > +       mt->time_delta_reference = ref;
> > > > +       mt->time_delta_computed = 0;
> > > > +}
> > > > +
> > > >  int aclint_mtimer_warm_init(void)
> > > >  {
> > > > -       u64 v1, v2, mv;
> > > > +       u64 *mt_time_cmp;
> > > >         u32 target_hart = current_hartid();
> > > > -       struct aclint_mtimer_data *reference;
> > > > -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
> > > >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > > >
> > > >         if (!mt)
> > > >                 return SBI_ENODEV;
> > > >
> > > > -       /*
> > > > -        * Compute delta if reference available
> > > > -        *
> > > > -        * We deliberately compute time_delta in warm init so that time_delta
> > > > -        * is computed on a HART which is going to use given MTIMER. We use
> > > > -        * atomic flag timer_delta_computed to ensure that only one HART does
> > > > -        * time_delta computation.
> > > > -        */
> > > > -       if (mt->time_delta_reference) {
> > > > -               reference = mt->time_delta_reference;
> > > > -               mt_time_val = (void *)mt->mtime_addr;
> > > > -               ref_time_val = (void *)reference->mtime_addr;
> > > > -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > -                       v1 = mt->time_rd(mt_time_val);
> > > > -                       mv = reference->time_rd(ref_time_val);
> > > > -                       v2 = mt->time_rd(mt_time_val);
> > > > -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> > > > -               }
> > > > -       }
> > > > +       /* Sync-up MTIME register */
> > > > +       aclint_mtimer_sync(mt);
> > > >
> > > >         /* Clear Time Compare */
> > > >         mt_time_cmp = (void *)mt->mtimecmp_addr;
> > > > @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > >                 return SBI_EINVAL;
> > > >
> > > >         /* Initialize private data */
> > > > -       mt->time_delta_reference = reference;
> > > > -       mt->time_delta_computed = 0;
> > > > -       mt->time_delta = 0;
> > > > +       aclint_mtimer_set_reference(mt, reference);
> > > >         mt->time_rd = mtimer_time_rd32;
> > > >         mt->time_wr = mtimer_time_wr32;
> > > >
> > > > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > > > index 15a36ed..26b5a2a 100644
> > > > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > > > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > > > @@ -17,19 +17,18 @@
> > > >
> > > >  static unsigned long mtimer_count = 0;
> > > >  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> > > > +static struct aclint_mtimer_data *mt_reference = NULL;
> > > >
> > > >  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >                                   const struct fdt_match *match)
> > > >  {
> > > > -       int rc;
> > > > +       int i, rc;
> > > >         unsigned long offset, addr[2], size[2];
> > > > -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> > > > +       struct aclint_mtimer_data *mt;
> > > >
> > > >         if (MTIMER_MAX_NR <= mtimer_count)
> > > >                 return SBI_ENOSPC;
> > > >         mt = &mtimer[mtimer_count];
> > > > -       if (0 < mtimer_count)
> > > > -               mtmaster = &mtimer[0];
> > > >
> > > >         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> > > >                                    &addr[0], &size[0], &addr[1], &size[1],
> > > > @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >         if (rc)
> > > >                 return rc;
> > > >         mt->has_64bit_mmio = true;
> > > > +       mt->has_shared_mtime = false;
> > > >
> > > >         if (match->data) { /* SiFive CLINT */
> > > >                 /* Set CLINT addresses */
> > > > @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >                         mt->has_64bit_mmio = false;
> > > >         }
> > > >
> > > > -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > > > +       /* Check if MTIMER device has shared MTIME address */
> > > > +       mt->has_shared_mtime = false;
> > > > +       for (i = 0; i < mtimer_count; i++) {
> > > > +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> > > > +                       mt->has_shared_mtime = true;
> > > > +                       break;
> > > > +               }
> > > > +       }
> > > > +
> > > > +       /* Initialize the MTIMER device */
> > > > +       rc = aclint_mtimer_cold_init(mt, mt_reference);
> > > >         if (rc)
> > > >                 return rc;
> > > >
> > > > +       /*
> > > > +        * Select first MTIMER device with no associated HARTs as
> > > > +        * our reference MTIMER device
> > > > +        */
> > > > +       if (!mt->hart_count && !mt_reference) {
> > > > +               mt_reference = mt;
> > > > +               /*
> > > > +                * Set reference for already propbed MTIMER devices
> > > > +                * with non-shared MTIME
> > > > +                */
> > > > +               for (i = 0; i < mtimer_count; i++)
> > > > +                       if (!mtimer[i].has_shared_mtime)
> > > > +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> > > > +       }
> > > > +
> > >
> > > Is there a reason this is done after cold_init ?
> >
> > We should select a MTIMER device as reference only after it is
> > successfully initialized by the cold_init(). This ensures that even the
> > reference MTIMER device has gone through all sanity checks.
>
> Got it. Thanks.
>
> >
> > Also, simply selecting the first successfully initialized MTIMER device is
> > also not appropriate because we don't know how MTIMER devices are
> > ordered in DT.
> >
> > For now, the strategy is to select a successfully initialized MTIMER
> > device with hart_count = 0 as reference. In future, we might select
>
> Is this information documented somewhere ? The platform must have a
> MTIMER device
> with zero hart_count in order to get a reference.

This is OpenSBI specific strategy. We can put comments in code if you
want.

>
> Just for my understanding, when do we need multiple MTIMER devices
> with zero hart count in multi-socket
> scenarios ?

If we define special DT properties in future for selecting a reference
MTIMER device in a multi-socket or multi-die system then we don't
need to MTIMER DT nodes with zero harts.

The approach of selecting MTIMER devices with zero harts is
temporary because I did not want to not define DT properties which
are not immediately required.

>
> > optional DT property to help us select the reference MTIMER device.
> >
> > Regards,
> > Anup
> >
> > >
> > > > +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> > > > +       if (!mt->hart_count)
> > > > +               aclint_mtimer_sync(mt);
> > > > +
> > > >         mtimer_count++;
> > > >         return 0;
> > > >  }
> > > > --
> > > > 2.25.1
> > > >
> > > >
> > > > --
> > > > opensbi mailing list
> > > > opensbi at lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/opensbi
> > >
> > >
> > > --
> > > Regards,
> > > Atish
>
> Other than that, this patch looks good to me.
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>
>
>
> --
> Regards,
> Atish

Regards,
Anup


From atishp at atishpatra.org  Thu Aug 12 16:10:22 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Thu, 12 Aug 2021 16:10:22 -0700
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <CAAhSdy1WgQ7fLTzrwyZ+S5oqw_yX0iHPd5c6FO0d=xosrN6m6g@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
 <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
 <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>
 <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>
 <CAAhSdy1WgQ7fLTzrwyZ+S5oqw_yX0iHPd5c6FO0d=xosrN6m6g@mail.gmail.com>
Message-ID: <CAOnJCUJcZA-5KT3VqDSiuvKi2TShEwK+1yqVCD_MCt6FFOpLeA@mail.gmail.com>

On Thu, Aug 12, 2021 at 9:54 AM Anup Patel <anup at brainfault.org> wrote:
>
> On Thu, Aug 12, 2021 at 8:39 PM Atish Patra <atishp at atishpatra.org> wrote:
> >
> > On Wed, Aug 11, 2021 at 9:19 PM Anup Patel <anup at brainfault.org> wrote:
> > >
> > > On Thu, Aug 12, 2021 at 2:37 AM Atish Patra <atishp at atishpatra.org> wrote:
> > > >
> > > > On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> > > > >
> > > > > We simplify MTIMER synchronization as follows:
> > > > >
> > > > > 1) Detect MTIMER devices with unique (or non-shared) MTIME
> > > > >    register at boot-time
> > > > > 2) Select first MTIMER device with no associated HART as our
> > > > >    reference MTIMER device
> > > > > 3) Only synchronize MTIMER devices with unique (or non-shared)
> > > > >    MTIME register using reference MTIMER device
> > > > > 4) Directly update the MTIME register at time of synchronization
> > > > >    because MTIME is a read/write register.
> > > > >
> > > > > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > > > > ---
> > > > >  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
> > > > >  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
> > > > >  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
> > > > >  3 files changed, 80 insertions(+), 33 deletions(-)
> > > > >
> > > > > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > > > > index fdc46cd..a9fe445 100644
> > > > > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > > > > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > > > > @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
> > > > >         u32 first_hartid;
> > > > >         u32 hart_count;
> > > > >         bool has_64bit_mmio;
> > > > > +       bool has_shared_mtime;
> > > > >         /* Private details (initialized and used by ACLINT MTIMER library) */
> > > > >         struct aclint_mtimer_data *time_delta_reference;
> > > > >         unsigned long time_delta_computed;
> > > > > -       u64 time_delta;
> > > > >         u64 (*time_rd)(volatile u64 *addr);
> > > > >         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
> > > > >  };
> > > > >
> > > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> > > > > +
> > > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > > +                                struct aclint_mtimer_data *ref);
> > > > > +
> > > > >  int aclint_mtimer_warm_init(void);
> > > > >
> > > > >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > > > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > > > > index 0e4e846..d612b12 100644
> > > > > --- a/lib/utils/timer/aclint_mtimer.c
> > > > > +++ b/lib/utils/timer/aclint_mtimer.c
> > > > > @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
> > > > >         u64 *time_val = (void *)mt->mtime_addr;
> > > > >
> > > > >         /* Read MTIMER Time Value */
> > > > > -       return mt->time_rd(time_val) + mt->time_delta;
> > > > > +       return mt->time_rd(time_val);
> > > > >  }
> > > > >
> > > > >  static void mtimer_event_stop(void)
> > > > > @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
> > > > >         u64 *time_cmp = (void *)mt->mtimecmp_addr;
> > > > >
> > > > >         /* Program MTIMER Time Compare */
> > > > > -       mt->time_wr(true, next_event - mt->time_delta,
> > > > > +       mt->time_wr(true, next_event,
> > > > >                     &time_cmp[target_hart - mt->first_hartid]);
> > > > >  }
> > > > >
> > > > > @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
> > > > >         .timer_event_stop = mtimer_event_stop
> > > > >  };
> > > > >
> > > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> > > > > +{
> > > > > +       u64 v1, v2, mv, delta;
> > > > > +       u64 *mt_time_val, *ref_time_val;
> > > > > +       struct aclint_mtimer_data *reference;
> > > > > +
> > > > > +       /* Sync-up non-shared MTIME if reference is available */
> > > > > +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> > > > > +               return;
> > > > > +
> > > > > +       reference = mt->time_delta_reference;
> > > > > +       mt_time_val = (void *)mt->mtime_addr;
> > > > > +       ref_time_val = (void *)reference->mtime_addr;
> > > > > +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > > +               v1 = mt->time_rd(mt_time_val);
> > > > > +               mv = reference->time_rd(ref_time_val);
> > > > > +               v2 = mt->time_rd(mt_time_val);
> > > > > +               delta = mv - ((v1 / 2) + (v2 / 2));
> > > > > +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> > > > > +                           mt_time_val);
> > > > > +       }
> > > > > +
> > > > > +}
> > > > > +
> > > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > > +                                struct aclint_mtimer_data *ref)
> > > > > +{
> > > > > +       if (!mt || !ref || mt == ref)
> > > > > +               return;
> > > > > +
> > > > > +       mt->time_delta_reference = ref;
> > > > > +       mt->time_delta_computed = 0;
> > > > > +}
> > > > > +
> > > > >  int aclint_mtimer_warm_init(void)
> > > > >  {
> > > > > -       u64 v1, v2, mv;
> > > > > +       u64 *mt_time_cmp;
> > > > >         u32 target_hart = current_hartid();
> > > > > -       struct aclint_mtimer_data *reference;
> > > > > -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
> > > > >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > > > >
> > > > >         if (!mt)
> > > > >                 return SBI_ENODEV;
> > > > >
> > > > > -       /*
> > > > > -        * Compute delta if reference available
> > > > > -        *
> > > > > -        * We deliberately compute time_delta in warm init so that time_delta
> > > > > -        * is computed on a HART which is going to use given MTIMER. We use
> > > > > -        * atomic flag timer_delta_computed to ensure that only one HART does
> > > > > -        * time_delta computation.
> > > > > -        */
> > > > > -       if (mt->time_delta_reference) {
> > > > > -               reference = mt->time_delta_reference;
> > > > > -               mt_time_val = (void *)mt->mtime_addr;
> > > > > -               ref_time_val = (void *)reference->mtime_addr;
> > > > > -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > > -                       v1 = mt->time_rd(mt_time_val);
> > > > > -                       mv = reference->time_rd(ref_time_val);
> > > > > -                       v2 = mt->time_rd(mt_time_val);
> > > > > -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> > > > > -               }
> > > > > -       }
> > > > > +       /* Sync-up MTIME register */
> > > > > +       aclint_mtimer_sync(mt);
> > > > >
> > > > >         /* Clear Time Compare */
> > > > >         mt_time_cmp = (void *)mt->mtimecmp_addr;
> > > > > @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > > >                 return SBI_EINVAL;
> > > > >
> > > > >         /* Initialize private data */
> > > > > -       mt->time_delta_reference = reference;
> > > > > -       mt->time_delta_computed = 0;
> > > > > -       mt->time_delta = 0;
> > > > > +       aclint_mtimer_set_reference(mt, reference);
> > > > >         mt->time_rd = mtimer_time_rd32;
> > > > >         mt->time_wr = mtimer_time_wr32;
> > > > >
> > > > > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > > > > index 15a36ed..26b5a2a 100644
> > > > > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > > > > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > > > > @@ -17,19 +17,18 @@
> > > > >
> > > > >  static unsigned long mtimer_count = 0;
> > > > >  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> > > > > +static struct aclint_mtimer_data *mt_reference = NULL;
> > > > >
> > > > >  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > > >                                   const struct fdt_match *match)
> > > > >  {
> > > > > -       int rc;
> > > > > +       int i, rc;
> > > > >         unsigned long offset, addr[2], size[2];
> > > > > -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> > > > > +       struct aclint_mtimer_data *mt;
> > > > >
> > > > >         if (MTIMER_MAX_NR <= mtimer_count)
> > > > >                 return SBI_ENOSPC;
> > > > >         mt = &mtimer[mtimer_count];
> > > > > -       if (0 < mtimer_count)
> > > > > -               mtmaster = &mtimer[0];
> > > > >
> > > > >         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> > > > >                                    &addr[0], &size[0], &addr[1], &size[1],
> > > > > @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > > >         if (rc)
> > > > >                 return rc;
> > > > >         mt->has_64bit_mmio = true;
> > > > > +       mt->has_shared_mtime = false;
> > > > >
> > > > >         if (match->data) { /* SiFive CLINT */
> > > > >                 /* Set CLINT addresses */
> > > > > @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > > >                         mt->has_64bit_mmio = false;
> > > > >         }
> > > > >
> > > > > -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > > > > +       /* Check if MTIMER device has shared MTIME address */
> > > > > +       mt->has_shared_mtime = false;
> > > > > +       for (i = 0; i < mtimer_count; i++) {
> > > > > +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> > > > > +                       mt->has_shared_mtime = true;
> > > > > +                       break;
> > > > > +               }
> > > > > +       }
> > > > > +
> > > > > +       /* Initialize the MTIMER device */
> > > > > +       rc = aclint_mtimer_cold_init(mt, mt_reference);
> > > > >         if (rc)
> > > > >                 return rc;
> > > > >
> > > > > +       /*
> > > > > +        * Select first MTIMER device with no associated HARTs as
> > > > > +        * our reference MTIMER device
> > > > > +        */
> > > > > +       if (!mt->hart_count && !mt_reference) {
> > > > > +               mt_reference = mt;
> > > > > +               /*
> > > > > +                * Set reference for already propbed MTIMER devices
> > > > > +                * with non-shared MTIME
> > > > > +                */
> > > > > +               for (i = 0; i < mtimer_count; i++)
> > > > > +                       if (!mtimer[i].has_shared_mtime)
> > > > > +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> > > > > +       }
> > > > > +
> > > >
> > > > Is there a reason this is done after cold_init ?
> > >
> > > We should select a MTIMER device as reference only after it is
> > > successfully initialized by the cold_init(). This ensures that even the
> > > reference MTIMER device has gone through all sanity checks.
> >
> > Got it. Thanks.
> >
> > >
> > > Also, simply selecting the first successfully initialized MTIMER device is
> > > also not appropriate because we don't know how MTIMER devices are
> > > ordered in DT.
> > >
> > > For now, the strategy is to select a successfully initialized MTIMER
> > > device with hart_count = 0 as reference. In future, we might select
> >
> > Is this information documented somewhere ? The platform must have a
> > MTIMER device
> > with zero hart_count in order to get a reference.
>
> This is OpenSBI specific strategy. We can put comments in code if you
> want.
>

IMO, it should be in the docs. It should also say the below text about
this being a current strategy which
may change in future if a dedicated DT property is defined.

> >
> > Just for my understanding, when do we need multiple MTIMER devices
> > with zero hart count in multi-socket
> > scenarios ?
>
> If we define special DT properties in future for selecting a reference
> MTIMER device in a multi-socket or multi-die system then we don't
> need to MTIMER DT nodes with zero harts.
>
> The approach of selecting MTIMER devices with zero harts is
> temporary because I did not want to not define DT properties which
> are not immediately required.
>
> >
> > > optional DT property to help us select the reference MTIMER device.
> > >
> > > Regards,
> > > Anup
> > >
> > > >
> > > > > +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> > > > > +       if (!mt->hart_count)
> > > > > +               aclint_mtimer_sync(mt);
> > > > > +
> > > > >         mtimer_count++;
> > > > >         return 0;
> > > > >  }
> > > > > --
> > > > > 2.25.1
> > > > >
> > > > >
> > > > > --
> > > > > opensbi mailing list
> > > > > opensbi at lists.infradead.org
> > > > > http://lists.infradead.org/mailman/listinfo/opensbi
> > > >
> > > >
> > > > --
> > > > Regards,
> > > > Atish
> >
> > Other than that, this patch looks good to me.
> >
> > Reviewed-by: Atish Patra <atish.patra at wdc.com>
> >
> >
> > --
> > Regards,
> > Atish
>
> Regards,
> Anup



-- 
Regards,
Atish


From Dd_nirvana at sjtu.edu.cn  Fri Aug 13 05:33:00 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Fri, 13 Aug 2021 20:33:00 +0800
Subject: [PATCH] lib: sbi: Fix bug in sbi_ecall_rfence that misses checking
Message-ID: <20210813123300.26085-1-Dd_nirvana@sjtu.edu.cn>

In sbi_ecall_rfence_handler, it will compare the funcid with REMOTE_HFENCE_GVMA and
REMOTE_HFENCE_VVMA_ASID.
And then check whether the misa includes H-extension.
This checking is incomplete which misses REMOTE_HFENCE_GVMA_VMID and REMOTE_HFENCE_VVMA.
Fix the issue by updating the checking range.

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 lib/sbi/sbi_ecall_replace.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/sbi/sbi_ecall_replace.c b/lib/sbi/sbi_ecall_replace.c
index a7935d9..5d24565 100644
--- a/lib/sbi/sbi_ecall_replace.c
+++ b/lib/sbi/sbi_ecall_replace.c
@@ -54,8 +54,8 @@ static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid,
 	struct sbi_tlb_info tlb_info;
 	u32 source_hart = current_hartid();
 
-	if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA &&
-	    funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID)
+	if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID &&
+	    funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA)
 		if (!misa_extension('H'))
 			return SBI_ENOTSUPP;
 
-- 
2.31.1



From anup at brainfault.org  Fri Aug 13 20:44:17 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 14 Aug 2021 09:14:17 +0530
Subject: [PATCH v2 1/5] lib: utils/timer: Allow separate base addresses
 for MTIME and MTIMECMP
In-Reply-To: <20210807133322.545675-2-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-2-anup.patel@wdc.com>
Message-ID: <CAAhSdy1M65Q=jXEYiZz3Mf4bSJ1q+FrpdrnwN5YzwmvAeZi0SQ@mail.gmail.com>

On Sat, Aug 7, 2021 at 7:04 PM Anup Patel <anup.patel at wdc.com> wrote:
>
> We extend the ACLINT library to support separate base addresses
> for MTIME and MTIMECMP registers.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Regards,
Anup

> ---
>  include/sbi_utils/timer/aclint_mtimer.h | 16 +++--
>  lib/utils/timer/aclint_mtimer.c         | 78 +++++++++++++++++++------
>  lib/utils/timer/fdt_timer_mtimer.c      | 16 +++--
>  platform/fpga/ariane/platform.c         |  8 ++-
>  platform/fpga/openpiton/platform.c      | 13 ++++-
>  platform/kendryte/k210/platform.c       |  8 ++-
>  platform/nuclei/ux600/platform.c        |  8 ++-
>  platform/template/platform.c            |  8 ++-
>  8 files changed, 114 insertions(+), 41 deletions(-)
>
> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> index 62aa086..fdc46cd 100644
> --- a/include/sbi_utils/timer/aclint_mtimer.h
> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> @@ -12,16 +12,22 @@
>
>  #include <sbi/sbi_types.h>
>
> -#define ACLINT_MTIMER_ALIGN            0x1000
> -#define ACLINT_MTIMER_SIZE             0x8000
> -#define ACLINT_MTIMER_MAX_HARTS        4095
> +#define ACLINT_MTIMER_ALIGN            0x8
> +#define ACLINT_MTIMER_MAX_HARTS                4095
> +
> +#define ACLINT_DEFAULT_MTIME_OFFSET    0x7ff8
> +#define ACLINT_DEFAULT_MTIME_SIZE      0x8
> +#define ACLINT_DEFAULT_MTIMECMP_OFFSET 0x0000
> +#define ACLINT_DEFAULT_MTIMECMP_SIZE   0x7ff8
>
>  #define CLINT_MTIMER_OFFSET            0x4000
>
>  struct aclint_mtimer_data {
>         /* Public details */
> -       unsigned long addr;
> -       unsigned long size;
> +       unsigned long mtime_addr;
> +       unsigned long mtime_size;
> +       unsigned long mtimecmp_addr;
> +       unsigned long mtimecmp_size;
>         u32 first_hartid;
>         u32 hart_count;
>         bool has_64bit_mmio;
> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> index 41b0290..0e4e846 100644
> --- a/lib/utils/timer/aclint_mtimer.c
> +++ b/lib/utils/timer/aclint_mtimer.c
> @@ -10,6 +10,7 @@
>  #include <sbi/riscv_asm.h>
>  #include <sbi/riscv_atomic.h>
>  #include <sbi/riscv_io.h>
> +#include <sbi/sbi_bitops.h>
>  #include <sbi/sbi_domain.h>
>  #include <sbi/sbi_error.h>
>  #include <sbi/sbi_hartmask.h>
> @@ -17,9 +18,6 @@
>  #include <sbi/sbi_timer.h>
>  #include <sbi_utils/timer/aclint_mtimer.h>
>
> -#define MTIMER_CMP_OFF         0x0000
> -#define MTIMER_VAL_OFF         0x7ff8
> -
>  static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS];
>
>  #if __riscv_xlen != 32
> @@ -56,7 +54,7 @@ static void mtimer_time_wr32(bool timecmp, u64 value, volatile u64 *addr)
>  static u64 mtimer_value(void)
>  {
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[current_hartid()];
> -       u64 *time_val = ((void *)mt->addr) + MTIMER_VAL_OFF;
> +       u64 *time_val = (void *)mt->mtime_addr;
>
>         /* Read MTIMER Time Value */
>         return mt->time_rd(time_val) + mt->time_delta;
> @@ -66,7 +64,7 @@ static void mtimer_event_stop(void)
>  {
>         u32 target_hart = current_hartid();
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
>
>         /* Clear MTIMER Time Compare */
>         mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]);
> @@ -76,7 +74,7 @@ static void mtimer_event_start(u64 next_event)
>  {
>         u32 target_hart = current_hartid();
>         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> -       u64 *time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       u64 *time_cmp = (void *)mt->mtimecmp_addr;
>
>         /* Program MTIMER Time Compare */
>         mt->time_wr(true, next_event - mt->time_delta,
> @@ -111,8 +109,8 @@ int aclint_mtimer_warm_init(void)
>          */
>         if (mt->time_delta_reference) {
>                 reference = mt->time_delta_reference;
> -               mt_time_val = (void *)mt->addr + MTIMER_VAL_OFF;
> -               ref_time_val = (void *)reference->addr + MTIMER_VAL_OFF;
> +               mt_time_val = (void *)mt->mtime_addr;
> +               ref_time_val = (void *)reference->mtime_addr;
>                 if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
>                         v1 = mt->time_rd(mt_time_val);
>                         mv = reference->time_rd(ref_time_val);
> @@ -122,24 +120,54 @@ int aclint_mtimer_warm_init(void)
>         }
>
>         /* Clear Time Compare */
> -       mt_time_cmp = (void *)mt->addr + MTIMER_CMP_OFF;
> +       mt_time_cmp = (void *)mt->mtimecmp_addr;
>         mt->time_wr(true, -1ULL,
>                     &mt_time_cmp[target_hart - mt->first_hartid]);
>
>         return 0;
>  }
>
> +static int aclint_mtimer_add_regions(unsigned long addr, unsigned long size)
> +{
> +#define MTIMER_ADD_REGION_ALIGN                0x1000
> +       int rc;
> +       unsigned long pos, end, rsize;
> +       struct sbi_domain_memregion reg;
> +
> +       pos = addr;
> +       end = addr + size;
> +       while (pos < end) {
> +               rsize = pos & (MTIMER_ADD_REGION_ALIGN - 1);
> +               if (rsize)
> +                       rsize = 1UL << __ffs(pos);
> +               else
> +                       rsize = ((end - pos) < MTIMER_ADD_REGION_ALIGN) ?
> +                               (end - pos) : MTIMER_ADD_REGION_ALIGN;
> +
> +               sbi_domain_memregion_init(pos, rsize,
> +                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> +               rc = sbi_domain_root_add_memregion(&reg);
> +               if (rc)
> +                       return rc;
> +               pos += rsize;
> +       }
> +
> +       return 0;
> +}
> +
>  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>                             struct aclint_mtimer_data *reference)
>  {
>         u32 i;
>         int rc;
> -       unsigned long pos, region_size;
> -       struct sbi_domain_memregion reg;
>
>         /* Sanity checks */
> -       if (!mt || (mt->addr & (ACLINT_MTIMER_ALIGN - 1)) ||
> -           (mt->size < ACLINT_MTIMER_SIZE) ||
> +       if (!mt || !mt->mtime_size ||
> +           (mt->hart_count && !mt->mtimecmp_size) ||
> +           (mt->mtime_addr & (ACLINT_MTIMER_ALIGN - 1)) ||
> +           (mt->mtime_size & (ACLINT_MTIMER_ALIGN - 1)) ||
> +           (mt->mtimecmp_addr & (ACLINT_MTIMER_ALIGN - 1)) ||
> +           (mt->mtimecmp_size & (ACLINT_MTIMER_ALIGN - 1)) ||
>             (mt->first_hartid >= SBI_HARTMASK_MAX_BITS) ||
>             (mt->hart_count > ACLINT_MTIMER_MAX_HARTS))
>                 return SBI_EINVAL;
> @@ -164,12 +192,24 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>                 mtimer_hartid2data[mt->first_hartid + i] = mt;
>
>         /* Add MTIMER regions to the root domain */
> -       for (pos = 0; pos < mt->size; pos += ACLINT_MTIMER_ALIGN) {
> -               region_size = ((mt->size - pos) < ACLINT_MTIMER_ALIGN) ?
> -                             (mt->size - pos) : ACLINT_MTIMER_ALIGN;
> -               sbi_domain_memregion_init(mt->addr + pos, region_size,
> -                                         SBI_DOMAIN_MEMREGION_MMIO, &reg);
> -               rc = sbi_domain_root_add_memregion(&reg);
> +       if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) {
> +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> +                                       mt->mtime_size + mt->mtimecmp_size);
> +               if (rc)
> +                       return rc;
> +       } else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) {
> +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> +                                       mt->mtime_size + mt->mtimecmp_size);
> +               if (rc)
> +                       return rc;
> +       } else {
> +               rc = aclint_mtimer_add_regions(mt->mtime_addr,
> +                                               mt->mtime_size);
> +               if (rc)
> +                       return rc;
> +
> +               rc = aclint_mtimer_add_regions(mt->mtimecmp_addr,
> +                                               mt->mtimecmp_size);
>                 if (rc)
>                         return rc;
>         }
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 4907428..3f830ad 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
>         int rc;
> -       unsigned long offset;
> +       unsigned long offset, addr, size;
>         struct aclint_mtimer_data *mt, *mtmaster = NULL;
>
>         if (MTIMER_MAX_NR <= mtimer_count)
> @@ -31,19 +31,23 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>         if (0 < mtimer_count)
>                 mtmaster = &mtimer[0];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &mt->addr, &mt->size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
>                                    &mt->first_hartid, &mt->hart_count);
>         if (rc)
>                 return rc;
>         mt->has_64bit_mmio = true;
>
> +       mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> +       mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> +       mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
> +       mt->mtime_size = size - mt->mtimecmp_size;
> +
>         if (match->data) {
>                 /* Adjust MTIMER address and size for CLINT device */
>                 offset = *((unsigned long *)match->data);
> -               mt->addr += offset;
> -               if ((mt->size - offset) < ACLINT_MTIMER_SIZE)
> -                       return SBI_EINVAL;
> -               mt->size -= offset;
> +               mt->mtime_addr += offset;
> +               mt->mtimecmp_addr += offset;
> +               mt->mtime_size -= offset;
>                 /* Parse additional CLINT properties */
>                 if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
>                         mt->has_64bit_mmio = false;
> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
> index 0b47aa0..58a46c0 100644
> --- a/platform/fpga/ariane/platform.c
> +++ b/platform/fpga/ariane/platform.c
> @@ -44,8 +44,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = ARIANE_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = ARIANE_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = ARIANE_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index 6939b57..a9bfa99 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -49,8 +49,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> @@ -82,7 +86,10 @@ static int openpiton_early_init(bool cold_boot)
>         rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0");
>         if (!rc) {
>                 mswi.addr = clint_addr;
> -               mtimer.addr = clint_addr + CLINT_MTIMER_OFFSET;
> +               mtimer.mtime_addr = clint_addr + CLINT_MTIMER_OFFSET +
> +                                   ACLINT_DEFAULT_MTIME_OFFSET;
> +               mtimer.mtimecmp_addr = clint_addr + CLINT_MTIMER_OFFSET +
> +                                   ACLINT_DEFAULT_MTIMECMP_OFFSET;
>         }
>
>         return 0;
> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
> index 55c4b1e..ee4c223 100644
> --- a/platform/kendryte/k210/platform.c
> +++ b/platform/kendryte/k210/platform.c
> @@ -42,8 +42,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = K210_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = K210_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = K210_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
> index 22ca4c9..ab0becc 100644
> --- a/platform/nuclei/ux600/platform.c
> +++ b/platform/nuclei/ux600/platform.c
> @@ -74,8 +74,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = UX600_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = UX600_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = UX600_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> diff --git a/platform/template/platform.c b/platform/template/platform.c
> index 3f09d98..4528822 100644
> --- a/platform/template/platform.c
> +++ b/platform/template/platform.c
> @@ -43,8 +43,12 @@ static struct aclint_mswi_data mswi = {
>  };
>
>  static struct aclint_mtimer_data mtimer = {
> -       .addr = PLATFORM_ACLINT_MTIMER_ADDR,
> -       .size = ACLINT_MTIMER_SIZE,
> +       .mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> +                     ACLINT_DEFAULT_MTIME_OFFSET,
> +       .mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
> +       .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> +                        ACLINT_DEFAULT_MTIMECMP_OFFSET,
> +       .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>         .first_hartid = 0,
>         .hart_count = PLATFORM_HART_COUNT,
>         .has_64bit_mmio = TRUE,
> --
> 2.25.1
>


From anup at brainfault.org  Fri Aug 13 20:48:46 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 14 Aug 2021 09:18:46 +0530
Subject: [PATCH v2 2/5] lib: utils: Extend fdt_get_node_addr_size() for
 multiple register sets
In-Reply-To: <20210807133322.545675-3-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-3-anup.patel@wdc.com>
Message-ID: <CAAhSdy0WeV_vLMdJRUA8PMLRVoiXH386NNdaQDj9fBOtU4qq=Q@mail.gmail.com>

On Sat, Aug 7, 2021 at 7:04 PM Anup Patel <anup.patel at wdc.com> wrote:
>
> We add "index" parameter to fdt_get_node_addr_size() API so that
> calling function can specify index of desired register set. This
> will allow fdt_get_node_addr_size() to handle DT nodes with
> multiple register sets.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Regards,
Anup

> ---
>  include/sbi_utils/fdt/fdt_helper.h      |  4 ++--
>  lib/utils/fdt/fdt_helper.c              | 31 ++++++++++++++++++-------
>  lib/utils/gpio/fdt_gpio_sifive.c        |  2 +-
>  lib/utils/reset/fdt_reset_sifive_test.c |  2 +-
>  4 files changed, 27 insertions(+), 12 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 32aebb4..1a93e1c 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -43,8 +43,8 @@ int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
>                                 const char *prop, const char *cells_prop,
>                                 int index, struct fdt_phandle_args *out_args);
>
> -int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr,
> -                          uint64_t *size);
> +int fdt_get_node_addr_size(void *fdt, int node, int index,
> +                          uint64_t *addr, uint64_t *size);
>
>  int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
>
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index a27f5ba..b68544f 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -157,13 +157,17 @@ static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
>         return 0;
>  }
>
> -int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
> +int fdt_get_node_addr_size(void *fdt, int node, int index,
> +                          uint64_t *addr, uint64_t *size)
>  {
>         int parent, len, i, rc;
>         int cell_addr, cell_size;
>         const fdt32_t *prop_addr, *prop_size;
>         uint64_t temp = 0;
>
> +       if (!fdt || node < 0 || index < 0)
> +               return SBI_EINVAL;
> +
>         parent = fdt_parent_offset(fdt, node);
>         if (parent < 0)
>                 return parent;
> @@ -178,6 +182,11 @@ int fdt_get_node_addr_size(void *fdt, int node, uint64_t *addr, uint64_t *size)
>         prop_addr = fdt_getprop(fdt, node, "reg", &len);
>         if (!prop_addr)
>                 return SBI_ENODEV;
> +
> +       if ((len / sizeof(u32)) <= (index * (cell_addr + cell_size)))
> +               return SBI_EINVAL;
> +
> +       prop_addr = prop_addr + (index * (cell_addr + cell_size));
>         prop_size = prop_addr + cell_addr;
>
>         if (addr) {
> @@ -270,7 +279,8 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -308,7 +318,8 @@ int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -342,7 +353,8 @@ int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -380,7 +392,8 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
>         if (nodeoffset < 0 || !uart || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         uart->addr = reg_addr;
> @@ -440,7 +453,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
>         if (nodeoffset < 0 || !plic || !fdt)
>                 return SBI_ENODEV;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         plic->addr = reg_addr;
> @@ -481,7 +495,8 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>             !out_first_hartid || !out_hart_count)
>                 return SBI_EINVAL;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, &reg_addr, &reg_size);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
> +                                   &reg_addr, &reg_size);
>         if (rc < 0 || !reg_addr || !reg_size)
>                 return SBI_ENODEV;
>         *out_addr = reg_addr;
> @@ -543,7 +558,7 @@ int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
>         if (nodeoffset < 0)
>                 return nodeoffset;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoffset, addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, addr, NULL);
>         if (rc < 0 || !addr)
>                 return SBI_ENODEV;
>
> diff --git a/lib/utils/gpio/fdt_gpio_sifive.c b/lib/utils/gpio/fdt_gpio_sifive.c
> index 00d3e14..677f0fa 100644
> --- a/lib/utils/gpio/fdt_gpio_sifive.c
> +++ b/lib/utils/gpio/fdt_gpio_sifive.c
> @@ -77,7 +77,7 @@ static int sifive_gpio_init(void *fdt, int nodeoff, u32 phandle,
>                 return SBI_ENOSPC;
>         chip = &sifive_gpio_chip_array[sifive_gpio_chip_count];
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
>         if (rc)
>                 return rc;
>
> diff --git a/lib/utils/reset/fdt_reset_sifive_test.c b/lib/utils/reset/fdt_reset_sifive_test.c
> index b0b59e7..7e0eba3 100644
> --- a/lib/utils/reset/fdt_reset_sifive_test.c
> +++ b/lib/utils/reset/fdt_reset_sifive_test.c
> @@ -18,7 +18,7 @@ static int sifive_test_reset_init(void *fdt, int nodeoff,
>         int rc;
>         uint64_t addr;
>
> -       rc = fdt_get_node_addr_size(fdt, nodeoff, &addr, NULL);
> +       rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
>         if (rc)
>                 return rc;
>
> --
> 2.25.1
>


From anup at brainfault.org  Fri Aug 13 20:50:22 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 14 Aug 2021 09:20:22 +0530
Subject: [PATCH v2 3/5] lib: utils/fdt: Extend fdt_parse_aclint_node()
 function
In-Reply-To: <20210807133322.545675-4-anup.patel@wdc.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-4-anup.patel@wdc.com>
Message-ID: <CAAhSdy0UZFzMxWzKt+2KVmDWz0KvEzAc47nXCpC99shaBD5AnQ@mail.gmail.com>

On Sat, Aug 7, 2021 at 7:04 PM Anup Patel <anup.patel at wdc.com> wrote:
>
> The fdt_parse_aclint_node() is used to parse DT node for SiFive
> CLINT, ACLINT MTIMER, and ACLINT MSWI devices.
>
> The ACLINT MTIMER has undergone following changes:
> 1) MTIMER DT node now requires separate addresses in for MTIME
>    register and MTIMECMPx registers in the reg DT property.
> 2) MTIMER DT node might have no interrupts-extended DT property
>    when the MTIMER device has no associated HARTs (i.e. the
>    MTIMER device has no MTIMECMPx registers)
>
> This patch extends fdt_parse_aclint_node() to handle above
> mentioned changes in ACLINT MTIMER DT bindings.
>
> Signed-off-by: Anup Patel <anup.patel at wdc.com>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Regards,
Anup

> ---
>  include/sbi_utils/fdt/fdt_helper.h |  3 +-
>  lib/utils/fdt/fdt_helper.c         | 50 ++++++++++++++++++------------
>  lib/utils/ipi/fdt_ipi_mswi.c       |  3 +-
>  lib/utils/timer/fdt_timer_mtimer.c | 23 +++++++++-----
>  4 files changed, 49 insertions(+), 30 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 1a93e1c..2246254 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -72,7 +72,8 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
>  int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
>
>  int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
> -                         unsigned long *out_addr, unsigned long *out_size,
> +                         unsigned long *out_addr1, unsigned long *out_size1,
> +                         unsigned long *out_addr2, unsigned long *out_size2,
>                           u32 *out_first_hartid, u32 *out_hart_count);
>
>  int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index b68544f..5628337 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -481,38 +481,50 @@ int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat)
>  }
>
>  int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
> -                         unsigned long *out_addr, unsigned long *out_size,
> +                         unsigned long *out_addr1, unsigned long *out_size1,
> +                         unsigned long *out_addr2, unsigned long *out_size2,
>                           u32 *out_first_hartid, u32 *out_hart_count)
>  {
>         const fdt32_t *val;
>         uint64_t reg_addr, reg_size;
>         int i, rc, count, cpu_offset, cpu_intc_offset;
> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid;
> +       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
>
>         if (nodeoffset < 0 || !fdt ||
> -           !out_addr || !out_size ||
> +           !out_addr1 || !out_size1 ||
>             !out_first_hartid || !out_hart_count)
>                 return SBI_EINVAL;
>
>         rc = fdt_get_node_addr_size(fdt, nodeoffset, 0,
>                                     &reg_addr, &reg_size);
> -       if (rc < 0 || !reg_addr || !reg_size)
> +       if (rc < 0 || !reg_size)
>                 return SBI_ENODEV;
> -       *out_addr = reg_addr;
> -       *out_size = reg_size;
> +       *out_addr1 = reg_addr;
> +       *out_size1 = reg_size;
> +
> +       rc = fdt_get_node_addr_size(fdt, nodeoffset, 1,
> +                                   &reg_addr, &reg_size);
> +       if (rc < 0 || !reg_size)
> +               reg_addr = reg_size = 0;
> +       if (out_addr2)
> +               *out_addr2 = reg_addr;
> +       if (out_size2)
> +               *out_size2 = reg_size;
> +
> +       *out_first_hartid = 0;
> +       *out_hart_count = 0;
>
>         val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count);
>         if (!val || count < sizeof(fdt32_t))
> -               return SBI_ENODEV;
> +               return 0;
>         count = count / sizeof(fdt32_t);
>
>         first_hartid = -1U;
> -       last_hartid = 0;
> -       *out_hart_count = 0;
> -       for (i = 0; i < count; i += 2) {
> -               phandle = fdt32_to_cpu(val[i]);
> -               hwirq = fdt32_to_cpu(val[i + 1]);
> +       hart_count = last_hartid = 0;
> +       for (i = 0; i < (count / 2); i++) {
> +               phandle = fdt32_to_cpu(val[2 * i]);
> +               hwirq = fdt32_to_cpu(val[(2 * i) + 1]);
>
>                 cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
>                 if (cpu_intc_offset < 0)
> @@ -534,17 +546,15 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,
>                                 first_hartid = hartid;
>                         if (hartid > last_hartid)
>                                 last_hartid = hartid;
> -                       (*out_hart_count)++;
> +                       hart_count++;
>                 }
>         }
>
> -       if ((last_hartid < first_hartid) || first_hartid == -1U)
> -               return SBI_ENODEV;
> -
> -       *out_first_hartid = first_hartid;
> -       count = last_hartid - first_hartid + 1;
> -       if (*out_hart_count < count)
> -               *out_hart_count = count;
> +       if ((last_hartid >= first_hartid) && first_hartid != -1U) {
> +               *out_first_hartid = first_hartid;
> +               count = last_hartid - first_hartid + 1;
> +               *out_hart_count = (hart_count < count) ? hart_count : count;
> +       }
>
>         return 0;
>  }
> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
> index f119f9c..1f0fda7 100644
> --- a/lib/utils/ipi/fdt_ipi_mswi.c
> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
> @@ -28,7 +28,8 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
>                 return SBI_ENOSPC;
>         ms = &mswi[mswi_count];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, false, &ms->addr, &ms->size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, false,
> +                                  &ms->addr, &ms->size, NULL, NULL,
>                                    &ms->first_hartid, &ms->hart_count);
>         if (rc)
>                 return rc;
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 3f830ad..b08ed38 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -22,7 +22,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                                   const struct fdt_match *match)
>  {
>         int rc;
> -       unsigned long offset, addr, size;
> +       unsigned long offset, addr[2], size[2];
>         struct aclint_mtimer_data *mt, *mtmaster = NULL;
>
>         if (MTIMER_MAX_NR <= mtimer_count)
> @@ -31,18 +31,19 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>         if (0 < mtimer_count)
>                 mtmaster = &mtimer[0];
>
> -       rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr, &size,
> +       rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> +                                  &addr[0], &size[0], &addr[1], &size[1],
>                                    &mt->first_hartid, &mt->hart_count);
>         if (rc)
>                 return rc;
>         mt->has_64bit_mmio = true;
>
> -       mt->mtimecmp_addr = addr + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> -       mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> -       mt->mtime_addr = addr + ACLINT_DEFAULT_MTIME_OFFSET;
> -       mt->mtime_size = size - mt->mtimecmp_size;
> -
> -       if (match->data) {
> +       if (match->data) { /* SiFive CLINT */
> +               /* Set CLINT addresses */
> +               mt->mtimecmp_addr = addr[0] + ACLINT_DEFAULT_MTIMECMP_OFFSET;
> +               mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE;
> +               mt->mtime_addr = addr[0] + ACLINT_DEFAULT_MTIME_OFFSET;
> +               mt->mtime_size = size[0] - mt->mtimecmp_size;
>                 /* Adjust MTIMER address and size for CLINT device */
>                 offset = *((unsigned long *)match->data);
>                 mt->mtime_addr += offset;
> @@ -51,6 +52,12 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>                 /* Parse additional CLINT properties */
>                 if (fdt_getprop(fdt, nodeoff, "clint,has-no-64bit-mmio", &rc))
>                         mt->has_64bit_mmio = false;
> +       } else { /* RISC-V ACLINT MTIMER */
> +               /* Set ACLINT MTIMER addresses */
> +               mt->mtime_addr = addr[0];
> +               mt->mtime_size = size[0];
> +               mt->mtimecmp_addr = addr[1];
> +               mt->mtimecmp_size = size[1];
>         }
>
>         rc = aclint_mtimer_cold_init(mt, mtmaster);
> --
> 2.25.1
>


From anup at brainfault.org  Fri Aug 13 20:50:51 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 14 Aug 2021 09:20:51 +0530
Subject: [PATCH v2 4/5] lib: utils/timer: Allow ACLINT MTIMER supporting
 only 32-bit MMIO
In-Reply-To: <CAOnJCUKht+Wjw05KO3FNVNS4ND8HLXWrc+i0pYCws2_ZnaupYw@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-5-anup.patel@wdc.com>
 <CAOnJCUKht+Wjw05KO3FNVNS4ND8HLXWrc+i0pYCws2_ZnaupYw@mail.gmail.com>
Message-ID: <CAAhSdy2_+z9+=QaeY+bc9+uV-+iYkj-psmBmH85MBkTBXRvw+Q@mail.gmail.com>

On Wed, Aug 11, 2021 at 9:58 PM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> >
> > We can have ACLINT MTIMER devices which only support 32-bit MMIO
> > accesses on RV64 system so this patch adds a boolean DT property
> > "mtimer,no-64bit-mmio" to detect this from MTIMER DT node.
> >
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > ---
> >  lib/utils/timer/fdt_timer_mtimer.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > index b08ed38..15a36ed 100644
> > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > @@ -58,6 +58,9 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >                 mt->mtime_size = size[0];
> >                 mt->mtimecmp_addr = addr[1];
> >                 mt->mtimecmp_size = size[1];
> > +               /* Parse additional ACLINT MTIMER properties */
> > +               if (fdt_getprop(fdt, nodeoff, "mtimer,no-64bit-mmio", &rc))
> > +                       mt->has_64bit_mmio = false;
> >         }
> >
> >         rc = aclint_mtimer_cold_init(mt, mtmaster);
> > --
> > 2.25.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Regards,
Anup

>
> --
> Regards,
> Atish


From anup at brainfault.org  Fri Aug 13 20:52:22 2021
From: anup at brainfault.org (Anup Patel)
Date: Sat, 14 Aug 2021 09:22:22 +0530
Subject: [PATCH v2 5/5] lib: utils/timer: Simplify MTIMER synchronization
In-Reply-To: <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>
References: <20210807133322.545675-1-anup.patel@wdc.com>
 <20210807133322.545675-6-anup.patel@wdc.com>
 <CAOnJCUJrAmB53o_rYX8Oam2T7D37cb24GX07K5FiJU8--UcVCA@mail.gmail.com>
 <CAAhSdy0LJHPy5smQp1zrmCMzWM=J_YWTysx7unC6WTMrQ81rHQ@mail.gmail.com>
 <CAOnJCUK6dCSDHaVhmh7KJ_W70CB34goAy7gWgTfePSDKKma96w@mail.gmail.com>
Message-ID: <CAAhSdy12nTod_ZtX-tZvnq+0QpuNnq6JNpmy8nt1SEOM0VHciQ@mail.gmail.com>

On Thu, Aug 12, 2021 at 8:39 PM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Wed, Aug 11, 2021 at 9:19 PM Anup Patel <anup at brainfault.org> wrote:
> >
> > On Thu, Aug 12, 2021 at 2:37 AM Atish Patra <atishp at atishpatra.org> wrote:
> > >
> > > On Sat, Aug 7, 2021 at 6:34 AM Anup Patel <anup.patel at wdc.com> wrote:
> > > >
> > > > We simplify MTIMER synchronization as follows:
> > > >
> > > > 1) Detect MTIMER devices with unique (or non-shared) MTIME
> > > >    register at boot-time
> > > > 2) Select first MTIMER device with no associated HART as our
> > > >    reference MTIMER device
> > > > 3) Only synchronize MTIMER devices with unique (or non-shared)
> > > >    MTIME register using reference MTIMER device
> > > > 4) Directly update the MTIME register at time of synchronization
> > > >    because MTIME is a read/write register.
> > > >
> > > > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > > > ---
> > > >  include/sbi_utils/timer/aclint_mtimer.h |  7 ++-
> > > >  lib/utils/timer/aclint_mtimer.c         | 67 +++++++++++++++----------
> > > >  lib/utils/timer/fdt_timer_mtimer.c      | 39 ++++++++++++--
> > > >  3 files changed, 80 insertions(+), 33 deletions(-)
> > > >
> > > > diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> > > > index fdc46cd..a9fe445 100644
> > > > --- a/include/sbi_utils/timer/aclint_mtimer.h
> > > > +++ b/include/sbi_utils/timer/aclint_mtimer.h
> > > > @@ -31,14 +31,19 @@ struct aclint_mtimer_data {
> > > >         u32 first_hartid;
> > > >         u32 hart_count;
> > > >         bool has_64bit_mmio;
> > > > +       bool has_shared_mtime;
> > > >         /* Private details (initialized and used by ACLINT MTIMER library) */
> > > >         struct aclint_mtimer_data *time_delta_reference;
> > > >         unsigned long time_delta_computed;
> > > > -       u64 time_delta;
> > > >         u64 (*time_rd)(volatile u64 *addr);
> > > >         void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
> > > >  };
> > > >
> > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
> > > > +
> > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > +                                struct aclint_mtimer_data *ref);
> > > > +
> > > >  int aclint_mtimer_warm_init(void);
> > > >
> > > >  int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > > diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> > > > index 0e4e846..d612b12 100644
> > > > --- a/lib/utils/timer/aclint_mtimer.c
> > > > +++ b/lib/utils/timer/aclint_mtimer.c
> > > > @@ -57,7 +57,7 @@ static u64 mtimer_value(void)
> > > >         u64 *time_val = (void *)mt->mtime_addr;
> > > >
> > > >         /* Read MTIMER Time Value */
> > > > -       return mt->time_rd(time_val) + mt->time_delta;
> > > > +       return mt->time_rd(time_val);
> > > >  }
> > > >
> > > >  static void mtimer_event_stop(void)
> > > > @@ -77,7 +77,7 @@ static void mtimer_event_start(u64 next_event)
> > > >         u64 *time_cmp = (void *)mt->mtimecmp_addr;
> > > >
> > > >         /* Program MTIMER Time Compare */
> > > > -       mt->time_wr(true, next_event - mt->time_delta,
> > > > +       mt->time_wr(true, next_event,
> > > >                     &time_cmp[target_hart - mt->first_hartid]);
> > > >  }
> > > >
> > > > @@ -88,36 +88,51 @@ static struct sbi_timer_device mtimer = {
> > > >         .timer_event_stop = mtimer_event_stop
> > > >  };
> > > >
> > > > +void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
> > > > +{
> > > > +       u64 v1, v2, mv, delta;
> > > > +       u64 *mt_time_val, *ref_time_val;
> > > > +       struct aclint_mtimer_data *reference;
> > > > +
> > > > +       /* Sync-up non-shared MTIME if reference is available */
> > > > +       if (mt->has_shared_mtime || !mt->time_delta_reference)
> > > > +               return;
> > > > +
> > > > +       reference = mt->time_delta_reference;
> > > > +       mt_time_val = (void *)mt->mtime_addr;
> > > > +       ref_time_val = (void *)reference->mtime_addr;
> > > > +       if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > +               v1 = mt->time_rd(mt_time_val);
> > > > +               mv = reference->time_rd(ref_time_val);
> > > > +               v2 = mt->time_rd(mt_time_val);
> > > > +               delta = mv - ((v1 / 2) + (v2 / 2));
> > > > +               mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
> > > > +                           mt_time_val);
> > > > +       }
> > > > +
> > > > +}
> > > > +
> > > > +void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
> > > > +                                struct aclint_mtimer_data *ref)
> > > > +{
> > > > +       if (!mt || !ref || mt == ref)
> > > > +               return;
> > > > +
> > > > +       mt->time_delta_reference = ref;
> > > > +       mt->time_delta_computed = 0;
> > > > +}
> > > > +
> > > >  int aclint_mtimer_warm_init(void)
> > > >  {
> > > > -       u64 v1, v2, mv;
> > > > +       u64 *mt_time_cmp;
> > > >         u32 target_hart = current_hartid();
> > > > -       struct aclint_mtimer_data *reference;
> > > > -       u64 *mt_time_val, *mt_time_cmp, *ref_time_val;
> > > >         struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
> > > >
> > > >         if (!mt)
> > > >                 return SBI_ENODEV;
> > > >
> > > > -       /*
> > > > -        * Compute delta if reference available
> > > > -        *
> > > > -        * We deliberately compute time_delta in warm init so that time_delta
> > > > -        * is computed on a HART which is going to use given MTIMER. We use
> > > > -        * atomic flag timer_delta_computed to ensure that only one HART does
> > > > -        * time_delta computation.
> > > > -        */
> > > > -       if (mt->time_delta_reference) {
> > > > -               reference = mt->time_delta_reference;
> > > > -               mt_time_val = (void *)mt->mtime_addr;
> > > > -               ref_time_val = (void *)reference->mtime_addr;
> > > > -               if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
> > > > -                       v1 = mt->time_rd(mt_time_val);
> > > > -                       mv = reference->time_rd(ref_time_val);
> > > > -                       v2 = mt->time_rd(mt_time_val);
> > > > -                       mt->time_delta = mv - ((v1 / 2) + (v2 / 2));
> > > > -               }
> > > > -       }
> > > > +       /* Sync-up MTIME register */
> > > > +       aclint_mtimer_sync(mt);
> > > >
> > > >         /* Clear Time Compare */
> > > >         mt_time_cmp = (void *)mt->mtimecmp_addr;
> > > > @@ -173,9 +188,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> > > >                 return SBI_EINVAL;
> > > >
> > > >         /* Initialize private data */
> > > > -       mt->time_delta_reference = reference;
> > > > -       mt->time_delta_computed = 0;
> > > > -       mt->time_delta = 0;
> > > > +       aclint_mtimer_set_reference(mt, reference);
> > > >         mt->time_rd = mtimer_time_rd32;
> > > >         mt->time_wr = mtimer_time_wr32;
> > > >
> > > > diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> > > > index 15a36ed..26b5a2a 100644
> > > > --- a/lib/utils/timer/fdt_timer_mtimer.c
> > > > +++ b/lib/utils/timer/fdt_timer_mtimer.c
> > > > @@ -17,19 +17,18 @@
> > > >
> > > >  static unsigned long mtimer_count = 0;
> > > >  static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR];
> > > > +static struct aclint_mtimer_data *mt_reference = NULL;
> > > >
> > > >  static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >                                   const struct fdt_match *match)
> > > >  {
> > > > -       int rc;
> > > > +       int i, rc;
> > > >         unsigned long offset, addr[2], size[2];
> > > > -       struct aclint_mtimer_data *mt, *mtmaster = NULL;
> > > > +       struct aclint_mtimer_data *mt;
> > > >
> > > >         if (MTIMER_MAX_NR <= mtimer_count)
> > > >                 return SBI_ENOSPC;
> > > >         mt = &mtimer[mtimer_count];
> > > > -       if (0 < mtimer_count)
> > > > -               mtmaster = &mtimer[0];
> > > >
> > > >         rc = fdt_parse_aclint_node(fdt, nodeoff, true,
> > > >                                    &addr[0], &size[0], &addr[1], &size[1],
> > > > @@ -37,6 +36,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >         if (rc)
> > > >                 return rc;
> > > >         mt->has_64bit_mmio = true;
> > > > +       mt->has_shared_mtime = false;
> > > >
> > > >         if (match->data) { /* SiFive CLINT */
> > > >                 /* Set CLINT addresses */
> > > > @@ -63,10 +63,39 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> > > >                         mt->has_64bit_mmio = false;
> > > >         }
> > > >
> > > > -       rc = aclint_mtimer_cold_init(mt, mtmaster);
> > > > +       /* Check if MTIMER device has shared MTIME address */
> > > > +       mt->has_shared_mtime = false;
> > > > +       for (i = 0; i < mtimer_count; i++) {
> > > > +               if (mtimer[i].mtime_addr == mt->mtime_addr) {
> > > > +                       mt->has_shared_mtime = true;
> > > > +                       break;
> > > > +               }
> > > > +       }
> > > > +
> > > > +       /* Initialize the MTIMER device */
> > > > +       rc = aclint_mtimer_cold_init(mt, mt_reference);
> > > >         if (rc)
> > > >                 return rc;
> > > >
> > > > +       /*
> > > > +        * Select first MTIMER device with no associated HARTs as
> > > > +        * our reference MTIMER device
> > > > +        */
> > > > +       if (!mt->hart_count && !mt_reference) {
> > > > +               mt_reference = mt;
> > > > +               /*
> > > > +                * Set reference for already propbed MTIMER devices
> > > > +                * with non-shared MTIME
> > > > +                */
> > > > +               for (i = 0; i < mtimer_count; i++)
> > > > +                       if (!mtimer[i].has_shared_mtime)
> > > > +                               aclint_mtimer_set_reference(&mtimer[i], mt);
> > > > +       }
> > > > +
> > >
> > > Is there a reason this is done after cold_init ?
> >
> > We should select a MTIMER device as reference only after it is
> > successfully initialized by the cold_init(). This ensures that even the
> > reference MTIMER device has gone through all sanity checks.
>
> Got it. Thanks.
>
> >
> > Also, simply selecting the first successfully initialized MTIMER device is
> > also not appropriate because we don't know how MTIMER devices are
> > ordered in DT.
> >
> > For now, the strategy is to select a successfully initialized MTIMER
> > device with hart_count = 0 as reference. In future, we might select
>
> Is this information documented somewhere ? The platform must have a
> MTIMER device
> with zero hart_count in order to get a reference.
>
> Just for my understanding, when do we need multiple MTIMER devices
> with zero hart count in multi-socket
> scenarios ?
>
> > optional DT property to help us select the reference MTIMER device.
> >
> > Regards,
> > Anup
> >
> > >
> > > > +       /* Explicitly sync-up MTIMER devices not associated with any HARTs */
> > > > +       if (!mt->hart_count)
> > > > +               aclint_mtimer_sync(mt);
> > > > +
> > > >         mtimer_count++;
> > > >         return 0;
> > > >  }
> > > > --
> > > > 2.25.1
> > > >
> > > >
> > > > --
> > > > opensbi mailing list
> > > > opensbi at lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/opensbi
> > >
> > >
> > > --
> > > Regards,
> > > Atish
>
> Other than that, this patch looks good to me.
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>
>

I have added a more detailed comment in fdt_timer_mtimer.c
based on our discussion here.

Applied this patch to the riscv/opensbi repo.

Regards,
Anup

>
> --
> Regards,
> Atish


From samuel at sholland.org  Sat Aug 14 06:41:47 2021
From: samuel at sholland.org (Samuel Holland)
Date: Sat, 14 Aug 2021 08:41:47 -0500
Subject: [PATCH] lib: sbi_trap: Restore redirect for access faults
Message-ID: <20210814134147.14056-1-samuel@sholland.org>

commit 764a17d852a8 ("lib: sbi: Implement firmware counters") added
switch cases for CAUSE_LOAD_ACCESS and CAUSE_STORE_ACCESS. This caused
them to stop being redirected to U or S mode, as that is handled in the
default switch case. As a result, an error in userspace could cause the
system to hang. Fix this by allowing the acces fault case to fall
through to the default case.

Signed-off-by: Samuel Holland <samuel at sholland.org>
---
 lib/sbi/sbi_trap.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index 5781fea..8d20e04 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -259,11 +259,10 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
 		msg = "ecall handler failed";
 		break;
 	case CAUSE_LOAD_ACCESS:
-		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD);
-		break;
 	case CAUSE_STORE_ACCESS:
-		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE);
-		break;
+		sbi_pmu_ctr_incr_fw(mcause == CAUSE_LOAD_ACCESS ?
+			SBI_PMU_FW_ACCESS_LOAD : SBI_PMU_FW_ACCESS_STORE);
+		/* fallthrough */
 	default:
 		/* If the trap came from S or U mode, redirect it there */
 		trap.epc = regs->mepc;
-- 
2.31.1



From samuel at sholland.org  Sat Aug 14 06:52:10 2021
From: samuel at sholland.org (Samuel Holland)
Date: Sat, 14 Aug 2021 08:52:10 -0500
Subject: [PATCH] payloads/test: Add support for SBI v0.2 ecalls
Message-ID: <20210814135210.17729-1-samuel@sholland.org>

It can be useful to make SBI v0.2 or newer ecalls from this payload
for testing purposes. To support this, convert the macros to use the
extension/function parameter convention.

Signed-off-by: Samuel Holland <samuel at sholland.org>
---
 firmware/payloads/test_main.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
index 0d65930..ae2ed4f 100644
--- a/firmware/payloads/test_main.c
+++ b/firmware/payloads/test_main.c
@@ -9,24 +9,25 @@
 
 #include <sbi/sbi_ecall_interface.h>
 
-#define SBI_ECALL(__num, __a0, __a1, __a2)                                    \
+#define SBI_ECALL(__eid, __fid, __a0, __a1, __a2)                             \
 	({                                                                    \
 		register unsigned long a0 asm("a0") = (unsigned long)(__a0);  \
 		register unsigned long a1 asm("a1") = (unsigned long)(__a1);  \
 		register unsigned long a2 asm("a2") = (unsigned long)(__a2);  \
-		register unsigned long a7 asm("a7") = (unsigned long)(__num); \
+		register unsigned long a6 asm("a6") = (unsigned long)(__fid); \
+		register unsigned long a7 asm("a7") = (unsigned long)(__eid); \
 		asm volatile("ecall"                                          \
 			     : "+r"(a0)                                       \
-			     : "r"(a1), "r"(a2), "r"(a7)                      \
+			     : "r"(a1), "r"(a2), "r"(a6), "r"(a7)             \
 			     : "memory");                                     \
 		a0;                                                           \
 	})
 
-#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
-#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
-#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
+#define SBI_ECALL_0(__eid, __fid) SBI_ECALL(__eid, __fid, 0, 0, 0)
+#define SBI_ECALL_1(__eid, __fid, __a0) SBI_ECALL(__eid, __fid, __a0, 0, 0)
+#define SBI_ECALL_2(__eid, __fid, __a0, __a1) SBI_ECALL(__eid, __fid, __a0, __a1, 0)
 
-#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, (c))
+#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, (c))
 
 static inline void sbi_ecall_console_puts(const char *str)
 {
-- 
2.31.1



From atishp at atishpatra.org  Mon Aug 16 17:06:37 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 16 Aug 2021 17:06:37 -0700
Subject: [PATCH] lib: sbi_trap: Restore redirect for access faults
In-Reply-To: <20210814134147.14056-1-samuel@sholland.org>
References: <20210814134147.14056-1-samuel@sholland.org>
Message-ID: <CAOnJCU+uqPpr-f4-_qK3_spkq3iXbTVPCX9_-9VjAm38nrJCng@mail.gmail.com>

On Sat, Aug 14, 2021 at 6:42 AM Samuel Holland <samuel at sholland.org> wrote:
>
> commit 764a17d852a8 ("lib: sbi: Implement firmware counters") added
> switch cases for CAUSE_LOAD_ACCESS and CAUSE_STORE_ACCESS. This caused
> them to stop being redirected to U or S mode, as that is handled in the
> default switch case. As a result, an error in userspace could cause the
> system to hang. Fix this by allowing the acces fault case to fall
> through to the default case.

Thanks for catching this.

>
> Signed-off-by: Samuel Holland <samuel at sholland.org>
> ---
>  lib/sbi/sbi_trap.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index 5781fea..8d20e04 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -259,11 +259,10 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
>                 msg = "ecall handler failed";
>                 break;
>         case CAUSE_LOAD_ACCESS:
> -               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD);
> -               break;
>         case CAUSE_STORE_ACCESS:
> -               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE);
> -               break;
> +               sbi_pmu_ctr_incr_fw(mcause == CAUSE_LOAD_ACCESS ?
> +                       SBI_PMU_FW_ACCESS_LOAD : SBI_PMU_FW_ACCESS_STORE);
> +               /* fallthrough */
>         default:
>                 /* If the trap came from S or U mode, redirect it there */
>                 trap.epc = regs->mepc;
> --
> 2.31.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug 16 17:10:38 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 16 Aug 2021 17:10:38 -0700
Subject: [PATCH] payloads/test: Add support for SBI v0.2 ecalls
In-Reply-To: <20210814135210.17729-1-samuel@sholland.org>
References: <20210814135210.17729-1-samuel@sholland.org>
Message-ID: <CAOnJCUKZzpZ5pKbg8vGnUifjtAbJfbvYnTHrAxjidAqS7GkxjQ@mail.gmail.com>

On Sat, Aug 14, 2021 at 6:52 AM Samuel Holland <samuel at sholland.org> wrote:
>
> It can be useful to make SBI v0.2 or newer ecalls from this payload
> for testing purposes. To support this, convert the macros to use the
> extension/function parameter convention.
>
> Signed-off-by: Samuel Holland <samuel at sholland.org>
> ---
>  firmware/payloads/test_main.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
> index 0d65930..ae2ed4f 100644
> --- a/firmware/payloads/test_main.c
> +++ b/firmware/payloads/test_main.c
> @@ -9,24 +9,25 @@
>
>  #include <sbi/sbi_ecall_interface.h>
>
> -#define SBI_ECALL(__num, __a0, __a1, __a2)                                    \
> +#define SBI_ECALL(__eid, __fid, __a0, __a1, __a2)                             \
>         ({                                                                    \
>                 register unsigned long a0 asm("a0") = (unsigned long)(__a0);  \
>                 register unsigned long a1 asm("a1") = (unsigned long)(__a1);  \
>                 register unsigned long a2 asm("a2") = (unsigned long)(__a2);  \
> -               register unsigned long a7 asm("a7") = (unsigned long)(__num); \
> +               register unsigned long a6 asm("a6") = (unsigned long)(__fid); \
> +               register unsigned long a7 asm("a7") = (unsigned long)(__eid); \
>                 asm volatile("ecall"                                          \
>                              : "+r"(a0)                                       \
> -                            : "r"(a1), "r"(a2), "r"(a7)                      \
> +                            : "r"(a1), "r"(a2), "r"(a6), "r"(a7)             \
>                              : "memory");                                     \
>                 a0;                                                           \
>         })
>
> -#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
> -#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
> -#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
> +#define SBI_ECALL_0(__eid, __fid) SBI_ECALL(__eid, __fid, 0, 0, 0)
> +#define SBI_ECALL_1(__eid, __fid, __a0) SBI_ECALL(__eid, __fid, __a0, 0, 0)
> +#define SBI_ECALL_2(__eid, __fid, __a0, __a1) SBI_ECALL(__eid, __fid, __a0, __a1, 0)
>
> -#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, (c))
> +#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, (c))
>
>  static inline void sbi_ecall_console_puts(const char *str)
>  {
> --
> 2.31.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug 16 17:22:05 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 16 Aug 2021 17:22:05 -0700
Subject: [PATCH] lib: sbi: Fix bug in sbi_ecall_rfence that misses checking
In-Reply-To: <20210813123300.26085-1-Dd_nirvana@sjtu.edu.cn>
References: <20210813123300.26085-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <CAOnJCULR-KCvf4A8SZZB31A5_rfK-=Z-onW_Ypgp00o9eHWUVQ@mail.gmail.com>

On Fri, Aug 13, 2021 at 5:34 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>
> In sbi_ecall_rfence_handler, it will compare the funcid with REMOTE_HFENCE_GVMA and
> REMOTE_HFENCE_VVMA_ASID.
> And then check whether the misa includes H-extension.
> This checking is incomplete which misses REMOTE_HFENCE_GVMA_VMID and REMOTE_HFENCE_VVMA.
> Fix the issue by updating the checking range.
>
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> ---
>  lib/sbi/sbi_ecall_replace.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/lib/sbi/sbi_ecall_replace.c b/lib/sbi/sbi_ecall_replace.c
> index a7935d9..5d24565 100644
> --- a/lib/sbi/sbi_ecall_replace.c
> +++ b/lib/sbi/sbi_ecall_replace.c
> @@ -54,8 +54,8 @@ static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid,
>         struct sbi_tlb_info tlb_info;
>         u32 source_hart = current_hartid();
>
> -       if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA &&
> -           funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID)
> +       if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID &&
> +           funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA)
>                 if (!misa_extension('H'))
>                         return SBI_ENOTSUPP;
>
> --
> 2.31.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From bmeng.cn at gmail.com  Mon Aug 16 23:17:57 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Tue, 17 Aug 2021 14:17:57 +0800
Subject: [PATCH] lib: sbi_trap: Restore redirect for access faults
In-Reply-To: <20210814134147.14056-1-samuel@sholland.org>
References: <20210814134147.14056-1-samuel@sholland.org>
Message-ID: <CAEUhbmWkBgsZM5NjiDJh6AyZZTGmFUiLLC=WQXyAq8xkwm5XDA@mail.gmail.com>

On Sat, Aug 14, 2021 at 9:42 PM Samuel Holland <samuel at sholland.org> wrote:
>
> commit 764a17d852a8 ("lib: sbi: Implement firmware counters") added
> switch cases for CAUSE_LOAD_ACCESS and CAUSE_STORE_ACCESS. This caused
> them to stop being redirected to U or S mode, as that is handled in the
> default switch case. As a result, an error in userspace could cause the
> system to hang. Fix this by allowing the acces fault case to fall
> through to the default case.
>
> Signed-off-by: Samuel Holland <samuel at sholland.org>
> ---
>  lib/sbi/sbi_trap.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
>

Should have a:

Fixes 764a17d852a8 ("lib: sbi: Implement firmware counters")
Reviewed-by: Bin Meng <bmeng.cn at gmail.com>


From anup at brainfault.org  Thu Aug 19 21:53:02 2021
From: anup at brainfault.org (Anup Patel)
Date: Fri, 20 Aug 2021 10:23:02 +0530
Subject: [PATCH] lib: sbi: Fix bug in sbi_ecall_rfence that misses checking
In-Reply-To: <CAOnJCULR-KCvf4A8SZZB31A5_rfK-=Z-onW_Ypgp00o9eHWUVQ@mail.gmail.com>
References: <20210813123300.26085-1-Dd_nirvana@sjtu.edu.cn>
 <CAOnJCULR-KCvf4A8SZZB31A5_rfK-=Z-onW_Ypgp00o9eHWUVQ@mail.gmail.com>
Message-ID: <CAAhSdy1vSze30iBv=KrjXBL7wpU0Y_dCB+DM=736-7022i5cPA@mail.gmail.com>

On Tue, Aug 17, 2021 at 5:52 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Fri, Aug 13, 2021 at 5:34 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
> >
> > In sbi_ecall_rfence_handler, it will compare the funcid with REMOTE_HFENCE_GVMA and
> > REMOTE_HFENCE_VVMA_ASID.
> > And then check whether the misa includes H-extension.
> > This checking is incomplete which misses REMOTE_HFENCE_GVMA_VMID and REMOTE_HFENCE_VVMA.
> > Fix the issue by updating the checking range.
> >
> > Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> > ---
> >  lib/sbi/sbi_ecall_replace.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/sbi/sbi_ecall_replace.c b/lib/sbi/sbi_ecall_replace.c
> > index a7935d9..5d24565 100644
> > --- a/lib/sbi/sbi_ecall_replace.c
> > +++ b/lib/sbi/sbi_ecall_replace.c
> > @@ -54,8 +54,8 @@ static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid,
> >         struct sbi_tlb_info tlb_info;
> >         u32 source_hart = current_hartid();
> >
> > -       if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA &&
> > -           funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID)
> > +       if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID &&
> > +           funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA)
> >                 if (!misa_extension('H'))
> >                         return SBI_ENOTSUPP;
> >
> > --
> > 2.31.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

>
> --
> Regards,
> Atish
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Thu Aug 19 21:53:52 2021
From: anup at brainfault.org (Anup Patel)
Date: Fri, 20 Aug 2021 10:23:52 +0530
Subject: [PATCH] lib: sbi_trap: Restore redirect for access faults
In-Reply-To: <CAEUhbmWkBgsZM5NjiDJh6AyZZTGmFUiLLC=WQXyAq8xkwm5XDA@mail.gmail.com>
References: <20210814134147.14056-1-samuel@sholland.org>
 <CAEUhbmWkBgsZM5NjiDJh6AyZZTGmFUiLLC=WQXyAq8xkwm5XDA@mail.gmail.com>
Message-ID: <CAAhSdy08+gkHPFZqRwoxCZn1asEQj6qvRKQV6UfPoRo3m36FaQ@mail.gmail.com>

On Tue, Aug 17, 2021 at 11:48 AM Bin Meng <bmeng.cn at gmail.com> wrote:
>
> On Sat, Aug 14, 2021 at 9:42 PM Samuel Holland <samuel at sholland.org> wrote:
> >
> > commit 764a17d852a8 ("lib: sbi: Implement firmware counters") added
> > switch cases for CAUSE_LOAD_ACCESS and CAUSE_STORE_ACCESS. This caused
> > them to stop being redirected to U or S mode, as that is handled in the
> > default switch case. As a result, an error in userspace could cause the
> > system to hang. Fix this by allowing the acces fault case to fall
> > through to the default case.
> >
> > Signed-off-by: Samuel Holland <samuel at sholland.org>
> > ---
> >  lib/sbi/sbi_trap.c | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> >
>
> Should have a:
>
> Fixes 764a17d852a8 ("lib: sbi: Implement firmware counters")
> Reviewed-by: Bin Meng <bmeng.cn at gmail.com>

I have included the Fixes tag at time of merging this patch.

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Thu Aug 19 21:54:18 2021
From: anup at brainfault.org (Anup Patel)
Date: Fri, 20 Aug 2021 10:24:18 +0530
Subject: [PATCH] payloads/test: Add support for SBI v0.2 ecalls
In-Reply-To: <CAOnJCUKZzpZ5pKbg8vGnUifjtAbJfbvYnTHrAxjidAqS7GkxjQ@mail.gmail.com>
References: <20210814135210.17729-1-samuel@sholland.org>
 <CAOnJCUKZzpZ5pKbg8vGnUifjtAbJfbvYnTHrAxjidAqS7GkxjQ@mail.gmail.com>
Message-ID: <CAAhSdy2z0fgK0M2y5Q2=nc=OXzJS4qupjM8CEk4D=r6_Kf8-WQ@mail.gmail.com>

On Tue, Aug 17, 2021 at 5:41 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Sat, Aug 14, 2021 at 6:52 AM Samuel Holland <samuel at sholland.org> wrote:
> >
> > It can be useful to make SBI v0.2 or newer ecalls from this payload
> > for testing purposes. To support this, convert the macros to use the
> > extension/function parameter convention.
> >
> > Signed-off-by: Samuel Holland <samuel at sholland.org>
> > ---
> >  firmware/payloads/test_main.c | 15 ++++++++-------
> >  1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
> > index 0d65930..ae2ed4f 100644
> > --- a/firmware/payloads/test_main.c
> > +++ b/firmware/payloads/test_main.c
> > @@ -9,24 +9,25 @@
> >
> >  #include <sbi/sbi_ecall_interface.h>
> >
> > -#define SBI_ECALL(__num, __a0, __a1, __a2)                                    \
> > +#define SBI_ECALL(__eid, __fid, __a0, __a1, __a2)                             \
> >         ({                                                                    \
> >                 register unsigned long a0 asm("a0") = (unsigned long)(__a0);  \
> >                 register unsigned long a1 asm("a1") = (unsigned long)(__a1);  \
> >                 register unsigned long a2 asm("a2") = (unsigned long)(__a2);  \
> > -               register unsigned long a7 asm("a7") = (unsigned long)(__num); \
> > +               register unsigned long a6 asm("a6") = (unsigned long)(__fid); \
> > +               register unsigned long a7 asm("a7") = (unsigned long)(__eid); \
> >                 asm volatile("ecall"                                          \
> >                              : "+r"(a0)                                       \
> > -                            : "r"(a1), "r"(a2), "r"(a7)                      \
> > +                            : "r"(a1), "r"(a2), "r"(a6), "r"(a7)             \
> >                              : "memory");                                     \
> >                 a0;                                                           \
> >         })
> >
> > -#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
> > -#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
> > -#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
> > +#define SBI_ECALL_0(__eid, __fid) SBI_ECALL(__eid, __fid, 0, 0, 0)
> > +#define SBI_ECALL_1(__eid, __fid, __a0) SBI_ECALL(__eid, __fid, __a0, 0, 0)
> > +#define SBI_ECALL_2(__eid, __fid, __a0, __a1) SBI_ECALL(__eid, __fid, __a0, __a1, 0)
> >
> > -#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, (c))
> > +#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, (c))
> >
> >  static inline void sbi_ecall_console_puts(const char *str)
> >  {
> > --
> > 2.31.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>
>
> Reviewed-by: Atish Patra <atish.patra at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

>
> --
> Regards,
> Atish
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From rpathak at ventanamicro.com  Thu Aug 26 02:54:18 2021
From: rpathak at ventanamicro.com (Rahul Pathak)
Date: Thu, 26 Aug 2021 15:24:18 +0530
Subject: [PATCH] lib: sbi: Correct typo in faults delegation CSR name
Message-ID: <20210826095417.135448-1-rpathak@ventanamicro.com>

Correcting the name of faults delegation CSR
%s/mfdeleg/medeleg

Signed-off-by: Rahul Pathak <rpathak at ventanamicro.com>
---
 lib/sbi/sbi_platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
index e8b94a3..99bd8f5 100644
--- a/lib/sbi/sbi_platform.c
+++ b/lib/sbi/sbi_platform.c
@@ -20,7 +20,7 @@ static inline char *sbi_platform_feature_id2string(unsigned long feature)
 
 	switch (feature) {
 	case SBI_PLATFORM_HAS_MFAULTS_DELEGATION:
-		fstr = "mfdeleg";
+		fstr = "medeleg";
 		break;
 	default:
 		break;
-- 
2.25.1



From Dd_nirvana at sjtu.edu.cn  Fri Aug 27 02:35:03 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Fri, 27 Aug 2021 17:35:03 +0800
Subject: [PATCH] lib: sbi: protect dprintf output with spinlock
Message-ID: <20210827093503.16916-1-Dd_nirvana@sjtu.edu.cn>

Avoid getting messages from multiple harts (using dprintf and printf) concurrently
with a spinlock serializaing calls to sbi_dprintf() with sbi_printf() and sbi_puts()

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 lib/sbi/sbi_console.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
index b54f7a2..850af04 100644
--- a/lib/sbi/sbi_console.c
+++ b/lib/sbi/sbi_console.c
@@ -386,10 +386,12 @@ int sbi_dprintf(const char *format, ...)
 	int retval = 0;
 	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
 
+	spin_lock(&console_out_lock);
 	va_start(args, format);
 	if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS)
 		retval = print(NULL, NULL, format, args);
 	va_end(args);
+	spin_unlock(&console_out_lock);
 
 	return retval;
 }
-- 
2.31.1



From Dd_nirvana at sjtu.edu.cn  Fri Aug 27 07:46:28 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Fri, 27 Aug 2021 22:46:28 +0800
Subject: [PATCH] lib: sbi: Checking fifo validness in sbi_fifo_is_empty and
 is_full
Message-ID: <20210827144628.29728-1-Dd_nirvana@sjtu.edu.cn>

As other exported fifo functions, we should check whether the fifo is
valid in sbi_fifo_is_empty and sbi_fifo_is_full.
To this end, this patch changes the retval from bool to int, and the
two functions will return SBI_EINVAL in the case the fifo is invalid.

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 include/sbi/sbi_fifo.h |  4 ++--
 lib/sbi/sbi_fifo.c     | 10 ++++++++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/sbi/sbi_fifo.h b/include/sbi/sbi_fifo.h
index bc8f8f6..1a85f07 100644
--- a/include/sbi/sbi_fifo.h
+++ b/include/sbi/sbi_fifo.h
@@ -33,8 +33,8 @@ int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data);
 int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data);
 void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
 		   u16 entry_size);
-bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
-bool sbi_fifo_is_full(struct sbi_fifo *fifo);
+int sbi_fifo_is_empty(struct sbi_fifo *fifo);
+int sbi_fifo_is_full(struct sbi_fifo *fifo);
 int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in,
 			    int (*fptr)(void *in, void *data));
 u16 sbi_fifo_avail(struct sbi_fifo *fifo);
diff --git a/lib/sbi/sbi_fifo.c b/lib/sbi/sbi_fifo.c
index b2395f3..589cc18 100644
--- a/lib/sbi/sbi_fifo.c
+++ b/lib/sbi/sbi_fifo.c
@@ -43,10 +43,13 @@ u16 sbi_fifo_avail(struct sbi_fifo *fifo)
 	return ret;
 }
 
-bool sbi_fifo_is_full(struct sbi_fifo *fifo)
+int sbi_fifo_is_full(struct sbi_fifo *fifo)
 {
 	bool ret;
 
+	if (!fifo)
+		return SBI_EINVAL;
+
 	spin_lock(&fifo->qlock);
 	ret = __sbi_fifo_is_full(fifo);
 	spin_unlock(&fifo->qlock);
@@ -75,10 +78,13 @@ static inline bool __sbi_fifo_is_empty(struct sbi_fifo *fifo)
 	return (fifo->avail == 0) ? TRUE : FALSE;
 }
 
-bool sbi_fifo_is_empty(struct sbi_fifo *fifo)
+int sbi_fifo_is_empty(struct sbi_fifo *fifo)
 {
 	bool ret;
 
+	if (!fifo)
+		return SBI_EINVAL;
+
 	spin_lock(&fifo->qlock);
 	ret = __sbi_fifo_is_empty(fifo);
 	spin_unlock(&fifo->qlock);
-- 
2.31.1



From Dd_nirvana at sjtu.edu.cn  Fri Aug 27 23:45:02 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Sat, 28 Aug 2021 14:45:02 +0800
Subject: [PATCH v2] lib: sbi: protect dprintf output with spinlock
Message-ID: <20210828064502.7227-1-Dd_nirvana@sjtu.edu.cn>

Avoid getting messages from multiple harts (using dprintf and printf)
concurrently with a spinlock serializaing calls to sbi_dprintf(),
sbi_printf() and sbi_puts()

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 lib/sbi/sbi_console.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
index b54f7a2..29eede3 100644
--- a/lib/sbi/sbi_console.c
+++ b/lib/sbi/sbi_console.c
@@ -387,8 +387,11 @@ int sbi_dprintf(const char *format, ...)
 	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
 
 	va_start(args, format);
-	if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS)
+	if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS) {
+		spin_lock(&console_out_lock);
 		retval = print(NULL, NULL, format, args);
+		spin_unlock(&console_out_lock);
+	}
 	va_end(args);
 
 	return retval;
-- 
2.31.1



From wxjstz at 126.com  Sun Aug 29 19:50:07 2021
From: wxjstz at 126.com (Xiang W)
Date: Mon, 30 Aug 2021 10:50:07 +0800
Subject: [PATCH v2] lib: sbi: protect dprintf output with spinlock
In-Reply-To: <20210828064502.7227-1-Dd_nirvana@sjtu.edu.cn>
References: <20210828064502.7227-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <8e0a879265c7817ba07e6e64353d81a2816b46b2.camel@126.com>

? 2021-08-28???? 14:45 +0800?Dong Du???
> Avoid getting messages from multiple harts (using dprintf and printf)
> concurrently with a spinlock serializaing calls to sbi_dprintf(),
> sbi_printf() and sbi_puts()
> 
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>

look good to me.
Reviewed-by: Xiang W <wxjstz at 126.com>
> ---
> ?lib/sbi/sbi_console.c | 5 ++++-
> ?1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
> index b54f7a2..29eede3 100644
> --- a/lib/sbi/sbi_console.c
> +++ b/lib/sbi/sbi_console.c
> @@ -387,8 +387,11 @@ int sbi_dprintf(const char *format, ...)
> ????????struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
> ?
> ????????va_start(args, format);
> -???????if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS)
> +???????if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS) {
> +???????????????spin_lock(&console_out_lock);
> ????????????????retval = print(NULL, NULL, format, args);
> +???????????????spin_unlock(&console_out_lock);
> +???????}
> ????????va_end(args);
> ?
> ????????return retval;
> -- 
> 2.31.1
> 
> 




From Anup.Patel at wdc.com  Sun Aug 29 20:40:00 2021
From: Anup.Patel at wdc.com (Anup Patel)
Date: Mon, 30 Aug 2021 03:40:00 +0000
Subject: [PATCH] lib: sbi: Correct typo in faults delegation CSR name
In-Reply-To: <20210826095417.135448-1-rpathak@ventanamicro.com>
References: <20210826095417.135448-1-rpathak@ventanamicro.com>
Message-ID: <3E07CD9C-7894-4609-936A-02388F877468@wdc.com>



?On 26/08/21, 9:13 PM, "opensbi on behalf of Rahul Pathak" <opensbi-bounces at lists.infradead.org on behalf of rpathak at ventanamicro.com> wrote:

    Correcting the name of faults delegation CSR
    %s/mfdeleg/medeleg

    Signed-off-by: Rahul Pathak <rpathak at ventanamicro.com>

Looks good to me.

Reviewed-by: Anup Patel <anup.patel at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup
    ---
     lib/sbi/sbi_platform.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)

    diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
    index e8b94a3..99bd8f5 100644
    --- a/lib/sbi/sbi_platform.c
    +++ b/lib/sbi/sbi_platform.c
    @@ -20,7 +20,7 @@ static inline char *sbi_platform_feature_id2string(unsigned long feature)

     	switch (feature) {
     	case SBI_PLATFORM_HAS_MFAULTS_DELEGATION:
    -		fstr = "mfdeleg";
    +		fstr = "medeleg";
     		break;
     	default:
     		break;
    -- 
    2.25.1


    -- 
    opensbi mailing list
    opensbi at lists.infradead.org
    http://lists.infradead.org/mailman/listinfo/opensbi


From Anup.Patel at wdc.com  Sun Aug 29 20:56:27 2021
From: Anup.Patel at wdc.com (Anup Patel)
Date: Mon, 30 Aug 2021 03:56:27 +0000
Subject: [PATCH v2] lib: sbi: protect dprintf output with spinlock
In-Reply-To: <8e0a879265c7817ba07e6e64353d81a2816b46b2.camel@126.com>
References: <20210828064502.7227-1-Dd_nirvana@sjtu.edu.cn>
 <8e0a879265c7817ba07e6e64353d81a2816b46b2.camel@126.com>
Message-ID: <397FF35B-066C-4490-9D98-016571D66BF7@wdc.com>



?On 30/08/21, 8:20 AM, "opensbi on behalf of Xiang W" <opensbi-bounces at lists.infradead.org on behalf of wxjstz at 126.com> wrote:

    ? 2021-08-28???? 14:45 +0800?Dong Du???
    > Avoid getting messages from multiple harts (using dprintf and printf)
    > concurrently with a spinlock serializaing calls to sbi_dprintf(),
    > sbi_printf() and sbi_puts()
    > 
    > Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>

    look good to me.
    Reviewed-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup.patel at wdc.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

    > ---
    >  lib/sbi/sbi_console.c | 5 ++++-
    >  1 file changed, 4 insertions(+), 1 deletion(-)
    > 
    > diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
    > index b54f7a2..29eede3 100644
    > --- a/lib/sbi/sbi_console.c
    > +++ b/lib/sbi/sbi_console.c
    > @@ -387,8 +387,11 @@ int sbi_dprintf(const char *format, ...)
    >         struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
    >  
    >         va_start(args, format);
    > -       if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS)
    > +       if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS) {
    > +               spin_lock(&console_out_lock);
    >                 retval = print(NULL, NULL, format, args);
    > +               spin_unlock(&console_out_lock);
    > +       }
    >         va_end(args);
    >  
    >         return retval;
    > -- 
    > 2.31.1
    > 
    > 



    -- 
    opensbi mailing list
    opensbi at lists.infradead.org
    http://lists.infradead.org/mailman/listinfo/opensbi


From Dd_nirvana at sjtu.edu.cn  Mon Aug 30 06:59:14 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Mon, 30 Aug 2021 21:59:14 +0800
Subject: [PATCH] lib: sbi: Refine the way to construct platform features
Message-ID: <20210830135914.15395-1-Dd_nirvana@sjtu.edu.cn>

sbi_platform_get_features_str() uses sbi_snprintf() to construct the
features_str. However, it passes the wrong length value (i.e., the nfstr),
which should be (nfstr-offset) as the starting point of str (i.e., features_str + offset)
changes.
This commit also checks the return value of snprintf, and handles the corner case
that the string buffer is full.

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 lib/sbi/sbi_platform.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
index 99bd8f5..56c37aa 100644
--- a/lib/sbi/sbi_platform.c
+++ b/lib/sbi/sbi_platform.c
@@ -48,9 +48,17 @@ void sbi_platform_get_features_str(const struct sbi_platform *plat,
 		if (features & feat) {
 			temp = sbi_platform_feature_id2string(feat);
 			if (temp) {
-				sbi_snprintf(features_str + offset, nfstr,
+				int len = sbi_snprintf(features_str + offset, nfstr - offset,
 					     "%s,", temp);
-				offset = offset + sbi_strlen(temp) + 1;
+				if (len < 0)
+					break;
+
+				if (offset + len >= nfstr) {
+					// No more space for features
+					offset = nfstr;
+					break;
+				} else
+					offset = offset + len;
 			}
 		}
 		feat = feat << 1;
-- 
2.31.1



From atishp at atishpatra.org  Mon Aug 30 14:21:52 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 30 Aug 2021 14:21:52 -0700
Subject: [PATCH] lib: sbi: Checking fifo validness in sbi_fifo_is_empty
 and is_full
In-Reply-To: <20210827144628.29728-1-Dd_nirvana@sjtu.edu.cn>
References: <20210827144628.29728-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <CAOnJCUK_ad-aNWKrLEd2UKxDP-s09tXgkDG89ATH_gtwJB7HCw@mail.gmail.com>

On Fri, Aug 27, 2021 at 7:47 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>
> As other exported fifo functions, we should check whether the fifo is
> valid in sbi_fifo_is_empty and sbi_fifo_is_full.
> To this end, this patch changes the retval from bool to int, and the
> two functions will return SBI_EINVAL in the case the fifo is invalid.
>
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> ---
>  include/sbi/sbi_fifo.h |  4 ++--
>  lib/sbi/sbi_fifo.c     | 10 ++++++++--
>  2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/include/sbi/sbi_fifo.h b/include/sbi/sbi_fifo.h
> index bc8f8f6..1a85f07 100644
> --- a/include/sbi/sbi_fifo.h
> +++ b/include/sbi/sbi_fifo.h
> @@ -33,8 +33,8 @@ int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data);
>  int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data);
>  void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
>                    u16 entry_size);
> -bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
> -bool sbi_fifo_is_full(struct sbi_fifo *fifo);
> +int sbi_fifo_is_empty(struct sbi_fifo *fifo);
> +int sbi_fifo_is_full(struct sbi_fifo *fifo);
>  int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in,
>                             int (*fptr)(void *in, void *data));
>  u16 sbi_fifo_avail(struct sbi_fifo *fifo);
> diff --git a/lib/sbi/sbi_fifo.c b/lib/sbi/sbi_fifo.c
> index b2395f3..589cc18 100644
> --- a/lib/sbi/sbi_fifo.c
> +++ b/lib/sbi/sbi_fifo.c
> @@ -43,10 +43,13 @@ u16 sbi_fifo_avail(struct sbi_fifo *fifo)
>         return ret;
>  }
>
> -bool sbi_fifo_is_full(struct sbi_fifo *fifo)
> +int sbi_fifo_is_full(struct sbi_fifo *fifo)
>  {
>         bool ret;
>
> +       if (!fifo)
> +               return SBI_EINVAL;
> +
>         spin_lock(&fifo->qlock);
>         ret = __sbi_fifo_is_full(fifo);
>         spin_unlock(&fifo->qlock);
> @@ -75,10 +78,13 @@ static inline bool __sbi_fifo_is_empty(struct sbi_fifo *fifo)
>         return (fifo->avail == 0) ? TRUE : FALSE;
>  }
>
> -bool sbi_fifo_is_empty(struct sbi_fifo *fifo)
> +int sbi_fifo_is_empty(struct sbi_fifo *fifo)
>  {
>         bool ret;
>
> +       if (!fifo)
> +               return SBI_EINVAL;
> +
>         spin_lock(&fifo->qlock);
>         ret = __sbi_fifo_is_empty(fifo);
>         spin_unlock(&fifo->qlock);
> --
> 2.31.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


Reviewed-by: Atish Patra <atish.patra at wdc.com>

-- 
Regards,
Atish


From atishp at atishpatra.org  Mon Aug 30 14:32:19 2021
From: atishp at atishpatra.org (Atish Patra)
Date: Mon, 30 Aug 2021 14:32:19 -0700
Subject: [PATCH] lib: sbi: Refine the way to construct platform features
In-Reply-To: <20210830135914.15395-1-Dd_nirvana@sjtu.edu.cn>
References: <20210830135914.15395-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <CAOnJCUKFJhFjTSV1DJn1iCfoPBHXA1VKutWyLBhvRcC7RcWwpw@mail.gmail.com>

On Mon, Aug 30, 2021 at 6:59 AM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>
> sbi_platform_get_features_str() uses sbi_snprintf() to construct the
> features_str. However, it passes the wrong length value (i.e., the nfstr),
> which should be (nfstr-offset) as the starting point of str (i.e., features_str + offset)
> changes.
> This commit also checks the return value of snprintf, and handles the corner case
> that the string buffer is full.
>
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> ---
>  lib/sbi/sbi_platform.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
> index 99bd8f5..56c37aa 100644
> --- a/lib/sbi/sbi_platform.c
> +++ b/lib/sbi/sbi_platform.c
> @@ -48,9 +48,17 @@ void sbi_platform_get_features_str(const struct sbi_platform *plat,
>                 if (features & feat) {
>                         temp = sbi_platform_feature_id2string(feat);
>                         if (temp) {
> -                               sbi_snprintf(features_str + offset, nfstr,
> +                               int len = sbi_snprintf(features_str + offset, nfstr - offset,
>                                              "%s,", temp);
> -                               offset = offset + sbi_strlen(temp) + 1;
> +                               if (len < 0)
> +                                       break;
> +
> +                               if (offset + len >= nfstr) {
> +                                       // No more space for features
> +                                       offset = nfstr;
> +                                       break;
> +                               } else
> +                                       offset = offset + len;
>                         }
>                 }
>                 feat = feat << 1;
> --
> 2.31.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Thanks for catching it. Looks good

Reviewed-by: Atish Patra <atish.patra at wdc.com>


-- 
Regards,
Atish


From heinrich.schuchardt at canonical.com  Tue Aug 31 10:09:27 2021
From: heinrich.schuchardt at canonical.com (Heinrich Schuchardt)
Date: Tue, 31 Aug 2021 19:09:27 +0200
Subject: [RFC 1/1] fw_base: header for vendor information
Message-ID: <20210831170927.93019-1-heinrich.schuchardt@canonical.com>

To implement secure boot OpenSBI should provide a well defined header
structure with reserved space in which a vendor can place information
related to a signature that the boot ROM code can check.

Typically this space will be used to add

* vendor magic
* type of signature
* offset to signature

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
---
Ideally such a header would be standardized. This would allow alternative
firmware to be validated by the same boot ROM.

Could this be a topic for the platform specification?

Best regards

Heinrich
---
 firmware/fw_base.S | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 1569e60..e2cc5cb 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -13,6 +13,7 @@
 #include <sbi/sbi_platform.h>
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_trap.h>
+#include <sbi/sbi_version.h>
 
 #define BOOT_STATUS_RELOCATE_DONE	1
 #define BOOT_STATUS_BOOT_HART_DONE	2
@@ -47,6 +48,15 @@
 	.globl _start
 	.globl _start_warm
 _start:
+	j	_real_start
+	.align	2
+	.ascii	"OpenSBI\0"
+	.short	OPENSBI_VERSION_MAJOR
+	.short  OPENSBI_VERSION_MINOR
+	/* Space reserved for vendor information, e.g. offset to a signature */
+	.long	0
+	.skip	12
+_real_start:
 	/* Find preferred boot HART id */
 	MOV_3R	s0, a0, s1, a1, s2, a2
 	call	fw_boot_hart
-- 
2.30.2



From bmeng.cn at gmail.com  Tue Aug 31 15:15:54 2021
From: bmeng.cn at gmail.com (Bin Meng)
Date: Wed, 1 Sep 2021 06:15:54 +0800
Subject: [PATCH] lib: sbi: Refine the way to construct platform features
In-Reply-To: <20210830135914.15395-1-Dd_nirvana@sjtu.edu.cn>
References: <20210830135914.15395-1-Dd_nirvana@sjtu.edu.cn>
Message-ID: <CAEUhbmXEUOdW6M-tA3SnwK2jzYpvu_nVwmrk9DQErSPvHjj5UQ@mail.gmail.com>

On Mon, Aug 30, 2021 at 10:00 PM Dong Du <Dd_nirvana at sjtu.edu.cn> wrote:
>
> sbi_platform_get_features_str() uses sbi_snprintf() to construct the
> features_str. However, it passes the wrong length value (i.e., the nfstr),
> which should be (nfstr-offset) as the starting point of str (i.e., features_str + offset)
> changes.
> This commit also checks the return value of snprintf, and handles the corner case
> that the string buffer is full.
>
> Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
> ---
>  lib/sbi/sbi_platform.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
> index 99bd8f5..56c37aa 100644
> --- a/lib/sbi/sbi_platform.c
> +++ b/lib/sbi/sbi_platform.c
> @@ -48,9 +48,17 @@ void sbi_platform_get_features_str(const struct sbi_platform *plat,
>                 if (features & feat) {
>                         temp = sbi_platform_feature_id2string(feat);
>                         if (temp) {
> -                               sbi_snprintf(features_str + offset, nfstr,
> +                               int len = sbi_snprintf(features_str + offset, nfstr - offset,
>                                              "%s,", temp);
> -                               offset = offset + sbi_strlen(temp) + 1;
> +                               if (len < 0)
> +                                       break;
> +
> +                               if (offset + len >= nfstr) {
> +                                       // No more space for features

Use /* */ style

> +                                       offset = nfstr;
> +                                       break;
> +                               } else
> +                                       offset = offset + len;
>                         }
>                 }
>                 feat = feat << 1;
>

Regards,
Bin


From Dd_nirvana at sjtu.edu.cn  Tue Aug 31 20:06:24 2021
From: Dd_nirvana at sjtu.edu.cn (Dong Du)
Date: Wed,  1 Sep 2021 11:06:24 +0800
Subject: [PATCH v2] lib: sbi: Refine the way to construct platform features
Message-ID: <20210901030624.20065-1-Dd_nirvana@sjtu.edu.cn>

sbi_platform_get_features_str() uses sbi_snprintf() to construct the
features_str. However, it passes the wrong length value (i.e., the nfstr),
which should be (nfstr-offset) as the starting point of str (i.e., features_str + offset)
changes.
This commit also checks the return value of snprintf, and handles the corner case
that the string buffer is full.

Signed-off-by: Dong Du <Dd_nirvana at sjtu.edu.cn>
---
 lib/sbi/sbi_platform.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lib/sbi/sbi_platform.c b/lib/sbi/sbi_platform.c
index 99bd8f5..7f0ed23 100644
--- a/lib/sbi/sbi_platform.c
+++ b/lib/sbi/sbi_platform.c
@@ -48,9 +48,17 @@ void sbi_platform_get_features_str(const struct sbi_platform *plat,
 		if (features & feat) {
 			temp = sbi_platform_feature_id2string(feat);
 			if (temp) {
-				sbi_snprintf(features_str + offset, nfstr,
+				int len = sbi_snprintf(features_str + offset, nfstr - offset,
 					     "%s,", temp);
-				offset = offset + sbi_strlen(temp) + 1;
+				if (len < 0)
+					break;
+
+				if (offset + len >= nfstr) {
+					/* No more space for features */
+					offset = nfstr;
+					break;
+				} else
+					offset = offset + len;
 			}
 		}
 		feat = feat << 1;
-- 
2.31.1



