From f27ca60c2fcbf90cdebcf57245e97d9e6d6421bf Mon Sep 17 00:00:00 2001 From: cheloha Date: Tue, 9 Aug 2022 04:40:08 +0000 Subject: [PATCH] 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@. --- sys/arch/powerpc64/include/cpu.h | 4 +-- sys/arch/powerpc64/powerpc64/clock.c | 52 +++++++++++++++------------- sys/arch/powerpc64/powerpc64/intr.c | 7 +++- 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 @@ -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 @@ -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 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 @@ -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); -- 2.20.1