On Sun, Nov 20, 2022 at 03:15:55PM -0500, George Koehler wrote: > On Sun, 20 Nov 2022 06:55:23 -0600 > Scott Cheloha <scottchel...@gmail.com> wrote: > > > Build completed, upgrade from resulting bsd.rd completed. I think > > this is ready to commit. > > I'm happy to hear that your dual G4 macppc is running and your diff > works. Your clock diff doesn't conflict with my incomplete suspend > diff, because we are editing different files. (My PowerBook G4 can > suspend but not resume, so my diff isn't ready to commit.) > > I want to mention one little detail, > > > @@ -54,7 +58,14 @@ u_int tb_get_timecount(struct timecounte > > */ > > u_int32_t ticks_per_sec = 3125000; > > u_int32_t ns_per_tick = 320; > > -static int32_t ticks_per_intr; > > +uint64_t dec_nsec_cycle_ratio; > > +uint64_t dec_nsec_max; > > +static int initialized; > > + > > +const struct intrclock dec_intrclock = { > > + .ic_rearm = dec_rearm, > > + .ic_trigger = dec_trigger > > +}; > > > > static struct timecounter tb_timecounter = { > > .tc_get_timecount = tb_get_timecount, > > The old "static int32_t ticks_per_intr;" was visible in ddb, > > ddb> x/ld ticks_per_intr,1 > ticks_per_intr: 184320 > > I don't like "static int initialized;" because its name is too > generic, so "x/ld initialized,1" might examine the wrong file's > "initialized". > > I prefer a less generic name, perhaps > "int clock_initialized;" > > If it isn't "static", the linker might check that it doesn't have > the same name as another variable. I don't need you to try another > "make build" if you rename this variable.
Alright, I changed it to a non-static "clock_initialized". Kernel compiles, boots, etc. Will go ahead with the attached patch shortly. Index: sys/arch/macppc/macppc/clock.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/clock.c,v retrieving revision 1.50 diff -u -p -r1.50 clock.c --- sys/arch/macppc/macppc/clock.c 8 Sep 2022 03:06:33 -0000 1.50 +++ sys/arch/macppc/macppc/clock.c 21 Nov 2022 20:30:41 -0000 @@ -35,7 +35,9 @@ #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/autoconf.h> @@ -46,6 +48,8 @@ #include <dev/clock_subr.h> #include <dev/ofw/openfirm.h> +void dec_rearm(void *, uint64_t); +void dec_trigger(void *); void decr_intr(struct clockframe *frame); u_int tb_get_timecount(struct timecounter *); @@ -54,7 +58,14 @@ u_int tb_get_timecount(struct timecounte */ u_int32_t ticks_per_sec = 3125000; u_int32_t ns_per_tick = 320; -static int32_t ticks_per_intr; +uint64_t dec_nsec_cycle_ratio; +uint64_t dec_nsec_max; +int clock_initialized; + +const struct intrclock dec_intrclock = { + .ic_rearm = dec_rearm, + .ic_trigger = dec_trigger +}; static struct timecounter tb_timecounter = { .tc_get_timecount = tb_get_timecount, @@ -75,15 +86,8 @@ static const char *calibrate_tc_models[] time_read_t *time_read; time_write_t *time_write; -/* vars for stats */ -int statint; -u_int32_t statvar; -u_int32_t statmin; - static struct evcount clk_count; -static struct evcount stat_count; static int clk_irq = PPC_CLK_IRQ; -static int stat_irq = PPC_STAT_IRQ; extern todr_chip_handle_t todr_handle; struct todr_chip_handle rtc_todr; @@ -115,18 +119,16 @@ rtc_settime(struct todr_chip_handle *han void decr_intr(struct clockframe *frame) { - u_int64_t tb; - u_int64_t nextevent; struct cpu_info *ci = curcpu(); - int nstats; int s; - /* - * Check whether we are initialized. - */ - if (!ticks_per_intr) + if (!clock_initialized) return; + clk_count.ec_count++; /* XXX not atomic */ + + ppc_mtdec(UINT32_MAX >> 1); /* clear DEC exception */ + /* * We can't actually mask DEC interrupts at or above IPL_CLOCK * without masking other essential interrupts. To simulate @@ -135,73 +137,15 @@ decr_intr(struct clockframe *frame) */ if (ci->ci_cpl >= IPL_CLOCK) { ci->ci_dec_deferred = 1; - ppc_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 = ppc_mftb(); - while (ci->ci_nexttimerevent <= tb) - ci->ci_nexttimerevent += ticks_per_intr; - - ci->ci_prevtb = ci->ci_nexttimerevent - ticks_per_intr; - - for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) { - int r; - do { - r = random() & (statvar -1); - } while (r == 0); /* random == 0 not allowed */ - ci->ci_nextstatevent += statmin + r; - } - - /* only count timer ticks for CLK_IRQ */ - stat_count.ec_count += nstats; - - if (ci->ci_nexttimerevent < ci->ci_nextstatevent) - nextevent = ci->ci_nexttimerevent; - else - nextevent = ci->ci_nextstatevent; - - /* - * Need to work about the near constant skew this introduces??? - * reloading tb here could cause a missed tick. - */ - ppc_mtdec(nextevent - tb); - - nstats += ci->ci_statspending; - ci->ci_statspending = 0; - s = splclock(); - - /* - * Reenable interrupts - */ ppc_intr_enable(1); - - /* - * Do standard timer interrupt stuff. - */ - while (ci->ci_lasttb < ci->ci_prevtb) { - /* sync lasttb with hardclock */ - ci->ci_lasttb += ticks_per_intr; - clk_count.ec_count++; - hardclock(frame); - } - - while (nstats-- > 0) - statclock(frame); - + clockintr_dispatch(frame); splx(s); (void) ppc_intr_disable(); - - /* if a tick has occurred while dealing with these, - * dont service it now, delay until the next tick. - */ } void cpu_startclock(void); @@ -210,7 +154,6 @@ void cpu_initclocks(void) { int intrstate; - int minint; u_int32_t first_tb, second_tb; time_t first_sec, sec; int calibrate = 0, n; @@ -242,6 +185,7 @@ cpu_initclocks(void) ticks_per_sec); #endif } + ns_per_tick = 1000000000 / ticks_per_sec; tb_timecounter.tc_frequency = ticks_per_sec; tc_init(&tb_timecounter); @@ -252,23 +196,16 @@ cpu_initclocks(void) intrstate = ppc_intr_disable(); - ticks_per_intr = ticks_per_sec / hz; - stathz = 100; profhz = 1000; /* must be a multiple of stathz */ + clockintr_init(CL_RNDSTAT); - /* init secondary clock to stathz */ - statint = ticks_per_sec / stathz; - statvar = 0x40000000; /* really big power of two */ - /* find largest 2^n which is nearly smaller than statint/2 */ - minint = statint / 2 + 100; - while (statvar > minint) - statvar >>= 1; - statmin = statint - (statvar >> 1); + dec_nsec_cycle_ratio = ticks_per_sec * (1ULL << 32) / 1000000000; + dec_nsec_max = UINT64_MAX / dec_nsec_cycle_ratio; evcount_attach(&clk_count, "clock", &clk_irq); - evcount_attach(&stat_count, "stat", &stat_irq); + clock_initialized = 1; cpu_startclock(); ppc_intr_enable(intrstate); @@ -277,21 +214,8 @@ cpu_initclocks(void) void cpu_startclock(void) { - struct cpu_info *ci = curcpu(); - u_int64_t nextevent; - - ci->ci_lasttb = ppc_mftb(); - - /* - * no point in having random on the first tick, - * it just complicates the code. - */ - ci->ci_nexttimerevent = ci->ci_lasttb + ticks_per_intr; - nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent; - - ci->ci_statspending = 0; - - ppc_mtdec(nextevent - ci->ci_lasttb); + clockintr_cpu_init(&dec_intrclock); + clockintr_trigger(); } /* @@ -308,35 +232,41 @@ delay(unsigned n) ; } -/* - * Nothing to do. - */ void setstatclockrate(int newhz) { - int minint; - int intrstate; - - intrstate = ppc_intr_disable(); - - statint = ticks_per_sec / newhz; - statvar = 0x40000000; /* really big power of two */ - /* find largest 2^n which is nearly smaller than statint/2 */ - minint = statint / 2 + 100; - while (statvar > minint) - statvar >>= 1; - - statmin = statint - (statvar >> 1); - ppc_intr_enable(intrstate); - - /* - * XXX this allows the next stat timer to occur then it switches - * to the new frequency. Rather than switching instantly. - */ + clockintr_setstatclockrate(newhz); } u_int tb_get_timecount(struct timecounter *tc) { return ppc_mftbl(); +} + +void +dec_rearm(void *unused, uint64_t nsecs) +{ + uint32_t cycles; + int s; + + 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 = ppc_intr_disable(); + ppc_mtdec(cycles); + ppc_intr_enable(s); +} + +void +dec_trigger(void *unused) +{ + int s; + + s = ppc_intr_disable(); + ppc_mtdec(0); + ppc_mtdec(UINT32_MAX); + ppc_intr_enable(s); } Index: sys/arch/powerpc/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/powerpc/include/cpu.h,v retrieving revision 1.73 diff -u -p -r1.73 cpu.h --- sys/arch/powerpc/include/cpu.h 21 Oct 2022 21:26:49 -0000 1.73 +++ sys/arch/powerpc/include/cpu.h 21 Nov 2022 20:30:41 -0000 @@ -36,6 +36,7 @@ #include <machine/frame.h> +#include <sys/clockintr.h> #include <sys/device.h> #include <sys/sched.h> #include <sys/srp.h> @@ -72,11 +73,7 @@ struct cpu_info { #define DISISAVE_LEN 4 register_t ci_disisave[DISISAVE_LEN]; - volatile u_int64_t ci_nexttimerevent; - volatile u_int64_t ci_prevtb; - volatile u_int64_t ci_lasttb; - volatile u_int64_t ci_nextstatevent; - int ci_statspending; + struct clockintr_queue ci_queue; volatile int ci_ddb_paused; #define CI_DDB_RUNNING 0 Index: sys/arch/powerpc/include/_types.h =================================================================== RCS file: /cvs/src/sys/arch/powerpc/include/_types.h,v retrieving revision 1.23 diff -u -p -r1.23 _types.h --- sys/arch/powerpc/include/_types.h 5 Mar 2018 01:15:25 -0000 1.23 +++ sys/arch/powerpc/include/_types.h 21 Nov 2022 20:30:41 -0000 @@ -35,6 +35,8 @@ #ifndef _POWERPC__TYPES_H_ #define _POWERPC__TYPES_H_ +#define __HAVE_CLOCKINTR + #if defined(_KERNEL) typedef struct label_t { long val[25];