DF-5722 / fix.diff
--- a/sys/platform/pc64/x86_64/db_interface.c +++ b/sys/platform/pc64/x86_64/db_interface.c @@ -102,6 +102,7 @@ static jmp_buf db_global_jmpbuf; static int db_global_jmpbuf_valid; +static int db_saved_critcount; /* * kdb_trap - field a TRACE or BPT trap */ int kdb_trap(int type, int code, struct x86_64_saved_state *regs) { volatile int ddb_mode = !(boothowto & RB_GDB); @@ -158,7 +159,9 @@ kdb_trap(int type, int code, struct x86_64_saved_state *regs) /* * XXX We really should switch to a local stack here. */ ddb_regs = *regs; crit_enter(); + db_saved_critcount = curthread->td_critcount; db_printf("\nCPU%d stopping CPUs: 0x%08jx\n", mycpu->gd_cpuid, (uintmax_t)CPUMASK_LOWMASK(mycpu->gd_other_cpus)); @@ -198,7 +201,10 @@ kdb_trap(int type, int code, struct x86_64_saved_state *regs) restart_cpus(stopped_cpus); } db_printf(" restarted\n"); - crit_exit(); + /* + * Force-restore the interrupted context's critical section count: + * debugger paths (polled console, IPI handling) can lose a count + * when the session was entered from interrupt context, which + * otherwise underflows here and panics with + * "td_critcount is/would-go negative". + */ + curthread->td_critcount = db_saved_critcount; regs->tf_rip = ddb_regs.tf_rip; ``` |