mirror of
https://github.com/duggasco/bc250-40cu-unlock.git
synced 2026-07-16 01:51:05 +00:00
Re-enable all 40 CUs on the AMD BC-250 (gfx1013 / Cyan Skillfish) via two register writes during amdgpu driver init: - CC_GC_SHADER_ARRAY_CONFIG: clears harvest enumeration mask - SPI_PG_ENABLE_STATIC_WGP_MASK: enables hardware wave dispatch to all WGPs Both required — neither alone is sufficient. Verified 1.61x compute scaling at 1500MHz (pp512: 230 → 372 tok/s) via controlled A/B/A testing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
156 lines
4.8 KiB
Markdown
156 lines
4.8 KiB
Markdown
# BC-250 40 CU Unlock
|
|
|
|
Re-enable all 40 CUs on the AMD BC-250 (gfx1013 / Cyan Skillfish / salvaged PS5 APU).
|
|
|
|
The BC-250 ships with 24 of 40 RDNA2 CUs active. This patch unlocks all 40 by writing two hardware registers during amdgpu driver init. No firmware mods, no permanent changes — just a kernel module parameter.
|
|
|
|
## Results
|
|
|
|
**pp512 (Vulkan LLM inference, Qwen3.5-9B Q4_K_XL):**
|
|
|
|
| Config | pp512 tok/s | Power | Temp | SCLK |
|
|
|--------|------------|-------|------|------|
|
|
| Stock 24 CU | 230 | 95W | 79C | 1500MHz |
|
|
| **40 CU unlocked** | **372** | **125W** | **83C** | **1500MHz** |
|
|
| **Ratio** | **1.61x** | +30W | +4C | same |
|
|
|
|
At 2 GHz (governor default): 302 → 466 tok/s = 1.54x, but hits 96C. 1500 MHz / 900 mV is the recommended sweet spot.
|
|
|
|
## How It Works
|
|
|
|
Two registers control CU availability — both must be modified:
|
|
|
|
| Register | What it does | Stock | Unlocked |
|
|
|----------|-------------|-------|----------|
|
|
| `CC_GC_SHADER_ARRAY_CONFIG` | Enumeration mask (tells driver how many CUs) | `0xfff80000` (24 CU) | `0xffe00000` (40 CU) |
|
|
| `SPI_PG_ENABLE_STATIC_WGP_MASK` | Dispatch gate (tells SPI where to send waves) | `0x7` (WGP 0-2) | `0x1F` (WGP 0-4) |
|
|
|
|
**Neither alone is sufficient.** CC alone changes what the driver reports but SPI still dispatches to 24 CUs. SPI alone enables hardware dispatch but the driver only generates work for 24 CUs.
|
|
|
|
The patch writes both during `gfx_v10_0_get_cu_info()`, guarded by `device == 0x13FE` (BC-250 only) and `bc250_cc_write_mode=3` (off by default).
|
|
|
|
## Quick Start
|
|
|
|
### Option 1: Build Script (any distro)
|
|
|
|
```bash
|
|
git clone https://github.com/duggasco/bc250-40cu-unlock.git
|
|
cd bc250-40cu-unlock
|
|
sudo ./scripts/bc250-enable-40cu.sh build
|
|
sudo ./scripts/bc250-enable-40cu.sh enable # reboots
|
|
```
|
|
|
|
Requirements: `gcc`, `make`, `zstd`, kernel headers (`linux-headers-$(uname -r)`)
|
|
|
|
### Option 2: Apply Patch Manually
|
|
|
|
```bash
|
|
# Get your kernel source
|
|
cd /path/to/linux-source/drivers/gpu/drm/amd/amdgpu/
|
|
|
|
# Apply
|
|
patch -p5 < /path/to/bc250-40cu-unlock/patch/bc250-40cu-amdgpu.patch
|
|
|
|
# Build just amdgpu
|
|
make -C /lib/modules/$(uname -r)/build M=$(pwd) -j$(nproc) modules
|
|
|
|
# Install
|
|
sudo cp amdgpu.ko.zst /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/amd/amdgpu/
|
|
sudo depmod -a
|
|
|
|
# Enable
|
|
echo 'options amdgpu bc250_cc_write_mode=3' | sudo tee /etc/modprobe.d/bc250-40cu.conf
|
|
sudo reboot
|
|
```
|
|
|
|
### Option 3: CachyOS / Arch
|
|
|
|
Apply `patch/bc250-40cu-amdgpu.patch` to your kernel PKGBUILD patch set, rebuild, add the modprobe config.
|
|
|
|
## Verification
|
|
|
|
After reboot:
|
|
|
|
```bash
|
|
# Check CU count
|
|
dmesg | grep active_cu_number
|
|
# Expected: active_cu_number 40
|
|
|
|
# Check register writes
|
|
dmesg | grep bc250-40cu
|
|
# Expected: bc250-40cu-enable: mode=3 se=0 sh=0 CC=0xfff80000->0xffe00000 SPI=0x00000007->0x0000001f
|
|
|
|
# Check RADV
|
|
RADV_DEBUG=info vulkaninfo --summary 2>&1 | grep num_cu
|
|
# Expected: num_cu = 40
|
|
```
|
|
|
|
## CU Harvest Map
|
|
|
|
Check your board's stock CU layout (run without the patch):
|
|
|
|
```bash
|
|
./scripts/cu_map.sh
|
|
```
|
|
|
|
Our boards show contiguous harvesting:
|
|
```
|
|
SE0 SH0: ■■■■■■□□□□
|
|
SE0 SH1: ■■■■■■□□□□
|
|
SE1 SH0: ■■■■■■□□□□
|
|
SE1 SH1: ■■■■■■□□□□
|
|
24/40 CUs active, 16 harvested
|
|
```
|
|
|
|
We're collecting maps from across the fleet to find out if all BC-250s share this pattern.
|
|
|
|
## Governor / Thermal
|
|
|
|
40 CU at 2 GHz draws ~181W and hits 96C. Recommended: cap at 1500 MHz / 900 mV via `cyan-skillfish-governor`:
|
|
|
|
```toml
|
|
# /etc/cyan-skillfish-governor/config.toml
|
|
[[safe-points]]
|
|
frequency = 350
|
|
voltage = 700
|
|
|
|
[[safe-points]]
|
|
frequency = 1500
|
|
voltage = 900
|
|
```
|
|
|
|
## Disabling
|
|
|
|
```bash
|
|
sudo ./scripts/bc250-enable-40cu.sh disable # removes config, reboots to 24 CU
|
|
sudo ./scripts/bc250-enable-40cu.sh restore # restores original amdgpu module
|
|
```
|
|
|
|
## Technical Details
|
|
|
|
See [docs/technical-report.md](docs/technical-report.md) for the full writeup including:
|
|
- 4-state A/B test proving both registers are needed
|
|
- Register map (UMR dumps)
|
|
- Architecture analysis (CC vs SPI vs RLC vs SMU)
|
|
- Why `ignore_cu_harvest` doesn't work
|
|
- Power/thermal characterization
|
|
|
|
## Safety
|
|
|
|
- Default off (`bc250_cc_write_mode=0`) — does nothing unless explicitly enabled
|
|
- Guarded by PCI device ID `0x13FE` — only fires on BC-250
|
|
- No permanent hardware changes — reboot without the config returns to stock 24 CU
|
|
- The harvested CUs have power, clocks, and matching CGTS config — they were disabled by firmware policy, not silicon defects (RLC_PG_CNTL = 0, no power gating active)
|
|
|
|
## Credits
|
|
|
|
- **duggasco** — research, testing, documentation
|
|
- **filippor** — independent testing, `ignore_cu_harvest` kernel patch, cyan-skillfish-governor
|
|
- **Claude** — analysis, tooling, SPI register discovery
|
|
- **Codex** — identified SPI_PG_ENABLE_STATIC_WGP_MASK architecture
|
|
- **BC-250 Discord** — thermal/voltage guidance, fleet testing
|
|
|
|
## License
|
|
|
|
GPL-2.0 (same as the Linux kernel)
|