Files
blog/content/posts/2026/11/bc-zero-board-testing/index.it.md
T
2026-11-08 16:01:25 +01:00

20 KiB

+++ title = "BC-Zero - Testing della scheda" summary = "Da vecchia scheda da mining a console e server AI" date = "2026-11-08"

tags = ["BC-250", "PS5", "Sblocco", "BIOS", "CPU", "GPU"] categories = ["Progetti"] series = ["BC-Zero"] series_order = 1 +++

Il 5 febbraio Soffio, amico e socio LUGMan, 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, 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"

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😂🌚👌"

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

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 è 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, ma più avanti ho scoperto un altro BIOS, quello di Forbidden Darkness 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 è la migliore imho) e procede a flashare.

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 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

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

{{< 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ò Il sistema installato

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:

stress-ng --cpu 16 --cpu-method all --verify --timeout 2h --metrics

Verifichiamo poi che non ci siano stati errori con:

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)

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 e da li non ho più avuto problemi.

PSU deceduta

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:

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)

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. 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)

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, 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, 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 Dopo la modifica al dissipatore

È 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.