Linuxのブートプロセスを追うときに見るべきファイル(x86_64編)のarm64版のようなもの。
ブートストラップ
linux/Documentation/arm64/booting.txt によると、現在のarm64用カーネルは、x86_64用カーネルが持つようなブートストラップの機能が存在しない。実際、arch/arm64/boot/以下にはx86_64のようなソースコード(head_64.S等)が存在しない。ブートローダがハードウェアの最低限の初期化をして、解凍された生のカーネルイメージ(ELFではない)を配置、エントリポイントにジャンプしてやらないといけない。カーネルに実行を移すときの要件も、booting.txtに書かれている。
ブートローダとしては、ubootやUEFIが使えると思われる。(Boot Wrapperというのも使えるみたいだが、今も使えるかは分からない。)
ブートプロセス
- arch/arm64/kernel/head.S
- エントリポイントは_text
- _textは.head.textセクションの先頭にある
- .head.textセクションはファイル先頭の__HEAD
- すぐにstextへジャンプ
- いろいろ初期化
- ブート引数を待避
- EL2(ハイパーバイザ用の実行モード)からEL1へ落ちる
- eret命令
- __boot_cpu_modeにブートしたときのCPUモードを設定する
- ページテーブルを設定
- 最終的に__cpu_setupへジャンプする
- 戻ってくるアドレスを__enable_mmuにしておく
- 後で使うために、x27に__mmap_switchedのアドレスを入れておく
- arch/arm64/mm/proc.S
- __cpu_setupがある
- MMUをonにするためのCPUの初期化
- SCTLRとかTCRとかTTBRの値を用意する
- 最後にretすると__enable_mmuに飛ぶ
- arch/arm64/kernel/head.S
- __enable_mmuでTTBR0とTTBR1を設定
- SCTLRを設定する
- x27レジスタを使って__mmap_switchedに飛ぶ
- start_kernelに飛ぶ
- init/main.c
- start_kernelがある
Imageのファイル形式
ところで、CONFIG_EFIがyesの場合、自分でビルドしたカーネル(Image)をfileコマンドで見てみると、"MS-DOS executable, MZ for MS-DOS"と判定される。これは、(U)EFIがPE形式(MS-DOS MZ)を必要としているためらしい。そのため、MZヘッダのふりをするために(ファイル先頭が0x5A4Dになるように)、命令の先頭は"add x13, x18, #0x16"という意味のない命令になっている。あと_textの直後(stextの手前)にPEヘッダが用意されている。
そういえばx86_64の方でもarch/x86/boot/header.Sの先頭にそれらしきものがあった気がする。