2018年12月04日
Xilinx QEMUのWindows版をUbuntu上でクロスビルドする
QEMU の Windows 版のビルド方法は、このブログでも何度も取り上げていますが、QEMU が要求する GLib ライブラリのバージョンが上がり続けているなどの理由により、正常動作する QEMU をビルドできる環境を構築し、QEMU のバージョンアップに追従し続けることが、現状かなり難しくなっています。(少なくとも現在の MSYS2 の GCC 8.2.0 環境でビルドした QEMU は正常動作しません。)
そこで本記事では、QEMU のメンテナの一人であり、長年 Windows 版を開発、バイナリの配布をし続けている Stefan Weil さんがメンテナンスしているビルド環境をお借りして、Ubuntu 18.04 上で Windows 64-bit 版 QEMU をクロスビルドする方法を解説します。
そこで本記事では、QEMU のメンテナの一人であり、長年 Windows 版を開発、バイナリの配布をし続けている Stefan Weil さんがメンテナンスしているビルド環境をお借りして、Ubuntu 18.04 上で Windows 64-bit 版 QEMU をクロスビルドする方法を解説します。
注意:本記事のビルド方法では、APT リストに Stefan Weil さんを信頼できるディストリビューターとして登録し、そこから deb パッケージを apt-get することになります。もちろん Stefan Weil さんは信頼できる方だと思われますが、非公式のパッケージをシステムにインストールすることは、本質的に重大なセキュリティリスクを伴う行為となりますので、重要なデータが含まれるシステムにはインストールせず、ビルド専用の環境か、仮想マシン上にインストールすることを強く推奨します。
〇 ビルド環境の準備
- 公式パッケージのインストール
まずは MinGW-w64 の 64-bit 版をインストールします。ここでは、今回は不要なものもありますが、私が MinGW GCC をビルドする時のパッケージを全部入れます。また、QEMU のビルドに pkg-config が必要なので、mingw-w64-tools も追加しました。
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install build-essential gitk mingw-w64 g++-mingw-w64-i686 autoconf autopoint flex bison gettext texinfo texlive dejagnu ruby zip libxml2-utils dblatex doxygen libncurses5-dev qemu-user-static groff zlib1g-dev autogen mingw-w64-tools- 非公式パッケージのインストール
参考サイト:Packages for Mingw-w64 cross compilation on Debian GNU Linux
Stefan Weil さんの GPG キーを APT システムの信頼リストに追加します。サイトに書いてあるコマンドラインでは上手く行かなかったので、一度ファイルを DL してから追加しました。
$ wget https://qemu.weilnetz.de/debian/gpg.key $ sudo apt-key add gpg.key続いて、APT リストに新規ファイルを追加します。適当なエディタでファイルを作ってください。
$ sudo vi /etc/apt/sources.list.d/cygwin.list deb https://qemu.weilnetz.de/debian/ testing contrib非公式パッケージをインストールします。x86_64 パッケージは /usr/x86_64-w64-mingw32/sys-root/ 以下に展開されるので、公式パッケージとバッティングすることは無いと思います。
参考サイト:QEMU for Windows - Build instructions
$ sudo apt-get update $ sudo apt-get install mingw64-x86-64-curl mingw64-x86-64-gnutls mingw64-x86-64-gtk3 mingw64-x86-64-libxml2 mingw64-x86-64-ncurses mingw64-x86-64-sdl2 mingw64-x86-64-libusb1.0 mingw64-x86-64-usbredir mingw64-x86-64-glib2.0 mingw64-x86-64-pixman ... (省略) ... 以下の追加パッケージがインストールされます: mingw64-x86-64-atk1.0 mingw64-x86-64-bzip2 mingw64-x86-64-cairo mingw64-x86-64-expat mingw64-x86-64-fontconfig mingw64-x86-64-freetype2 mingw64-x86-64-gdk-pixbuf2.0 mingw64-x86-64-gettext mingw64-x86-64-gmp mingw64-x86-64-harfbuzz mingw64-x86-64-jasper mingw64-x86-64-jbigkit mingw64-x86-64-libepoxy mingw64-x86-64-libffi mingw64-x86-64-libgnurx mingw64-x86-64-libidn2 mingw64-x86-64-libjpeg-turbo mingw64-x86-64-libpng mingw64-x86-64-libssh2 mingw64-x86-64-libtasn1 mingw64-x86-64-libunistring mingw64-x86-64-lzo2 mingw64-x86-64-nettle mingw64-x86-64-nghttp2 mingw64-x86-64-openssl mingw64-x86-64-p11-kit mingw64-x86-64-pango1.0 mingw64-x86-64-pcre mingw64-x86-64-tiff mingw64-x86-64-win-iconv mingw64-x86-64-xz mingw64-x86-64-zlib 以下のパッケージが新たにインストールされます: mingw64-x86-64-atk1.0 mingw64-x86-64-bzip2 mingw64-x86-64-cairo mingw64-x86-64-curl mingw64-x86-64-expat mingw64-x86-64-fontconfig mingw64-x86-64-freetype2 mingw64-x86-64-gdk-pixbuf2.0 mingw64-x86-64-gettext mingw64-x86-64-glib2.0 mingw64-x86-64-gmp mingw64-x86-64-gnutls mingw64-x86-64-gtk3 mingw64-x86-64-harfbuzz mingw64-x86-64-jasper mingw64-x86-64-jbigkit mingw64-x86-64-libepoxy mingw64-x86-64-libffi mingw64-x86-64-libgnurx mingw64-x86-64-libidn2 mingw64-x86-64-libjpeg-turbo mingw64-x86-64-libpng mingw64-x86-64-libssh2 mingw64-x86-64-libtasn1 mingw64-x86-64-libunistring mingw64-x86-64-libusb1.0 mingw64-x86-64-libxml2 mingw64-x86-64-lzo2 mingw64-x86-64-ncurses mingw64-x86-64-nettle mingw64-x86-64-nghttp2 mingw64-x86-64-openssl mingw64-x86-64-p11-kit mingw64-x86-64-pango1.0 mingw64-x86-64-pcre mingw64-x86-64-pixman mingw64-x86-64-sdl2 mingw64-x86-64-tiff mingw64-x86-64-usbredir mingw64-x86-64-win-iconv mingw64-x86-64-xz mingw64-x86-64-zlib
これらのファイルは、MinGW GCC が使用するライブラリファイル(データ)であり、何かが実行されるわけではないので、ホスト環境の Ubuntu のバージョンには依存しないはずです。(もともとは cygwin のパッケージだったものを、Stefan Weil さんが cyg2deb というツールで Debian 用に変換して使用しているものを、Ubuntu にインストールしているわけなので、けっこう無茶なことしてます。deb パッケージとか言ってますが Windows のようなインストーラではなく、実体は単なるアーカイブファイルを依存関係をチェックした後に展開しているだけなので問題無いのでしょう。)
〇 QEMU のビルド
公式の QEMU 3.0.0 がビルドでき、動作することも確認済みですが、ここでは Xilinx QEMU をビルドしてみます。(Xilinx QEMU は Yocto/OpenEmbedded で Windows 版がビルドできると公式 wiki で解説されていますが、私が不慣れなせいもあり、いろいろ試してみてもすぐエラーで止まってしまい、どうもよくわかりませんでした…。)
現在最新の SDK である Xilinx SDK 2018.2 に合わせて、tag をチェックアウトしてビルドします。
参考 PDF:Xilinx Quick Emulator User Guide QEMU UG1169(v2018.2) June 6, 2018.PDF
$ mkdir xilinx $ cd xilinx/ $ git clone https://github.com/Xilinx/qemu.git $ cd qemu/ $ git checkout -b xilinx-v2018.2 refs/tags/xilinx-v2018.2 Switched to a new branch 'xilinx-v2018.2' $ git branch master * xilinx-v2018.2 $ cd .. $ mkdir build install $ cd buildprefix は必ず絶対パスで指定してください。(相対パスで指定してしまうと、それぞれの生成物をビルドしたディレクトリからの相対パスにインストールされてしまいます。)
追記: --enable-debug を付けたままでした。最適化無しのデバッグ用バイナリが生成されます。-O2 最適化したリリース用バイナリを作りたい場合はオプションを外してください。デバッグ情報が不要な場合は --disable-strip も外してください。
$ ../qemu/configure --prefix=/home/kmc/xilinx/install --enable-fdt --enable-gtk --enable-sdl --with-sdlabi=2.0 --target-list=aarch64-softmmu,microblazeel-softmmu,arm-softmmu --enable-debug --disable-strip --disable-werror --cross-prefix=x86_64-w64-mingw32- --extra-cflags="-I/usr/x86_64-w64-mingw32/sys-root/mingw/include/" --extra-ldflags="-L/usr/x86_64-w64-mingw32/sys-root/mingw/lib/" Install prefix /home/kmc/xilinx/install BIOS directory /home/kmc/xilinx/install firmware path /home/kmc/xilinx/install/share/qemu-firmware binary directory /home/kmc/xilinx/install library directory /home/kmc/xilinx/install/lib module directory /home/kmc/xilinx/install/lib libexec directory /home/kmc/xilinx/install/libexec include directory /home/kmc/xilinx/install/include config directory /home/kmc/xilinx/install local state directory queried at runtime Windows SDK no Source path /home/kmc/xilinx/qemu GIT binary git GIT submodules ui/keycodemapdb dtc capstone C compiler x86_64-w64-mingw32-gcc Host C compiler cc C++ compiler x86_64-w64-mingw32-g++ Objective-C compiler x86_64-w64-mingw32-gcc ARFLAGS rv CFLAGS -g QEMU_CFLAGS -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1 -I$(SRC_PATH)/dtc/libfdt -DHAS_LIBSSH2_SFTP_FSYNC -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -DNCURSES_WIDECHAR -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506L -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -m64 -mcx16 -mthreads -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/ -Wexpansion-to-defined -Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/p11-kit-1 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/libpng16 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I$(SRC_PATH)/capstone/include LDFLAGS -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m64 -g -L/usr/x86_64-w64-mingw32/sys-root/mingw/lib/ make make install install python python -B smbd /usr/sbin/smbd module support no host CPU x86_64 host big endian no target list aarch64-softmmu microblazeel-softmmu arm-softmmu gprof enabled no sparse enabled no strip binaries no profiler no static build no SDL support yes (2.0.7) GTK support yes (3.22.28) GTK GL support no VTE support no TLS priority NORMAL GNUTLS support yes GNUTLS rnd yes libgcrypt no libgcrypt kdf no nettle yes (3.4) nettle kdf yes libtasn1 yes curses support yes virgl support no curl support yes mingw32 support yes Audio drivers dsound Block whitelist (rw) Block whitelist (ro) VirtFS support no Multipath support no VNC support yes VNC SASL support no VNC JPEG support yes VNC PNG support yes xen support no brlapi support no bluez support no Documentation yes PIE no vde support no netmap support no Linux AIO support no ATTR/XATTR support no Install blobs yes KVM support no HAX support yes TCG support yes TCG debug enabled yes TCG interpreter no RDMA support no fdt support yes preadv support no fdatasync no madvise no posix_madvise no libcap-ng support no vhost-net support no vhost-scsi support no vhost-vsock support no vhost-user support no Trace backends log spice support no rbd support no xfsctl support no smartcard support no libusb yes usb net redir yes OpenGL support no OpenGL dmabufs no libiscsi support no libnfs support no build guest agent yes QGA VSS support no QGA w32 disk info yes QGA MSI support no seccomp support no coroutine backend win32 coroutine pool yes debug stack usage no crypto afalg no GlusterFS support no gcov gcov gcov enabled no TPM support yes libssh2 support yes TPM passthrough no TPM emulator no QOM debugging yes Live block migration yes lzo support yes snappy support no bzip2 support yes NUMA host support no tcmalloc support no jemalloc support no avx2 optimization yes replication support yes VxHS block device no capstone git $ make -j8 $ make install $ ls ../install/ QEMU,cgthree.bin openbios-sparc64 qemu-system-arm.exe QEMU,tcx.bin palcode-clipper qemu-system-armw.exe acpi-dsdt.aml petalogix-ml605.dtb qemu-system-microblazeel.exe bamboo.dtb petalogix-s3adsp1800.dtb qemu-system-microblazeelw.exe bios-256k.bin ppc_rom.bin qemu_logo_no_text.svg bios.bin pxe-e1000.rom qemu_vga.ndrv efi-e1000.rom pxe-eepro100.rom s390-ccw.img efi-e1000e.rom pxe-ne2k_pci.rom s390-netboot.img efi-eepro100.rom pxe-pcnet.rom sgabios.bin efi-ne2k_pci.rom pxe-rtl8139.rom share efi-pcnet.rom pxe-virtio.rom skiboot.lid efi-rtl8139.rom qemu-doc.html slof.bin efi-virtio.rom qemu-doc.txt spapr-rtas.bin efi-vmxnet3.rom qemu-ga.exe trace-events-all keymaps qemu-icon.bmp u-boot.e500 kvmvapic.bin qemu-img.exe vgabios-cirrus.bin linuxboot.bin qemu-io.exe vgabios-qxl.bin linuxboot_dma.bin qemu-qmp-ref.html vgabios-stdvga.bin multiboot.bin qemu-qmp-ref.txt vgabios-virtio.bin openbios-ppc qemu-system-aarch64.exe vgabios-vmware.bin openbios-sparc32 qemu-system-aarch64w.exe vgabios.bin
〇 必要な dll のコピー
今回は以下のクロス MinGW GCC でビルドしたので、Windows 上で exe を実行するためには、対応する dll をコピーする必要があります。
$ x86_64-w64-mingw32-gcc -v Using built-in specs. COLLECT_GCC=x86_64-w64-mingw32-gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/lto-wrapper Target: x86_64-w64-mingw32 Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --with-headers=/usr/x86_64-w64-mingw32/include --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++,ada --enable-lto --with-plugin-ld --enable-threads=win32 --program-suffix=-win32 --program-prefix=x86_64-w64-mingw32- --target=x86_64-w64-mingw32 --with-as=/usr/bin/x86_64-w64-mingw32-as --with-ld=/usr/bin/x86_64-w64-mingw32-ld --enable-libatomic --enable-libstdcxx-filesystem-ts=yes Thread model: win32 gcc version 7.3-win32 20180312 (GCC)
$ cp /usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/*.dll ../install/ $ cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll ../install/ $ cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll ../install/ここまでは Ubuntu Linux 上での作業でしたが、以後の動作確認は Windows のコマンドプロンプト上となります。
samba でファイルを共有し、install ディレクトリを丸ごとコピーしても良いですし、net use で Windows にマウントしても良いです。
以後の例は net use で home を U ドライブにマウントしている状況で実行するので、適宜読み替えてください。
〇 簡単な動作確認
U:\>cd xilinx U:\xilinx>install\qemu-system-aarch64.exe --version QEMU emulator version 2.11.1 (v2.6.0-12948-gf5fb2a88ff-dirty) Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
〇 Xilinx SDK でベアメタルの hello, world をビルドし、動作確認
Xilinx 社のソフトウェア開発キット スタンドアロン WebInstall Client - 2018.2 Lightweight Installer Windows 64 用 SDK 2018.2 ウェブ インストール (EXE - 50.4 MB) をインストールしてください。
ダウンロードとインストールには Xilinx 社のアカウントとパスワード、開発者情報の入力が必要です。
インストールした後、「Xilinx Design Tools > Xilinx SDK 2018.2」を起動し、初期設定をした後、新規 Application プロジェクトを作成します。プロジェクト名を適当に設定し(今回は hello_world)、Hardware Platform を ZCU102_hw_platform に指定する以外は全てデフォルトで構いません。プロジェクトを作成し、eclipse で開けたら、「Build All」でビルドします。できた hello_world.elf を使用し、以下のように起動します。(hello_world.elf の場所は適宜読み替えてください。全てデフォルトで設定していれば、ユーザー名以外は同じはずです。)
U:\xilinx>install\qemu-system-aarch64.exe -nographic -M arm-generic-fdt -dtb c:/Xilinx/SDK/2018.2/data/qemu/zynqMP/SINGLE_ARCH/zcu102-arm.dtb -device loader,file=C:/Users/kmc/workspace/hello_world/Debug/hello_world.elf,cpu-num=0 -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4ちょっと他のエラーも出ていますが、無事に Hello World が UART に出力されました。
dsound: Could not initialize DirectSoundCapture dsound: Reason: No sound driver is available for use, or the given GUID is not a valid DirectSound device ID Hello WorldXilinx QEMU は、バニラの QEMU とはほぼ別物になっていて、ZCU102(AArch64)の場合は Cortex-A53 が 4 コアと、Cortex-R5f が 2 コアの、計 6 コアのヘテロジニアスマルチコア構成がデフォルトになっていて、私は確認してませんが qemu-system-arm や aarch64 の QEMU と、qemu-system-microblazeel をファイルシステム経由で協調動作させる MULT_ARCH 構成もサポートしているそうです。
上記の確認では AArch64 QEMU 単体の SINGLE_ARCH (実機では microblaze で PMU をコントロールするようですが、そこはたぶんオミットされている?)の dtb を使用し、コア 0 のみを有効にして hello_world.elf を実行しています。
マルチコアを活かすプログラムをスクラッチから開発することはあまり現実的ではないので、実用上は RPU(R コアのような Real-time Processing Unit)で RTOS を、APU (A コアのような Application Processing Unit)で Linux を動かすことになりますが、こうしてサクッと(プラットフォームの知識ゼロで)ベアメタルのコードが IDE でビルドできて実機が無くても動作確認できる Xilinx 社の開発環境は素晴らしいですね。(弊社のハードウェアチームや、FPGA に関わるソフトの人たちは普通にずっとバリバリ使ってるようです。私が今まで知らなかっただけ。)
追記: ZCU102 ターゲットの APU 4 コア、RPU 2 コアの 6 コア構成は本家 QEMU にもマージされていました。-machine-path オプションによるマルチアーキテクチャ連携(MULTI_ARCH)機能はマージされていないようです。また、hw/misc/xilinx_zynqmp_* は一切マージされていないようです。ターゲットマシンに arm-generic-fdt を指定し、-hw-dtb (device tree binary) オプションで指定した dtb でエミュレーションする仮想ハードウェアを設定するという Xilinx QEMU の肝となる機能もマージされていません。(非常に紛らわしいですが、-dtb で指定可能な dtb は Linux が使用するブート ROM (BIOS のようなソフトウェア)で、こちらは本家でも使える機能です。)