lib: utils/timer: Use scratch space to save per-HART MTIMER pointer
authorAnup Patel <apatel@ventanamicro.com>
Wed, 19 Apr 2023 15:57:27 +0000 (21:27 +0530)
committerAnup Patel <anup@brainfault.org>
Mon, 5 Jun 2023 11:16:50 +0000 (16:46 +0530)
Instead of using a global array indexed by hartid, we should use
scratch space to save per-HART MTIMER pointer.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
lib/utils/timer/aclint_mtimer.c

index 84ded4ed44e50396651b55680682b5558d9a6e7b..13af5d8232d3c443e8515a1427f99d724c72e8dc 100644 (file)
 #include <sbi/sbi_bitops.h>
 #include <sbi/sbi_domain.h>
 #include <sbi/sbi_error.h>
-#include <sbi/sbi_hartmask.h>
-#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_scratch.h>
 #include <sbi/sbi_timer.h>
 #include <sbi_utils/timer/aclint_mtimer.h>
 
-static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS];
+static unsigned long mtimer_ptr_offset;
+
+#define mtimer_get_hart_data_ptr(__scratch)                            \
+       sbi_scratch_read_type((__scratch), void *, mtimer_ptr_offset)
+
+#define mtimer_set_hart_data_ptr(__scratch, __mtimer)                  \
+       sbi_scratch_write_type((__scratch), void *, mtimer_ptr_offset, (__mtimer))
 
 #if __riscv_xlen != 32
 static u64 mtimer_time_rd64(volatile u64 *addr)
@@ -53,30 +58,54 @@ 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->mtime_addr;
+       struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+       struct aclint_mtimer_data *mt;
+
+       mt = mtimer_get_hart_data_ptr(scratch);
+       if (!mt)
+               return 0;
 
        /* Read MTIMER Time Value */
-       return mt->time_rd(time_val);
+       return mt->time_rd((void *)mt->mtime_addr);
 }
 
 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->mtimecmp_addr;
+       struct sbi_scratch *scratch;
+       struct aclint_mtimer_data *mt;
+       u64 *time_cmp;
+
+       scratch = sbi_hartid_to_scratch(target_hart);
+       if (!scratch)
+               return;
+
+       mt = mtimer_get_hart_data_ptr(scratch);
+       if (!mt)
+               return;
 
        /* Clear MTIMER Time Compare */
+       time_cmp = (void *)mt->mtimecmp_addr;
        mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]);
 }
 
 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->mtimecmp_addr;
+       struct sbi_scratch *scratch;
+       struct aclint_mtimer_data *mt;
+       u64 *time_cmp;
+
+       scratch = sbi_hartid_to_scratch(target_hart);
+       if (!scratch)
+               return;
+
+       mt = mtimer_get_hart_data_ptr(scratch);
+       if (!mt)
+               return;
 
        /* Program MTIMER Time Compare */
+       time_cmp = (void *)mt->mtimecmp_addr;
        mt->time_wr(true, next_event,
                    &time_cmp[target_hart - mt->first_hartid]);
 }
@@ -126,8 +155,14 @@ int aclint_mtimer_warm_init(void)
 {
        u64 *mt_time_cmp;
        u32 target_hart = current_hartid();
-       struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart];
+       struct sbi_scratch *scratch;
+       struct aclint_mtimer_data *mt;
 
+       scratch = sbi_hartid_to_scratch(target_hart);
+       if (!scratch)
+               return SBI_ENOENT;
+
+       mt = mtimer_get_hart_data_ptr(scratch);
        if (!mt)
                return SBI_ENODEV;
 
@@ -147,6 +182,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 {
        u32 i;
        int rc;
+       struct sbi_scratch *scratch;
 
        /* Sanity checks */
        if (!mt ||
@@ -155,12 +191,18 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
            (mt->mtime_size && (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;
        if (reference && mt->mtime_freq != reference->mtime_freq)
                return SBI_EINVAL;
 
+       /* Allocate scratch space pointer */
+       if (!mtimer_ptr_offset) {
+               mtimer_ptr_offset = sbi_scratch_alloc_type_offset(void *);
+               if (!mtimer_ptr_offset)
+                       return SBI_ENOMEM;
+       }
+
        /* Initialize private data */
        aclint_mtimer_set_reference(mt, reference);
        mt->time_rd = mtimer_time_rd32;
@@ -174,9 +216,13 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
        }
 #endif
 
-       /* Update MTIMER hartid table */
-       for (i = 0; i < mt->hart_count; i++)
-               mtimer_hartid2data[mt->first_hartid + i] = mt;
+       /* Update MTIMER pointer in scratch space */
+       for (i = 0; i < mt->hart_count; i++) {
+               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
+               if (!scratch)
+                       return SBI_ENOENT;
+               mtimer_set_hart_data_ptr(scratch, mt);
+       }
 
        if (!mt->mtime_size) {
                /* Disable reading mtime when mtime is not available */