# Bc250 Ultimate Setup

> Set up, tune, and stabilize Linux on an AMD BC-250 board (Cyan Skillfish, the cut-down PS5 APU, PCI 0x13fe / gfx1013). Installs the GPU governor that unpins the 1500 MHz lock, enables CPU C-states and P-states, raises the dynamic VRAM ceiling, and replaces ZRAM with zswap. Use when a user mentions BC250/BC-250, Cyan Skillfish, gfx1013, cyan-skillfish-governor, or reports that such a board stutters, crashes, or sits at a locked 1500 MHz.

- Skill: `silkyland/bc250-ultimate-setup` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add silkyland/bc250-ultimate-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/silkyland/bc250-ultimate-setup/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: CC-BY-SA-4.0
- Author: silkyland (https://skillmd.com/u/silkyland)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/silkyland/bc250-ultimate-setup

---


# BC-250 Ultimate Setup

Bring an AMD BC-250 board from a fresh Linux install to a stable, tuned system.

The BC-250 is an ex-crypto-mining board built around AMD's "Cyan Skillfish" APU:
6× Zen 2 cores, 24 RDNA2 CUs (`gfx1013`), and **16 GB of GDDR6 shared between
CPU and GPU**. It runs Linux only. Out of the box it is unstable in specific,
predictable ways — every one of them has a known fix.

## Mental model — the six things that make this board different

1. **No GPU governor exists by default**, so the GPU is pinned at 1500 MHz and
   idles around 105 W. Adding one is the single highest-impact change.
2. **No CPU C-states or P-states** are exposed by stock firmware. Idle power
   stays high and the CPU never scales. A community ACPI override fixes it.
3. **Unified memory.** The "VRAM split" is a *minimum* carve-out; the dynamic
   ceiling needs a kernel parameter, and there are two distinct crash modes.
4. **IOMMU is broken.** It must be disabled in BIOS or the board crashes.
5. **The GPU is usually `card1`, not `card0`.** Never hardcode a card index or
   a `/sys/class/drm/card0` path. Find it by PCI device id `0x13fe`.
6. **A GPU crash is a system crash.** CPU and GPU share one die — there is no
   isolating reset. Stability work is therefore about *avoiding* crashes:
   kernel version, voltage curve, and thermals.

## Non-negotiables

- Never enable IOMMU in BIOS.
- Never set the GPU minimum voltage below **700 mV** — it locks the GPU at
  1500 MHz and silently defeats the governor.
- Never use `Smokeless_UMAF` — it has bricked boards.
- Avoid kernels **6.15.0–6.15.6** and **6.17.8–6.17.10** (GPU init fails).
- Clear CMOS after every BIOS flash, and keep a fallback boot entry.
- Never change RAM timings without a hardware flasher available.

## Workflow

Always run detection first; never assume the machine's state.

```
detect → stage 1 → verify → stage 2 (reboot) → verify → optional tuning
```

### 0. Detect (always, read-only, no root)

```bash
bash scripts/detect.sh          # or --json for machine-readable output
```

It reports distro, bootloader, initramfs, kernel, Mesa, the real GPU card
index, VRAM split, C/P-states, swap/ZRAM/zswap, governor and sensor status,
then prints the next steps that apply. **Decide from this output, not from
assumptions.**

Decision rules:

- `kernel_broken: true` → stop, get off that kernel before anything else.
- `bootloader`/`initramfs` determine which `stage2-boot.sh` branch runs. If
  either is `unknown`, do not run stage 2 — read `references/distro-notes.md`
  and apply the boot changes by hand.
- `gpu_governor_running: false` → stage 1 is required.
- `zram_active: true` or `ttm_pages_limit` unset → stage 2 is worth doing.

### 1. Core must-haves (no reboot)

```bash
sudo bash scripts/stage1-core.sh --dry-run    # preview
sudo bash scripts/stage1-core.sh              # apply
```

Installs monitoring tooling, loads the NCT6686D board sensors (`nct6683`,
read-only), and installs + enables `cyan-skillfish-governor-smu` with an
annotated conservative config. Idempotent; an existing governor config is
backed up, never overwritten.

Do **not** use the project's own `install.sh`: the release tarball omits the
files it tries to copy. The script installs the binary and writes the unit.

### 2. Verify stage 1

```bash
bash scripts/verify.sh
```

The GPU clock should read 1000 MHz at idle and rise above 1500 MHz under load.
If it stays at 1500, see `references/troubleshooting.md`. Note that a *light*
workload legitimately stays at 1000 MHz — the default load target only ramps
above 65 % GPU busy.

### 3. Boot-affecting changes (reboot required)

```bash
sudo bash scripts/stage2-boot.sh              # PREVIEW ONLY (default, safe)
sudo bash scripts/stage2-boot.sh --yes        # apply
```

Because this edits the bootloader, the default is a no-op preview. It:

- installs the ACPI override (`SSDT-CST` = C-states, `SSDT-PST` = P-states,
  800–3200 MHz) using whichever mechanism the detected initramfs needs;
- adds `ttm.pages_limit` (≈12 GB dynamic VRAM) and zswap parameters to the
  kernel cmdline via the detected bootloader;
- optionally replaces ZRAM with zswap(lz4) over a 16 GB swapfile — the swapfile
  is created and activated *before* ZRAM is disabled, so you are never left
  without swap;
- backs every file it touches up to `/root/bc250-backup-<timestamp>/`.

Useful overrides:

```bash
ENABLE_ZSWAP=0 sudo bash scripts/stage2-boot.sh --yes    # leave swap alone
TTM_PAGES=3145728 sudo bash scripts/stage2-boot.sh --yes # different VRAM cap
```

Then **reboot**, and if it does not come up pick the fallback / LTS entry in
the boot menu.

### 4. Verify stage 2, and keep verifying

```bash
bash scripts/verify.sh        # exits non-zero if a hard requirement failed
```

Expect: C-states on every CPU, P-states 800 MHz–3.2 GHz, `zswap` enabled, no
ZRAM swap device, GPU governor running, and `nct6686` sensors visible.

## Optional tuning (only after the baseline is stable)

- GPU ceiling — the default caps at 1850 MHz. To go higher, edit
  `[frequency-range] max` and add `[[safe-points]]`, then test 30+ minutes per
  step. Read `references/governor-tuning.md` first; the method (freeze → find
  voltage floor → widen) matters more than the numbers.
- Fan curves — needs the out-of-tree `nct6687` driver plus CoolerControl;
  `references/cooling-and-power.md`.
- 40 CU unlock / 8-core unlock / CPU OC — real gains, real risk. The 8-core
  unlock **requires** swapping to the 16-thread ACPI tables. See
  `references/kernel-matrix.md`.

## Worked example (real numbers)

Reference run on CachyOS, kernel 7.2.4, limine, btrfs, stock cooling:

| | before | after stage 1 | after stage 2 |
|---|---|---|---|
| GPU @ idle | 1500 MHz pinned | 1000 MHz @ 799 mV, ~40 W | same |
| GPU @ load | 1500 MHz | 1850 MHz, 80–86 W, 61–64 °C | same |
| CPU | no cpufreq at all | no cpufreq | idle 0.93 GHz ↔ load 3.49 GHz |
| swap | ZRAM 14.8 GB | ZRAM 14.8 GB | zswap(lz4) + 16 GB swapfile |
| `dmesg` resets/panics | — | 0 | 0 |

The ACPI override shows up at boot as
`ACPI: Table Upgrade: install [SSDT- HACK- P_CST3]` / `[SSDT- HACK- PSTATES]`.

## Troubleshooting

Symptom → cause → fix lives in `references/troubleshooting.md`. The highest
yield checks are always: kernel version, IOMMU, and whether CMOS was cleared.

## Where the detail lives

| Read this | When |
|---|---|
| `references/kernel-matrix.md` | kernel choice, pinning, the optional unlocks |
| `references/bios-and-vram.md` | BIOS musts, VRAM split, the two crash modes, `ttm.pages_limit` |
| `references/governor-tuning.md` | governor options, config schema, voltage-curve method, hard limits |
| `references/cooling-and-power.md` | PSU, temps, fans, sensors, CoolerControl |
| `references/troubleshooting.md` | anything is broken |
| `references/distro-notes.md` | non-Arch distros, what is tested vs documented |
| `references/credits.md` | upstream projects and community links |
| `assets/governor-smu-config.toml` | annotated starting config |

## Safety

These scripts change the boot configuration. `stage2-boot.sh` is preview-first
for that reason, backs up before writing, and prints its rollback steps. Review
what it will do (`--dry-run`) before applying, and keep a bootable fallback
entry. Numbers in the references are community defaults, not guarantees —
silicon varies per board.

