Re: panic: mi_switch: switch in a critical section

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Sat, 12 Jul 2025 18:10:03 UTC
On Fri, Jul 11, 2025 at 08:56:04AM +0000, Bjoern A. Zeeb wrote:
> 
> # sysctl debug.kdb.enter=1 db> cont
> panic: mi_switch: switch in a critical section
> cpuid = 3
> time = 1752224052
> KDB: stack backtrace:
> db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe007a575d00
> vpanic() at vpanic+0x136/frame 0xfffffe007a575e30
> panic() at panic+0x43/frame 0xfffffe007a575e90
> mi_switch() at mi_switch+0x1b7/frame 0xfffffe007a575eb0
> ast_scheduler() at ast_scheduler+0x45/frame 0xfffffe007a575ed0
> ast_handler() at ast_handler+0xe8/frame 0xfffffe007a575f10
> ast() at ast+0x20/frame 0xfffffe007a575f30
> fast_syscall_common() at fast_syscall_common+0x1a2/frame 0xfffffe007a575f30
> --- syscall (0, FreeBSD ELF64, syscall), rip = 0x9da5012b7aa, rsp = 0x9da4ce76fd8, rbp = 0x9da4ce77020 ---
> KDB: enter: panic
> [ thread pid 62399 tid 100210 ]
> Stopped at      kdb_enter+0x33: movq    $0,0x103c492(%rip)

We manage td->td_critnest with the plain C increments and decrements.
This is done both in the top level, and in interrupt handlers (real
handlers, not ithreads I mean).

In principle, if interrupt handlers always return with the same value of
the td_critnest field as entered, it is fine.  But if it is not, there
is a possibility of loosing updated.

I was not able to find a place where such case could occur.  Still, out
of caution, might be it makes sense to switch to interrupt-safe updates.
On x86 it is enough to use INC/DEC instructions, similar to pcb_flags with
it OR/AND.