# DF-5611 — SIGXCPU omitted from the vkernel's signal-block sets → one host signal silently kills the whole vkernel

**Finding:** `cpu_mask_all_signals()` (sys/platform/vkernel64/platform/machintr.c:204-210)
and `cpu_disable_intr()` (machintr.c:191-196) deliberately omit SIGXCPU from
the sets of host signals they block. SIGXCPU's handler `stopsig()`
(sys/platform/vkernel64/x86_64/exception.c:108-137) dereferences `mycpu`
(%gs-relative) *before* doing anything else — so a **process-directed SIGXCPU
that the host kernel routes to any cothread (%gs == 0) faults at the mycpu
load and kills the entire vkernel via the DF-5587 unbounded
exc_segfault→kern_trap→mycpu recursion: no panic, no dump request, no console
output.** The same omission in `cpu_disable_intr()` leaves SIGXCPU deliverable
to a freshly-created AP vCPU pthread during the window between
`pthread_create()` (mp.c:462-465) and `init_secondary()`'s `tls_set_gs()`
(mp.c:369), where %gs is still the pthread TCB, not a `privatespace`.

Distinct from DF-5607 (fault signals on cothreads — those *cannot* be masked
without breaking the vkernel fault mechanism): SIGXCPU is asynchronous and
*maskable in cothreads without side effects*, because `stop_cpus()` /
`restart_cpus()` only ever `pthread_kill()` vCPU threads (mp.c:239, mp.c:260)
and a running vCPU unblocks everything at `cpu_idle` entry
(cpu_enable_intr → sigsetmask(0), cpu_regs.c:485). Natural triggers:
RLIMIT_CPU soft-limit expiry (the host kernel sends process-directed
SIGXCPU), or any same-uid host process / admin `kill -XCPU <vkernel-pid>`.

## Reproduce (guest, root)

```
sh build.sh          # /vkroot.img + siglog.so + kernel.debug (see env notes)
sh run.sh            # ctrl1(control) fault1-3(fault) fixed1-2(after fix.diff)
```

Success criterion (baseline): `RESULT: DEAD at iteration 1`, console shows
`SIGLOG: XCPU-IN thr=<cothread> gs=0x0` immediately before silent death, and
`gdb kernel.debug kernel.debug.core` reports `signal 4 (SIGILL)` with the
innermost frames `_get_mycpu (thread.h:77) ← kern_trap (trap.c:585) ←
exc_segfault (exception.c:269)` on the cothread process, the vCPU threads
parked in `umtx_sleep`. After `fix.diff`: `RESULT: ALIVE after 40 SIGXCPU
sends`, all `XCPU-IN` lines on vCPU threads (nonzero %gs).

## Files

- `siglog.c` — LD_PRELOAD **observation-only** shim (wraps sigaction(SIGXCPU),
  pthread_create, sigblock; logs thread id + %gs base at delivery time).
  The trigger itself is a real `kill -XCPU` from the driver.
- `run5611.sh` — boot/kill driver (control | fault modes).
- `image5611.sh`, `buildk.sh`, `build.sh`, `run.sh` — rig.
- `fix.diff` — add SIGXCPU to both sigblock sets (+ comment), validated.
- `panic.txt` — gdb backtrace of the death core (both fault runs identical).
- `env.txt`, `logs/` — full driver + console logs (ctrl/fault1-3/fixed1-2).

## Observed (3/3 baseline runs, 2/2 fixed runs)

```
baseline fault1-3: DEAD at iteration 1; XCPU-IN thr=0x800a92dc0 (cothread #1,
                   start=cothread_thread) gs=0x0; core: signal 4, #0 _get_mycpu
                   thread.h:77 / #1 kern_trap trap.c:585 / #2 exc_segfault
                   exception.c:269; vCPUs parked in umtx_sleep.
fixed1-2:          ALIVE after 40 sends; every XCPU-IN on the BSP vCPU
                   (thr=0x800a930c0, gs=0x8000400000 = privatespace);
                   runtime sigblock masks 0x20c0a000 / 0x6840e804 now include
                   the SIGXCPU bit (0x800000); boot unregressed.
```
