Add opt-in cmpunlocker unlock step with post-unlock Gen2 x16 acceptance
Insert a "cmpunlocker unlock (install)" step after unlock verification: y/N confirmation (default n) or --unlock runs install.sh from the harness clone (main branch, ff-only pull first) with live terminal output and full log to cards/<serial>/install_unlocker.log. On success the Vulkan stress is skipped until after the cold reboot. Score now enforces the post-unlock invariant: when verify reports unlocked-ok, any final link other than Gen2 x16 fails with a red [ERROR] and exit 1. README safety section and AGENTS.md harness cloning invariant updated to match.
This commit is contained in:
+64
-10
@@ -3,11 +3,15 @@
|
||||
|
||||
Per run: wait for card -> auto serial -> VBIOS backup -> PCIe link/AER/config
|
||||
checks -> retrain + rescan tests -> dmesg scrape -> cmpunlocker verify.sh
|
||||
(read-only) -> optional 5-min Vulkan VRAM stress (last step, ask yes/no)
|
||||
(read-only) -> opt-in cmpunlocker unlock (install.sh, y/N or --unlock; a
|
||||
successful install skips VRAM stress and asks for a cold reboot, then you
|
||||
re-run this script for the final Gen2 x16 PCIe check)
|
||||
-> optional 5-min Vulkan VRAM stress (last step, ask yes/no)
|
||||
-> cards/<serial>/report.json.
|
||||
|
||||
Scoring (lenient): FAIL only on no-device/link-down/lost-after-rescan;
|
||||
WARN on correctable AER/Xid/width< x16/verify issues.
|
||||
Scoring: FAIL on no-device/link-down/lost-after-rescan, and on a final
|
||||
post-unlock link other than Gen2 x16; WARN on correctable AER/Xid/width< x16/
|
||||
verify issues/failed unlock install.
|
||||
|
||||
Exit codes: 0 = PASS/WARN, 1 = FAIL, 2 = no card, 3 = preflight blocking.
|
||||
"""
|
||||
@@ -24,6 +28,8 @@ from cxlib import C, ask, detect_gpus, err, info, now_iso, ok, sanitize, step, w
|
||||
|
||||
def score(rep):
|
||||
fails, warns = [], []
|
||||
ver = rep.get("cmpunlocker_verify", {})
|
||||
unlocked = ver.get("status") == "unlocked-ok"
|
||||
if not rep.get("bdf"):
|
||||
fails.append("no CMP 170HX device detected on the bus")
|
||||
link = rep.get("link", {})
|
||||
@@ -33,11 +39,20 @@ def score(rep):
|
||||
if link.get("lnksta_width") in ("x0", "x1", None) or not link.get("lnksta_speed"):
|
||||
fails.append(f"link down or untrained: {link.get('lnksta_raw') or 'no LnkSta'}")
|
||||
width = link.get("lnksta_width")
|
||||
if width and width != "x16":
|
||||
warns.append(f"link width {width} (capacitor mod expects x16 - mod likely "
|
||||
f"missing/incomplete on this card)")
|
||||
if link.get("lnksta_gen") == 1:
|
||||
warns.append("link negotiated Gen1 only (cmpunlocker Gen2 patch/service not active?)")
|
||||
gen = link.get("lnksta_gen")
|
||||
if unlocked:
|
||||
# Post-unlock final acceptance: only Gen2 x16 passes. The pre-unlock
|
||||
# width/Gen1 warns are suppressed here - the error replaces them.
|
||||
if width != "x16" or gen is None or gen < 2:
|
||||
fails.append(f"[ERROR] final PCIe link after unlock is "
|
||||
f"{link.get('lnksta_speed') or '?'} {width or '?'} "
|
||||
f"- expected Gen2 x16")
|
||||
else:
|
||||
if width and width != "x16":
|
||||
warns.append(f"link width {width} (capacitor mod expects x16 - mod likely "
|
||||
f"missing/incomplete on this card)")
|
||||
if gen == 1:
|
||||
warns.append("link negotiated Gen1 only (cmpunlocker Gen2 patch/service not active?)")
|
||||
if rep.get("rescan", {}).get("ok") is False:
|
||||
fails.append("device lost after bus rescan")
|
||||
if rep.get("retrain", {}).get("ok") is False:
|
||||
@@ -60,9 +75,11 @@ def score(rep):
|
||||
warns.append("kernel errors around VRAM stress window")
|
||||
if not rep.get("bios", {}).get("ok"):
|
||||
warns.append("VBIOS backup failed/incomplete")
|
||||
ver = rep.get("cmpunlocker_verify", {})
|
||||
if ver.get("ran") and ver.get("status") not in ("unlocked-ok",):
|
||||
warns.append(f"cmpunlocker verify status: {ver.get('status')}")
|
||||
unlock = rep.get("unlock", {})
|
||||
if unlock.get("attempted") and not unlock.get("ok"):
|
||||
warns.append("cmpunlocker install failed (see install_unlocker.log)")
|
||||
|
||||
result = "FAIL" if fails else ("WARN" if warns else "PASS")
|
||||
return result, fails, warns
|
||||
@@ -156,8 +173,38 @@ def process_card(args):
|
||||
info("verify: " + (f"rc={v.get('rc')} -> {v.get('status')}" if v.get("ran")
|
||||
else f"skipped - {v.get('note')}"))
|
||||
|
||||
step("cmpunlocker unlock (install)")
|
||||
unlock_installed = False
|
||||
if rep["cmpunlocker_verify"].get("status") == "unlocked-ok":
|
||||
info("memory already unlocked - skipping install")
|
||||
rep["unlock"] = {"attempted": False, "ok": False, "note": "already unlocked"}
|
||||
elif getattr(args, "demo", False):
|
||||
# --demo never prompts: force the unlock install path off.
|
||||
rep["unlock"] = {"attempted": False, "ok": False, "note": "demo"}
|
||||
info("unlock install skipped (demo mode)")
|
||||
elif not X.INSTALL_SH.exists():
|
||||
rep["unlock"] = {"attempted": False, "ok": False,
|
||||
"note": "harness/cmpunlocker not cloned - run --preflight"}
|
||||
warn("harness/cmpunlocker not cloned - run --preflight (unlock install skipped)")
|
||||
elif args.unlock or ask("Run cmpunlocker install.sh now? (y/N)", "n").lower().startswith("y"):
|
||||
X.update_cmpunlocker()
|
||||
rep["unlock"] = X.run_installer(folder / "install_unlocker.log")
|
||||
unlock_installed = bool(rep["unlock"].get("attempted") and rep["unlock"].get("ok"))
|
||||
if unlock_installed:
|
||||
# Kernel modules are replaced but the card is not unlocked until the
|
||||
# cold reboot - VRAM stress against the half-applied state is unsafe.
|
||||
rep["vulkan_test"] = {"requested": False, "ran": False,
|
||||
"note": "skipped - unlock installed, reboot first"}
|
||||
else:
|
||||
warn("cmpunlocker install failed - continuing with the Vulkan step")
|
||||
else:
|
||||
rep["unlock"] = {"attempted": False, "ok": False, "note": "operator declined"}
|
||||
info("unlock install skipped")
|
||||
|
||||
step("optional Vulkan VRAM test (last step)")
|
||||
if args.vulkan == "never":
|
||||
if unlock_installed:
|
||||
info("vulkan test skipped - unlock installed, cold reboot first")
|
||||
elif args.vulkan == "never":
|
||||
rep["vulkan_test"] = {"requested": False, "ran": False, "note": "disabled via --vulkan never"}
|
||||
elif args.vulkan == "always":
|
||||
rep["vulkan_test"] = X.run_vulkan_test()
|
||||
@@ -201,6 +248,7 @@ def demo(args):
|
||||
orig_aer, orig_dm, orig_cfg = X.aer_snapshot, X.dmesg_capture, X.dump_config
|
||||
orig_retrain, orig_rescan = X.retrain_test, X.rescan_test
|
||||
orig_smi, orig_verify = X.nvidia_smi_info, X.run_verify_unlocker
|
||||
orig_update, orig_installer = X.update_cmpunlocker, X.run_installer
|
||||
globals()["wait_for_gpu"] = lambda: "0000:0a:00.0"
|
||||
X.detect_gpus = lambda: ["0000:0a:00.0"]
|
||||
X.check_link = lambda b: ({"lnksta_speed": "5GT/s", "lnksta_width": "x4", "lnksta_gen": 2,
|
||||
@@ -218,6 +266,9 @@ def demo(args):
|
||||
X.rescan_test = lambda b: {"attempted": True, "ok": True, "note": "re-enumerated"}
|
||||
X.nvidia_smi_info = lambda: {"available": False}
|
||||
X.run_verify_unlocker = lambda: {"ran": False, "note": "demo"}
|
||||
X.update_cmpunlocker = lambda: {"ok": True, "note": "demo"}
|
||||
X.run_installer = lambda log_path: {"attempted": False, "ok": False, "rc": None,
|
||||
"note": "demo", "log": str(log_path)}
|
||||
try:
|
||||
rep = process_card(args)
|
||||
finally:
|
||||
@@ -226,6 +277,7 @@ def demo(args):
|
||||
X.aer_snapshot, X.dmesg_capture, X.dump_config = orig_aer, orig_dm, orig_cfg
|
||||
X.retrain_test, X.rescan_test = orig_retrain, orig_rescan
|
||||
X.nvidia_smi_info, X.run_verify_unlocker = orig_smi, orig_verify
|
||||
X.update_cmpunlocker, X.run_installer = orig_update, orig_installer
|
||||
return rep
|
||||
|
||||
|
||||
@@ -241,6 +293,8 @@ def main():
|
||||
ap.add_argument("--skip-bios", action="store_true", help="skip VBIOS backup")
|
||||
ap.add_argument("--vulkan", choices=("ask", "always", "never"), default="ask",
|
||||
help="5-min Vulkan VRAM test policy (default ask, runs as last step)")
|
||||
ap.add_argument("--unlock", action="store_true",
|
||||
help="run cmpunlocker install.sh without prompting (default: ask y/N)")
|
||||
ap.add_argument("--no-install", action="store_true",
|
||||
help="do not auto-install packages (skips the sudo precondition)")
|
||||
ap.add_argument("--no-clone", action="store_true", help="do not clone harness repos")
|
||||
|
||||
Reference in New Issue
Block a user