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