Hi,

I am unsure how to properly mask RISC-V timer interrupts in hardware
at or above IPL_CLOCK.  I think that would be cleaner than doing
another timer interrupt deferral thing.

But, just to get the ball rolling, here a first attempt at the timer
interrupt deferral thing for riscv64.  The motivation, as with every
other platform, is to eventually make it unnecessary for the machine
dependent code to know anything about the clock interrupt schedule.

The thing I'm most unsure about is where to retrigger the timer in the
PLIC code.  It seems right to do it from plic_setipl() because I want
to retrigger it before doing soft interrupt work, but I'm not sure.

Unless I'm missing something, I don't think I need to do anything in
the default interrupt handler code, i.e. riscv64_dflt_setipl(), right?

I have no riscv64 machine, so this is untested.  Would appreciate
tests and feedback.

-Scott

Index: include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/include/cpu.h,v
retrieving revision 1.12
diff -u -p -r1.12 cpu.h
--- include/cpu.h       10 Jun 2022 21:34:15 -0000      1.12
+++ include/cpu.h       1 Aug 2022 01:13:38 -0000
@@ -92,7 +92,7 @@ struct cpu_info {
        uint64_t                ci_lasttb;
        uint64_t                ci_nexttimerevent;
        uint64_t                ci_nextstatevent;
-       int                     ci_statspending;
+       volatile int            ci_timer_deferred;
 
        uint32_t                ci_cpl;
        uint32_t                ci_ipending;
Index: riscv64/clock.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/riscv64/clock.c,v
retrieving revision 1.3
diff -u -p -r1.3 clock.c
--- riscv64/clock.c     24 Jul 2021 22:41:09 -0000      1.3
+++ riscv64/clock.c     1 Aug 2022 01:13:38 -0000
@@ -21,6 +21,7 @@
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/evcount.h>
+#include <sys/stdint.h>
 #include <sys/timetc.h>
 
 #include <machine/cpufunc.h>
@@ -106,6 +107,17 @@ clock_intr(void *frame)
        int s;
 
        /*
+        * If the clock interrupt is masked, defer all clock interrupt
+        * work until the clock interrupt is unmasked from splx(9).
+        */
+       if (ci->ci_cpl >= IPL_CLOCK) {
+               ci->ci_timer_deferred = 1;
+               sbi_set_timer(UINT64_MAX);
+               return 0;
+       }
+       ci->ci_timer_deferred = 0;
+
+       /*
         * Based on the actual time delay since the last clock interrupt,
         * we arrange for earlier interrupt next time.
         */
@@ -132,30 +144,23 @@ clock_intr(void *frame)
 
        sbi_set_timer(nextevent);
 
-       if (ci->ci_cpl >= IPL_CLOCK) {
-               ci->ci_statspending += nstats;
-       } else {
-               nstats += ci->ci_statspending;
-               ci->ci_statspending = 0;
-
-               s = splclock();
-               intr_enable();
-
-               /*
-                * Do standard timer interrupt stuff.
-                */
-               while (ci->ci_lasttb < prevtb) {
-                       ci->ci_lasttb += tick_increment;
-                       clock_count.ec_count++;
-                       hardclock((struct clockframe *)frame);
-               }
+       s = splclock();
+       intr_enable();
 
-               while (nstats-- > 0)
-                       statclock((struct clockframe *)frame);
-
-               intr_disable();
-               splx(s);
+       /*
+        * Do standard timer interrupt stuff.
+        */
+       while (ci->ci_lasttb < prevtb) {
+               ci->ci_lasttb += tick_increment;
+               clock_count.ec_count++;
+               hardclock((struct clockframe *)frame);
        }
+
+       while (nstats-- > 0)
+               statclock((struct clockframe *)frame);
+
+       intr_disable();
+       splx(s);
 
        return 0;
 }
Index: dev/plic.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/dev/plic.c,v
retrieving revision 1.10
diff -u -p -r1.10 plic.c
--- dev/plic.c  6 Apr 2022 18:59:27 -0000       1.10
+++ dev/plic.c  1 Aug 2022 01:13:38 -0000
@@ -557,6 +557,10 @@ plic_setipl(int new)
        /* higher values are higher priority */
        plic_set_threshold(ci->ci_cpuid, new);
 
+       /* trigger deferred timer interrupt if cpl is now low enough */
+       if (ci->ci_timer_deferred && new < IPL_CLOCK)
+               sbi_set_timer(0);
+
        intr_restore(sie);
 }
 

Reply via email to