summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-08-09 04:40:09 +0000
committerScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-08-09 04:40:09 +0000
commiteb271bbf049b099f905d8e2191de9e49b6bc4f70 (patch)
tree50d2e6b0895c3b627804fdcd13d1ce95bd968c84 /sys/arch
parentf35e53196e820d63b533298688c38c3e1f1f4b65 (diff)
powerpc64: trigger deferred DEC interrupts from splx(9)
In order to move to a machine-independent clock interrupt subsystem, the powerpc64 clock interrupt code needs to work without knowing anything about the clock interrupt schedule. The easiest way to do this is, if the DEC fires while the CPU's IPL is at or above IPL_CLOCK, to postpone clock interrupt work until the clock interrupt is logically unmasked from splx(9). Because we no longer defer work until the next tick, we don't need to keep track of pending statclock ticks in the cpu_info struct. With input from kettenis@. Graciously compiled and tested by gkoehler@ and kettenis@. Link: https://marc.info/?l=openbsd-tech&m=165862522102767&w=2 ok kettenis@ gkoehler@.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/powerpc64/include/cpu.h4
-rw-r--r--sys/arch/powerpc64/powerpc64/clock.c52
-rw-r--r--sys/arch/powerpc64/powerpc64/intr.c7
3 files changed, 36 insertions, 27 deletions
diff --git a/sys/arch/powerpc64/include/cpu.h b/sys/arch/powerpc64/include/cpu.h
index 7825e62dfbc..7df5a2ba921 100644
--- a/sys/arch/powerpc64/include/cpu.h
+++ b/sys/arch/powerpc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.31 2021/07/06 09:34:07 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.32 2022/08/09 04:40:08 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -74,9 +74,9 @@ struct cpu_info {
uint64_t ci_lasttb;
uint64_t ci_nexttimerevent;
uint64_t ci_nextstatevent;
- int ci_statspending;
volatile int ci_cpl;
+ volatile int ci_dec_deferred;
uint32_t ci_ipending;
uint32_t ci_idepth;
#ifdef DIAGNOSTIC
diff --git a/sys/arch/powerpc64/powerpc64/clock.c b/sys/arch/powerpc64/powerpc64/clock.c
index 204ce0fcac2..31d1769e109 100644
--- a/sys/arch/powerpc64/powerpc64/clock.c
+++ b/sys/arch/powerpc64/powerpc64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.3 2021/02/23 04:44:31 cheloha Exp $ */
+/* $OpenBSD: clock.c,v 1.4 2022/08/09 04:40:08 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -98,6 +98,17 @@ decr_intr(struct trapframe *frame)
int s;
/*
+ * 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.
*/
@@ -130,30 +141,23 @@ decr_intr(struct trapframe *frame)
mtdec(nextevent - tb);
mtdec(nextevent - mftb());
- if (ci->ci_cpl >= IPL_CLOCK) {
- ci->ci_statspending += nstats;
- } else {
- nstats += ci->ci_statspending;
- ci->ci_statspending = 0;
-
- 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);
-
- intr_disable();
- splx(s);
+ 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);
+
+ intr_disable();
+ splx(s);
}
void
diff --git a/sys/arch/powerpc64/powerpc64/intr.c b/sys/arch/powerpc64/powerpc64/intr.c
index ebcf4ef7ba8..022db1b6446 100644
--- a/sys/arch/powerpc64/powerpc64/intr.c
+++ b/sys/arch/powerpc64/powerpc64/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.10 2022/07/27 20:26:17 kettenis Exp $ */
+/* $OpenBSD: intr.c,v 1.11 2022/08/09 04:40:08 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -139,6 +139,11 @@ splx(int new)
{
struct cpu_info *ci = curcpu();
+ if (ci->ci_dec_deferred && new < IPL_CLOCK) {
+ mtdec(0);
+ mtdec(UINT32_MAX); /* raise DEC exception */
+ }
+
if (ci->ci_ipending & intr_smask[new])
intr_do_pending(new);