keigo1216 / ketchup

raspberrypi 3A+用のOS
1 stars 0 forks source link

implement exception handler #12

Closed keigo1216 closed 9 months ago

keigo1216 commented 9 months ago

公式レファレンス

Chapter12に詳しく書いてある https://github.com/keigo1216/ketchup/issues/13#issue-2014404831

例外ハンドラの実装

Armの実行レベル

数字が大きくなるほど, 権限が強くなる(正式には例外レベルと呼ばれているらしい)

例外の種類

主に4つの例外がある

例外に関係してくるレジスタ

例外ベクタの設定

例外が起きた際に呼ばれる関数の先頭アドレスを設定したもの それぞれの実行レベル(EL0, EL1, EL2, EL3)でそれぞれ別の例外ベクタを保持している.それぞれの例外ベクトルのベースアドレスはVBAR_ELn(n=0, 1, 2, 3)に格納されている.このベースアドレスからの指定されたオフセットで指定された例外を設定していく

address | Exception type | Description
VBAR_ELn + 0x000 | Synchronous 
+ 0x080 | IRQ/vIRQ
+ 0x100 | FIQ/vFIQ
+ 0x180 | SError/vSError
+ 0x200 | Synchronous |
...

例外ハンドラの実装

とりあえずnestedをしないハンドラを実装する サンプルのアセンブリコードを下に示す(公式のドキュメントから拝借)

ASM_IRQ_Handler:
        ; Stack all corruptible registers          // 
        STP X0, X1, [SP, #-16]!                 // save PCS corruptible
        STP X2, X3, [SP, #-16]!                 // interrupts
        ... 
        BL      identify_and_clear_source
        BL      C_IRQ_Handler

        ; Restore corruptible registers
        ...
        LDP X2, X3, [SP], #16                           // Restore PCS corruptible
        LDP X0, X1, [SP], #16                           // interrupts

        ; Return from exception                     //
        ERET    

例外の仕分け

公式ドキュメントの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

keigo1216 commented 9 months ago

エラーハンドリングに関して詳しそうな公式ぺーじ https://developer.arm.com/documentation/100933/0100/AArch64-Exception-and-Interrupt-Handling?lang=en

keigo1216 commented 9 months ago

ブート処理

実行モードの変更

起動した時には, 実行モードがEL3なので, 諸々の処理(何が必要?)が終わったらモードをEL2 -> EL1と順に変更していく

スタック領域の確保

それぞれのモードで別々のスタック領域を使うので, eret命令でモードを変更する前にスタック領域を確保する(これを忘れると実行が止まってしまう)

各レジスタの設定

scr_el3

公式レファレンス https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/SCR-EL3--Secure-Configuration-Register?lang=en#fieldset_0-0_0

実行モードの確認

実行モードはCurrentELレジスタの2, 3bit目に書かれている

参考文献

https://qiita.com/eggman/items/e500ecb33f8f126c0052

keigo1216 commented 9 months ago

沼ったところ

浮動小数点レジスタの有効化

可変長引数を取るような関数では, 関数のプロローグでいくつかの浮動小数点レジスタ(q0, q1, ...)を退避させる しかし, デフォルトではそもそも浮動小数点が有効化されていないので, 有効化してあげないと, 突然printfが動かない謎バグに襲われる

keigo1216 commented 9 months ago

https://github.com/keigo1216/ketchup/blob/92b8d7538b8506268863688bef68b29e52a941c5/kernel/trap.S#L57 ユーザー空間を実装したらesr_el1に変更する