← Back to list

Running LLMs on the AMD Strix Halo NPU Under Linux — A Complete Guide for Fedora 43

If you own a Ryzen AI MAX+ 395 machine with 128GB unified memory and you’re running Linux, this guide is for you.

Mark Baker · 2026-03-26 15:13 · 10 claps · 7.8 min read
#llm #npu #halo-strix #amd-ryzen #ai
Open on Medium ↗
Wiki topics: LLM · Large Language Models AI · AI · General 🔓 · Open Source 🏃 · Running & Endurance 🧘 · Spirituality

Running LLMs on the AMD Strix Halo NPU Under Linux — A Complete Guide for Fedora 43

If you own a Ryzen AI MAX+ 395 machine with 128GB unified memory and you’re running Linux, this guide is for you.

An honest note on process: I used Claude (Anthropic) as an AI assistant throughout this work — for debugging help, research, and drafting this writeup. Every command was run and validated by me on my own hardware.

There’s a dedicated AI accelerator sitting inside your AMD Ryzen AI MAX+ 395 that most Linux users haven’t been able to touch — until now. The XDNA 2 NPU has 50 TOPS of dedicated AI compute, and as of late March 2026, the full software stack to use it for LLM inference on Linux is finally in place. Getting there requires a pre-release kernel, building two components from source, and a handful of dependency fixes that aren’t documented anywhere in one place.

This guide walks through exactly what it took on a Nimo MME2S and Corsair AI Workstation 300 (both Sixunited AXB35 board — same silicon as the GMKtec EVO-X2 and Bosgame M5) running Fedora 43. Every command here was run and verified.

What you’ll end up with: Linux kernel 7.0-rc6 (or later), XRT 2.23.0 built from source, FastFlowLM 0.9.37 built from source, and a validated NPU running LLM inference.

Prerequisites

  • Fedora 43 installed and running (kernel 6.x is fine as a starting point)
  • You’re in the video and render groups: sudo usermod -aG video,render $(whoami)
  • Basic familiarity with building software from source
  • About 2–3 hours and a decent internet connection

Part 1: Installing Kernel 7.0

The NPU firmware protocol changed between the 6.x and 7.0 kernel series. Specifically, firmware version 1.1.x requires protocol support that only landed in kernel 7.0. Without it, the driver loads but immediately fails with:

aie2_check_protocol: Incompatible firmware protocol major 7 minor 2
aie2_hw_start: firmware is not alive

Fedora’s build infrastructure (Koji) already has the latest rc build available. Install koji and check what’s current:

sudo dnf install -y koji
koji latest-build rawhide kernel

This will show you the current build name. At time of writing it’s kernel-7.0.0-0.rc6.49.fc45. The rc number advances — use whatever koji latest-build returns, the process is identical. Download it:

koji download-build --arch=x86_64 kernel-7.0.0-0.rc6.49.fc45

Install the essential packages (you only need core, modules, and modules-extra — skip the debug and devel packages unless you need them):

sudo dnf install -y \
  kernel-core-7.0.0-0.rc6.*.x86_64.rpm \
  kernel-modules-core-7.0.0-0.rc6.*.x86_64.rpm \
  kernel-modules-7.0.0-0.rc6.*.x86_64.rpm \
  kernel-modules-extra-7.0.0-0.rc6.*.x86_64.rpm \
  kernel-7.0.0-0.rc6.*.x86_64.rpm

Set it as the default boot entry. Use the exact version string from your download:

sudo grub2-set-default "7.0.0-0.rc6.49.fc45.x86_64"
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Add the required kernel parameters via /etc/default/grub. Open it and append to GRUB_CMDLINE_LINUX:

ttm.pages_limit=32505856 ttm.page_pool_size=32505856 amdgpu.cwsr_enable=0

Important: Do NOT add amd_iommu=off. That parameter is sometimes recommended for Strix Halo GPU performance in llama.cpp, but it completely disables the NPU (/dev/accel/accel0 will not appear). Leave IOMMU enabled.

Rebuild grub and reboot:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot

After rebooting, confirm you’re on the new kernel and parameters are set:

uname -r
# 7.0.0-0.rc6.49.fc45.x86_64
cat /proc/cmdline
# Should include the three ttm/amdgpu params

