Closed keigo1216 closed 9 months ago
起動した時には, 実行モードがEL3
なので, 諸々の処理(何が必要?)が終わったらモードをEL2
-> EL1
と順に変更していく
それぞれのモードで別々のスタック領域を使うので, eret
命令でモードを変更する前にスタック領域を確保する(これを忘れると実行が止まってしまう)
NS
=1 : EL3
以外のモードではノンセキュアモードで動作する(信頼しないってこと)ノンセキュアモードからセキュアモードへのメモリへのアクセスはできないRES
SMD
=1 : SMC
命令をOFFRW
=1 : EL2
でAArch64
であることを指定 実行モードはCurrentEL
レジスタの2, 3bit目に書かれている
0
: EL0
ユーザーモード 1
: EL1
カーネルモード2
: EL2
ハイパーバイザーモード(使わない?)3
: EL3
公式レファレンス
https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/CurrentEL--Current-Exception-Level?lang=en可変長引数を取るような関数では, 関数のプロローグでいくつかの浮動小数点レジスタ(q0
, q1
, ...)を退避させる
しかし, デフォルトではそもそも浮動小数点が有効化されていないので, 有効化してあげないと, 突然printf
が動かない謎バグに襲われる
https://github.com/keigo1216/ketchup/blob/92b8d7538b8506268863688bef68b29e52a941c5/kernel/trap.S#L57
ユーザー空間を実装したらesr_el1
に変更する
公式レファレンス
Chapter12に詳しく書いてある https://github.com/keigo1216/ketchup/issues/13#issue-2014404831
例外ハンドラの実装
Armの実行レベル
数字が大きくなるほど, 権限が強くなる(正式には例外レベルと呼ばれているらしい)
例外の種類
主に4つの例外がある
Interrupts
: ハードウェア割り込み,IR
,FIQ
,SError
Exception generating instructions
:システムコールとかReset
:電源を入れた後にCoreをリセットAborts
:メモリの例外とか,MMU
が出してくる例外に関係してくるレジスタ
PSTATE
: 条件フラグとか現在の例外レベルの保存. 例外発生時にSPSR_ELx
(xはその例外が発生した時のレベル)に保存される.LR
: リングレジスタ. サブルーチンからのリターンアドレスを保存するELR
: 例外処理が終了した時にリターンアドレスを保存する例外ベクタの設定
例外が起きた際に呼ばれる関数の先頭アドレスを設定したもの それぞれの実行レベル(EL0, EL1, EL2, EL3)でそれぞれ別の例外ベクタを保持している.それぞれの例外ベクトルのベースアドレスは
VBAR_ELn
(n=0, 1, 2, 3)に格納されている.このベースアドレスからの指定されたオフセットで指定された例外を設定していく例外ハンドラの実装
とりあえず
nested
をしないハンドラを実装する サンプルのアセンブリコードを下に示す(公式のドキュメントから拝借)例外の仕分け
公式ドキュメントの
10.2.6 The Exception Syndrome Register
に詳しく書いてある. また, レジスタの構造は下のURLに書いてある. https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/ESR-EL1--Exception-Syndrome-Register--EL1-参考文献
https://developer.arm.com/documentation/100933/0100/Example-exception-handlers https://valinux.hatenablog.com/entry/20221110 https://logmi.jp/tech/articles/323824