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>

Reply via email to