[QEMU] Hello world on QEMU

QEMU で Hello world を動かす試みは探してみるといくつか実施されています。

いずれも versatilepb モデルで実施されているので、vexpress や virt でもできるかどうか試してみました。toolchain は Linaro toolchain を使いましたが、外部関数を呼び出さないので baremetal toolchain でなくても使えます。

プログラムソース init.c、スタートコード startup.s、リンカスクリプト link.ld を用意します。

init.c は “Hello, world!” を一文字ずつ UART I/O に書き込むだけのプログラムです。

/* init.c */
static void print(const char *str)
{
	while (*str)
		*(volatile unsigned char *)UART0_PTR = *str++;
}
int init()
{
	print("Hello, world!\n");
}

link.ld は外部定義された START からセクション定義を行います。スタックを 0x800 byte 分空けて スタックポインタの開始位置 sp_top を定義します。

/* link.ld */
ENTRY(_start)
SECTIONS {
	. = START;
	startup : { startup.o(.text)}
	.data   : {*(.data)}
	.bss    : {*(.bss)}
	. = . + 0x800;
	sp_top = .;

vexpress(aarch32) の場合

aarch32 とaarch64 で命令体系が変わるので、startup.s はそれぞれのものを用意します。aarch32 向けはスタックポインタに直接 sp_top を設定して init 関数を呼び出します。最後は無限ループです。

/* startup.s */
	.global _start
_start:
	ldr	sp,=sp_top
	bl	init
	b	.

vexpress-a9 モデルの場合のビルド・実行例です。UART0 I/O と SDRAM がモデルで異なるので、コマンドラインで設定しています。

$ arm-linux-gnueabihf-as  -mcpu=cortex-a9 -o startup.o startup.s
$ arm-linux-gnueabihf-gcc -mcpu=cortex-a9 -c init.c -DUART0_PTR=0x10009000
$ arm-linux-gnueabihf-ld -T link.ld -defsym START=0x60010000 -o output.elf startup.o init.o
$ arm-linux-gnueabihf-objcopy -O binary output.elf output.bin
$ qemu-system-aarch64 -M vexpress-a9 -cpu cortex-a9 -nographic -kernel output.bin
Hello, world!

vexpress-a15 モデルの場合は以下のようにします。

$ arm-linux-gnueabihf-as  -mcpu=cortex-a15 -o startup.o startup.s
$ arm-linux-gnueabihf-gcc -mcpu=cortex-a15 -c init.c -DUART0_PTR=0x1c090000
$ arm-linux-gnueabihf-ld -T link.ld -defsym START=0x80010000 -o output.elf startup.o init.o
$ arm-linux-gnueabihf-objcopy -O binary output.elf output.bin
$ qemu-system-aarch64 -M vexpress-a15 -cpu cortex-a15 -nographic -kernel output.bin
Hello, world!

virt(aarch64) の場合

aarch64 向けのスタートコード startup64.s を用意します。sp は直接代入できないので、x0 を間接的に使います。

/* startup64.s */
	.global _start
_start:
	ldr	x0,=sp_top
	mov	sp,x0
	bl	init
	b	.

virt モデルの場合の実行例です。toolchain は aarch64 のものを使います。

$ aarch64-linux-gnu-as -mcpu=cortex-a53 startup64.s
$ aarch64-linux-gnu-gcc -mcpu=cortex-a53 -DUART0_PTR=0x09000000 -c init.c
$ aarch64-linux-gnu-ld -T link.ld -o output.elf startup64.o init.o
$ aarch64-linux-gnu-objcopy -O binary output.elf output.bin
$ qemu-system-aarch64 -M vexpress-a53 -cpu cortex-a53 -nographic -kernel output.bin
Hello, world!

上記のソースは Makefile を使う形で github に置く予定です。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です