先按照官方說明將 bootloader, Kernel image 燒錄到板子上,裡面有用到 Tera term 傳送 Flash Writer 到板子上的操作,我不知道如何在 Linux 上面做,所以都是在 Windows 上面用好,確定透過 UART 看 log、下命令,才到 Ubuntu 上面改用 screen 連線到板子上
root@rzfive-tinker-v:~/tests# ./box64_v2 ./x86/puzzle
./box64_v2: /lib/libc.so.6: version `GLIBC_2.29' not found (required by ./box64_v2)
./box64_v2: /lib/libc.so.6: version `GLIBC_2.33' not found (required by ./box64_v2)
./box64_v2: /lib/libc.so.6: version `GLIBC_2.38' not found (required by ./box64_v2)
./box64_v2: /lib/libc.so.6: version `GLIBC_2.32' not found (required by ./box64_v2)
./box64_v2: /lib/libc.so.6: version `GLIBC_2.34' not found (required by ./box64_v2)
/dev
底下有沒有 /dev/ttyUSB{id}
,確定裝置後用 screen 連線到 Tinker-V 上面,鮑率要設 115200$ ls /dev | grep USB
/dev/ttyUSB0
$ sudo screen /dev/ttyUSB1 115200
這時候應該能夠看 rzfive-tinker-v login:
,輸入 root
即可登入
screen 沒辦法捲動終端機,或許可以試試看 PuTTY
有時候 UART 會遇到下面這些問題,遇到的話就把 RS232 拔掉重連,或是拔電源重開
abc
,當輸入到 b 才會出現 a,輸入到 c 才出現 b,最後印出的是 ab
GPIO 佔用 kernel
使用 patching 詳見 : issue
glib2.0 來源遺失
修改 recipe ,詳見:issue
修改 linux_libc_headers_5.10.bb
缺少 checksum
在 linux_libc_headers_5.10.bb
中添加 :
SRC_URI[sha256sum] = "c1d276741f8387da5aab790954e7486354feb7de2c830f123ea830a1723bf604"
glibc-2.28-r0 do_fetch
: Fetcher failure# This is generated by debian-source.bbclass
DPV = "2.28-10+deb10u4"
DPV_EPOCH = ""
REPACK_PV = "2.28"
PV = "2.28"
DEBIAN_SRC_URI = " \
${DEBIAN_SECURITY_UPDATE_MIRROR}/main/g/glibc/glibc_2.28-10+deb10u4.dsc;name=glibc_2.28-10+deb10u4.dsc \
${DEBIAN_SECURITY_UPDATE_MIRROR}/main/g/glibc/glibc_2.28.orig.tar.xz;name=glibc_2.28.orig.tar.xz \
${DEBIAN_SECURITY_UPDATE_MIRROR}/main/g/glibc/glibc_2.28-10+deb10u4.debian.tar.xz;name=glibc_2.28-10+deb10u4.debian.tar.xz \
"
SRC_URI[glibc_2.28-10+deb10u4.dsc.md5sum] = "b39dd7f7f54c6b7da3eefcd391470af2"
SRC_URI[glibc_2.28.orig.tar.xz.md5sum] = "2d78d5b080fbe4fefa2e1ccef9c39dbc"
SRC_URI[glibc_2.28-10+deb10u4.debian.tar.xz.md5sum] = "8ebb6ee80ba6a5e39eacc31c95994ef0"
SRC_URI[glibc_2.28-10+deb10u4.dsc.sha256sum] = "55e4ebd9a55755c84d42709b23f9b269f46b6a76f5040a0e05cfd323ba67f8af"
SRC_URI[glibc_2.28.orig.tar.xz.sha256sum] = "53d3c1c7bff0fb25d4c7874bf13435dc44a71fd7dd5ffc9bfdcb513cdfc36854"
SRC_URI[glibc_2.28-10+deb10u4.debian.tar.xz.sha256sum] = "dc287870d4b8cb5d1d175fa9b95e3a97d6b68699680b443ae7b2a1b89f0fe8fc"
本部分資訊已過時
要用舊版 RISC-V 編譯器來編譯 box64 才能夠在板子上面執行,需下載 glibc 版本的 toolchain 來用,解壓縮到 /opt
並更新好 PATH
變數後,應能夠在終端機使用到 toolchain 提供的執行檔
$ riscv64-unknown-linux-gnu-gcc --version
riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
如果要用 QEMU 來執行 box64 的程式,會遇到某些 library 找不到(e.g. ld-linux-riscv64-lp64d.so.1
),可以將 {toolchain_path}/sysroot/lib
更新到 LD_LIBRARY_PATH
Note: 新版的 toolchain 在 bin/
目錄底下會有 QEMU 可以使用
export LD_LIBRARY_PATH="/opt/riscv64-unknown-linux-gnu_1320/lib:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="/opt/riscv64-unknown-linux-gnu_1320/sysroot/lib:$LD_LIBRARY_PATH"
如果要用 man 來閱讀 toolchain 的文件,可以將 toolchain 提供的 man 目錄複製到 PC 的 /usr/local/share/man/
底下
> sudo cp -r /opt/riscv64-unknown-linux-gnu_1320/share/man/man5 /usr/local/share/man/man5
複製好後就可以使用 man 來閱讀 toolchain 的文件了
> man riscv64-unknown-linux-gnu-gcc
使用最新的 GNU Toolchain for RISC-V,選 riscv64-glibc-ubuntu-20.04-gcc-nightly
安裝 ninja 以加快編譯:
$ sudo apt-get install ninja-build
編譯 box64 可以設定幾個選項來編譯,詳細可以看官方文件,這裡我主要針對 RISC-V 配置編譯選項,最後 make 時,用 bear 輸出 compile_commands.json
給 clangd 來分析程式碼,以便用來 trace code
$ mkdir -m 777 build
$ cd build
$ cmake \
-G Ninja \
-D RV64=1 -D RV64_DYNAREC=ON \
-D CMAKE_BUILD_TYPE=RelWithDebInfo \
-D CMAKE_C_COMPILER=riscv64-unknown-linux-gnu-gcc \
..
$ ninja
預期可見到 box64
執行檔,注意在連結階段可能會等待較長時間,之後可改用 mold。
由於 box64
使用新版 toolchain 內附的 glibc,因此會遇到跟原本 rootfs 裡頭 glibc 符號不匹配的狀況,因此可利用 patchelf 工具,修改動態連結器和函式庫的位置。首先安裝 patchelf:
$ git clone https://github.com/NixOS/patchelf
$ cd patchelf
$ ./bootstrap.sh
$ ./configure --prefix=/usr
$ make
$ sudo make install
利用 patchelf 修改上面產生的 box64
執行檔: (假設切換到 box64/build
目錄)
$ patchelf --set-rpath /lib:/lib/custom box64
$ patchelf --set-interpreter /lib/custom/ld-linux-riscv64-lp64d.so.1 box64
先準備 /lib/custom
目錄和從 GNU Toolchain 複製必要檔案: (__TOOLCHAIN__
是從 GNU Toolchain for RISC-V 取得並解開的目錄)
$ mkdir -p sysroot/lib/custom
$ cp __TOOLCHAIN__/sysroot/lib/*.so* sysroot/lib/custom
接著利用 QEMU 測試:
$ qemu-riscv64 -L sysroot box64 --help
預期可見到:
Dynarec for RISC-V With extension: I M A F D C Zba Zbb Zbc Zbs Vector (vlen: 128)
...
This is Box64, The Linux x86_64 emulator with a twist
...
接著可用 box64
執行預先編譯好的 x86-64 執行檔,例如 /bin/busybox
。
將上述 sysroot/lib/custom
目錄的內容,放到 Tinker V 的檔案系統中,確保 /lib/custom
目錄包含 ld-linux-riscv64-lp64d.so.1
和 libc.so.6
在內的動態連結函式庫檔案。
為了在 x86-64 主機測試更多程式,進行以下準備: (記得修改 box64/build
的路徑)
$ sudo su -
$ cd /lib
$ ln -s box64/build/sysroot/lib/custom .
$ exit
執行 xlogo 程式:
$ qemu-riscv64 -L sysroot box64 /usr/bin/xlogo
預期可見 X
字樣的視窗。
Rui Ueyama 是一位高產的開放原始碼先鋒,他常帶給技術社群各式驚喜,代表作品像是 8cc (短小精悍且可 self-hosting) 和 lld (LLVM linker,比 GNU gold 或 Microsoft Visual Studio linker 快)。他從 2020 年 9 月開始發展名為 mold 的新連結器 (linker),並於 2022 年初發布 mold 連結器的 1.0 版,以更快的演算法和高效的內部結構,獲得比 LLVM 的 lld 更快的表現,引起許多開發者的重視,GCC 12 也納入相關的支援。
通常構建時間 (build time) 由編譯時間和連結時間組成。與編譯時間相比,後者可藉由 Ninja 和 ccache 等工具加速,連結時間主要依賴於連結器本身的效率。因此,連結器的速度至關重要,mold 無疑是目前開放原始碼實作效率最高,且有足夠好相容性的專案,例如 LLVM 子專案 lld 儘管也強調平行化的連結,但不支援 GCC LTO,而 GNU gold 一開始要跳脫 GNU ld 的效能限制,但現在 gold 發展停滯。
安裝 mold:
$ curl -L -o mold.tar.gz https://github.com/rui314/mold/releases/download/v2.34.1/mold-2.34.1-x86_64-linux.tar.gz
$ sudo tar -xz --strip-components=1 -C /usr/ -f mold.tar.gz
在上述的 cmake
階段,要增加 -D WITH_MOLD=1
選項,重新執行 cmake
後,執行以下:
$ mold -run ninja
在 Intel Xeon CPU E5-2650 v4 @ 2.20GHz 機器上,原本要花 7 分鐘建構 box64
,利用 mold 則縮減到 4 分鐘
可觀看撿到槍的系統軟體工程師 GDB&VScode ,大致了解 clangd 的配置和用途。
建議在 VSCode 的 user setting 加入關閉自動插入 header 的設定,有時候會引入到不對的 header
"clangd.arguments": [
"--header-insertion=never",
],
clangd 還有哪些 arguments 可以修改?請在終端機輸入 clangd --help
.clangd
示範.clangd
為 clangd 的設定檔,一般來說會放在 project 的根目錄,細節可以看文件,這裡示範如何在不同環境下引入 header files。例如使用不同的 ARM 或是 RISC-V toolchain 會有自己的 C library,如果在 x86 的 PC 上面練習 RISC-V 的 C code,對程式碼的 memset
跳躍到定義,會跳到 usr/include/string.h
,顯然這不是真正被宣告的路徑。
上述例子看似沒什麼大不了,toolchain 都應該支援標準的 C headers,那麽如果要在 PC 上練習 ARM 的 neon 指令,VSCode 就會找不到 arm_neon.h
,還是可以 ARM 的 toolchain 編譯,但就是不方便 trace code,下面那 RISC-V 和 Kernel module 為例。
如果要用 RISC-V 的 toolchain 來開發,可以在 .clangd
的 compiler flags 加上 headers 的路徑,改完後重新啟動 clangd,找一個 standard C 函式 goto defination,例如 printf
就會跳到 toolchain 的 stdio.h
,而不是 /usr/include/stdio.h
CompileFlags:
Add: [-I/opt/riscv64-unknown-linux-gnu_1320/sysroot/usr/include]
Remove: -W*
Compiler: riscv64-unknown-linux-gnu-gcc
反之如果要開發 Kernel module 就可以把 -I
改成 usr/src/
底下的 Linux/include,可用 echo 搭配 uname -r
查看 Kernel version
$ echo /usr/src/linux-headers-`uname -r`/include
/usr/src/linux-headers-6.8.0-40-generic/include
把 include 的路徑貼到 .clangd
即可
CompileFlags:
Add: [-I/usr/src/linux-headers-6.8.0-40-generic/include]
Remove: -W*
Compiler: gcc
這樣就可以跳躍到 Kernel 的 headers,寫程式也會跳出 Kernel 函式的提示字
例如下面兩個是 Kernel module 會用到的 header,一般情況下,VSCode 找不到路徑,按上述修改完路徑,就能跳躍過去
#include <linux/printk.h>
#include <linux/slab.h>
如此一來,就算換成開發板提供的 toolchain,只要加入 headers 的路徑到 .clangd
就能夠讓 VSCode 跳躍到實際宣告的 header 或函式的實作。
-static
非必要,且為了讓 box64 能善用 wrapper,應儘量採用動態連結 (即預設編譯組態)。
編譯 x86 的程式要加上 -static
,因為環境從 PC 換到 Tinker-V,板子不一定會有 PC 的函式庫,避免板子找不到函式庫而無法執行。以 rv32emu 的 puzzle.c 為例
> gcc -static puzzle.c -o puzzle_x86
編譯完之後可以存到 SD 卡或是 USB,
可以在板子上用 fdsik -l
來看是 SD 卡的裝置是那一個
掛載 SD card 到 /media
mount -t ext4 /dev/mmcblk1p2 /media
mount -t ext4 /dev/sda /media
卸載
umount /media
如果程式存到 USB 可以透過 micro USB(OTG) 接到板子上再掛載到指定目錄,載入方式和 SD 卡一樣
Note
或許也可以透過某種方式用 wget 來下載程式到板子上就不用每次都要插拔儲存裝置?之前有用過網路線接到板子後可以使用 wget 下載檔案
ifconfig
獲得 inet addr
接著就可以傳輸、刪除檔案,如下圖所示:
也可以使用 ssh 來操控 tinker-v 的終端機
$ ssh root@{inet addr}
Linux PC 可以先將自己的 public key 加入到 Tinker-V 的 ~/.ssh/authorized_keys
,往後複製檔案和連線都不必輸入密碼
Tinker-V 和 PC 都要 SSH key-gen,如果已經 keygen 過的話可以省略
$ ssh-keygen -t ed25519 -b 4096 -C "your_email@example.com"
將 PC 的公鑰內容複製好
$ cat ~/.ssh/OOO.pub
將 PC 端的 SSH 公鑰內容貼入到 Tinker-V 的 authorized_keys
$ vim ~/.ssh/authorized_keys
如果你有多台電腦或板子要連線到 Tinker-V的話,則要將每個公鑰內容一行一行的貼上
vsode 沒辦法用 SSH 連線到 Tinker-V,會出現下面的錯誤訊息,但還是可以在 vscode 的終端機用 ssh 命令來連線,這樣就不必透過 screen 了
Resolver error: Error: The remote host's architecture is not supported
先把 Tinker-V 的公鑰內容複製到 PC 端的 ~/.ssh/authorized_keys
再開啟 PC 的 ssh server 的功能
$ sudo apt-get install openssh-server
$ sudo service ssh start
在 Tinker-V 上面一樣使用 scp 傳檔案到 PC 端,PC 的 IP 地址一樣用 ifconfig
查詢,user 就是 whoami
命令輸出的名稱
$ scp ./msg.txt lambert-wu@{PC inet addr}:~/Documents
Tinker-V 傳完檔案後可以在 PC 的 ~/Documents
目錄確認有沒有 msg.txt
如果開啟 SSH server 不放心的話,可以用下面的命令關掉 ssh service
$ sudo service ssh stop
Stopping 'ssh.service', but its triggering units are still active:
ssh.socket
$ sudo service disable --now ssh.socket
$ systemctl -a | grep ssh
systemctl -a | grep ssh
用來確認 ssh 相關的服務是不是 inactive dead
的狀態
當 box64 和 x86 程式都在 Tinker-V 上面,就可以測試了
>./box64 ./puzzle_x86
目前使用幾個 rv32emu 的 test cases 在 box64 上面執行,大部分沒遇到 crash 問題,但是有些程式會執行很久。
executable 空白欄位表示程式可以執行,但執行時間要很久,沒有完全執行完,先終止掉
program | executable | Note |
---|---|---|
aes | Y | |
donut | Y | |
hamilton | 執行太久,用 time 來測量,到 mapping edges 終止,已達 181m |
|
lena | Y | |
mandelbrot | Y | |
nqueens | Y | 大約 size = 12 後會變慢 |
pi | Y | |
qrcode | Y | |
rvsim | Y | |
stream | ||
captcha | Y | |
fcalc | Y | |
jit | N | segement fault |
line | Y | |
mt19937 | Y | |
nyancat | Y | 中止程式後,畫面會看不到游標,使用 clear 依舊如此,但還是可以打字下命令 |
puzzle | Y | |
richards | ||
spirograph | Y | 會影響到終端機顯示,同 nyancat |
test-path | Y |
推薦先讀 box64 官方的 blog 找幾篇相關的文章來了解 box64 的運作,像是 Inner workings
利用 /usr/bin/time -p 測量 RV64 和 box64 對應的執行時間: (user time)
Benchmark Name | RV64 | x86-64 |
---|---|---|
aes | 3.41 | 482.13 |
dhrystone | 1.05 | 353.21 |
miniz | 9.74 | 1612.67 |
norx | 2.47 | 214.66 |
primes | 16.01 | 678.36 |
qsort | 3.52 | 795.05 |
sha512 | 2.01 | 395.96 |
使用動態連結之後的數據: (user time)
註: 會遇到 sh: relocation error: /lib/custom/libc.so.6: symbol __nptl_set_robust_list_avail version GLIBC_PRIVATE not defined in file ld-linux-riscv64-lp64d.so.1 with link time reference
,但輸出正確,原因待查明
使用動態編譯後:
Benchmark Name | RV64 | x86-64 |
---|---|---|
aes | 4.06 | 8.37 |
dhystone | 1.17 | 33.86 |
miniz | 11.79 | 181.11 |
norx | 2.8 | 4.51 |
primes | 18.54 | 24.82 |
sha512 | 2.25 | 3.97 |
NBench | 206.93 | 211.38 |
Coremark | 16.10 | 22.60 |
whetstonez | 4.16 | 51.87 |
更新後的數據
Dynarec for RISC-V With extension: I M A F D C PageSize:4096 Running on unknown riscv64 cpu with 1 Cores
Will use Hardware counter measured at 12.0 MHz emulating 3.0 GHz
Params database has 14 entries
Box64 with Dynarec v0.3.1 126cf279 built on Nov 1 2024 18:08:42
Benchmark Name | RV64 | x86-64 |
---|---|---|
aes | 3.01 | 6.32 |
dhrystone | 1.17 | 26.39 |
miniz | 9.43 | 145.21 |
norx | 2.23 | 3.38 |
primes | 15.84 | 21.03 |
qsort | 2.97 | 124.39 |
sha512 | 2.00 | 3.20 |
NBench | 205.80 | 209.08 |
Coremark | 9.79 | 9.67 |
whetstonez | 3.38 | 47.42 |
在 Tinker V 上面執行 proprietary x86-64 (closed source) 的程式:
在完全不用 recompile 程式的前提 (事實上,也沒辦法做到,因為沒辦法取得原始程式碼),利用 box64
Tinker V (RV64) 在模擬 x86-64 程式,並利用 X11 forwarding,將視窗操作導向到具備
顯示及輸入的裝置,過程中,proprietary x86-64 的程式沒有任何洩漏的風險,且運行效率尚可,亦即
將 Tinker V 視為 Hardware Security Modules (HSM),換言之,在 Tinker V 上面可執行密碼學
或者涉及特定領域專業之演算法,在最小資訊揭露的前提,進行裝置之間的互動。
TODO: 撰寫 X11 forwarding 原理
TODO: 製作 Hardware Security Modules (HSM) 介紹圖文