Re: riscv64: use sstc for clocks when available
Mike Larkin <[email protected]> Tue, 28 Jul 2026 19:13:26 -0700
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Jul 26, 2026 at 07:33:58PM +0200, Jeremie Courreges-Anglas wrote: > On Mon, Jul 13, 2026 at 09:18:20AM -0700, Nick Owens wrote: > > hi, > > Hi, sorry for the delay ;) > > > this implements support for sstc extension. with sstc, we can write the > > stimecmp csr directly instead of needing an sbi ecall to set the timer > > comparison register. > > > > both the k1 and k3 support it, and since it's a direct register write it > > takes only ~10ns instead of several hundred ns for the ecall and > > possible hypervisor emulation in the case of linux kvm. > > > > i've tested on orangepi rv2 (k1) directly, and on the k3 under linux > > kvm. fallback path tested on kvm by disabling sstc in the advertised > > features of qemu kvm as well. without sstc, the k1 takes about 250ns and > > the k3 + kvm takes about 600ns. with this change, both are around 10ns > > per timer write. > > > > this also conveniently works around a bug in upstream kvm where timer > > writes via sbi ecall can get lost if there's a context switch at the > > wrong time, which makes kvm guest timers permanently stop firing. see > > https://lore.kernel.org/all/[email protected]/ > > Getting rid of this overhead appears desirable, working around a bug > in a hypervisor is just a bonus... > > No visible regression on my k1 which exposes Sstc. Please find a > tweaked diff below: I'd rather have the check for the feature in a > single place. The "timer_set_timer" name is admittedly a bit > redundant, suggestions welcome. > > I'll commit this in a few days unless I hear objections. Tests & oks > welcome. > > ok mlarkin > Index: clock.c > =================================================================== > RCS file: /cvs/src/sys/arch/riscv64/riscv64/clock.c,v > diff -u -p -r1.14 clock.c > --- clock.c 27 Jan 2024 12:05:40 -0000 1.14 > +++ clock.c 24 Jul 2026 14:54:28 -0000 > @@ -25,6 +25,7 @@ > #include <sys/stdint.h> > #include <sys/timetc.h> > > +#include <machine/elf.h> > #include <machine/cpufunc.h> > #include <machine/sbi.h> > > @@ -60,6 +61,15 @@ static struct timecounter tb_timecounter > void (*cpu_startclock_fcn)(void) = timer_startclock; > int clock_intr(void *); > > +static inline void > +timer_set_timer(uint64_t nsecs) > +{ > + if (riscv_hwcap & HWCAP_ISA_SSTC) > + csr_write(stimecmp, nsecs); > + else > + sbi_set_timer(nsecs); > +} > + > void > timer_rearm(void *unused, uint64_t nsecs) > { > @@ -68,13 +78,13 @@ timer_rearm(void *unused, uint64_t nsecs > if (nsecs > timer_nsec_max) > nsecs = timer_nsec_max; > cycles = (nsecs * timer_nsec_cycle_ratio) >> 32; > - sbi_set_timer(rdtime() + cycles); > + timer_set_timer(rdtime() + cycles); > } > > void > timer_trigger(void *unused) > { > - sbi_set_timer(0); > + timer_set_timer(0); > } > > u_int > @@ -125,7 +135,7 @@ clock_intr(void *frame) > struct cpu_info *ci = curcpu(); > int s; > > - sbi_set_timer(UINT64_MAX); /* clear timer interrupt */ > + timer_set_timer(UINT64_MAX); /* clear timer interrupt */ > > /* > * If the clock interrupt is masked, defer all clock interrupt > > > -- > jca >