Research-Stack/4-Infrastructure/kernel/qfox_topology_manager/probe_qfox_topology_manager.py
Brandon Schneider 382277ec28 chore: preserve working tree before secure wipe
- Update .gitignore with **/target/ for Rust build artifacts
- Add eval receipts to UniversalBridge.lean (compile-time verification comments)
- Add PCIe Idle-Cycle Compute Harvester to ROADMAP.md
- Clean up deprecated scripts, generated Verilog, and old tools (23 deletions)
- Stage new infrastructure: Xen/Alpine embedded surface, QFOX topology manager
- Stage new probes: boundary activation field, holographic carving
- Stage new applications: finance manager, script roots
- Stage new research spec: PCIe idle-cycle substrate
2026-05-13 17:36:02 -05:00

205 lines
6.4 KiB
Python
Executable file

#!/usr/bin/env python3
"""Probe the QFox topology-manager kernel module.
The probe is receipt-shaped and intentionally non-failing for missing module
state: absence is data. CLI/write errors still exit non-zero.
"""
from __future__ import annotations
import argparse
import json
import os
import subprocess
import sys
import time
from pathlib import Path
from typing import Any
SCHEMA = "research_stack_qfox_topology_manager_probe_v1"
SYSFS = Path("/sys/kernel/qfox_topology_manager")
DEBUGFS = Path("/sys/kernel/debug/qfox_topology_manager")
DEV = Path("/dev/qfox_topoman")
def _parse_kv(text: str | None) -> dict[str, str]:
values: dict[str, str] = {}
if not text:
return values
for raw in text.splitlines():
if "=" not in raw:
continue
key, value = raw.split("=", 1)
values[key.strip()] = value.strip()
return values
def _parse_int(value: str | None) -> int | None:
if value is None:
return None
try:
return int(value, 0)
except ValueError:
return None
def _read(path: Path, max_bytes: int = 65536) -> str | None:
try:
with path.open("r", encoding="utf-8", errors="replace") as handle:
return handle.read(max_bytes)
except OSError:
return None
def _cmd(argv: list[str]) -> dict[str, Any]:
try:
result = subprocess.run(argv, capture_output=True, text=True, timeout=5)
except (OSError, subprocess.TimeoutExpired) as exc:
return {"ok": False, "error": str(exc), "stdout": "", "stderr": ""}
return {
"ok": result.returncode == 0,
"returncode": result.returncode,
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
}
def _snapshot() -> dict[str, Any]:
status = _read(SYSFS / "status")
slots = _read(SYSFS / "slots")
status_kv = _parse_kv(status)
slots_kv = _parse_kv(slots)
events = _parse_int(status_kv.get("events"))
avg_x1000 = _parse_int(status_kv.get("avg_events_per_sec_x1000"))
return {
"timestamp_unix": time.time(),
"status": status,
"status_kv": status_kv,
"slots": slots,
"slots_kv": slots_kv,
"events": events,
"avg_events_per_sec": None if avg_x1000 is None else avg_x1000 / 1000.0,
}
def build_probe(sample_sec: float = 0.0) -> dict[str, Any]:
loaded = "qfox_topology_manager" in (_read(Path("/proc/modules")) or "")
first = _snapshot()
sample: dict[str, Any] | None = None
if sample_sec > 0:
time.sleep(sample_sec)
second = _snapshot()
first_events = first.get("events")
second_events = second.get("events")
delta_events = None
if isinstance(first_events, int) and isinstance(second_events, int):
delta_events = max(0, second_events - first_events)
sample = {
"seconds": sample_sec,
"start": first,
"end": second,
"delta_events": delta_events,
"events_per_second": None
if delta_events is None
else delta_events / sample_sec,
}
return {
"schema": SCHEMA,
"timestamp_unix": int(time.time()),
"module": {
"name": "qfox_topology_manager",
"loaded": loaded,
"modinfo": _cmd(["modinfo", "qfox_topology_manager"]),
},
"interfaces": {
"sysfs": str(SYSFS),
"sysfs_present": SYSFS.exists(),
"debugfs": str(DEBUGFS),
"debugfs_present": DEBUGFS.exists(),
"device": str(DEV),
"device_present": DEV.exists(),
},
"status": first["status"],
"status_kv": first["status_kv"],
"slots": first["slots"],
"slots_kv": first["slots_kv"],
"mode": _read(SYSFS / "mode"),
"events": _read(DEBUGFS / "events"),
"average": {
"since_load_events_per_second": first["avg_events_per_sec"],
"sample": sample,
},
}
def emit_text(probe: dict[str, Any]) -> str:
module = probe["module"]
interfaces = probe["interfaces"]
lines = [
f"schema: {probe['schema']}",
f"module: {module['name']}",
f"loaded: {module['loaded']}",
f"sysfs: {interfaces['sysfs_present']} ({interfaces['sysfs']})",
f"debugfs: {interfaces['debugfs_present']} ({interfaces['debugfs']})",
f"device: {interfaces['device_present']} ({interfaces['device']})",
]
if probe.get("status"):
lines.append("")
lines.append("status:")
lines.append(probe["status"].rstrip())
if probe.get("slots"):
lines.append("")
lines.append("slots:")
lines.append(probe["slots"].rstrip())
average = probe.get("average") or {}
if average.get("since_load_events_per_second") is not None:
lines.append("")
lines.append(
"average_since_load_events_per_second: "
f"{average['since_load_events_per_second']:.3f}"
)
sample = average.get("sample")
if sample:
lines.append(
f"sample_{sample['seconds']:.3f}s_events_per_second: "
f"{sample['events_per_second']:.3f}"
if sample.get("events_per_second") is not None
else f"sample_{sample['seconds']:.3f}s_events_per_second: unavailable"
)
return "\n".join(lines) + "\n"
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--json", action="store_true", help="emit JSON")
parser.add_argument("--out", type=Path, help="write probe payload to path")
parser.add_argument(
"--sample-sec",
type=float,
default=0.0,
help="sleep for N seconds and report an event-rate delta",
)
args = parser.parse_args(argv)
if args.sample_sec < 0:
print("--sample-sec must be non-negative", file=sys.stderr)
return 2
probe = build_probe(args.sample_sec)
payload = json.dumps(probe, indent=2, sort_keys=True) + "\n"
rendered = payload if args.json else emit_text(probe)
if args.out:
try:
args.out.parent.mkdir(parents=True, exist_ok=True)
args.out.write_text(payload, encoding="utf-8")
except OSError as exc:
print(f"probe write failed: {exc}", file=sys.stderr)
return 2
print(rendered, end="")
return 0
if __name__ == "__main__":
raise SystemExit(main())