Linux

Linux/arm64のブートプロセスについてのメモ

More than 3 years have passed since last update.

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の先頭にそれらしきものがあった気がする。

参考文献