chore: moved the newly added article to the correct directory and removed the draft parameter
Build and Publish / build (push) Successful in 1m38s

This commit is contained in:
2026-11-08 16:01:25 +01:00
parent e693645bb9
commit 44a3f6ae5f
19 changed files with 2 additions and 6 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 893 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 959 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 KiB

@@ -1,532 +0,0 @@
+++
title = "BC-Zero - Testing della scheda"
summary = "Da vecchia scheda da mining a console e server AI"
date = "2038-01-19"
tags = ["BC-250", "PS5", "Sblocco", "BIOS", "CPU", "GPU"]
categories = ["Progetti"]
series = ["BC-Zero"]
series_order = 1
draft = true
+++
Il 5 febbraio [Soffio](https://t.me/Soffioo), amico e socio
[LUGMan](https://lugman.org/), mi ha fatto scoprire una scheda particolare: la
**BC-250**.
La BC-250 è una scheda proveniente da un [rig per il mining di criptovalute di
ASRock](https://www.tomshardware.com/news/twelve-ps5-apus-power-asrocks-new-cryptomining-rig),
che ne ospitava dodici.
Dentro ognuna di queste schede c'è un chip *binned* derivato dall'APU AMD della
PlayStation 5, con 6 degli 8 core CPU e 24 delle 36 CU GPU attivi, insieme a
16GB di RAM GDDR6 **unificati** tra CPU e GPU, uno slot M.2 (PCIe 2.0x2 o SATA
III) e poche porte: due USB 2.0, due USB 3.0, una Ethernet Gigabit e una
DisplayPort. L'alimentazione è fornita da un connettore PCIe a 8 pin.
All'inizio non ero proprio convinto, soprattutto nel vedere un terzo delle CU
tagliate via così e nel sapere che è una scheda con un chip custom, parzialmente
bloccato (oltre ai core bloccati, alcune funzionalità come l'enconding/decoding
video non sono presenti), derivante dal mining e senza alcun tipo di supporto o
community dietro. Ma il prezzo era decisamente interessante, e a quanto pare
questa scheda ha una community molto attiva che si impegna per tirarne fuori il
100% del potenziale su Linux.
![Soffio: "Oh se vuoi te ne do una, perché l'avevo presa senza coupon e avevo
intenzione di rivenderla😂" "Quindi tecnicamente me ne arrivano due😂" Io: "Ma
no tranqui" "Non saprei che farmene"](images/01-not-fully-convinced.png "Io non
pienamente convinto")
Le cose cambiano però quando la mattina del 30 maggio ricevo questo messaggio:
![Soffio: "Sono riusciti a sbloccare tutte le CU, passato da 24 a 40. Adesso
stanno guardando per sbloccare gli 8
core😂🌚👌"](images/02-40cu-unlocked-news.png)
E sempre il caro Soffio mi fa presente che da li a breve sarebbero iniziati i
super sconti AliExpress. Incuriosito dalla faccenda gli chiedo se può prestarmi
la sua scheda per un po' di giorni, giusto per provarla e vedere cosa si può
fare.
E *oh boy* se questa scheda mi ha convinto.
## Step 0: Preparazione
Una pecca della BC-250 è che non è proprio *plug-and-play*. Bisogna come minimo:
1. Trovare un alimentatore in grado di fornire ***realmente*** almeno 300W sul
rail +12V e con dei cavi che sappiano gestire tutti quegli ampere;
2. Avere un monitor con DisplayPort (o comprare un adattatore);
3. Trovare un modo per raffreddare la maledetta;
4. Flashare il BIOS.
Il mio setup di prova era:
1. Il primo alimentatore marchiato "*el cheapo*" che ho trovato sottomano (che
"sicuramente andrà bene, c'è scritto 500W");
2. Adattatore passivo DP ➜ HDMI;
3. Climatizzatore portatile per il raffreddamento (era estate e iniziava a fare
caldo);
4. Programmatore SPI CH341 (che avevo già).
![Setup casalingo](images/03-initial-setup.png "Se guardate attentamente, il
bridge PS_ON ➜ GND è stato fatto con un cavetto e tutta la potenza passa per un
convertitore SATA ➜ PCIe. Non fatelo a casa")
Non proprio il setup migliore per testare la scheda, ma si lavora con quello che
si ha.
## Step 1: Flashare il BIOS
Il [primo punto sulla documentazione della
community](https://elektricm.github.io/amd-bc250-docs/getting-started/quick-start/#step-1-bios-flash-critical)
è il flashing del BIOS. Senza un BIOS custom non si hanno funzionalità
essenziali come l'allocazione dinamica della VRAM (voglio ricordare che i 16GB
di RAM sono condivisi) e una corretta gestione delle ventole.
All'inizio ho installato quello consigliato dalla guida, quello di
[TuxThePenguin0](https://gitlab.com/TuxThePenguin0/bc250-bios), ma più avanti ho
scoperto un altro BIOS, quello di [Forbidden
Darkness](https://github.com/Forbidden-Darkness/AMD-BC-250-UEFI-v2.2-Firmware-Menu-Script)
che, oltre allo sblocco del menù per l'allocazione dinamica offre una selezioni
di immagini di splash custom e, soprattutto, **lo sblocco di tutti gli 8 core
CPU**.
"*Ma come, non erano bloccati?*" A quanto pare non abbastanza.
L'APU ha tutti i core presenti sul silicio, sono solo disattivati via firmware.
Un principio simile vale anche per le CU della GPU, ma lo vedremo dopo.
---
L'installazione è anche più semplice e non richiede un flasher BIOS: basta
copiare i file contenuti nell'archivio `.7z` delle release in una chiavetta
formattata in FAT32 e farci il boot. L'installer chiede che splash image
vogliamo (la
[`07`](https://github.com/user-attachments/assets/ca23ce6c-08ab-4293-9a70-0e55f66dc93c)
è la migliore *imho*) e procede a flashare.
![Flashing del BIOS](images/04-bios-flashing.png "Flashing del BIOS")
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557"
textColor="#1d3557" >}}
Il flashing del BIOS è un operazione pericolosa. Assicuratevi che la scheda non
si spenga nel mentre.
{{< /alert >}}
Una volta terminato il flashing bisogna resettare tutte le impostazioni del
BIOS. Per farlo basta staccare l'alimentazione e bridgare i pin 2 e 3
dell'header `CLRCMOS1` per qualche secondo. Una volta fatto possiamo
ripristinare l'header sui pin 1 e 2, ricollegare l'alimentazione ed entrando nel
BIOS premendo `Canc` all'avvio vedremo molte più opzioni.
![Nuovo logo al boot](images/05-new-boot-logo.png "Nuovo logo al boot")
![Nuove entry nel menù "Advanced"](images/06-new-advanced-menu.png "Nuove entry
nel menù \"Advanced\"")
Per prima cosa facciamo in modo che l'allocazione di VRAM sia automatica. Per
farlo dobbiamo andare nella sezione `Chipset` > `GFX Configuration` > `GFX
Configuration` e impostare `Integrated Graphics Controller` a `Forces`, poi `UMA
Mode` a `UMA_SPECIFIED` e infine `UMA Frame buffer size` a `512M`.
![La configurazione corretta per l'UMA](images/07-uma-512m.png "La
configurazione corretta per l'UMA")
Poi in `NB Configuration` disabilitiamo l'IOMMU (su questa scheda sembra non
essere funzionante)
Infine abilitiamo tutti i core andando nella sezione `Advanced` > `MeiMeiDXEv3
Menu` e abilitando tutto.
![La configurazione per l'attivazione degli 8 core](images/08-8-core-unlock.png
"La configurazione per l'attivazione degli 8 core")
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557"
textColor="#1d3557" >}}
Nulla garantisce che i tutti core siano funzionanti. Core danneggiati potrebbero
causare crash improvvisi.
Per evitare ciò faremo uno stress-test su tutti i core e controlleremo che nei
log del kernel non appaia nessun `Machine Check Exception` prima di abilitare
questa impostazione in produzione
{{< /alert >}}
Una volta che abbiamo configurato correttamente il BIOS siamo pronti per
installare un sistema operativo e testare per bene questa scheda.
## Step 2: Installazione di un OS di prova
Per fare un po' di stress testing CPU e per fare dei test con la GPU installerò
Arch Linux.
Non sarà la distro finale che andrò ad installare, ma la scelta non è casuale:
lo sviluppo di questa scheda è bleeding-edge e per ora quasi tutti gli script
assumono che sia installato Arch o Fedora per avere le ultime versioni dei
pacchetti.
![La configurazione di archinstall che userò](images/09-archinstall.png "La
configurazione di archinstall che userò")
![Il sistema installato](images/10-fastfetch.png "Il sistema installato. Come
vedete si possono già vedere i 16 thread")
### Test degli 8 core
Per prima cosa testiamo se tutti gli 8 core funzionano come dovrebbero. Per
farlo installiamo il pacchetto `stress-ng` e facciamo uno stress test:
```sh
stress-ng --cpu 16 --cpu-method all --verify --timeout 2h --metrics
```
Verifichiamo poi che non ci siano stati errori con:
```sh
sudo dmesg | grep -iE "mce|machine check|hardware error"
```
Se il kernel non segnala alcun errore siamo appena passati da 6 a 8 core
gratuitamente. In caso di errore invece è possibile modificare quali core
attivare e quali no dal BIOS.
### Stress-testing della GPU
Facciamo poi uno stress testing della GPU per avere una baseline delle
performance prima di installare il governor o abilitare tutte le CU. Per farlo
ho installato Furmark e ho fatto il test 1080p
![Furmark (68 FPS)](images/11-baseline-furmark.png)
Direi che 70 FPS non sono *così* male per la scheda *out-of-the-box*, ma si può
sicuramente fare di meglio, molto meglio.
---
Piccola nota che mi sento di aggiungere: se durante lo stess test lo schermo
diventa nero e la scheda non risponde in alcun modo, controllate
l'alimentazione. Il piccolo *foreshadowing* che ho fatto nello step 0 riguardo
all'alimentatore riguarda il fatto che durante i miei test ho fatto girare
Ollama e ho completamente bruciato la power supply dato che (a quanto pare) non
riusciva a gestire davvero tutto il carico sul rail +12V. Ho successivamente
comprato su AliExpress, insieme alla scheda, il PSU consigliato dalla community,
il [Metalfish 500W
FlexATX](https://elektricm.github.io/amd-bc250-docs/hardware/power#option-2-flexatx-psu-500w)
e da li non ho più avuto problemi.
![PSU deceduta](images/12-dead-psu.jpg "Riposa in pace, soldato 🫡")
### Installazione del Governor GPU
Di default la GPU gira sempre a 1500MHz: un governor permette di alzare il clock
quando la GPU è sotto carico e di abbassarlo quando non lo è per consumare meno.
Installeremo `cyan-skillfish-governor-smu`, progetto della community che
comunica direttamente con la System Management Unit della scheda. È anche già
pacchettizzato nella AUR, quindi per installarlo basta lanciare un:
```sh
paru -S cyan-skillfish-governor-smu
systemctl enable --now cyan-skillfish-governor-smu
```
Possiamo contollare che funzioni con:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk # Se non funziona prova con card0
0: 1000Mhz *
1: 1500Mhz
2: 2000Mhz
```
La prima e l'ultima riga sono rispettivamente la frequenza minima e massima
della GPU, mentre il valore centrale è variabile. L'asterisco indica la
frequenza attualmente in uso. Un esempio sotto sforzo:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz
1: 1850Mhz *
2: 2000Mhz
```
Dovremmo vedere che la GPU usa automaticamente una frequenza più alta sotto
sforzo e più bassa a riposo.
---
**Piccola nota**: lo sblocco degli 8 core influisce sulla lettura dei valori
dell'SMU. È un problema noto ed andremo a risolverlo più avanti, quando ci
preoccuperemo del sistema operativo. Senza alcun fix i valori di frequenza
risultano sbagliati, ad esempio:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz *
1: 4575Mhz
2: 2000Mhz
# Per un chip che può andare al massimo a 2230MHz non è male come overclock
```
Detto ciò facciamo uno stress test adesso, con il governor installato.
![Furmark (83 FPS)](images/13-furmark-governor.png)
Adesso che riusciamo a scalare fino a 1850MHz la nostra GPU riesce ad arrivare a
83 FPS in 1080p, niente male!
1850MHz non è assolutamente il massimo che questo chip può gestire, ma per
adesso ci accontenteremo di questo. Per i più curiosi la curva delle frequenze e
delle tensioni è completamente personalizzabile e si trova in
`/etc/cyan-skillfish-governor-smu/config.toml`. Con un po' di prove si può
spingere al massimo l'hardware minimizzando i consumi, ma lo faremo sempre
quando andremo a configurare il sistema operativo definitivo.
### Sblocco delle 40 CU
Come abbiamo detto all'inizio questa scheda presenta al kernel solamente 24 CU,
nonostante nella PS5 ce ne siano 36 e sul silicio ce ne siano effettivamente 40.
Possiamo verificarlo con:
```
$ sudo dmesg | grep active_cu_number
[ 6.882856] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
```
Per testare e successivamente sbloccare tutte le CU useremo il [repository di
duggasco](https://github.com/duggasco/bc250-40cu-unlock). Il meccanismo è simile
a quello dello sblocco dei core: anche qui basta cambiare qualche valore, perché
le CU non sono bloccate a livello hardware, ma solo disattivate dal firmware.
A decidere quante CU sono attive sono due registri della GPU. Quello che fa
questo script è patchare il driver `amdgpu` e scrivere i valori giusti nei
registri mentre il driver si avvia, avviando le CU spente.
```
$ git clone https://github.com/duggasco/bc250-40cu-unlock.git
$ cd bc250-40cu-unlock/
$ sudo pacman -S linux-headers vulkan-headers
$ sudo scripts/bc250-enable-40cu-arch.sh build
# Attendi la ricompilazione del modulo `amdgpu`
$ sudo scripts/bc250-enable-40cu-arch.sh enable
```
Una volta che la BC-250 si sarà riavviata possiamo verificare che la patch ha
funzionato usando sempre il comando di prima:
```
$ sudo dmesg | grep active_cu_number
[ 8.004012] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
```
A quanto pare il modulo custom non viene caricato in automatico dallo script.
Non è un problema: rigeneriamo l'initramfs e riavviamo a mano:
```
$ sudo mkinitcpio -P
$ reboot
# Una volta che si è riavviato
$ sudo dmesg | grep active_cu_number
[ 8.058999] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 40
```
Molto meglio!
---
Una volta installato il modulo custom possiamo procedere con il testing delle
CU:
```
$ sudo scripts/bc250-cu-health-test.sh start
```
Durante il test il PC si riavvierà automaticamente una ventina di volte. Una
volta che il PC smette di riavviarsi in automatico possiamo vedere i risultati
del test con:
```
$ scripts/cu_map.sh
BC-250 CU Map + Health
SE0 SH0: ■■■■■■■■■■
SE0 SH1: ■■■■■■■■■■
SE1 SH0: ■■■■■■■■■■
SE1 SH1: ■■■■■■■■■■
40/40 CUs active, 0 harvested
BC-250 CU Map + Health
SE0 SH0: ■■■■■■✓✓✓✓
SE0 SH1: ■■■■■■✓✓✓✓
SE1 SH0: ■■■■■■✓✓✓✓
SE1 SH1: ■■■■■■✓✓✓✓
40/40 CUs usable (0 defective, masked)
```
A quanto pare ho vinto la lotteria del silicio e ho 8 core e 40 CU funzionanti.
Urrà! 🎉
In caso però ci fossero state delle CU difettose avrei potuto mascherarle usando
lo script `bc250-cu-mask.sh`.
---
Facendo l'ultimo stress test con Furmark:
![Furmark (128 FPS)](images/14-furmark-40cu.png)
Siamo passati dalla scheda nuda e cruda, senza alcun software aggiuntivo, che
girava mediamente a 70 FPS ad avere un governor e tutte le CU sbloccate per
avere dei picchi da 138 FPS, il doppio!
Ovviamente questo approccio per lo sblocco delle 40 CU ha un problema abbastanza
evidente soprattutto su distribuzioni rolling come Arch: bisogna ricordarsi di
ricompilare il modulo ogni volta che si aggiorna il kernel. Anche questo è un
problema che risolveremo più avanti, quando smetteremo di usare un OS di prova,
ma se dopo un aggiornamento la GPU non va più veloce quanto prima forse è meglio
buttarci un occhio.
### Sensori e altre configurazioni indispensabili
Una volta sistemate le cose essenziali come CPU e GPU rimangono alcune piccole
accortezze, come ad esempio la gestione dei sensori, delle ventole, la swap, lo
split della VRAM, ecc...
Potrei starne per ore a parlarne, ma rimando alla [documentazione della
community](https://elektricm.github.io/amd-bc250-docs/), che è ben fornita.
Quello che mi sento di fare adesso è far notare una cosa: usando il comando
`sensors` abbiamo pochi dati OOTB:
```
$ sensors
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +39.0°C
PPT: 41.41 W (avg = 40.85 W)
sclk: 1000 MHz
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +41.6°C
```
Per avere più dati abbiamo bisogno del modulo `nct6683` (read-only) o `nct6687`
(si possono creare curve custom, ma è *out of tree*). Dato che `nct6683` è già
disponibile possiamo abilitarlo con:
```
$ echo 'options nct6683 force=true' | sudo tee /etc/modprobe.d/sensors.conf
$ echo 'nct6683' | sudo tee /etc/modules-load.d/99-sensors.conf
$ sudo mkinitcpio -P
$ reboot
```
Dopo aver riavviato vedremo molti più dati:
```
$ sensors
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +46.9°C
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +41.0°C
PPT: 42.61 W (avg = 40.75 W)
sclk: 1000 MHz
nct6686-isa-0a20
Adapter: ISA adapter
VIN0: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN1: 1.01 V (min = +0.00 V, max = +0.00 V)
VIN2: 992.00 mV (min = +0.00 V, max = +0.00 V)
VIN6: 1.39 V (min = +0.00 V, max = +0.00 V)
VIN7: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN16: 896.00 mV (min = +0.00 V, max = +0.00 V)
fan1: 0 RPM (min = 0 RPM)
fan2: 1709 RPM (min = 0 RPM)
fan3: 0 RPM (min = 0 RPM)
fan4: 0 RPM (min = 0 RPM)
fan5: 0 RPM (min = 0 RPM)
AMD TSI Addr 98h: +47.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = AMD AMDSI
Thermistor 14: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
Thermistor 15: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
pwm1: 64%
pwm2: 64%
pwm3: 64%
pwm4: 64%
pwm5: 64%
intrusion0: OK
beep_enable: disabled
```
## Step 3: Modifiche hardware
Vorrei ricordare che per tutti questi test stavo utilizzando la BC-250 di
Soffio, giusto per vedere se mi potesse interessare. E dato che ormai ero
abbastanza preso, decido di prendermi tutto l'occorrente da AliExpress.
Per fortuna con i saldi e anche grazie a TopCashback riesco a portarmi a casa
tutto il necessario per meno di 200€. Compro poi un paio di Arctic P12 Pro da
Amazon.
In data 24 giugno mi arriva il tutto, e quindi ci si mette all'opera per fare:
* Cambio pasta e pad termici;
* Installazione dei dissipatori sul pannello posteriore, in modo da raffreddare
le GDDR6;
* Rimozione della linguetta metallica e dell'I/O shield (servono solo se la
scheda viene montata nel rig);
* Rifare la suite di test sopracitati per vedere se avevo vinto la lotteria del
silicio per la seconda volta (per fortuna sì);
* Modifica del dissipatore.
La modifica del dissipatore mi permette di risolvere uno dei problemi che stavo
avendo con la scheda, ovvero: come rimuovo 200W di calore? Per adesso avevo il
pinguino, ma non potevo continuare ad usare una pompa di calore per raffreddare
una singola scheda.
Quando sono nel rig da mining, le BC-250 hanno tutti il dissipatore disposto
longitudinalmente, quindi basta un array di ventole per raffreddare tutte e 12
le schede contemporaneamente. Se si vuole usare una di queste schede
indipendentemente bisogna diventare un po' più creativi per rimuovere il calore.
La soluzione più comune nella community è la [heatsink
mod](https://reddit.com/r/BC250Gaming/comments/1rjc3io/), che consiste di aprire
letteralmente il dissipatore nella sezione sopra l'APU per avere un posto dove
mettere la ventola.
È un operazione un po' lunga e tediosa, ma nulla di impossibile. È anche un
compito abbastanza ripetitivo, quindi una volta che si è presa la mano finisce
presto. Alla fine mi ci è voluta solo una forbice, buona musica e un'ora del mio
tempo.
![Prima della modifica al dissipatore](images/15-before-heatsink-mod.jpg "La
BC-250 appena rimossa dalla confezione, senza linguetta metallica e I/O shield")
![Dopo la modifica al dissipatore](images/16-after-heatsink-mod.jpg
"Il dissipatore dopo la modifica")
È un lavoro un po' *rough around the edges* (*literally*), ma funziona. E il
foro è grande esattamente quando una ventola da 120mm, quindi una delle due
ventole porta soffiare direttamente sopra all'APU.
---
Dato che questo articolo si è fatto abbastanza lungo mi sento di spezzettarlo in
più parti. Nella prossima andremo a progettare un case custom per il mio use
case.
@@ -1,525 +0,0 @@
+++
title = "BC-Zero - Board Testing"
summary = "From an old mining board to a console and AI server"
date = "2038-01-19"
tags = ["BC-250", "PS5", "Unlock", "BIOS", "CPU", "GPU"]
categories = ["Projects"]
series = ["BC-Zero"]
series_order = 1
draft = true
+++
On February 5th, [Soffio](https://t.me/Soffioo), a friend and fellow
[LUGMan](https://lugman.org/) member, made me discover a peculiar board: the
**BC-250**.
The BC-250 is a board that comes from an [ASRock cryptocurrency mining
rig](https://www.tomshardware.com/news/twelve-ps5-apus-power-asrocks-new-cryptomining-rig),
which housed twelve of them.
Inside each of these boards there's a *binned* chip derived from the AMD APU of
the PlayStation 5, with 6 of the 8 CPU cores and 24 of the 36 GPU CUs enabled,
along with 16GB of GDDR6 RAM **unified** between CPU and GPU, an M.2 slot (PCIe
2.0x2 or SATA III), and just a few ports: two USB 2.0, two USB 3.0, one Gigabit
Ethernet, and one DisplayPort. Power is supplied through an 8-pin PCIe
connector.
At first I wasn't really convinced, especially seeing a third of the CUs cut off
and knowing that it's a board with a custom, partially locked chip (on top of
the locked cores, some features like video encoding/decoding are missing),
coming from cryptocurrency mining and with no support or community behind it.
But the price was definitely interesting, and apparently this board has a very
active community that works hard to squeeze 100% of its potential out of it on
Linux.
![Soffio: "If you want I can give you one, I bought it without the coupon and I
was planning to resell it😂" "So technically I'm getting two😂" Me: "Nah, no
worries" "I wouldn't know what to do with it"](images/01-not-fully-convinced.png
"Me, not fully convinced<br><br>**Translation**:<br>*Soffio*: \"If you want I
can give you one, I bought it without the coupon and I was planning to resell
it😂\" \"So technically I'm getting two😂\"<br>*Me*: \"Nah, no worries\" \"I
wouldn't know what to do with it\"")
Things changed when, on the morning of May 30th, I got this message:
![Soffio: "They managed to unlock all the CUs, went from 24 to 40. Now they're
looking into unlocking the 8 cores😂🌚👌"](images/02-40cu-unlocked-news.png
"<br>**Translation**:<br>*Soffio*: \"They managed to unlock all the CUs, went
from 24 to 40. Now they're looking into unlocking the 8 cores😂🌚👌\"")
And good old Soffio also pointed out that the AliExpress sales were about to
start. Intrigued by the whole thing, I asked him if he could lend me his board
for a few days, just to try it out and see what could be done.
And *oh boy*, did this board convince me.
## Step 0: Preparation
One downside of the BC-250 is that it's not exactly *plug-and-play*. At the very
least, you need to:
1. Find a power supply that can ***really*** deliver at least 300W on the +12V
rail, with cables that can handle all those amperes;
2. Have a monitor with DisplayPort (or buy an adapter);
3. Find a way to cool the damn thing;
4. Flash the BIOS.
My test setup was:
1. The first "*el cheapo*" power supply I could find lying around (which "will
surely be fine, it says 500W");
2. A passive DP ➜ HDMI adapter;
3. A portable air conditioner for cooling (it was summer and it was starting to
get hot);
4. A CH341 SPI programmer (which I already had).
![Home setup](images/03-initial-setup.png "If you look closely, the PS_ON ➜ GND
bridge was made with a jumper wire and all the power goes through a SATA ➜ PCIe
adapter. Don't try this at home")
Not exactly the best setup for testing the board, but you work with what you
have.
## Step 1: Flashing the BIOS
The [first step in the community
documentation](https://elektricm.github.io/amd-bc250-docs/getting-started/quick-start/#step-1-bios-flash-critical)
is flashing the BIOS. Without a custom BIOS you don't get essential features
like dynamic VRAM allocation (remember, the 16GB of RAM are shared) and proper
fan control.
At first I installed the one recommended by the guide, the one by
[TuxThePenguin0](https://gitlab.com/TuxThePenguin0/bc250-bios), but later on I
discovered another BIOS, the one by [Forbidden
Darkness](https://github.com/Forbidden-Darkness/AMD-BC-250-UEFI-v2.2-Firmware-Menu-Script),
which, on top of unlocking the dynamic allocation menu, offers a selection of
custom splash images and, most importantly, **unlocks all 8 CPU cores**.
"*Wait, weren't they locked down?*" Apparently not enough.
The APU has all cores on the silicon, they're just disabled via firmware. A
similar principle also applies to the GPU CUs, but we'll get to that later.
---
The installation is even simpler and doesn't require a BIOS flasher: just copy
the files from the `.7z` archive in the releases to a USB stick formatted in
FAT32 and boot from it. The installer asks which splash image we want (the
[`07`](https://github.com/user-attachments/assets/ca23ce6c-08ab-4293-9a70-0e55f66dc93c)
is the best one, *imho*) and proceeds with the flashing.
![Flashing the BIOS](images/04-bios-flashing.png "Flashing the BIOS")
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557"
textColor="#1d3557" >}}
Flashing the BIOS is a dangerous operation. Make sure the board doesn't turn
off.
{{< /alert >}}
Once the flashing is done, you need to reset all the BIOS settings. To do that,
just unplug the power and bridge pin 2 and 3 of the `CLRCMOS1` header for a few
seconds. Once that's done, we can put the header back on pins 1 and 2 and plug
the power back in. By entering the BIOS with the `Del` key at boot we'll see a
lot more options.
![New boot logo](images/05-new-boot-logo.png "New boot logo")
![New entries in the "Advanced" menu](images/06-new-advanced-menu.png "New
entries in the \"Advanced\" menu")
First, let's make the VRAM allocation automatic. To do that, we need to go to
`Chipset` > `GFX Configuration` > `GFX Configuration` and set `Integrated
Graphics Controller` to `Forces`, then `UMA Mode` to `UMA_SPECIFIED`, and
finally `UMA Frame buffer size` to `512M`.
![The correct UMA configuration](images/07-uma-512m.png "The correct UMA
configuration")
Then in `NB Configuration` disable the IOMMU (it doesn't seem to work on this
board).
Finally, we enable all the cores by going to `Advanced` > `MeiMeiDXEv3 Menu` and
enabling everything.
![The configuration to enable all 8 cores](images/08-8-core-unlock.png "The
configuration to enable all 8 cores")
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557"
textColor="#1d3557" >}}
There's no guarantee that all the cores will work. Damaged cores could cause
sudden crashes.
To avoid that, we'll run a stress test on all the cores and check that no
`Machine Check Exception` shows up in the kernel logs before enabling this
setting in production.
{{< /alert >}}
Once the BIOS is properly configured, we're ready to install an operating system
and test this board for real.
## Step 2: Installing a OS for testing
To do some CPU stress testing and run some tests on the GPU, I'll install Arch
Linux.
It won't be the final distro I'll install, but the choice isn't random:
development for this board is bleeding-edge, and for now almost all the scripts
assume you're running Arch or Fedora, so you have the latest package versions.
![The archinstall configuration I'll use](images/09-archinstall.png "The
archinstall configuration I'll use")
![The installed system](images/10-fastfetch.png "The installed system. As you
can see, all 16 threads already show up")
### Testing the 8 cores
First of all, let's test whether all 8 cores work as they should. To do that,
install the `stress-ng` package and run a stress test:
```sh
stress-ng --cpu 16 --cpu-method all --verify --timeout 2h --metrics
```
Then we check that there were no errors with:
```sh
sudo dmesg | grep -iE "mce|machine check|hardware error"
```
If the kernel doesn't report any errors, we've just gone from 6 to 8 cores for
free. If there is an error you can change which cores to enable from the BIOS.
### Stress-testing the GPU
Next, let's stress test the GPU to get a performance baseline before installing
the governor or enabling all the CUs. To do that, I installed Furmark and ran
the 1080p test.
![Furmark (68 FPS)](images/11-baseline-furmark.png)
I'd say 70 FPS isn't *that* bad for the board *out-of-the-box*, but we can
definitely do better, much better.
---
A small note I feel I should add: if during the stress test the screen goes
black and the board doesn't respond in any way, check your power supply. The
little foreshadowing I did in step 0 about the power supply is because during my
tests I ran Ollama and completely fried the PSU since (apparently) it couldn't
really handle the whole load on the +12V rail. I then bought the PSU recommended
by the community on AliExpress, along with the board, the [Metalfish 500W
FlexATX](https://elektricm.github.io/amd-bc250-docs/hardware/power#option-2-flexatx-psu-500w),
and I haven't had any problems since.
![Deceased PSU](images/12-dead-psu.jpg "Rest in peace, soldier 🫡")
### Installing the GPU Governor
By default the GPU always runs at 1500MHz: a governor lets you raise the clock
when the GPU is under load and lower it when it isn't, to save power.
We'll install `cyan-skillfish-governor-smu`, a community project that talks
directly to the board's System Management Unit. It's also already packaged in
the AUR, so to install it you just need to run:
```sh
paru -S cyan-skillfish-governor-smu
systemctl enable --now cyan-skillfish-governor-smu
```
We can check that it works with:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk # If it doesn't work, try card0
0: 1000Mhz *
1: 1500Mhz
2: 2000Mhz
```
The first and last lines are, respectively, the minimum and maximum GPU
frequency, while the middle line can change. The asterisk marks the frequency
currently in use. An example under load:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz
1: 1850Mhz *
2: 2000Mhz
```
We should see the GPU automatically use a higher frequency under load and a
lower one when idle.
---
**Small note**: unlocking the 8 cores affects how the SMU values are read. It's
a known issue and we'll fix it later on, when we'll deal with the operating
system. Without any fix, the frequency values are wrong, for example:
```
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz *
1: 4575Mhz
2: 2000Mhz
# Not a bad overclock for a chip that tops out at 2230MHz
```
With that said, let's run a stress test now, with the governor installed.
![Furmark (83 FPS)](images/13-furmark-governor.png)
Now that we can scale up to 1850MHz, our GPU manages to reach 83 FPS at 1080p,
not bad!
1850MHz is by no means the most this chip can handle, but for now we'll settle
for it. For the curious, the frequency and voltage curves are fully customizable
and live in `/etc/cyan-skillfish-governor-smu/config.toml`. With a bit of trial
and error you can push the hardware to its limits while minimizing power draw,
but we'll do that when we set up the final operating system.
### Unlocking the 40 CUs
As we said at the beginning, this board only exposes 24 CUs to the kernel, even
though the PS5 has 36 and there are actually 40 on the silicon. We can verify
this with:
```
$ sudo dmesg | grep active_cu_number
[ 6.882856] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
```
To test and then unlock all the CUs, we'll use [duggasco's
repository](https://github.com/duggasco/bc250-40cu-unlock). The mechanism is
similar to the core unlock: here too you just need to change a few values,
because the CUs aren't locked at the hardware level, they're just disabled by
the firmware.
Two registers in the GPU decide how many CUs are active. What this script does
is patch the `amdgpu` driver and write the right values into those registers
while the driver starts up, waking up the disabled CUs.
```
$ git clone https://github.com/duggasco/bc250-40cu-unlock.git
$ cd bc250-40cu-unlock/
$ sudo pacman -S linux-headers vulkan-headers
$ sudo scripts/bc250-enable-40cu-arch.sh build
# Wait for the `amdgpu` module to be recompiled
$ sudo scripts/bc250-enable-40cu-arch.sh enable
```
Once the BC-250 has rebooted, we can check that the patch worked using the same
command as before:
```
$ sudo dmesg | grep active_cu_number
[ 8.004012] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
```
Apparently the script doesn't load the custom module automatically. That's not a
problem: let's regenerate the initramfs and reboot manually:
```
$ sudo mkinitcpio -P
$ reboot
# Once it has rebooted
$ sudo dmesg | grep active_cu_number
[ 8.058999] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 40
```
Much better!
---
Once the custom module is installed, we can move on to testing the CUs:
```
$ sudo scripts/bc250-cu-health-test.sh start
```
During the test the PC will automatically reboot twenty times. Once the PC stops
rebooting on its own, we can see the test results with:
```
$ scripts/cu_map.sh
BC-250 CU Map + Health
SE0 SH0: ■■■■■■■■■■
SE0 SH1: ■■■■■■■■■■
SE1 SH0: ■■■■■■■■■■
SE1 SH1: ■■■■■■■■■■
40/40 CUs active, 0 harvested
BC-250 CU Map + Health
SE0 SH0: ■■■■■■✓✓✓✓
SE0 SH1: ■■■■■■✓✓✓✓
SE1 SH0: ■■■■■■✓✓✓✓
SE1 SH1: ■■■■■■✓✓✓✓
40/40 CUs usable (0 defective, masked)
```
Apparently I won the silicon lottery and have 8 cores and 40 working CUs.
Hurray! 🎉
If there had been any defective CUs I could have masked them using the
`bc250-cu-mask.sh` script.
---
Running the last stress test with Furmark:
![Furmark (128 FPS)](images/14-furmark-40cu.png)
We went from the bare board, without any additional software, running at an
average of 70 FPS, to having a governor and all the CUs unlocked, with peaks of
138 FPS, twice as much!
Of course, this approach to unlocking the 40 CUs has a pretty obvious problem,
especially on rolling distributions like Arch: you have to recompile the module
every time you update the kernel. This is another problem we'll solve later on,
when we stop using a test OS, but if after an update the GPU isn't as fast as
before, it might be worth taking a look.
### Sensors and Other Essential Configurations
Once the essentials like CPU and GPU are sorted out, there are still a few small
things to take care of, such as sensor management, fans, swap, VRAM split,
etc...
I could go on about it for hours, but I'll point you to the [community
documentation](https://elektricm.github.io/amd-bc250-docs/), which is very
thorough.
What I'd like to do now is point out one thing: using the `sensors` command, we
get very little data OOTB:
```
$ sensors
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +39.0°C
PPT: 41.41 W (avg = 40.85 W)
sclk: 1000 MHz
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +41.6°C
```
To get more data we need the `nct6683` module (read-only) or `nct6687` (you can
create custom curves with it, but it's *out of tree*). Since `nct6683` is
already available, we can enable it with:
```
$ echo 'options nct6683 force=true' | sudo tee /etc/modprobe.d/sensors.conf
$ echo 'nct6683' | sudo tee /etc/modules-load.d/99-sensors.conf
$ sudo mkinitcpio -P
$ reboot
```
After rebooting we'll see a lot more data:
```
$ sensors
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +46.9°C
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +41.0°C
PPT: 42.61 W (avg = 40.75 W)
sclk: 1000 MHz
nct6686-isa-0a20
Adapter: ISA adapter
VIN0: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN1: 1.01 V (min = +0.00 V, max = +0.00 V)
VIN2: 992.00 mV (min = +0.00 V, max = +0.00 V)
VIN6: 1.39 V (min = +0.00 V, max = +0.00 V)
VIN7: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN16: 896.00 mV (min = +0.00 V, max = +0.00 V)
fan1: 0 RPM (min = 0 RPM)
fan2: 1709 RPM (min = 0 RPM)
fan3: 0 RPM (min = 0 RPM)
fan4: 0 RPM (min = 0 RPM)
fan5: 0 RPM (min = 0 RPM)
AMD TSI Addr 98h: +47.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = AMD AMDSI
Thermistor 14: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
Thermistor 15: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
pwm1: 64%
pwm2: 64%
pwm3: 64%
pwm4: 64%
pwm5: 64%
intrusion0: OK
beep_enable: disabled
```
## Step 3: Hardware Mods
I want to remind you that for all these tests I was using Soffio's BC-250, just
to see whether it was something I'd be interested in. And since I found myself
pretty hooked I decided to get everything I needed from AliExpress.
Luckily with the sales and also using TopCashback I managed to bring home
everything I needed for less than €200. I then bought a couple of Arctic P12
Pros from Amazon.
Everything arrived on June 24th, so it was time to get to work on:
* Replacing the thermal paste and pads;
* Installing heatsinks on the back panel, to cool the GDDR6;
* Removing the metal bracket and the I/O shield (they're only needed if the
board is mounted in the rig);
* Re-running the test suite mentioned above to see if I had won the silicon
lottery a second time (luckily I did);
* Modding the heatsink.
The heatsink mod let me solve one of the problems I was having with the board:
how do I get rid of 200W of heat? So far I had the portable AC, but I couldn't
keep using a heat pump to cool a single board.
When they're in the mining rig, the BC-250 all have their heatsinks laid out
lengthwise, so a single array of fans is enough to cool all 12 boards at once.
If you want to use one of these boards on its own, you need to get a bit more
creative to get rid of the heat.
The most common solution in the community is the [heatsink
mod](https://reddit.com/r/BC250Gaming/comments/1rjc3io/), which consists of
literally cutting open the heatsink in the section above the APU to make room
for a fan.
It's a somewhat long and tedious job, but it's not impossible to do. It's also a
pretty repetitive task, so once you get the hang of it, it goes by farely
quickly. In the end all it took was a pair of scissors, some good music, and an
hour of my time.
![Before the heatsink mod](images/15-before-heatsink-mod.jpg "The BC-250 as it
comes out of the box, with the metal bracket and I/O shield removed")
![After the heatsink mod](images/16-after-heatsink-mod.jpg "The heatsink after
the mod")
It's a bit *rough around the edges* (*literally*), but it works. And the hole is
big exactly as a 120mm fan, so one of the two fans can blow directly onto the
APU.
---
Since this article has gotten pretty long, I've decided to split it into
multiple parts. In the next one, we'll design a custom case for my needs.