TOPPERS/FMPをqemu-system-arm -M vexpress-a9で動かす

pkgsrc/cross/arm-none-eabi-binutilsとarm-none-eabi-gcc5と言うパッケージを作っていて、これらが正しいバイナリーを生成してくれるか試したいと思っていた。
と同時に、一度リアルタイムオペレーティングシステムと言うのを試してみたいとも思っていた。
そこで、arm-none-eabi-*を使ってビルドすることになっているTOPPERS kernelを試してみることにした。ビルドしたら、そのバイナリーが正しく動作するか確認しないといけない。私はRaspberry PiとCubieboard 2を持っているのだが、TOPPERS/JSP、TOPPERS/ASP、TOPPERS/FMPともに、これらのボードには移植されていないようである。
Skyeye のARMエミュレーション用に移植されているのだが、どうやらCodeSourcery Liteが必要らしく、CodeSourcery Liteは既に無料で配布されていないし、それをNetBSDで動かすのも面倒に違いないので、Skyeye用は試すこともしなかった。
エミュレーターと言えばqemuと思って検索してみると、TOPPERS/FMP kernelは、qemu 1.3.0にパッチを当てたものに移植されているらしい。
https://www.toppers.jp/fmp-e-download.html
に、QEMU Versatile Express Cortex-A9 (4 cores)簡易パッケージとして、TOPPERS/FMP 1.2.2が掲載されている。
TOPPERS/FMPの最新版は1.3.0なので、最新版でないのは少し引っかかるが、試してみることにした。

まず、TOPPERS新世代カーネル用コンフィギュレーターと言うものをビルドしないといけないらしい。

https://www.toppers.jp/cfg-download.html

によると、最新版は1.9.4なので、それを試してみることにした。
Makefile中でGNU makeをmakeとして呼んでいるので、そこを$(MAKE)に変更すれば、NetBSD/amd64 currentでも他には修正は必要ない。
パッチは、

https://www.toppers.jp/TOPPERS-USERS/2015-October/004251.html

に投稿しておいた。
pkgsrcからboostをインストールしてある場合には、以下のようにしたら良い。
$ tar zxvf cfg-1.9.4.tar.gz
$ cd cfg
$ ./configure --with-libraries=/usr/pkg/lib --with-headers=/usr/pkg/include
$ patch < diff
$ gmake LDFLAGS=-Wl,-R/usr/pkg/lib

$ tar zxvf fmp_vexpressa9_gcc-20121214.tar.gz
$ cd fmp
$ cp ../cfg/cfg cfg/
$ mkdir build
$ perl ../configure -g ../cfg/cfg/cfg -T vexpressa9_gcc
$ PATH=/usr/pkg/cross-arm-none-eabi/bin:${PATH} gmake ENABLE_G_SYSLOG=false PRC_NUM=4 KERNEL_FUNCOBJS=

fmpというのが、kernelとサンプルアプリケーションが含まれたものになるので、それを実行してみる。

$ qemu-system-arm -cpu cortex-a9 -M vexpress-a9 -smp 4 -serial vc:80Cx40C -serial vc:80Cx40C -serial vc:80Cx40C -serial vc:80Cx40C -no-reboot -icount auto -m 1024M

表示されたGUIの画面で、Ctrl+Alt+4から7を入力することで、タイマー動いているのを確認することができる。
これには、qemu 1.3.0にパッチを当てたものを使用したのだが、qemu 2.4.0.1に替えてみると、タイマーが動き出さず、しばらくしたらメインメモリーアクセスの違反でcore dumpしてしまう。

qemu: fatal: Trying to execute code outside RAM or ROM at 0x04000000

