# DF-5568 — vkernel64 `vktimer_intr_reload()`: wakeup CAS loop is dead code (`(sysclock_t) … < 0` unsigned compare)

## What

`sys/platform/vkernel64/platform/systimer.c:301-303`:

```c
	if (vktimer_cotd && (ssysclock_t)(reload - vktimer_target) < 0) {
		while ((sysclock_t)(reload - vktimer_target) < 0)      /* <-- BUG */
			reload = atomic_swap_long(&vktimer_target, reload);
		cothread_wakeup(vktimer_cotd, &vktimer_ts);
	}
```

`sysclock_t` is `__uint64_t` (`sys/sys/systimer.h:51`). The `while`
condition casts the wrap-around delta to an **unsigned** type and then
compares `< 0` — always false. The loop body (`atomic_swap_long` target
lowering, the lock-free protocol intended to pull `vktimer_target` down to
the earliest deadline seen by any vcpu) **never executes**. The `if` five
lines up uses the correct `(ssysclock_t)` (int64_t) cast for the identical
expression — the `while` cast is a typo.

Consequences (all measured, see run logs):
- the atomic target-lowering protocol is inert; `vktimer_target` is only
  ever updated by the cothread itself (`systimer.c:263`);
- every earlier-than-stale-target reload re-fires `cothread_wakeup()` →
  `pthread_kill(SIGINT)` (cothread.c:192-197) instead of only those that
  lower the target — redundant signal churn under dense one-shot timer
  load (checklist (a) amplification);
- the intended narrowing of the reload-vs-cothread wakeup race is absent.

NOT affected: timer delivery itself — 10 ms sleeps are exact
(ratio 1.000) and the vkernel runs to completion on both builds; the
1 ms-sleep 10x quantization seen in both runs is the *documented*
coarse-timer clamp at `systimer.c:275-282` (`use_precise_timer == 0`,
default per init.c:126; `-t` boot flag enables precise mode) — it is
identical before and after the fix.

## How it was proven (A/B instrumented kernels)

Two vkernel64 kernels were built in the guest (`nativekernel
KERNCONF=VKERNEL64`, DF-5474 `--defsym` link workaround):

- `kernel.instr`  — stock logic + two counters exposed as
  `debug.vkt_if` (entries into the `if` body) and `debug.vkt_swap`
  (executions of the `while` body). See `instr.diff`.
- `kernel.fixed`  — same + the one-cast fix (`(sysclock_t)` →
  `(ssysclock_t)` in the `while`). See `instrfix.diff` (verification
  build) and `fix.diff` (the clean, shippable fix).

Each kernel booted with `-n 2` on `/vkroot2.img`; inside the vkernel:
counter read T0 → `drift` (timer sanity) → two 20 s `hog` processes
(dense 2 ms one-shot sleeps driving `vktimer_intr_reload`) → counter
read T1.

| build | vkt_if T0→T1 | vkt_swap T0→T1 | drift 10ms | vkernel |
|---|---|---|---|---|
| stock `(sysclock_t)` | 16042 → 42294 | **0 → 0** | 1.000 | alive |
| fixed `(ssysclock_t)` | 12411 → 32540 | **12515 → 32722** | 1.000 | alive |

42,294 opportunities, zero executions on stock; ~1:1 execution with the
fix. The only delta between the two kernels is the cast. QED.

## Reproduce

On the DragonFly guest as root (files from this pack in /root):

```sh
sh build.sh          # binaries + /vkroot2.img + kernel.instr + kernel.fixed
sh run.sh /root/kernel.instr instr    # stock   -> expect vkt_swap: 0
sh run.sh /root/kernel.fixed fixed    # patched -> expect vkt_swap > 0
```

Expected decisive output (inside the vkernel console, after the hogs):

```
# sysctl debug.vkt_if; sysctl debug.vkt_swap
debug.vkt_if: 42294          (stock: large)
debug.vkt_swap: 0            (stock: ZERO  -> CAS body dead)
```

`mkdir -p /var/vkernel` and `sysctl vm.vkernel_enable=1` are required
before the first boot. Root fs is specified as `ufs:vkd0` at the
`mountroot>` prompt (fed automatically by run.sh).

## Fix

`fix.diff` — one-character-class change:

```diff
-		while ((sysclock_t)(reload - vktimer_target) < 0)
+		while ((ssysclock_t)(reload - vktimer_target) < 0)
```

Validated: with the fix the loop executes under the same workload, timer
behavior is unchanged (drift 1.000 both builds, hogs complete, no panic),
and the vkernel stays alive.
