feat(hardware): xe-aware GuC, class-based NPU detect, latestKernel + VM test
Harden the hardware-enablement broad seed for newer hardware: - xe vs i915: intel.guc emits the i915 param (i915.enable_guc=3), which the newer `xe` driver (Lunar Lake / Battlemage / Panther Lake, recent Xe GPUs) ignores — it enables GuC by default. hardware-db.sh now reads the in-use GPU driver (lspci -k) and writes `intel.guc = false` on xe hardware, so the toggle isn't a misleading no-op there. - NPU detection by PCI accelerator class [1200] (+ keywords), attributing the vendor, instead of a fixed device-ID list — so new NPUs (e.g. Panther Lake) are caught without a code change. Known IDs kept as a fallback/reference. - Kernel awareness: a nomarchy.hardware.latestKernel escape hatch (linuxPackages_latest) for very-new hardware whose drivers only just landed, and a build-time warning when npu.enable predates the shipped kernel (amdxdna needs 6.14+, intel_vpu wants recent). Downstream default is 6.18, which already carries amd-pstate + amdxdna; the reference host pins latest. - VM test (checks.hardware-toggles, pkgs.testers.runNixOSTest): boots a minimal VM with the toggles on and asserts the config landed — amd_pstate + i915.enable_guc in /proc/cmdline, fprintd.service present, pam_fprintd in /etc/pam.d/sudo. Passing. (Hardware behaviour still needs bare metal.) Docs: README + template note latestKernel; ROADMAP records the hardening. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -226,6 +226,7 @@ examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**.
|
|||||||
| `nomarchy.hardware.fingerprint.enable` | `false` | fprintd for a detected fingerprint reader (installer-set); enroll with `fprintd-enroll` |
|
| `nomarchy.hardware.fingerprint.enable` | `false` | fprintd for a detected fingerprint reader (installer-set); enroll with `fprintd-enroll` |
|
||||||
| `nomarchy.hardware.fingerprint.pam` | `false` | Opt-in: use the fingerprint for login + sudo (PAM) |
|
| `nomarchy.hardware.fingerprint.pam` | `false` | Opt-in: use the fingerprint for login + sudo (PAM) |
|
||||||
| `nomarchy.hardware.npu.enable` | `false` | Opt-in/experimental: load the on-die NPU driver (`amdxdna`/`intel_vpu`); userspace runtime is BYO |
|
| `nomarchy.hardware.npu.enable` | `false` | Opt-in/experimental: load the on-die NPU driver (`amdxdna`/`intel_vpu`); userspace runtime is BYO |
|
||||||
|
| `nomarchy.hardware.latestKernel` | `false` | Opt-in: ship `linuxPackages_latest` instead of the default kernel — for very new hardware whose drivers landed recently |
|
||||||
| `nomarchy.services.tailscale.enable` | `false` | Opt-in: Tailscale mesh VPN (then `sudo tailscale up`) |
|
| `nomarchy.services.tailscale.enable` | `false` | Opt-in: Tailscale mesh VPN (then `sudo tailscale up`) |
|
||||||
| `nomarchy.services.syncthing.enable` | `false` | Opt-in: Syncthing file sync as the login user (GUI at `127.0.0.1:8384`) |
|
| `nomarchy.services.syncthing.enable` | `false` | Opt-in: Syncthing file sync as the login user (GUI at `127.0.0.1:8384`) |
|
||||||
| `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) |
|
| `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) |
|
||||||
|
|||||||
@@ -279,6 +279,15 @@ how to override it. Items marked ✓ are shipped.
|
|||||||
**Remaining: on-hardware verification of the runtime bits (AMD/NPU/Intel
|
**Remaining: on-hardware verification of the runtime bits (AMD/NPU/Intel
|
||||||
GPU-compute) — none are testable in CI or on the Intel Latitudes for the
|
GPU-compute) — none are testable in CI or on the Intel Latitudes for the
|
||||||
AMD paths.** SSD TRIM is intentionally left to `common-pc-ssd`.
|
AMD paths.** SSD TRIM is intentionally left to `common-pc-ssd`.
|
||||||
|
- ✓ **Hardening (driver-gen + kernel awareness):** `intel.guc` emits the
|
||||||
|
*i915* param, so the installer turns it off when the GPU is on the newer
|
||||||
|
`xe` driver (Lunar Lake / Battlemage / Panther Lake — GuC is default-on
|
||||||
|
there); the NPU detector matches the PCI *accelerator class* (not just a
|
||||||
|
device-ID list) so new gens are caught without a code change; and a
|
||||||
|
`nomarchy.hardware.latestKernel` escape hatch (+ a build-time warning when
|
||||||
|
`npu.enable` predates the shipped kernel) covers very-new hardware whose
|
||||||
|
drivers only just landed. A config-assertion VM test guards the wiring
|
||||||
|
(`checks.hardware-toggles`: kernel cmdline + fprintd + PAM, booted in a VM).
|
||||||
Worked example — ThinkPad T14s (Ryzen 7 PRO 7840U + Radeon 780M):
|
Worked example — ThinkPad T14s (Ryzen 7 PRO 7840U + Radeon 780M):
|
||||||
- **GPU compute — ROCm:** the 780M is an RDNA3 iGPU (gfx1103) ROCm doesn't
|
- **GPU compute — ROCm:** the 780M is an RDNA3 iGPU (gfx1103) ROCm doesn't
|
||||||
officially list, so it needs `HSA_OVERRIDE_GFX_VERSION=11.0.0`. Multi-GB
|
officially list, so it needs `HSA_OVERRIDE_GFX_VERSION=11.0.0`. Multi-GB
|
||||||
|
|||||||
25
flake.nix
25
flake.nix
@@ -134,6 +134,31 @@
|
|||||||
downstream.nixosConfigurations.default.config.system.build.toplevel;
|
downstream.nixosConfigurations.default.config.system.build.toplevel;
|
||||||
downstream-template-home =
|
downstream-template-home =
|
||||||
downstream.homeConfigurations.me.activationPackage;
|
downstream.homeConfigurations.me.activationPackage;
|
||||||
|
|
||||||
|
# Config-level VM assertions for the nomarchy.hardware.* toggles —
|
||||||
|
# what they SET (kernel cmdline, fprintd, PAM). Real hardware
|
||||||
|
# behaviour (firmware/driver/device) needs bare metal and is out of
|
||||||
|
# scope here. Imports only hardware.nix, so the VM stays minimal.
|
||||||
|
hardware-toggles = pkgs.testers.runNixOSTest {
|
||||||
|
name = "nomarchy-hardware-toggles";
|
||||||
|
nodes.machine = { ... }: {
|
||||||
|
imports = [ ./modules/nixos/hardware.nix ];
|
||||||
|
nomarchy.hardware = {
|
||||||
|
intel.enable = true;
|
||||||
|
amd.enable = true;
|
||||||
|
fingerprint = { enable = true; pam = true; };
|
||||||
|
npu.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testScript = ''
|
||||||
|
machine.wait_for_unit("multi-user.target")
|
||||||
|
cmdline = machine.succeed("cat /proc/cmdline")
|
||||||
|
assert "amd_pstate=active" in cmdline, cmdline
|
||||||
|
assert "i915.enable_guc=3" in cmdline, cmdline
|
||||||
|
machine.succeed("systemctl cat fprintd.service")
|
||||||
|
machine.succeed("grep -q pam_fprintd /etc/pam.d/sudo")
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# ─── Reference host ────────────────────────────────────────────
|
# ─── Reference host ────────────────────────────────────────────
|
||||||
|
|||||||
@@ -28,9 +28,12 @@ in
|
|||||||
default = cfg.intel.enable;
|
default = cfg.intel.enable;
|
||||||
defaultText = lib.literalExpression "config.nomarchy.hardware.intel.enable";
|
defaultText = lib.literalExpression "config.nomarchy.hardware.intel.enable";
|
||||||
description = ''
|
description = ''
|
||||||
Load the GPU's GuC/HuC firmware (i915.enable_guc=3) — better power
|
Load the GPU's GuC/HuC firmware via the i915 param
|
||||||
management and HuC-accelerated media on Gen11+ (Xe) iGPUs. On by
|
(i915.enable_guc=3) — better power management and HuC-accelerated
|
||||||
default with intel.enable; safe on modern Intel graphics.
|
media. On by default with intel.enable. NOTE: this is the *i915*
|
||||||
|
driver's param; the newer `xe` driver (Lunar Lake / Battlemage /
|
||||||
|
Panther Lake and other recent Xe GPUs) enables GuC by default and
|
||||||
|
ignores it, so the installer turns this off on xe-driver hardware.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,7 +101,14 @@ in
|
|||||||
the on-die NPU (AI accelerator) kernel driver — amdxdna on AMD (Ryzen
|
the on-die NPU (AI accelerator) kernel driver — amdxdna on AMD (Ryzen
|
||||||
AI), intel_vpu on Intel (Core Ultra and newer). Opt-in and experimental:
|
AI), intel_vpu on Intel (Core Ultra and newer). Opt-in and experimental:
|
||||||
this loads the in-kernel driver only; the userspace runtime (AMD XRT /
|
this loads the in-kernel driver only; the userspace runtime (AMD XRT /
|
||||||
oneAPI Level Zero NPU) is yours to add'';
|
oneAPI Level Zero NPU) is yours to add. Needs a recent kernel (see
|
||||||
|
latestKernel)'';
|
||||||
|
|
||||||
|
latestKernel = lib.mkEnableOption ''
|
||||||
|
the latest mainline kernel (pkgs.linuxPackages_latest) instead of the
|
||||||
|
distro default — for very new hardware whose drivers (a fresh NPU, the
|
||||||
|
`xe` GPU driver, new-platform enablement) only landed recently. Off by
|
||||||
|
default; the default kernel already carries amd-pstate and amdxdna (6.14+)'';
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkMerge [
|
config = lib.mkMerge [
|
||||||
@@ -136,12 +146,32 @@ in
|
|||||||
security.pam.services.sudo.fprintAuth = true;
|
security.pam.services.sudo.fprintAuth = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# ── Newest kernel for very-new hardware (opt-in escape hatch) ──────
|
||||||
|
(lib.mkIf cfg.latestKernel {
|
||||||
|
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
|
||||||
|
})
|
||||||
|
|
||||||
# ── NPU (in-kernel driver only; userspace runtime is BYO) ──────────
|
# ── NPU (in-kernel driver only; userspace runtime is BYO) ──────────
|
||||||
|
# The driver has to actually be in the running kernel — warn (don't fail)
|
||||||
|
# when it predates the shipped one, pointing at latestKernel.
|
||||||
(lib.mkIf (cfg.npu.enable && cfg.amd.enable) {
|
(lib.mkIf (cfg.npu.enable && cfg.amd.enable) {
|
||||||
boot.kernelModules = [ "amdxdna" ];
|
boot.kernelModules = [ "amdxdna" ];
|
||||||
|
warnings = lib.optional
|
||||||
|
(!lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.14")
|
||||||
|
''
|
||||||
|
nomarchy.hardware.npu: the amdxdna driver needs kernel >= 6.14, but
|
||||||
|
this config ships ${config.boot.kernelPackages.kernel.version}. Set
|
||||||
|
nomarchy.hardware.latestKernel = true.'';
|
||||||
})
|
})
|
||||||
(lib.mkIf (cfg.npu.enable && cfg.intel.enable) {
|
(lib.mkIf (cfg.npu.enable && cfg.intel.enable) {
|
||||||
boot.kernelModules = [ "intel_vpu" ];
|
boot.kernelModules = [ "intel_vpu" ];
|
||||||
|
warnings = lib.optional
|
||||||
|
(!lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.11")
|
||||||
|
''
|
||||||
|
nomarchy.hardware.npu: the intel_vpu driver (especially for newer
|
||||||
|
NPUs) wants a recent kernel, but this config ships
|
||||||
|
${config.boot.kernelPackages.kernel.version}. Consider
|
||||||
|
nomarchy.hardware.latestKernel = true.'';
|
||||||
})
|
})
|
||||||
|
|
||||||
# ── Sanity ─────────────────────────────────────────────────────────
|
# ── Sanity ─────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -149,6 +149,13 @@ nomarchy_detect_hw() {
|
|||||||
if [[ "$cpu_vendor" == "GenuineIntel" || $intelgpu -eq 1 ]]; then
|
if [[ "$cpu_vendor" == "GenuineIntel" || $intelgpu -eq 1 ]]; then
|
||||||
echo "NOMARCHY hardware.intel.enable=true"
|
echo "NOMARCHY hardware.intel.enable=true"
|
||||||
echo "DETAIL nomarchy.hardware.intel: GuC/HuC on; GPU-compute runtime opt-in"
|
echo "DETAIL nomarchy.hardware.intel: GuC/HuC on; GPU-compute runtime opt-in"
|
||||||
|
# i915.enable_guc applies to the i915 driver only. The newer `xe` driver
|
||||||
|
# (Lunar Lake / Battlemage / Panther Lake, recent Xe GPUs) enables GuC by
|
||||||
|
# default and ignores the param — so turn the toggle off when xe is bound.
|
||||||
|
if lspci -k 2>/dev/null | grep -qiE 'driver in use: xe\b'; then
|
||||||
|
echo "NOMARCHY hardware.intel.guc=false"
|
||||||
|
echo "DETAIL Intel GPU on the xe driver → GuC default-on (i915 param skipped)"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ "$cpu_vendor" == "AuthenticAMD" || $amdgpu -eq 1 ]]; then
|
if [[ "$cpu_vendor" == "AuthenticAMD" || $amdgpu -eq 1 ]]; then
|
||||||
echo "NOMARCHY hardware.amd.enable=true"
|
echo "NOMARCHY hardware.amd.enable=true"
|
||||||
@@ -177,16 +184,22 @@ nomarchy_detect_hw() {
|
|||||||
echo "DETAIL fingerprint reader detected → fprintd (PAM login/sudo opt-in)"
|
echo "DETAIL fingerprint reader detected → fprintd (PAM login/sudo opt-in)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# NPU (detect-only → a commented, experimental opt-in). Intel VPU /
|
# NPU (detect-only → a commented, experimental opt-in). Match the PCI
|
||||||
# AMD XDNA PCI IDs; best-effort across recent gens.
|
# "Processing accelerators" class [1200] (or accelerator keywords) and
|
||||||
|
# attribute by vendor — future-proof vs a per-device-ID list, so new gens
|
||||||
|
# (e.g. Panther Lake) are caught without a code change. Known IDs kept for
|
||||||
|
# reference: Intel VPU 8086:{7d1d,643e,ad1d,b03e}, AMD XDNA 1022:1502.
|
||||||
if command -v lspci >/dev/null 2>&1; then
|
if command -v lspci >/dev/null 2>&1; then
|
||||||
if lspci -nn 2>/dev/null | grep -qiE '\[8086:(7d1d|643e|ad1d|b03e)\]'; then
|
local npu_line
|
||||||
echo "NOMARCHY-NPU intel"
|
npu_line=$(lspci -nn 2>/dev/null \
|
||||||
echo "DETAIL Intel NPU detected (opt-in, experimental)"
|
| grep -iE '\[1200\]|processing accelerat|neural|\[8086:(7d1d|643e|ad1d|b03e)\]|\[1022:1502\]' \
|
||||||
elif lspci -nn 2>/dev/null | grep -qiE '\[1022:1502\]'; then
|
| head -1)
|
||||||
echo "NOMARCHY-NPU amd"
|
case "$npu_line" in
|
||||||
echo "DETAIL AMD XDNA NPU detected (opt-in, experimental)"
|
*"[8086:"*|*Intel*)
|
||||||
fi
|
echo "NOMARCHY-NPU intel"; echo "DETAIL Intel NPU detected (opt-in, experimental)" ;;
|
||||||
|
*"[1022:"*|*"Advanced Micro Devices"*|*AMD*)
|
||||||
|
echo "NOMARCHY-NPU amd"; echo "DETAIL AMD XDNA NPU detected (opt-in, experimental)" ;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Chassis (glob test, not compgen — nixpkgs' non-interactive bash
|
# Chassis (glob test, not compgen — nixpkgs' non-interactive bash
|
||||||
|
|||||||
@@ -437,11 +437,12 @@ fi
|
|||||||
# experimental opt-ins written commented for the user to flip on.
|
# experimental opt-ins written commented for the user to flip on.
|
||||||
HARDWARE_CONFIG=""
|
HARDWARE_CONFIG=""
|
||||||
if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then
|
if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then
|
||||||
has_intel=0; has_amd=0; has_fp=0
|
has_intel=0; has_amd=0; has_fp=0; intel_guc_off=0
|
||||||
if [[ ${#HW_NOMARCHY[@]} -gt 0 ]]; then
|
if [[ ${#HW_NOMARCHY[@]} -gt 0 ]]; then
|
||||||
for nm in "${HW_NOMARCHY[@]}"; do
|
for nm in "${HW_NOMARCHY[@]}"; do
|
||||||
case "$nm" in
|
case "$nm" in
|
||||||
hardware.intel.enable=true) has_intel=1 ;;
|
hardware.intel.enable=true) has_intel=1 ;;
|
||||||
|
hardware.intel.guc=false) intel_guc_off=1 ;;
|
||||||
hardware.amd.enable=true) has_amd=1 ;;
|
hardware.amd.enable=true) has_amd=1 ;;
|
||||||
hardware.fingerprint.enable=true) has_fp=1 ;;
|
hardware.fingerprint.enable=true) has_fp=1 ;;
|
||||||
esac
|
esac
|
||||||
@@ -451,7 +452,12 @@ if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then
|
|||||||
# the heavier opt-ins are commented — uncomment to turn them on."
|
# the heavier opt-ins are commented — uncomment to turn them on."
|
||||||
if [[ $has_intel -eq 1 ]]; then
|
if [[ $has_intel -eq 1 ]]; then
|
||||||
hw_lines+="
|
hw_lines+="
|
||||||
nomarchy.hardware.intel.enable = true; # GuC/HuC firmware (i915.enable_guc=3)
|
nomarchy.hardware.intel.enable = true; # GuC/HuC firmware (i915.enable_guc=3)"
|
||||||
|
if [[ $intel_guc_off -eq 1 ]]; then
|
||||||
|
hw_lines+="
|
||||||
|
nomarchy.hardware.intel.guc = false; # GPU on the xe driver → GuC is default-on"
|
||||||
|
fi
|
||||||
|
hw_lines+="
|
||||||
# nomarchy.hardware.intel.computeRuntime = true; # OpenCL/oneVPL GPU compute (opt-in)"
|
# nomarchy.hardware.intel.computeRuntime = true; # OpenCL/oneVPL GPU compute (opt-in)"
|
||||||
fi
|
fi
|
||||||
if [[ $has_amd -eq 1 ]]; then
|
if [[ $has_amd -eq 1 ]]; then
|
||||||
@@ -467,7 +473,8 @@ if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then
|
|||||||
fi
|
fi
|
||||||
if [[ -n "$NPU_VENDOR" ]]; then
|
if [[ -n "$NPU_VENDOR" ]]; then
|
||||||
hw_lines+="
|
hw_lines+="
|
||||||
# nomarchy.hardware.npu.enable = true; # $NPU_VENDOR NPU driver (experimental; userspace runtime BYO)"
|
# nomarchy.hardware.npu.enable = true; # $NPU_VENDOR NPU driver (experimental; userspace runtime BYO)
|
||||||
|
# nomarchy.hardware.latestKernel = true; # newest kernel if the NPU driver isn't in the shipped one"
|
||||||
fi
|
fi
|
||||||
HARDWARE_CONFIG=$(cat <<NIX
|
HARDWARE_CONFIG=$(cat <<NIX
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
# fingerprint.enable = true; # fprintd; installer-set when a reader is detected
|
# fingerprint.enable = true; # fprintd; installer-set when a reader is detected
|
||||||
# fingerprint.pam = true; # use the fingerprint for login + sudo
|
# fingerprint.pam = true; # use the fingerprint for login + sudo
|
||||||
# npu.enable = true; # on-die NPU driver (experimental; userspace runtime BYO)
|
# npu.enable = true; # on-die NPU driver (experimental; userspace runtime BYO)
|
||||||
|
# latestKernel = true; # newest kernel for very-new hardware (drivers not yet in the default)
|
||||||
# };
|
# };
|
||||||
#
|
#
|
||||||
# nomarchy.services.tailscale.enable = true; # mesh VPN — then `sudo tailscale up`
|
# nomarchy.services.tailscale.enable = true; # mesh VPN — then `sudo tailscale up`
|
||||||
|
|||||||
Reference in New Issue
Block a user