Otwarta architektura procesora RISC-V to rewolucja w branży procesorów. Dzięki emulatorowi Qemu możemy zaznajomić się z RISC-V bez czekania na dostępność niedrogiego sprzętu.
Większość branży IT skonsolidowała się wokół procesorów Intela i AMD opartych na architekturze x86 i (pokrewnej) AMD64. Ale zaledwie dwie dekady temu o miejsce na rynku walczyło kilku innych producentów procesorów obsługujących inne architektury. Wiele z tych procesorów (w tym MIPS, PowerPC, Alpha i SPARC) przestrzegało zestawu zasad projektowania procesorów znanych jako „komputer z ograniczonym zestawem instrukcji” (Reduced Instruction Set Computer, w skrócie RISC). Systemy RISC są używane również dziś, w szczególności w architekturze ARM używanej w popularnych smartfonach, Raspberry Pi i różnych urządzeniach elektronicznych. (Skrót ARM w rzeczywistości oznacza Advanced RISC Machine, czyli zaawansowana maszyna RISC”.) Ale rośnie też popularność innej architektury opartej na RISC.
Opcje sprzętowe
Płytka ESP32-C3-DevKitC-02 z rdzeniem RISC-V jest dostępna w sklepach wysyłkowych w cenach od około 10 euro (Rysunek 1). ESP32-C3 został wyprodukowany przez chińską firmę Espressif; to młodszy brat swojego znanego i odnoszącego sukcesy modelu ESP32. Ma nieco mniejszą wydajność niż klasyczny model, ale jest mniejszy i tańszy.
Tabela 1: Cechy RISC-V
Modułowość | Podstawowy zestaw instrukcji plus rozszerzenia |
Szerokość rejestru | 32, 64, 128 |
Liczba rejestrów: | 16 (dla systemów wbudowanych), 32, 64 |
Typ architektury | załaduj/przechowuj |
Format przechowywania plików | Little Endian |
Liczba instrukcji | 40 (RV32I, obliczeniowa, przepływ sterowania, dostęp do pamięci) |
Poziomy uprawnień | 3 |
Typ maszyny | Maszyna trzyrejestrowa |
Typy instrukcji: | 6 (R, I, U, S, B, J) |
Oprogramowanie | Kompleksowy ekosystem oprogramowania, łącznie z popularnymi stosami oprogramowania (Linux, FreeRTOS) |
Dodatkowo | Stabilna specyfikacja, żadne dalsze zmiany nie są planowane |
Tabela 2: Wybór rozszerzeń zestawu instrukcji RISC-V
RV32I | Podstawowy zestaw instrukcji |
RV32A | Rozszerzenie A (atomowy odczyt-modyfikacja-zapis) |
RV32B | Rozszerzenie B (manipulacja bitami) |
RV32C | Rozszerzenie C (skompresowane instrukcje) |
RV32D | Rozszerzenie D (zmiennoprzecinkowe podwójnej precyzji) |
RV32F | Rozszerzenie F (zmiennoprzecinkowe pojedynczej precyzji) |
RV32M | Rozszerzenie M (mnożenie, dzielenie) |
RV32S | Rozszerzenie S (instrukcje na poziomie superwizora) |
RV32V | Rozszerzenie V (instrukcje wektorowe) |
RISC-V (wymawiamy jak angielskie „risk five”) uważany jest za wschodzącą gwiazdę na niebie architektur procesorów [1]. Jego zwolennicy uważają, że RISC-V może zrobić wszystko to co ARM – a przy tym jest otwarty i wolny od opłat licencyjnych. Niezastrzeżony charakter RISC-V oznacza, że umożliwia on wejście małym producentom na bardzo ważny rynek, który jest teraz zdominowany przez kilku gigantów technologicznych. Nawet duzi gracze mogą pewnego dnia zyskać przewagę, wybierając RISC-V i unikając opłat licencyjnych.
Architektura RISC-V ma zaledwie 10 lat, nadal więc uważa się ją za stosunkowo młodą. Jeśli potrafimy żyć bez Linuksa i wolimy FreeRTOS, możemy zacząć przygodę z RISC-V już dziś i zdobyć trochę doświadczenia, pracując na sprzęcie o rozsądnej cenie (patrz ramka „Opcje sprzętowe”). Do niedawna, jeśli szukaliśmy procesora RISC-V obsługującego Linuksa, musieliśmy zapłacić aż 600 euro. Kiedy do druku wysyłany był niniejszy numer „Linux Magazine”, na rynek trafiła w końcu przystępna cenowo i gotowa na Linuksa płyta RISC-V [2]. Co prawda nie jest ona demonem prędkości, jednak za kilkadziesiąt złotych możemy nabyć urządzenie RISC-V, które możemy podłączyć do monitora przez HDMI i uruchomić na nim Linuksa.
Jeśli chcemy poznać RISC-V w połączeniu z Linuksem, możemy to zrobić już teraz, nie czekając na idealny sprzęt. Kompilator RISC-V jest dostępny dla Ubuntu, do emulacji kompletnego 32- lub 64-bitowego systemu RISC-V możemy zaś użyć emulatora sprzętu Qemu. Niektóre dystrybucje Linuksa już są dostępne w wersji dla RISC-V, możemy więc szybko zabrać się do pracy.
Listing 1: RISC-V w Ubuntu na Qemu
#!/bin/bash
BASISDIR=~/risc-v
UBUNTU_IMG=ubuntu-20.04.3-preinstalled-server-riscv64+unmatched.img
if test ! -f `type -p riscv64-linux-gnu-gcc`; then
echo "install compiler..."
sudo apt install gcc-riscv64-linux-gnu
fi
if test ! -f `type -p qemu-system-riscv64`; then
echo "install qemu..."
sudo apt install qemu-system-misc qemu-utils
fi
if test ! -d ${BASISDIR}; then
echo "mkdir ${BASISDIR}"
mkdir ${BASISDIR}
fi
cd ${BASISDIR}
if test ! -f opensbi/build/platform/generic/firmware/fw_payload.bin; then
wget https://cdimage.ubuntu.com/releases/20.04/release/${UBUNTU_IMG}.xz
xz -dk ${UBUNTU_IMG}.xz
qemu-img resize -f raw ${UBUNTU_IMG} +6G
export CROSS_COMPILE=riscv64-linux-gnu-
git clone https://source.denx.de/u-boot/u-boot.git
cd u-boot/
git reset --hard v2021.10-rc3
make qemu-riscv64_smode_defconfig
make -j$(nproc)
cd ..
git clone https://github.com/riscv/opensbi.git
cd opensbi/
make PLATFORM=generic FW_PAYLOAD_PATH=../u-boot/u-boot.bin
cd ..
fi
qemu-system-riscv64 -machine virt -m 4G -nographic \
-bios opensbi/build/platform/generic/firmware/fw_payload.bin \
-smp cores=2 -gdb tcp::1234 \
-device virtio-net-device,netdev=eth0 \
-netdev user,id=eth0,hostfwd=tcp::2222-:22 \
-drive if=none,file=${UBUNTU_IMG},format=raw,id=mydisk \
-device ich9-ahci,id=ahci -device ide-hd,drive=mydisk,bus=ahci.0 \
-device virtio-rng-pci
W niniejszym artykule pokażemy, jak zrobić pierwsze kroki w odkrywaniu Linuksa na RISC-V – ale najpierw kilka słów teorii.
O RISC-V
Dziesięć lat temu informatycy z Uniwersytetu Kalifornijskiego w Berkeley (UC Berkeley) opracowali nową architekturę zestawu instrukcji procesora (ISA) znaną jako RISC-V (Rysunek 2); pomysł polegał na tym, aby RISC-V był nowoczesny i nadawał się zarówno do nauczania i badań, jak i do rzeczywistych zastosowań [3]. Szczególną atrakcją był model licencjonowania oparty na BSD, który umożliwia licencjobiorcy bezpłatne korzystanie z architektury (tabela 1).
W ciągu ostatnich kilku lat duże i małe firmy zaczęły badać możliwości RISC-V, a także opracowywać, produkować i dystrybuować sprzęt z rdzeniem RISC-V i nieodpłatne udostępniać swoje projekty. Na przykład duży chiński sklep internetowy Alibaba całkowicie ujawnił opracowany przez siebie rdzeń RISC-V, podobnie jak producent dysków Western Digital. Nawet Apple, który ma w zanadrzu bardzo mocny i wydajny procesor ARM w postaci układu M1, szukał ostatnio programistów RISC-V.
Podobnie jak ARM, ale w całkowitym przeciwieństwie do x86, architektura RISC-V bardzo dobrze skaluje się do małych rozmiarów. Oprócz wariantów, które mają w pełni rozwiniętą jednostkę zarządzania pamięcią (MMU) i dlatego są odpowiednie dla systemu Linux, RISC-V obsługuje bardzo proste mikrokontrolery do bezpośredniego programowania sprzętu, dzięki czemu nadaje się do zastosowań niewymagających oprogramowania systemowego; działa też na systemie operacyjnym czasu rzeczywistego FreeRTOS.
Najprostsze warianty RISC-V implementują tylko podstawowe instrukcje, znane również jako „instrukcje I”. Oprócz operacji logicznych te podstawowe instrukcje składają się tylko z dodawania i odejmowania; mnożenie i dzielenie zarezerwowane jest dla rozszerzenia M. Tabela 2 zawiera przykłady rozszerzeń RISC-V, takich jak rozszerzenie F dla liczb zmiennoprzecinkowych lub rozszerzenie C dla instrukcji skompresowanych. UC Berkeley sugeruje implementację przynajmniej rozszerzeń I, M, F, D i A i używa litery G (ogólne) w celu skrócenia tej architektury do RV32G.
RISC-V jest definiowany jako architektura 32-, 64-, a nawet 128-bitowa. Innymi słowy, wszystkie rejestry wewnętrzne mają szerokość 32, 64 lub nawet 128 bitów, w zależności od architektury. Istnieje nie mniej niż 32 lub 64 rejestrów, które są ponumerowane od X0 do X31 lub X63. Oprócz rejestru X0, który może być tylko odczytywany i w którym wszystkie bity są ustawione na 0, rejestry te mogą być używane w sposób uniwersalny. Nie ma na przykład specjalnego wskaźnika stosu jak w x86/AMD64. Jednak architektura zapewnia oddzielny licznik programu (PC) (tj. licznik instrukcji, który zawiera adres instrukcji, którą procesor musi przetworzyć w następnej kolejności).
Podczas gdy architektura x86 jest maszyną z dwoma rejestrami, RISC-V zazwyczaj ma trzy rejestry zaangażowane w operację. Jeśli maszyna z dwoma rejestrami dodaje zawartość dwóch rejestrów, musi przechowywać wyniki w jednym z dwóch rejestrów. Natomiast maszyna z trzema rejestrami może przechowywać wynik w trzecim rejestrze (X1 = X2 + X3).
Instalacja RISC-V Linux
Ponieważ mówimy o całkowicie innej architekturze, nie wystarczy wywołać apt install, by móc zacząć testować RISC-V. Do emulowanej maszyny RISC-V potrzebny jest BIOS, program ładujący i wreszcie sam Linux.
Cały proces zaczynamy od instalacji kompilatora RISC-V poleceniem:
apt install gcc-riscv64-linux-gnu
Pobieramy najnowszą wersję otwartego BIOS-u OpenSBI wygenerujemy BIOS. Menedżerem ładowania jest U-Boot, który jest dobrze znany w zastosowaniach wbudowanych – będziemy musieli skompilować U-Boot w wersji dla RISC-V.
Hostowany przez firmę Canonical obraz serwera RISC-V [4] jest zoptymalizowany pod kątem niewielkich rozmiarów – ma 466 MB. Po pobraniu i rozpakowaniu obrazu za pomocą narzędzi Qemu musimy przekonwertować go do użytecznego rozmiaru. Musimy sami zdecydować, czy będzie to 20 GB, czy tylko 5 GB.
Na koniec musimy uruchomić Qemu z mnóstwem parametrów, zwłaszcza jeśli chcemy korzystać z dostępu do Internetu. Użytkownik Aaronfranke udostępnia skrypt [5] zawierający podstawowe etapy instalacji. Listing 1 pokazuje zmodyfikowaną i rozszerzoną odmianę tego skryptu; optymalizuje on system startowy, dopasowuje go do bieżącego środowiska i uruchamia.
Skrypt tworzy w naszym katalogu domowym nowy podkatalog risc-v/, instaluje niezbędne oprogramowanie, uruchamiając apt install i ponownie ładuje inne wymagane komponenty, w tym gotowy obraz Ubuntu. Generuje oprogramowanie układowe i bootloader, a na koniec uruchamia Linuksa w wersji dla RISC-V. Nawiasem mówiąc, pobieranie i instalacja mają miejsce tylko przy pierwszym wywołaniu.
Skrypt należy zapisać, np. jako risc-v-linux.sh, i odpowiednio zmienić prawa dostępu:
chmod 755 risc-v-linux.sh
Możemy teraz spróbować uruchomić Linuksa dla RISC-V na konsoli:
./risc-v-linux.sh
Musimy jednak uzbroić się w cierpliwość, ponieważ implementacja procesora RISC-V w Qemu polega na emulacji programowej, nie wirtualizacji. Po kilku minutach system powinien poprosić nas o zalogowanie się; wpisujemy nazwę użytkownika ubuntu i takie samo hasło początkowe (Rysunek 3). System wymusi zmianę hasła ze względów bezpieczeństwa.
Brak zabawy w wierszu poleceń
Ponieważ konsola szeregowa ma pewne wady, najlepiej zalogować się do nowego systemu przez SSH przy użyciu innego okna terminala. Nasz skrypt skonfigurował logowanie do Qemu przez SSH, możemy więc napisać:
ssh -p 2222 ubuntu@localhost
Jeśli wydamy teraz polecenie uname -a, zobaczymy, że pracujesz na komputerze RISC-V. Również polecenie cat /proc/cpuinfo pokaże bieżącą architekturę, w tym zaimplementowane rozszerzenia, ale poza tym zawiera zaskakująco mało informacji. Kolejne ślady architektury RISC-Vznajdziemy, wydając polecenia takie jak cat /proc/interrupts, dmesg, czy w file /usr/bin/bash (Rysunek 4). Jak widzimy, Linux zdecydowanie zasługuje na miano niezależnego od platformy systemu operacyjnego, starannie ukrywając pod maską nową architekturę procesora.
Listę pakietów zaktualizujemy w zwykły sposób poleceniem apt update. Unikajmy jednak apt upgrade, które może zamienić jądro i bootloader i spowodować problemy. Ogólnie rzecz biorąc, oprogramowanie nie będzie w stu procentach stabilne. Po zainstalowaniu kompilatora i narzędzi programistycznych za pomocą:
apt install build-essential gdb vim
możemy skompilować niewielki program „Hello RISC-V”. Rejestry procesora i kod asemblera możemy sprawdzić w debuggerze GNU (Rysunek 5).
Nawiasem mówiąc, rejestry procesora nie używają wcześniej wspomnianych oznaczeń rejestrów od X0 do X31 w debuggerze ani w danych wyjściowych polecenia dmesg –kernel. Zamiast tego ujrzymy nazwy ra, sp, t0, s6 i tak dalej. Fundacja RISC-V zaproponowała – czy też określiła – konwencję korzystania z rejestrów, a programiści lub producenci narzędzi programistycznych również stosują się do tej konwencji. Zgodnie z nią np. rejestr X2 działa jako wskaźnik stosu (sp), natomiast X1 zawiera adres zwrotny (ra) dla wywołania podprogramu. Rejestry z T w nazwie służą do buforowania danych, a te, które zaczynają się od A, zawierają parametry wywołania funkcji.
W większości przypadków programiści aplikacji nie muszą się martwić o te szczegóły; są one istotne głównie dla programistów jądra.
Zamykanie Qemu
Po zakończeniu pracy wyłączamy Ubuntu na RISC-V w terminalu, wpisując sudo poweroff. Aby móc wyjść z Qemu, używamy skrótu klawiaturowego Ctrl+A,X.
Doskonałe dopasowanie
Oprócz Ubuntu, gotowe obrazy RISC-V udostępnia też Fedora [6] i Debian [7]. Jednak testowana przez nas odmiana Debiana nie działała idealnie i nie pozwoliła nam zainstalować Vima. Tak czy inaczej bardziej ekscytujące jest korzystanie z własnoręcznie przygotowanej kompilacji zamiast gotowego obrazu systemu. Jeśli interesuje nas ten proces, możemy użyć w tym celu konstruktora systemu Buildroot; krótki samouczek można znaleźć pod adresem [8].
Jak widzimy, użytkownicy Linuksa nie mają powodu narzekać na brak wsparcia dla architektury zestawu instrukcji RISC-V. Nie powinno nas to dziwić: można pokusić się o stwierdzenie, że dzięki inteligentnemu, modułowemu projektowi o otwartym kodzie źródłowym oraz bezpłatnej licencji Linux i RISC-V idealnie do siebie pasują.
Żródła:
[1] Specyfikacje RISC-V: https://riscv.org/technical/specifications/
[2] Nowa płyta RISC-V gotowa na Linuksa: https://www.aliexpress.com/item/1005003594875290.html
[3] RISC-V: https://en.wikipedia.org/wiki/RISC-V
[4] RISC-V na Ubuntu: https://wiki.ubuntu.com/RISC-V
[5] „Dokumentacja serwera Ubuntu na RISC-V wymaga aktualizacji”: https://discourse.ubuntu.com/t/ubuntu-server-on-risc-v-documentation-needs-updating/23927/10
[6] Fedora dla RISC-V: https://fedoraproject.org/wiki/Architectures/RISC-V
[7] Debian dla RISC-V: https://wiki.debian.org/RISC-V
[8] Qemu i RISC-V: https://wiki.amarulasolutions.com/bsp/riscv/qemu.html