P2 asked whether the ENE at 0x27 has readable state. The answer had been reached twice by elimination, and the last link in that chain was a comment in a third party's patched OpenRGB detector, not a measurement of ours. probe-ene-receive-byte.sh runs the experiment the driver made possible on 2026-07-27, when PNTR_SEL (BIT(18)) gave us a bare Receive Byte: a read with no command byte on the wire cannot return a transform of a register that was never sent. It does, however, return the last command byte the chip received — 12/12 on both channels — so the value is still ours, not the device's. A Receive Byte taken from 0x31 after addressing 0x27 answers 0xff instead of the echo, which places the latch in the device and not in the iMC engine; empty addresses NACK, so the transaction is real. Everything here is read-only: Receive Byte and Read Byte Data at 0x27, SPD reads through ee1004 sysfs, and the four SPD serials compared before and after every run. Two engine behaviours the script has to work around, both measured: the first transaction on a channel answers with a stale value (hence the discarded warm-up read), and a read following a successful one usually NACKs, which one retry always clears — the P1 policy, confirmed. lore-thread-check.py is unrelated to the probe but shares the same motive: lore and patchwork now sit behind an Anubis bot check, so a shell cannot tell "not published" from "not allowed to look". The NNTP mirror can.
196 lines
8.9 KiB
Markdown
196 lines
8.9 KiB
Markdown
# Hardware measurements still owed to the submission
|
|
|
|
Three scripts, meant to be run by hand on an X299 (or Cascade Lake-X) system
|
|
with the PCU function `8086:2085`. None of them is run by CI and none is run by
|
|
`make test`.
|
|
|
|
Output of all three belongs in the cover letter or in a reply on the list, as
|
|
raw numbers. Do not paraphrase them.
|
|
|
|
| Script | Answers | Writes to hardware |
|
|
| --- | --- | --- |
|
|
| `watch-engine.sh` | Is firmware using the engine on this system? | no |
|
|
| `dump-pcu-config.sh` | Which PCU registers move on their own? Is there a TSOD polling control? | no |
|
|
| `probe-cf8-write.sh` | Is the CF8/CFC write really dropped, and does it raise an SMI? | **yes**, requires `--i-understand` |
|
|
|
|
Not part of the submission: `pre-poweroff-load.sh` — fixed, mixed SMBus load
|
|
to run before every poweroff of the A5 hang observation window (TODO.md E1),
|
|
identical in the `use_ecam=1` phase and the `use_ecam=0` counter-proof.
|
|
3-minute blocks: software effect stream (~2760 writes/s) → rapid hw/sw switch
|
|
burst → hardware effect → full SPD dump via ee1004 + serial integrity check.
|
|
Fully automatic: saves run context + any driver warnings to a per-run file in
|
|
`tools/pre-poweroff-runs/`, appends one summary line to
|
|
`pre-poweroff-load.log`, then — **only with `--poweroff`** — powers the
|
|
machine off (15 s grace, Ctrl-C aborts); without the flag it just reports and
|
|
exits. Run: `sudo ./tools/pre-poweroff-load.sh [minutes] [--poweroff]`
|
|
(default 30; re-execs under sudo by itself). The one exception: an SPD serial
|
|
mismatch saves everything and does NOT power off — investigate first.
|
|
|
|
## 1. `watch-engine.sh` — foreign activity (read-only)
|
|
|
|
Samples the six per-channel registers and reports every change that this
|
|
system's Linux side did not cause. Run it with the driver **unloaded**, so that
|
|
anything observed is firmware.
|
|
|
|
```bash
|
|
sudo ./tools/watch-engine.sh --seconds 3600
|
|
```
|
|
|
|
What the cover letter needs: a run of at least one hour, ideally across a
|
|
suspend/resume cycle, with the observed change count. A non-zero count on a
|
|
system means the driver must not be loaded there, and is itself a result worth
|
|
reporting.
|
|
|
|
## 2. `dump-pcu-config.sh` — register survey (read-only)
|
|
|
|
Dumps the function's 4 KB config space twice and diffs them, then prints the
|
|
neighbourhood of the offsets that matter.
|
|
|
|
```bash
|
|
sudo ./tools/dump-pcu-config.sh --settle 10
|
|
```
|
|
|
|
This is the search for the open item F2: the Broadwell-E iMC driver stops the
|
|
PCU's TSOD polling for the duration of a transfer by writing 0 to `TSODCNTL`
|
|
at offset `0xe0` of its PCU function, waiting 10 ms for in-flight transactions
|
|
to drain, and restoring the value afterwards. No equivalent register has been
|
|
identified on `8086:2085`. A field that changes on its own with a fixed cadence
|
|
is the first candidate.
|
|
|
|
## 3. `probe-cf8-write.sh` — the dropped write (WRITES TO HARDWARE)
|
|
|
|
This is the only script that writes. It changes the register/offset field of a
|
|
command register while the GO bit is clear, which does not start an SMBus
|
|
transaction, then reads it back and reports whether the write stuck. It also
|
|
reads `MSR_SMI_COUNT` (0x34) on every CPU before and after.
|
|
|
|
```bash
|
|
sudo ./tools/probe-cf8-write.sh --i-understand
|
|
```
|
|
|
|
Two results matter:
|
|
|
|
* the value does **not** read back → the claim "CF8/CFC writes to this function
|
|
do not take effect" is confirmed on the tested board;
|
|
* the SMI delta is **0** → the behaviour is not System Management Mode, and the
|
|
driver's comments and the cover letter must not say it is.
|
|
|
|
Requirements: `msr-tools` (`rdmsr`), `pciutils` (`setpci`, `lspci`), and the
|
|
`msr` module (`modprobe msr`).
|
|
|
|
## 4. `probe-cf8-transaction.sh` — does CF8/CFC start a transfer? (WRITES TO HARDWARE)
|
|
|
|
Follow-up to §3. `probe-cf8-write.sh` shows whether the register accepts a
|
|
value; this shows whether the engine acts on it, by setting the GO bit for a
|
|
read of an unpopulated address and watching STATUS.
|
|
|
|
```bash
|
|
sudo ./tools/probe-cf8-transaction.sh --i-understand
|
|
```
|
|
|
|
It does start one. That result retired the plan to reach these registers
|
|
through ECAM with a PCI-core change, and the driver uses the ordinary config
|
|
accessors.
|
|
|
|
## 5. `probe-imc-documented.sh` — the interface Intel documents (WRITES TO HARDWARE)
|
|
|
|
Issues a read through `SMB_STAT`/`SMBCMD`/`SMBCNTL` on the iMC channel
|
|
functions (`8086:2040`), the interface the datasheet describes, rather than the
|
|
PCU registers this driver uses.
|
|
|
|
```bash
|
|
sudo ./tools/probe-imc-documented.sh --i-understand
|
|
```
|
|
|
|
On the development board it reports `RDO=1, SBE=0, RDATA=0x00` identically for
|
|
a populated 0x50, a populated 0x52 and an absent 0x57: it completes but cannot
|
|
tell a populated slot from an empty one, so it is not reaching this bus.
|
|
|
|
## 6. `probe-pntr-sel.sh` — find the address-only bit (read-only on the bus)
|
|
|
|
Finds the command-word bit that suppresses the register byte, which is what
|
|
SMBus Receive Byte and Send Byte need.
|
|
|
|
```bash
|
|
sudo ./tools/probe-pntr-sel.sh --i-understand --channel 1
|
|
```
|
|
|
|
Not a blind sweep. An EEPROM auto-increments its pointer after a read, so
|
|
priming the pointer with an ordinary read and then repeating it with the
|
|
candidate bit set has a predicted answer: the *next* byte, not the one named.
|
|
The script checks that prediction at two different offsets and then walks eight
|
|
consecutive reads, which an ordinary dump must reproduce exactly.
|
|
|
|
The answer on this engine is bit 18, matching the position of `PNTR_SEL`
|
|
relative to `WORD_ACCESS` in the documented `SMBCMD` layout. Reads only, and
|
|
never to the page-select addresses, so the DDR4 page latch does not move.
|
|
|
|
## 7. `probe-send-byte.sh` — the write half (WRITES TO HARDWARE)
|
|
|
|
Confirms the same bit produces a Send Byte, against the page-select addresses
|
|
`0x36`/`0x37`. Those hold a latch and store no data, so the only thing a write
|
|
there can do is choose which half of the SPD is visible — and that choice is
|
|
itself the readout, since byte 0x00 is the JEDEC `0x23` on page 0 and something
|
|
else on page 1. Nothing is written to `0x50`-`0x57`.
|
|
|
|
```bash
|
|
sudo ./tools/probe-send-byte.sh --i-understand --channel 0 --restore
|
|
```
|
|
|
|
`--restore` is the safe first run: it targets a channel already stuck on page 1
|
|
and selects page 0, so a working Send Byte repairs that channel and a broken one
|
|
leaves it exactly as found. There is no outcome worse than the starting state.
|
|
`--flip` does the full round trip on a healthy channel, after `--restore` has
|
|
shown the encoding works.
|
|
|
|
A channel found on page 1 is not a fault of this driver: `ee1004`, and
|
|
OpenRGB's `DDR4DirectAccessor::set_page()`, both select a page and leave it
|
|
selected.
|
|
|
|
## 8. `lore-thread-check.py` — "la patch è stata pubblicata? qualcuno ha risposto?"
|
|
|
|
Niente hardware: interroga l'archivio **NNTP** di lore, `nntp.lore.kernel.org:119`,
|
|
e dice (a) se un message-id è nell'archivio della lista, con gli header veri, e
|
|
(b) quali articoli successivi appartengono allo stesso thread. Sola lettura, il
|
|
server rifiuta il posting comunque.
|
|
|
|
```bash
|
|
./tools/lore-thread-check.py [email protected]
|
|
./tools/lore-thread-check.py <msgid> --group org.kernel.vger.linux-kernel
|
|
```
|
|
|
|
Esce `0` se il messaggio è archiviato, `1` se non c'è, `2` su errore.
|
|
|
|
> ⚠️ Esiste perché dal browser o con `curl` la risposta è ingannevole:
|
|
> `lore.kernel.org` e `patchwork.kernel.org` stanno dietro il bot-check **Anubis**
|
|
> e restituiscono 403 o la pagina *"Making sure you're not a bot!"* al posto del
|
|
> messaggio — che si legge facilmente come "la patch non è mai stata pubblicata".
|
|
> Il mirror NNTP non ha il challenge. Per patchwork non esiste equivalente: lì
|
|
> serve un browser vero.
|
|
|
|
## 9. `probe-ene-receive-byte.sh` — la Receive Byte a 0x27 (read-only)
|
|
|
|
L'esperimento di `TODO.md` §P2, e le sue varianti diagnostiche. Nessuna
|
|
scrittura, su nessun indirizzo: solo Receive Byte e Read Byte Data verso `0x27`
|
|
e letture SPD dai nodi sysfs di `ee1004`. Le quattro seriali SPD sono
|
|
confrontate prima e dopo a ogni run e una differenza è errore fatale.
|
|
|
|
```bash
|
|
sudo systemctl stop furyd # lo script rifiuta di partire con furyd attivo
|
|
sudo ./tools/probe-ene-receive-byte.sh --rounds 12 # l'esperimento
|
|
sudo ./tools/probe-ene-receive-byte.sh --latch-test # eco del command byte + cross-address
|
|
sudo ./tools/probe-ene-receive-byte.sh --map # ri-deriva l'artefatto N>>2
|
|
sudo ./tools/probe-ene-receive-byte.sh --addr-sweep # stessa read su altri indirizzi
|
|
sudo systemctl start furyd
|
|
```
|
|
|
|
Esito del 2026-08-10 (log in `docs/evidence/2026-08-10-ene-*.log`): la Receive
|
|
Byte restituisce l'**eco dell'ultimo command byte** mandato a quel chip (12/12,
|
|
due canali), il latch è del device e non dell'engine (da `0x31` torna `0xff`),
|
|
gli indirizzi vuoti NACKano. **L'ENE non ha stato leggibile** — ora misurato.
|
|
|
|
> ⚠️ Due trappole, valgono per qualunque misura su questo engine: la **prima**
|
|
> transazione di un canale restituisce un valore stale (per questo lo script fa
|
|
> un read di warm-up scartato), e la lettura successiva a una riuscita NACKa
|
|
> spesso — un solo retry la pulisce sempre, come dice P1.
|