On Sun, 6 Nov 2022 19:52:36 +0000 Scott Cheloha <scottchel...@gmail.com> wrote:
> This patch switches powerpc64 to clockintr(9). > > gkoehler@ has been testing it, I assume on some kind of Raptor > Computing Power9. It has survived two parallel release builds and > upgrades from the resulting bsd.rd. It's a Raptor Talos II T2P9S01 with a 4-core POWER9, and did its 3rd and 4th releases and upgrades. ok gkoehler@ > > Testing on an additional powerpc64 machine would help. > > Notes: > > - There are no longer separate interrupt counters for "clock" and > "stat". > > Index: sys/arch/powerpc64/include/cpu.h > =================================================================== > RCS file: /cvs/src/sys/arch/powerpc64/include/cpu.h,v > retrieving revision 1.32 > diff -u -p -r1.32 cpu.h > --- sys/arch/powerpc64/include/cpu.h 9 Aug 2022 04:40:08 -0000 1.32 > +++ sys/arch/powerpc64/include/cpu.h 6 Nov 2022 19:50:34 -0000 > @@ -46,6 +46,7 @@ > #include <machine/psl.h> > #include <machine/pte.h> > > +#include <sys/clockintr.h> > #include <sys/device.h> > #include <sys/sched.h> > #include <sys/srp.h> > @@ -71,10 +72,8 @@ struct cpu_info { > register_t ci_tempsave[CPUSAVE_LEN]; > register_t ci_idle_sp_save; > > - uint64_t ci_lasttb; > - uint64_t ci_nexttimerevent; > - uint64_t ci_nextstatevent; > - > + struct clockintr_queue ci_queue; > + > volatile int ci_cpl; > volatile int ci_dec_deferred; > uint32_t ci_ipending; > Index: sys/arch/powerpc64/include/_types.h > =================================================================== > RCS file: /cvs/src/sys/arch/powerpc64/include/_types.h,v > retrieving revision 1.2 > diff -u -p -r1.2 _types.h > --- sys/arch/powerpc64/include/_types.h 27 May 2020 22:22:04 -0000 > 1.2 > +++ sys/arch/powerpc64/include/_types.h 6 Nov 2022 19:50:34 -0000 > @@ -34,6 +34,8 @@ > #ifndef _MACHINE__TYPES_H_ > #define _MACHINE__TYPES_H_ > > +#define __HAVE_CLOCKINTR > + > #if defined(_KERNEL) > typedef struct label_t { > long val[22]; > Index: sys/arch/powerpc64/powerpc64/clock.c > =================================================================== > RCS file: /cvs/src/sys/arch/powerpc64/powerpc64/clock.c,v > retrieving revision 1.6 > diff -u -p -r1.6 clock.c > --- sys/arch/powerpc64/powerpc64/clock.c 5 Nov 2022 16:23:02 -0000 > 1.6 > +++ sys/arch/powerpc64/powerpc64/clock.c 6 Nov 2022 19:50:34 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: clock.c,v 1.6 2022/11/05 16:23:02 cheloha Exp $ */ > +/* $OpenBSD: clock.c,v 1.5 2022/08/11 17:15:21 cheloha Exp $ */ > > /* > * Copyright (c) 2020 Mark Kettenis <kette...@openbsd.org> > @@ -20,19 +20,26 @@ > #include <sys/param.h> > #include <sys/kernel.h> > #include <sys/systm.h> > +#include <sys/clockintr.h> > #include <sys/evcount.h> > +#include <sys/stdint.h> > #include <sys/timetc.h> > > #include <machine/cpufunc.h> > > extern uint64_t tb_freq; /* cpu.c */ > - > -uint64_t tick_increment; > -uint64_t statmin; > -uint32_t statvar; > +uint64_t dec_nsec_cycle_ratio; > +uint64_t dec_nsec_max; > > struct evcount clock_count; > -struct evcount stat_count; > + > +void dec_rearm(void *, uint64_t); > +void dec_trigger(void *); > + > +const struct intrclock dec_intrclock = { > + .ic_rearm = dec_rearm, > + .ic_trigger = dec_trigger > +}; > > u_int tb_get_timecount(struct timecounter *); > > @@ -49,6 +56,33 @@ static struct timecounter tb_timecounter > > void cpu_startclock(void); > > +void > +dec_rearm(void *unused, uint64_t nsecs) > +{ > + u_long s; > + uint32_t cycles; > + > + if (nsecs > dec_nsec_max) > + nsecs = dec_nsec_max; > + cycles = (nsecs * dec_nsec_cycle_ratio) >> 32; > + if (cycles > UINT32_MAX >> 1) > + cycles = UINT32_MAX >> 1; > + s = intr_disable(); > + mtdec(cycles); > + intr_restore(s); > +} > + > +void > +dec_trigger(void *unused) > +{ > + u_long s; > + > + s = intr_disable(); > + mtdec(0); > + mtdec(UINT32_MAX); > + intr_restore(s); > +} > + > u_int > tb_get_timecount(struct timecounter *tc) > { > @@ -61,15 +95,14 @@ cpu_initclocks(void) > tb_timecounter.tc_frequency = tb_freq; > tc_init(&tb_timecounter); > > - tick_increment = tb_freq / hz; > + dec_nsec_cycle_ratio = tb_freq * (1ULL << 32) / 1000000000; > + dec_nsec_max = UINT64_MAX / dec_nsec_cycle_ratio; > > stathz = 100; > profhz = 1000; /* must be a multiple of stathz */ > - > - setstatclockrate(stathz); > + clockintr_init(CL_RNDSTAT); > > evcount_attach(&clock_count, "clock", NULL); > - evcount_attach(&stat_count, "stat", NULL); > > cpu_startclock(); > } > @@ -77,14 +110,8 @@ cpu_initclocks(void) > void > cpu_startclock(void) > { > - struct cpu_info *ci = curcpu(); > - uint64_t nextevent; > - > - ci->ci_lasttb = mftb(); > - ci->ci_nexttimerevent = ci->ci_lasttb + tick_increment; > - nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent; > - > - mtdec(nextevent - ci->ci_lasttb); > + clockintr_cpu_init(&dec_intrclock); > + clockintr_trigger(); > intr_enable(); > } > > @@ -92,71 +119,25 @@ void > decr_intr(struct trapframe *frame) > { > struct cpu_info *ci = curcpu(); > - uint64_t tb, prevtb; > - uint64_t nextevent; > - uint32_t r; > - int nstats; > int s; > > + clock_count.ec_count++; > + > + mtdec(UINT32_MAX >> 1); /* clear DEC exception */ > + > /* > * If the clock interrupt is masked, postpone all work until > * it is unmasked in splx(9). > */ > if (ci->ci_cpl >= IPL_CLOCK) { > ci->ci_dec_deferred = 1; > - mtdec(UINT32_MAX >> 1); /* clear DEC exception */ > return; > } > ci->ci_dec_deferred = 0; > > - /* > - * Based on the actual time delay since the last decrementer reload, > - * we arrange for earlier interrupt next time. > - */ > - > - tb = mftb(); > - > - while (ci->ci_nexttimerevent <= tb) > - ci->ci_nexttimerevent += tick_increment; > - > - prevtb = ci->ci_nexttimerevent - tick_increment; > - > - for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) { > - do { > - r = random() & (statvar - 1); > - } while (r == 0); /* random == 0 not allowed */ > - ci->ci_nextstatevent += statmin + r; > - } > - stat_count.ec_count += nstats; > - > - if (ci->ci_nexttimerevent < ci->ci_nextstatevent) > - nextevent = ci->ci_nexttimerevent; > - else > - nextevent = ci->ci_nextstatevent; > - > - /* > - * Transition of the MSB will trigger a decrementer interrupt. > - * So the next sequence is guaranteed to do the job without a > - * systematic skew. > - */ > - mtdec(nextevent - tb); > - mtdec(nextevent - mftb()); > - > 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); > - } > - > - while (nstats-- > 0) > - statclock((struct clockframe *)frame); > - > + clockintr_dispatch(frame); > intr_disable(); > splx(s); > } > @@ -164,25 +145,7 @@ decr_intr(struct trapframe *frame) > void > setstatclockrate(int newhz) > { > - uint64_t stat_increment; > - uint64_t min_increment; > - uint32_t var; > - u_long msr; > - > - msr = intr_disable(); > - > - stat_increment = tb_freq / newhz; > - var = 0x40000000; /* really big power of two */ > - /* Find largest 2^n which is nearly smaller than statint/2. */ > - min_increment = stat_increment / 2 + 100; > - while (var > min_increment) > - var >>= 1; > - > - /* Not atomic, but we can probably live with that. */ > - statmin = stat_increment - (var >> 1); > - statvar = var; > - > - intr_restore(msr); > + clockintr_setstatclockrate(newhz); > } > > void -- George Koehler <kern...@gmail.com>