# DF-5155 — perfbias: raw wrmsr/rdmsr(MSR_IA32_ENERGY_PERF_BIAS) panics on CPUID-lying platforms (DF-4735 class)

## What this is
`perfbias_set_handler()` (sys/dev/powermng/perfbias/perfbias.c:178-179) writes and
reads MSR 0x1b0 with the raw, non-fault-safe accessors, gated only by
CPUID.06H.ECX bit 3 (`CPUID_THERMAL2_SETBH`, checked live in `perfbias_identify()`,
perfbias.c:102-103). On any CPU/VMM that advertises the CPUID bit without
implementing the MSR — the exact "lying CPUID" class proven for MSR 0x19c in
DF-4735 on this same guest — the raw `wrmsr` takes a fatal #GP in kernel mode:

```
Fatal trap 9: general protection fault while in kernel mode
Stopped at      pbtest_modevent+0xad:   wrmsr
db>
```

Reach of the stock compiled-in driver (`device perfbias`, X86_64_GENERIC:173):
root-only — `sysctl -w machdep.perfbiasN.hint=0..15` (write needs
`SYSCAP_NOSYSCTL_WR`, kern_sysctl.c:1446-1447) and driver detach
(`perfbias_set(sc, 0)`, perfbias.c:152). Severity: Low (privileged DoS), same
bucket/calibration as DF-4735 (coretemp).

## Build
```
mkdir -p /tmp/pbmod && cp pbtest.c /tmp/pbmod/ && cd /tmp/pbmod
printf 'KMOD=\tpbtest\nSRCS=\tpbtest.c\n\n.include <bsd.kmod.mk>\n' > Makefile
make SYSDIR=/usr/src/sys
```

## Run (on a platform where MSR 0x1b0 faults, e.g. this KVM guest with `-cpu host`)
```
kldload /tmp/pbmod/pbtest.ko
```

## Expected
```
pbtest: rdmsr_safe -> error 14, val 0
pbtest: wrmsr_safe -> error 14
pbtest: raw wrmsr now (perfbias.c:178 path) -- expect #GP panic
Fatal trap 9: general protection fault while in kernel mode
Stopped at      pbtest_modevent+0xad:   wrmsr
db>
```
Guest dead in DDB (`vm.sh status` -> down). Full console in `run.log` /
`panic.txt`.

## Fix-path replica (post-fix semantics, loads harmlessly)
`pbfix.c` = the patched handler body (wrmsr_safe/rdmsr_safe + error return):
```
pbfix: patched handler returns error 14 (sysctl writer gets EIO, no trap)
```

## Fix validation
`fix.diff` (git-apply-able, validated to apply exactly): `wrmsr_safe`/`rdmsr_safe`
+ error propagation through `cpuhelper_replymsg` -> `perfbias_set` -> sysctl.
Applied to guest /usr/src, single-fix kernel built with
`make -j6 nativekernel KERNCONF=X86_64_GENERIC` (-Werror, build.log), installed,
booted clean; `pbfix.ko` loaded on the patched kernel demonstrates the fixed
path returning error 14 where the baseline trapped (run.2.log).

## Honest gap (same as DF-4735)
KVM masks CPUID.06H.ECX bit 3 on this guest (perfbias_identify never opens the
gate: no `machdep.perfbias0.hint` under `-cpu host`), so the stock driver path
cannot fire on this VMM. The trigger module executes the identical
instruction pair (perfbias.c:178-179) in kernel context on a platform where the
MSR provably faults — the consequence (fatal trap 9, unrecoverable) is
reproduced; only the CPUID advertisement is substituted by the root kldload.