このエラーメッセージで検索してみると、
http://blog.3mdeb.com/2014/08/07/debugging-coreboot-for-qemu-armv7-vexpress-a9-emulated-mainboard/
で同じ問題が解析されている。
私の場合はどうかとqemuで、実行している命令をダンプしてみると、以下のようになっている。-d in_asmをqemu-system-armの引数として加えると、実行している命令をディスアセンブルして表示できる。
----------------
IN:
0x6000591c:  e5901014      ldr  r1, [r0, #20]
0x60005920:  e5801010      str  r1, [r0, #16]
0x60005924:  e3510000      cmp  r1, #0  ; 0x0
0x60005928:  0a000001      beq  0x60005934

----------------
IN:
0x6000592c:  e591d018      ldr  sp, [r1, #24]
0x60005930:  e591f01c      ldr  pc, [r1, #28]

----------------
IN:
0x60005984:  e32ff013      msr  CPSR_fsxc, #19  ; 0x13

----------------
IN:
0x00000018:  00000000      andeq        r0, r0, r0
0x0000001c:  00000000      andeq        r0, r0, r0

(snip)

0x03fffff8:  00000000      andeq        r0, r0, r0
0x03fffffc:  00000000      andeq        r0, r0, r0

qemu: fatal: Trying to execute code outside RAM or ROM at 0x04000000

R00=6004d314 R01=6004e15c R02=00000001 R03=6004d314
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=60033994
R12=600000d3 R13=00000000 R14=6000598c R15=04000000
PSR=00000192 ---- A irq32
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
s22=00000000 s23=00000000 d11=0000000000000000
s24=00000000 s25=00000000 d12=0000000000000000
s26=00000000 s27=00000000 d13=0000000000000000
s28=00000000 s29=00000000 d14=0000000000000000
s30=00000000 s31=00000000 d15=0000000000000000
s32=00000000 s33=00000000 d16=0000000000000000
s34=00000000 s35=00000000 d17=0000000000000000
s36=00000000 s37=00000000 d18=0000000000000000
s38=00000000 s39=00000000 d19=0000000000000000
s40=00000000 s41=00000000 d20=0000000000000000
s42=00000000 s43=00000000 d21=0000000000000000
s44=00000000 s45=00000000 d22=0000000000000000
s46=00000000 s47=00000000 d23=0000000000000000
s48=00000000 s49=00000000 d24=0000000000000000
s50=00000000 s51=00000000 d25=0000000000000000
s52=00000000 s53=00000000 d26=0000000000000000
s54=00000000 s55=00000000 d27=0000000000000000
s56=00000000 s57=00000000 d28=0000000000000000
s58=00000000 s59=00000000 d29=0000000000000000
s60=00000000 s61=00000000 d30=0000000000000000
s62=00000000 s63=00000000 d31=0000000000000000
FPSCR: 00000000

どうやら、アドレス0x000000018に何らかの理由でジャンプしたらそこが0で埋められていて、それを順々に実行して、0x04000000に到達してエラーでcore dumpしていることが分かった。
では、0x000000018に何があるのかと言うと、0x60000018がマッピングされていることが想定されていて、irq_vectorと言うのがあると期待されている。これは、
$ arm-none-eabi-objdump -D fmp
fmp:     file format elf32-littlearm


Disassembly of section .text:

60000000 <__text>:
60000000:       e59ff018        ldr     pc, [pc, #24]   ; 60000020 <_kernel_vector_ref_tbl>
60000004:       e59ff018        ldr     pc, [pc, #24]   ; 60000024 <undef_vector>
60000008:       e59ff018        ldr     pc, [pc, #24]   ; 60000028 <swi_vector>
6000000c:       e59ff018        ldr     pc, [pc, #24]   ; 6000002c <prefech_vector>
60000010:       e59ff018        ldr     pc, [pc, #24]   ; 60000030 <data_abort_vector>
60000014:       e59ff004        ldr     pc, [pc, #4]    ; 60000020 <_kernel_vector_ref_tbl>
60000018:       e59ff014        ldr     pc, [pc, #20]   ; 60000034 <irq_vector>
6000001c:       e59ff014        ldr     pc, [pc, #20]   ; 60000038 <fiq_vector>

60000020 <_kernel_vector_ref_tbl>:
60000020:       6000003c        andvs   r0, r0, ip, lsr r0

60000024 <undef_vector>:
60000024:       60003c68        andvs   r3, r0, r8, ror #24
(snip)

で確認することができる。

さきほどのウェブサイトによると、

http://git.qemu.org/?p=qemu.git;a=commit;h=6ec1588e09770ac7e9c60194faff6101111fc7f0

によって、0x60000000が0x00000000にマッピングされなくなっているらしい。
そう言うことであれば、割込みベクターの位置を0x60000000にすれば良いと考えられる。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0388fj/CIHGDDEI.html

にあるVBARレジスターを0x6000000に設定すれば良いように見える。

vexpressa9_gccターゲットをTOPPERS/FMP 1.3.0に移植し、qemu 2.4.0.1で動くようにしたソースコードを、

https://github.com/ryo-on/toppers-fmp-for-qemu-vexpress-a9

に置いておいた。
しかし、VBARの部分は、移植性を無視した形になっているので、他の方法を考えないといけないように思う。

とりあえず、pkgsrc/cross/arm-none-eabi-*が正しいバイナリーを生成していそうであるのは確認できたので良いことにする。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

plgarc/wip/llama.cppでpkgsrcのBLASサポートを探る

この記事は、 NetBSD Advent Calendar 2024 の13日目の記事です。 llama.cppを使ってみる 以前に、 NetBSD/amd64でllama.cppを使ってみる という記事で llama.cpp を使ってみていました。 あれか...