refactor: modularize audit and harden build validation

This commit is contained in:
Mikhail Chusavitin
2026-08-31 21:22:16 +03:00
parent bb22ccfafe
commit ac4bc0b2b7
78 changed files with 13598 additions and 13130 deletions
+1
View File
@@ -53,6 +53,7 @@ All SAT run endpoints enqueue an async task. Response: `{"task_id": "..."}`.
| POST | `/api/sat/memory-stress/run` | Memory stress |
| POST | `/api/sat/sat-stress/run` | Combined storage+memory stress |
| POST | `/api/sat/platform-stress/run` | Fan + thermal stress |
| POST | `/api/sat/run-all` | Plan + enqueue the whole validate/check set server-side. Body: `{stress_mode, amd_targets[], nvidia_gpu_indices[]}` (operator intent only). Response: `{task_ids[], task_count, notes[]}`. Hardware presence/readiness and which tasks to run are decided by `handler.planSATRunAll`, not the page. |
| GET | `/api/sat/stream` | SSE: live SAT log stream |
| POST | `/api/sat/abort` | Abort the running SAT task |
+75 -12
View File
@@ -32,6 +32,12 @@ local-fs.target
- `bee-network.service` uses `dhclient -nw` (background) — network bring-up is best effort and non-blocking.
- `bee-nvidia.service` loads modules via `insmod` with absolute paths — NOT `modprobe`.
Reason: the modules are shipped in the ISO overlay under `/usr/local/lib/nvidia/`, not in the host module tree.
- `bee-nvidia-load` refreshes `nvidia-fabricmanager.service` / `nvidia-dcgm.service`
with `systemctl --no-block try-restart` only. DO NOT make it a blocking
`systemctl {start,restart}`: `bee-nvidia.service` is `Type=oneshot` and
`Before=` both units, so a synchronous call deadlocks against that ordering
and previously reached a 60-second wrapper timeout for each unit. See
`decisions/2026-08-31-bee-nvidia-restart-deadlock.md`.
- `bee-audit.service` does not wait for `network-online.target`; audit is local and must run even if DHCP is broken.
- `bee-audit.service` logs audit failures but does not turn partial collector problems into a boot blocker.
- `bee-web.service` binds `0.0.0.0:80` and always renders the current `/var/log/bee-audit.json` contents.
@@ -67,7 +73,7 @@ Rules:
```
build-in-container.sh [--authorized-keys /path/to/keys]
1. compile `bee` binary (skip if .go files older than binary)
1. compile `bee` binary (always; version/git state is part of the artifact)
2. create a temporary overlay staging dir under `dist/`
3. inject authorized_keys into staged `root/.ssh/` (or set password fallback marker)
4. copy `bee` binary → staged `/usr/local/bin/bee`
@@ -93,7 +99,12 @@ build-in-container.sh [--authorized-keys /path/to/keys]
13. patch staged `motd` with build metadata
14. copy `iso/builder/` into a temporary live-build workdir under `dist/`
15. sync staged overlay into workdir `config/includes.chroot/`
16. run `lb config && lb build` inside the privileged builder container
16. choose the build path from persisted content/ABI/overlay state:
a. full: run `lb clean --all && lb config && lb build`
b. fast: unpack the last squashfs, sync the staged overlay, repack it,
then rebuild checksums, bootloader assets, ISO, and zsync
17. validate the final ISO boot menus, volume label, memtest, GRUB assets,
and variant runtime before publishing it
```
Build host notes:
@@ -109,7 +120,26 @@ Build host notes:
- `bee-gpu-burn` worker must be built against cached CUDA userspace headers from `build-cublas.sh`, not against random host-installed CUDA headers.
- The live ISO must ship `libcublas`, `libcublasLt`, and `libcudart` together with `libcuda` so tensor-core stress works without internet or package installs at boot.
- The source overlay in `iso/overlay/` is treated as immutable source. Build-time files are injected only into the staged overlay.
- Fast-path state lives outside the rsync-managed live-build workdir and is
accepted only when the heavy-input content hash and resolved kernel ABI
match the last successful full build. A failed full build never leaves a
valid completion marker. The workdir's `binary/` tree is preserved because
it is the source artifact for squashfs reuse.
- Bootloader menu text has two canonical sources only:
`config/bootloaders/grub-efi/grub.cfg` and
`config/bootloaders/isolinux/live.cfg.in`. `lib/bootloader.sh` renders those
templates after both full and fast builds; hooks do not append duplicate
menu entries.
- Build orchestration stays in `build.sh`; ISO validation, bootloader
rendering, fast-path/memtest recovery, and logging helpers live under
`iso/builder/lib/`. Run `iso/builder/test-build-libs.sh` after changing
those helpers or the canonical boot parameters.
- ISO filename, squashfs filename, ISO volume label, and the live system's hostname all derive from the same `easy-bee-<variant>-v<version>` scheme (`ISO_BASENAME`/`SQUASHFS_FILENAME`/`BEE_ISO_VOLUME`/`BEE_HOSTNAME` in `build.sh`) instead of the live-build default (`debian`). Keep new naming derived from `PROJECT_VERSION_EFFECTIVE`/`BUILD_VARIANT` in sync with this set rather than hardcoding a new scheme.
- Every live boot entry carries `udev.children_max=1`,
`intel_iommu=on`, `iommu.passthrough=0`, and
`efi=disable_early_pci_dma`. Only the single failsafe entry additionally
carries `pci=realloc iommu.strict=1`; `iommu=pt` is forbidden. The final-ISO
validator enforces this for both GRUB and isolinux.
- The live-build workdir under `dist/` is disposable; source files under `iso/builder/` stay clean.
- Container build requires `--privileged` because `live-build` uses mounts/chroots/loop devices during ISO assembly.
- On macOS / Docker Desktop, the builder still must run as `linux/amd64` so the shipped ISO binaries remain `amd64`.
@@ -170,11 +200,11 @@ Acceptance flows:
- Runtime overrides:
- `BEE_MEMTESTER_SIZE_MB`
- `BEE_MEMTESTER_PASSES`
- NVIDIA Bandwidth SAT (`RunNvidiaBandwidthPack`, `dcgmi diag -r nvbandwidth`) on a
multi-socket system runs per CPU socket first, then all selected GPUs together
- NVIDIA Bandwidth SAT (`RunNvidiaBandwidthPack`, `dcgmi diag -r nvbandwidth`) in
Stress mode runs per resolved PCI NUMA node first, then all selected GPUs together
(`03-dcgmi-nvbandwidth-socket0.log`, `...-socket1.log`, `...-all.log`) --
see `decisions/2026-07-27-nvbandwidth-per-socket-split.md`. Single-socket
systems (or systems where a GPU's NUMA node can't be resolved) keep the
see `decisions/2026-07-27-nvbandwidth-per-socket-split.md`. Single-node
systems (or systems where any GPU's NUMA node cannot be resolved) keep the
original single `NN-dcgmi-nvbandwidth.log` shape.
## SAT job output durability
@@ -228,18 +258,51 @@ bee-blackbox.service (separate process from bee-web/bee-audit)
- DO NOT assume a local write under the live ISO's export directory is
durable on its own (RAM-backed overlay) -- blackbox's mirror to removable
media is the only real persistence boundary across a hard reset.
- `BuildSupportBundle` stages into a private `os.MkdirTemp` parent, not a
shared `os.TempDir()/bee-support-stage-<host>-<ts>` path. DO NOT go back to
a time-derived staging path: two builds in the same wall-clock second (two
operators, or an on-demand build racing the blackbox worker) then share one
tree and one's deferred `os.RemoveAll` truncates the other's archive.
## NVIDIA SAT Web UI flow
```
Web UI: Acceptance Tests page Run Test button
1. POST /api/sat/nvidia/run returns job_id
2. GET /api/sat/stream?job_id=... (SSE) streams stdout/stderr lines live
3. After completion archive written to /appdata/bee/export/bee-sat/
summary.txt contains overall_status (OK / FAILED) and per-job status values
Web UI: Acceptance Tests page -> Run Test button
1. POST /api/sat/nvidia/run -> returns job_id
2. GET /api/sat/stream?job_id=... (SSE): streams stdout/stderr lines live
3. After completion: archive written to /appdata/bee/export/bee-sat/
summary.txt contains overall_status (OK / FAILED / UNSUPPORTED) and per-job status
```
## Run All (validate / check) flow
```
Web UI: "Run All" button -> POST /api/sat/run-all
body: operator intent only { stress_mode, amd_targets[], nvidia_gpu_indices[] }
server (handler.planSATRunAll):
1. always: cpu, memory, storage, pcie-link
2. tpm - only if App.TPMPresent() finds tpm_version_major=2
3. nvidia-config - if DetectGPUPresence().Nvidia || NvidiaInitializing
4. wait for NVIDIA enumeration: repeat fresh ListNvidiaGPUs queries until
at least one GPU is returned, NvidiaGSPMode=="gsp-stuck", or 75s
5. nvidia / nvidia-interconnect / nvidia-bandwidth / nvidia-pcie-bandwidth
(+ targeted-stress/power/pulse when stress_mode) - only once ready,
-i = App.ListNvidiaGPUs() indices (intersected with the requested subset)
6. amd / amd-mem / amd-bandwidth - if DetectGPUPresence().AMD and selected
response: { task_ids[], task_count, notes[] } (notes = what was skipped and why)
```
**Critical invariants:**
- `bee-gpu-burn` / `bee-john-gpu-stress` use `exec.CommandContext` — killed on job context cancel.
- Hardware presence, readiness, and which tasks to run are decided server-side.
DO NOT move this back into page JS (`satSelectedGPUIndices().length` gating):
a browser-cached empty GPU list then silently drops every GPU test. See
`decisions/2026-08-31-backend-driven-sat-planning.md`.
- `DetectGPUPresence` is the shared detection source (existing operational
vendor detection plus an lspci display-class fallback).
`/api/gpu/presence`, `/api/gpu/tools` and the planner all use it.
- `bee-gpu-burn` / `bee-john-gpu-stress` use `exec.CommandContext`: killed on job context cancel.
- Metric goroutine uses stopCh/doneCh pattern; main goroutine waits `<-doneCh` before reading rows (no mutex needed).
- SVG chart is fully offline: no JS, no external CSS, pure inline SVG.
- `RunNvidiaBandwidthPack` runs one all-GPU `nvbandwidth` pass in Validate; the
per-NUMA-node matrix is Stress-tier only (`fullMatrix` arg). See
`decisions/2026-08-31-nvbandwidth-validate-single-deep-matrix.md`.
@@ -175,8 +175,8 @@ those files may not exist yet. Instead:
- Tries to copy `memtest86+x64.bin` / `memtest86+x64.efi` from `chroot/boot/` first.
- Falls back to extracting from the cached `.deb` (via `dpkg-deb -x`) if `chroot/boot/` is empty.
- Appends GRUB and isolinux menu entries only if the respective cfg files already exist at hook time.
If they do not exist, the hook warns and continues (does not fail).
- It does not edit bootloader menus. The complete menus are rendered later
from the two canonical project templates.
Controlled by `BEE_REQUIRE_MEMTEST=1` env var to turn warnings into hard errors when needed.
@@ -186,7 +186,8 @@ After `lb build` completes, `build.sh` checks whether the fully materialized `bi
contains all required memtest artifacts. If not:
- Copies/extracts memtest binaries into `binary/boot/`.
- Patches `binary/boot/grub/grub.cfg` and `binary/isolinux/live.cfg` directly.
- Calls `enforce_live_build_bootloader_assets`, which renders the complete
GRUB and isolinux configs from the canonical project templates.
- Reruns the late binary stages (`binary_checksums`, `binary_iso`, `binary_zsync`) to rebuild
the ISO with the patched tree.
@@ -59,10 +59,11 @@ individual failure mode. This keeps the total entry count in
entries plus wipe/memtest/firmware-settings), rather than letting it
grow linearly with every workaround discovered.
The isolinux (BIOS/legacy boot) menu in `iso/builder/config/bootloaders/isolinux/live.cfg.in`
already had no `pci=realloc` entry at all (pre-existing asymmetry with
grub-efi, not introduced by this change) -- not addressed here since no
incident has been observed via legacy boot.
As of v13.0, GRUB and isolinux both expose exactly one troubleshooting entry
with `pci=realloc`. It remains absent from every normal, toram, no-GUI, and
wipe entry. The same v13.0 amendment replaces `iommu=pt` in that entry with
translated strict IOMMU mode; this changes DMA diagnostics, not the scope of
the PCI reallocation workaround.
## Consequences
@@ -0,0 +1,67 @@
# "Run All" SAT planning happens on the backend, not in the browser
**Date:** 2026-08-31
**Status:** active
## Symptom
Support bundle `210619KUGGXGS2000017` (8x H200 NVL, identical to `...008`):
the operator hit "Run All" and only 6 tasks were queued - cpu, memory,
storage, tpm, nvidia-config, pcie-link. No `nvidia`, `nvidia-interconnect`,
`nvidia-bandwidth`, `nvidia-pcie-bandwidth`. The GPUs were physically present
and `nvidia-config` (which enumerates them) passed.
## Root cause
Task planning lived in page JavaScript:
- `runAllCheckSAT()` / `runAllSAT()` added the NVIDIA targets only
`if (satSelectedGPUIndices().length)`.
- That list came from `/api/gpu/nvidia` (`nvidia-smi --query-gpu=...`), fetched
**once per page load and cached** in `satNvidiaGPUsPromise`.
- If the page first queried while the driver was still enumerating GPUs (the
two 60-second service timeouts described in
[2026-08-31-bee-nvidia-restart-deadlock.md](2026-08-31-bee-nvidia-restart-deadlock.md),
plus per-GPU GSP firmware boot), it got an empty list and cached it for the
whole session. "Run All" then silently dropped every GPU test - no banner,
no error. `/api/gpu/presence` (a separate `os.Stat("/dev/nvidia0")` check)
meanwhile said "GPU present", so the UI even contradicted itself.
## Decision
- **New endpoint `POST /api/sat/run-all`.** The browser sends only operator
*intent*: `stress_mode`, `amd_targets` (checkbox selection), and
an optional `nvidia_gpu_indices` subset. The server decides what hardware
is present/ready and what to enqueue (`handler.planSATRunAll`).
`runAllSAT()` / `runAllCheckSAT()` are now thin `fetch` wrappers and render
the `notes[]` the server returns ("TPM: no device - skipped", etc.).
- **GPU planning waits on a readiness gate, not a device probe.**
`planSATRunAll` calls `waitForNvidiaReady`, which repeats the fresh
`ListNvidiaGPUs` query until `nvidia-smi` enumerates at least one GPU, the
runtime snapshot reports `NvidiaGSPMode == "gsp-stuck"`, or the 75-second
deadline expires. A loaded kernel module is not treated as proof that
user-space tools can address a GPU. `CUDAReady == false` after enumeration
is a note, not a blocker.
- **One presence source with a PCI fallback.** `app.DetectGPUPresence`:
- primary - the existing operational vendor result (`DetectGPUVendor`);
- fallback - `System.PhysicalGPUVendors()` (lspci VGA/3D/Display class +
vendor id): a GPU on the bus not reported by operational detection sets
`NvidiaInitializing` / `AMDInitializing`, an explicit state distinct from
"absent". For NVIDIA, the page can show that enumeration is still pending
instead of reporting no hardware.
`/api/gpu/tools`, `/api/gpu/presence` and the run-all planner all go through
it.
- **TPM gate.** `tpm` is planned only when `app.TPMPresent()` finds a sysfs TPM
whose stable `tpm_version_major` attribute is exactly `2`; otherwise a note explains the skip. This
matches the pack-level guard already in `RunTPMValidationPack`.
## Consequences
- "Run All" can no longer skip hardware because a browser-cached probe was
early/empty. A genuinely absent or dead GPU still gets skipped - but with a
`notes[]` entry, and `nvidia-config` still runs to capture diagnostics.
- The per-card `disableSATCard('...','No NVIDIA GPU detected')` hints in the
page still use `/api/gpu/presence` - cosmetic only now, and self-heal on
reload.
- Automated / headless callers get correct planning for free by POSTing the
same endpoint instead of replicating the JS logic.
@@ -0,0 +1,66 @@
# bee-nvidia.service: never call blocking `systemctl restart` on units ordered After= itself
**Date:** 2026-08-31
**Status:** active
## Symptom
Every affected NVIDIA boot reaches two 60-second wrapper timeouts in
`bee-nvidia.service`. `bee-nvidia.log`:
```
[bee-nvidia] restarting nvidia-fabricmanager.service (timeout 60s)
[bee-nvidia] WARN: systemctl restart nvidia-fabricmanager.service timed out after 60s
[bee-nvidia] restarting nvidia-dcgm.service (timeout 60s)
[bee-nvidia] WARN: systemctl restart nvidia-dcgm.service timed out after 60s
[bee-nvidia] done
```
Seen on both `210619KUGGXGS2000008` and `...017` (8x H200 NVL). That 120 s
window overlaps exactly with when an operator opens the web UI and clicks
"Run All" - during it `nvidia-smi` may not yet enumerate all GPUs, which is
how bundle `...017` ended up running the check set with **no GPU tests**
(see [2026-08-31-backend-driven-sat-planning.md](2026-08-31-backend-driven-sat-planning.md)).
## Root cause
`bee-nvidia.service` is `Type=oneshot` and `Before=nvidia-fabricmanager.service
nvidia-dcgm.service`. Its `ExecStart` (`bee-nvidia-load`) then ran, synchronously:
```
timeout 60 systemctl restart nvidia-fabricmanager.service
timeout 60 systemctl restart nvidia-dcgm.service
```
A oneshot unit is not "active" until `ExecStart` returns. Both target units
are ordered `After=bee-nvidia.service`, so systemd queues them behind
bee-nvidia and will not run them while `bee-nvidia-load` is still executing.
`bee-nvidia-load` blocks on `systemctl restart` waiting for exactly that job
to complete -> deadlock -> broken only when `timeout 60` fires. Twice.
`nvidia-smi -q` inside `bee-check-nvswitch` (the fabricmanager ExecCondition)
is not part of this ordering cycle; the deadlock is structural.
## Decision
`bee-nvidia-load` no longer blocks on those units. It calls
`systemctl --no-block try-restart` for each:
- `--no-block` returns immediately; systemd runs the job after bee-nvidia
exits, via the existing `Before=` ordering.
- `try-restart` only acts if the unit is already running (the "stale instance
from a reload / re-run" case the old code worried about). If it is inactive,
this command does nothing; an enabled unit already queued by the normal boot
transaction starts after `bee-nvidia.service` via the declared ordering.
The `SYSTEMCTL_TIMEOUT` / `timeout_systemctl` wrapper and the fallback
`systemctl start` / `systemctl status` branches are gone. `--no-block` means
systemctl does not wait for the queued unit job to finish.
## Consequences
- NVIDIA boot no longer waits for those two 60-second wrapper deadlines.
- DO NOT reintroduce a synchronous `systemctl {start,restart}` of any unit
that is `After=bee-nvidia.service` from inside `bee-nvidia-load`. If a unit
genuinely must be up before the script returns, invert the ordering
instead.
@@ -0,0 +1,47 @@
# nvbandwidth: single all-GPU pass in Validate, per-NUMA-node matrix only in the deep tier
**Date:** 2026-08-31
**Status:** active
**Amends:** [2026-07-27-nvbandwidth-per-socket-split.md](2026-07-27-nvbandwidth-per-socket-split.md)
## Context
`2026-07-27` made `RunNvidiaBandwidthPack` split `dcgmi diag -r nvbandwidth`
using Linux PCI `numa_node` locality, followed by an all-GPU pass. A NUMA node
is not assumed to be identical to a physical CPU socket.
Two problems showed up on an 8x H200 NVL / dual-socket EPYC box
(`210619KUGGXGS2000008`):
1. `SATEstimatedNvidiaBandwidthSec` assigns 2700 seconds to one all-GPU pass.
Three such invocations are assigned 8100 seconds, which is outside the
intended **Validate** duration.
2. The split silently never engaged anyway: `normalizeNvidiaBDF` returned
nvidia-smi's upper-case PCI BDF (`0000:CB:00.0`) while `/sys/bus/pci/devices`
entries are lower-case, so `readPCINumaNode` failed for every GPU on a bus
with a hex letter and `gpuBandwidthSocketGroups` fell back to one group.
## Decision
- `normalizeNvidiaBDF` now lower-cases (and trims) the BDF, so sysfs
`numa_node` / link-speed reads actually resolve.
- `RunNvidiaBandwidthPack` takes a `fullMatrix bool`. The **only** thing it
changes is which GPU set each `nvbandwidth` invocation gets via `-i` - the
command itself is untouched (no extra flags, no testcase filtering).
- **Validate** (`stress_mode=false`) -> `fullMatrix=false`: one pass,
`-i <all selected GPUs>`. No NUMA-locality split.
- **Stress / deep** (`stress_mode=true`) -> `fullMatrix=true`: the
`2026-07-27` behaviour - one pass per resolved NUMA-node group, then one
all-GPU pass. If any selected GPU has no resolved NUMA node, the code does
not guess a group and falls back to the single all-GPU pass.
- `task_runner` passes `t.params.StressMode` through.
## Consequences
- Validate schedules exactly one nvbandwidth invocation regardless of NUMA-node count.
- The NUMA-locality isolation from `2026-07-27` is preserved, just moved to
the tier where a 2-3x runtime is acceptable. DO NOT re-add the split to the
Validate path.
- `SATEstimatedNvidiaBandwidthSec` still reflects a single pass; the deep
tier's multi-pass duration is not modelled - revisit once real
multi-node deep-run logs exist (same open item as `2026-07-27`).
+4
View File
@@ -11,3 +11,7 @@ One file per decision, named `YYYY-MM-DD-short-topic.md`.
| 2026-07-27 | Split the NVIDIA Bandwidth SAT into per-socket passes before the all-GPU pass | active |
| 2026-07-27 | Stream SAT job output live to disk and kick blackbox sync on job completion | active |
| 2026-07-28 | Move pci=realloc out of the default/toram/no-GUI GRUB entries | active |
| 2026-08-24 | PCIe Gen1-at-idle GPU warning: load-bearing link check, not idle sysfs | active |
| 2026-08-31 | nvbandwidth: single all-GPU pass in Validate, per-socket matrix only in deep tier | active |
| 2026-08-31 | bee-nvidia.service: never blocking `systemctl restart` on units ordered After= itself | active |
| 2026-08-31 | "Run All" SAT planning happens on the backend, not the browser | active |
@@ -1,54 +1,67 @@
# GPU PCIe Test Methodology
Which of the checks below run is decided by the backend (`POST
/api/sat/run-all` -> `handler.planSATRunAll`), not the web page: it enumerates
the hardware, waits for the NVIDIA driver to finish enumerating GPUs, and
enqueues only the applicable checks. The TPM check is planned only when sysfs
reports a TPM 2.x device (`tpm_version_major=2`). See
`bible-local/decisions/2026-08-31-backend-driven-sat-planning.md`.
## Validate
- CPU check
- `lscpu`
- `sensors`
- `stress-ng`
- `lscpu`
- `sensors`
- `stress-ng`
- Memory check
- `free`
- `timeout <timeout_sec> memtester`
- `free`
- `free`
- `timeout <timeout_sec> memtester`
- `free`
- NVMe storage check
- `nvme id-ctrl`
- `nvme smart-log`
- `nvme device-self-test`
- `nvme id-ctrl`
- `nvme smart-log`
- `nvme device-self-test`
- SATA/SAS storage check
- `smartctl -H -A`
- `smartctl -t short`
- `smartctl -H -A`
- `smartctl -t short`
- Basic NVIDIA GPU check
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dmidecode -t baseboard`
- `dmidecode -t system`
- `dcgmi diag -r 2`
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dmidecode -t baseboard`
- `dmidecode -t system`
- `dcgmi diag -r 2`
- Inter-GPU communication check
- `all_reduce_perf`
- `all_reduce_perf`
- GPU bandwidth check
- `dcgmi diag -r nvbandwidth`
- `dcgmi diag -r nvbandwidth` - **one pass across all GPUs** (`-i <all>`).
No NUMA-locality split in Validate.
## Validate -> Stress
- Extended NVIDIA GPU check
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dmidecode -t baseboard`
- `dmidecode -t system`
- `dcgmi diag -r 3`
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dmidecode -t baseboard`
- `dmidecode -t system`
- `dcgmi diag -r 3`
- NVIDIA targeted stress
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r targeted_stress`
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r targeted_stress`
- NVIDIA targeted power
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r targeted_power`
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r targeted_power`
- NVIDIA pulse test
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r pulse_test`
- `nvidia-smi -pm 1`
- `nvidia-smi -q`
- `dcgmi diag -r pulse_test`
- Inter-GPU communication check
- `all_reduce_perf`
- `all_reduce_perf`
- GPU bandwidth check
- `dcgmi diag -r nvbandwidth`
- `dcgmi diag -r nvbandwidth` - **per-NUMA-node matrix**: one pass per
completely resolved Linux PCI NUMA group, then one all-GPU pass. If any
selected GPU has no resolved `numa_node`, no group is guessed and the test
falls back to one all-GPU pass. See
`bible-local/decisions/2026-07-27-nvbandwidth-per-socket-split.md` and
`bible-local/decisions/2026-08-31-nvbandwidth-validate-single-deep-matrix.md`.
+14 -9
View File
@@ -17,15 +17,18 @@ This applies to:
## Bootloader sync rule
The ISO has two independent bootloader configs that must be kept in sync manually:
The ISO has two canonical bootloader templates whose live entries must remain
semantically equivalent:
| File | Used by |
|------|---------|
| `config/bootloaders/grub-efi/grub.cfg` | UEFI (all modern servers) |
| `config/bootloaders/isolinux/live.cfg.in` | CSM / legacy BIOS (syslinux) |
live-build does NOT derive one from the other. Any new boot entry, kernel parameter
change, or new mode added to one file must be manually mirrored in the other.
live-build does not derive one from the other. `lib/bootloader.sh` renders both
templates into the final `binary/` tree after live-build has created it, and the
ISO validator checks every live entry. Any menu or kernel-parameter change must
still be made in both templates.
**Canonical entry list** (both files must have all of these):
@@ -33,18 +36,20 @@ change, or new mode added to one file must be manually mirrored in the other.
|-------|-----------|
| normal (default) | `nomodeset bee.nvidia.mode=normal` + full param set |
| load to RAM | `toram nomodeset bee.nvidia.mode=normal` + full param set |
| GSP=off | `nomodeset bee.nvidia.mode=gsp-off` + full param set |
| KMS | no `nomodeset`, `bee.nvidia.mode=normal` + full param set |
| KMS + GSP=off | no `nomodeset`, `bee.nvidia.mode=gsp-off` + full param set |
| fail-safe | `nomodeset bee.nvidia.mode=gsp-off noapic noapm nodma nomce nolapic nosmp` |
| no GUI | `nomodeset bee.gui=off bee.nvidia.mode=normal` + full param set |
| fail-safe | normal parameters plus `pci=realloc iommu.strict=1` |
| wipe | `toram nomodeset bee.gui=off bee.wipe=all` + reduced performance params |
**Full standard param set** (append after `@APPEND_LIVE@` / `nomodeset` flags):
```
net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always
numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1
nowatchdog nosoftlockup
nowatchdog nosoftlockup udev.children_max=1 intel_iommu=on
iommu.passthrough=0 efi=disable_early_pci_dma
```
(fail-safe is the exception — it deliberately uses minimal params.)
The fail-safe entry alone adds `pci=realloc iommu.strict=1`. `pci=realloc` must
not be copied into normal entries. Memtest and firmware-setup entries are not
Linux live entries and therefore do not carry these parameters.
**Historical note:** `grub-pc/` was mistakenly used instead of `grub-efi/` until v8.25.
live-build reads `config/bootloaders/grub-efi/` for UEFI because the build is