From bdf20f2d8e1cdcd1ff4a8bc2fbfa17e67d0440d2 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Thu, 18 Jun 2026 20:13:31 +0100 Subject: [PATCH] feat(hardware): xe-aware GuC, class-based NPU detect, latestKernel + VM test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- README.md | 1 + docs/ROADMAP.md | 9 ++++++ flake.nix | 25 +++++++++++++++ modules/nixos/hardware.nix | 38 ++++++++++++++++++++--- pkgs/nomarchy-install/hardware-db.sh | 31 ++++++++++++------ pkgs/nomarchy-install/nomarchy-install.sh | 13 ++++++-- templates/downstream/system.nix | 1 + 7 files changed, 102 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c916558..1a47ed3 100644 --- a/README.md +++ b/README.md @@ -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.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.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.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) | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 7266096..df77081 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -279,6 +279,15 @@ how to override it. Items marked ✓ are shipped. **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 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): - **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 diff --git a/flake.nix b/flake.nix index 3ce076f..6e67080 100644 --- a/flake.nix +++ b/flake.nix @@ -134,6 +134,31 @@ downstream.nixosConfigurations.default.config.system.build.toplevel; downstream-template-home = 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 ──────────────────────────────────────────── diff --git a/modules/nixos/hardware.nix b/modules/nixos/hardware.nix index 2851055..b3d2c14 100644 --- a/modules/nixos/hardware.nix +++ b/modules/nixos/hardware.nix @@ -28,9 +28,12 @@ in default = cfg.intel.enable; defaultText = lib.literalExpression "config.nomarchy.hardware.intel.enable"; description = '' - Load the GPU's GuC/HuC firmware (i915.enable_guc=3) — better power - management and HuC-accelerated media on Gen11+ (Xe) iGPUs. On by - default with intel.enable; safe on modern Intel graphics. + Load the GPU's GuC/HuC firmware via the i915 param + (i915.enable_guc=3) — better power management and HuC-accelerated + 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 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 / - 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 [ @@ -136,12 +146,32 @@ in 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) ────────── + # 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) { 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) { 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 ───────────────────────────────────────────────────────── diff --git a/pkgs/nomarchy-install/hardware-db.sh b/pkgs/nomarchy-install/hardware-db.sh index 1497bec..c1cec3b 100644 --- a/pkgs/nomarchy-install/hardware-db.sh +++ b/pkgs/nomarchy-install/hardware-db.sh @@ -149,6 +149,13 @@ nomarchy_detect_hw() { if [[ "$cpu_vendor" == "GenuineIntel" || $intelgpu -eq 1 ]]; then echo "NOMARCHY hardware.intel.enable=true" 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 if [[ "$cpu_vendor" == "AuthenticAMD" || $amdgpu -eq 1 ]]; then echo "NOMARCHY hardware.amd.enable=true" @@ -177,16 +184,22 @@ nomarchy_detect_hw() { echo "DETAIL fingerprint reader detected → fprintd (PAM login/sudo opt-in)" fi - # NPU (detect-only → a commented, experimental opt-in). Intel VPU / - # AMD XDNA PCI IDs; best-effort across recent gens. + # NPU (detect-only → a commented, experimental opt-in). Match the PCI + # "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 lspci -nn 2>/dev/null | grep -qiE '\[8086:(7d1d|643e|ad1d|b03e)\]'; then - echo "NOMARCHY-NPU intel" - echo "DETAIL Intel NPU detected (opt-in, experimental)" - elif lspci -nn 2>/dev/null | grep -qiE '\[1022:1502\]'; then - echo "NOMARCHY-NPU amd" - echo "DETAIL AMD XDNA NPU detected (opt-in, experimental)" - fi + local npu_line + npu_line=$(lspci -nn 2>/dev/null \ + | grep -iE '\[1200\]|processing accelerat|neural|\[8086:(7d1d|643e|ad1d|b03e)\]|\[1022:1502\]' \ + | head -1) + case "$npu_line" in + *"[8086:"*|*Intel*) + 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 # Chassis (glob test, not compgen — nixpkgs' non-interactive bash diff --git a/pkgs/nomarchy-install/nomarchy-install.sh b/pkgs/nomarchy-install/nomarchy-install.sh index dc6ed3e..7ad186a 100644 --- a/pkgs/nomarchy-install/nomarchy-install.sh +++ b/pkgs/nomarchy-install/nomarchy-install.sh @@ -437,11 +437,12 @@ fi # experimental opt-ins written commented for the user to flip on. HARDWARE_CONFIG="" 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 for nm in "${HW_NOMARCHY[@]}"; do case "$nm" in hardware.intel.enable=true) has_intel=1 ;; + hardware.intel.guc=false) intel_guc_off=1 ;; hardware.amd.enable=true) has_amd=1 ;; hardware.fingerprint.enable=true) has_fp=1 ;; 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." if [[ $has_intel -eq 1 ]]; then 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)" fi if [[ $has_amd -eq 1 ]]; then @@ -467,7 +473,8 @@ if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then fi if [[ -n "$NPU_VENDOR" ]]; then 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 HARDWARE_CONFIG=$(cat <