This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2026-08-20 00:45:43 +02:00

873 lines
26 KiB
Markdown

!!!warning ""
This was my try on implementing ROCm to the BC250. It is discontinued as of March 22th 2026 (Latest Commit).
This Repository is a sanitized re-upload of my findings based off of [Dani's research](./_TestScripts/Danis%20ROCm%20Kernel%20Patch%20Research/) including the Patches that are now applyed to [project-ariel](https://github.com/cachenetics/project-ariel). This Repository is now a public Archive under the GPL-2.0 License and can be used as such.
# ROCm on AsRock BC-250 — Complete Installation Guide
**Hardware**: AsRock BC-250 (AMD Cyan Skillfish / gfx1013)
**Target ROCm**: 7.2.0 | **OS**: CachyOS (Arch-based) | **Shell**: fish / bash
**Bootloader**: Limine | **Compiler**: Clang (LLVM)
**Author**: [Fabian](https://git.sudx.de/Fabian) | **Last Updated**: 2026-03-17
**Honorable Mention**: [Dani](https://git.sudx.de/Dani) (Creator of first KIQ Timeout fix)
# This is not working Standalone.
---
## Table of Contents
1. [Hardware Overview](#1-hardware-overview)
2. [Prerequisites](#2-prerequisites)
3. [Step 1 — Install ROCm Packages](#3-step-1--install-rocm-packages)
4. [Step 2 — User Group Configuration](#4-step-2--user-group-configuration)
5. [Step 3 — Environment Variables](#5-step-3--environment-variables)
6. [Step 4 — Kernel Boot Parameters](#6-step-4--kernel-boot-parameters)
7. [Step 5 — Modprobe Configuration](#7-step-5--modprobe-configuration)
8. [Step 6 — Build Patched amdgpu Kernel Module](#8-step-6--build-patched-amdgpu-kernel-module)
9. [Step 7 — Install Module & Reboot](#9-step-7--install-module--reboot)
10. [Step 8 — Post-Reboot Verification](#10-step-8--post-reboot-verification)
11. [Step 9 — HIP Compute Tests](#11-step-9--hip-compute-tests)
12. [Cyan Skillfish Governor (GPU Clock Management)](#12-cyan-skillfish-governor-gpu-clock-management)
13. [GPU Watchdog (Safety Monitor)](#13-gpu-watchdog-safety-monitor)
14. [HIP Programming Guidelines for BC-250](#14-hip-programming-guidelines-for-bc-250)
15. [Kernel Module Rebuild After Updates](#15-kernel-module-rebuild-after-updates)
16. [Technical Reference — Why This GPU Needs Patches](#16-technical-reference--why-this-gpu-needs-patches)
17. [Troubleshooting](#17-troubleshooting)
18. [File Inventory](#18-file-inventory)
---
## 1. Hardware Overview
```
GPU: AMD BC-250 (Cyan Skillfish)
Device ID: 0x13FE (Vendor: 0x1002 AMD)
Architecture: RDNA 1.5 (GFX 10.1.3 / gfx1013)
ROCm Target: gfx10-1-generic (auto-mapped), runs as gfx1010 via override
Compute Units: 24 (reported by some tools as 12 due to SIMD config)
Wavefront Size: 32 (RDNA-style)
Memory: ~14.75 GB shared system GDDR6 (NO dedicated VRAM)
Memory Type: APU-style unified memory (system RAM shared with CPU)
PCIe: Internal SoC fabric (Completion Timeout: Not Supported)
```
### Why This GPU Is Special
The BC-250 is a **cryptocurrency mining board repurposed as a compute accelerator**. It behaves
like an APU — there is **no dedicated VRAM**; all GPU memory operations use system RAM. This has
critical implications:
| Behavior | Explanation |
|----------|-------------|
| **No standard hipMalloc** | Standard device memory allocation targets non-existent VRAM |
| **hipMallocManaged required** | Unified memory works on shared RAM |
| **hipHostMalloc works** | Pinned host memory is safe for APU |
| **GPU reset = system crash** | Resetting the GPU corrupts shared system RAM |
| **SDMA engine unreliable** | Must disable via `HSA_ENABLE_SDMA=0` |
| **GFXOFF is fatal** | GPU enters power-save and can't wake — CPU hangs on MMIO read |
| **KIQ ring is broken** | KIQ commands cause fence timeouts → system hang |
---
## 2. Prerequisites
- CachyOS (or Arch-based distro) with a working internet connection
- `sudo` access for the installation user
- `paru` or another AUR helper (for the GPU governor)
- Sufficient disk space (~2 GB for kernel source + build artifacts)
Install base build dependencies:
```fish
sudo pacman -S --needed --noconfirm base-devel bc python
```
---
## 3. Step 1 — Install ROCm Packages
Install all 16 required ROCm 7.2.0 packages:
```fish
sudo pacman -S --needed --noconfirm \
rocm-core hsa-rocr rocminfo rocm-smi-lib rocm-device-libs \
rocm-llvm comgr hip-runtime-amd rocm-hip-runtime \
rocm-opencl-runtime rocblas hipblas rocrand rocm-cmake \
rocm-language-runtime hipblas-common
```
You can also run the provided script:
```fish
bash scripts/01_install_rocm_packages.sh
```
### Package List
| Package | Description |
|---------|-------------|
| `rocm-core` | ROCm core (version files) |
| `hsa-rocr` | HSA Runtime API |
| `rocminfo` | ROCm system info tool |
| `rocm-smi-lib` | ROCm SMI library |
| `rocm-device-libs` | ROCm device libraries |
| `rocm-llvm` | ROCm LLVM/Clang compiler (~4.5 GB) |
| `comgr` | AMDGPU Code Object Manager |
| `hip-runtime-amd` | HIP Runtime (AMD backend) |
| `rocm-hip-runtime` | Meta-package for HIP runtime |
| `rocm-opencl-runtime` | ROCm OpenCL runtime |
| `rocblas` | ROCm BLAS library |
| `hipblas` | ROCm BLAS marshalling library |
| `hipblas-common` | hipBLAS common files |
| `rocrand` | ROCm random number generator |
| `rocm-cmake` | ROCm CMake modules |
| `rocm-language-runtime` | ROCm language runtime meta |
---
## 4. Step 2 — User Group Configuration
Add your user to the `render` and `video` groups:
```fish
sudo usermod -aG render,video $USER
```
**You must log out and back in** (or reboot) for group changes to take effect.
Verify:
```fish
groups $USER
# Should include: render video
```
---
## 5. Step 3 — Environment Variables
The BC-250 requires specific environment variables for ROCm to function. With the v3 kernel
patches (Step 6), only a **minimal set** is needed.
### For fish shell
Add to `~/.config/fish/config.fish`:
```fish
# === ROCm Configuration for AMD BC-250 ===
set -gx PATH /opt/rocm/bin $PATH
set -gx LD_LIBRARY_PATH /opt/rocm/lib $LD_LIBRARY_PATH
set -gx ROCM_PATH /opt/rocm
set -gx HSA_OVERRIDE_GFX_VERSION 10.1.0
set -gx HIP_VISIBLE_DEVICES 0
set -gx HSA_ENABLE_SDMA 0
set -gx HSA_TOOLS_LIB ""
set -gx HSA_TOOLS_REPORT_LOAD_FAILURE 0
```
### For bash shell
Add to `~/.bashrc`:
```bash
# === ROCm Configuration for AMD BC-250 ===
export PATH="/opt/rocm/bin:$PATH"
export LD_LIBRARY_PATH="/opt/rocm/lib:$LD_LIBRARY_PATH"
export ROCM_PATH=/opt/rocm
export HSA_OVERRIDE_GFX_VERSION=10.1.0
export HIP_VISIBLE_DEVICES=0
export HSA_ENABLE_SDMA=0
export HSA_TOOLS_LIB=""
export HSA_TOOLS_REPORT_LOAD_FAILURE=0
```
You can also run the provided script:
```fish
bash scripts/02_configure_environment.sh
```
### Variable Reference
| Variable | Value | Why Required |
|----------|-------|--------------|
| `HSA_OVERRIDE_GFX_VERSION` | `10.1.0` | Maps gfx1013 → gfx1010 (closest supported target) |
| `HIP_VISIBLE_DEVICES` | `0` | Explicit GPU device selection |
| `HSA_ENABLE_SDMA` | `0` | SDMA engine is broken on gfx1013, use shader DMA |
| `HSA_TOOLS_LIB` | `""` | Prevent profiling tools from destabilizing GPU |
| `HSA_TOOLS_REPORT_LOAD_FAILURE` | `0` | Suppress tool load warnings |
### Variables You Must NOT Set
These were pre-v3 workarounds that **severely hurt performance**:
| Variable | Why It's Harmful |
|----------|------------------|
| `GPU_MAX_HW_QUEUES=1` | Serializes all GPU ops to 1 queue — severe slowdown |
| `HIP_LAUNCH_BLOCKING=1` | Forces synchronous kernel launches — prevents pipelining |
| `HSA_DISABLE_FRAGMENT_ALLOCATOR=1` | Not needed with v3 patches |
---
## 6. Step 4 — Kernel Boot Parameters
### Limine Bootloader
Edit `/etc/default/limine` and add these parameters to the `KERNEL_CMDLINE`:
```
amdgpu.gpu_recovery=1 amdgpu.noretry=0 amdgpu.dc=0 amdgpu.lockup_timeout=120000 amdgpu.ppfeaturemask=0xfff73ef7
```
Apply changes:
```fish
sudo limine-update
```
### GRUB Bootloader (if applicable)
Edit `/etc/default/grub` and add to `GRUB_CMDLINE_LINUX_DEFAULT`:
```
amdgpu.gpu_recovery=1 amdgpu.noretry=0 amdgpu.dc=0 amdgpu.lockup_timeout=120000 amdgpu.ppfeaturemask=0xfff73ef7
```
Apply changes:
```bash
sudo grub-mkconfig -o /boot/grub/grub.cfg
```
### Parameter Reference
| Parameter | Value | Purpose |
|-----------|-------|---------|
| `amdgpu.gpu_recovery=1` | Enabled | **CRITICAL**: Auto-recover from GPU hangs |
| `amdgpu.noretry=0` | Retry enabled | Allow page fault retry (required for shared memory) |
| `amdgpu.dc=0` | Display disabled | Disable display controller (headless — prevents IRQ errors) |
| `amdgpu.lockup_timeout=120000` | 120 seconds | Time before declaring GPU hung (allows heavy compute) |
| `amdgpu.ppfeaturemask=0xfff73ef7` | Custom mask | Disable GFXOFF + DeepSleep + ULV (see below) |
### ppfeaturemask Calculation
```
Default value: 0xfff7bfff
BC-250 value: 0xfff73ef7
Bits disabled:
Bit 15 (0x8000) — PP_GFXOFF_MASK: GPU enters unrecoverable power-save
Bit 8 (0x0100) — PP_ULV_MASK: Ultra-low voltage may destabilize GPU
Bit 3 (0x0008) — PP_SCLK_DEEP_SLEEP_MASK: Deep clock sleep prevents GPU wake
```
---
## 7. Step 5 — Modprobe Configuration
Copy the provided config file:
```fish
sudo cp config/amdgpu.conf /etc/modprobe.d/amdgpu.conf
```
Or create manually — file `/etc/modprobe.d/amdgpu.conf`:
```
# AMD BC-250 (Cyan Skillfish / gfx1013) — ROCm Stability Parameters
# noretry=0 — Allow page fault retry (critical for shared memory / APU)
# gpu_recovery=1 — Enable GPU recovery on timeout
# sched_hw_submission=2 — Limit concurrent HW submissions (prevent queue overload)
# ppfeaturemask=0xfff73ef7 — Disable GFXOFF (bit 15), DeepSleep (bit 3), ULV (bit 8)
options amdgpu noretry=0 gpu_recovery=1 sched_hw_submission=2 ppfeaturemask=0xfff73ef7
```
---
## 8. Step 6 — Build Patched amdgpu Kernel Module
This is the most critical step. The BC-250 has a hardware/firmware bug where the KIQ (Kernel
Interface Queue) ring causes fatal GPU hangs. The v3 patch applies 8 surgical modifications
across 3 kernel source files to bypass KIQ and add dead-GPU detection.
### Why a Custom Module is Needed
The stock amdgpu driver routes TLB (Translation Lookaside Buffer) invalidation commands through
the KIQ ring. On the BC-250, this causes:
1. **KIQ fence timeouts** → GPU becomes unresponsive
2. **GFXOFF power-save** → GPU can't wake, CPU hangs on MMIO read (no PCIe timeout)
3. **System freeze** → No recovery possible, hard power-off required
The v3 patch has three protection layers:
- **Layer 1**: Disable GFXOFF for Cyan Skillfish (`gfx_v10_0.c`)
- **Layer 2**: KIQ bypass + dead-GPU detection (`gmc_v10_0.c`, `amdgpu_gmc.c`)
- **Layer 3**: Boot parameters disable GFXOFF/DeepSleep/ULV (Step 4)
### CRITICAL: Use CachyOS Kernel Source (Not Vanilla!)
**You MUST build from the CachyOS kernel source**, not vanilla kernel.org source. CachyOS patches
their kernel with struct layout changes that are incompatible with vanilla source headers. Building
from vanilla kernel source will produce a module that causes a **NULL pointer dereference** at boot
in `drm_vma_offset_add` during `gmc_v10_0_sw_init`.
### Build Process
#### Option A: Automated (Recommended)
The provided build script handles everything:
```fish
# Edit scripts/04_build_patched_module.sh and verify your kernel version first!
bash scripts/04_build_patched_module.sh
```
#### Option B: Manual Step-by-Step
##### 1. Identify Your Kernel Version
```fish
uname -r
# Example output: 6.19.6-2-cachyos
```
Note both the **kernel version** (e.g., `6.19.6`) and the **full string** (e.g., `6.19.6-2-cachyos`).
##### 2. Find the Matching CachyOS Source
Go to https://github.com/CachyOS/linux/releases and find the release matching your kernel.
For example, kernel `6.19.6-2-cachyos` → release `cachyos-6.19.6-1` or similar.
```fish
mkdir -p ~/kernel-build
cd ~/kernel-build
# Download (replace URL with your matching version)
curl -L -o cachyos-source.tar.gz \
"https://github.com/CachyOS/linux/archive/refs/tags/YOUR_TAG.tar.gz"
# Extract
tar xf cachyos-source.tar.gz
cd linux-* # or whatever the extracted directory is named
```
##### 3. Prepare Build Environment
```fish
set KVER (uname -r)
# Copy the running kernel's config and build files
cp /usr/lib/modules/$KVER/build/.config .
cp /usr/lib/modules/$KVER/build/Module.symvers .
# Copy localversion files (these set the kernel version string)
cp /usr/lib/modules/$KVER/build/localversion.* . 2>/dev/null
# Prepare the build system
make LLVM=1 olddefconfig
make LLVM=1 modules_prepare
```
> **Note**: `LLVM=1` is **mandatory** — CachyOS kernels are compiled with Clang, not GCC.
> Using GCC will produce an incompatible module.
##### 4. Apply the Patches
Copy the three patch scripts from this guide's `patches/` directory to the BC-250, then run them:
```fish
set AMDGPU_DIR (pwd)/drivers/gpu/drm/amd/amdgpu
python3 patches/patch1_gfxoff.py $AMDGPU_DIR
python3 patches/patch2_gmc.py $AMDGPU_DIR
python3 patches/patch3_amdgpu_gmc.py $AMDGPU_DIR
```
Verify the patches were applied:
```fish
grep -c "BC-250" $AMDGPU_DIR/gfx_v10_0.c # Should be ≥ 4
grep -c "BC-250" $AMDGPU_DIR/gmc_v10_0.c # Should be ≥ 14
grep -c "BC-250" $AMDGPU_DIR/amdgpu_gmc.c # Should be ≥ 9
```
##### 5. Build the Module
```fish
make LLVM=1 -j(nproc) M=drivers/gpu/drm/amd/amdgpu modules
```
This takes 3-10 minutes depending on CPU. The output should end with:
```
LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.ko
```
##### 6. Strip and Compress
```fish
# Strip debug symbols: ~600MB → ~30MB
strip --strip-debug drivers/gpu/drm/amd/amdgpu/amdgpu.ko
# Compress: ~30MB → ~4.5MB
zstd -19 -f drivers/gpu/drm/amd/amdgpu/amdgpu.ko
```
---
## 9. Step 7 — Install Module & Reboot
##### 1. Backup the Original Module
```fish
set KVER (uname -r)
set MODULE_DIR /usr/lib/modules/$KVER/kernel/drivers/gpu/drm/amd/amdgpu
sudo cp $MODULE_DIR/amdgpu.ko.zst $MODULE_DIR/amdgpu.ko.zst.original
```
##### 2. Install the Patched Module
```fish
sudo cp drivers/gpu/drm/amd/amdgpu/amdgpu.ko.zst $MODULE_DIR/amdgpu.ko.zst
sudo depmod -a
```
##### 3. Rebuild Initramfs
For Limine:
```fish
sudo limine-update
```
For GRUB/mkinitcpio:
```fish
sudo mkinitcpio -P
```
##### 4. Verify Before Reboot
```fish
# Check the installed module has all 9 BC-250 strings
zstd -d -c $MODULE_DIR/amdgpu.ko.zst | strings | grep "BC-250"
```
Expected output (9 strings):
```
BC-250: GFXOFF disabled to prevent GPU power-state hangs
BC-250: GPU unreachable (MMIO returned 0xFFFFFFFF)...
BC-250: GPU died during sem acquire (0xFFFFFFFF)
BC-250: GPU died during TLB flush ACK wait (0xFFFFFFFF)
BC-250: GPU unreachable in fw_reg_write_reg_wait...
BC-250: GPU died during reg_write_reg_wait (0xFFFFFFFF)
BC-250 KIQ bypass active
BC-250 KIQ bypass active in fw_reg_write_reg_wait
BC-250: MMIO reg write/wait timeout
```
##### 5. Reboot
```fish
sudo reboot
```
##### Emergency Rollback
If the system doesn't boot or the GPU crashes, restore the original module:
```fish
set KVER (uname -r)
set MODULE_DIR /usr/lib/modules/$KVER/kernel/drivers/gpu/drm/amd/amdgpu
sudo cp $MODULE_DIR/amdgpu.ko.zst.original $MODULE_DIR/amdgpu.ko.zst
sudo depmod -a
sudo limine-update # or: sudo mkinitcpio -P
sudo reboot
```
---
## 10. Step 8 — Post-Reboot Verification
After reboot, run the verification script:
```fish
bash scripts/06_verify_installation.sh
```
Or check manually:
### Check dmesg for v3 Module
```fish
sudo dmesg | grep -E "BC-250|GFXOFF|out-of-tree"
```
Expected:
```
amdgpu: loading out-of-tree module taints kernel.
amdgpu 0000:01:00.0: amdgpu: BC-250: GFXOFF disabled to prevent GPU power-state hangs
```
### Check for Errors
```fish
# KIQ timeout errors (should be 0)
sudo dmesg | grep -ci "timeout waiting for kiq fence"
# GPU unreachable events (should be 0)
sudo dmesg | grep -ci "GPU unreachable\|GPU died"
# NULL pointer / BUG (should be 0)
sudo dmesg | grep -ci "BUG\|NULL pointer"
```
### Check Device Nodes
```fish
ls /dev/dri/
# Expected: card0 renderD128 (and by-path/)
ls /dev/kfd
# Expected: /dev/kfd (character device)
```
### Check ppfeaturemask
```fish
cat /sys/module/amdgpu/parameters/ppfeaturemask
# Expected: 0xfff73ef7
```
### Check rocminfo
```fish
rocminfo | grep -E "Name:|Marketing|gfx|Done"
```
Expected output includes:
```
Name: gfx1010
Marketing Name: AMD BC-250
*** Done ***
```
---
## 11. Step 9 — HIP Compute Tests
Compile and run the provided HIP test programs:
### Compile Tests
```fish
cd tests/
hipcc --offload-arch=gfx1010 -o hip_probe hip_probe.cpp
hipcc --offload-arch=gfx1010 -o hip_minimal_test hip_minimal_test.cpp
hipcc --offload-arch=gfx1010 -o hip_vector_add hip_vector_add.cpp
```
### Run Tests (in order)
```fish
# Test 1: Device probe (no compute)
./hip_probe
# Test 2: Minimal kernel compute (32 values)
./hip_minimal_test
# Test 3: Full vector add with managed memory (65536 elements, sin²+cos²=1.0)
./hip_vector_add
```
### Sequential Stress Test
The critical test — on unpatched kernels, the **second** consecutive HIP run crashes the system:
```fish
for i in (seq 1 5)
echo "=== Round $i ==="
./hip_minimal_test
sleep 2
end
```
All 5 rounds should pass. If any round hangs or crashes, the module patch may not be applied
correctly.
You can also run the comprehensive test script:
```fish
bash scripts/07_run_hip_tests.sh
```
---
## 12. Cyan Skillfish Governor (GPU Clock Management)
The BC-250's GPU clock/voltage management is handled by the `cyan-skillfish-governor` service.
The kernel patches handle GFXOFF/power-state prevention; the governor handles DPM clock scaling.
### Installation
```fish
paru -S cyan-skillfish-governor
```
### Enable & Start
```fish
sudo systemctl enable --now cyan-skillfish-governor
```
### Verify
```fish
systemctl is-active cyan-skillfish-governor
# Expected: active
cat /sys/class/drm/card0/device/pp_dpm_sclk
# Expected: Shows clock levels with governor managing transitions
```
### Safe Operating Points
| Clock | Voltage | Use Case |
|-------|---------|----------|
| 1000 MHz | 700 mV | Idle |
| 1500 MHz | 900 mV | Light load |
| 2000 MHz | 1000 mV | Compute (max recommended) |
---
## 13. GPU Watchdog (Safety Monitor)
A safety watchdog script monitors kernel logs for KIQ timeouts and auto-kills GPU processes
before the timeout cascade crashes the system. The window to act is ~10 seconds after first timeout.
### Usage
```fish
# Monitor and auto-kill on KIQ timeout
bash scripts/gpu_watchdog.sh
# Monitor only (no kill)
bash scripts/gpu_watchdog.sh --dry-run
# Kill after 2 KIQ timeouts instead of 1
bash scripts/gpu_watchdog.sh --max-kiq 2
```
### Running as a Background Monitor
```fish
nohup bash scripts/gpu_watchdog.sh > /tmp/gpu_watchdog.log 2>&1 &
```
---
## 14. HIP Programming Guidelines for BC-250
### Memory Allocation
| Function | Safe? | Notes |
|----------|-------|-------|
| `hipMallocManaged()` | **YES** | Preferred — unified memory for APU |
| `hipHostMalloc()` | **YES** | Pinned host memory — safe |
| `hipHostMallocCoherent` | **YES** | Cache-coherent host memory |
| `hipMalloc()` | **CAUTION** | Works with v3 patches but may be slower |
| `hipMemcpy()` | **CAUTION** | Works with v3 patches |
### Critical Rules
1. **Never call `hipDeviceReset()`** — triggers KIQ queue teardown, crashes the system
2. **Use `_exit(0)` instead of `return 0`** in HIP programs — bypasses C++ static destructors
that trigger HIP runtime cleanup, which can cause KIQ fence timeouts
3. **Never call `rocm-smi` repeatedly** — GPU management queries can destabilize the device
4. **Run a single long-lived daemon** for GPU workloads when possible — each process startup/exit
cycles TLB flush paths
### Example: Safe HIP Program Exit
```cpp
#include <hip/hip_runtime.h>
#include <unistd.h> // _exit()
int main() {
// ... your HIP code ...
// CRITICAL: Use _exit() to avoid HIP runtime destructor crash
printf("Done\n");
fflush(stdout);
_exit(0); // Bypasses C++ destructors and HIP cleanup
}
```
---
## 15. Kernel Module Rebuild After Updates
**Any CachyOS kernel update will replace your patched module.** After updating the kernel,
you must rebuild and reinstall the patched module.
### Quick Rebuild Steps
```fish
set OLD_KVER "6.19.6-2-cachyos" # Previous kernel
set NEW_KVER (uname -r) # New kernel after update
# If kernel version changed, download new CachyOS source and repeat Step 6
# If only pkgrel changed (e.g., -2-cachyos → -3-cachyos), you may be able to
# just copy the module and rebuild initramfs:
set MODULE_DIR /usr/lib/modules/$NEW_KVER/kernel/drivers/gpu/drm/amd/amdgpu
sudo cp /usr/lib/modules/$OLD_KVER/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko.zst $MODULE_DIR/
sudo depmod -a
sudo limine-update
```
> **Note**: This copy approach only works if the kernel ABI hasn't changed between versions.
> If the module fails to load, you must do a full rebuild from the new kernel source.
---
## 16. Technical Reference — Why This GPU Needs Patches
### The KIQ Problem
KIQ (Kernel Interface Queue) is a privileged ring buffer used by the amdgpu driver for TLB
invalidation and GPU management. On the BC-250, KIQ commands cause **fence timeouts** — the GPU
never acknowledges the command, and the CPU waits indefinitely.
There are exactly **4 code paths** that use the KIQ ring at runtime:
| # | Function | File | Patched? |
|---|----------|------|----------|
| 1 | `gmc_v10_0_flush_gpu_tlb()` | gmc_v10_0.c | **YES** — goto use_mmio |
| 2 | `amdgpu_gmc_flush_gpu_tlb_pasid()` | amdgpu_gmc.c | **YES** — direct callout |
| 3 | `amdgpu_gmc_fw_reg_write_reg_wait()` | amdgpu_gmc.c | **YES** — MMIO write+poll |
| 4 | `amdgpu_gfx_enable/disable_kcq()` | amdgpu_gfx.c | No (boot only, works fine) |
### The GFXOFF Problem
After a HIP process exits, the GPU enters GFXOFF (a power-saving state). When the next process
starts and triggers a TLB flush, the GPU is unresponsive. MMIO reads via `readl()` inside a
spinlock-protected loop hang the CPU indefinitely because the BC-250's internal PCIe fabric has
**no completion timeout** (`DevCap2: Completion Timeout: Not Supported`).
### The v3 Three-Layer Solution
| Layer | Mechanism | Purpose |
|-------|-----------|---------|
| 1 — GFXOFF Disable | `gfx_v10_0.c`: `PP_GFXOFF_MASK` cleared for IP 10.1.3 | Prevents GPU from entering unrecoverable power-save |
| 2 — KIQ Bypass + Dead-GPU | `gmc_v10_0.c` + `amdgpu_gmc.c`: MMIO instead of KIQ, 0xFFFFFFFF checks | Avoids KIQ ring entirely; detects dead GPU before hanging |
| 3 — Boot Parameters | `ppfeaturemask=0xfff73ef7` | Belt-and-suspenders: disables GFXOFF+DeepSleep+ULV at power management level |
### Patch Summary (8 modifications across 3 files)
| # | File | Function | Type | Purpose |
|---|------|----------|------|---------|
| 1 | `gfx_v10_0.c` | `gfx_v10_0_check_gfxoff_flag` | v3 | Disable GFXOFF for IP 10.1.3 |
| 2 | `gmc_v10_0.c` | `gmc_v10_0_flush_gpu_tlb` | v2 | KIQ bypass → `goto use_mmio` |
| 3 | `gmc_v10_0.c` | `gmc_v10_0_flush_gpu_tlb` | v3 | Pre-spinlock 0xFFFFFFFF health check |
| 4 | `gmc_v10_0.c` | `gmc_v10_0_flush_gpu_tlb` | v3 | Sem acquire loop dead-GPU bail |
| 5 | `gmc_v10_0.c` | `gmc_v10_0_flush_gpu_tlb` | v3 | ACK-wait loop dead-GPU bail |
| 6 | `gmc_v10_0.c` | `gmc_v10_0_hw_init` | v2 | `flush_pasid_uses_kiq = false` |
| 7 | `amdgpu_gmc.c` | `amdgpu_gmc_flush_gpu_tlb_pasid` | v2 | Direct MMIO TLB flush |
| 8 | `amdgpu_gmc.c` | `amdgpu_gmc_fw_reg_write_reg_wait` | v2+v3 | MMIO write+poll + dead-GPU detection |
### Why Mining OS (Kernel 5.10) Worked Without Patches
In kernel 5.10 + AMDGPU-PRO 22.20, TLB flush was simpler and more localized. The centralized
`amdgpu_gmc_flush_gpu_tlb_pasid()` in `amdgpu_gmc.c` and the deferred work
`amdgpu_vm_tlb_fence_work()` didn't exist yet. KIQ failures returned `-ETIME` gracefully instead
of cascading to GPU death. Modern kernels (6.x) refactored TLB flushing into a shared centralized
path that defaults to KIQ for all hardware — which breaks BC-250.
---
## 17. Troubleshooting
### System freezes after HIP program runs
**Cause**: v3 module not loaded, or initramfs not rebuilt after installation.
**Fix**: Boot from recovery, restore original module, verify initramfs was rebuilt:
```fish
sudo cp /usr/lib/modules/(uname -r)/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko.zst.original \
/usr/lib/modules/(uname -r)/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko.zst
sudo depmod -a
sudo limine-update # MUST rebuild initramfs!
sudo reboot
```
### NULL pointer dereference at boot (drm_vma_offset_add)
**Cause**: Module was built from vanilla kernel.org source instead of CachyOS source.
**Fix**: Rebuild from CachyOS-specific kernel source (see Step 6).
### `rocminfo` shows no GPU / "No HSA GPU agents found"
**Cause**: Environment variables not set, or `/dev/kfd` doesn't exist.
**Fix**:
```fish
# Check env vars
echo $HSA_OVERRIDE_GFX_VERSION # Should be 10.1.0
# Check /dev/kfd exists
ls -la /dev/kfd
# Check user groups
groups # Should include 'render'
```
### "KIQ timeout" messages in dmesg
**Cause**: Stock (unpatched) module is loaded instead of v3.
**Fix**: Verify the v3 module is installed:
```fish
zstd -d -c /usr/lib/modules/(uname -r)/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko.zst \
| strings | grep "BC-250"
# Should show 9 BC-250 strings
```
### Module version mismatch after kernel update
**Cause**: CachyOS updated the kernel, replacing the patched module.
**Fix**: Rebuild the module from matching CachyOS source (see Section 15).
---
## 18. File Inventory
```
BC250_ROCm_Guide/
├── README.md ← This guide
├── config/
│ └── amdgpu.conf ← Modprobe configuration
├── patches/
│ ├── patch1_gfxoff.py ← Layer 1: Disable GFXOFF
│ ├── patch2_gmc.py ← Layer 2: KIQ bypass + dead-GPU (gmc_v10_0.c)
│ └── patch3_amdgpu_gmc.py ← Layer 2: KIQ bypass + dead-GPU (amdgpu_gmc.c)
├── scripts/
│ ├── 01_install_rocm_packages.sh ← Package installation
│ ├── 02_configure_environment.sh ← Environment variables + modprobe + boot params
│ ├── 04_build_patched_module.sh ← Download source, patch, build module
│ ├── 05_install_module.sh ← Install module + rebuild initramfs
│ ├── 06_verify_installation.sh ← Post-reboot verification
│ ├── 07_run_hip_tests.sh ← Compile and run HIP tests
│ └── gpu_watchdog.sh ← KIQ timeout safety monitor
└── tests/
├── hip_probe.cpp ← Device diagnostic (6 steps)
├── hip_minimal_test.cpp ← Minimal kernel compute test
└── hip_vector_add.cpp ← Full managed-memory vector add test
```
---
*Based on research and patches by Dani (2026-02-22), adapted and verified on CachyOS kernel
6.19.6-2-cachyos with ROCm 7.2.0.*