summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-11-29 01:04:45 +0000
committerScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-11-29 01:04:45 +0000
commite4a2c825a848052b2f19fefce2448c8226944713 (patch)
treee5f31893f4f175c0a6ac635b94a3f5e85e0c15ca
parent6240c372569aa7cddcfe8b56552b7dc38a35ac47 (diff)
powerpc64: switch to clockintr
- Remove powerpc64-specific clock interrupt scheduling bits from cpu_info. - Remove powerpc64-specific randomized statclock() bits from powerpc64/clock.c. - Remove the 'stat_count' evcount. All clock interrupts are now counted via the 'clock_count' evcount. - Wire up dec_intrclock. Bringup help from gkoehler@. Tested by gkoehler@: this patch has survived four kernel-release-upgrade cycles on a Raptor Talos II T2P9S01 sporting a quad-core POWER9 CPU. Link: https://marc.info/?l=openbsd-tech&m=166776404803622&w=2 ok gkoehler@ mlarkin@
-rw-r--r--sys/arch/powerpc64/include/_types.h4
-rw-r--r--sys/arch/powerpc64/include/cpu.h9
-rw-r--r--sys/arch/powerpc64/powerpc64/clock.c139
3 files changed, 58 insertions, 94 deletions
diff --git a/sys/arch/powerpc64/include/_types.h b/sys/arch/powerpc64/include/_types.h
index c93d8b0d84e..63fd7c9c63b 100644
--- a/sys/arch/powerpc64/include/_types.h
+++ b/sys/arch/powerpc64/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.2 2020/05/27 22:22:04 gkoehler Exp $ */
+/* $OpenBSD: _types.h,v 1.3 2022/11/29 01:04:44 cheloha Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -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];
diff --git a/sys/arch/powerpc64/include/cpu.h b/sys/arch/powerpc64/include/cpu.h
index 7df5a2ba921..0a8cdb33631 100644
--- a/sys/arch/powerpc64/include/cpu.h
+++ b/sys/arch/powerpc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.32 2022/08/09 04:40:08 cheloha Exp $ */
+/* $OpenBSD: cpu.h,v 1.33 2022/11/29 01:04:44 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -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;
diff --git a/sys/arch/powerpc64/powerpc64/clock.c b/sys/arch/powerpc64/powerpc64/clock.c
index 20e81c62414..87ec0650067 100644
--- a/sys/arch/powerpc64/powerpc64/clock.c
+++ b/sys/arch/powerpc64/powerpc64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.6 2022/11/05 16:23:02 cheloha Exp $ */
+/* $OpenBSD: clock.c,v 1.7 2022/11/29 01:04:44 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@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