On Sun, 6 Nov 2022 19:52:36 +0000
Scott Cheloha <[email protected]> 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 <[email protected]>
> @@ -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 <[email protected]>