git: 3a0e2ca3eecd - main - x86: ipi_bitmap_handler(): Account for IPIs correctly on COUNT_IPIS

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Tue, 20 Oct 2026 16:47:21 UTC
The branch main has been updated by olce:

URL: https://cgit.FreeBSD.org/src/commit/?id=3a0e2ca3eecd3176fa7dd139e59913a67c858ac9

commit 3a0e2ca3eecd3176fa7dd139e59913a67c858ac9
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-10-13 14:46:26 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-10-20 16:46:13 +0000

    x86: ipi_bitmap_handler(): Account for IPIs correctly on COUNT_IPIS
    
    A preemption could occur before the updates to the initial CPU's IPI
    counters, leading to a potential non-atomic updates of these counters
    from another CPU.
    
    Reviewed by:    kib
    Fixes:          ff326a187907 ("x86: Restore the critical section (...)")
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D60862
---
 sys/x86/x86/mp_x86.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 8fdeff859561..abdc18feb5f8 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -1347,14 +1347,21 @@ ipi_bitmap_handler(struct trapframe *frame)
 	td->td_intr_nesting_level++;
 	oldframe = td->td_intr_frame;
 	td->td_intr_frame = frame;
+
+#ifdef COUNT_IPIS
+	if (ipi_bitmap & (1 << IPI_AST)) {
+		(*ipi_ast_counts[cpu])++;
+	if (ipi_bitmap & (1 << IPI_HARDCLOCK)) {
+		(*ipi_hardclock_counts[cpu])++;
+	if (ipi_bitmap & (1 << IPI_PREEMPT))
+		(*ipi_preempt_counts[cpu])++;
+#endif
+
 #if defined(STACK) || defined(DDB)
 	if (ipi_bitmap & (1 << IPI_TRACE))
 		stack_capture_intr();
 #endif
 	if (ipi_bitmap & (1 << IPI_HARDCLOCK)) {
-#ifdef COUNT_IPIS
-		(*ipi_hardclock_counts[cpu])++;
-#endif
 		/*
 		 * Enter a critical section so that hardclockintr() can execute
 		 * entirely without preemption (as it calls code that can enter
@@ -1371,9 +1378,6 @@ ipi_bitmap_handler(struct trapframe *frame)
 		critical_exit();
 	}
 	if (ipi_bitmap & (1 << IPI_AST)) {
-#ifdef COUNT_IPIS
-		(*ipi_ast_counts[cpu])++;
-#endif
 		/* Nothing to do for AST */
 	}
 	/*
@@ -1382,13 +1386,8 @@ ipi_bitmap_handler(struct trapframe *frame)
 	 * IPIs are processed in due course (in particular, hardclockintr()), it
 	 * has to be called last.
 	 */
-	if (ipi_bitmap & (1 << IPI_PREEMPT)) {
-#ifdef COUNT_IPIS
-		(*ipi_preempt_counts[cpu])++;
-#endif
-		if (do_preempt)
-			sched_preempt(td);
-	}
+	if (ipi_bitmap & (1 << IPI_PREEMPT) && do_preempt)
+		sched_preempt(td);
 	td->td_intr_frame = oldframe;
 	td->td_intr_nesting_level--;
 }