VOOZH about

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

⇱ aarch64でEL (Exception Level)を変更する #ARM - Qiita


👁 Image
14

Go to list of users who liked

10

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

More than 5 years have passed since last update.

@eggman

aarch64でEL (Exception Level)を変更する

14
Last updated at Posted at 2018-05-19

aarch64でEL (Exception Level)を変更してみました。

あまり良く分かっていないのですが、aarch64でOSをブートするためにはExceptin Levelを変更する必要があります。

ELについて

EL : Exception Level 例外レベル
ARMv8では4つの例外レベルが定義されている。

EL 説明
EL0 アプリ
EL1 OS
EL2 ハイパーバイザ
EL3 セキュアモニタ

分かったこと

  • Aarch32の User modeがEL0
  • Aarch32のIRQ Mode, FIQ ModeがEL1
  • ELの数値が下がるほど、アクセス可能なシステムレジスタが少なくなる。
  • CPUはEL3で動作開始する。
  • Linux起動時は事前にEL2/EL1に設定しておく。

Raspberry Pi 3Bについて

  • kernel_old=1 で起動するとEL3で起動する。
  • kernel_old=1 を指定しないと、EL2で起動する。

ELを確認する。

ELの数値をレジスタx0に代入するアセンブリコード。

mrs x0, CurrentEL

bit3とbit2がELの値でb、it31-4とbit1とbit0は0となる。
つまり、EL3なら0xC, EL2なら0x8, EL1なら0x4, EL0なら0x0となる。(だがEL0からはこのレジスタにアクセスできない。EL0の判定はどうやるのか?)

CurrentELの仕様は、ARMv8のアーキテクチャリファレンスマニュアル C5.2.1 にある。

ELを変更する。

ELを変更するアセンブリーコードです。

EL3 to EL2

EL3からEL2に変更するアセンブリコード。

# define MODE_AARCH64_EL2H 0x9
mov x0, #0x4b1 // RW=1, SMD=1, RES=1, NS=1
msr scr_el3, x0
adr x0, start_el2
msr elr_el3, x0
mov x0, #MODE_AARCH64_EL2H
msr spsr_el3, x0
eret

EL2に変更する例外を発生

  • EL3の例外リンクアドレスレジスタ elr_el3,に、EL2に変更できた際の開始アドレス(start_el2)を設定する。
  • EL3のセーブドプログラムステータスレジスタ spsr_el3に例外の戻り先のモードをEL2hに設定する。

とするとeretの後にELがEL3からEL2hに変更になる。

この時に指定するモードは同じELでも2種類あるEL2hとEL2tがある。EL2tだとEL変更後スタックポインタSP0を使う。
EL2hだとEL変更後はSP_EL2を使う

elr_el3の仕様は、ARMv8のアーキテクチャリファレンスマニュアル C5.2.7 にある。
spsr_el3の仕様は、ARMv8のアーキテクチャリファレンスマニュアル C5.2.20 にある。

EL2 to EL1

ほぼ同様です。

# define MODE_AARCH64_EL1H 0x5
mov x2, #(1 << 31) // AArch64
orr x2, x2, #(1 << 1) // SWIO hardwired on Pi3
msr hcr_el2, x2
mrs x0, hcr_el2
adr x0, start_el1
msr elr_el2, x0
mov x0, #MODE_AARCH64_EL1H
msr spsr_el2, x0
eret

EL1 to EL0

ほぼ同様です。

# define MODE_AARCH64_EL0 0x0
adr x0, start_el0
msr elr_el1, x0
mov x0, #MODE_AARCH64_EL0
msr spsr_el1, x0
eret

ERETによるEL変更

ERETでは数字が同じか小さいいELに変更できる

  • EL3はEL3, EL2、EL1、EL0に変更できる。
  • EL2はEL2, EL1、EL0に変更できる。
  • EL1はEL1, EL0 に変更できる

数字が小さいELから大きいELに変更するためには、IRQ、FIQなどの外部割り込みを発生させるか、SVC, HVC, SMC命令を使う。

ELを変更する実行例

コードをQEMUで実行した場合のトレース。

  • 1回目のeretの後にelr_el3に設定した0x30番地にジャンプしている。
  • 2回目のeretの後にelr_el2に設定した0x54番地にジャンプしている。
  • 3回目のeretの後にelr_el1に設定した0x68番地にジャンプしている。
0x00000010: 58000441 ldr x1, #0x98
0x00000014: d2809622 movz x2, #0x4b1
0x00000018: d51e1102 msr scr_el3, x2
0x0000001c: d2800122 movz x2, #0x9
0x00000020: d51e4002 msr spsr_el3, x2
0x00000024: 10000062 adr x2, #0x30
0x00000028: d51e4022 msr elr_el3, x2
0x0000002c: d69f03e0 eret 

0x00000030: d2b00002 movz x2, #0x8000, lsl #16
0x00000034: b27f0042 orr x2, x2, #2
0x00000038: d51c1102 msr hcr_el2, x2
0x0000003c: d53c1100 mrs x0, hcr_el2
0x00000040: d28000a2 movz x2, #0x5
0x00000044: d51c4002 msr spsr_el2, x2
0x00000048: 10000062 adr x2, #0x54
0x0000004c: d51c4022 msr elr_el2, x2
0x00000050: d69f03e0 eret 

0x00000054: d2800002 movz x2, #0
0x00000058: d5184002 msr spsr_el1, x2
0x0000005c: 10000062 adr x2, #0x68
0x00000060: d5184022 msr elr_el1, x2
0x00000064: d69f03e0 eret 

0x00000068: 9100003f mov sp, x1

このトレースはqemuの-d in_asm で出力しました。この機能は便利です。

参考にしたページ

14

Go to list of users who liked

10
0

Go to list of comments

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14

Go to list of users who liked

10