# DF-4904 — Unsigned underflow in Phase-1 voltage ramp writes malformed MSR 0xc0010041

**File:** `sys/dev/powermng/powernow/powernow.c:231,260-262`
**Severity:** Low · **Bucket:** base:dev · **Confidence:** likely (type bug certain; hardware impact conditional)

## Root cause

```c
uint32_t val;                                    /* powernow.c:231 */
while (cvid > vid) {                             /* powernow.c:260 */
        val = cvid - (1 << cstate->mvs);         /* powernow.c:261 */
        WRITE_FIDVID(cfid, (val > 0) ? val : 0, 1ULL);  /* powernow.c:262 */
```

`val` is `uint32_t`; `cvid - (1 << mvs)` is computed in `int` and goes
negative whenever the current VID is smaller than one MVS step (e.g.
cvid=1, mvs=2 ⇒ −3).  Assignment wraps to `0xFFFFFFFD`, so the intended
clamp `(val > 0) ? val : 0` can never fire (unsigned values are always
≥ 0, and `0xFFFFFFFD > 0` is true).  `WRITE_FIDVID` (powernow.c:76-78)
then shifts that word `<< 8` into MSR `MSR_AMDK7_FIDVID_CTL`
(0xc0010041): bits 13-31 (reserved + control fields) receive garbage and
the programmed VID is `0x1d` instead of `0`.

On K8 silicon, writing reserved bits of FID_VID_CTL either #GPs
(kernel panic) or misprograms the voltage-change control logic.  The
path runs whenever a downward voltage transition begins with
`cvid < (1 << mvs)` — reachable at module load via the DF-4903 route
(powernow_init:392 → setperf drives vid toward 0) or whenever root
writes a lower target to `machdep.powernow.frequency.target`
(powernow.c:323-335; sysctl writes are privilege-gated,
kern_sysctl.c:1446).

## Harness (logic-level, run on guest as uid=1001 — run.log)

```
cvid=1 vid=0 mvs=2  ->  cvid-(1<<mvs) = -3
stored in uint32_t val     = 0xfffffffd
(val > 0) as evaluated     = TRUE   <-- underflow slips through
WRMSR(0xc0010041) value    = 0x000000fffffffd0a
  VID field (bits 8-12)    = 0x1d
  bits 13-31 (reserved)    = 0x7ffff  <-- garbage written
```

## Verification status

`untested` at kernel level: the MSR write requires AMD K8 (guest is
Intel/QEMU; module gate refuses, `MOD_LOAD error 2` — env.txt).

## Recommended fix

Do the arithmetic in signed and clamp before the unsigned narrowing —
`val = cvid - (1 << mvs); WRITE_FIDVID(cfid, (val >= 0 && cvid > (1 << mvs)) ? ... ` —
see `fix.diff` (makes `val` `int`).

## Build / run

```
cc -Wall -O2 -o sim_vidunderflow sim_vidunderflow.c && ./sim_vidunderflow
```
