Okay, we did this for powerpc/macppc, on to powerpc64.

It's roughly the same problem as before:

- On powerpc64 we need to leave the DEC unmasked at or above
  IPL_CLOCK.

- Currently we defer clock interrupt work to the next tick if a DEC
  interrupt arrives when the CPU's priority level is at or above
  IPL_CLOCK.

- This is a problem because the MD code needs to know about
  when the next clock interrupt event is scheduled and I intend
  to make that information machine-independent and handle it
  in machine-independent code in the future.

- This patch instead defers clock interrupt work to the next splx(9)
  call where the CPU's priority level is dropping below IPL_CLOCK.
  This requires no knowledge of when the next clock interrupt
  event is scheduled.

The code is almost identical to what we did for powerpc/macppc,
except that:

- We can do the ci_dec_deferred handling in trap(), which is a
  bit cleaner.

- There is only one splx() function that needs modifying.

Unless I'm missing something, we no longer need the struct member
cpu_info.ci_statspending.

I don't have a powerpc64 machine, so this is untested.  I would
appreciate tests and review.  If you're copied on this, I'm under the
impression you have a powerpc64 machine or know someone who might.

Thoughts?  Test results?

I'm really sorry if this doesn't work out of the box and your machine
hangs.

Index: include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/powerpc64/include/cpu.h,v
retrieving revision 1.31
diff -u -p -r1.31 cpu.h
--- include/cpu.h       6 Jul 2021 09:34:07 -0000       1.31
+++ include/cpu.h       24 Jul 2022 01:08:22 -0000
@@ -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: powerpc64/clock.c
===================================================================
RCS file: /cvs/src/sys/arch/powerpc64/powerpc64/clock.c,v
retrieving revision 1.3
diff -u -p -r1.3 clock.c
--- powerpc64/clock.c   23 Feb 2021 04:44:31 -0000      1.3
+++ powerpc64/clock.c   24 Jul 2022 01:08:22 -0000
@@ -130,30 +130,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();
 
-               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);
-               }
+       /*
+        * 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);
+       while (nstats-- > 0)
+               statclock((struct clockframe *)frame);
 
-               intr_disable();
-               splx(s);
-       }
+       intr_disable();
+       splx(s);
 }
 
 void
Index: powerpc64/intr.c
===================================================================
RCS file: /cvs/src/sys/arch/powerpc64/powerpc64/intr.c,v
retrieving revision 1.9
diff -u -p -r1.9 intr.c
--- powerpc64/intr.c    26 Sep 2020 17:56:54 -0000      1.9
+++ powerpc64/intr.c    24 Jul 2022 01:08:22 -0000
@@ -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);
 
Index: powerpc64/trap.c
===================================================================
RCS file: /cvs/src/sys/arch/powerpc64/powerpc64/trap.c,v
retrieving revision 1.51
diff -u -p -r1.51 trap.c
--- powerpc64/trap.c    11 May 2021 18:21:12 -0000      1.51
+++ powerpc64/trap.c    24 Jul 2022 01:08:22 -0000
@@ -65,9 +65,15 @@ trap(struct trapframe *frame)
        switch (type) {
        case EXC_DECR:
                uvmexp.intrs++;
-               ci->ci_idepth++;
-               decr_intr(frame);
-               ci->ci_idepth--;
+               if (ci->ci_cpl < IPL_CLOCK) {
+                       ci->ci_decr_deferred = 0;
+                       ci->ci_idepth++;
+                       decr_intr(frame);
+                       ci->ci_idepth--;
+               } else {
+                       ci->ci_decr_deferred = 1;
+                       mtdec(UINT32_MAX >> 1); /* clear DEC exception */
+               }
                return;
        case EXC_EXI:
                uvmexp.intrs++;

Reply via email to