On Sat, Nov 19, 2022 at 09:46:03AM -0600, Scott Cheloha wrote:
> On Sun, Nov 06, 2022 at 07:48:31PM +0000, Scott Cheloha wrote:
> > This patch switches macppc to clockintr(9).
> >
> > It has survived two or three parallel release builds on my G4 MDD
> > (PowerMac7,3) and upgrades from the resulting bsd.rd. The machine
> > does not have a working IDE drive at the moment, so I booted and built
> > over USB 1.1 on an external drive.
> >
> > It needs testing on a beefier Mac. It should probably also be tested
> > on a Mac with a working graphics card.
> >
> > I am aware of gkoehler@'s work on suspend/resume. We'll need to
> > coordinate this to avoid breaking things.
> >
> > Notes:
> >
> > - There are no longer separate counters for "clock" and "stat".
>
> I bought a SATA/PATA adapter and, to my surprise, it worked! I had an
> older Kingston SATA SDD lying around and lo, the G4 now boots from
> that over the PATA ribbon. What a time to be alive!
>
> The mac is doing a parallel build (`make -j2 build`) atop a kernel
> with the attached patch right now. Still up after two days.
> Accelerated graphics do not work on this machine, but I think the
> radeon card is just semi-fried... pretty sure it has nothing to do
> with the patch.
>
> Assuming the build completes and the install from the resulting bsd.rd
> succeeds, can I commit this?
>
> Trying to avoid trampling on whatever gkoehler@ is doing.
>
> ok?
Build completed, upgrade from resulting bsd.rd completed. I think
this is ready to commit.
Looking for an ok.
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 19 Nov 2022 15:44:22 -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;
+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,
@@ -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 (!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);
+ 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 19 Nov 2022 15:44:22 -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 19 Nov 2022 15:44:22 -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];