Jetson nanoでx86_64のdockerイメージを動かす
クロスのdockerイメージを動かすにはLinuxカーネルのbinfmt_miscのしくみとstatic linkされたqemuを使用します。
Oracle Cloudのarm64のインスタンスでは特に問題なくできました。
同じことをjetson nano でやってみたらうまくいかない。
warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
というメッセージが連発して、dpkgやaptが異常終了してしまいます。
このメッセージで検索すると以下の記事がヒットしました。全く同じ状況です。
私が過去に書いた記事が引用されていました。活用してくれるのは嬉しいものです。
この記事ではさて、同じことがOracle Cloudではできて、jetson nanoではできないのはなぜなのか気になります。
両者のcpuinfoを比べてみます。
$ cat /proc/cpuinfo
...
processor : 3
BogoMIPS : 50.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part : 0xd0c
CPU revision : 1
$ cat /proc/cpuinfo
...
processor : 1
model name : ARMv8 Processor rev 1 (v8l)
BogoMIPS : 38.40
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part : 0xd07
CPU revision : 1
jetson nanoの方はFeatures
の項目がかなり少ないです。arm64の初期型のためです。
cpuid
というのが気になります。これでいろいろ検索してみるとx86_64にはCPUID
という命令があり、これで現在実行中のCPUコアを識別することができます。これと同等のことをarm64でやるのはMultiprocessor Affinity Register (MPIDR_EL1)
を読むことでできます。しかし、jetson nanoのCPUではこのレジスタはユーザーモード(EL0)からは読むことができず、getcpu
というLinuxカーネルのシステムコールを呼ぶことで同等のことが実現できます。一方、 OracleのCPUではこのレジスタをユーザーモードから読むことができるようになっています。/proc/cpuinfo
のFeatures
のcpuid
がこれを示しています。
warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
このメッセージの意味はCPUIDがユーザーモードから読めないということを訴えているようです。
でもそれは、qemuがgetcpu
のシステムコールを呼ぶようなコードを生成すればいけるはずです。
jetson nanoで使用していたqemuのバージョンは
$ /usr/bin/qemu-x86_64-static --version
qemu-x86_64 version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.39)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
最新のqemuは7.0.0なので、だいぶ古いものでした。
というわけで、新しいものをソースからビルドして差し替えてみました。その方法はこの記事に書きました。
その結果、問題は解消しました!
ブラボー!!
ただし、その実行速度はひどいもので全く実用にはなりません。計測していませんが、Oracleのものより10倍のオーダーで遅いです。
追記 2022.4.29
qemu 7.0.0はメジャーバージョンアップの最初のものなので、安定性にやや難があるようでした。
qemu 6.2.0に差し替えたら安定して動作しました。
Discussion