はじめに
Linux Kernel 5.2 からメインラインに Lima Driver が追加されました。Lima Driver は Mali-400/450 用のオープンソースなカーネルドライバです。この記事では、linux-xlnx v2020.1 (Linux Kernel 5.4 ベース) で Lima Driverを動かす方法を示します。
なお、現時点では実験的に Lima Driver の起動を確認しただけです。その上で動作する Mesa Graphics Library まで動作させたわけではないことに注意してください。
Lima とは
Lima とは Mali-400/450 用のオープンソースなグラフィックドライバです。Lima には、Linux のカーネルドライバである Lima Driver と、Mesa Graphics Library のドライバである Mesa Lima があります。
Fig.1 Lima
Lima に関する詳しい情報は以下の URL を参照してください。
紛らわしいのですが、Lima Driver とは別に Mali Driver というのもあります。Mali Driver は ARM が提供しているオープンソースの Mali Ulgard GPU Kernel Driver です。Mali Driver を使うには ARM の Web ページにアクセスして、エンドユーザーライセンスに同意する必要があります。Ultra96/Ultra96-V2 に Mali Driver を組み込む方法に関しては次の記事を参照してください。
Lima Driver のビルド
Kernel への組み込み
Linux Kernel 5.2 からはメインラインに Lima Driver が組み込まれています。ドライバのソースコードは drivers/gpu/drm/lima にあります。
linux-xlnx v2020.1 は Linux Kernel 5.4 をベースにしているので、Lima Driver が追加されています。しかしUltra96/Ultra96-V2 用に提供されているカーネルコンフィギュレーションファイル(xilinx_zynqmp_defconfig) では Lima Driver が組み込まれません。arch/arm64/configs/xilinx_zynqmp_defconfig に CONFIG_DRM_LIMA=y または CONFIG_DRM_LIMA=m を追加するか、 make menuconfig で Device Drivers > Graphics support > LIMA (DRM support for ARM Mali 400/450 GPU) を選択してください。
Device Tree の設定
linux-xlnx v2020.1 の zynqmp 用の Device Tree には次の記述があります。
:
(中略)
:
gpu: gpu@fd4b0000 {
status = "disabled";
compatible = "arm,mali-400", "arm,mali-utgard";
reg = <0x0 0xfd4b0000 0x0 0x10000>;
interrupt-parent = <&gic>;
interrupts = <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>;
interrupt-names = "IRQGP", "IRQGPMMU", "IRQPP0", "IRQPPMMU0", "IRQPP1", "IRQPPMMU1";
clock-names = "gpu", "gpu_pp0", "gpu_pp1";
power-domains = <&zynqmp_firmware PD_GPU>;
};
:
(後略)
また、Ultra96 用の Device Tree には次の記述があります。
/dts-v1/;
#include "zynqmp.dtsi"
:
(中略)
:
&gpu {
status = "okay";
};
:
(後略)
このことから、Ultra96 では GPU は有効になっているはずです。しかし、このままでは Lima Driver は動きません。実は、上で紹介した Device Tree は、Lima Driver 用ではなく Mali Driver 用だからです。
Device Tree を Lima Driver に対応させるためには、 gpu ノードのinterrupt-names プロパティとclock-names プロパティの値を変更する必要があります。
interrupt-names プロパティ
Mali Driver と Lima Driver では割り込みの名前が異なります。Lima Driver では interrupt-names プロパティを次のようにします。
interrupts = <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>;
interrupt-names = "gp", "gpmmu", "pp0", "ppmmu0", "pp1", "ppmmu1";
;
clock-names プロパティ
Mali Driver と Lima Driver とでは想定してるクロックが異なります。Mali Driver が想定しているクロックは "gpu"、"gpu_pp0"、"gpu_pp1" の3つですが、Lima が想定しているクロックは "bus"、"core" の二つです。
このように名前が異なるだけでなく、想定しているクロックの種類が異なるため、単純にクロックの名前を変えるだけでは「通常は」上手くいきません。「通常なら」 Lima Driver のソースコードレベルで変更が必要です。
しかし、ZynqMP に関しては少しトリッキーですが Device Tree を修正するだけで動かすことが可能です。具体的には次のように "gpu_pp0" を "core" に、"gpu_pp1" を "bus" に変更します。
clock-names = "gpu", "core", "bus";
Lima Driver はまず "bus" の名前を持つクロックを有効にします。しかしこの Device Tree では実質的には "gpu_pp1" のクロックが有効になります。続いて "core" の名前を持つクロックを有効にします。しかし実質的には "gpu_pp0" のクロックが有効になります。
じゃあ "gpu" クロックはどうなるのか? という疑問がわきますが、ZynqMP の場合は問題ありません。というのも ZynqMP では "gpu_pp0"、"gpu_pp1"、"gpu" は階層構造になっていて、"gpu" -> "gpu_pp0"、"gpu" -> "gpu_pp1" のように "gpu" クロック出力は "gpu_pp0" クロックの入力および "gpu_pp1" クロックの入力に接続されています。Linux Kernel のクロックドライバは、あるクロックを有効にしたときに階層にさかのぼって有効にします。したがって、"gpu_pp0" クロックを有効にした時点で "gpu" クロックも有効になります。
Lima Driver の起動
Lima Driver を組み込んだ Linux Kernel を起動すると次のようなログがコンソール(or dmesg)にでます。
shell$ dmesg
:
(中略)
:
[ 7.269921] lima fd4b0000.gpu: IRQ pmu not found
[ 7.274750] lima fd4b0000.gpu: IRQ ppmmu2 not found
[ 7.279683] lima fd4b0000.gpu: IRQ ppmmu3 not found
[ 7.284718] lima fd4b0000.gpu: gp - mali400 version major 1 minor 1
[ 7.291112] lima fd4b0000.gpu: pp0 - mali400 version major 1 minor 1
[ 7.297575] lima fd4b0000.gpu: pp1 - mali400 version major 1 minor 1
[ 7.304059] lima fd4b0000.gpu: IRQ pp2 not found
[ 7.308708] lima fd4b0000.gpu: IRQ pp3 not found
[ 7.313368] lima fd4b0000.gpu: l2 cache 64K, 4-way, 64byte cache line, 128bit external bus
[ 7.330325] lima fd4b0000.gpu: bus rate = 499999995
[ 7.335463] lima fd4b0000.gpu: mod rate = 499999995
[ 7.360178] [drm] Initialized lima 1.0.0 20190217 for fd4b0000.gpu on minor 1
:
(後略)
また、/dev/dri の下に renderD128 が出来ます。
shell$ ls -la /dev/dri
total 0
drwxr-xr-x 3 root root 120 Feb 14 2019 .
drwxr-xr-x 14 root root 13820 Feb 14 2019 ..
drwxr-xr-x 2 root root 100 Feb 14 2019 by-path
crw-rw---- 1 root video 226, 0 Feb 14 2019 card0
crw-rw---- 1 root video 226, 1 Feb 14 2019 card1
crw-rw---- 1 root render 226, 128 Feb 14 2019 renderD128
Lima Driver の問題点
Lima Driver を組み込んだ linux-xlnx v2020.1 を動かしてみましたが、現時点では次の二つの問題が生じました。
- zocl と共存できない
- 再起動に失敗する
zocl と共存できない
zocl は XRT(Xilinx Runtime) のカーネルモジュールです。zocl および XRT に関しては以下の記事を参照してください。
Lima Driver を組み込んだ状態で zocl を組み込むと、zocl のデバイスファイルが /dev/dri/renderD129 になります(renderD128 はすでに lima driver が使っている)。この状態で例えば ZynqMP-XRT-Example-1-Ultra96 のサンプルプログラムを起動しようとすると次のようにデバイスが見つからないと言われます。
shell$ ./streaming_lap_filter5.exe streaming_lap_filter5.xclbin
Using FPGA binary file specfied through the command line: streaming_lap_filter5.xclbin
XRT build version: 2.6.0
Build hash: 7104cc336e010e3e0755264ff832d811ff605e2c
Build date: 2020-03-24 21:07:36
Git branch: 2019.2_Ultra96
PID: 610
UID: 1000
[Tue Jun 23 10:12:10 2020]
HOST: debian-fpga
EXE: /home/fpga/examples/ZynqMP-FPGA-XRT-Example-1-Ultra96/streaming_lap_filter5.exe
[XRT] ERROR: No devices found
../src/krnl_streaming_lap_host3.cpp:71 Error calling err = cl::Platform::get(&platforms), error code is: -1
どうやら /dev/dri/renderD128 が zocl に割り当てられてないとうまく動かないようです。試しに lima driver を rmmod してから zocl をロードして /dev/dri/renderD128 を zocl に割り当てると正常に動作しました。
再起動に失敗する
一度 Lima Driver を rmmod してから modprobe で再起動しようとすると、次のようなログがでて再起動に失敗します。
shell$ dmesg
:
(中略)
:
[ 1758.651570] lima fd4b0000.gpu: IRQ pmu not found
[ 1758.656223] lima fd4b0000.gpu: mmu gpmmu dte write test fail
[ 1758.662084] lima: probe of fd4b0000.gpu failed with error -5
この件に関しては現在保留中です。
最後に
筆者は Ultra96/Ultra96-V2(ZynqMP) 向けに Debian GNU/Linux を提供しています1。しかし、現時点では前節で述べた問題があったので Lima Driver を組み込んでいません。これらの問題が解決し次第、Lima を組み込む予定です。何かいいアイデアを募集しています。