Update the NPU Firmware

The default firmware on the system (npu.sbin.1.0.0.166) is incompatible with the new driver protocol. You need firmware 1.1.2.65, which is in the upstream linux-firmware git repository but not yet in the Fedora package:

git clone --depth 1 \
  https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git \
  /tmp/linux-firmware-upstream
# Install the newer firmware
sudo cp /tmp/linux-firmware-upstream/amdnpu/17f0_11/npu.sbin.1.1.2.65 \
  /lib/firmware/amdnpu/17f0_11/
# Point the symlink at it
sudo ln -sf npu.sbin.1.1.2.65 /lib/firmware/amdnpu/17f0_11/npu.sbin
# Rebuild initramfs and reload the driver
sudo dracut --force
sudo modprobe -r amdxdna
sudo modprobe amdxdna
# Verify
cat /sys/bus/pci/drivers/amdxdna/*/fw_version
# 1.1.2.65

Part 2: Building XRT 2.23.0 from Source

XRT (Xilinx Runtime) is the userspace library stack that FLM uses to talk to the NPU hardware. There’s a Fedora COPR package available (xanderlent/amd-npu-driver) but it ships XRT 2.19.0, which is missing the xrt::runlist::add API that FLM's prebuilt NPU kernel libraries require. You'll hit a linker error if you try to use it.

The right approach is to build XRT from the xdna-driver repo using its own build system, which pins XRT at exactly the version the NPU driver was tested against (builds as 2.23.0).

Clone and Prepare

git clone --recursive https://github.com/amd/xdna-driver.git ~/xdna-driver

The --recursive flag is important — XRT is a submodule.

Install Build Dependencies

sudo dnf install -y \
  gcc-c++ cmake ninja-build \
  ncurses-devel \
  python3-pybind11 pybind11-devel \
  systemtap-sdt-devel \
  libstdc++-static glibc-static \
  ocl-icd-devel opencl-headers \
  libdrm-devel \
  python3-devel \
  elfutils-libelf-devel \
  rapidjson-devel \
  boost-devel \
  libuuid-devel \
  rpm-build \
  openssl-devel

Build Using the Provided Build Script

The repo has its own build system that handles XRT and the XDNA plugin together in one pass. Use it:

cd ~/xdna-driver/build
./build.sh -release -nokmod

-nokmod skips the kernel module (already in-tree on kernel 7.0). This will take several minutes — it builds XRT core, the XDNA shim, and downloads some prebuilt NPU kernel archives from GitHub.

When the build completes, generate the RPM package:

cd ~/xdna-driver/build/Release
cpack

You should see:

CPack: - package: .../xrt_plugin.2.23.0_43-x86_64-amdxdna.rpm generated.

Install the RPM

The RPM declares a dependency on xrt-base which doesn't exist as a separate package in this build path. Use --nodeps to bypass it — we'll install the required libraries manually in the next step:

sudo rpm -ivh --nodeps ~/xdna-driver/build/Release/xrt_plugin.2.23.0_43-x86_64-amdxdna.rpm

Install XRT Core Libraries

The RPM installs the XDNA plugin but not the XRT core libraries. Copy them from the build output:

sudo mkdir -p /opt/xilinx/xrt/lib64
sudo cp ~/xdna-driver/build/Release/bins/lib64/libxrt_core.so.2.23.0 /opt/xilinx/xrt/lib64/
sudo cp ~/xdna-driver/build/Release/bins/lib64/libxrt_coreutil.so.2.23.0 /opt/xilinx/xrt/lib64/
# Create versioned symlinks
sudo ln -sf libxrt_core.so.2.23.0     /opt/xilinx/xrt/lib64/libxrt_core.so.2
sudo ln -sf libxrt_core.so.2.23.0     /opt/xilinx/xrt/lib64/libxrt_core.so
sudo ln -sf libxrt_coreutil.so.2.23.0 /opt/xilinx/xrt/lib64/libxrt_coreutil.so.2
sudo ln -sf libxrt_coreutil.so.2.23.0 /opt/xilinx/xrt/lib64/libxrt_coreutil.so

Install XRT Headers

FLM’s build system needs the XRT headers. Copy them from the submodule source:

sudo mkdir -p /opt/xilinx/xrt/include
sudo cp -r ~/xdna-driver/xrt/src/runtime_src/core/include/xrt /opt/xilinx/xrt/include/
sudo cp -r ~/xdna-driver/xrt/src/runtime_src/core/include/experimental /opt/xilinx/xrt/include/

Fix the lib vs lib64 Path

FLM links against -L/opt/xilinx/xrt/lib but the libraries are in lib64. Create a symlink:

sudo ln -sf /opt/xilinx/xrt/lib64 /opt/xilinx/xrt/lib

Verify the Critical Symbol

Before moving on, confirm the API that FLM needs is present in the built library:

nm -D /opt/xilinx/xrt/lib64/libxrt_coreutil.so.2.23.0 | grep "runlist.*add"
# Should show: T _ZN3xrt7runlist3addEONS_3runE

If you see that symbol, you’re good.

Make XRT Permanent

These steps ensure FLM works correctly in all contexts — interactive shells, systemd services, and any process that doesn’t manually set up the environment:

# Make the libraries findable by the dynamic linker
echo '/opt/xilinx/xrt/lib64' | sudo tee /etc/ld.so.conf.d/xrt.conf
sudo ldconfig
# flm serve looks for libxrt_core in /usr/local/lib64 specifically
sudo ln -sf /opt/xilinx/xrt/lib64/libxrt_core.so.2.23.0 /usr/local/lib64/libxrt_core.so.2
sudo ln -sf /opt/xilinx/xrt/lib64/libxrt_core.so.2.23.0 /usr/local/lib64/libxrt_core.so
# Set XRT environment variables for all shells and systemd services
sudo tee /etc/profile.d/xrt.sh <<EOF
export XILINX_XRT=/opt/xilinx/xrt
export PATH=/opt/xilinx/xrt/bin:\$PATH
export LD_LIBRARY_PATH=/opt/xilinx/xrt/lib64:\$LD_LIBRARY_PATH
EOF

Part 3: Building FastFlowLM from Source

FastFlowLM (FLM) is the inference engine that orchestrates NPU-accelerated LLM inference. The prebuilt NPU kernel libraries in the repo (src/lib/) are closed-source, but FLM itself builds from source against those.

Clone FastFlowLM

git clone https://github.com/FastFlowLM/FastFlowLM.git ~/FastFlowLM
cd ~/FastFlowLM
git submodule update --init --recursive

Install Build Dependencies

Several of these aren’t obvious from the error messages — here’s the complete list:

sudo dnf install -y \
  cargo rust \
  libcurl-devel \
  libuuid-devel \
  libdrm-devel \
  fftw-devel \
  ffmpeg-free-devel \
  boost-program-options \
  boost-devel \
  ncurses-devel

The ffmpeg headers in Fedora install to /usr/include/ffmpeg/ rather than the standard /usr/include/ path that the build system expects. Fix this with symlinks:

sudo ln -sf /usr/include/ffmpeg/libavcodec    /usr/include/libavcodec
sudo ln -sf /usr/include/ffmpeg/libavformat   /usr/include/libavformat
sudo ln -sf /usr/include/ffmpeg/libavutil     /usr/include/libavutil
sudo ln -sf /usr/include/ffmpeg/libswresample /usr/include/libswresample
sudo ln -sf /usr/include/ffmpeg/libswscale    /usr/include/libswscale
sudo ln -sf /usr/include/ffmpeg/libavdevice   /usr/include/libavdevice
sudo ln -sf /usr/include/ffmpeg/libavfilter   /usr/include/libavfilter

Configure and Build

cd ~/FastFlowLM
cmake -S src --preset linux-default
ninja -C src/build -j$(nproc)

The first build will take some time — the Rust tokenizer library (tokenizers-cpp) compiles all its dependencies from scratch. Subsequent builds are fast.

Install:

sudo ninja -C src/build install

FLM installs to /opt/fastflowlm/.

Part 4: Validation and First Inference

Set the Memlock Limit

The NPU requires unlimited locked memory. Add this to /etc/security/limits.conf:

sudo tee -a /etc/security/limits.conf <<EOF
*    soft    memlock    unlimited
*    hard    memlock    unlimited
EOF

Reboot at this point. The memlock change requires a full reboot to take effect — a new shell or ulimit -l unlimited in an unprivileged session will fail with "Operation not permitted".

Validate

flm validate

You should see:

[Linux]  Kernel: 7.0.0-rc6...
[Linux]  NPU: /dev/accel/accel0 with 8 columns
[Linux]  NPU FW Version: 1.1.2.65
[Linux]  amdxdna version: 0.6
[Linux]  Memlock Limit: infinity

amdxdna version: 0.6 is expected — it refers to the kernel driver interface version, not a problem.

Note that flm validate works without sudo — the /dev/accel/accel0 device is owned by the render group (crw-rw-rw-. 1 root render), which you added yourself to in the prerequisites.

Pull a Model and Run It

flm pull qwen3:4b
flm run qwen3:4b --pmode turbo

Inside the interactive session, use /verbose to see performance metrics:

>>> /verbose
>>> Explain the difference between vLLM and llama.cpp in 3 sentences
...
Verbose:
  TTFT:           1.31 s
  Prefill speed:  22.12 tokens/s
  Decoding speed: 19.10 tokens/s

For a broader look at available models:

flm list

You’ll find llama3.x, Qwen3, Gemma3, Phi4, Whisper, and multimodal (VL) variants — all with NPU-optimized kernels. The 4B models decode at around 19–20 t/s; the 1B model at ~62 t/s.

Serve via OpenAI-Compatible API

FLM includes a server mode that exposes an OpenAI-compatible REST API — useful for pointing other tools at your NPU without any API keys or cloud costs:

flbm serve llama3.2:1b --host 0.0.0.0 --port 8081 --pmode turbo

Open port 8081 in the firewall if you want to reach it from other machines on your LAN:

sudo firewall-cmd --add-port=8081/tcp --permanent && sudo firewall-cmd --reload

Test it from any machine on your network:

curl -s -X POST http://<server-ip>:8081/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.2:1b",
    "messages": [{"role": "user", "content": "Hello from the NPU!"}]
  }' | python3 -c "import sys,json; r=json.load(sys.stdin); print(r['choices'][0]['message']['content'])"

At ~54 t/s over LAN with a 1B model, this is a responsive and low-power endpoint for agentic workloads that don’t need heavy reasoning.

Understanding What You’ve Actually Built

A few honest notes for context.

The NPU is a Copilot+ PC feature, not an HPC accelerator. It was designed for background tasks: real-time transcription, translation, camera effects. At 50 TOPS of dedicated INT8 compute it’s genuinely useful for small models running continuously, but it doesn’t compete with the GPU for raw throughput — your Radeon 8060S with 256 GB/s of memory bandwidth will outpace the NPU on anything larger than ~4B parameters.

Where the NPU shines is power efficiency and simultaneous use. Running a lightweight monitoring or routing model on the NPU while the GPU handles the heavy lifting is a compelling architecture for 24/7 agentic workflows — both can run at the same time without contention.

The GPU story on this hardware is also worth mentioning: with ROCm 7.x and the kyuz0 toolboxes (see strix-halo-toolboxes.com), a 35B MoE model runs at ~47 t/s decode and a 72B Q4 at ~4.8 t/s — serious numbers for a mini PC. The NPU complements that, it doesn’t replace it.

Quick Reference: What You Built and Where It Lives

What you build and where it lives. Way to go!

What you build and where it lives. Way to go!

Key References

Tested on a Nimo MME2S and Corsair AI Workstation 300 (Sixunited AXB35 board, AMD Ryzen AI MAX+ 395, 128GB LPDDR5X) running Fedora 43 Server Edition. The same board ships under several OEM names including GMKtec EVO-X2 and Bosgame M5.


메타데이터
post_id
5544acfbfcec
slug
running-llms-on-the-amd-strix-halo-npu-under-linux-a-complete-guide-for-fedora-43-5544acfbfcec
url
https://medium.com/@Fail-Safe/running-llms-on-the-amd-strix-halo-npu-under-linux-a-complete-guide-for-fedora-43-5544acfbfcec
canonical_url
https://medium.com/@Fail-Safe/running-llms-on-the-amd-strix-halo-npu-under-linux-a-complete-guide-for-fedora-43-5544acfbfcec
author_url
https://medium.com/@Fail-Safe
status
ok
fetched_at
2026-08-11 04:39:50