--- a/sys/platform/vkernel64/x86_64/exception.c +++ b/sys/platform/vkernel64/x86_64/exception.c @@ -58,6 +58,8 @@ int _ucodesel = GSEL(GUCODE_SEL, SEL_UPL); int _udatasel = GSEL(GUDATA_SEL, SEL_UPL); +static int exc_nesting; /* exc_segfault re-entrancy guard */ + static void exc_segfault(int signo, siginfo_t *info, void *ctx); #ifdef DDB static void exc_debugger(int signo, siginfo_t *info, void *ctx); @@ -266,7 +268,26 @@ int save; save = errno; + if (atomic_fetchadd_int(&exc_nesting, 1) != 0) { + /* + * Fault inside the fault path (e.g. a cothread, which runs + * with %gs == 0, 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); + signal(SIGSEGV, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGTRAP, SIG_DFL); + signal(SIGFPE, SIG_DFL); + raise(signo); + /* NOT REACHED */ + } kern_trap((struct trapframe *)&ctx->uc_mcontext.mc_rdi); + atomic_subtract_int(&exc_nesting, 1); splz(); errno = save; }