sili_pm: pm_read/pm_write recycle the ata_xfer while the chip still owns the slot β deferred poll timeout returns ATA_S_ONCHIP and the accessors put the ccb back on the free list with ap_expired processing pending
Summary
The accessors put_xfer on ANY non-COMPLETE return; when the poll timeout defers because other commands are on-chip, ata_cmd returns with state==ONCHIP - the ccb is recycled while the slot is still programmed and ap_active/expired bits set. Slot reuse trips the sili_poll KKASSERT (INVARIANTS panic); later expiry drain completes the re-issued ccb prematurely (cross-command corruption); a stale never-clearing ap_active bit wedges exclusive_access forever. DF-4503 twin. Wait-for-off-chip fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4693 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.5 KB | β raw | |
| VERDICT.md | β | 3.4 KB | β raw | |
| trigger_sili_pm.c | β | 3.1 KB | view raw | |
| build.sh | β | 120 B | view raw | |
| run.sh | β | 137 B | view raw | |
| build.log | β | 106 B | view raw | |
| run.log | β | 1.1 KB | view raw | |
| env.txt | β | 664 B | view raw | |
| fix.diff | β | 1.6 KB | view raw | |
| manifest.json | β | 1.4 KB | view raw | |
| verdict.json | β | 2.8 KB | view raw |
DF-4693 β sili_pm: pm register accessors recycle the ata_xfer while the chip still owns the slot (deferred-timeout returns ATA_S_ONCHIP)
Build & run
sh build.sh # cc -O2 -Wall -o trigger_sili_pm trigger_sili_pm.c sh run.sh # ./trigger_sili_pm 15 (reset/rescan storm + dd saturation)
Expected output
- On hardware (SiI HBA + PM, other-target I/O in flight): a PM register
read/write (e.g. EINFO poll sili.c:530, SERR clear sili_pm.c:589, XPT_RESET_DEV
softreset) that times out while other commands are still on-chip takes the
deferred-timeout branch (
ap->ap_active != ap->ap_expired, sili.c:2507-2510):sili_ata_cmd()returns withxa->state == ATA_S_ONCHIP(sili.c:1357-1359, 2375),sili_pm_read/pm_writetreat it as plain failure and callsili_ata_put_xfer()(sili_pm.c:667 / 702) β the CCB returns to the free list while the slot is still programmed andap_expiredprocessing is pending. Consequences:sili_poll()KKASSERT on slot reuse (sili.c:1321),sili_ata_cmd_donecompleting a re-issued ccb / unloading the new command's live dmamap whensili_port_reinit()later drains the expired slot (sili.c:403-411 β 2415-2418), and a staleap_activebit wedgingsili_exclusive_access()forever (sili.c:1437-1443). - On the audit QEMU guest: no sili HBA (env.txt) β path unreachable; hardware gate, not a false positive.
Twin of DF-4503 (ahci_pm.c); sili instance of the DF-4027 mechanism observed from the PM accessor call sites.
VERDICT β DF-4693
Status: inconclusive (hardware-gated) Β· code-path proven Β· expected impact: kernel panic (KKASSERT) / cross-command CCB corruption / port wedge
Reproduced?
No β no sili(4) HBA on the audit guest and QEMU has no SiL3726 PM emulation (env.txt). The trigger builds and runs (build.log / run.log) and drives the CAM entry points (XPT_RESET_DEV, rescan) against the only buses present; the defective code is unreachable at runtime here. Full control-flow proof below; same evidence standard as the accepted DF-4503 sibling (ahci).
Why the defect is real (trace)
sili_pm_read()/sili_pm_write()/sili_pm_set_feature()issue their FIS viasili_ata_cmd()β sili_pm.c:657 / 698 / 563.- Poll path:
sili_ata_cmd()βsili_poll(ccb, 1000, sili_ata_cmd_timeout)β sili.c:2374-2375. - On timeout with the command on-chip,
sili_core_timeout()setsap->ap_expired |= 1 << slot; if any other command is still active (ap->ap_active != ap->ap_expired) it prints "Deferred timeout until its safe" and returns without reinit β sili.c:2502-2511. The xa state remainsATA_S_ONCHIP. sili_poll()then returnsccb->ccb_xa.stateβ sili.c:1357-1359 β i.e. ATA_S_ONCHIP.- The PM accessors treat every non-
ATA_S_COMPLETEreturn identically: error path βsili_ata_put_xfer(xa)β sili_pm.c:663-668 / 698-703 β whichsili_put_ccb()s the ccb back ontoap_ccb_freewithstate = ATA_S_PUT(sili.c:2020-2030). The chip still owns the slot;ap_active/ap_expiredbits remain set. - Detonations:
- a new command takes the recycled slot β
sili_poll()'sKKASSERT((ap->ap_expired & (1 << ccb->ccb_slot)) == 0)fires (sili.c:1321) β panic on INVARIANTS kernels (X86_64_GENERIC:56); - when the remaining commands finish,sili_port_intr()callssili_port_reinit()(sili.c:1956-1958) which drains the expired slot:ccb->ccb_xa.state = ATA_S_TIMEOUT; ccb->ccb_done(ccb);(sili.c:403-411) βsili_ata_cmd_done()(sili.c:2393-2419) on a ccb that may already be re-issued for an unrelated command β premature completion / stalesili_unload_prb()of the new command's live dmamap (the DF-4027 corruption signature); - if the slot never completes, the staleap_activebit makessili_exclusive_access()spin forever (sili.c:1437-1443) β permanent port-thread wedge.
Co-activity precondition
PM register traffic runs outside exclusive access in exactly the paths
where other commands are on-chip: the port-thread EINFO poll (sili.c:530) and
sili_pm_check_good() (sili.c:580,654 β sili_pm.c:584,589,610). Only
sili_pm_hardreset() drains first (sili_pm.c:272). A hung or slow PM target
(1 s accessor timeout) while another target streams NCQ is the realistic
trigger β device-timing dependent, hence confidence "likely", matching
DF-4503's classification for the identical ahci defect.
Impact ceiling
Kernel panic (common, INVARIANTS) with a narrower cross-command corruption window (premature CAM completion / live-dmamap unload). Severity Medium.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableFix validation not testable: the guest has no SiI 3124/3132 HBA and QEMU does not emulate the SiL3726 port multiplier, so neither baseline nor patched kernel can reach sili_pm_* at runtime. fix.diff is a line-accurate source-level fix (all referenced helpers declared in sili.h); code-reviewed only.
env.txt (PCI inventory, 0 sili dmesg lines); fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md trace steps 1-6 with the three detonation paths; run.log/env.txt document the hardware gate.
PoC changes
No seed; trigger written fresh (same shared program as DF-4692 pack).
Verified recommended fix
Treat ATA_S_ONCHIP from sili_ata_cmd as deferred: wait for expiry processing to complete the xa before sili_ata_put_xfer.
Verdict
Code-trace proven (twin of accepted DF-4503, ahci); hardware-gated on this guest: sili_pm_read (:657-668) and sili_pm_write (:698-703) call sili_ata_put_xfer() on ANY non-ATA_S_COMPLETE return. When the poll timeout defers because other commands are still on-chip ('Deferred timeout until its safe', sili.c:2505-2511), sili_ata_cmd returns with xa->state==ATA_S_ONCHIP (sili.c:1357-1359,2375) - the CCB is recycled onto ap_ccb_free while the chip still owns the slot and ap_expired processing is pending. Detonations: sili_poll KKASSERT on slot reuse (sili.c:1321); sili_port_reinit later completes the recycled/reissued ccb (sili.c:403-411 -> 2393-2419) causing premature completion or stale sili_unload_prb of the new command's live dmamap (DF-4027 signature); stale ap_active bit wedges sili_exclusive_access forever (sili.c:1437-1443). Co-activity precondition holds: PM register traffic runs outside exclusive access on the EINFO/check_good paths (sili.c:530,580,654).
No comments yet.