qemu-arm を使う

qemu で ARM や MicroBlaze のエミュレーションが出来るそうなので、インストールして使ってみた。

インストールは configure, make するだけ。

$ wget http://download.savannah.gnu.org/releases/qemu/qemu-0.14.1.tar.gz
$ tar xvfz qemu-0.14.1.tar.gz
$ mkdir build
$ cd build
$ ../qemu-0.14.1/configure

Error: zlib check failed
Make sure to have the zlib libs and headers installed.

zlib.h が無いとコンパイルが通らないことがわかったので、

$ sudo apt-get install zlib1g-dev

で zlib をインストール。
そのまま、

$ make
$ make install

で、/usr/local/bin/qemu-* がインストールされる。


インストールされたら、arm 用 gccコンパイル・リンクした hello world を動かしてみる。ダイナミックリンクにするかスタティックリンクにするかで、qemu 上での動かし方が変わる。まずはスタティックリンクの場合:

$ arm-none-linux-gnueabi-gcc -o arm_static -static hello.c
$ file ./arm_static
./arm_static: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.
6.16, statically linked, not stripped
$ qemu-arm arm_static
hello, world

ちゃんと動いた。

ダイナミックリンクしたプログラムを動かすには、-L でライブラリの場所を指定しなければならない。
引数に -L を入れない場合は以下のようにエラーになる:

$ arm-none-linux-gnueabi-gcc -o arm_dynamic hello.c
$ file ./arm_dynamic
./arm_dynamic: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2
.6.16, dynamically linked (uses shared libs), not stripped
$ qemu-arm arm_dynamic
/lib/ld-linux.so.3: No such file or directory

引数に -L を入れると、

$ qemu-arm -L /usr/local/arm-2010q1/arm-none-linux-gnueabi/libc/ arm_dynamic
hello, world

ちゃんと動いた。

MicroBlaze の場合は以下のようになる:

$ mb-linux-gcc -o mb hello.c
$ qemu-microblaze -L /opt/xilinx/microblaze-unknown-linux-gnu/microblaze-unknow
n-linux-gnu/ mb
hello, world

引数 -L のオプションは一つしか指定出来ないようだ。自分でクロスコンパイルしたライブラリをロードさせるには、仕方がないので gnutools のライブラリと、自分でコンパイルしたライブラリを一つのディレクトリにコピーするなりして動作確認を行った。


qemuコンパイル時の追記で、
最新版の qemuコンパイルする場合、カーネルのバージョンが古いと普通に configure しただけではコンパイルが通らないことがある。
qemu は configure で、eventfd の有無をチェックしているが、カーネルの eventfd のバージョンが qemu 0.14 の期待しているバージョンより古く、かつ configure では eventfd のバージョンのチェックなどしないので、configure が通ってもコンパイルエラーが発生する問題があった。
エラー内容は、EFD_NONBLOCK が無い、というコンパイルエラーである。
カーネルが新しいと、linux/eventfd.h に EFD_NONBLOCK が定義されてる。
configure のオプションで eventfd を使わなくするような回避方法があれば良いのだが、調べたところ、そのような機能を configure は提供していないことがわかった。
無理やり configure を編集して make した:

$ diff -U 14 configure.org configure
--- configure.org       2011-06-15 09:11:39.000000000 +0900
+++ configure   2011-06-15 09:11:29.000000000 +0900
@@ -2062,28 +2062,29 @@
 # check if eventfd is supported
 eventfd=no
 cat > $TMPC << EOF
 #include <sys/eventfd.h>

 int main(void)
 {
     int efd = eventfd(0, 0);
     return 0;
 }
 EOF
 if compile_prog "" "" ; then
   eventfd=yes
 fi
+eventfd=no