# DF-4780 — corecstat attach-time kernel panic on original Atom (KKASSERT(sc->sc_version != 0) reachable for exactly the models probe() whitelists)

**File:** `sys/dev/powermng/corecstat/corecstat.c`
**Severity:** Low (attach-time kernel panic; debug/INVARIANTS builds panic, production
builds execute the "impossible" path) · **Confidence:** certain · **Bucket:** base:powermng

## Root cause

`corecstat_attach()` routes original Atoms (`sc_is_atom=1`, `sc_version=0`) like this
(corecstat.c:342-362):

```c
	if (node != NULL && cpu == BSRCPUMASK(node->members)) {
		... /* chip-representative cpu: create cpu_nodeN sensordev + PKG sensors */
	} else if (sc->sc_is_atom && sc->sc_version == 0) {
		return (ENXIO);                    /* non-representative cpus bail */
	}

	if (sc->sc_is_atom)
		corecstat_init_atom_cpu(sc, cpu);  /* KKASSERT(sc->sc_version != 0) !! */
	else
		corecstat_init_core_cpu(sc, cpu);
```

and `corecstat_init_atom_cpu()` opens with:

```c
	/* No Core C-state residency counters on old Atoms */
	KKASSERT(sc->sc_version != 0);         /* corecstat.c:424 */
```

The `else if` only diverts **non-representative** cpus. The chip-representative cpu of an
original Atom (models 0x1c/0x26/0x27/0x35/0x36 — all explicitly whitelisted by
`corecstat_probe()` at corecstat.c:186-191) falls straight into
`corecstat_init_atom_cpu()` with `sc_version == 0` — violating the driver's own
invariant on every original-Atom system (`child_no` of a CHIP node is its child count,
sys/kern/subr_cpu_topology.c:125, and is ≥1 on any real topology, so the representative
cpu always takes the first branch).

* **INVARIANTS builds** (`KKASSERT` active, sys/sys/systm.h:94-101 — LINT64-style
  configs, which include `device corecstat`): **kernel panic at attach** — boot-time
  doom if compiled in, panic on `kldload` otherwise. Reproduced on the guest:
  `panic: assertion "sc->sc_version != 0" failed in corecstat_init_atom_cpu`.
* **Production builds** (KKASSERT compiled out, systm.h:116-119): the "impossible"
  path executes — the representative original-Atom cpu registers Silvermont-only
  core C1 (MSR 0x660) / C6 (0x3fd) sensor probes. Both are `rdmsr_safe`-gated, so the
  damage is wrong-behavior, not corruption. Live-observed on the guest (console lines
  `msr node0 core5 C1 res. (0x00000660) not available` from a version-0 softc).

## Reproduce (guest)

```
sh build.sh     # builds: patchcpu.ko (CPUID substitution) + corecstat.ko
                # (stock source + "#define INVARIANTS 1" line 1 == debug-kernel build)
sh run.sh       # kldload patchcpu; kldload corecstat
# expected: cpu0..4 "attach returned 6" (ENXIO), cpu5: 3 pkg MSR rejections, then
#           panic: assertion "sc->sc_version != 0" failed in corecstat_init_atom_cpu
#           -> DDB, guest down (vm.sh status => down)
```

`patchcpu` only substitutes the CPUID model advertisement (cpu_id -> 0x00030661,
family 06h model 36h Cedarview — a model the driver itself whitelists); the panicked
code is the stock, unmodified driver.

## Fix

`fix.diff` guards the atom dispatch (`if (sc->sc_version != 0)`) so old Atoms get only
their package sensors, restoring the author's documented design ("Only Package
C-States available, no Core C-states", corecstat.c:267). Validated on the guest:
same trigger, fixed module → no panic, no core C1/C6 probes, clean load/unload.
