powerpc64: trigger deferred DEC interrupts from splx(9)
authorcheloha <cheloha@openbsd.org>
Tue, 9 Aug 2022 04:40:08 +0000 (04:40 +0000)
committercheloha <cheloha@openbsd.org>
Tue, 9 Aug 2022 04:40:08 +0000 (04:40 +0000)
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@.

sys/arch/powerpc64/include/cpu.h
sys/arch/powerpc64/powerpc64/clock.c
sys/arch/powerpc64/powerpc64/intr.c

index 7825e62..7df5a2b 100644 (file)
@@ -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
index 204ce0f..31d1769 100644 (file)
@@ -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>
@@ -97,6 +97,17 @@ decr_intr(struct trapframe *frame)
        int nstats;
        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
index ebcf4ef..022db1b 100644 (file)
@@ -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);