# DF-5640 — TSC cputimer registered with unvalidated `tsc_frequency` → division by zero (boot-time panic)

File: `sys/cpu/x86_64/misc/cputimer_tsc.c` (pass 2) · Severity: **Low** (CWE-369)

## What

`tsc_cputimer_register()` (cputimer_tsc.c:122-171) copies the
hardware/calibration-derived global `tsc_frequency` into `tsc_cputimer.freq`
(cputimer_tsc.c:145-146) **without validation**, then
`cputimer_select(&tsc_cputimer, 0)` (cputimer_tsc.c:156) →
`cputimer_set_frequency(timer, timer->freq)` (kern/kern_cputimer.c:99) →

```c
timer->freq64_usec = (1000000LL << 32) / freq;    /* kern_cputimer.c:190 */
```

`tsc_frequency == 0` (failed calibration, clock.c:980-1043) combined with
`tsc_mpsync == 1` (`hw.tsc_cputimer_force=1` — clock.c:871/1522, the tunable
the kernel recommends for qemu — or the `ncpus == 1` early-out at
clock.c:1513-1516) ⇒ integer division by zero ⇒ **fatal trap 18 during boot**.
The `regcnt:` invariant-not-mpsync path likewise installs
`tsc_cpucounter.freq = tsc_frequency` unvalidated (cputimer_tsc.c:162).

Low severity: the trigger requires a loader (root) tunable or broken/lying
hardware; there is no unprivileged runtime surface (boot SYSINIT only, all
globals sysctl-RD after boot).

## Reproduce on the dfbsd-qemu guest

```sh
./build.sh    # builds df5640.ko on the guest against /usr/src
./run.sh      # kldload -> Fatal trap 18 (integer divide fault) at
              # cputimer_select+0x29 (divq); guest drops to DDB, ssh dies
```

The harness replays cputimer_tsc.c:145-156 verbatim (replica timer,
`tsc_frequency = 0`, real `cputimer_register()`/`cputimer_select()` entry
points, `pri = CPUTIMER_PRI_DUMMY-1` so only the pre-pri-check sink call at
kern_cputimer.c:99 can fire). The faulting instruction is in production code,
not the harness.

Also in the pack:

- `forced_boot_dmesg.txt` — the **real** production path, no harness: booting
  with `hw.tsc_cputimer_force=1` runs the whole qualification state machine
  and the genuine registration (`TSC: cputimer freq 3600008821`,
  `kern.cputimer.name: TSC`).
- `env.txt` — stock guest introspection (HPET selected; `tsc_mpsync=0`,
  `tsc_invariant=0` — the file is inert on the stock config).

Methodology constraint (why kldload-time replay): boot-loaded KLDs link at
`SI_BOOT2_KLD` (0x1e00000), *after* `SI_BOOT2_POST_SMP` (0x1cc0000), so no
boot-loaded module can precondition the globals before the registration
SYSINIT runs — established empirically, see VERDICT.md.

## Fix validation

`fix.diff` guards the producer (cputimer_tsc.c: both the mpsync path and the
`regcnt:` path refuse `tsc_frequency == 0`) and the sink
(kern_cputimer.c: `cputimer_set_frequency()` refuses zero). Applied in the
guest's /usr/src, `make nativekernel + installkernel`, rebooted:

- identical harness: `cputimer: refusing zero frequency for DF5640 (cputimer
  unchanged)` — **no trap**, module load returns, system healthy (`fix_run.log`);
- legit path regression check: forced boot still selects the TSC cputimer
  (`fix_forced_boot.txt`).

See `VERDICT.md` for the full narrative and attempt log.
