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); }