git: 07ab87b60d08 - main - powerpc: powerpc_ipi_handler(): Stop first, preempt last
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 20 Oct 2026 16:47:23 UTC
The branch main has been updated by olce:
URL: https://cgit.FreeBSD.org/src/commit/?id=07ab87b60d08c665eab0b187e81a239145f9961d
commit 07ab87b60d08c665eab0b187e81a239145f9961d
Author: Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-10-17 17:38:59 +0000
Commit: Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-10-20 16:46:13 +0000
powerpc: powerpc_ipi_handler(): Stop first, preempt last
Preemption should happen last so that other IPIs have a chance to be
executed in due course, in particular hardclockintr(). So, move
handling of IPI_PREEMPT at the end.
An IPI_STOP/IPI_STOP_HARD request should be processed immediately to
avoid risks that further processing changes the system state on panic,
or worse itself causes another panic on corrupted kernel state.
While here, move IPI_AST handling just before IPI_PREEMPT. We currently
do not need to do anything for it, but if we were to, it is likely that
would have to happen after other IPIs but IPI_PREEMPT.
Reviewed by: jhibbits
Fixes: 9d5a22b928c2 ("MFp4: SMP support")
Fixes: 12640815f815 ("MFp4: SMP support")
Fixes: 7ed09a6778d3 ("powerpc: Rework IPI message processing")
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D60863
---
sys/powerpc/powerpc/mp_machdep.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index 114990a97cdb..ff08bd56ad58 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -302,17 +302,7 @@ powerpc_ipi_handler(void *arg)
ipimask = atomic_readandclear_32(&(pcpup->pc_ipimask));
if (ipimask == 0)
return (FILTER_STRAY);
- if (ipimask & (1 << IPI_AST)) {
- CTR1(KTR_SMP, "%s: IPI_AST", __func__);
- }
- if (ipimask & (1 << IPI_PREEMPT)) {
- CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
- sched_preempt(curthread);
- }
- if (ipimask & (1 << IPI_RENDEZVOUS)) {
- CTR1(KTR_SMP, "%s: IPI_RENDEZVOUS", __func__);
- smp_rendezvous_action();
- }
+ /* A stop request should not be delayed. Keep it first. */
if (ipimask & (1 << IPI_STOP)) {
/*
@@ -330,10 +320,26 @@ powerpc_ipi_handler(void *arg)
CPU_CLR_ATOMIC(cpuid, &started_cpus);
CTR1(KTR_SMP, "%s: IPI_STOP (restart)", __func__);
}
+ if (ipimask & (1 << IPI_RENDEZVOUS)) {
+ CTR1(KTR_SMP, "%s: IPI_RENDEZVOUS", __func__);
+ smp_rendezvous_action();
+ }
if (ipimask & (1 << IPI_HARDCLOCK)) {
CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
hardclockintr();
}
+ if (ipimask & (1 << IPI_AST)) {
+ CTR1(KTR_SMP, "%s: IPI_AST", __func__);
+ }
+ /*
+ * sched_preempt() causes an immediate switch to another thread when not
+ * executing in a critical section. In order to ensure that all other
+ * IPIs are processed in due course, it has to be called last.
+ */
+ if (ipimask & (1 << IPI_PREEMPT)) {
+ CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
+ sched_preempt(curthread);
+ }
return (FILTER_HANDLED);
}