Created
September 17, 2011 02:25
-
-
Save poutyface/1223553 to your computer and use it in GitHub Desktop.
QEMU: 仮想ボード ARM Cortex-A9 マルチコアで Linux を動かす
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
モチベーション | |
--------------- | |
Androidのエミュレータは中でQEMUを使ってる | |
中で使われているので、Android開発とは直接関係がないけど、 | |
素のQEMUの使い方を知る。 | |
* QEMUの使い方を覚える | |
* Linuxをエミュレータ環境で動かしてみる | |
* ARM のクロス環境に慣れてみる | |
* ARM はマルチコア | |
環境 | |
----- | |
Linux 2.6.38-11-generic Ubuntu SMP | |
kernel-v2.6.39 | |
QEMU emulator version 0.14.0 (qemu-kvm-0.14.0) | |
linux kernelをコンパイル | |
------------------------- | |
$ cd kernel-v2.6.39 | |
$ export ARCH=arm | |
$ export CROSS_COMPILE=arm-none-linux-gnueabi- | |
クロス環境のツールチェインはCodeSourceryのツールチェインを使用する | |
https://sourcery.mentor.com/sgpp/lite/arm/portal/subscription?@template=lite | |
target OS GNU/LinuxをダウンロードしてbinにPATHを通す. | |
$ make realview_smp-defconfig | |
ターゲット向けのコンフィグレーションファイルを作る。 | |
あらかじめ用意されているコンフィグレーションがあるので(XXX-defconfig)を | |
それを指定する. 今回はSMPなので realview_smp-defconfigを指定. | |
ターゲットのコンフィグレーションファイルの種類はARMの場合,arch/arm/configsで確認できる。 | |
$ make menuconfig | |
ARMv7アーキテクチャに設定する、またCortex-A9を使用する. | |
* loadable module support [disabled] | |
* Platform Baseboard for ARM11 [disabled] | |
* Support ARM ARMv6 [disabled] | |
* PBX A9 and ARMv7 [enabled] | |
-> Support RealView(R) Emulation Baseboard | |
-> Support Multicore Cortex-A9 Tile | |
* Support RealView(R) Platform Baseboard Explore [enabled] | |
* CONFIG_REALVIEW_HIGHT_PHYS_OFFSET [disabled] | |
RealView platform type | |
-> Hight physical base address for the RealView platform | |
* EABI(allowing also old ABI) SupportがEnabledになっているかを確認すること | |
これはCodeSourcery toolchainでコンパイルするので必要 | |
** Network device support | |
-> Network Ethernet (10 or 100Mbit) | |
->SMSC LAN911X [disabled] | |
qemu-0.14.0でハードフェアエラーがでるためdisabledにする | |
ビルドが成功するとarch/arm/boot/zImageにカーネルイメージが出来上がる | |
このカーネルイメージはQemuで実行することができる | |
Kernel の起動を確認する | |
------------------------ | |
シングルコアでの起動を確認 | |
qemu-system-arm -M realview-pbx-a9 -m 128M -kernel kernel-v2.6.39/arch/arm/boot/zImage -nographic -append "console=ttyAMA0 mem=128M" | |
マルチコアでの起動を確認 | |
qemu-system-arm -M realview-pbx-a9 -m 128M -kernel kernel-v2.6.39/arch/arm/boot/zImage -nographic -smp 2 -append "console=ttyAMA0 mem=128M" | |
initrd(ルートファイルシステム)を指定していないので、途中でエラーになるのが正しい | |
-M : 仮想ボードのモデル名 | |
-m : メモリ容量 | |
-kernel : linux kernelのイメージ | |
-nographic : windowでなくconsoleで | |
-append : カーネル起動パラメータを指定する | |
-smp : CPUコアの数 | |
Note: | |
モデル名は qemu-system-arm -M ? でリストが表示される | |
QEMUを抜けるには Ctrl-A, x を順番にタイプする。 | |
確認用のinitrdの作成 | |
--------------------- | |
確認のためにinitrdを作成し、正しく起動するかを確認してみる | |
普通のlinuxであると、ルートファイルシステムはさまざまなディレクトリ(/bin, /etc, /usr等) がある | |
が、これは後回しで、簡単なプログラムを1つ作成して、1ファイルを含むだけのinitrdを作ってみる. | |
-- test.c | |
#include <stdio.h> | |
void main() | |
{ | |
printf("Welcome world\n"); | |
while(1); | |
} | |
---- | |
Note: | |
while(1) でループしているのは、linuxがこのプログラムを初めに動かすので、プログラムを | |
終了させないため | |
$ arm-none-linux-gnueabi-gcc -static test.c -o test | |
$ echo test | cpio -o --format=newc > rootfs | |
$ qemu-system-arm -M realview-pbx-a9 -m 128M -kernel kernel-v2.6.39/arch/arm/boot/zImage -nographic -initrd rootfs -smp 2 -append "root=/dev/ram rdinit=/test console=ttyAMA0 mem=128M" | |
Note: | |
cpioはfilesystemを作るのに使われる。cpioはファイルのリストを入力しアーカイブを出力する。 | |
formatにnewcを指定するとinitramfs形式のフォーマット。 | |
いま作成したrootfsはtestバイナリファイルを1つ含んだファイルシステムイメージで、これを | |
QEMUのinitrdパラメータに渡すことができる。 | |
-initrd でinitrd を指定する | |
-append でrdinit=に初めに実行するプログラムを指定できる | |
上手く動いていれば "Welcom world" が最後に出力される。 | |
BusyBoxを使用してツールを作成する, initrdも作成 | |
------------------------------------------------ | |
上記でlinuxは起動できたが、いろいろツールが足りないので、BusyBoxでターゲット用の | |
各種ツール群を作成する。 | |
BusyBoxはコンパクトなファイルシステムを必要とする組み込みlinuxでよくつかわれる、 | |
さまざまなシステムユーティリティを提供する。 | |
busybox-1.19.2 | |
http://www.busybox.net/ | |
$ export ARCH=arm | |
$ export CROSS_COMPILE=arm-none-linux-gnueabi- | |
$ make defconfig | |
$ make menuconfig | |
デフォルトのコンフィグレーションではかなりの数のツールが選択されているので、ほしいものだけ | |
をチェックする。コンパイル途中でエラーがでたら素直に外すのが吉 | |
$ make install | |
ビルドが成功すると _install/ にルートファイルシステムのツリーが生成される。 | |
これらを前回の"Welcome world"と同じように、cpioツールを使用してlinuxのルートファイル | |
システムイメージを作ると出来上がり。 | |
$ cd _install | |
$ find . | cpio -o --format=newc > ../rootfs.img | |
$ cd .. | |
$ gzip -c rootfs.img > rootfs.img.gz | |
$ qemu-system-arm -M realview-pbx-a9 -m 128M -kernel kernel-v2.6.39/arch/arm/boot/zImage -nographic -initrd rootfs.img.gz -smp 2 -append "root=/dev/ram rdinit=/bin/sh console=ttyAMA0 mem=128M" | |
rdinit=で/bin/shを指定しているのでシェルが立ち上がる。ls, pwd等のコマンドが使えるようになっている。 | |
一方今のままでは、psコマンドが使えない。これは特殊なファイルシステムが/procが必要なので作成する必要がある。 | |
$ mkdir /proc | |
$ mount -t proc none /proc | |
また、/devがconsoleデバイスを除いて、空っぽである。こちらも特殊なファイルシステム/sysを作成する | |
$ mkdir /sys | |
$ mount -t sysfs none /sys | |
$ mdev -s | |
これらのマウント処理は通常、起動時に/sbin/initにさせることができる。 | |
/sbin/initは通常linux kernelによって最初に起動されるプログラムである。 | |
initに何かをさせるには/etc/init.d/rcSに記述する。 | |
なのでBusyBoxで_installを作成したあとに各種設定ファイルを追加して、cpio -> gzip でinitrdを作れば | |
いいだろう | |
$ cd _install | |
$ mkdir proc sys dev etc etc/init.d | |
$ cd .. | |
-- _install/etc/init.d/rcS | |
#!/bin/sh | |
mount -t proc none /porc | |
mount -t sysfs none /sys | |
/sbin/mdev -s | |
--- | |
$ chmod +x _install/etc/init.d/rcS | |
この内容で、またrootfs.img.gzを作成 | |
今回は、rdinit=/sbin/initを指定する | |
$ qemu-system-arm -M realview-pbx-a9 -m 128M -kernel kernel-v2.6.39/arch/arm/boot/zImage -nographic -initrd rootfs.img.gz -smp 2 -append "root=/dev/ram rdinit=/sbin/init Console=ttyAMA0 mem=128M" | |
appendix | |
--------- | |
QEMUでは-kernelオプションに渡されたバイナリファイルを0x00010000にロードする。 | |
エミュレータは0x00000000番地からスタートするが、ここには予めいくつかのインストラクションが | |
含まれており、最終的に0x00010000にジャンプするようになっている。このことから | |
あるプログラムをQEMU上で単に実行するには、0x00010000でリンクされたバイナリを作成することで | |
実行できる | |
startup.o | |
------------ | |
.global _Reset | |
_Reset: | |
LDR sp, =stack_top | |
BR c_entry | |
B . | |
test.ld | |
-------- | |
ENTRY(_Reset) | |
SECTIONS | |
{ | |
. = 0x10000; | |
.startup . : { startup.o(.text) } | |
.text : { *(.text) } | |
.data : { *(.data) } | |
.bss : { *(.bss) } | |
. = . + 0x1000; | |
stack_top = .; | |
} | |
----- | |
$ arm-none-eabi-as -mcpu=arm926ej-s -g startup.s -o startup.o | |
$ arm-none-eabi-gcc -c -mcpu=arm926ej-s -g test.c -o test.o | |
$ arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf | |
$ arm-none-eabi-objcopy -O binary test.elf test.bin | |
----- | |
arch/arm/mach-<mach>/Makefile.boot | |
zreladdr: head.SがRAMにzImageを展開したあとのKernelのスタートアドレス |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment