DF-5607 / fix.diff
--- a/sys/platform/vkernel64/x86_64/exception.c 2026-10-08 15:08:18.200358517 +0000 +++ b/sys/platform/vkernel64/x86_64/exception.c 2026-10-08 15:08:26.636249987 +0000 @@ -58,6 +58,9 @@ int _ucodesel = GSEL(GUCODE_SEL, SEL_UPL); int _udatasel = GSEL(GUDATA_SEL, SEL_UPL); +/* per-pthread re-entrancy guard (cothreads run with %gs == 0) */ +static __thread int exc_nesting; + static void exc_segfault(int signo, siginfo_t *info, void *ctx); #ifdef DDB static void exc_debugger(int signo, siginfo_t *info, void *ctx); @@ -263,12 +266,39 @@ exc_segfault(int signo, siginfo_t *info, void *ctxp) { ucontext_t *ctx = ctxp; + struct sigaction sa; + sigset_t ss; int save; + if (exc_nesting) { + /* + * Fault inside the fault path (e.g. a cothread, which + * runs with %gs == 0 per tls_set_gs(0), cothread.c:149, + * faulting on kern_trap's mycpu load). SA_NODEFER + + * empty sa_mask would recurse until the host kills us + * with no diagnostic; die honestly instead. + */ + static char msg[] = + "vkernel: recursive fault in exc_segfault\n"; + + write(2, msg, sizeof(msg) - 1); + bzero(&sa, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(signo, &sa, NULL); + sigemptyset(&ss); + sigaddset(&ss, signo); + sigprocmask(SIG_UNBLOCK, &ss, NULL); + raise(signo); + /* NOT REACHED */ + _exit(127); + } + exc_nesting = 1; save = errno; kern_trap((struct trapframe *)&ctx->uc_mcontext.mc_rdi); splz(); errno = save; + exc_nesting = 0; } #ifdef DDB |