source: ssp_aarch64/trunk/arm64_gcc/prc_design.txt@ 356

Last change on this file since 356 was 356, checked in by nmir-saito, 6 years ago

set svn:mime-type to files

  • Property svn:mime-type set to text/plain; charset=utf-8
File size: 16.1 KB
Line 
1=====================================================================
2 ARM64プロセッサ依存部設計メモ
3 Last Modified: 5 Jun 2018
4=====================================================================
5
6○このドキュメントの位置づけ
7
8このドキュメントは,TOPPERS/SSPカーネルをARMv8-Aプロセッサに移植する際
9の設計メモである.
10
11
12○ARMv8-Aの仕様まとめ
13
14ARMv8-Aの仕様のうち,カーネルの設計に関係する事項についてまとめる.
15
16●レジスタ
17
18汎用レジスタはr0〜r30 (特に64ビットレジスタはX0..X30で表現)の31種類からなる.
19(参考)「Procedure Call Standard for the ARM 64-bit Architecture」
20
21r0...r7 Parameter/result registers(引数および返値の受け渡し用)
22r8 Indirect result location register (大きなデータ構造を
23 返値として返す場合など,呼び出し側が結果を取り出すために
24 間接アドレッシングを多用する際,そのベースアドレスを受け渡し
25 するために使われる)
26r9..r15 Caller-saved Temporary registers(呼び出し側で保存すべきレジスタ)
27r16(IP0) The first intra-procedure-call scratch register
28 リンカによって veneer(注1) および PLT(Procedure Linkage Table,注2) コード
29 の呼び出しで使われる.それ以外の時はテンポラリレジスタとして使われることもある.
30 (注1)リンカによって挿入される小さなコード片で,
31 分岐命令のターゲットが範囲外の場合などに使われる
32 (注2)共有ライブラリの呼び出しでシンボル解決を行うために使用される
33 関数テーブル
34r17(IP1) The second intra-procedure-call temporary register(r16と役割は同じ)
35r18 The Platform Register(プラットフォームABIで使用されるレジスタ.
36 ABIで使われない場合はテンポラリレジスタとして使われる)
37r19..r28 Callee-saved registers(呼び出された側で保存して使うレジスタ)
38r29(FP) The Frame Pointer(フレームポインタ)
39r30(LR) The Link Register(リンクレジスタ)
40
41SSPカーネルのアセンブラによる実装ではr8, r16...r18は使用していない.
42
43
44●コーリングコンベンション
45
46r0...R7 が引数および返値に使われる.
47ARMにより規定されているため,コンパイラに依存せずこのルールとなる
48
49●PSTATE
50
51AArch64ではプロセッサの状態を表すフラグの集まりをまとめてPSTATEと呼び,
52それぞれのフラグへ別々にアクセスするための特別なレジスタ名が定義されている.
53
54PSTATEの詳細は,ARM Architecture Reference Manual
55ARMv8, for ARMv8-A architecture profile の D1.7 などを参照のこと.
56
57・spsel
58EL1より上の例外レベルでは,spsel という特別な名称のレジスタにアクセスし,
59PSTATE.SPフラグの値をセットして使用スタックの切り替えを行う.
60
61・daif
62daif という名称のレジスタを使用してPSTATEのD,A,I,Fビットを操作し,
63各種例外および割込みの禁止/許可を制御する
64
65
66SSPカーネルの実装では,スタックはSP_EL1のみを使用する.
67また,CPUロック状態および割込みロック状態の実装にPSTATEのIおよびFフラグを
68利用している.
69
70
71●割込みベクタ
72
73ベクタテーブルのアドレスはリセット時に,システムレジスタの一つVector Base
74Address Register(VBAR, システムレジスタ)にアドレスをセットすることで,
752048バイト境界の任意のアドレスに配置可能である.
76
77SSPカーネルの実装ではスタートアップルーチンで設定している.
78
79
80●割込み優先度
81
82設定値の小さい方が高優先度となる.
83
84優先度は最大8bitであり,SoC毎に実装されているビット幅が異なる.実装さ
85れるビットが8bit以下の場合は,LSBから無効になる.例えば,実装されてい
86るビット幅が7bitの場合は,ビット0が無効となる.
87
88優先度のビットフィールドのLSBから数ビットをサブ優先度と呼ぶフィールド
89に設定することが可能である.残りの上位ビットをプリエンプション優先度と
90呼ぶ.プリエンプション優先度が同じで,サブ優先度が異なる優先度のグルー
91プは,お互いをプリエンプトすることができない.
92
93例として,QEMU Virtボード向けSSPの実装では Cortex-A53プロセッサを
94ターゲットとしており,優先度は16段階(4bit)でビット0から3が無効である.
95
96●CPUモード
97
98プロセッサは,EL0からEL3までの例外レベルのいずれかで動作する.
99またそれぞれのレベルで64ビットモード(AArch64) または32ビットモード(AArch32)を
100選択することができる.ただし,ある例外レベルが32ビットモードで動作する場合は
101それより低い例外レベルでは64ビットモードを選択することができない.
102
103また,セキュリティ拡張機能を搭載するプロセッサではセキュアモードおよび
104非セキュアモードを選択することができる.
105
106SSPの実装では,64ビットモード(AArch64),非セキュア,例外レベル1(EL1) で動作する.
107
108
109●リセット時の状態
110
111リセット時はプロセッサチップがサポートする最大の例外レベルおよびそのレベルの
112スタック(SP_ELx)が有効となっている.
113
114例としてQEMU向けVirtボード(Cortex-A53) では,既定でEL1が最大例外レベルのため
115リセット直後はSP_EL1が有効となっている.
116
117●割込み/例外の受付
118
119割込みを受け付けると受け付けた割込みの番号が,GICC_IARにセットされる.
120割込み番号はこのレジスタにセットされる値を使用する.
121
122例外番号は,例外発生時のプロセッサ状態に応じて決定される,ベクタテーブル中の
123ジャンプ先オフセット毎に異なる番号を割り振ることにしている.
124
125 例外発生時の状態 例外の種類 例外番号  例外ベクタ先頭からのオフセット
126 AArch64, EL1t(EL1, SP_EL0) Synchronous 0 0x0000
127 AArch64, EL1t(EL1, SP_EL0) SError 1 0x0180
128 AArch64, EL1h(EL1, SP_EL1) Synchronous 2 0x0200
129 AArch64, EL1h(EL1, SP_EL1) SError 3 0x0380
130 AArch64, EL0 (EL0, SP_EL0) Synchronous 4 0x0400
131 AArch64, EL0 (EL0, SP_EL0) SError 5 0x0580
132 AArch32, EL0 (EL0, SP_EL0) Synchronous 6 0x0600
133 AArch32, EL0 (EL0, SP_EL0) SError 7 0x0780
134
135割込みを受け付けた際,受け付けた割込みに設定された優先度より低い割込みを
136禁止するため,GICC_RPRから取得した割込み要因の割込み優先度を GICC_PMRへ
137セットしている.そしてハンドラ終了後に割込み発生前の割り込み優先度に戻す.
138
139● スタックポインタ(SP_EL0とSP_ELx)
140
141スタックポインタは,例外レベル0のスタックポインタ(SP_EL0)および実行中の
142例外レベルのスタックポインタ(SP_ELx)が選択可能である.
143スタックの選択はspselレジスタへ1を設定するとSP_ELxを,0を設定すると
144SP_EL0 を選択する.
145
146SSPの実装では,EL1 で SP_EL1 のみを使用して動作する.
147
148●例外レベルの遷移
149
150例外レベル(EL)の遷移は割込み/例外の受付および例外リターン命令(eret)により行う.
151
152割込みおよび例外を受け付けることで発生前と同じまたはより高い例外レベルへ遷移する.
153一方,同じまたはより低い例外レベルへの遷移は例外リターン命令(eret)により行う.
154
155受付時の遷移先となる例外レベルの指定はシステムレジスタにより設定することで行う.
156割込み/例外リターン時の遷移先となる例外レベルは,SPSR_ELxのビット2および3で
157指定する.割込み/例外受付時,PSTATEの状態がSPSR_ELxに,リターンアドレスがELR_ELxに,
158それぞれ保存されeret命令の実行によりその格納値が復帰されるため,eret実行前に
159あらかじめSPSR_ELxにセットしておくことで指定した例外レベルへ遷移することが可能である.
160同じタイミングで使用スタックや64ビット/32ビットモードの指定も行うことができる.
161
162QEMU Virt向けSSPの実装ではEL1のみを使用するため,例外レベル間の遷移処理は行っていない.
163
164●例外レベルの判定
165
166現状の例外レベルを判定するには,CPSRのビット2およびビット3の値を使用する.
167bit[3:2]の値が
168 '11'の場合:EL3
169 '10'の場合:EL2
170 '01'の場合:EL1
171 '00'の場合:EL0
172
173●GICC_PMRレジスタ
174
175設定した優先度以下(値としては以上)の優先度の割込みの受付を禁止する.
176設定可能な最大値を設定すると,全ての割込みを許可する.
177例えば優先度が16段階の場合は0xf0(=0x0f << 4)をセットするとすべての割込み許可
178となる.値は例外/割込みの受付とリターンにより変化しないため,受け付けた割込み
179の優先度を割込みの入口処理で設定する必要がある.
180
181●例外/割込みの受付
182
183・例外/割込みを受付けると,受付け時にアクティブなスタック上に以下のコ
184 ンテキストを保存する.
185
186 ---------------
187 | GICC_PMR | <- new SP
188 ----------------
189 | 割込み/例外番号|
190 ----------------
191 | ダミー(0) |
192 ----------------
193 | 調整量(0 or 8) |
194 ----------------
195 |調整領域(必要時)| (*)アライメント調整が必要なときのみ
196 ----------------
197 | ESR_ELx |
198 ----------------
199 | ELR_ELx |
200 ----------------
201 | SPSR_ELx |
202 ----------------
203 | X30 |
204 ----------------
205 | X29 |
206 ----------------
207 | : |
208 | : |
209 ----------------
210 | X1 |
211 ----------------
212 | X0 |
213 ----------------
214 | | <- old SP
215
216
217割込み/例外発生時の主なシーケンスは次のようになる(遷移先の例外レベルをELxと表現する)
218
219(ハードウェアの処理)
220 ・PSTATEをSPSR_ELxに保存する
221 ・リターンアドレスをELR_ELxに保存する
222 ・PSTATE.{D,A,I,F}を1にセットする
223 ・同期例外およびSError割込みのとき,例外要因情報をESR_ELxに保存する
224 ・スタックポインタをSP_ELxに切り替える
225 ・ELxへ遷移する
226
227(ソフトウェアでの処理)
228 ・(発生時にSP_EL0を使用していた場合)スタックを割込み発生前(SP_EL0)に戻す
229 ・汎用レジスタ(X0-X30)をスタックに保存
230 ・SPSR_ELx, ESR_ELx, ELR_ELxをスタックに保存
231 ・スタックポインタのアライメントを調整
232 ・割込み番号(GICC_IARから取得),例外番号(オフセット毎に定義した値)をスタックに保存
233 ・割込み発生前の割込み優先度マスクをスタックに保存
234 ・GICC_PMRに受け付けた割込みの割込み優先度をセット
235 ・割込み/例外ネストカウンタのインクリメント
236 ・(割込みの場合)CPUロック解除
237 ・ベクタテーブルを読み込みハンドラを実行する
238
239●例外/割込みからのリターン
240
241(ソフトウェアでの処理)
242 ・CPUロック状態へ移行
243 ・割込み/例外ネスとカウンタのデクリメント
244 ・GICC_PMRに割込み発生前の優先度マスクを戻す
245 ・スタックポインタのアライメント調整分を戻す
246 ・戻り先のコンテキストやシステム状態に応じて割込み/例外発生元へリターン
247 または遅延ディスパッチを実行する
248 ・ELR_ELxに戻り先アドレス,SPSR_ELxにプロセッサ状態がそれぞれ
249 セットされている状態でeret命令を実行し,割込み/例外からリターン
250
251●スタックポインタのアライメント調整
252
253AArch64では,外部インタフェースにおいてスタックポインタは16バイト境界に
254アラインさせる必要がある.しかし例外発生時にそれが満たされているとは限らないため,
255割込み/CPU例外の入口処理で,スタックポインタがアライメント条件を満たしていない場合には,
256スタックポインタを調整する.また,出口処理でスタックポインタを元に戻せるように,調整量を保存する.
257
258
259○OSの実装
260
2611.プロセッサ依存部名称: arm64
262
263ARMv8 では,64ビットモード(AArch64)および32ビットモード(AArch32)の両方をサポートするが
264本実装は64ビットモードのみをサポートすることを明示するためプロセッサ依存部名称を arm64 とした
265
2662. 例外モードの使い分け
267
268本実装ではタスクコンテキスト,非タスクコンテキストいずれも例外レベル1(EL1)で動作する.
269タスクコンテキストをEL0で動作する案も考えられる.その場合は割込み/例外の出口処理において
270遅延ディスパッチの前に例外レベルの切り替えが必要となる.
271
2723.ディスパッチャの実行モード
273
274本実装ではすべて例外レベル1で動作するため,ディスパッチャは例外レベル1(EL1)で動作する.
275
276
2774.スタックの使い分け
278
279SSPではタスクコンテキスト,非タスクコンテキスト共に一つのスタックを共用する.
280本実装ではSP_ELxを使用している.
281この他にSP_EL0を使用する実装も考えられる.その場合は割込み/例外の入口処理にて
282レジスタを保存する前にSP_EL0へのスタック切り替えを行う.
283
2845.コンテキストの判定
285
286割込み/例外のネスト回数を保持する変数(intnest)が0ならタスクタスクコンテキスト,
2871以上なら非タスクコンテキストとする.
288コンテキスト毎に例外レベルを分ける実装を取る場合はPSTATEのビット2および3で
289例外レベルを読み出すことにより判別するという方法も考えられる.
290本実装ではコンテキストによらず同じ例外レベルを使用し,プロセッサの
291ステータスレジスタでは判別ができないため変数で判別する.
292
2936. CPUロック
294
295CPUロックPSTATE.IおよびPSTATE.FによりCPUロックを実現する.
296
2977. 割込みロックとCPU例外の関係
298
299カーネル管理外の割込みはサポートしないため,割込みロックとCPUロックがマスクする
300割込みの範囲は同じとする.ただし,フラグ自体はお互いに独立させるため,
301割込みロック状態の設定/解除の際は,ロック前にCPUロックフラグの状態を保存し,
302解除前に元の状態に戻すようにしている.
303
3048. 外部優先度と内部優先度
305
306外部優先度とはAPIで指定する割込み優先度(PRI型)のことであり,値が小さい
307ほど優先度が高い.割込みハンドラには,-1から連続した負の値を設定可能で
308ある.内部優先度は,GICC_PMRレジスタに設定する値である.
309外部優先度と内部優先度の変換は以下のマクロで表現される.
310
311/* 外部表現への変換 */
312#define EXT_IPM(pri) \
313 (((PRI)((pri) >> GIC_PRI_SHIFT)) - (GIC_PRI_LEVEL - 1))
314
315/* 内部表現への変換 */
316#define INT_IPM(ipm) \
317 (((uint_t)((ipm) + (GIC_PRI_LEVEL - 1))) << GIC_PRI_SHIFT)
318
319ここでGIC_PRI_LEVELはサポートする割込み優先度の数,GIC_PRI_SHIFTはGICC_PMRレジスタ内
320の,内部優先度の値が格納される位置(ビット0からのオフセット)を表す.
321
322
3239. カーネル管理内の最高優先度(CPUロック状態での優先度マスク)
324
325カーネル管理内の割込みの最高優先度は設定可能な外部優先度の最高値と同じとする.
326
327
328以上.
Note: See TracBrowser for help on using the repository browser.