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++;